From fca9b48556d3d0dc2cbfb6e8724fdb90e7eeb6fe Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Tue, 2 Sep 2014 11:55:20 +0200 Subject: [PATCH 001/543] [mcs] more nonliteral constants pattern matching --- mcs/mcs/cs-parser.jay | 4 ++++ mcs/mcs/ecore.cs | 6 +++--- mcs/mcs/expression.cs | 37 +++++++++++++++++++++++++++++++----- mcs/mcs/namespace.cs | 2 ++ mcs/tests/test-pattern-02.cs | 25 ++++++++++++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 7 ++++++- 6 files changed, 72 insertions(+), 9 deletions(-) diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index c4226637171..7200290286c 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -4336,6 +4336,9 @@ is_match_expr { $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, GetLocation ($1)); } + | sizeof_expression + | invocation_expression + | default_value_expression ; match_type @@ -7934,6 +7937,7 @@ static string GetTokenName (int token) case Token.OP_AND_ASSIGN: case Token.OP_XOR_ASSIGN: case Token.OP_OR_ASSIGN: + case Token.INTERR_OPERATOR: return ""; case Token.BOOL: diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 5729e21b3e7..ee0fce56191 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -230,10 +230,10 @@ public virtual Expression DoResolveLValue (ResolveContext rc, Expression right_s // public virtual TypeSpec ResolveAsType (IMemberContext mc, bool allowUnboundTypeArguments = false) { - ResolveContext ec = new ResolveContext (mc); - Expression e = Resolve (ec); + var rc = mc as ResolveContext ?? new ResolveContext (mc); + Expression e = Resolve (rc); if (e != null) - e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc); + e.Error_UnexpectedKind (rc, ResolveFlags.Type, loc); return null; } diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 8f133291f95..07ab42429c2 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -1595,8 +1595,10 @@ void EmitConstantMatch (EmitContext ec) return; } + var probe_type = ProbeType.Type; + Expr.Emit (ec); - ec.Emit (OpCodes.Isinst, ProbeType.Type); + ec.Emit (OpCodes.Isinst, probe_type); ec.Emit (OpCodes.Dup); ec.Emit (OpCodes.Brfalse, no_match); @@ -1604,6 +1606,9 @@ void EmitConstantMatch (EmitContext ec) var ce = new CallEmitter (); ce.Emit (ec, number_mg, number_args, loc); } else { + if (TypeSpec.IsValueType (probe_type)) + ec.Emit (OpCodes.Unbox_Any, probe_type); + ProbeType.Emit (ec); ec.Emit (OpCodes.Ceq); } @@ -1696,14 +1701,36 @@ public override void FlowAnalysis (FlowAnalysisContext fc) protected override void ResolveProbeType (ResolveContext rc) { if (!(ProbeType is TypeExpr) && rc.Module.Compiler.Settings.Version == LanguageVersion.Experimental) { - ProbeType = ProbeType.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup | ResolveFlags.Type); - if (ProbeType == null) + // + // Have to use session recording because we don't have reliable type probing + // mechanism (similar issue as in attributes resolving) + // + // TODO: This is still wrong because ResolveAsType can be destructive + // + var type_printer = new SessionReportPrinter (); + var prev_recorder = rc.Report.SetPrinter (type_printer); + + probe_type_expr = ProbeType.ResolveAsType (rc); + type_printer.EndSession (); + + if (probe_type_expr != null) { + type_printer.Merge (rc.Report.Printer); + rc.Report.SetPrinter (prev_recorder); return; + } - if (ProbeType.eclass == ExprClass.Type) { - probe_type_expr = ProbeType.Type; + var expr_printer = new SessionReportPrinter (); + rc.Report.SetPrinter (expr_printer); + ProbeType = ProbeType.Resolve (rc); + expr_printer.EndSession (); + + if (ProbeType != null) { + expr_printer.Merge (rc.Report.Printer); + } else { + type_printer.Merge (rc.Report.Printer); } + rc.Report.SetPrinter (prev_recorder); return; } diff --git a/mcs/mcs/namespace.cs b/mcs/mcs/namespace.cs index a0669b8ce3d..970e2ca024e 100644 --- a/mcs/mcs/namespace.cs +++ b/mcs/mcs/namespace.cs @@ -498,6 +498,8 @@ public void RemoveContainer (TypeContainer tc) types.Remove (tc.MemberName.Name); else found.RemoveAt (i); + + break; } } diff --git a/mcs/tests/test-pattern-02.cs b/mcs/tests/test-pattern-02.cs index 9efe5d8c308..695775ec179 100644 --- a/mcs/tests/test-pattern-02.cs +++ b/mcs/tests/test-pattern-02.cs @@ -9,6 +9,11 @@ enum MyEnum : short class ConstantPattern { + static bool Generic (T t) where T : class + { + return t is default (T); + } + public static int Main () { bool b4 = false; @@ -62,6 +67,26 @@ public static int Main () if (!r4) return 12; + ConstantPattern o7 = new ConstantPattern (); + if (!(o7 is ConstantPattern)) + return 13; + + if (!(o7 is object)) + return 14; + + object o8 = true; + if (o8 is false) + return 15; + + if (!(o8 is true)) + return 16; + + if (Generic ("")) + return 17; + + if (!Generic (null)) + return 18; + Console.WriteLine ("ok"); return 0; } diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 29f597e6033..201af97a9e7 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -68446,7 +68446,7 @@ - 470 + 633 7 @@ -68457,6 +68457,11 @@ 54 + + + 28 + + From 09bb2dc4bd14f1c4d3f0550ccd9c8696d606a072 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 2 Sep 2014 18:38:20 +0800 Subject: [PATCH 002/543] Changed InternalGetCharCount to iterate the bytes as InternalGetChars. --- mcs/class/corlib/System.Text/UTF8Encoding.cs | 33 ++++++++++---------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/mcs/class/corlib/System.Text/UTF8Encoding.cs b/mcs/class/corlib/System.Text/UTF8Encoding.cs index cdddb802b16..f45b0aafe47 100644 --- a/mcs/class/corlib/System.Text/UTF8Encoding.cs +++ b/mcs/class/corlib/System.Text/UTF8Encoding.cs @@ -457,18 +457,18 @@ private unsafe static int InternalGetCharCount ( } private unsafe static int InternalGetCharCount ( - byte* bytes, int count, uint leftOverBits, + byte* bytes, int byteCount, uint leftOverBits, uint leftOverCount, object provider, ref DecoderFallbackBuffer fallbackBuffer, ref byte [] bufferArg, bool flush) { - int index = 0; + int byteIndex = 0; int length = 0; if (leftOverCount == 0) { - int end = index + count; - for (; index < end; index++, count--) { - if (bytes [index] < 0x80) + int end = byteIndex + byteCount; + for (; byteIndex < end; byteIndex++, byteCount--) { + if (bytes [byteIndex] < 0x80) length++; else break; @@ -480,9 +480,11 @@ private unsafe static int InternalGetCharCount ( uint leftBits = leftOverBits; uint leftSoFar = (leftOverCount & (uint)0x0F); uint leftSize = ((leftOverCount >> 4) & (uint)0x0F); - while (count > 0) { - ch = (uint)(bytes[index++]); - --count; + + int byteEnd = byteIndex + byteCount; + for(; byteIndex < byteEnd; byteIndex++) { + // Fetch the next character from the byte buffer. + ch = (uint)(bytes[byteIndex]); if (leftSize == 0) { // Process a UTF-8 start character. if (ch < (uint)0x0080) { @@ -515,7 +517,7 @@ private unsafe static int InternalGetCharCount ( leftSize = 6; } else { // Invalid UTF-8 start character. - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, index - 1, 1); + length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex, 1); } } else { // Process an extra byte in a multi-byte sequence. @@ -544,34 +546,33 @@ private unsafe static int InternalGetCharCount ( break; } if (overlong) { - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, index - leftSoFar, leftSoFar); + length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar); } else if ((leftBits & 0xF800) == 0xD800) { // UTF-8 doesn't use surrogate characters - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, index - leftSoFar, leftSoFar); + length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar); } else ++length; } else if (leftBits < (uint)0x110000) { length += 2; } else { - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, index - leftSoFar, leftSoFar); + length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar); } leftSize = 0; } } else { // Invalid UTF-8 sequence: clear and restart. - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, index - leftSoFar, leftSoFar); + length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar); leftSize = 0; - --index; - ++count; + --byteIndex; } } } if (flush && leftSize != 0) { // We had left-over bytes that didn't make up // a complete UTF-8 character sequence. - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, index - leftSoFar, leftSoFar); + length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar); } // Return the final length to the caller. From 10d4e765254aa85de4c3e3b1ab973cba9ee60430 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 2 Sep 2014 14:32:03 +0200 Subject: [PATCH 003/543] Do not specify key file when building for mobile, it should be passed on command line --- mcs/class/System.Drawing/Assembly/AssemblyInfo.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mcs/class/System.Drawing/Assembly/AssemblyInfo.cs b/mcs/class/System.Drawing/Assembly/AssemblyInfo.cs index 115adf5d92e..c036603b98a 100644 --- a/mcs/class/System.Drawing/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.Drawing/Assembly/AssemblyInfo.cs @@ -56,7 +56,9 @@ [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] +#if !MOBILE [assembly: AssemblyKeyFile("../msfinal.pub")] +#endif [assembly: AssemblyFileVersion (Consts.FxFileVersion)] [assembly: CompilationRelaxations (CompilationRelaxations.NoStringInterning)] From 60aa49b35bd67391aa17e3ced2639eda9884a9a2 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 2 Sep 2014 22:42:54 +0800 Subject: [PATCH 004/543] Added class EncodingTester that can be used to test fallbacks. EncodingTester is a testing helper class with a method TestDecoderFallback that makes DecoderFalback testing easier. --- .../corlib/Test/System.Text/EncodingTester.cs | 116 ++++++++++++++++++ mcs/class/corlib/corlib_test.dll.sources | 1 + 2 files changed, 117 insertions(+) create mode 100644 mcs/class/corlib/Test/System.Text/EncodingTester.cs diff --git a/mcs/class/corlib/Test/System.Text/EncodingTester.cs b/mcs/class/corlib/Test/System.Text/EncodingTester.cs new file mode 100644 index 00000000000..939d38160fb --- /dev/null +++ b/mcs/class/corlib/Test/System.Text/EncodingTester.cs @@ -0,0 +1,116 @@ +// +// EncodingTester.cs +// +// Author: +// Marcos Henrich +// +// (C) 2014 Xamarin, Inc. +// + +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Text; + +namespace MonoTests.System.Text +{ + class EncodingTester + { + class DecoderTestFallbackBuffer : DecoderFallbackBuffer + { + DecoderFallbackBuffer buffer; + private FallbackDelegate fallbackAction; + + public DecoderTestFallbackBuffer (DecoderReplacementFallback fallback, FallbackDelegate fallbackAction) + { + this.fallbackAction = fallbackAction; + buffer = new DecoderReplacementFallbackBuffer (fallback); + } + + public override bool Fallback (byte [] bytesUnknown, int index) + { + fallbackAction (bytesUnknown, index); + return buffer.Fallback (bytesUnknown, index); + } + + public override char GetNextChar () + { + return buffer.GetNextChar (); + } + + public override bool MovePrevious () + { + return buffer.MovePrevious (); + } + + public override int Remaining + { + get { return buffer.Remaining; } + } + + public override void Reset () + { + buffer.Reset (); + } + } + + class DecoderTestFallback : DecoderFallback + { + private DecoderReplacementFallback fallback; + private FallbackDelegate fallbackAction; + + public DecoderTestFallback (FallbackDelegate fallbackAction) + { + this.fallbackAction = fallbackAction; + } + + public override DecoderFallbackBuffer CreateFallbackBuffer () + { + fallback = new DecoderReplacementFallback (); + return new DecoderTestFallbackBuffer (fallback, fallbackAction); + } + + public override int MaxCharCount + { + get { return fallback.MaxCharCount; } + } + } + + public delegate void FallbackDelegate (byte [] bytesUnknown, int index); + + Encoding encoding; + + byte [][] expectedUnknownBytes; + int expectedUnknownBytesIndex; + + public EncodingTester (string encodingName) + { + var decoderFallback = new DecoderTestFallback (this.DecoderFallback); + encoding = Encoding.GetEncoding (encodingName, new EncoderReplacementFallback(), decoderFallback); + } + + private void DecoderFallback (byte [] bytesUnknown, int index) + { + if (expectedUnknownBytesIndex == expectedUnknownBytes.Length) + expectedUnknownBytesIndex = 0; + + var expectedBytes = expectedUnknownBytes [expectedUnknownBytesIndex++]; + Assert.AreEqual (expectedBytes, bytesUnknown); + } + + public void TestDecoderFallback (byte [] data, string expectedString, params byte [][] expectedUnknownBytes) + { + lock (this) + { + this.expectedUnknownBytes = expectedUnknownBytes; + this.expectedUnknownBytesIndex = 0; + + Assert.AreEqual (expectedString.Length, encoding.GetCharCount (data)); + Assert.AreEqual (expectedUnknownBytesIndex, expectedUnknownBytes.Length); + + Assert.AreEqual (expectedString, encoding.GetString (data)); + Assert.AreEqual (expectedUnknownBytesIndex, expectedUnknownBytes.Length); + } + } + } +} \ No newline at end of file diff --git a/mcs/class/corlib/corlib_test.dll.sources b/mcs/class/corlib/corlib_test.dll.sources index 1742ea7ff24..8cb367e813e 100644 --- a/mcs/class/corlib/corlib_test.dll.sources +++ b/mcs/class/corlib/corlib_test.dll.sources @@ -394,6 +394,7 @@ System.Text/EncoderReplacementFallbackTest.cs System.Text/EncoderReplacementFallbackBufferTest.cs System.Text/EncoderTest.cs System.Text/EncodingTest.cs +System.Text/EncodingTester.cs System.Text/EncodingInfoTest.cs System.Text/StringBuilderTest.cs System.Text/TestEncoding.cs From a7b779648be027cfd95b387b6dda9f15e3f6e13d Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Tue, 2 Sep 2014 10:49:26 -0400 Subject: [PATCH 005/543] Bring fix for Cecil, includes fix for F#/Fody --- external/cecil | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/cecil b/external/cecil index 89cfb1d4079..33d50b874fd 160000 --- a/external/cecil +++ b/external/cecil @@ -1 +1 @@ -Subproject commit 89cfb1d4079002394010fd351628ad057c94422f +Subproject commit 33d50b874fd527118bc361d83de3d494e8bb55e1 From 3d332ac26da5a05f75ca8a44f54a60c708718fa7 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 2 Sep 2014 22:46:03 +0800 Subject: [PATCH 006/543] Added UTF8EncodingTest.EncodingFallback. EncodingFallback tests for multiple invalid inputs the unknownBytes that are given to the DecoderFallback. --- .../Test/System.Text/UTF8EncodingTest.cs | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/mcs/class/corlib/Test/System.Text/UTF8EncodingTest.cs b/mcs/class/corlib/Test/System.Text/UTF8EncodingTest.cs index 91a465c13d3..8943ab6b099 100644 --- a/mcs/class/corlib/Test/System.Text/UTF8EncodingTest.cs +++ b/mcs/class/corlib/Test/System.Text/UTF8EncodingTest.cs @@ -1198,5 +1198,88 @@ public void Bug10789() int charactersWritten = Encoding.UTF8.GetDecoder ().GetChars (bytes, 0, 0, chars, 10, false); Assert.AreEqual (0, charactersWritten, "#3"); } + + [Test] + public void EncodingFallback () + { + /* Legal UTF-8 Byte Sequences + * 1st 2nd 3rd 4th + * 00..7F + * C2..DF 80..BF + * E0 A0..BF 80..BF + * E1..EF 80..BF 80..BF + * F0 90..BF 80..BF 80..BF + * F1..F3 80..BF 80..BF 80..BF + * F4 80..8F 80..BF 80..BF + */ + + var t = new EncodingTester ("utf-8"); + byte [] data; + + // Invalid 1st byte + for (byte b = 0x80; b <= 0xC1; b++) { + data = new byte [] { b }; + t.TestDecoderFallback (data, "?", new byte [] { b }); + } + + ///Invalid 2nd byte + // C2..DF 80..BF + for (byte b = 0xC2; b <= 0xDF; b++) { + data = new byte [] { b, 0x61 }; + t.TestDecoderFallback (data, "?a", new byte [] { b }); + } + + // E0 A0..BF + data = new byte [] { 0xE0, 0x99}; + t.TestDecoderFallback (data, "?", new byte [] { 0xE0, 0x99}); + + // E1..EF 80..BF + for (byte b = 0xE1; b <= 0xEF; b++) { + data = new byte [] { b, 0x61 }; + t.TestDecoderFallback (data, "?a", new byte [] { b }); + } + + // F0 90..BF + data = new byte [] { 0xF0, 0x8F}; + t.TestDecoderFallback (data, "?", new byte [] { 0xF0, 0x8F }); + + // F1..F4 80..XX + for (byte b = 0xF1; b <= 0xF4; b++) { + data = new byte [] { b, 0x61 }; + t.TestDecoderFallback (data, "?a", new byte [] { b }); + } + + // C2..F3 XX..BF + for (byte b = 0xC2; b <= 0xF3; b++) { + data = new byte [] { b, 0xC0 }; + t.TestDecoderFallback (data, "??", new byte [] { b }, new byte [] { 0xC0 }); + } + + // Invalid 3rd byte + // E0..F3 90..BF 80..BF + for (byte b = 0xE0; b <= 0xF3; b++) { + data = new byte [] { b, 0xB0, 0x61 }; + t.TestDecoderFallback (data, "?a", new byte [] { b, 0xB0 }); + data = new byte [] { b, 0xB0, 0xC0 }; + t.TestDecoderFallback (data, "??", new byte [] { b, 0xB0 }, new byte [] { 0xC0 }); + } + + // F4 80..8F 80..BF + data = new byte [] { 0xF4, 0x8F, 0xC0 }; + t.TestDecoderFallback (data, "??", new byte [] { 0xF4, 0x8F }, new byte [] { 0xC0 }); + + // Invalid 4th byte + // F0..F3 90..BF 80..BF 80..BF + for (byte b = 0xF0; b <= 0xF3; b++) { + data = new byte [] { b, 0xB0, 0xB0, 0x61 }; + t.TestDecoderFallback (data, "?a", new byte [] { b, 0xB0, 0xB0 }); + data = new byte [] { b, 0xB0, 0xB0, 0xC0 }; + t.TestDecoderFallback (data, "??", new byte [] { b, 0xB0, 0xB0 }, new byte [] { 0xC0 }); + } + + // F4 80..8F 80..BF 80..BF + data = new byte [] { 0xF4, 0x8F, 0xB0, 0xC0 }; + t.TestDecoderFallback (data, "??", new byte [] { 0xF4, 0x8F, 0xB0 }, new byte [] { 0xC0 }); + } } } From 91fa140dd00c7ada08a79022389fd1f97663370b Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 2 Sep 2014 22:57:26 +0800 Subject: [PATCH 007/543] Changed UTF8Encoding to call fallback with whole byte sequences. Removed unnecessary parameters ref byte [] bufferArg. This changes are required by UTF8EncodingTest.EncodingFallback that in some cases is expecting multibyte values.. --- mcs/class/corlib/System.Text/UTF8Encoding.cs | 97 ++++++++++---------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/mcs/class/corlib/System.Text/UTF8Encoding.cs b/mcs/class/corlib/System.Text/UTF8Encoding.cs index f45b0aafe47..9c8ed4dcbb7 100644 --- a/mcs/class/corlib/System.Text/UTF8Encoding.cs +++ b/mcs/class/corlib/System.Text/UTF8Encoding.cs @@ -436,7 +436,7 @@ public unsafe override int GetBytes (char* chars, int charCount, byte* bytes, in private unsafe static int InternalGetCharCount ( byte[] bytes, int index, int count, uint leftOverBits, uint leftOverCount, object provider, - ref DecoderFallbackBuffer fallbackBuffer, ref byte [] bufferArg, bool flush) + ref DecoderFallbackBuffer fallbackBuffer, bool flush) { // Validate the parameters. if (bytes == null) { @@ -453,13 +453,13 @@ private unsafe static int InternalGetCharCount ( return 0; fixed (byte *bptr = bytes) return InternalGetCharCount (bptr + index, count, - leftOverBits, leftOverCount, provider, ref fallbackBuffer, ref bufferArg, flush); + leftOverBits, leftOverCount, provider, ref fallbackBuffer, flush); } private unsafe static int InternalGetCharCount ( byte* bytes, int byteCount, uint leftOverBits, uint leftOverCount, object provider, - ref DecoderFallbackBuffer fallbackBuffer, ref byte [] bufferArg, bool flush) + ref DecoderFallbackBuffer fallbackBuffer, bool flush) { int byteIndex = 0; @@ -517,7 +517,7 @@ private unsafe static int InternalGetCharCount ( leftSize = 6; } else { // Invalid UTF-8 start character. - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex, 1); + length += Fallback (provider, ref fallbackBuffer, bytes, byteIndex, 1); } } else { // Process an extra byte in a multi-byte sequence. @@ -546,24 +546,24 @@ private unsafe static int InternalGetCharCount ( break; } if (overlong) { - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar); + length += Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar); } else if ((leftBits & 0xF800) == 0xD800) { // UTF-8 doesn't use surrogate characters - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar); + length += Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar); } else ++length; } else if (leftBits < (uint)0x110000) { length += 2; } else { - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar); + length += Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar); } leftSize = 0; } } else { // Invalid UTF-8 sequence: clear and restart. - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar); + length += Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar); leftSize = 0; --byteIndex; } @@ -572,7 +572,7 @@ private unsafe static int InternalGetCharCount ( if (flush && leftSize != 0) { // We had left-over bytes that didn't make up // a complete UTF-8 character sequence. - length += Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar); + length += Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar); } // Return the final length to the caller. @@ -580,7 +580,7 @@ private unsafe static int InternalGetCharCount ( } // for GetCharCount() - static unsafe int Fallback (object provider, ref DecoderFallbackBuffer buffer, ref byte [] bufferArg, byte* bytes, long index, uint size) + static unsafe int Fallback (object provider, ref DecoderFallbackBuffer buffer, byte* bytes, long index, uint size) { if (buffer == null) { DecoderFallback fb = provider as DecoderFallback; @@ -589,20 +589,21 @@ static unsafe int Fallback (object provider, ref DecoderFallbackBuffer buffer, r else buffer = ((Decoder) provider).FallbackBuffer; } - if (bufferArg == null) - bufferArg = new byte [1]; - int ret = 0; - for (int i = 0; i < size; i++) { - bufferArg [0] = bytes [(int) index + i]; - buffer.Fallback (bufferArg, 0); - ret += buffer.Remaining; - buffer.Reset (); - } + + var bufferArg = new byte [size]; + + for (int i = 0; i < size; i++) + bufferArg [i] = bytes [(int) index + i]; + + buffer.Fallback (bufferArg, 0); + int ret = buffer.Remaining; + buffer.Reset (); + return ret; } // for GetChars() - static unsafe void Fallback (object provider, ref DecoderFallbackBuffer buffer, ref byte [] bufferArg, byte* bytes, long byteIndex, uint size, + static unsafe void Fallback (object provider, ref DecoderFallbackBuffer buffer, byte* bytes, long byteIndex, uint size, char* chars, ref int charIndex) { if (buffer == null) { @@ -612,23 +613,23 @@ static unsafe void Fallback (object provider, ref DecoderFallbackBuffer buffer, else buffer = ((Decoder) provider).FallbackBuffer; } - if (bufferArg == null) - bufferArg = new byte [1]; - for (int i = 0; i < size; i++) { - bufferArg [0] = bytes [byteIndex + i]; - buffer.Fallback (bufferArg, 0); - while (buffer.Remaining > 0) - chars [charIndex++] = buffer.GetNextChar (); - buffer.Reset (); - } + + var bufferArg = new byte [size]; + + for (int i = 0; i < size; i++) + bufferArg [i] = bytes [byteIndex + i]; + + buffer.Fallback (bufferArg, 0); + while (buffer.Remaining > 0) + chars [charIndex++] = buffer.GetNextChar (); + buffer.Reset (); } // Get the number of characters needed to decode a byte buffer. public override int GetCharCount (byte[] bytes, int index, int count) { DecoderFallbackBuffer buf = null; - byte [] bufferArg = null; - return InternalGetCharCount (bytes, index, count, 0, 0, DecoderFallback, ref buf, ref bufferArg, true); + return InternalGetCharCount (bytes, index, count, 0, 0, DecoderFallback, ref buf, true); } [CLSCompliant (false)] @@ -636,8 +637,7 @@ public override int GetCharCount (byte[] bytes, int index, int count) public unsafe override int GetCharCount (byte* bytes, int count) { DecoderFallbackBuffer buf = null; - byte [] bufferArg = null; - return InternalGetCharCount (bytes, count, 0, 0, DecoderFallback, ref buf, ref bufferArg, true); + return InternalGetCharCount (bytes, count, 0, 0, DecoderFallback, ref buf, true); } // Get the characters that result from decoding a byte buffer. @@ -645,7 +645,7 @@ private unsafe static int InternalGetChars ( byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, ref uint leftOverBits, ref uint leftOverCount, object provider, - ref DecoderFallbackBuffer fallbackBuffer, ref byte [] bufferArg, bool flush) + ref DecoderFallbackBuffer fallbackBuffer, bool flush) { // Validate the parameters. if (bytes == null) { @@ -669,10 +669,10 @@ private unsafe static int InternalGetChars ( fixed (char* cptr = chars) { if (byteCount == 0 || byteIndex == bytes.Length) - return InternalGetChars (null, 0, cptr + charIndex, chars.Length - charIndex, ref leftOverBits, ref leftOverCount, provider, ref fallbackBuffer, ref bufferArg, flush); + return InternalGetChars (null, 0, cptr + charIndex, chars.Length - charIndex, ref leftOverBits, ref leftOverCount, provider, ref fallbackBuffer, flush); // otherwise... fixed (byte* bptr = bytes) - return InternalGetChars (bptr + byteIndex, byteCount, cptr + charIndex, chars.Length - charIndex, ref leftOverBits, ref leftOverCount, provider, ref fallbackBuffer, ref bufferArg, flush); + return InternalGetChars (bptr + byteIndex, byteCount, cptr + charIndex, chars.Length - charIndex, ref leftOverBits, ref leftOverCount, provider, ref fallbackBuffer, flush); } } @@ -680,7 +680,7 @@ private unsafe static int InternalGetChars ( byte* bytes, int byteCount, char* chars, int charCount, ref uint leftOverBits, ref uint leftOverCount, object provider, - ref DecoderFallbackBuffer fallbackBuffer, ref byte [] bufferArg, bool flush) + ref DecoderFallbackBuffer fallbackBuffer, bool flush) { int charIndex = 0, byteIndex = 0; int length = charCount; @@ -745,7 +745,7 @@ private unsafe static int InternalGetChars ( leftSize = 6; } else { // Invalid UTF-8 start character. - Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex, 1, chars, ref posn); + Fallback (provider, ref fallbackBuffer, bytes, byteIndex, 1, chars, ref posn); } } else { // Process an extra byte in a multi-byte sequence. @@ -774,11 +774,11 @@ private unsafe static int InternalGetChars ( break; } if (overlong) { - Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); + Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); } else if ((leftBits & 0xF800) == 0xD800) { // UTF-8 doesn't use surrogate characters - Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); + Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); } else { if (posn >= length) { @@ -798,13 +798,13 @@ private unsafe static int InternalGetChars ( chars[posn++] = (char)((leftBits & (uint)0x3FF) + (uint)0xDC00); } else { - Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); + Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); } leftSize = 0; } } else { // Invalid UTF-8 sequence: clear and restart. - Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); + Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); leftSize = 0; --byteIndex; } @@ -813,7 +813,7 @@ private unsafe static int InternalGetChars ( if (flush && leftSize != 0) { // We had left-over bytes that didn't make up // a complete UTF-8 character sequence. - Fallback (provider, ref fallbackBuffer, ref bufferArg, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); + Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); } leftOverBits = leftBits; leftOverCount = (leftSoFar | (leftSize << 4)); @@ -831,7 +831,7 @@ public override int GetChars (byte[] bytes, int byteIndex, int byteCount, DecoderFallbackBuffer buf = null; byte [] bufferArg = null; return InternalGetChars (bytes, byteIndex, byteCount, chars, - charIndex, ref leftOverBits, ref leftOverCount, DecoderFallback, ref buf, ref bufferArg, true); + charIndex, ref leftOverBits, ref leftOverCount, DecoderFallback, ref buf, true); } [CLSCompliant (false)] @@ -839,11 +839,10 @@ public override int GetChars (byte[] bytes, int byteIndex, int byteCount, public unsafe override int GetChars (byte* bytes, int byteCount, char* chars, int charCount) { DecoderFallbackBuffer buf = null; - byte [] bufferArg = null; uint leftOverBits = 0; uint leftOverCount = 0; return InternalGetChars (bytes, byteCount, chars, - charCount, ref leftOverBits, ref leftOverCount, DecoderFallback, ref buf, ref bufferArg, true); + charCount, ref leftOverBits, ref leftOverCount, DecoderFallback, ref buf, true); } // Get the maximum number of bytes needed to encode a @@ -953,17 +952,15 @@ public UTF8Decoder (Encoding encoding) public override int GetCharCount (byte[] bytes, int index, int count) { DecoderFallbackBuffer buf = null; - byte [] bufferArg = null; return InternalGetCharCount (bytes, index, count, - leftOverBits, leftOverCount, this, ref buf, ref bufferArg, false); + leftOverBits, leftOverCount, this, ref buf, false); } public override int GetChars (byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { DecoderFallbackBuffer buf = null; - byte [] bufferArg = null; return InternalGetChars (bytes, byteIndex, byteCount, - chars, charIndex, ref leftOverBits, ref leftOverCount, this, ref buf, ref bufferArg, false); + chars, charIndex, ref leftOverBits, ref leftOverCount, this, ref buf, false); } } // class UTF8Decoder From f79c64942e7a8508cc8ce72e39328b057ba1c1cc Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 2 Sep 2014 23:10:19 +0800 Subject: [PATCH 008/543] Changed overlong byte to be processed again. The byte is processed again because it can be the begin of a new multi-byte encoded character. --- mcs/class/corlib/System.Text/UTF8Encoding.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mcs/class/corlib/System.Text/UTF8Encoding.cs b/mcs/class/corlib/System.Text/UTF8Encoding.cs index 9c8ed4dcbb7..1ea7a9ea86a 100644 --- a/mcs/class/corlib/System.Text/UTF8Encoding.cs +++ b/mcs/class/corlib/System.Text/UTF8Encoding.cs @@ -547,6 +547,7 @@ private unsafe static int InternalGetCharCount ( } if (overlong) { length += Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar); + --byteIndex; //process byte again } else if ((leftBits & 0xF800) == 0xD800) { // UTF-8 doesn't use surrogate characters @@ -775,6 +776,7 @@ private unsafe static int InternalGetChars ( } if (overlong) { Fallback (provider, ref fallbackBuffer, bytes, byteIndex - leftSoFar, leftSoFar, chars, ref posn); + --byteIndex; //process byte again } else if ((leftBits & 0xF800) == 0xD800) { // UTF-8 doesn't use surrogate characters From 883f9399f40e0c962f6cea211d9b316aac9fc1a9 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 2 Sep 2014 20:22:05 -0400 Subject: [PATCH 009/543] [runtime] Add an 'app' attribute to the 'aotcache' config section to specify which apps should use the AOT cache. --- mono/metadata/metadata-internals.h | 5 ++++ mono/metadata/mono-config.c | 10 +++++++ mono/mini/aot-runtime.c | 42 ++++++++++++++++++++++++------ 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/mono/metadata/metadata-internals.h b/mono/metadata/metadata-internals.h index e8e9c956526..b04b811d123 100644 --- a/mono/metadata/metadata-internals.h +++ b/mono/metadata/metadata-internals.h @@ -529,6 +529,11 @@ struct _MonoMethodSignature { * Doesn't really belong here. */ typedef struct { + /* + * Enable aot caching for applications whose main assemblies are in + * this list. + */ + GSList *apps; GSList *assemblies; } MonoAotCacheConfig; diff --git a/mono/metadata/mono-config.c b/mono/metadata/mono-config.c index ac148b08d6f..4d8ab4fccc7 100644 --- a/mono/metadata/mono-config.c +++ b/mono/metadata/mono-config.c @@ -365,12 +365,22 @@ aot_cache_start (gpointer user_data, { int i; MonoAotCacheConfig *config; + char *app_name = NULL; if (strcmp (element_name, "aotcache") != 0) return; config = mono_get_aot_cache_config (); + /* Per-app configuration */ + for (i = 0; attribute_names [i]; ++i) { + if (!strcmp (attribute_names [i], "app")) { + config->apps = g_slist_prepend (config->apps, g_strdup (attribute_values [i])); + return; + } + } + + /* Global configuration */ for (i = 0; attribute_names [i]; ++i) { if (!strcmp (attribute_names [i], "assemblies")) { char **parts, **ptr; diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index f484f18364b..b31acd95ecf 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -176,6 +176,8 @@ static GHashTable *ji_to_amodule; */ static gboolean enable_aot_cache = FALSE; +static gboolean mscorlib_aot_loaded; + /* For debugging */ static gint32 mono_last_aot_method = -1; @@ -1381,6 +1383,7 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) gint exit_status; char *hash; int pid; + gboolean enabled; *aot_name = NULL; @@ -1389,13 +1392,33 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) /* Check in the list of assemblies enabled for aot caching */ config = mono_get_aot_cache_config (); - for (l = config->assemblies; l; l = l->next) { - char *n = l->data; - if (!strcmp (assembly->aname.name, n)) - break; + enabled = FALSE; + if (config->apps) { + MonoDomain *domain = mono_domain_get (); + MonoAssembly *entry_assembly = domain->entry_assembly; + + for (l = config->apps; l; l = l->next) { + char *n = l->data; + + if ((entry_assembly && !strcmp (entry_assembly->aname.name, n)) || (!entry_assembly && !strcmp (assembly->aname.name, n))) + break; + } + if (l) + enabled = TRUE; } - if (!l) + + if (!enabled) { + for (l = config->assemblies; l; l = l->next) { + char *n = l->data; + + if (!strcmp (assembly->aname.name, n)) + break; + } + if (l) + enabled = TRUE; + } + if (!enabled) return NULL; if (!cache_dir) { @@ -3761,10 +3784,13 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method) MonoAotModule *amodule = klass->image->aot_module; guint8 *code; - if (enable_aot_cache && !amodule && klass->image == mono_defaults.corlib) { + if (enable_aot_cache && !amodule && domain->entry_assembly && klass->image == mono_defaults.corlib) { /* This cannot be AOTed during startup, so do it now */ - load_aot_module (klass->image->assembly, NULL); - amodule = klass->image->aot_module; + if (!mscorlib_aot_loaded) { + load_aot_module (klass->image->assembly, NULL); + amodule = klass->image->aot_module; + } + mscorlib_aot_loaded = TRUE; } if (!amodule) From 541639c3bb82651af7bb6a49ecb9a818a4b8024c Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 2 Sep 2014 20:25:16 -0400 Subject: [PATCH 010/543] [runtime] Load the runtime config file before initializing the runtime, so it can pick up the aot-cache configuration information. --- mono/mini/driver.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mono/mini/driver.c b/mono/mini/driver.c index 2929e813a4d..7b34b18df0e 100644 --- a/mono/mini/driver.c +++ b/mono/mini/driver.c @@ -1903,6 +1903,11 @@ mono_main (int argc, char* argv[]) mono_load_coree (argv [i]); #endif + /* Parse gac loading options before loading assemblies. */ + if (mono_compile_aot || action == DO_EXEC || action == DO_DEBUGGER) { + mono_config_parse (config_file); + } + mono_set_defaults (mini_verbose, opt); domain = mini_init (argv [i], forced_version); @@ -1968,11 +1973,6 @@ mono_main (int argc, char* argv[]) break; } - /* Parse gac loading options before loading assemblies. */ - if (mono_compile_aot || action == DO_EXEC || action == DO_DEBUGGER) { - mono_config_parse (config_file); - } - #ifdef MONO_JIT_INFO_TABLE_TEST if (test_jit_info_table) jit_info_table_test (domain); From f9b27e2e7383bd8c2064a38c64bbb6f6ef40ef56 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 2 Sep 2014 21:10:11 -0400 Subject: [PATCH 011/543] Fix a warning. --- mono/metadata/mono-config.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mono/metadata/mono-config.c b/mono/metadata/mono-config.c index 4d8ab4fccc7..1e85012dd0f 100644 --- a/mono/metadata/mono-config.c +++ b/mono/metadata/mono-config.c @@ -365,7 +365,6 @@ aot_cache_start (gpointer user_data, { int i; MonoAotCacheConfig *config; - char *app_name = NULL; if (strcmp (element_name, "aotcache") != 0) return; From ec2b629fa9c15f7f2631651972e5f4fe87ef5f18 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 3 Sep 2014 19:47:17 +1000 Subject: [PATCH 012/543] Stop warning about winsock2.h being included before windows.h This change is released under the MIT license. --- mono/io-layer/io-layer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/io-layer/io-layer.h b/mono/io-layer/io-layer.h index 394799bc86c..6b21f056ca2 100755 --- a/mono/io-layer/io-layer.h +++ b/mono/io-layer/io-layer.h @@ -21,9 +21,9 @@ * Declare as __GetProcessId for unsupported targets. */ #define GetProcessId __GetProcessId #endif -#include #include #include +#include /* * The mingw version says: * /usr/i686-pc-mingw32/sys-root/mingw/include/ws2tcpip.h:38:2: error: #error "ws2tcpip.h is not compatible with winsock.h. Include winsock2.h instead." From 17972cec4f5d88ab1732e02b9c11fbf7922fe2c5 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 3 Sep 2014 18:27:28 +0800 Subject: [PATCH 013/543] Added test ISO8601FractionalDigits. Covers #22417. --- mcs/class/corlib/Test/System/DateTimeTest.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mcs/class/corlib/Test/System/DateTimeTest.cs b/mcs/class/corlib/Test/System/DateTimeTest.cs index 343e723be82..b8eac3a8939 100644 --- a/mcs/class/corlib/Test/System/DateTimeTest.cs +++ b/mcs/class/corlib/Test/System/DateTimeTest.cs @@ -2584,5 +2584,16 @@ public void Parse_ThaiCalendar () Assert.AreEqual (dt, parsed, "#1"); } + + [Test] + public void ISO8601FractionalDigits () + { + string date = "2014-08-25T01:20:23.601911612343423423465789789365674575676746756747467Z"; + long expectedTicks = 635445264236019116; + + var dt = DateTime.Parse (date, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); + + Assert.AreEqual (expectedTicks, dt.Ticks); + } } } From db57c23c291653353bbd00996552cca02c95cd53 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 3 Sep 2014 18:29:58 +0800 Subject: [PATCH 014/543] DateTime.Parse now handles unlimited number of fractional digits. This change was made because .NET can parse ISO8601 format with an unlimited number of fractional digits. Fixes #22417. --- mcs/class/corlib/System/DateTime.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/mcs/class/corlib/System/DateTime.cs b/mcs/class/corlib/System/DateTime.cs index 735599680c5..8337d80ef84 100644 --- a/mcs/class/corlib/System/DateTime.cs +++ b/mcs/class/corlib/System/DateTime.cs @@ -1466,6 +1466,25 @@ private static bool _DoParse (string s, if (num_parsed == -1) return false; fractionalSeconds = decimalNumber / Math.Pow(10.0, num_parsed); + + //Parse ISO8601 with an unlimited number of fractional digits. + if (!exact && num == 6 && hour != -1 && minute != -1 && second != -1) { + var total_num_parsed = num_parsed; + while (true) { + valuePos += num_parsed; + decimalNumber = (double) _ParseNumber (s, valuePos, 0, 1, leading_zeros, sloppy_parsing, out num_parsed); + if (num_parsed < 1) { + num_parsed = 0; + break; + } + + total_num_parsed += num_parsed; + if (total_num_parsed > 15) + continue; //not enough precision, ignore additional digits. + + fractionalSeconds += decimalNumber / Math.Pow (10.0, total_num_parsed); + } + } break; case 't': if (!_ParseAmPm (s, valuePos, num > 0 ? 0 : 1, dfi, exact, out num_parsed, ref ampm)) From 59668db7f46bb9397f6ea6a9639e7c768701411e Mon Sep 17 00:00:00 2001 From: Vladimir Kargov Date: Wed, 3 Sep 2014 16:29:05 +0400 Subject: [PATCH 015/543] [corlib] In a TimeZone test, UtcOffset is taken for the current year, so take DaylightChanges for the current year as well. --- mcs/class/corlib/Test/System/TimeZoneTest.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mcs/class/corlib/Test/System/TimeZoneTest.cs b/mcs/class/corlib/Test/System/TimeZoneTest.cs index 6f97c359ebc..47915f722b4 100644 --- a/mcs/class/corlib/Test/System/TimeZoneTest.cs +++ b/mcs/class/corlib/Test/System/TimeZoneTest.cs @@ -303,11 +303,12 @@ public void GetUtcOffsetAtDSTBoundary () TimeZone tz = TimeZone.CurrentTimeZone; - DaylightTime daylightChanges = tz.GetDaylightChanges(2007); + int year = DateTime.Now.Year; + DaylightTime daylightChanges = tz.GetDaylightChanges(year); DateTime dst_end = daylightChanges.End; if (dst_end == DateTime.MinValue) - Assert.Ignore (tz.StandardName + " did not observe daylight saving time during 2007."); + Assert.Ignore (tz.StandardName + " did not observe daylight saving time during " + year + "."); var standardOffset = tz.GetUtcOffset(daylightChanges.Start.AddMinutes(-1)); From 748fefa1d7199f008c6e56499ba482fb17fe1583 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Wed, 3 Sep 2014 15:57:39 -0400 Subject: [PATCH 016/543] [runtime] Cleanup the horrible ifdef hell that is the stack bounds discovery code. This split a single chunk of intractable ifdef hell into a beautiful set of per-target files. This will allow us to actually figure out what's going on on each target. --- mono/utils/Makefile.am | 3 + mono/utils/mono-threads-freebsd.c | 24 ++++++ mono/utils/mono-threads-linux.c | 21 +++++ mono/utils/mono-threads-mach.c | 27 ++++++- mono/utils/mono-threads-openbsd.c | 32 ++++++++ mono/utils/mono-threads-posix.c | 123 ------------------------------ mono/utils/mono-threads.c | 10 +++ 7 files changed, 114 insertions(+), 126 deletions(-) create mode 100644 mono/utils/mono-threads-freebsd.c create mode 100644 mono/utils/mono-threads-linux.c create mode 100644 mono/utils/mono-threads-openbsd.c diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am index 09410cda403..53e0e3d20d8 100644 --- a/mono/utils/Makefile.am +++ b/mono/utils/Makefile.am @@ -99,6 +99,9 @@ monoutils_sources = \ mono-threads-mach.c \ mono-threads-mach-helper.c \ mono-threads-windows.c \ + mono-threads-linux.c \ + mono-threads-freebsd.c \ + mono-threads-openbsd.c \ mono-threads.h \ mono-tls.h \ mono-tls.c \ diff --git a/mono/utils/mono-threads-freebsd.c b/mono/utils/mono-threads-freebsd.c new file mode 100644 index 00000000000..7cbbca14b57 --- /dev/null +++ b/mono/utils/mono-threads-freebsd.c @@ -0,0 +1,24 @@ +#include + +#if defined(__FreeBSD__) + +#include +#include + +void +mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +{ + pthread_attr_t attr; + guint8 *current = (guint8*)&attr; + + *staddr = NULL; + *stsize = (size_t)-1; + + pthread_attr_init (&attr); + pthread_attr_get_np (pthread_self (), &attr); + + pthread_attr_getstack (&attr, (void**)staddr, stsize); + pthread_attr_destroy (&attr); +} + +#endif diff --git a/mono/utils/mono-threads-linux.c b/mono/utils/mono-threads-linux.c new file mode 100644 index 00000000000..13b2fed651d --- /dev/null +++ b/mono/utils/mono-threads-linux.c @@ -0,0 +1,21 @@ +#include + +#if defined(PLATFORM_LINUX) + +#include + +void +mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +{ + pthread_attr_t attr; + guint8 *current = (guint8*)&attr; + + *staddr = NULL; + *stsize = (size_t)-1; + + pthread_getattr_np (pthread_self (), &attr); + pthread_attr_getstack (&attr, (void**)staddr, stsize); + pthread_attr_destroy (&attr); +} + +#endif diff --git a/mono/utils/mono-threads-mach.c b/mono/utils/mono-threads-mach.c index f4ad2637e57..4ed6820e900 100644 --- a/mono/utils/mono-threads-mach.c +++ b/mono/utils/mono-threads-mach.c @@ -11,18 +11,19 @@ #if defined(__MACH__) +/* For pthread_main_np, pthread_get_stackaddr_np and pthread_get_stacksize_np */ +#define _DARWIN_C_SOURCE 1 + #include #include #include #include #include +#include #include #include #include -#include -#include - void mono_threads_init_platform (void) { @@ -148,4 +149,24 @@ mono_threads_core_set_name (MonoNativeThreadId tid, const char *name) /* pthread_setnmae_np() on Mac is not documented and doesn't receive thread id. */ } +void +mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +{ + *staddr = (guint8*)pthread_get_stackaddr_np (pthread_self()); + *stsize = pthread_get_stacksize_np (pthread_self()); + +#ifdef TARGET_OSX + /* + * Mavericks reports stack sizes as 512kb: + * http://permalink.gmane.org/gmane.comp.java.openjdk.hotspot.devel/11590 + * https://bugs.openjdk.java.net/browse/JDK-8020753 + */ + if (pthread_main_np () && *stsize == 512 * 1024) + *stsize = 2048 * mono_pagesize (); +#endif + + /* staddr points to the start of the stack, not the end */ + *staddr -= *stsize; +} + #endif diff --git a/mono/utils/mono-threads-openbsd.c b/mono/utils/mono-threads-openbsd.c new file mode 100644 index 00000000000..96a962230e1 --- /dev/null +++ b/mono/utils/mono-threads-openbsd.c @@ -0,0 +1,32 @@ +#include + +#if defined(__OpenBSD__) + +#include +#include + +void +mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +{ + /* TODO : Determine if this code is actually still needed. It may already be covered by the case above. */ + pthread_attr_t attr; + guint8 *current = (guint8*)&attr; + + *staddr = NULL; + *stsize = (size_t)-1; + + pthread_attr_init (&attr); + + stack_t ss; + int rslt; + + rslt = pthread_stackseg_np (pthread_self (), &ss); + g_assert (rslt == 0); + + *staddr = (guint8*)((size_t)ss.ss_sp - ss.ss_size); + *stsize = ss.ss_size; + + pthread_attr_destroy (&attr); +} + +#endif diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index 8a21c553054..ce087bbc36b 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -9,17 +9,6 @@ #include -#if defined(TARGET_OSX) -/* For pthread_main_np () */ -#define _DARWIN_C_SOURCE 1 -#include -#endif - -#if defined(__OpenBSD__) || defined(__FreeBSD__) -#include -#include -#endif - #include #include #include @@ -34,11 +23,6 @@ extern int tkill (pid_t tid, int signal); #endif -#if defined(PLATFORM_MACOSX) && defined(HAVE_PTHREAD_GET_STACKADDR_NP) -void *pthread_get_stackaddr_np(pthread_t); -size_t pthread_get_stacksize_np(pthread_t); -#endif - #if defined(_POSIX_VERSION) || defined(__native_client__) #include #include @@ -185,113 +169,6 @@ mono_threads_core_resume_created (MonoThreadInfo *info, MonoNativeThreadId tid) MONO_SEM_POST (&info->create_suspended_sem); } -void -mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) -{ -#if defined(HAVE_PTHREAD_GET_STACKSIZE_NP) && defined(HAVE_PTHREAD_GET_STACKADDR_NP) - /* Mac OS X */ - *staddr = (guint8*)pthread_get_stackaddr_np (pthread_self()); - *stsize = pthread_get_stacksize_np (pthread_self()); - -#ifdef TARGET_OSX - /* - * Mavericks reports stack sizes as 512kb: - * http://permalink.gmane.org/gmane.comp.java.openjdk.hotspot.devel/11590 - * https://bugs.openjdk.java.net/browse/JDK-8020753 - */ - if (pthread_main_np () && *stsize == 512 * 1024) - *stsize = 2048 * mono_pagesize (); -#endif - - /* staddr points to the start of the stack, not the end */ - *staddr -= *stsize; - - /* When running under emacs, sometimes staddr is not aligned to a page size */ - *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize() - 1)); - return; - -#elif (defined(HAVE_PTHREAD_GETATTR_NP) || defined(HAVE_PTHREAD_ATTR_GET_NP)) && defined(HAVE_PTHREAD_ATTR_GETSTACK) - /* Linux, BSD */ - - pthread_attr_t attr; - guint8 *current = (guint8*)&attr; - - *staddr = NULL; - *stsize = (size_t)-1; - - pthread_attr_init (&attr); - -#if defined(HAVE_PTHREAD_GETATTR_NP) - /* Linux */ - pthread_getattr_np (pthread_self(), &attr); - -#elif defined(HAVE_PTHREAD_ATTR_GET_NP) - /* BSD */ - pthread_attr_get_np (pthread_self(), &attr); - -#else -#error Cannot determine which API is needed to retrieve pthread attributes. -#endif - - pthread_attr_getstack (&attr, (void**)staddr, stsize); - pthread_attr_destroy (&attr); - - if (*staddr) - g_assert ((current > *staddr) && (current < *staddr + *stsize)); - - /* When running under emacs, sometimes staddr is not aligned to a page size */ - *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1)); - return; - -#elif defined(__OpenBSD__) - /* OpenBSD */ - /* TODO : Determine if this code is actually still needed. It may already be covered by the case above. */ - - pthread_attr_t attr; - guint8 *current = (guint8*)&attr; - - *staddr = NULL; - *stsize = (size_t)-1; - - pthread_attr_init (&attr); - - stack_t ss; - int rslt; - - rslt = pthread_stackseg_np(pthread_self(), &ss); - g_assert (rslt == 0); - - *staddr = (guint8*)((size_t)ss.ss_sp - ss.ss_size); - *stsize = ss.ss_size; - - pthread_attr_destroy (&attr); - - if (*staddr) - g_assert ((current > *staddr) && (current < *staddr + *stsize)); - - /* When running under emacs, sometimes staddr is not aligned to a page size */ - *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1)); - return; - -#elif defined(sun) || defined(__native_client__) - /* Solaris/Illumos, NaCl */ - pthread_attr_t attr; - pthread_attr_init (&attr); - pthread_attr_getstacksize (&attr, &stsize); - pthread_attr_destroy (&attr); - *staddr = NULL; - return; - -#else - /* FIXME: It'd be better to use the 'error' preprocessor macro here so we know - at compile-time if the target platform isn't supported. */ -#warning "Unable to determine how to retrieve a thread's stack-bounds for this platform in 'mono_thread_get_stack_bounds()'." - *staddr = NULL; - *stsize = 0; - return; -#endif -} - gboolean mono_threads_core_yield (void) { diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index 195a919c3e7..cbb768aea8c 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -787,7 +788,16 @@ mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 void mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize) { + guint8 *current = (guint8 *)&stsize; mono_threads_core_get_stack_bounds (staddr, stsize); + if (!*staddr) + return; + + /* Sanity check the result */ + g_assert ((current > *staddr) && (current < *staddr + *stsize)); + + /* When running under emacs, sometimes staddr is not aligned to a page size */ + *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1)); } gboolean From b7604565016ea1d0883765dcd7a44ba9662a1521 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Wed, 3 Sep 2014 16:32:30 -0400 Subject: [PATCH 017/543] [build] Include mono/utils into the extensions module. --- autogen.sh | 1 + mono/utils/{Makefile.am => Makefile.am.in} | 0 2 files changed, 1 insertion(+) rename mono/utils/{Makefile.am => Makefile.am.in} (100%) diff --git a/autogen.sh b/autogen.sh index 5213ecffd3c..bf9c4a330e6 100755 --- a/autogen.sh +++ b/autogen.sh @@ -124,6 +124,7 @@ if test x$has_ext_mod = xtrue; then else cat mono/mini/Makefile.am.in > mono/mini/Makefile.am cat mono/metadata/Makefile.am.in > mono/metadata/Makefile.am + cat mono/utils/Makefile.am.in > mono/utils/Makefile.am fi diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am.in similarity index 100% rename from mono/utils/Makefile.am rename to mono/utils/Makefile.am.in From a2e939a8a37e1baa3c7c3c4f54871cb6839aa6c3 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Wed, 3 Sep 2014 16:34:18 -0400 Subject: [PATCH 018/543] [build] Deps tracking for mono/utils/Makefile.am when extension module is disabled. --- mono/utils/Makefile.am.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mono/utils/Makefile.am.in b/mono/utils/Makefile.am.in index 53e0e3d20d8..b96155be87e 100644 --- a/mono/utils/Makefile.am.in +++ b/mono/utils/Makefile.am.in @@ -200,3 +200,9 @@ libmonoutilsinclude_HEADERS = \ mono-counters.h EXTRA_DIST = ChangeLog mono-embed.h mono-embed.c + +if HAS_EXTENSION_MODULE +else +Makefile.am: Makefile.am.in + cp $< $@ +endif From 43177ef54bb2657d28dc4ea3cfb95f30aa44fa7c Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Wed, 3 Sep 2014 16:58:30 -0400 Subject: [PATCH 019/543] [utils] Add android extension point to threading. --- mono/utils/Makefile.am.in | 1 + mono/utils/mono-threads-android.c | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 mono/utils/mono-threads-android.c diff --git a/mono/utils/Makefile.am.in b/mono/utils/Makefile.am.in index b96155be87e..24e5d064e37 100644 --- a/mono/utils/Makefile.am.in +++ b/mono/utils/Makefile.am.in @@ -102,6 +102,7 @@ monoutils_sources = \ mono-threads-linux.c \ mono-threads-freebsd.c \ mono-threads-openbsd.c \ + mono-threads-android.c \ mono-threads.h \ mono-tls.h \ mono-tls.c \ diff --git a/mono/utils/mono-threads-android.c b/mono/utils/mono-threads-android.c new file mode 100644 index 00000000000..a72ee81a560 --- /dev/null +++ b/mono/utils/mono-threads-android.c @@ -0,0 +1,9 @@ +#include + +#if defined(PLATFORM_ANDROID) + +#ifdef ENABLE_EXTENSION_MODULE +#include "../../../mono-extensions/mono/utils/mono-threads-android.c" +#endif + +#endif From d2cee144fe0dec1d68256e6b787641d90096eccf Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 3 Sep 2014 18:14:47 -0400 Subject: [PATCH 020/543] [sgen] Use mono_thread_info_get_stack_bounds () on win32 as well, the stack bottom value returned by it is correct, only the stack top value is unusable, since windows dynamically extends the stack. --- mono/metadata/sgen-gc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index aec3359b526..890001a8cb2 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -3835,11 +3835,11 @@ sgen_thread_register (SgenThreadInfo* info, void *addr) binary_protocol_thread_register ((gpointer)mono_thread_info_get_tid (info)); /* On win32, stack_start_limit should be 0, since the stack can grow dynamically */ -#ifndef HOST_WIN32 mono_thread_info_get_stack_bounds (&staddr, &stsize); -#endif if (staddr) { +#ifndef HOST_WIN32 info->stack_start_limit = staddr; +#endif info->stack_end = staddr + stsize; } else { gsize stack_bottom = (gsize)addr; From f746fe8d1bb40f22d45e12655fa04ef44eb5dd1a Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 3 Sep 2014 21:20:11 -0400 Subject: [PATCH 021/543] Revert "[build] Deps tracking for mono/utils/Makefile.am when extension module is disabled." This reverts commit a2e939a8a37e1baa3c7c3c4f54871cb6839aa6c3. Revert this as is not needed. --- mono/utils/Makefile.am.in | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mono/utils/Makefile.am.in b/mono/utils/Makefile.am.in index 24e5d064e37..c5464d16b16 100644 --- a/mono/utils/Makefile.am.in +++ b/mono/utils/Makefile.am.in @@ -201,9 +201,3 @@ libmonoutilsinclude_HEADERS = \ mono-counters.h EXTRA_DIST = ChangeLog mono-embed.h mono-embed.c - -if HAS_EXTENSION_MODULE -else -Makefile.am: Makefile.am.in - cp $< $@ -endif From c7b3d5c3ba3b1be9dcc1b7c5491b82ce099ca381 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 3 Sep 2014 21:20:33 -0400 Subject: [PATCH 022/543] Revert "[build] Include mono/utils into the extensions module." This reverts commit b7604565016ea1d0883765dcd7a44ba9662a1521. Revert this as it is not needed. --- autogen.sh | 1 - mono/utils/{Makefile.am.in => Makefile.am} | 0 2 files changed, 1 deletion(-) rename mono/utils/{Makefile.am.in => Makefile.am} (100%) diff --git a/autogen.sh b/autogen.sh index bf9c4a330e6..5213ecffd3c 100755 --- a/autogen.sh +++ b/autogen.sh @@ -124,7 +124,6 @@ if test x$has_ext_mod = xtrue; then else cat mono/mini/Makefile.am.in > mono/mini/Makefile.am cat mono/metadata/Makefile.am.in > mono/metadata/Makefile.am - cat mono/utils/Makefile.am.in > mono/utils/Makefile.am fi diff --git a/mono/utils/Makefile.am.in b/mono/utils/Makefile.am similarity index 100% rename from mono/utils/Makefile.am.in rename to mono/utils/Makefile.am From 5d80954463306778a9145ff94f27afe27f7d0a1c Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Thu, 4 Sep 2014 00:14:06 -0400 Subject: [PATCH 023/543] Bump Mono version -> 3.10.1 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 985d487f30b..2d78df23994 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # Process this file with autoconf to produce a configure script. #AC_PREREQ([2.62]) -AC_INIT(mono, [3.10], +AC_INIT(mono, [3.10.1], [http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono]) AC_CONFIG_SRCDIR([README.md]) From 806b95d844b2704d352d3b2fcb82abbf0bbdd000 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 4 Sep 2014 10:36:22 +0200 Subject: [PATCH 024/543] [mcs] recursive pattern matching --- mcs/mcs/codegen.cs | 2 + mcs/mcs/cs-parser.jay | 128 +++++++++-------- mcs/mcs/expression.cs | 258 ++++++++++++++++++++++++++++++++++- mcs/mcs/method.cs | 4 + mcs/tests/test-pattern-03.cs | 14 ++ mcs/tests/test-pattern-04.cs | 77 +++++++++++ mcs/tests/ver-il-net_4_5.xml | 36 +++++ 7 files changed, 457 insertions(+), 62 deletions(-) create mode 100644 mcs/tests/test-pattern-03.cs create mode 100644 mcs/tests/test-pattern-04.cs diff --git a/mcs/mcs/codegen.cs b/mcs/mcs/codegen.cs index 55a061cf034..7ab8f746f53 100644 --- a/mcs/mcs/codegen.cs +++ b/mcs/mcs/codegen.cs @@ -222,6 +222,8 @@ public List StatementEpilogue { public List TryFinallyUnwind { get; set; } + public Label RecursivePatternLabel { get; set; } + #endregion public void AddStatementEpilog (IExpressionCleanup cleanupExpression) diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index 7200290286c..5205d11d860 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -2179,6 +2179,8 @@ operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS { valid_param_mod = ParameterModifierType.DefaultValue; + if ((Operator.OpType) $3 == Operator.OpType.Is) + valid_param_mod |= ParameterModifierType.Out; } opt_formal_parameter_list CLOSE_PARENS { @@ -2203,6 +2205,8 @@ operator_declarator report.Error (1535, loc, "Overloaded unary operator `{0}' takes one parameter", Operator.GetName (op)); } + } else if (op == Operator.OpType.Is) { + // TODO: Special checks for is operator } else { if (p_count == 1) { report.Error (1019, loc, "Overloadable unary operator expected"); @@ -2249,6 +2253,13 @@ overloadable_operator | OP_LT { $$ = Operator.OpType.LessThan; } | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; } | OP_LE { $$ = Operator.OpType.LessThanOrEqual; } + | IS + { + if (lang_version != LanguageVersion.Experimental) + FeatureIsNotAvailable (GetLocation ($1), "is user operator"); + + $$ = Operator.OpType.Is; + } ; conversion_operator_declarator @@ -3240,7 +3251,7 @@ integral_type primary_expression - : primary_expression_or_type + : type_name_expression | literal | array_creation_expression | parenthesized_expression @@ -3262,7 +3273,7 @@ primary_expression | undocumented_expressions ; -primary_expression_or_type +type_name_expression : simple_name_expr | IDENTIFIER GENERATE_COMPLETION { var lt = (LocatedToken) $1; @@ -4280,7 +4291,7 @@ additive_expression { $$ = new As ((Expression) $1, (Expression) $3, GetLocation ($2)); } - | additive_expression IS is_match_expr opt_identifier + | additive_expression IS pattern_type_expr opt_identifier { var is_expr = new Is ((Expression) $1, (Expression) $3, GetLocation ($2)); if ($4 != null) { @@ -4292,6 +4303,14 @@ additive_expression current_block.AddLocalName (is_expr.Variable); } + $$ = is_expr; + } + | additive_expression IS pattern_expr + { + var is_expr = new Is ((Expression) $1, (Expression) $3, GetLocation ($2)); + if (lang_version != LanguageVersion.Experimental) + FeatureIsNotAvailable (GetLocation ($2), "pattern matching"); + $$ = is_expr; } | additive_expression AS error @@ -4318,16 +4337,12 @@ additive_expression } ; -is_match_expr - : match_type - | match_type rank_specifiers - { - if ($1 is VarExpr) - $1 = new SimpleName ("var", ((VarExpr) $1).Location); +pattern_type_expr + : variable_type + ; - $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); - } - | literal +pattern_expr + : literal | PLUS prefixed_unary_expression { $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, GetLocation ($1)); @@ -4339,38 +4354,49 @@ is_match_expr | sizeof_expression | invocation_expression | default_value_expression + | STAR + { + $$ = new WildcardPattern (GetLocation ($1)); + } + | type_name_expression OPEN_PARENS opt_pattern_list CLOSE_PARENS + { + $$ = new RecursivePattern ((ATypeNameExpression) $1, (List) $3, GetLocation ($2)); + } ; -match_type - : primary_expression_or_type opt_nullable +pattern + : pattern_expr + | pattern_type_expr opt_identifier { - Expression expr = (Expression) $1; - if ($2 == null) { - SimpleName sn = expr as SimpleName; - if (sn != null && sn.Name == "var") - $$ = new VarExpr (sn.Location); - else - $$ = $1; - } else if (expr is ATypeNameExpression) { - $$ = new ComposedCast ((ATypeNameExpression)expr, (ComposedTypeSpecifier) $2); - } else { - Error_ExpectingTypeName (expr); - $$ = null; - } + var lt = (LocatedToken) $2; + var variable = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (variable); } - | primary_expression_or_type pointer_stars - { - ATypeNameExpression expr = $1 as ATypeNameExpression; + ; - if (expr != null) { - $$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2); - } else { - Error_ExpectingTypeName ((Expression)$1); - $$ = expr; - } +opt_pattern_list + : /* empty */ + | pattern_list + ; + +pattern_list + : pattern_argument + { + var expr = new List (); + expr.Add ((Expression) $1); + $$ = expr; } - | builtin_type_expression - | void_invalid + | pattern_list COMMA pattern_argument + { + var expr = (List) $1; + expr.Add ((Expression) $3); + $$ = expr; + } + ; + +pattern_argument + : pattern + | IDENTIFIER COLON pattern ; shift_expression @@ -5429,7 +5455,7 @@ variable_type * > The expressions are converted into types during semantic analysis. */ variable_type_simple - : primary_expression_or_type opt_nullable + : type_name_expression opt_nullable { // Ok, the above "primary_expression" is there to get rid of // both reduce/reduce and shift/reduces in the grammar, it should @@ -5445,30 +5471,20 @@ variable_type_simple // SimpleName is when you have // Blah i; - Expression expr = (Expression) $1; + var expr = (ATypeNameExpression) $1; if ($2 == null) { - SimpleName sn = expr as SimpleName; - if (sn != null && sn.Name == "var") - $$ = new VarExpr (sn.Location); + if (expr.Name == "var" && expr is SimpleName) + $$ = new VarExpr (expr.Location); else $$ = $1; - } else if (expr is ATypeNameExpression) { - $$ = new ComposedCast ((ATypeNameExpression)expr, (ComposedTypeSpecifier) $2); } else { - Error_ExpectingTypeName (expr); - $$ = null; + $$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2); } } - | primary_expression_or_type pointer_stars + | type_name_expression pointer_stars { - ATypeNameExpression expr = $1 as ATypeNameExpression; - - if (expr != null) { - $$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2); - } else { - Error_ExpectingTypeName ((Expression)$1); - $$ = expr; - } + var expr = (ATypeNameExpression) $1; + $$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2); } | builtin_type_expression | void_invalid diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 07ab42429c2..244f8abd40e 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -1541,7 +1541,12 @@ Expression CreateConstantResult (ResolveContext rc, bool result) public override void Emit (EmitContext ec) { if (probe_type_expr == null) { - EmitConstantMatch (ec); + if (ProbeType is WildcardPattern) { + expr.EmitSideEffect (ec); + ProbeType.Emit (ec); + } else { + EmitPatternMatch (ec); + } return; } @@ -1556,7 +1561,7 @@ public override void Emit (EmitContext ec) public override void EmitBranchable (EmitContext ec, Label target, bool on_true) { if (probe_type_expr == null) { - EmitConstantMatch (ec); + EmitPatternMatch (ec); } else { EmitLoad (ec); } @@ -1564,7 +1569,7 @@ public override void EmitBranchable (EmitContext ec, Label target, bool on_true) ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target); } - void EmitConstantMatch (EmitContext ec) + void EmitPatternMatch (EmitContext ec) { var no_match = ec.DefineLabel (); var end = ec.DefineLabel (); @@ -1602,6 +1607,10 @@ void EmitConstantMatch (EmitContext ec) ec.Emit (OpCodes.Dup); ec.Emit (OpCodes.Brfalse, no_match); + var rp = ProbeType as RecursivePattern; + if (rp != null) + ec.RecursivePatternLabel = ec.DefineLabel (); + if (number_mg != null) { var ce = new CallEmitter (); ce.Emit (ec, number_mg, number_args, loc); @@ -1610,12 +1619,20 @@ void EmitConstantMatch (EmitContext ec) ec.Emit (OpCodes.Unbox_Any, probe_type); ProbeType.Emit (ec); - ec.Emit (OpCodes.Ceq); + if (rp != null) { + ec.EmitInt (1); + } else { + ec.Emit (OpCodes.Ceq); + } } ec.Emit (OpCodes.Br_S, end); ec.MarkLabel (no_match); ec.Emit (OpCodes.Pop); + + if (rp != null) + ec.MarkLabel (ec.RecursivePatternLabel); + ec.EmitInt (0); ec.MarkLabel (end); } @@ -1701,6 +1718,11 @@ public override void FlowAnalysis (FlowAnalysisContext fc) protected override void ResolveProbeType (ResolveContext rc) { if (!(ProbeType is TypeExpr) && rc.Module.Compiler.Settings.Version == LanguageVersion.Experimental) { + if (ProbeType is PatternExpression) { + ProbeType.Resolve (rc); + return; + } + // // Have to use session recording because we don't have reliable type probing // mechanism (similar issue as in attributes resolving) @@ -1719,6 +1741,13 @@ protected override void ResolveProbeType (ResolveContext rc) return; } + var vexpr = ProbeType as VarExpr; + if (vexpr != null && vexpr.InferType (rc, expr)) { + probe_type_expr = vexpr.Type; + rc.Report.SetPrinter (prev_recorder); + return; + } + var expr_printer = new SessionReportPrinter (); rc.Report.SetPrinter (expr_printer); ProbeType = ProbeType.Resolve (rc); @@ -1777,7 +1806,13 @@ Expression ResolveMatchingExpression (ResolveContext rc) return this; } - throw new NotImplementedException (); + if (ProbeType is PatternExpression) { + return this; + } + + // TODO: Better error message + rc.Report.Error (150, ProbeType.Location, "A constant value is expected"); + return this; } Expression ResolveResultExpression (ResolveContext ec) @@ -1926,6 +1961,208 @@ public override object Accept (StructuralVisitor visitor) } } + class WildcardPattern : PatternExpression + { + public WildcardPattern (Location loc) + : base (loc) + { + } + + protected override Expression DoResolve (ResolveContext rc) + { + eclass = ExprClass.Value; + type = rc.BuiltinTypes.Object; + return this; + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (1); + } + } + + class RecursivePattern : PatternExpression + { + MethodGroupExpr operator_mg; + Arguments args; + Expression[] args_comparison; + + public RecursivePattern (ATypeNameExpression typeExpresion, List arguments, Location loc) + : base (loc) + { + PatternList = arguments; + TypeExpression = typeExpresion; + } + + public List PatternList { get; private set; } + + public ATypeNameExpression TypeExpression { get; private set; } + + protected override Expression DoResolve (ResolveContext rc) + { + type = TypeExpression.ResolveAsType (rc); + if (type == null) + return null; + + var operators = MemberCache.GetUserOperator (type, Operator.OpType.Is, true); + if (operators == null) { + Error_TypeDoesNotContainDefinition (rc, type, Operator.GetName (Operator.OpType.Is) + " operator"); + return null; + } + + var ops = FindMatchingOverloads (operators); + if (ops == null) { + // TODO: better error message + Error_TypeDoesNotContainDefinition (rc, type, Operator.GetName (Operator.OpType.Is) + " operator"); + return null; + } + + args = new Arguments (PatternList.Count + 1); + args.Add (new Argument (new EmptyExpression (type))); + + bool ok = true; + for (int i = 0; i < PatternList.Count; ++i) { + var expr = PatternList [i].Resolve (rc); + if (expr == null) { + ok = false; + continue; + } + + PatternList [i] = expr; + } + + if (!ok) + return null; + + var op = FindBestOverload (rc, ops); + if (op == null) { + // TODO: better error message + Error_TypeDoesNotContainDefinition (rc, type, Operator.GetName (Operator.OpType.Is) + " operator"); + return null; + } + + var op_types = op.Parameters.Types; + + for (int i = 0; i < PatternList.Count; ++i) { + // TODO: Needs releasing optimization + var lt = new LocalTemporary (op_types [i + 1]); + args.Add (new Argument (lt, Argument.AType.Out)); + + if (args_comparison == null) + args_comparison = new Expression[PatternList.Count]; + + var expr = PatternList [i]; + if (expr is WildcardPattern) { + args_comparison [i] = new EmptyExpression (expr.Type); + continue; + } + + var recursive = expr as RecursivePattern; + if (recursive != null) { + recursive.SetParentInstance (lt); + } + + expr = Convert.ImplicitConversionRequired (rc, expr, lt.Type, expr.Location); + if (expr == null) + continue; + + if (expr is RecursivePattern) { + args_comparison [i] = expr; + continue; + } + + // TODO: Better error handling + args_comparison [i] = new Binary (Binary.Operator.Equality, lt, expr, expr.Location).Resolve (rc); + } + + operator_mg = MethodGroupExpr.CreatePredefined (op, type, loc); + + eclass = ExprClass.Value; + return this; + } + + List FindMatchingOverloads (IList members) + { + List best = null; + foreach (MethodSpec method in members) { + var pm = method.Parameters; + if (pm.Count != PatternList.Count + 1) + continue; + + // TODO: Needs more thorough checks elsewhere to avoid doing this every time + bool ok = true; + for (int ii = 1; ii < pm.Count; ++ii) { + if ((pm.FixedParameters [ii].ModFlags & Parameter.Modifier.OUT) == 0) { + ok = false; + break; + } + } + + if (!ok) + continue; + + if (best == null) + best = new List (); + + best.Add (method); + } + + return best; + } + + MethodSpec FindBestOverload (ResolveContext rc, List methods) + { + for (int ii = 0; ii < PatternList.Count; ++ii) { + var expr = PatternList [ii]; + if (expr is WildcardPattern) + continue; + + for (int i = 0; i < methods.Count; ++i) { + var m = methods [i].Parameters.Types [ii + 1]; + if (!Convert.ImplicitConversionExists (rc, expr, m)) + methods.RemoveAt (i--); + } + } + + if (methods.Count != 1) + return null; + + return methods [0]; + } + + public override void Emit (EmitContext ec) + { + EmitBranchable (ec, ec.RecursivePatternLabel, false); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + operator_mg.EmitCall (ec, args, false); + ec.Emit (OpCodes.Brfalse, ec.RecursivePatternLabel); + foreach (var ac in args_comparison) { + ac.EmitBranchable (ec, ec.RecursivePatternLabel, false); + } + } + + void SetParentInstance (LocalTemporary instance) + { + args [0] = new Argument (instance); + } + } + + abstract class PatternExpression : Expression + { + protected PatternExpression (Location loc) + { + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotImplementedException (); + } + } + /// /// Implementation of the `as' operator. /// @@ -2710,11 +2947,16 @@ public Binary (Operator oper, Expression left, Expression right, bool isCompound } public Binary (Operator oper, Expression left, Expression right) + : this (oper, left, right, left.Location) + { + } + + public Binary (Operator oper, Expression left, Expression right, Location loc) { this.oper = oper; this.left = left; this.right = right; - this.loc = left.Location; + this.loc = loc; } #region Properties @@ -10556,6 +10798,10 @@ public override void Emit (EmitContext ec) // nothing, as we only exist to not do anything. } + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + } + public override void EmitSideEffect (EmitContext ec) { } diff --git a/mcs/mcs/method.cs b/mcs/mcs/method.cs index aa54bc4a4d9..a78b99c6419 100644 --- a/mcs/mcs/method.cs +++ b/mcs/mcs/method.cs @@ -2571,6 +2571,9 @@ public enum OpType : byte { Implicit, Explicit, + // Pattern matching + Is, + // Just because of enum TOP }; @@ -2608,6 +2611,7 @@ static Operator () names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" }; names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" }; names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" }; + names [(int) OpType.Is] = new string[] { "is", "op_Is" }; } public Operator (TypeDefinition parent, OpType type, FullNamedExpression ret_type, Modifiers mod_flags, ParametersCompiled parameters, diff --git a/mcs/tests/test-pattern-03.cs b/mcs/tests/test-pattern-03.cs new file mode 100644 index 00000000000..c4793bdb9d3 --- /dev/null +++ b/mcs/tests/test-pattern-03.cs @@ -0,0 +1,14 @@ +// Compiler options: -langversion:experimental + +class WildcardPattern +{ + static int Main () + { + long? o = 1; + bool b = o is *; + if (!b) + return 1; + + return 0; + } +} \ No newline at end of file diff --git a/mcs/tests/test-pattern-04.cs b/mcs/tests/test-pattern-04.cs new file mode 100644 index 00000000000..dff391cde5a --- /dev/null +++ b/mcs/tests/test-pattern-04.cs @@ -0,0 +1,77 @@ +// Compiler options: -langversion:experimental + +using System; + +class RecursivePattern +{ + static int Main () + { + object o = null; + bool b = o is C1 (8); + if (b) + return 1; + + o = new C1 (); + b = o is C1 (-4); + if (b) + return 2; + + b = o is C1 (8); + if (!b) + return 3; + + b = o is C1 (C1 (9), C1 (8)); + if (b) + return 4; + + b = o is C1 (C1 (*), C1 (8)); + if (!b) + return 41; + + b = o is C1 (0); + if (b) + return 5; + + ValueType vt = new S (); + b = vt is S (null, 0); + if (b) + return 6; + + b = vt is S (8, 0); + if (b) + return 7; + + b = vt is S (8, 2); + if (!b) + return 8; + + Console.WriteLine ("ok"); + return 0; + } +} + +class C1 +{ + public static bool operator is (C1 c, out int x) + { + x = 8; + return true; + } + + public static bool operator is (C1 c, out C1 c2, out C1 c3) + { + c2 = null; + c3 = null; + return true; + } +} + +struct S +{ + public static bool operator is (S s, out int? x, out decimal d) + { + x = 8; + d = 2; + return true; + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 201af97a9e7..f6bc79256a1 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -68463,6 +68463,42 @@ + + + + 33 + + + 7 + + + + + + + 750 + + + 7 + + + + + 13 + + + 16 + + + 7 + + + + + 34 + + + From 2b88d0235657bf790881b4998762af234e837c9c Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 4 Sep 2014 15:12:21 +0200 Subject: [PATCH 025/543] [mcs] recursive pattern with named arguments --- mcs/mcs/cs-parser.jay | 27 ++++++++--- mcs/mcs/expression.cs | 90 ++++++++++++++++++++++-------------- mcs/tests/test-pattern-05.cs | 39 ++++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 21 +++++++++ 4 files changed, 135 insertions(+), 42 deletions(-) create mode 100644 mcs/tests/test-pattern-05.cs diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index 5205d11d860..84d4e3f9f1b 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -4360,7 +4360,7 @@ pattern_expr } | type_name_expression OPEN_PARENS opt_pattern_list CLOSE_PARENS { - $$ = new RecursivePattern ((ATypeNameExpression) $1, (List) $3, GetLocation ($2)); + $$ = new RecursivePattern ((ATypeNameExpression) $1, (Arguments) $3, GetLocation ($2)); } ; @@ -4376,27 +4376,40 @@ pattern opt_pattern_list : /* empty */ + { + $$ = new Arguments (0); + } | pattern_list ; pattern_list : pattern_argument { - var expr = new List (); - expr.Add ((Expression) $1); - $$ = expr; + Arguments args = new Arguments (4); + args.Add ((Argument) $1); + $$ = args; } | pattern_list COMMA pattern_argument { - var expr = (List) $1; - expr.Add ((Expression) $3); - $$ = expr; + Arguments args = (Arguments) $1; + if (args [args.Count - 1] is NamedArgument && !($3 is NamedArgument)) + Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); + + args.Add ((Argument) $3); + $$ = args; } ; pattern_argument : pattern + { + $$ = new Argument ((Expression) $1); + } | IDENTIFIER COLON pattern + { + var lt = (LocatedToken) $1; + $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $3); + } ; shift_expression diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 244f8abd40e..a8573955cf3 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -1984,17 +1984,17 @@ public override void Emit (EmitContext ec) class RecursivePattern : PatternExpression { MethodGroupExpr operator_mg; - Arguments args; Expression[] args_comparison; + Arguments operator_args; - public RecursivePattern (ATypeNameExpression typeExpresion, List arguments, Location loc) + public RecursivePattern (ATypeNameExpression typeExpresion, Arguments arguments, Location loc) : base (loc) { - PatternList = arguments; + Arguments = arguments; TypeExpression = typeExpresion; } - public List PatternList { get; private set; } + public Arguments Arguments { get; private set; } public ATypeNameExpression TypeExpression { get; private set; } @@ -2017,22 +2017,10 @@ protected override Expression DoResolve (ResolveContext rc) return null; } - args = new Arguments (PatternList.Count + 1); - args.Add (new Argument (new EmptyExpression (type))); - - bool ok = true; - for (int i = 0; i < PatternList.Count; ++i) { - var expr = PatternList [i].Resolve (rc); - if (expr == null) { - ok = false; - continue; - } - - PatternList [i] = expr; - } - - if (!ok) - return null; + bool dynamic_args; + Arguments.Resolve (rc, out dynamic_args); + if (dynamic_args) + throw new NotImplementedException ("dynamic argument"); var op = FindBestOverload (rc, ops); if (op == null) { @@ -2042,18 +2030,32 @@ protected override Expression DoResolve (ResolveContext rc) } var op_types = op.Parameters.Types; + operator_args = new Arguments (op_types.Length); + operator_args.Add (new Argument (new EmptyExpression (type))); - for (int i = 0; i < PatternList.Count; ++i) { + for (int i = 0; i < Arguments.Count; ++i) { // TODO: Needs releasing optimization var lt = new LocalTemporary (op_types [i + 1]); - args.Add (new Argument (lt, Argument.AType.Out)); + operator_args.Add (new Argument (lt, Argument.AType.Out)); if (args_comparison == null) - args_comparison = new Expression[PatternList.Count]; + args_comparison = new Expression[Arguments.Count]; + + int arg_comp_index; + Expression expr; + + var arg = Arguments [i]; + var named = arg as NamedArgument; + if (named != null) { + arg_comp_index = op.Parameters.GetParameterIndexByName (named.Name) - 1; + expr = Arguments [arg_comp_index].Expr; + } else { + arg_comp_index = i; + expr = arg.Expr; + } - var expr = PatternList [i]; if (expr is WildcardPattern) { - args_comparison [i] = new EmptyExpression (expr.Type); + args_comparison [arg_comp_index] = new EmptyExpression (expr.Type); continue; } @@ -2067,12 +2069,12 @@ protected override Expression DoResolve (ResolveContext rc) continue; if (expr is RecursivePattern) { - args_comparison [i] = expr; + args_comparison [arg_comp_index] = expr; continue; } // TODO: Better error handling - args_comparison [i] = new Binary (Binary.Operator.Equality, lt, expr, expr.Location).Resolve (rc); + args_comparison [arg_comp_index] = new Binary (Binary.Operator.Equality, lt, expr, expr.Location).Resolve (rc); } operator_mg = MethodGroupExpr.CreatePredefined (op, type, loc); @@ -2083,10 +2085,11 @@ protected override Expression DoResolve (ResolveContext rc) List FindMatchingOverloads (IList members) { + int arg_count = Arguments.Count + 1; List best = null; foreach (MethodSpec method in members) { var pm = method.Parameters; - if (pm.Count != PatternList.Count + 1) + if (pm.Count != arg_count) continue; // TODO: Needs more thorough checks elsewhere to avoid doing this every time @@ -2112,13 +2115,28 @@ List FindMatchingOverloads (IList members) MethodSpec FindBestOverload (ResolveContext rc, List methods) { - for (int ii = 0; ii < PatternList.Count; ++ii) { - var expr = PatternList [ii]; + for (int ii = 0; ii < Arguments.Count; ++ii) { + var arg = Arguments [ii]; + var expr = arg.Expr; if (expr is WildcardPattern) continue; + var na = arg as NamedArgument; for (int i = 0; i < methods.Count; ++i) { - var m = methods [i].Parameters.Types [ii + 1]; + var pd = methods [i].Parameters; + + int index; + if (na != null) { + index = pd.GetParameterIndexByName (na.Name); + if (index < 1) { + methods.RemoveAt (i--); + continue; + } + } else { + index = ii + 1; + } + + var m = pd.Types [index]; if (!Convert.ImplicitConversionExists (rc, expr, m)) methods.RemoveAt (i--); } @@ -2137,16 +2155,18 @@ public override void Emit (EmitContext ec) public override void EmitBranchable (EmitContext ec, Label target, bool on_true) { - operator_mg.EmitCall (ec, args, false); + operator_mg.EmitCall (ec, operator_args, false); ec.Emit (OpCodes.Brfalse, ec.RecursivePatternLabel); - foreach (var ac in args_comparison) { - ac.EmitBranchable (ec, ec.RecursivePatternLabel, false); + if (args_comparison != null) { + foreach (var ac in args_comparison) { + ac.EmitBranchable (ec, ec.RecursivePatternLabel, false); + } } } void SetParentInstance (LocalTemporary instance) { - args [0] = new Argument (instance); + operator_args [0] = new Argument (instance); } } diff --git a/mcs/tests/test-pattern-05.cs b/mcs/tests/test-pattern-05.cs new file mode 100644 index 00000000000..7553acd6df0 --- /dev/null +++ b/mcs/tests/test-pattern-05.cs @@ -0,0 +1,39 @@ +// Compiler options: -langversion:experimental + +using System; + +class RecursiveNamedPattern +{ + public static int Main () + { + object o = new C (); + bool b = o is C (name2: "", name1: -2); + if (b) + return 1; + + b = o is C (name2: "n2", name1: -2); + if (!b) + return 2; + + b = o is C (); + if (b) + return 3; + + return 0; + } +} + +class C +{ + public static bool operator is (C c, out long name1, out string name2) + { + name1 = -2; + name2 = "n2"; + return true; + } + + public static bool operator is (C c) + { + return false; + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index f6bc79256a1..3f1b70389a4 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -68499,6 +68499,27 @@ + + + + 204 + + + 7 + + + + + 22 + + + 10 + + + 7 + + + From ddcfc420706c60db22c4160616005a281d2ff00d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Thu, 4 Sep 2014 18:55:43 +0200 Subject: [PATCH 026/543] Cleanup namespace names of class lib tests to follow convention A couple of the test suites didn't follow the MonoTests. naming convention for the namespace. --- .../Test/NvdlValidatingReaderTests.cs | 2 +- mcs/class/Mono.Data.Tds/Test/bug-4786.cs | 4 +- .../Test/Mono.Options/OptionContextTest.cs | 2 +- .../Test/Mono.Options/OptionSetTest.cs | 2 +- .../Test/Mono.Options/OptionTest.cs | 2 +- .../Mono.Options/Test/Mono.Options/Utils.cs | 2 +- .../Test/ChangeInterceptorAttributeTests.cs | 6 +- .../Test/DataServiceExceptionTests.cs | 6 +- .../Test/DataServiceTests.cs | 6 +- .../Test/ETagAttributeTests.cs | 6 +- .../Test/ExpandSegmentCollectionTests.cs | 5 +- .../Test/ExpandSegmentTests.cs | 6 +- .../Test/IgnorePropertiesAttributeTests.cs | 6 +- .../Test/MimeTypeAttributeTests.cs | 5 +- .../Test/QueryInterceptorAttributeTests.cs | 6 +- .../System.Data.Common/DbDataReaderMock.cs | 2 +- .../System.Data.Common/DbDataReaderTest.cs | 2 +- .../System.Data/BinarySerializationTest.cs | 3 + .../System.Data/ConstraintExceptionTest.cs | 2 +- .../System.Data/DBConcurrencyExceptionTest.cs | 2 +- .../Test/System.Data/DataSetTest2.cs | 110 +++++++++--------- .../System.Data/DataTableCollectionTest2.cs | 14 ++- .../Test/System.Data/DataTableTest2.cs | 2 +- .../Test/System.Data/DataTableTest3.cs | 2 +- .../Test/System.Data/DataTableTest4.cs | 22 ++-- .../Test/System.Data/DataTableTest5.cs | 2 +- .../Test/System.Data/DataViewTest2.cs | 27 ++--- .../DeletedRowInaccessibleExceptionTest.cs | 2 +- .../System.Data/DuplicateNameExceptionTest.cs | 2 +- .../Test/System.Data/EvaluateExceptionTest.cs | 2 +- .../System.Data/ForeignKeyConstraintTest2.cs | 2 +- .../InRowChangingEventExceptionTest.cs | 2 +- .../InvalidConstraintExceptionTest.cs | 2 +- .../MissingPrimaryKeyExceptionTest.cs | 4 +- .../System.Data/NoNullAllowedExceptionTest.cs | 2 +- .../Test/System.Data/ReadOnlyExceptionTest.cs | 2 +- .../System.Data/RowNotInTableExceptionTest.cs | 2 +- .../System.Data/SyntaxErrorExceptionTest.cs | 2 +- .../Test/System.Data/TrailingSpaceTest.cs | 4 +- .../Test/System.Data/UniqueConstraintTest2.cs | 2 +- .../System.Data/VersionNotFoundException.cs | 4 +- .../Test/System.Data/XmlDataLoaderTest.cs | 4 +- .../Test/System.Data/XmlDataReaderTest.cs | 4 +- .../CommunicationObjectSyncTest.cs | 2 +- .../System.ServiceProcess/ServiceBaseTest.cs | 7 +- .../AnnotationPathPointTest.cs | 2 +- .../AnovaResultTest.cs | 2 +- .../ArrowAnnotationTest.cs | 2 +- .../AxisScaleBreakStyleTest.cs | 2 +- .../ChartElementTest.cs | 2 +- .../DataPointTest.cs | 2 +- .../Test/System.Xml/XmlResolverTest.cs | 2 +- .../Test/System.Xml/XmlSecureResolverCas.cs | 4 +- .../Test/System.Xml/XmlSecureResolverTests.cs | 2 +- .../Test/System.Net/NetworkCredentialTest.cs | 2 +- .../Test/System.IO.Packaging/FakePackage.cs | 6 +- .../System.IO.Packaging/FakePackagePart.cs | 4 +- .../FakePackagePartTests.cs | 9 +- .../System.IO.Packaging/FakePackageTests.cs | 4 +- .../Test/System.IO.Packaging/FakeStream.cs | 3 +- .../System.IO.Packaging/PackUriHelperTests.cs | 2 +- .../PackagePartFileTests.cs | 4 +- .../PackagePartStreamTests.cs | 6 +- .../System.IO.Packaging/PackagePartTest.cs | 4 +- .../PackageRelationshipTests.cs | 4 +- .../Test/System.IO.Packaging/PackageTest.cs | 8 +- .../Test/System.IO.Packaging/TestBase.cs | 4 +- mcs/class/corlib/Test/Mono/DataConvertTest.cs | 8 +- .../Test/System.IO/DirectoryInfoTest.cs | 2 +- .../corlib/Test/System.IO/DirectoryTest.cs | 4 +- 70 files changed, 222 insertions(+), 179 deletions(-) diff --git a/mcs/class/Commons.Xml.Relaxng/Test/NvdlValidatingReaderTests.cs b/mcs/class/Commons.Xml.Relaxng/Test/NvdlValidatingReaderTests.cs index e7d600c5ea0..8f0ae73cf6d 100644 --- a/mcs/class/Commons.Xml.Relaxng/Test/NvdlValidatingReaderTests.cs +++ b/mcs/class/Commons.Xml.Relaxng/Test/NvdlValidatingReaderTests.cs @@ -13,7 +13,7 @@ using Commons.Xml.Nvdl; using NUnit.Framework; -namespace MonoTests.Commons.Xml.Nvdl +namespace MonoTests.Commons.Xml.Relaxng { [TestFixture] public class NvdlValidatingReaderTests diff --git a/mcs/class/Mono.Data.Tds/Test/bug-4786.cs b/mcs/class/Mono.Data.Tds/Test/bug-4786.cs index e8436a7deca..91f8a06fc1a 100644 --- a/mcs/class/Mono.Data.Tds/Test/bug-4786.cs +++ b/mcs/class/Mono.Data.Tds/Test/bug-4786.cs @@ -27,11 +27,11 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -namespace bug4786test +namespace MonoTests.Mono.Data.Tds { using NUnit.Framework; - using Mono.Data.Tds.Protocol; + using global::Mono.Data.Tds.Protocol; using System; using System.Net; using System.Net.Sockets; diff --git a/mcs/class/Mono.Options/Test/Mono.Options/OptionContextTest.cs b/mcs/class/Mono.Options/Test/Mono.Options/OptionContextTest.cs index 8eb61b2c93b..ec3fb02270f 100644 --- a/mcs/class/Mono.Options/Test/Mono.Options/OptionContextTest.cs +++ b/mcs/class/Mono.Options/Test/Mono.Options/OptionContextTest.cs @@ -39,7 +39,7 @@ #if NDESK_OPTIONS namespace Tests.NDesk.Options #else -namespace Tests.Mono.Options +namespace MonoTests.Mono.Options #endif { [TestFixture] diff --git a/mcs/class/Mono.Options/Test/Mono.Options/OptionSetTest.cs b/mcs/class/Mono.Options/Test/Mono.Options/OptionSetTest.cs index 086c6d9c8c2..688297a0f68 100644 --- a/mcs/class/Mono.Options/Test/Mono.Options/OptionSetTest.cs +++ b/mcs/class/Mono.Options/Test/Mono.Options/OptionSetTest.cs @@ -46,7 +46,7 @@ #if NDESK_OPTIONS namespace Tests.NDesk.Options #else -namespace Tests.Mono.Options +namespace MonoTests.Mono.Options #endif { class FooConverter : TypeConverter { diff --git a/mcs/class/Mono.Options/Test/Mono.Options/OptionTest.cs b/mcs/class/Mono.Options/Test/Mono.Options/OptionTest.cs index 5242609162a..fad1b484784 100644 --- a/mcs/class/Mono.Options/Test/Mono.Options/OptionTest.cs +++ b/mcs/class/Mono.Options/Test/Mono.Options/OptionTest.cs @@ -39,7 +39,7 @@ #if NDESK_OPTIONS namespace Tests.NDesk.Options #else -namespace Tests.Mono.Options +namespace MonoTests.Mono.Options #endif { class DefaultOption : Option { diff --git a/mcs/class/Mono.Options/Test/Mono.Options/Utils.cs b/mcs/class/Mono.Options/Test/Mono.Options/Utils.cs index e5439aae4c3..074478e3e21 100644 --- a/mcs/class/Mono.Options/Test/Mono.Options/Utils.cs +++ b/mcs/class/Mono.Options/Test/Mono.Options/Utils.cs @@ -31,7 +31,7 @@ #if NDESK_OPTIONS namespace Tests.NDesk.Options #else -namespace Tests.Mono.Options +namespace MonoTests.Mono.Options #endif { static class Utils { diff --git a/mcs/class/System.Data.Services/Test/ChangeInterceptorAttributeTests.cs b/mcs/class/System.Data.Services/Test/ChangeInterceptorAttributeTests.cs index d8d0e157a8e..3cc769d05e3 100644 --- a/mcs/class/System.Data.Services/Test/ChangeInterceptorAttributeTests.cs +++ b/mcs/class/System.Data.Services/Test/ChangeInterceptorAttributeTests.cs @@ -26,9 +26,11 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; +using System.Data.Services; using NUnit.Framework; -namespace System.Data.Services.Tests { +namespace MonoTests.System.Data.Services { [TestFixture] public class ChangeInterceptorAttributeTests { [Test] @@ -45,4 +47,4 @@ public void Ctor() Assert.AreEqual ("setName", ci.EntitySetName); } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data.Services/Test/DataServiceExceptionTests.cs b/mcs/class/System.Data.Services/Test/DataServiceExceptionTests.cs index 6058fc3e386..5f9758a44c5 100644 --- a/mcs/class/System.Data.Services/Test/DataServiceExceptionTests.cs +++ b/mcs/class/System.Data.Services/Test/DataServiceExceptionTests.cs @@ -26,9 +26,11 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; +using System.Data.Services; using NUnit.Framework; -namespace System.Data.Services.Tests { +namespace MonoTests.System.Data.Services { [TestFixture] public class DataServiceExceptionTests { [Test] @@ -68,4 +70,4 @@ public void CtorStatusAndErrorMessageLanguageException() Assert.AreEqual (inner, ex.InnerException); } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data.Services/Test/DataServiceTests.cs b/mcs/class/System.Data.Services/Test/DataServiceTests.cs index 58b67859593..2bcc6a9dd75 100644 --- a/mcs/class/System.Data.Services/Test/DataServiceTests.cs +++ b/mcs/class/System.Data.Services/Test/DataServiceTests.cs @@ -26,9 +26,11 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; +using System.Data.Services; using NUnit.Framework; -namespace System.Data.Services.Tests { +namespace MonoTests.System.Data.Services { [TestFixture] public class DataServiceTests { [Test] @@ -79,4 +81,4 @@ public void TestOnStartProcessingRequest (ProcessRequestArgs args) this.OnStartProcessingRequest (args); } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data.Services/Test/ETagAttributeTests.cs b/mcs/class/System.Data.Services/Test/ETagAttributeTests.cs index 8b40de6c5bd..706e02c6992 100644 --- a/mcs/class/System.Data.Services/Test/ETagAttributeTests.cs +++ b/mcs/class/System.Data.Services/Test/ETagAttributeTests.cs @@ -26,10 +26,12 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; +using System.Data.Services; using System.Linq; using NUnit.Framework; -namespace System.Data.Services.Tests { +namespace MonoTests.System.Data.Services { [TestFixture] public class ETagAttributeTests { [Test] @@ -63,4 +65,4 @@ public void CtorPropertyNames() Assert.AreEqual ("bar", e.PropertyNames[1]); } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data.Services/Test/ExpandSegmentCollectionTests.cs b/mcs/class/System.Data.Services/Test/ExpandSegmentCollectionTests.cs index e0eb629d5be..cd5e9a1d31f 100644 --- a/mcs/class/System.Data.Services/Test/ExpandSegmentCollectionTests.cs +++ b/mcs/class/System.Data.Services/Test/ExpandSegmentCollectionTests.cs @@ -26,10 +26,11 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System.Data.Services; using System.Linq.Expressions; using NUnit.Framework; -namespace System.Data.Services.Tests { +namespace MonoTests.System.Data.Services { [TestFixture] public class ExpandSegmentCollectionTests { [Test] @@ -101,4 +102,4 @@ public void HasFilterRemoveFilteredMultiple() Assert.IsFalse (esc.HasFilter); } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data.Services/Test/ExpandSegmentTests.cs b/mcs/class/System.Data.Services/Test/ExpandSegmentTests.cs index f64faa8fad2..ce6712c94e0 100644 --- a/mcs/class/System.Data.Services/Test/ExpandSegmentTests.cs +++ b/mcs/class/System.Data.Services/Test/ExpandSegmentTests.cs @@ -26,10 +26,12 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; +using System.Data.Services; using System.Linq.Expressions; using NUnit.Framework; -namespace System.Data.Services.Tests { +namespace MonoTests.System.Data.Services { [TestFixture] public class ExpandSegmentTests { [Test] @@ -84,4 +86,4 @@ public void PathDoesntHaveFilter() { new ExpandSegment ("first", null), new ExpandSegment ("second", null), new ExpandSegment ("third", null) })); } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data.Services/Test/IgnorePropertiesAttributeTests.cs b/mcs/class/System.Data.Services/Test/IgnorePropertiesAttributeTests.cs index 04c17e3d3ce..090b3bf64bd 100644 --- a/mcs/class/System.Data.Services/Test/IgnorePropertiesAttributeTests.cs +++ b/mcs/class/System.Data.Services/Test/IgnorePropertiesAttributeTests.cs @@ -26,10 +26,12 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; +using System.Data.Services; using System.Linq; using NUnit.Framework; -namespace System.Data.Services.Tests { +namespace MonoTests.System.Data.Services { [TestFixture] public class IgnorePropertiesAttributeTests { [Test] @@ -63,4 +65,4 @@ public void CtorPropertyNames() Assert.AreEqual ("bar", e.PropertyNames[1]); } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data.Services/Test/MimeTypeAttributeTests.cs b/mcs/class/System.Data.Services/Test/MimeTypeAttributeTests.cs index 6b5533ffa50..824cab9fcb1 100644 --- a/mcs/class/System.Data.Services/Test/MimeTypeAttributeTests.cs +++ b/mcs/class/System.Data.Services/Test/MimeTypeAttributeTests.cs @@ -26,9 +26,10 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System.Data.Services; using NUnit.Framework; -namespace System.Data.Services.Tests { +namespace MonoTests.System.Data.Services { [TestFixture] public class MimeTypeAttributeTests { [Test] @@ -39,4 +40,4 @@ public void Ctor() Assert.AreEqual ("type", mt.MimeType); } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data.Services/Test/QueryInterceptorAttributeTests.cs b/mcs/class/System.Data.Services/Test/QueryInterceptorAttributeTests.cs index b483fbe1cdd..e4b0147cccd 100644 --- a/mcs/class/System.Data.Services/Test/QueryInterceptorAttributeTests.cs +++ b/mcs/class/System.Data.Services/Test/QueryInterceptorAttributeTests.cs @@ -26,9 +26,11 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; +using System.Data.Services; using NUnit.Framework; -namespace System.Data.Services.Tests { +namespace MonoTests.System.Data.Services { [TestFixture] public class QueryInterceptorAttributeTests { [Test] @@ -45,4 +47,4 @@ public void CtorNull() new QueryInterceptorAttribute (null); } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderMock.cs b/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderMock.cs index 5d561b44dd5..2957cd73deb 100644 --- a/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderMock.cs +++ b/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderMock.cs @@ -31,7 +31,7 @@ using System.Data.Common; using System.IO; -namespace Test.System.Data.Common +namespace MonoTests.System.Data.Common { internal class DbDataReaderMock : DbDataReader { diff --git a/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderTest.cs b/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderTest.cs index 0a7235f1b90..20d5c1ab0bf 100644 --- a/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderTest.cs +++ b/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderTest.cs @@ -32,7 +32,7 @@ using System.Data.Common; using System.IO; -namespace Test.System.Data.Common +namespace MonoTests.System.Data.Common { [TestFixture] public class DbDataReaderTest diff --git a/mcs/class/System.Data/Test/System.Data/BinarySerializationTest.cs b/mcs/class/System.Data/Test/System.Data/BinarySerializationTest.cs index 5eae92a3963..efbe64a1a4a 100644 --- a/mcs/class/System.Data/Test/System.Data/BinarySerializationTest.cs +++ b/mcs/class/System.Data/Test/System.Data/BinarySerializationTest.cs @@ -12,6 +12,8 @@ using NUnit.Framework; +namespace MonoTests.System.Data +{ [TestFixture] public class BinarySerializationTest { @@ -751,3 +753,4 @@ ds1.Tables [3].Constraints [i].GetType (), } #endif +} diff --git a/mcs/class/System.Data/Test/System.Data/ConstraintExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/ConstraintExceptionTest.cs index c98a03c5aa4..fe575137ea4 100644 --- a/mcs/class/System.Data/Test/System.Data/ConstraintExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/ConstraintExceptionTest.cs @@ -33,7 +33,7 @@ using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class ConstraintExceptionTest { diff --git a/mcs/class/System.Data/Test/System.Data/DBConcurrencyExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/DBConcurrencyExceptionTest.cs index bfae78d6e6e..35e876ff51f 100644 --- a/mcs/class/System.Data/Test/System.Data/DBConcurrencyExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/DBConcurrencyExceptionTest.cs @@ -31,7 +31,7 @@ using NUnit.Framework; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class DBConcurrencyExceptionTest diff --git a/mcs/class/System.Data/Test/System.Data/DataSetTest2.cs b/mcs/class/System.Data/Test/System.Data/DataSetTest2.cs index 27df0f58984..6e338558389 100644 --- a/mcs/class/System.Data/Test/System.Data/DataSetTest2.cs +++ b/mcs/class/System.Data/Test/System.Data/DataSetTest2.cs @@ -39,7 +39,7 @@ using System.Runtime.Serialization.Formatters.Binary; using System.Globalization; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class DataSetTest2 @@ -448,7 +448,7 @@ [Test] public void GetXml() dt.Rows.Add(new object[] {2,"Value3","Value4"}); dt.Rows.Add(new object[] {3,"Value5","Value5"}); - System.Text.StringBuilder resultXML = new System.Text.StringBuilder(); + StringBuilder resultXML = new StringBuilder(); resultXML.Append("<" + ds.DataSetName + "xmlns=\"namespace\">"); @@ -975,13 +975,13 @@ [Test] public void InferXmlSchema_elementText2() [Test] public void Locale() { DataSet ds = new DataSet("MyDataSet"); - System.Globalization.CultureInfo culInfo = System.Globalization.CultureInfo.CurrentCulture ; + CultureInfo culInfo = CultureInfo.CurrentCulture ; // Checking Locale default from system Assert.AreEqual(culInfo, ds.Locale , "DS156"); // Checking Locale get/set - culInfo = new System.Globalization.CultureInfo("fr"); // = french + culInfo = new CultureInfo("fr"); // = french ds.Locale = culInfo ; Assert.AreEqual(culInfo , ds.Locale , "DS157"); } @@ -1998,11 +1998,11 @@ [Test] public void ReadXmlSchema_ByStream() ds1.Tables.Add(DataProvider.CreateParentDataTable()); ds1.Tables.Add(DataProvider.CreateChildDataTable()); - System.IO.MemoryStream ms = new System.IO.MemoryStream(); + MemoryStream ms = new MemoryStream(); //write xml schema only ds1.WriteXmlSchema(ms); - System.IO.MemoryStream ms1 = new System.IO.MemoryStream(ms.GetBuffer()); + MemoryStream ms1 = new MemoryStream(ms.GetBuffer()); //copy schema DataSet ds2 = new DataSet(); ds2.ReadXmlSchema(ms1); @@ -2073,7 +2073,7 @@ [Test] public void ReadXmlSchema_ByFileName() Assert.AreEqual(0, ds2.Tables[1].Rows.Count , "DS282"); //try to delete the file - System.IO.File.Delete(sTempFileName); + File.Delete(sTempFileName); } [Test] public void ReadXmlSchema_ByTextReader() @@ -2082,11 +2082,11 @@ [Test] public void ReadXmlSchema_ByTextReader() ds1.Tables.Add(DataProvider.CreateParentDataTable()); ds1.Tables.Add(DataProvider.CreateChildDataTable()); - System.IO.StringWriter sw = new System.IO.StringWriter(); + StringWriter sw = new StringWriter(); //write xml file, schema only ds1.WriteXmlSchema(sw); - System.IO.StringReader sr = new System.IO.StringReader(sw.GetStringBuilder().ToString()); + StringReader sr = new StringReader(sw.GetStringBuilder().ToString()); //copy both data and schema DataSet ds2 = new DataSet(); ds2.ReadXmlSchema(sr); @@ -2122,14 +2122,14 @@ [Test] public void ReadXmlSchema_ByXmlReader() ds1.Tables.Add(DataProvider.CreateParentDataTable()); ds1.Tables.Add(DataProvider.CreateChildDataTable()); - System.IO.StringWriter sw = new System.IO.StringWriter(); - System.Xml.XmlTextWriter xmlTW = new System.Xml.XmlTextWriter(sw); + StringWriter sw = new StringWriter(); + XmlTextWriter xmlTW = new XmlTextWriter(sw); //write xml file, schema only ds1.WriteXmlSchema(xmlTW); xmlTW.Flush(); - System.IO.StringReader sr = new System.IO.StringReader(sw.ToString()); - System.Xml.XmlTextReader xmlTR = new System.Xml.XmlTextReader(sr); + StringReader sr = new StringReader(sw.ToString()); + XmlTextReader xmlTR = new XmlTextReader(sr); //copy both data and schema DataSet ds2 = new DataSet(); @@ -2196,7 +2196,7 @@ public void ReadXml_Strg() Assert.AreEqual(ds2.Tables[1].Rows.Count, ds1.Tables[1].Rows.Count , "DS299"); //try to delete the file - System.IO.File.Delete(sTempFileName); + File.Delete(sTempFileName); } [Test] @@ -2212,7 +2212,7 @@ public void ReadXml_Strm() ds1.Tables[1].Rows.Add(new object[] {7,2," "," ",new DateTime(2000,1,1,0,0,0,0),35}); ds1.Tables[1].Rows.Add(new object[] {7,3,"","",new DateTime(2000,1,1,0,0,0,0),35}); - System.IO.MemoryStream ms = new System.IO.MemoryStream(); + MemoryStream ms = new MemoryStream(); //write xml file, data only ds1.WriteXml(ms); @@ -2241,7 +2241,7 @@ [Test] public void ReadXml_Strm2() { string input = string.Empty; - System.IO.StringReader sr; + StringReader sr; DataSet ds = new DataSet(); input += ""; @@ -2261,7 +2261,7 @@ [Test] public void ReadXml_Strm2() input += " "; input += ""; - sr = new System.IO.StringReader(input); + sr = new StringReader(input); ds.ReadXml(sr); @@ -2311,7 +2311,7 @@ [Test] public void ReadXml_Strm3() { DataSet ds = new DataSet("TestDataSet"); string input = string.Empty; - System.IO.StringReader sr; + StringReader sr; input += ""; input += "10.0"; @@ -2320,7 +2320,7 @@ [Test] public void ReadXml_Strm3() input += "22.2302/12/2001"; input += "1.9704/20/20033.0"; input += "TODAY"; - sr = new System.IO.StringReader(input); + sr = new StringReader(input); ds.EnforceConstraints = false; ds.ReadXml(sr); @@ -2339,7 +2339,7 @@ [Test] public void ReadXml_Strm4() { m_ds = new DataSet("Stocks"); string input = string.Empty; - System.IO.StringReader sr; + StringReader sr; input += ""; input += ""; @@ -2408,7 +2408,7 @@ [Test] public void ReadXml_Strm4() input += " "; input += ""; - sr = new System.IO.StringReader(input); + sr = new StringReader(input); m_ds.EnforceConstraints = true; m_ds.ReadXml(sr); this.privateTestCase("TestCase 1", "Company", "name='Microsoft Corp.'", "Stock", "name='MSFT'", "DS320"); @@ -2444,14 +2444,14 @@ public void ReadXml_Strm5() #region "TestCase 1 - Empty string" // Empty string DataSet ds = new DataSet(); - System.IO.StringReader sr = new System.IO.StringReader (string.Empty); - System.Xml.XmlTextReader xReader = new System.Xml.XmlTextReader(sr); + StringReader sr = new StringReader (string.Empty); + XmlTextReader xReader = new XmlTextReader(sr); try { ds.ReadXml (xReader); Assert.Fail("DS335: ReadXml Failed to throw XmlException"); } - catch (System.Xml.XmlException) {} + catch (XmlException) {} catch (AssertionException exc) {throw exc;} catch (Exception exc) { @@ -2635,8 +2635,8 @@ public void ReadXml_Strm5() private void PrivateTestCase(string a_name, string a_expected, string a_xmlData) { DataSet ds = new DataSet(); - System.IO.StringReader sr = new System.IO.StringReader(a_xmlData) ; - System.Xml.XmlTextReader xReader = new System.Xml.XmlTextReader(sr) ; + StringReader sr = new StringReader(a_xmlData) ; + XmlTextReader xReader = new XmlTextReader(sr) ; ds.ReadXml (xReader); Assert.AreEqual(a_expected, this.dataSetDescription(ds), "DS337"); } @@ -2681,8 +2681,8 @@ [Test] public void ReadXml_Strm6() xmlData += "3"; xmlData += ""; xmlData += ""; - System.IO.StringReader sr = new System.IO.StringReader(xmlData) ; - System.Xml.XmlTextReader xReader = new System.Xml.XmlTextReader(sr) ; + StringReader sr = new StringReader(xmlData) ; + XmlTextReader xReader = new XmlTextReader(sr) ; ds.ReadXml (xReader); Assert.AreEqual(3, ds.Tables["c"].Rows.Count, "DS338"); } @@ -2738,7 +2738,7 @@ public void ReadXml_ByTextReader() ds1.Tables[1].Rows.Add(new object[] {7,2," "," ",new DateTime(2000,1,1,0,0,0,0),35}); ds1.Tables[1].Rows.Add(new object[] {7,3,"","",new DateTime(2000,1,1,0,0,0,0),35}); - System.IO.StringWriter sw = new System.IO.StringWriter(); + StringWriter sw = new StringWriter(); //write xml file, data only ds1.WriteXml(sw); @@ -2747,7 +2747,7 @@ public void ReadXml_ByTextReader() //clear the data ds2.Clear(); - System.IO.StringReader sr = new System.IO.StringReader(sw.GetStringBuilder().ToString()); + StringReader sr = new StringReader(sw.GetStringBuilder().ToString()); ds2.ReadXml(sr); //check xml data @@ -2777,8 +2777,8 @@ public void ReadXml_ByXmlReader() ds1.Tables[1].Rows.Add(new object[] {7,2," "," ",new DateTime(2000,1,1,0,0,0,0),35}); ds1.Tables[1].Rows.Add(new object[] {7,3,"","",new DateTime(2000,1,1,0,0,0,0),35}); - System.IO.StringWriter sw = new System.IO.StringWriter(); - System.Xml.XmlTextWriter xmlTW = new System.Xml.XmlTextWriter(sw); + StringWriter sw = new StringWriter(); + XmlTextWriter xmlTW = new XmlTextWriter(sw); //write xml file, data only ds1.WriteXml(xmlTW); @@ -2788,8 +2788,8 @@ public void ReadXml_ByXmlReader() DataSet ds2 = ds1.Copy(); //clear the data ds2.Clear(); - System.IO.StringReader sr = new System.IO.StringReader(sw.ToString()); - System.Xml.XmlTextReader xmlTR = new System.Xml.XmlTextReader(sr); + StringReader sr = new StringReader(sw.ToString()); + XmlTextReader xmlTR = new XmlTextReader(sr); ds2.ReadXml(xmlTR); //check xml data @@ -2847,8 +2847,8 @@ [Test] public void WriteXmlSchema_RelationAnnotation () [Test] public void WriteXmlSchema_Relations_ForeignKeys () { - System.IO.MemoryStream ms = null; - System.IO.MemoryStream ms1 = null; + MemoryStream ms = null; + MemoryStream ms1 = null; DataSet ds1 = new DataSet(); @@ -2884,10 +2884,10 @@ [Test] public void WriteXmlSchema_Relations_ForeignKeys () new DataColumn[] {col1_5, col1_6}, new DataColumn[] {col2_5, col2_6}); - ms = new System.IO.MemoryStream(); + ms = new MemoryStream(); ds1.WriteXmlSchema (ms); - ms1 = new System.IO.MemoryStream (ms.GetBuffer()); + ms1 = new MemoryStream (ms.GetBuffer()); DataSet ds2 = new DataSet(); ds2.ReadXmlSchema(ms1); @@ -3096,18 +3096,18 @@ [Test] public void Tables() [Test] public void WriteXml_ByTextWriterXmlWriteMode() { - System.IO.StringReader sr = null; - System.IO.StringWriter sw = null; + StringReader sr = null; + StringWriter sw = null; try // For real { // ReadXml - DataSetOut DataSet oDataset = new DataSet("DataSetOut"); - sw = new System.IO.StringWriter(); - oDataset.WriteXml(sw,System.Data.XmlWriteMode.WriteSchema); + sw = new StringWriter(); + oDataset.WriteXml(sw, XmlWriteMode.WriteSchema); - sr = new System.IO.StringReader(sw.GetStringBuilder().ToString()); + sr = new StringReader(sw.GetStringBuilder().ToString()); oDataset = new DataSet("DataSetOut"); oDataset.ReadXml(sr); @@ -3252,13 +3252,13 @@ public void WriteXml_Stream() { DataSet ds = new DataSet(); string input = "2"; - System.IO.StringReader sr = new System.IO.StringReader(input) ; - System.Xml.XmlTextReader xReader = new System.Xml.XmlTextReader(sr) ; + StringReader sr = new StringReader(input) ; + XmlTextReader xReader = new XmlTextReader(sr) ; ds.ReadXml (xReader); - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - System.IO.StringWriter sw = new System.IO.StringWriter(sb); - System.Xml.XmlTextWriter xWriter = new System.Xml.XmlTextWriter(sw); + StringBuilder sb = new StringBuilder(); + StringWriter sw = new StringWriter(sb); + XmlTextWriter xWriter = new XmlTextWriter(sw); ds.WriteXml(xWriter); string output = sb.ToString(); Assert.AreEqual(input,output, "DS76"); @@ -3267,20 +3267,20 @@ public void WriteXml_Stream() DataSet ds = new DataSet(); string input = "2"; string expectedOutput = "2"; - System.IO.StringReader sr = new System.IO.StringReader(input) ; - System.Xml.XmlTextReader xReader = new System.Xml.XmlTextReader(sr) ; + StringReader sr = new StringReader(input) ; + XmlTextReader xReader = new XmlTextReader(sr) ; ds.ReadXml (xReader); - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - System.IO.StringWriter sw = new System.IO.StringWriter(sb); - System.Xml.XmlTextWriter xWriter = new System.Xml.XmlTextWriter(sw); + StringBuilder sb = new StringBuilder(); + StringWriter sw = new StringWriter(sb); + XmlTextWriter xWriter = new XmlTextWriter(sw); ds.WriteXml(xWriter); string output = sb.ToString(); Assert.AreEqual(expectedOutput,output, "DS77"); } { DataSet ds = new DataSet("DSName"); - System.IO.StringWriter sr = new System.IO.StringWriter(); + StringWriter sr = new StringWriter(); ds.WriteXml(sr); Assert.AreEqual("",sr.ToString(), "DS78"); } @@ -3315,7 +3315,7 @@ public void WriteXml_Stream() ds.Tables.Remove("ChildTable"); //Get the xml representation of the dataset. - System.IO.StringWriter sr = new System.IO.StringWriter(); + StringWriter sr = new StringWriter(); ds.WriteXml(sr); string xml = sr.ToString(); diff --git a/mcs/class/System.Data/Test/System.Data/DataTableCollectionTest2.cs b/mcs/class/System.Data/Test/System.Data/DataTableCollectionTest2.cs index 9229265648c..053825e3501 100644 --- a/mcs/class/System.Data/Test/System.Data/DataTableCollectionTest2.cs +++ b/mcs/class/System.Data/Test/System.Data/DataTableCollectionTest2.cs @@ -28,10 +28,12 @@ using NUnit.Framework; using System; +using System.Collections; +using System.ComponentModel; using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class DataTableCollectionTest2 { @@ -143,7 +145,7 @@ public void CollectionChanged() { counter = 0; DataSet ds = new DataSet(); - ds.Tables.CollectionChanged+=new System.ComponentModel.CollectionChangeEventHandler(Tables_CollectionChanged); + ds.Tables.CollectionChanged+=new CollectionChangeEventHandler(Tables_CollectionChanged); ds.Tables.Add(); ds.Tables.Add(); Assert.AreEqual(2, counter, "DTC15"); @@ -153,7 +155,7 @@ public void CollectionChanged() Assert.AreEqual(4, counter, "DTC16"); } - private void Tables_CollectionChanged(object sender, System.ComponentModel.CollectionChangeEventArgs e) + private void Tables_CollectionChanged(object sender, CollectionChangeEventArgs e) { counter++; } @@ -163,7 +165,7 @@ public void CollectionChanging() { counter = 0; DataSet ds = new DataSet(); - ds.Tables.CollectionChanging+=new System.ComponentModel.CollectionChangeEventHandler(Tables_CollectionChanging); + ds.Tables.CollectionChanging+=new CollectionChangeEventHandler(Tables_CollectionChanging); ds.Tables.Add(); ds.Tables.Add(); Assert.AreEqual(2, counter, "DTC17"); @@ -173,7 +175,7 @@ public void CollectionChanging() Assert.AreEqual(4, counter, "DTC18"); } - private void Tables_CollectionChanging(object sender, System.ComponentModel.CollectionChangeEventArgs e) + private void Tables_CollectionChanging(object sender, CollectionChangeEventArgs e) { counter++; } @@ -233,7 +235,7 @@ public void GetEnumerator() ds.Tables.Add(); int count=0; - System.Collections.IEnumerator myEnumerator = ds.Tables.GetEnumerator(); + IEnumerator myEnumerator = ds.Tables.GetEnumerator(); while (myEnumerator.MoveNext()) { diff --git a/mcs/class/System.Data/Test/System.Data/DataTableTest2.cs b/mcs/class/System.Data/Test/System.Data/DataTableTest2.cs index 331875ac888..bed6e55e50c 100644 --- a/mcs/class/System.Data/Test/System.Data/DataTableTest2.cs +++ b/mcs/class/System.Data/Test/System.Data/DataTableTest2.cs @@ -36,7 +36,7 @@ using NUnit.Framework; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class DataTableTest2 diff --git a/mcs/class/System.Data/Test/System.Data/DataTableTest3.cs b/mcs/class/System.Data/Test/System.Data/DataTableTest3.cs index 6fc2d64b20b..c706778c67b 100644 --- a/mcs/class/System.Data/Test/System.Data/DataTableTest3.cs +++ b/mcs/class/System.Data/Test/System.Data/DataTableTest3.cs @@ -31,7 +31,7 @@ using NUnit.Framework; -namespace Monotests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class DataTableTest3 diff --git a/mcs/class/System.Data/Test/System.Data/DataTableTest4.cs b/mcs/class/System.Data/Test/System.Data/DataTableTest4.cs index 2cdd5af913b..c7cb3a35e85 100644 --- a/mcs/class/System.Data/Test/System.Data/DataTableTest4.cs +++ b/mcs/class/System.Data/Test/System.Data/DataTableTest4.cs @@ -31,7 +31,7 @@ using System.Xml; using NUnit.Framework; -namespace Monotests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class DataTableTest4 @@ -1600,7 +1600,7 @@ public void XmlTest21 () DataSet ds = new DataSet (); DataTable table = new DataTable ("ParentTable"); XmlReadMode mode = XmlReadMode.Auto; - table.Columns.Add (new DataColumn ("id", System.Type.GetType ("System.Int32"))); + table.Columns.Add (new DataColumn ("id", Type.GetType ("System.Int32"))); ds.Tables.Add (table); using (FileStream stream = new FileStream (tempFile, FileMode.Open)) { @@ -1638,7 +1638,7 @@ public void XmlTest22 () using (FileStream stream = new FileStream (tempFile, FileMode.Open)) { DataSet ds = new DataSet (); DataTable table = new DataTable ("Table1"); - table.Columns.Add (new DataColumn ("id", System.Type.GetType ("System.Int32"))); + table.Columns.Add (new DataColumn ("id", Type.GetType ("System.Int32"))); ds.Tables.Add (table); try { @@ -1852,7 +1852,7 @@ public void XmlTest28 () DataTable table = new DataTable ("DummyTable"); //define the table schame partially with a column name which does not match with any //table columns in the diffgram - table.Columns.Add (new DataColumn ("WrongColumnName", System.Type.GetType ("System.String"))); + table.Columns.Add (new DataColumn ("WrongColumnName", Type.GetType ("System.String"))); XmlReadMode mode = XmlReadMode.Auto; @@ -2013,8 +2013,8 @@ public void XmlTest31 () Assert.AreEqual ("NewDataSet", table.DataSet.DataSetName, "#2"); Assert.AreEqual (2, table.Columns.Count, "#3"); Assert.AreEqual (2, table.Rows.Count, "#4"); - Assert.AreEqual (typeof (System.Int32), table.Columns [0].DataType, "#5"); - Assert.AreEqual (typeof (System.String), table.Columns [1].DataType, "#6"); + Assert.AreEqual (typeof (Int32), table.Columns [0].DataType, "#5"); + Assert.AreEqual (typeof (String), table.Columns [1].DataType, "#6"); Assert.AreEqual (1, table.Constraints.Count, "#7"); Assert.AreEqual (typeof (UniqueConstraint), table.Constraints [0].GetType (), "#8"); Assert.AreEqual (1, table.ChildRelations.Count, "#9"); @@ -2027,9 +2027,9 @@ public void XmlTest31 () Assert.AreEqual ("NewDataSet", table1.DataSet.DataSetName, "#14"); Assert.AreEqual (3, table1.Columns.Count, "#15"); Assert.AreEqual (4, table1.Rows.Count, "#16"); - Assert.AreEqual (typeof (System.Int32), table1.Columns [0].DataType, "#17"); - Assert.AreEqual (typeof (System.String), table1.Columns [1].DataType, "#18"); - Assert.AreEqual (typeof (System.Int32), table1.Columns [2].DataType, "#19"); + Assert.AreEqual (typeof (Int32), table1.Columns [0].DataType, "#17"); + Assert.AreEqual (typeof (String), table1.Columns [1].DataType, "#18"); + Assert.AreEqual (typeof (Int32), table1.Columns [2].DataType, "#19"); Assert.AreEqual (2, table1.Constraints.Count, "#20"); Assert.AreEqual (typeof (UniqueConstraint), table1.Constraints [0].GetType (), "#21"); Assert.AreEqual (typeof (ForeignKeyConstraint), table1.Constraints [1].GetType (), "#22"); @@ -2045,8 +2045,8 @@ public void XmlTest31 () Assert.AreEqual ("NewDataSet", table1.DataSet.DataSetName, "#29"); Assert.AreEqual (2, table1.Columns.Count, "#30"); Assert.AreEqual (8, table1.Rows.Count, "#31"); - Assert.AreEqual (typeof (System.Int32), table1.Columns [0].DataType, "#32"); - Assert.AreEqual (typeof (System.String), table1.Columns [1].DataType, "#33"); + Assert.AreEqual (typeof (Int32), table1.Columns [0].DataType, "#32"); + Assert.AreEqual (typeof (String), table1.Columns [1].DataType, "#33"); Assert.AreEqual (1, table1.Constraints.Count, "#34"); Assert.AreEqual (typeof (ForeignKeyConstraint), table1.Constraints [0].GetType (), "#35"); Assert.AreEqual (1, table1.ParentRelations.Count, "#36"); diff --git a/mcs/class/System.Data/Test/System.Data/DataTableTest5.cs b/mcs/class/System.Data/Test/System.Data/DataTableTest5.cs index 3bcbf75889a..0cacc8ea9ef 100644 --- a/mcs/class/System.Data/Test/System.Data/DataTableTest5.cs +++ b/mcs/class/System.Data/Test/System.Data/DataTableTest5.cs @@ -34,7 +34,7 @@ using NUnit.Framework; -namespace Monotests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class DataTableTest5 diff --git a/mcs/class/System.Data/Test/System.Data/DataViewTest2.cs b/mcs/class/System.Data/Test/System.Data/DataViewTest2.cs index f6c6b3f9a8c..58ca232fb53 100644 --- a/mcs/class/System.Data/Test/System.Data/DataViewTest2.cs +++ b/mcs/class/System.Data/Test/System.Data/DataViewTest2.cs @@ -28,12 +28,13 @@ using NUnit.Framework; using System; -using System.IO; +using System.Collections; using System.ComponentModel; +using System.IO; using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class DataViewTest2 { @@ -41,7 +42,7 @@ [TestFixture] public class DataViewTest2 class EventProperties //hold the event properties to be checked { - public System.ComponentModel.ListChangedType lstType ; + public ListChangedType lstType ; public int NewIndex; public int OldIndex; } @@ -508,7 +509,7 @@ [Test] public void GetEnumerator() //create the dataview for the table DataView dv = new DataView(dt); - System.Collections.IEnumerator ienm = null; + IEnumerator ienm = null; // GetEnumerator != null ienm = dv.GetEnumerator(); @@ -549,7 +550,7 @@ [Test] public void ListChanged() DataView dv = new DataView(dt); //add event handler - dv.ListChanged +=new System.ComponentModel.ListChangedEventHandler(dv_ListChanged); + dv.ListChanged +=new ListChangedEventHandler(dv_ListChanged); // ----- Change Value --------- evProp = null; @@ -557,7 +558,7 @@ [Test] public void ListChanged() dv[1]["String1"] = "something"; Assert.AreEqual(true , evProp!=null , "DV58"); // change value - ListChangedType - Assert.AreEqual(System.ComponentModel.ListChangedType.ItemChanged, evProp.lstType , "DV59"); + Assert.AreEqual(ListChangedType.ItemChanged, evProp.lstType , "DV59"); // change value - NewIndex Assert.AreEqual(1, evProp.NewIndex, "DV60"); // change value - OldIndex @@ -569,7 +570,7 @@ [Test] public void ListChanged() dv.AddNew(); Assert.AreEqual(true , evProp!=null , "DV62"); // Add New - ListChangedType - Assert.AreEqual(System.ComponentModel.ListChangedType.ItemAdded , evProp.lstType , "DV63"); + Assert.AreEqual(ListChangedType.ItemAdded , evProp.lstType , "DV63"); // Add New - NewIndex Assert.AreEqual(6, evProp.NewIndex, "DV64"); // Add New - OldIndex @@ -581,7 +582,7 @@ [Test] public void ListChanged() dv.Sort = "ParentId Desc"; Assert.AreEqual(true , evProp!=null , "DV66"); // sort - ListChangedType - Assert.AreEqual(System.ComponentModel.ListChangedType.Reset , evProp.lstType , "DV67"); + Assert.AreEqual(ListChangedType.Reset , evProp.lstType , "DV67"); // sort - NewIndex Assert.AreEqual(-1, evProp.NewIndex, "DV68"); // sort - OldIndex @@ -627,12 +628,12 @@ public void ClearTable () Assert.AreEqual(true , evProp != null , "DV168"); // Clear DataTable - should emit ListChangedType.Reset - Assert.AreEqual(System.ComponentModel.ListChangedType.Reset , evProp.lstType , "DV169"); + Assert.AreEqual(ListChangedType.Reset , evProp.lstType , "DV169"); // Clear DataTable - should clear view count Assert.AreEqual(0, dt.DefaultView.Count , "DV169"); } - private void dv_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) + private void dv_ListChanged(object sender, ListChangedEventArgs e) { evProp = new EventProperties(); evProp.lstType = e.ListChangedType; @@ -646,7 +647,7 @@ [Test] public void RowFilter() // this test also check DataView.Count property DataRowView[] drvResult = null; - System.Collections.ArrayList al = new System.Collections.ArrayList(); + ArrayList al = new ArrayList(); //create the source datatable DataTable dt = DataProvider.CreateChildDataTable(); @@ -763,7 +764,7 @@ Unchanged An unchanged row. 2 */ //DataRowView[] drvResult = null; - System.Collections.ArrayList al = new System.Collections.ArrayList(); + ArrayList al = new ArrayList(); DataTable dt = DataProvider.CreateParentDataTable(); @@ -821,7 +822,7 @@ Unchanged An unchanged row. 2 private DataRow[] GetResultRows(DataTable dt,DataRowState State) { //get expected rows - System.Collections.ArrayList al = new System.Collections.ArrayList(); + ArrayList al = new ArrayList(); DataRowVersion drVer = DataRowVersion.Current; //From MSDN - The row the default version for the current DataRowState. diff --git a/mcs/class/System.Data/Test/System.Data/DeletedRowInaccessibleExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/DeletedRowInaccessibleExceptionTest.cs index 89fdeb547b1..be2810330fd 100644 --- a/mcs/class/System.Data/Test/System.Data/DeletedRowInaccessibleExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/DeletedRowInaccessibleExceptionTest.cs @@ -33,7 +33,7 @@ using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class DeletedRowInaccessibleExceptionTest { diff --git a/mcs/class/System.Data/Test/System.Data/DuplicateNameExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/DuplicateNameExceptionTest.cs index c26a71db1e1..77cf583fc81 100644 --- a/mcs/class/System.Data/Test/System.Data/DuplicateNameExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/DuplicateNameExceptionTest.cs @@ -33,7 +33,7 @@ using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class DuplicateNameExceptionTest { diff --git a/mcs/class/System.Data/Test/System.Data/EvaluateExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/EvaluateExceptionTest.cs index dd6fe52c914..a9c41f0c2a1 100644 --- a/mcs/class/System.Data/Test/System.Data/EvaluateExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/EvaluateExceptionTest.cs @@ -33,7 +33,7 @@ using System.Data; //using GHTUtils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class EvaluateExceptionTest { diff --git a/mcs/class/System.Data/Test/System.Data/ForeignKeyConstraintTest2.cs b/mcs/class/System.Data/Test/System.Data/ForeignKeyConstraintTest2.cs index c0ed174c96d..591fef23f04 100644 --- a/mcs/class/System.Data/Test/System.Data/ForeignKeyConstraintTest2.cs +++ b/mcs/class/System.Data/Test/System.Data/ForeignKeyConstraintTest2.cs @@ -31,7 +31,7 @@ using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class ForeignKeyConstraintTest2 { diff --git a/mcs/class/System.Data/Test/System.Data/InRowChangingEventExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/InRowChangingEventExceptionTest.cs index 08dd7f08c69..549076cbb39 100644 --- a/mcs/class/System.Data/Test/System.Data/InRowChangingEventExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/InRowChangingEventExceptionTest.cs @@ -33,7 +33,7 @@ using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class InRowChangingEventExceptionTest { diff --git a/mcs/class/System.Data/Test/System.Data/InvalidConstraintExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/InvalidConstraintExceptionTest.cs index 1aacff1ee99..04c19bfc75f 100644 --- a/mcs/class/System.Data/Test/System.Data/InvalidConstraintExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/InvalidConstraintExceptionTest.cs @@ -33,7 +33,7 @@ using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class InvalidConstraintExceptionTest { diff --git a/mcs/class/System.Data/Test/System.Data/MissingPrimaryKeyExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/MissingPrimaryKeyExceptionTest.cs index 75791b325b4..14404f2b35f 100644 --- a/mcs/class/System.Data/Test/System.Data/MissingPrimaryKeyExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/MissingPrimaryKeyExceptionTest.cs @@ -32,7 +32,7 @@ using NUnit.Framework; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] class MissingPrimaryKeyExceptionTest @@ -57,4 +57,4 @@ public void Generate2() tbl.Rows.Contains("Something"); } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data/Test/System.Data/NoNullAllowedExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/NoNullAllowedExceptionTest.cs index 5b1506a857d..45a5c5f3f76 100644 --- a/mcs/class/System.Data/Test/System.Data/NoNullAllowedExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/NoNullAllowedExceptionTest.cs @@ -33,7 +33,7 @@ using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class NoNullAllowedExceptionTest { diff --git a/mcs/class/System.Data/Test/System.Data/ReadOnlyExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/ReadOnlyExceptionTest.cs index 4969ea0a93d..dd16e85714a 100644 --- a/mcs/class/System.Data/Test/System.Data/ReadOnlyExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/ReadOnlyExceptionTest.cs @@ -33,7 +33,7 @@ using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class ReadOnlyExceptionTest { diff --git a/mcs/class/System.Data/Test/System.Data/RowNotInTableExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/RowNotInTableExceptionTest.cs index 349bdb8ae88..edade038354 100644 --- a/mcs/class/System.Data/Test/System.Data/RowNotInTableExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/RowNotInTableExceptionTest.cs @@ -31,7 +31,7 @@ using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class RowNotInTableExceptionTest { diff --git a/mcs/class/System.Data/Test/System.Data/SyntaxErrorExceptionTest.cs b/mcs/class/System.Data/Test/System.Data/SyntaxErrorExceptionTest.cs index 875be983894..e1e2b08e24b 100644 --- a/mcs/class/System.Data/Test/System.Data/SyntaxErrorExceptionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/SyntaxErrorExceptionTest.cs @@ -32,7 +32,7 @@ using System.IO; using System.Data; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class SyntaxErrorExceptionTest { diff --git a/mcs/class/System.Data/Test/System.Data/TrailingSpaceTest.cs b/mcs/class/System.Data/Test/System.Data/TrailingSpaceTest.cs index 788cc5a390e..8c6d6a0d863 100644 --- a/mcs/class/System.Data/Test/System.Data/TrailingSpaceTest.cs +++ b/mcs/class/System.Data/Test/System.Data/TrailingSpaceTest.cs @@ -2,7 +2,7 @@ using System; using System.Data; -namespace Monotests_Mono.Data.SqlExpressions +namespace MonoTests.System.Data { [TestFixture] public class ComparisonTest { @@ -10,7 +10,7 @@ public class ComparisonTest { [Test] public void TestStringTrailingSpaceHandling () { // test for bug 79695 - does not ignore certain trailing whitespace chars when comparing strings - System.Data.DataTable dataTable = new System.Data.DataTable ("Person"); + DataTable dataTable = new DataTable ("Person"); dataTable.Columns.Add ("Name", typeof (string)); dataTable.Rows.Add (new object[] {"Mike "}); DataRow[] selectedRows = dataTable.Select ("Name = 'Mike'"); diff --git a/mcs/class/System.Data/Test/System.Data/UniqueConstraintTest2.cs b/mcs/class/System.Data/Test/System.Data/UniqueConstraintTest2.cs index a21d94f1883..4e0224430c0 100644 --- a/mcs/class/System.Data/Test/System.Data/UniqueConstraintTest2.cs +++ b/mcs/class/System.Data/Test/System.Data/UniqueConstraintTest2.cs @@ -31,7 +31,7 @@ using System.Data; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class UniqueConstraintTest2 { diff --git a/mcs/class/System.Data/Test/System.Data/VersionNotFoundException.cs b/mcs/class/System.Data/Test/System.Data/VersionNotFoundException.cs index 8c2e7a9f7f1..235e30890a2 100644 --- a/mcs/class/System.Data/Test/System.Data/VersionNotFoundException.cs +++ b/mcs/class/System.Data/Test/System.Data/VersionNotFoundException.cs @@ -32,7 +32,7 @@ using NUnit.Framework; using MonoTests.System.Data.Utils; -namespace MonoTests_System.Data +namespace MonoTests.System.Data { [TestFixture] class VersionNotFoundExceptionTest @@ -73,4 +73,4 @@ public void Generate3() object obj = drParent[0,DataRowVersion.Original]; } } -} \ No newline at end of file +} diff --git a/mcs/class/System.Data/Test/System.Data/XmlDataLoaderTest.cs b/mcs/class/System.Data/Test/System.Data/XmlDataLoaderTest.cs index dee7e6e378f..2e0fe018304 100644 --- a/mcs/class/System.Data/Test/System.Data/XmlDataLoaderTest.cs +++ b/mcs/class/System.Data/Test/System.Data/XmlDataLoaderTest.cs @@ -32,7 +32,7 @@ using NUnit.Framework; -namespace Monotests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class XmlDataLoaderTest @@ -74,7 +74,7 @@ private static DataSet Create () DataSet ds = new DataSet ("Set"); DataTable dt = new DataTable ("Test"); dt.Columns.Add ("CustName", typeof (String)); - dt.Columns.Add ("Type", typeof (System.Type)); + dt.Columns.Add ("Type", typeof (Type)); ds.Tables.Add (dt); return ds; } diff --git a/mcs/class/System.Data/Test/System.Data/XmlDataReaderTest.cs b/mcs/class/System.Data/Test/System.Data/XmlDataReaderTest.cs index 546db60bfb9..9bff68d0b92 100644 --- a/mcs/class/System.Data/Test/System.Data/XmlDataReaderTest.cs +++ b/mcs/class/System.Data/Test/System.Data/XmlDataReaderTest.cs @@ -33,7 +33,7 @@ using System.Xml.Schema; using NUnit.Framework; -namespace Monotests_System.Data +namespace MonoTests.System.Data { [TestFixture] public class XmlDataReaderTest @@ -103,7 +103,7 @@ public void XmlLoadCustomTypesTest () StringReader sr = new StringReader (xml); XmlTextReader xr = new XmlTextReader (sr); DataTable tbl = new DataTable("CustomTypesTable"); - tbl.Columns.Add("Dummy", typeof(System.UInt32)); + tbl.Columns.Add("Dummy", typeof(UInt32)); tbl.Columns.Add("FuncXml", typeof(CustomTypeXml)); DataSet ds = new DataSet("CustomTypesData"); diff --git a/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/CommunicationObjectSyncTest.cs b/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/CommunicationObjectSyncTest.cs index 1650bead02d..798a77915f1 100644 --- a/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/CommunicationObjectSyncTest.cs +++ b/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/CommunicationObjectSyncTest.cs @@ -35,7 +35,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Mono.Moonlight.UnitTesting; -namespace MoonTest.ServiceModel { +namespace MonoTests.System.ServiceModel.Channels { [TestClass] public class CommunicationObjectSyncTest { diff --git a/mcs/class/System.ServiceProcess/Test/System.ServiceProcess/ServiceBaseTest.cs b/mcs/class/System.ServiceProcess/Test/System.ServiceProcess/ServiceBaseTest.cs index 7a3c014f7cd..ec6a3a236b8 100644 --- a/mcs/class/System.ServiceProcess/Test/System.ServiceProcess/ServiceBaseTest.cs +++ b/mcs/class/System.ServiceProcess/Test/System.ServiceProcess/ServiceBaseTest.cs @@ -27,10 +27,11 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System.ComponentModel; using System.ServiceProcess; using NUnit.Framework; -namespace Test +namespace MonoTests.System.ServiceProcess { [TestFixture] public class ServiceBaseTest @@ -84,7 +85,7 @@ partial class ServiceFoo /// /// Required designer variable. /// - private System.ComponentModel.IContainer components = null; + private IContainer components = null; /// /// Clean up any resources being used. @@ -107,7 +108,7 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - components = new System.ComponentModel.Container(); + components = new Container(); this.ServiceName = "ServiceFoo"; } diff --git a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AnnotationPathPointTest.cs b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AnnotationPathPointTest.cs index 1933373d27b..a802e4b8c03 100644 --- a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AnnotationPathPointTest.cs +++ b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AnnotationPathPointTest.cs @@ -27,7 +27,7 @@ using System.Windows.Forms.DataVisualization.Charting; using NUnit.Framework; -namespace ChartingTests +namespace MonoTests.System.Windows.Forms.DataVisualization.Charting { [TestFixture] public class AnnotationPathPointTest diff --git a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AnovaResultTest.cs b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AnovaResultTest.cs index 8a146d266bd..ef1f648777d 100644 --- a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AnovaResultTest.cs +++ b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AnovaResultTest.cs @@ -27,7 +27,7 @@ using System.Windows.Forms.DataVisualization.Charting; using NUnit.Framework; -namespace ChartingTests +namespace MonoTests.System.Windows.Forms.DataVisualization.Charting { [TestFixture] public class AnovaResultTest diff --git a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/ArrowAnnotationTest.cs b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/ArrowAnnotationTest.cs index ccc57005014..9fced81aade 100644 --- a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/ArrowAnnotationTest.cs +++ b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/ArrowAnnotationTest.cs @@ -27,7 +27,7 @@ using System.Windows.Forms.DataVisualization.Charting; using NUnit.Framework; -namespace ChartingTests +namespace MonoTests.System.Windows.Forms.DataVisualization.Charting { [TestFixture] public class ArrowAnnotationTest diff --git a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AxisScaleBreakStyleTest.cs b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AxisScaleBreakStyleTest.cs index e820427d526..3871898efdf 100644 --- a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AxisScaleBreakStyleTest.cs +++ b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/AxisScaleBreakStyleTest.cs @@ -28,7 +28,7 @@ using NUnit.Framework; using System.Drawing; -namespace ChartingTests +namespace MonoTests.System.Windows.Forms.DataVisualization.Charting { [TestFixture] public class AxisScaleBreakStyleTest diff --git a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/ChartElementTest.cs b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/ChartElementTest.cs index c7053c6a7ee..3afeffe4238 100644 --- a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/ChartElementTest.cs +++ b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/ChartElementTest.cs @@ -27,7 +27,7 @@ using System.Windows.Forms.DataVisualization.Charting; using NUnit.Framework; -namespace ChartingTests +namespace MonoTests.System.Windows.Forms.DataVisualization.Charting { [TestFixture] public class ChartElementTest diff --git a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/DataPointTest.cs b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/DataPointTest.cs index 5431d77ea52..ec98463aa9b 100644 --- a/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/DataPointTest.cs +++ b/mcs/class/System.Windows.Forms.DataVisualization/Test/System.Windows.Forms.DataVisualization.Charting/DataPointTest.cs @@ -27,7 +27,7 @@ using System.Windows.Forms.DataVisualization.Charting; using NUnit.Framework; -namespace ChartingTests +namespace MonoTests.System.Windows.Forms.DataVisualization.Charting { [TestFixture] public class DataPointTest diff --git a/mcs/class/System.XML/Test/System.Xml/XmlResolverTest.cs b/mcs/class/System.XML/Test/System.Xml/XmlResolverTest.cs index fcdc34e7f7a..80a46e5c99f 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlResolverTest.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlResolverTest.cs @@ -33,7 +33,7 @@ using NUnit.Framework; -namespace MonoTest.System.Xml { +namespace MonoTests.System.Xml { [TestFixture] public class XmlResolverTest { diff --git a/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverCas.cs b/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverCas.cs index 52de90d1414..2e5316c1ffe 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverCas.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverCas.cs @@ -38,7 +38,7 @@ using System.Security.Policy; using System.Xml; -using MonoTestsXml; +using MonoTests.System.Xml; namespace MonoCasTests.System.Xml { @@ -85,4 +85,4 @@ public void DenyUnrestricted_CreateEvidenceForUrl_Local () } } -#endif \ No newline at end of file +#endif diff --git a/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverTests.cs b/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverTests.cs index c97407de984..a2eaa8b1064 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverTests.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverTests.cs @@ -20,7 +20,7 @@ using System.Xml; using NUnit.Framework; -namespace MonoTestsXml +namespace MonoTests.System.Xml { [TestFixture] public class XmlSecureResolverTests diff --git a/mcs/class/System/Test/System.Net/NetworkCredentialTest.cs b/mcs/class/System/Test/System.Net/NetworkCredentialTest.cs index 610b4aca31f..dbe3255cd68 100644 --- a/mcs/class/System/Test/System.Net/NetworkCredentialTest.cs +++ b/mcs/class/System/Test/System.Net/NetworkCredentialTest.cs @@ -31,7 +31,7 @@ using NUnit.Framework; -namespace MoonTest.System.Net { +namespace MonoTests.System.Net { [TestFixture] public class NetworkCredentialTest { diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackage.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackage.cs index 54df0eb5e8e..2818cd5e453 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackage.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackage.cs @@ -25,9 +25,11 @@ using System; +using System.IO; +using System.IO.Packaging; using System.Collections.Generic; -namespace System.IO.Packaging.Tests { +namespace MonoTests.System.IO.Packaging { public class FakePackage : Package { Dictionary Parts { get; set; } @@ -77,4 +79,4 @@ protected override PackagePart [] GetPartsCore () return p; } } -} \ No newline at end of file +} diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackagePart.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackagePart.cs index 9a7871c6ed0..1ca0bb20f05 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackagePart.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackagePart.cs @@ -24,9 +24,11 @@ // using System; +using System.IO; +using System.IO.Packaging; using System.Collections.Generic; -namespace System.IO.Packaging.Tests { +namespace MonoTests.System.IO.Packaging { class FakePackagePart : PackagePart { diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackagePartTests.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackagePartTests.cs index 731aed62ff9..216a1686f64 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackagePartTests.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackagePartTests.cs @@ -26,9 +26,12 @@ using System; using System.Linq; using System.Collections.Generic; +using System.IO; +using System.IO.Packaging; +using System.Xml; using NUnit.Framework; -namespace System.IO.Packaging.Tests { +namespace MonoTests.System.IO.Packaging { [TestFixture] public class FakePackagePartTests : TestBase { @@ -146,7 +149,7 @@ public void CreateRelationship7 () } [Test] - [ExpectedException (typeof (Xml.XmlException))] + [ExpectedException (typeof (XmlException))] public void CreateDupeRelationship () { part.CreateRelationship (uris [1], TargetMode.External, "blah", "asda"); @@ -154,7 +157,7 @@ public void CreateDupeRelationship () } [Test] - [ExpectedException (typeof (Xml.XmlException))] + [ExpectedException (typeof (XmlException))] public void CreateDupeRelationshipId () { part.CreateRelationship (uris [1], TargetMode.External, "blah", "asda"); diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackageTests.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackageTests.cs index bd751542927..bfea3c84973 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackageTests.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/FakePackageTests.cs @@ -26,11 +26,13 @@ using System; using System.Collections.Generic; +using System.IO; +using System.IO.Packaging; using System.Linq; using System.Text; using NUnit.Framework; -namespace System.IO.Packaging.Tests +namespace MonoTests.System.IO.Packaging { [TestFixture] diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/FakeStream.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/FakeStream.cs index b095375b177..aafc02e25ed 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/FakeStream.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/FakeStream.cs @@ -25,9 +25,10 @@ using System; +using System.IO; using System.Collections.Generic; -namespace System.IO.Packaging.Tests { +namespace MonoTests.System.IO.Packaging { public class FakeStream : MemoryStream { public bool canRead; diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackUriHelperTests.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackUriHelperTests.cs index c5361214f7b..d231315a0e9 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackUriHelperTests.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackUriHelperTests.cs @@ -8,7 +8,7 @@ using System.IO.Packaging; using NUnit.Framework; -namespace System.IO.Packaging.Tests { +namespace MonoTests.System.IO.Packaging { [TestFixture] public class PackUriHelperTests { diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartFileTests.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartFileTests.cs index 3f2850b602b..557e4a98b51 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartFileTests.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartFileTests.cs @@ -3,7 +3,7 @@ using System.IO.Packaging; using NUnit.Framework; -namespace System.IO.Packaging.Tests +namespace MonoTests.System.IO.Packaging { [TestFixture] public class PackagePartFileTests @@ -135,4 +135,4 @@ public void TestOverwrite() } } } -} \ No newline at end of file +} diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartStreamTests.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartStreamTests.cs index 915c2a09a98..1bf60221082 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartStreamTests.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartStreamTests.cs @@ -26,11 +26,13 @@ using System; using System.Collections.Generic; +using System.IO; +using System.IO.Packaging; using System.Linq; using System.Text; using NUnit.Framework; -namespace System.IO.Packaging.Tests { +namespace MonoTests.System.IO.Packaging { [TestFixture] public class PackagePartStreamTests : TestBase { @@ -190,4 +192,4 @@ public void CheckFlushTest2 () Assert.IsTrue (stream.Length > buffer.Length * 2, "#4"); } } -} \ No newline at end of file +} diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartTest.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartTest.cs index 07015c20173..ad7eb968c3a 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartTest.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackagePartTest.cs @@ -26,12 +26,14 @@ using System; using System.Collections.Generic; +using System.IO; +using System.IO.Packaging; using System.Linq; using System.Text; using NUnit.Framework; using System.Xml; -namespace System.IO.Packaging.Tests { +namespace MonoTests.System.IO.Packaging { [TestFixture] public class PackagePartTest : TestBase { diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackageRelationshipTests.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackageRelationshipTests.cs index 8c4b031de95..6ce92d31e57 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackageRelationshipTests.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackageRelationshipTests.cs @@ -28,12 +28,14 @@ using System; using System.Collections.Generic; +using System.IO; +using System.IO.Packaging; using System.Linq; using System.Text; using System.Xml; using NUnit.Framework; -namespace System.IO.Packaging.Tests { +namespace MonoTests.System.IO.Packaging { [TestFixture] public class PackageRelationshipTests : TestBase { diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackageTest.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackageTest.cs index ae7c5945de9..933449052f3 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/PackageTest.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/PackageTest.cs @@ -26,11 +26,13 @@ using System; using System.Collections.Generic; +using System.IO; +using System.IO.Packaging; using System.Linq; using System.Text; using NUnit.Framework; -namespace System.IO.Packaging.Tests { +namespace MonoTests.System.IO.Packaging { [TestFixture] public class PackageTest : TestBase { @@ -411,8 +413,8 @@ public void ReadWriteAccessDoesntExist () [ExpectedException (typeof (FileFormatException))] public void WriteOnlyAccessExists () { - System.IO.File.Create (path).Close (); + File.Create (path).Close (); package = Package.Open (path, FileMode.OpenOrCreate, FileAccess.Write); } } -} \ No newline at end of file +} diff --git a/mcs/class/WindowsBase/Test/System.IO.Packaging/TestBase.cs b/mcs/class/WindowsBase/Test/System.IO.Packaging/TestBase.cs index 6d8b43d057e..28afcd43151 100644 --- a/mcs/class/WindowsBase/Test/System.IO.Packaging/TestBase.cs +++ b/mcs/class/WindowsBase/Test/System.IO.Packaging/TestBase.cs @@ -26,11 +26,13 @@ using System; using System.Collections.Generic; +using System.IO; +using System.IO.Packaging; using System.Linq; using System.Text; using NUnit.Framework; -namespace System.IO.Packaging.Tests { +namespace MonoTests.System.IO.Packaging { public abstract class TestBase { protected string contentType = "mime/type"; diff --git a/mcs/class/corlib/Test/Mono/DataConvertTest.cs b/mcs/class/corlib/Test/Mono/DataConvertTest.cs index 89f99e918c1..f02a6a7db40 100644 --- a/mcs/class/corlib/Test/Mono/DataConvertTest.cs +++ b/mcs/class/corlib/Test/Mono/DataConvertTest.cs @@ -8,7 +8,7 @@ using NUnit.Framework.SyntaxHelpers; #endif -namespace MonoTests { +namespace MonoTests.Mono { [TestFixture] public class DataConverterTest @@ -50,9 +50,9 @@ public void ArrayTests () [Test] public void StringAlignment () { - byte[] packed = Mono.DataConverter.Pack ("bz8", 1, TEST_STRING); + byte[] packed = global::Mono.DataConverter.Pack ("bz8", 1, TEST_STRING); - IList unpacked = Mono.DataConverter.Unpack ("bz8", packed, 0); + IList unpacked = global::Mono.DataConverter.Unpack ("bz8", packed, 0); Assert.AreEqual(1, (byte) unpacked[0]); Assert.AreEqual(TEST_STRING, new string((char[]) unpacked[1])); @@ -65,4 +65,4 @@ public void UnpackTests () Assert.That ((f - 3.14f), Is.LessThanOrEqualTo (Single.Epsilon)); } } -} \ No newline at end of file +} diff --git a/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs b/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs index 699f94be803..cbb58727eb4 100644 --- a/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs +++ b/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs @@ -1111,7 +1111,7 @@ private void Symlink_helper () try { Directory.CreateDirectory (path); Directory.CreateDirectory (dir); - Mono.Unix.UnixSymbolicLinkInfo li = new Mono.Unix.UnixSymbolicLinkInfo (link); + global::Mono.Unix.UnixSymbolicLinkInfo li = new global::Mono.Unix.UnixSymbolicLinkInfo (link); li.CreateSymbolicLinkTo (dir); DirectoryInfo info = new DirectoryInfo (path); diff --git a/mcs/class/corlib/Test/System.IO/DirectoryTest.cs b/mcs/class/corlib/Test/System.IO/DirectoryTest.cs index 82536169f59..f2d7e03d3d6 100644 --- a/mcs/class/corlib/Test/System.IO/DirectoryTest.cs +++ b/mcs/class/corlib/Test/System.IO/DirectoryTest.cs @@ -374,11 +374,11 @@ public void ExistsAccessDenied () string path = TempFolder + DSC + "ExistsAccessDenied"; Directory.CreateDirectory (path); - Mono.Posix.Syscall.chmod (path, 0); + global::Mono.Posix.Syscall.chmod (path, 0); try { Assert.IsFalse (Directory.Exists(path + DSC + "b")); } finally { - Mono.Posix.Syscall.chmod (path, (Mono.Posix.FileMode) 755); + global::Mono.Posix.Syscall.chmod (path, (global::Mono.Posix.FileMode) 755); Directory.Delete (path); } } From ad8236ebb857acf1459d7c87b85df82918dc2313 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 4 Sep 2014 17:34:36 -0400 Subject: [PATCH 027/543] [runtime] Get rid of the Makefile.am.in->Makefile.am change in metadata/, its not needed. --- autogen.sh | 1 - mono/metadata/{Makefile.am.in => Makefile.am} | 0 2 files changed, 1 deletion(-) rename mono/metadata/{Makefile.am.in => Makefile.am} (100%) diff --git a/autogen.sh b/autogen.sh index 5213ecffd3c..d4a6ecaccbb 100755 --- a/autogen.sh +++ b/autogen.sh @@ -123,7 +123,6 @@ if test x$has_ext_mod = xtrue; then popd else cat mono/mini/Makefile.am.in > mono/mini/Makefile.am - cat mono/metadata/Makefile.am.in > mono/metadata/Makefile.am fi diff --git a/mono/metadata/Makefile.am.in b/mono/metadata/Makefile.am similarity index 100% rename from mono/metadata/Makefile.am.in rename to mono/metadata/Makefile.am From d84d1a94a06dc8c8585cdf360f8ad5fe4c5866cf Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 4 Sep 2014 17:38:16 -0400 Subject: [PATCH 028/543] Fix the build. --- mono/metadata/Makefile.am | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index d6b96795999..5aa44a4acca 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -343,9 +343,3 @@ endif EXTRA_DIST = make-bundle.pl sample-bundle $(win32_sources) $(unix_sources) $(null_sources) runtime.h \ tpool-poll.c tpool-epoll.c tpool-kqueue.c Makefile.am.in - -if HAS_EXTENSION_MODULE -else -Makefile.am: Makefile.am.in - cp $< $@ -endif From 39c87f6f6937accfa9d6871c70ec7e12f562007a Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 4 Sep 2014 19:11:30 -0400 Subject: [PATCH 029/543] [aot] Allow the redirection of output messages from the AOT compiler to a logfile. --- mono/mini/aot-compiler.c | 87 ++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 3c805ddae8c..86b8f7d9b9f 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -149,6 +149,7 @@ typedef struct MonoAotOptions { char *mtriple; char *llvm_path; char *instances_logfile_path; + char *logfile; } MonoAotOptions; typedef struct MonoAotStats { @@ -244,6 +245,7 @@ typedef struct MonoAotCompile { int objc_selector_index, objc_selector_index_2; GPtrArray *objc_selectors; GHashTable *objc_selector_to_index; + FILE *logfile; FILE *instances_logfile; } MonoAotCompile; @@ -303,6 +305,25 @@ get_patch_name (int info) static char* get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache); +static void +aot_printf (MonoAotCompile *acfg, const gchar *format, ...) +{ + char *msg; + va_list args; + + va_start (args, format); + if (vasprintf (&msg, format, args) < 0) + return; + va_end (args); + + if (acfg->logfile) + fprintf (acfg->logfile, "%s", msg); + else + printf ("%s", msg); + + free (msg); +} + /* Wrappers around the image writer functions */ static inline void @@ -3113,7 +3134,7 @@ add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth method = mini_get_shared_method (method); if (acfg->aot_opts.log_generics) - printf ("%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE)); + aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE)); add_method_full (acfg, method, TRUE, depth); } @@ -3929,7 +3950,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, return; if (acfg->aot_opts.log_generics) - printf ("%*sAdding generic instance %s [%s].\n", depth, "", mono_type_full_name (&klass->byval_arg), ref); + aot_printf (acfg, "%*sAdding generic instance %s [%s].\n", depth, "", mono_type_full_name (&klass->byval_arg), ref); g_hash_table_insert (acfg->ginst_hash, klass, klass); @@ -3979,7 +4000,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, method = mono_marshal_get_delegate_invoke (method, NULL); if (acfg->aot_opts.log_generics) - printf ("%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE)); + aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE)); add_method (acfg, method); } @@ -6361,6 +6382,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) opts->instances_logfile_path = g_strdup (arg + strlen ("log-instances=")); } else if (str_begins_with (arg, "log-instances")) { opts->log_instances = TRUE; + } else if (str_begins_with (arg, "internal-logfile=")) { + opts->logfile = g_strdup (arg + strlen ("internal-logfile=")); } else if (str_begins_with (arg, "mtriple=")) { opts->mtriple = g_strdup (arg + strlen ("mtriple=")); } else if (str_begins_with (arg, "llvm-path=")) { @@ -7104,7 +7127,7 @@ emit_llvm_file (MonoAotCompile *acfg) opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -sroa -domtree -early-cse -lazy-value-info -correlated-propagation -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -correlated-propagation -domtree -memdep -adce -simplifycfg -instcombine -strip-dead-prototypes -domtree -verify"); #if 1 command = g_strdup_printf ("%sopt -f %s -o \"%s.opt.bc\" \"%s.bc\"", acfg->aot_opts.llvm_path, opts, acfg->tmpbasename, acfg->tmpbasename); - printf ("Executing opt: %s\n", command); + aot_printf (acfg, "Executing opt: %s\n", command); if (system (command) != 0) { exit (1); } @@ -7133,7 +7156,7 @@ emit_llvm_file (MonoAotCompile *acfg) command = g_strdup_printf ("%sllc %s -disable-gnu-eh-frame -enable-mono-eh-frame -o \"%s\" \"%s.opt.bc\"", acfg->aot_opts.llvm_path, acfg->llc_args->str, acfg->tmpfname, acfg->tmpbasename); - printf ("Executing llc: %s\n", command); + aot_printf (acfg, "Executing llc: %s\n", command); if (system (command) != 0) { exit (1); @@ -8395,8 +8418,8 @@ collect_methods (MonoAotCompile *acfg) method = mono_get_method (acfg->image, token, NULL); if (!method) { - printf ("Failed to load method 0x%x from '%s'.\n", token, image->name); - printf ("Run with MONO_LOG_LEVEL=debug for more information.\n"); + aot_printf (acfg, "Failed to load method 0x%x from '%s'.\n", token, image->name); + aot_printf (acfg, "Run with MONO_LOG_LEVEL=debug for more information.\n"); exit (1); } @@ -8573,9 +8596,9 @@ compile_asm (MonoAotCompile *acfg) #endif if (acfg->aot_opts.asm_only) { - printf ("Output file: '%s'.\n", acfg->tmpfname); + aot_printf (acfg, "Output file: '%s'.\n", acfg->tmpfname); if (acfg->aot_opts.static_link) - printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol); + aot_printf (acfg, "Linking symbol: '%s'.\n", acfg->static_linking_symbol); return 0; } @@ -8588,7 +8611,7 @@ compile_asm (MonoAotCompile *acfg) objfile = g_strdup_printf ("%s.o", acfg->tmpfname); } command = g_strdup_printf ("%s%s %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS, acfg->as_args ? acfg->as_args->str : "", objfile, acfg->tmpfname); - printf ("Executing the native assembler: %s\n", command); + aot_printf (acfg, "Executing the native assembler: %s\n", command); if (system (command) != 0) { g_free (command); g_free (objfile); @@ -8598,8 +8621,8 @@ compile_asm (MonoAotCompile *acfg) g_free (command); if (acfg->aot_opts.static_link) { - printf ("Output file: '%s'.\n", objfile); - printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol); + aot_printf (acfg, "Output file: '%s'.\n", objfile); + aot_printf (acfg, "Linking symbol: '%s'.\n", acfg->static_linking_symbol); g_free (objfile); return 0; } @@ -8616,7 +8639,7 @@ compile_asm (MonoAotCompile *acfg) #else command = g_strdup_printf ("%sld %s -shared -o %s %s.o", tool_prefix, LD_OPTIONS, tmp_outfile_name, acfg->tmpfname); #endif - printf ("Executing the native linker: %s\n", command); + aot_printf (acfg, "Executing the native linker: %s\n", command); if (system (command) != 0) { g_free (tmp_outfile_name); g_free (outfile_name); @@ -8638,7 +8661,7 @@ compile_asm (MonoAotCompile *acfg) * happens a lot in emit_and_reloc_code (), so we need to get rid of them. */ command = g_strdup_printf ("%sstrip --strip-symbol=\\$a --strip-symbol=\\$d %s", tool_prefix, tmp_outfile_name); - printf ("Stripping the binary: %s\n", command); + aot_printf (acfg, "Stripping the binary: %s\n", command); if (system (command) != 0) { g_free (tmp_outfile_name); g_free (outfile_name); @@ -8652,7 +8675,7 @@ compile_asm (MonoAotCompile *acfg) #if defined(TARGET_MACH) command = g_strdup_printf ("dsymutil %s", outfile_name); - printf ("Executing dsymutil: %s\n", command); + aot_printf (acfg, "Executing dsymutil: %s\n", command); if (system (command) != 0) { return 1; } @@ -8666,7 +8689,7 @@ compile_asm (MonoAotCompile *acfg) g_free (objfile); if (acfg->aot_opts.save_temps) - printf ("Retained input file.\n"); + aot_printf (acfg, "Retained input file.\n"); else unlink (acfg->tmpfname); @@ -8778,8 +8801,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) } #endif - printf ("Mono Ahead of Time compiler - compiling assembly %s\n", image->name); - acfg = acfg_create (ass, opts); memset (&acfg->aot_opts, 0, sizeof (acfg->aot_opts)); @@ -8796,14 +8817,20 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) mono_aot_parse_options (aot_options, &acfg->aot_opts); + if (acfg->aot_opts.logfile) { + acfg->logfile = fopen (acfg->aot_opts.logfile, "a+"); + } + if (acfg->aot_opts.static_link) acfg->aot_opts.autoreg = TRUE; //acfg->aot_opts.print_skipped_methods = TRUE; + aot_printf (acfg, "Mono Ahead of Time compiler - compiling assembly %s\n", image->name); + #ifndef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES if (acfg->aot_opts.full_aot) { - printf ("--aot=full is not supported on this platform.\n"); + aot_printf (acfg, "--aot=full is not supported on this platform.\n"); return 1; } #endif @@ -8976,7 +9003,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) acfg->fp = fopen (tmp_outfile_name, "w"); if (!acfg->fp) { - printf ("Unable to create temporary file '%s': %s\n", tmp_outfile_name, strerror (errno)); + aot_printf (acfg, "Unable to create temporary file '%s': %s\n", tmp_outfile_name, strerror (errno)); return 1; } @@ -9125,7 +9152,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) all_sizes = acfg->stats.code_size + acfg->stats.info_size + acfg->stats.ex_info_size + acfg->stats.unwind_info_size + acfg->stats.class_info_size + acfg->stats.got_info_size + acfg->stats.offsets_size + acfg->stats.plt_size; - printf ("Code: %d(%d%%) Info: %d(%d%%) Ex Info: %d(%d%%) Unwind Info: %d(%d%%) Class Info: %d(%d%%) PLT: %d(%d%%) GOT Info: %d(%d%%) Offsets: %d(%d%%) GOT: %d\n", + aot_printf (acfg, "Code: %d(%d%%) Info: %d(%d%%) Ex Info: %d(%d%%) Unwind Info: %d(%d%%) Class Info: %d(%d%%) PLT: %d(%d%%) GOT Info: %d(%d%%) Offsets: %d(%d%%) GOT: %d\n", acfg->stats.code_size, acfg->stats.code_size * 100 / all_sizes, acfg->stats.info_size, acfg->stats.info_size * 100 / all_sizes, acfg->stats.ex_info_size, acfg->stats.ex_info_size * 100 / all_sizes, @@ -9135,19 +9162,19 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) acfg->stats.got_info_size, acfg->stats.got_info_size * 100 / all_sizes, acfg->stats.offsets_size, acfg->stats.offsets_size * 100 / all_sizes, (int)(acfg->got_offset * sizeof (gpointer))); - printf ("Compiled: %d/%d (%d%%)%s, No GOT slots: %d (%d%%), Direct calls: %d (%d%%)\n", + aot_printf (acfg, "Compiled: %d/%d (%d%%)%s, No GOT slots: %d (%d%%), Direct calls: %d (%d%%)\n", acfg->stats.ccount, acfg->stats.mcount, acfg->stats.mcount ? (acfg->stats.ccount * 100) / acfg->stats.mcount : 100, llvm_stats_msg, acfg->stats.methods_without_got_slots, acfg->stats.mcount ? (acfg->stats.methods_without_got_slots * 100) / acfg->stats.mcount : 100, acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100); if (acfg->stats.genericcount) - printf ("%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100); + aot_printf (acfg, "%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100); if (acfg->stats.abscount) - printf ("%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100); + aot_printf (acfg, "%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100); if (acfg->stats.lmfcount) - printf ("%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100); + aot_printf (acfg, "%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100); if (acfg->stats.ocount) - printf ("%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100); + aot_printf (acfg, "%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100); TV_GETTIME (atv); res = img_writer_emit_writeout (acfg->w); @@ -9159,7 +9186,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) int err = rename (tmp_outfile_name, outfile_name); if (err) { - printf ("Unable to rename '%s' to '%s': %s\n", tmp_outfile_name, outfile_name, strerror (errno)); + aot_printf (acfg, "Unable to rename '%s' to '%s': %s\n", tmp_outfile_name, outfile_name, strerror (errno)); return 1; } } else { @@ -9175,13 +9202,13 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) if (acfg->aot_opts.stats) { int i; - printf ("GOT slot distribution:\n"); + aot_printf (acfg, "GOT slot distribution:\n"); for (i = 0; i < MONO_PATCH_INFO_NONE; ++i) if (acfg->stats.got_slot_types [i]) - printf ("\t%s: %d (%d)\n", get_patch_name (i), acfg->stats.got_slot_types [i], acfg->stats.got_slot_info_sizes [i]); + aot_printf (acfg, "\t%s: %d (%d)\n", get_patch_name (i), acfg->stats.got_slot_types [i], acfg->stats.got_slot_info_sizes [i]); } - printf ("JIT time: %d ms, Generation time: %d ms, Assembly+Link time: %d ms.\n", acfg->stats.jit_time / 1000, acfg->stats.gen_time / 1000, acfg->stats.link_time / 1000); + aot_printf (acfg, "JIT time: %d ms, Generation time: %d ms, Assembly+Link time: %d ms.\n", acfg->stats.jit_time / 1000, acfg->stats.gen_time / 1000, acfg->stats.link_time / 1000); acfg_free (acfg); From 4f916f178b0619060cacc3245e5856b9f7157a0c Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 4 Sep 2014 20:06:53 -0400 Subject: [PATCH 030/543] [aot] Print error messages to the aot logfile as well, avoid exiting the process on failures. --- mono/mini/aot-compiler.c | 85 ++++++++++++++++++++++++++-------------- mono/mini/aot-runtime.c | 8 +--- 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 86b8f7d9b9f..bf779c0d624 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -324,6 +324,25 @@ aot_printf (MonoAotCompile *acfg, const gchar *format, ...) free (msg); } +static void +aot_printerrf (MonoAotCompile *acfg, const gchar *format, ...) +{ + char *msg; + va_list args; + + va_start (args, format); + if (vasprintf (&msg, format, args) < 0) + return; + va_end (args); + + if (acfg->logfile) + fprintf (acfg->logfile, "%s", msg); + else + fprintf (stderr, "%s", msg); + + free (msg); +} + /* Wrappers around the image writer functions */ static inline void @@ -7047,7 +7066,7 @@ mono_aot_patch_info_dup (MonoJumpInfo* ji) * Emit the LLVM code into an LLVM bytecode file, and compile it using the LLVM * tools. */ -static void +static gboolean emit_llvm_file (MonoAotCompile *acfg) { char *command, *opts, *tempbc; @@ -7128,9 +7147,8 @@ emit_llvm_file (MonoAotCompile *acfg) #if 1 command = g_strdup_printf ("%sopt -f %s -o \"%s.opt.bc\" \"%s.bc\"", acfg->aot_opts.llvm_path, opts, acfg->tmpbasename, acfg->tmpbasename); aot_printf (acfg, "Executing opt: %s\n", command); - if (system (command) != 0) { - exit (1); - } + if (system (command) != 0) + return FALSE; #endif g_free (opts); @@ -7158,9 +7176,9 @@ emit_llvm_file (MonoAotCompile *acfg) aot_printf (acfg, "Executing llc: %s\n", command); - if (system (command) != 0) { - exit (1); - } + if (system (command) != 0) + return FALSE; + return TRUE; } #endif @@ -8404,7 +8422,7 @@ emit_dwarf_info (MonoAotCompile *acfg) #endif } -static void +static gboolean collect_methods (MonoAotCompile *acfg) { int mindex, i; @@ -8418,9 +8436,9 @@ collect_methods (MonoAotCompile *acfg) method = mono_get_method (acfg->image, token, NULL); if (!method) { - aot_printf (acfg, "Failed to load method 0x%x from '%s'.\n", token, image->name); - aot_printf (acfg, "Run with MONO_LOG_LEVEL=debug for more information.\n"); - exit (1); + aot_printerrf (acfg, "Failed to load method 0x%x from '%s'.\n", token, image->name); + aot_printerrf (acfg, "Run with MONO_LOG_LEVEL=debug for more information.\n"); + return FALSE; } /* Load all methods eagerly to skip the slower lazy loading code */ @@ -8484,6 +8502,7 @@ collect_methods (MonoAotCompile *acfg) if (acfg->aot_opts.full_aot) add_wrappers (acfg); + return TRUE; } static void @@ -8794,13 +8813,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) TV_DECLARE (atv); TV_DECLARE (btv); -#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || !defined(ENABLE_GSHAREDVT) - if (opts & MONO_OPT_GSHAREDVT) { - fprintf (stderr, "-O=gsharedvt not supported on this platform.\n"); - exit (1); - } -#endif - acfg = acfg_create (ass, opts); memset (&acfg->aot_opts, 0, sizeof (acfg->aot_opts)); @@ -8826,18 +8838,25 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) //acfg->aot_opts.print_skipped_methods = TRUE; +#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || !defined(ENABLE_GSHAREDVT) + if (opts & MONO_OPT_GSHAREDVT) { + aot_printerrf (acfg, "-O=gsharedvt not supported on this platform.\n"); + return 1; + } +#endif + aot_printf (acfg, "Mono Ahead of Time compiler - compiling assembly %s\n", image->name); #ifndef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES if (acfg->aot_opts.full_aot) { - aot_printf (acfg, "--aot=full is not supported on this platform.\n"); + aot_printerrf (acfg, "--aot=full is not supported on this platform.\n"); return 1; } #endif if (acfg->aot_opts.direct_pinvoke && !acfg->aot_opts.static_link) { - fprintf (stderr, "The 'direct-pinvoke' AOT option also requires the 'static' AOT option.\n"); - exit (1); + aot_printerrf (acfg, "The 'direct-pinvoke' AOT option also requires the 'static' AOT option.\n"); + return 1; } if (acfg->aot_opts.static_link) @@ -8850,7 +8869,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) opt->gen_seq_points = TRUE; if (!mono_debug_enabled ()) { - fprintf (stderr, "The soft-debug AOT option requires the --debug option.\n"); + aot_printerrf (acfg, "The soft-debug AOT option requires the --debug option.\n"); return 1; } acfg->flags |= MONO_AOT_FILE_FLAG_DEBUG; @@ -8862,8 +8881,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) acfg->flags |= MONO_AOT_FILE_FLAG_WITH_LLVM; if (acfg->aot_opts.soft_debug) { - fprintf (stderr, "The 'soft-debug' option is not supported when compiling with LLVM.\n"); - exit (1); + aot_printerrf (acfg, "The 'soft-debug' option is not supported when compiling with LLVM.\n"); + return 1; } } @@ -8873,8 +8892,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) if (acfg->aot_opts.instances_logfile_path) { acfg->instances_logfile = fopen (acfg->aot_opts.instances_logfile_path, "w"); if (!acfg->instances_logfile) { - fprintf (stderr, "Unable to create logfile: '%s'.\n", acfg->aot_opts.instances_logfile_path); - exit (1); + aot_printerrf (acfg, "Unable to create logfile: '%s'.\n", acfg->aot_opts.instances_logfile_path); + return 1; } } @@ -8920,7 +8939,9 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) mono_set_partial_sharing_supported (TRUE); */ - collect_methods (acfg); + res = collect_methods (acfg); + if (!res) + return 1; acfg->cfgs_size = acfg->methods->len + 32; acfg->cfgs = g_new0 (MonoCompile*, acfg->cfgs_size); @@ -8972,6 +8993,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) #ifdef ENABLE_LLVM if (acfg->llvm) { + gboolean res; + if (acfg->aot_opts.asm_only) { if (acfg->aot_opts.outfile) { acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile); @@ -8985,7 +9008,9 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename); } - emit_llvm_file (acfg); + res = emit_llvm_file (acfg); + if (!res) + return FALSE; } #endif @@ -9027,7 +9052,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) } } if (acfg->fp == 0) { - fprintf (stderr, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno)); + aot_printerrf (acfg, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno)); return 1; } acfg->w = img_writer_create (acfg->fp, FALSE); @@ -9064,7 +9089,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) if (!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) { if (acfg->aot_opts.dwarf_debug && !mono_debug_enabled ()) { - fprintf (stderr, "The dwarf AOT option requires the --debug option.\n"); + aot_printerrf (acfg, "The dwarf AOT option requires the --debug option.\n"); return 1; } acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, FALSE, !acfg->gas_line_numbers); diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index b31acd95ecf..2aa4641b7e0 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1471,13 +1471,7 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) * - fork a new process and do the work there. */ if (in_process) { - FILE *logfile; - char *logfile_name; - - logfile_name = g_strdup_printf ("%s/aot.log", cache_dir); - logfile = fopen (logfile_name, "a+"); - - aot_options = g_strdup_printf ("outfile=%s", fname); + aot_options = g_strdup_printf ("outfile=%s,internal-logfile=%s/aot.log", fname, cache_dir); /* Maybe due this in another thread ? */ res = mono_compile_assembly (assembly, mono_parse_default_optimizations (NULL), aot_options); // FIXME: Cache failures From 385f84f18c33bb244af7e8cae71c654f0693ca5f Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 4 Sep 2014 23:31:50 -0400 Subject: [PATCH 031/543] [aot] Emit aot logging information to a per-assembly file when using the AOT cache. Cache aot failures. --- mono/mini/aot-runtime.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 2aa4641b7e0..d87bf7298d4 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1376,7 +1376,7 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) { MonoAotCacheConfig *config; GSList *l; - char *fname, *tmp2, *aot_options; + char *fname, *tmp2, *aot_options, *failure_fname; const char *home; MonoDl *module; gboolean res; @@ -1384,6 +1384,7 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) char *hash; int pid; gboolean enabled; + FILE *failure_file; *aot_name = NULL; @@ -1460,6 +1461,17 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) return NULL; cache_count ++; + /* Check for previous failure */ + failure_fname = g_strdup_printf ("%s.failure", fname); + failure_file = fopen (failure_fname, "r"); + g_free (failure_fname); + if (!failure_file) { + mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT: assembly '%s' previously failed to compile '%s' ('%s')... ", assembly->image->name, failure_fname); + return NULL; + } else { + fclose (failure_file); + } + mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT: compiling assembly '%s'... ", assembly->image->name); /* @@ -1471,10 +1483,15 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) * - fork a new process and do the work there. */ if (in_process) { - aot_options = g_strdup_printf ("outfile=%s,internal-logfile=%s/aot.log", fname, cache_dir); + aot_options = g_strdup_printf ("outfile=%s,internal-logfile=%s.log", fname, fname); /* Maybe due this in another thread ? */ res = mono_compile_assembly (assembly, mono_parse_default_optimizations (NULL), aot_options); - // FIXME: Cache failures + if (!res) { + failure_fname = g_strdup_printf ("%s.failure", fname); + failure_file = fopen (failure_fname, "a+"); + fclose (failure_file); + g_free (failure_fname); + } } else { /* * - Avoid waiting for the aot process to finish ? From 1852905c44aa4dd57f5635bb6b1e34524b5429eb Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 5 Sep 2014 21:31:53 +0800 Subject: [PATCH 032/543] Test that wrong ISO8601 dates throw FormatException. --- mcs/class/corlib/Test/System/DateTimeTest.cs | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/mcs/class/corlib/Test/System/DateTimeTest.cs b/mcs/class/corlib/Test/System/DateTimeTest.cs index b8eac3a8939..202c3d2117d 100644 --- a/mcs/class/corlib/Test/System/DateTimeTest.cs +++ b/mcs/class/corlib/Test/System/DateTimeTest.cs @@ -2595,5 +2595,29 @@ public void ISO8601FractionalDigits () Assert.AreEqual (expectedTicks, dt.Ticks); } + + [Test] + [ExpectedException (typeof (FormatException))] + public void ISO8601FractionalDigitsException1 () + { + string date = "2014-08-25T01:20:23.60191161234342342346578978936567457567:6746756747467Z"; + DateTime.Parse (date, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); + } + + [Test] + [ExpectedException (typeof (FormatException))] + public void ISO8601FractionalDigitsException2 () + { + string date = "2014-08-25T01:20:23.6019116-12343423423465789789365674575676746756747467Z"; + DateTime.Parse (date, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); + } + + [Test] + [ExpectedException (typeof (FormatException))] + public void ISO8601FractionalDigitsException3 () + { + string date = "2014-08-25T01:20:23.601911612343423423465789789365674575676746756747467%Z"; + DateTime.Parse (date, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); + } } } From 24fbaedcd2d7ded26bfc07cf25e188654932dbb7 Mon Sep 17 00:00:00 2001 From: Martin Baulig Date: Thu, 4 Sep 2014 16:36:19 +0200 Subject: [PATCH 033/543] [WCF]: Actually fix #22179 to allow concurrent requests. Pass the 'OperationContext' around in a parameter instead of storing it in an instance field to make this thread-safe. --- .../System.ServiceModel/ClientBase.cs | 2 +- .../System.ServiceModel/ClientRealProxy.cs | 3 +- .../ClientRuntimeChannel.cs | 63 +++++++------------ .../ServiceRuntimeChannel.cs | 4 +- 4 files changed, 25 insertions(+), 47 deletions(-) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/ClientBase.cs b/mcs/class/System.ServiceModel/System.ServiceModel/ClientBase.cs index 702217017d0..07952e04f14 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/ClientBase.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/ClientBase.cs @@ -389,7 +389,7 @@ protected object Invoke (string methodName, object [] args) var od = cd.Operations.Find (methodName); if (od == null) throw new ArgumentException (String.Format ("Operation '{0}' not found in the service contract '{1}' in namespace '{2}'", methodName, cd.Name, cd.Namespace)); - return Inner.Process (od.SyncMethod, methodName, args); + return Inner.Process (od.SyncMethod, methodName, args, OperationContext.Current); } protected IAsyncResult BeginInvoke (string methodName, object [] args, AsyncCallback callback, object state) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRealProxy.cs b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRealProxy.cs index 1c94718b6b9..41d75e98f9c 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRealProxy.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRealProxy.cs @@ -108,8 +108,7 @@ IMessage DoInvoke (IMessage inputMessage) // sync invocation pl = new object [inmsg.MethodBase.GetParameters ().Length]; Array.Copy (inmsg.Args, pl, inmsg.ArgCount); - channel.Context = OperationContext.Current; - ret = channel.Process (inmsg.MethodBase, od.Name, pl); + ret = channel.Process (inmsg.MethodBase, od.Name, pl, OperationContext.Current); method = od.SyncMethod; } else if (inmsg.MethodBase.Equals (od.BeginMethod)) { // async invocation diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs index 6d073e3d575..3fa8170565c 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs @@ -46,9 +46,7 @@ interface IInternalContextChannel { ContractDescription Contract { get; } - OperationContext Context { set; } - - object Process (MethodBase method, string operationName, object [] parameters); + object Process (MethodBase method, string operationName, object [] parameters, OperationContext context); IAsyncResult BeginProcess (MethodBase method, string operationName, object [] parameters, AsyncCallback callback, object asyncState); @@ -69,12 +67,11 @@ class ClientRuntimeChannel TimeSpan default_open_timeout, default_close_timeout; IChannel channel; IChannelFactory factory; - OperationContext context; #region delegates readonly ProcessDelegate _processDelegate; - delegate object ProcessDelegate (MethodBase method, string operationName, object [] parameters); + delegate object ProcessDelegate (MethodBase method, string operationName, object [] parameters, OperationContext context); readonly RequestDelegate requestDelegate; @@ -149,10 +146,6 @@ internal IDuplexChannel DuplexChannel { get { return channel as IDuplexChannel; } } - public OperationContext Context { - set { context = value; } - } - #region IClientChannel bool did_interactive_initialization; @@ -445,42 +438,28 @@ public IExtensionCollection Extensions { public IAsyncResult BeginProcess (MethodBase method, string operationName, object [] parameters, AsyncCallback callback, object asyncState) { - if (context != null) - throw new InvalidOperationException ("another operation is in progress"); - context = OperationContext.Current; - - try { - return _processDelegate.BeginInvoke (method, operationName, parameters, callback, asyncState); - } catch { - context = null; - throw; - } + return _processDelegate.BeginInvoke (method, operationName, parameters, OperationContext.Current, callback, asyncState); } public object EndProcess (MethodBase method, string operationName, object [] parameters, IAsyncResult result) { - try { - if (result == null) - throw new ArgumentNullException ("result"); - if (parameters == null) - throw new ArgumentNullException ("parameters"); - // FIXME: the method arguments should be verified to be - // identical to the arguments in the corresponding begin method. - return _processDelegate.EndInvoke (result); - } finally { - context = null; - } + if (result == null) + throw new ArgumentNullException ("result"); + if (parameters == null) + throw new ArgumentNullException ("parameters"); + // FIXME: the method arguments should be verified to be + // identical to the arguments in the corresponding begin method. + return _processDelegate.EndInvoke (result); } - public object Process (MethodBase method, string operationName, object [] parameters) + public object Process (MethodBase method, string operationName, object [] parameters, OperationContext context) { var previousContext = OperationContext.Current; try { // Inherit the context from the calling thread - if (this.context != null) - OperationContext.Current = this.context; + OperationContext.Current = context; - return DoProcess (method, operationName, parameters); + return DoProcess (method, operationName, parameters, context); } catch (Exception ex) { throw; } finally { @@ -489,7 +468,7 @@ public object Process (MethodBase method, string operationName, object [] parame } } - object DoProcess (MethodBase method, string operationName, object [] parameters) + object DoProcess (MethodBase method, string operationName, object [] parameters, OperationContext context) { if (AllowInitializationUI) DisplayInitializationUI (); @@ -499,9 +478,9 @@ object DoProcess (MethodBase method, string operationName, object [] parameters) Open (); if (!od.IsOneWay) - return Request (od, parameters); + return Request (od, parameters, context); else { - Output (od, parameters); + Output (od, parameters, context); return null; } } @@ -519,17 +498,17 @@ OperationDescription SelectOperation (MethodBase method, string operationName, o return od; } - void Output (OperationDescription od, object [] parameters) + void Output (OperationDescription od, object [] parameters, OperationContext context) { ClientOperation op = runtime.Operations [od.Name]; - Send (CreateRequest (op, parameters), OperationTimeout); + Send (CreateRequest (op, parameters, context), OperationTimeout); } - object Request (OperationDescription od, object [] parameters) + object Request (OperationDescription od, object [] parameters, OperationContext context) { ClientOperation op = runtime.Operations [od.Name]; object [] inspections = new object [runtime.MessageInspectors.Count]; - Message req = CreateRequest (op, parameters); + Message req = CreateRequest (op, parameters, context); for (int i = 0; i < inspections.Length; i++) inspections [i] = runtime.MessageInspectors [i].BeforeSendRequest (ref req, this); @@ -621,7 +600,7 @@ internal void EndSend (IAsyncResult result) } #endregion - Message CreateRequest (ClientOperation op, object [] parameters) + Message CreateRequest (ClientOperation op, object [] parameters, OperationContext context) { MessageVersion version = message_version; if (version == null) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/ServiceRuntimeChannel.cs b/mcs/class/System.ServiceModel/System.ServiceModel/ServiceRuntimeChannel.cs index 0fe0d47b3dc..7bc54823627 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/ServiceRuntimeChannel.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/ServiceRuntimeChannel.cs @@ -114,9 +114,9 @@ public object EndProcess (MethodBase method, string operationName, object [] par return client.EndProcess (method, operationName, parameters, result); } - public object Process (MethodBase method, string operationName, object [] parameters) + public object Process (MethodBase method, string operationName, object [] parameters, OperationContext context) { - return client.Process (method, operationName, parameters); + return client.Process (method, operationName, parameters, context); } } From c8c4bd9a78d398b949da68543ea919855874a623 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 5 Sep 2014 15:46:11 -0400 Subject: [PATCH 034/543] [runtime] Fix the linux build. --- mono/utils/mono-threads-linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/utils/mono-threads-linux.c b/mono/utils/mono-threads-linux.c index 13b2fed651d..ea74ef815fd 100644 --- a/mono/utils/mono-threads-linux.c +++ b/mono/utils/mono-threads-linux.c @@ -1,6 +1,6 @@ #include -#if defined(PLATFORM_LINUX) +#if defined(__linux__) && !defined(PLATFORM_ANDROID) #include From 3795639a4ad5c770243da425df6eb601ef323075 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 5 Sep 2014 17:18:18 -0400 Subject: [PATCH 035/543] Fix the linux build. --- mono/utils/mono-threads-linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/utils/mono-threads-linux.c b/mono/utils/mono-threads-linux.c index ea74ef815fd..e2ee61c42f8 100644 --- a/mono/utils/mono-threads-linux.c +++ b/mono/utils/mono-threads-linux.c @@ -2,13 +2,13 @@ #if defined(__linux__) && !defined(PLATFORM_ANDROID) +#include #include void mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) { pthread_attr_t attr; - guint8 *current = (guint8*)&attr; *staddr = NULL; *stsize = (size_t)-1; From 729bbe4041dc3fa61e128f378e12e794db87d73e Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 5 Sep 2014 18:07:08 -0400 Subject: [PATCH 036/543] [jit] Store the epilog length in MonoArchEHJitInfo instead of encoding it in jinfo->unwind_desc, since the latter can overflow for methods with large epilogs. Fixes #22685. --- mono/metadata/domain-internals.h | 1 + mono/mini/aot-compiler.c | 14 ++------------ mono/mini/aot-runtime.c | 4 ++-- mono/mini/exceptions-amd64.c | 2 +- mono/mini/mini-exceptions.c | 14 ++++++++++++-- mono/mini/mini.c | 18 +++++++++--------- mono/mini/mini.h | 3 ++- 7 files changed, 29 insertions(+), 27 deletions(-) diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index 119f173dd09..24989f49afd 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -175,6 +175,7 @@ typedef struct typedef struct { guint32 stack_size; + guint32 epilog_size; } MonoArchEHJitInfo; typedef struct { diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index bf779c0d624..5f388de76e8 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -5373,18 +5373,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) encoded = mono_unwind_ops_encode (cfg->unwind_ops, &encoded_len); unwind_desc = get_unwind_info_offset (acfg, encoded, encoded_len); - g_assert (unwind_desc < 0xffff); - if (cfg->has_unwind_info_for_epilog) { - /* - * The lower 16 bits identify the unwind descriptor, the upper 16 bits contain the offset of - * the start of the epilog from the end of the method. - */ - g_assert (cfg->code_size - cfg->epilog_begin < 0xffff); - encode_value (((cfg->code_size - cfg->epilog_begin) << 16) | unwind_desc, p, &p); - g_free (encoded); - } else { - encode_value (unwind_desc, p, &p); - } + encode_value (unwind_desc, p, &p); } else { encode_value (jinfo->unwind_info, p, &p); } @@ -5483,6 +5472,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) eh_info = mono_jit_info_get_arch_eh_info (jinfo); encode_value (eh_info->stack_size, p, &p); + encode_value (eh_info->epilog_size, p, &p); } if (jinfo->has_generic_jit_info) { diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index d87bf7298d4..58b84126d2e 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -2693,6 +2693,7 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, eh_info = mono_jit_info_get_arch_eh_info (jinfo); eh_info->stack_size = decode_value (p, &p); + eh_info->epilog_size = decode_value (p, &p); } if (async) { @@ -2852,8 +2853,7 @@ mono_aot_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len) mono_aot_unlock (); } - /* The upper 16 bits of ji->unwind_info might contain the epilog offset */ - p = amodule->unwind_info + (ji->unwind_info & 0xffff); + p = amodule->unwind_info + ji->unwind_info; *unwind_info_len = decode_value (p, &p); return p; } diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 2a253a8cef8..12b4ef31dde 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -604,7 +604,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, printf ("%s %p %p\n", ji->d.method->name, ji->code_start, ip); mono_print_unwind_info (unwind_info, unwind_info_len); */ - epilog = (guint8*)ji->code_start + ji->code_size - (ji->unwind_info >> 16); + epilog = (guint8*)ji->code_start + ji->code_size - mono_jinfo_get_epilog_size (ji); regs [AMD64_RAX] = new_ctx->rax; regs [AMD64_RBX] = new_ctx->rbx; diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 7659466cd24..5993ddddb63 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -2759,6 +2759,16 @@ mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len) if (ji->from_aot) return mono_aot_get_unwind_info (ji, unwind_info_len); else - /* The upper 16 bits of ji->unwind_info might contain the epilog offset */ - return mono_get_cached_unwind_info (ji->unwind_info & 0xffff, unwind_info_len); + return mono_get_cached_unwind_info (ji->unwind_info, unwind_info_len); +} + +int +mono_jinfo_get_epilog_size (MonoJitInfo *ji) +{ + MonoArchEHJitInfo *info; + + info = mono_jit_info_get_arch_eh_info (ji); + g_assert (info); + + return info->epilog_size; } diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 03e0eb7f8b3..a31e9003a13 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -4354,6 +4354,9 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) if (stack_size) arch_eh_info_size = sizeof (MonoArchEHJitInfo); } + + if (cfg->has_unwind_info_for_epilog && !arch_eh_info_size) + arch_eh_info_size = sizeof (MonoArchEHJitInfo); if (cfg->try_block_holes) { for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) { @@ -4651,16 +4654,13 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) unwind_desc = mono_cache_unwind_info (unwind_info, info_len); if (cfg->has_unwind_info_for_epilog) { - /* - * The lower 16 bits identify the unwind descriptor, the upper 16 bits contain the offset of - * the start of the epilog from the end of the method. - */ - g_assert (unwind_desc < 0xffff); - g_assert (cfg->code_size - cfg->epilog_begin < 0xffff); - jinfo->unwind_info = ((cfg->code_size - cfg->epilog_begin) << 16) | unwind_desc; - } else { - jinfo->unwind_info = unwind_desc; + MonoArchEHJitInfo *info; + + info = mono_jit_info_get_arch_eh_info (jinfo); + g_assert (info); + info->epilog_size = cfg->code_size - cfg->epilog_begin; } + jinfo->unwind_info = unwind_desc; g_free (unwind_info); } else { jinfo->unwind_info = cfg->used_int_regs; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index cccdc095616..4bb5ad1d7d4 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -123,7 +123,7 @@ #endif /* Version number of the AOT file format */ -#define MONO_AOT_FILE_VERSION 101 +#define MONO_AOT_FILE_VERSION 102 //TODO: This is x86/amd64 specific. #define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6)) @@ -2511,6 +2511,7 @@ typedef gboolean (*MonoExceptionFrameWalk) (MonoMethod *method, gpointer ip gboolean mono_exception_walk_trace (MonoException *ex, MonoExceptionFrameWalk func, gpointer user_data); void mono_restore_context (MonoContext *ctx) MONO_INTERNAL; guint8* mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len) MONO_INTERNAL; +int mono_jinfo_get_epilog_size (MonoJitInfo *ji) MONO_INTERNAL; gboolean mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls, From 4b6a2c8f89944fa50a6c40d3658d603ac4eedfa2 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 5 Sep 2014 20:07:13 -0400 Subject: [PATCH 037/543] Fix a warning. --- mono/mini/aot-runtime.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 58b84126d2e..ac18c6490c9 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -2098,9 +2098,7 @@ mono_aot_init (void) if (g_getenv ("MONO_LASTAOT")) mono_last_aot_method = atoi (g_getenv ("MONO_LASTAOT")); -#ifdef ENABLE_AOT_CACHE aot_cache_init (); -#endif } void From f8365f7900909a4ee900a1a905c77fe3225bf4ce Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sat, 6 Sep 2014 00:38:38 -0400 Subject: [PATCH 038/543] [gsharedvt] Allow the SIZEOF opcode in gsharedvt code if it doesn't reference a gsharedvt type. Fixes #22711. --- mono/mini/method-to-ir.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 27f26a14a76..8a52d6a7a23 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -12155,8 +12155,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b guint32 val; int ialign; - GSHAREDVT_FAILURE (*ip); - CHECK_STACK_OVF (1); CHECK_OPSIZE (6); token = read32 (ip + 2); @@ -12168,6 +12166,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b CHECK_TYPELOAD (klass); mono_class_init (klass); val = mono_type_size (&klass->byval_arg, &ialign); + + if (mini_is_gsharedvt_klass (cfg, klass)) + GSHAREDVT_FAILURE (*ip); } EMIT_NEW_ICONST (cfg, ins, val); *sp++= ins; From 788c95a0e0e02c1dc152ffa4d91ea3fac3b502c7 Mon Sep 17 00:00:00 2001 From: Kristian Hellang Date: Sun, 7 Sep 2014 17:19:42 +0200 Subject: [PATCH 039/543] Updated WOFF to official media type See http://www.w3.org/TR/WOFF/#appendix-b for the media type registration --- mcs/class/System.Web/System.Web/MimeTypes.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.Web/System.Web/MimeTypes.cs b/mcs/class/System.Web/System.Web/MimeTypes.cs index 8b7bfcadf75..82426161d45 100644 --- a/mcs/class/System.Web/System.Web/MimeTypes.cs +++ b/mcs/class/System.Web/System.Web/MimeTypes.cs @@ -529,7 +529,7 @@ static MimeTypes () mimeTypes.Add ("wmls", "text/vnd.wap.wmlscript"); mimeTypes.Add ("wml", "text/vnd.wap.wml"); mimeTypes.Add ("wmp", "video/x-ms-wmp"); - mimeTypes.Add ("woff", "application/x-woff"); + mimeTypes.Add ("woff", "application/font-woff"); mimeTypes.Add ("word", "application/msword"); mimeTypes.Add ("wp5", "application/wordperfect"); mimeTypes.Add ("wp6", "application/wordperfect"); From d595c66bbd999579193cd0c3b765b3dad22c5d1d Mon Sep 17 00:00:00 2001 From: Kristian Hellang Date: Sun, 7 Sep 2014 17:24:37 +0200 Subject: [PATCH 040/543] Added less media type --- mcs/class/System.Web/System.Web/MimeTypes.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/mcs/class/System.Web/System.Web/MimeTypes.cs b/mcs/class/System.Web/System.Web/MimeTypes.cs index 8b7bfcadf75..079cfe3a1a6 100644 --- a/mcs/class/System.Web/System.Web/MimeTypes.cs +++ b/mcs/class/System.Web/System.Web/MimeTypes.cs @@ -233,6 +233,7 @@ static MimeTypes () mimeTypes.Add ("la", "audio/nspaudio"); mimeTypes.Add ("lam", "audio/x-liveaudio"); mimeTypes.Add ("latex", "application/x-latex"); + mimeTypes.Add ("less", "text/css"); mimeTypes.Add ("list", "text/plain"); mimeTypes.Add ("lma", "audio/nspaudio"); mimeTypes.Add ("log", "text/plain"); From 92ff3c372d20b7d83fad86e931e729658e23c965 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 8 Sep 2014 11:43:22 +0200 Subject: [PATCH 041/543] [system.net.http] Make SendAsync state free to handle recursive calls. Fixes #22724 --- .../System.Net.Http/HttpClientHandler.cs | 10 +++------- mcs/class/System/System.Net/ServicePointManager.cs | 9 +++++++++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs b/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs index 865a8062b77..b4de2a029cf 100644 --- a/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs +++ b/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs @@ -50,7 +50,6 @@ public class HttpClientHandler : HttpMessageHandler bool useProxy; ClientCertificateOption certificate; bool sentRequest; - HttpWebRequest wrequest; string connectionGroupName; bool disposed; @@ -221,12 +220,9 @@ public bool UseProxy { protected override void Dispose (bool disposing) { - if (disposing) { - if (wrequest != null) { - wrequest.ServicePoint.CloseConnectionGroup (wrequest.ConnectionGroupName); - Volatile.Write (ref wrequest, null); - } + if (disposing && !disposed) { Volatile.Write (ref disposed, true); + ServicePointManager.CloseConnectionGroup (connectionGroupName); } base.Dispose (disposing); @@ -317,7 +313,7 @@ protected async internal override Task SendAsync (HttpReque throw new ObjectDisposedException (GetType ().ToString ()); Volatile.Write (ref sentRequest, true); - wrequest = CreateWebRequest (request); + var wrequest = CreateWebRequest (request); if (request.Content != null) { var headers = wrequest.Headers; diff --git a/mcs/class/System/System.Net/ServicePointManager.cs b/mcs/class/System/System.Net/ServicePointManager.cs index b6095b08904..dc7412d725a 100644 --- a/mcs/class/System/System.Net/ServicePointManager.cs +++ b/mcs/class/System/System.Net/ServicePointManager.cs @@ -369,6 +369,15 @@ public static ServicePoint FindServicePoint (Uri address, IWebProxy proxy) return sp; } + + internal static void CloseConnectionGroup (string connectionGroupName) + { + lock (servicePoints) { + foreach (ServicePoint sp in servicePoints.Values) { + sp.CloseConnectionGroup (connectionGroupName); + } + } + } #if SECURITY_DEP internal class ChainValidationHelper { From 88bc5cee97dfd8ad9dd2f89bddca3336ade8ca97 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 8 Sep 2014 11:46:27 +0200 Subject: [PATCH 042/543] [mcs] switch statement with recursive pattern matching --- mcs/mcs/cs-parser.jay | 25 ++++++-- mcs/mcs/expression.cs | 4 ++ mcs/mcs/module.cs | 11 +++- mcs/mcs/statement.cs | 116 +++++++++++++++++++++++++---------- mcs/tests/test-pattern-06.cs | 68 ++++++++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 31 +++++++++- 6 files changed, 213 insertions(+), 42 deletions(-) create mode 100644 mcs/tests/test-pattern-06.cs diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index 84d4e3f9f1b..45f719a3738 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -4352,13 +4352,16 @@ pattern_expr $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, GetLocation ($1)); } | sizeof_expression - | invocation_expression | default_value_expression | STAR { $$ = new WildcardPattern (GetLocation ($1)); } - | type_name_expression OPEN_PARENS opt_pattern_list CLOSE_PARENS + | pattern_expr_invocation + ; + +pattern_expr_invocation + : type_name_expression OPEN_PARENS opt_pattern_list CLOSE_PARENS { $$ = new RecursivePattern ((ATypeNameExpression) $1, (Arguments) $3, GetLocation ($2)); } @@ -4368,9 +4371,11 @@ pattern : pattern_expr | pattern_type_expr opt_identifier { - var lt = (LocatedToken) $2; - var variable = new LocalVariable (current_block, lt.Value, lt.Location); - current_block.AddLocalName (variable); + if ($2 != null) { + var lt = (LocatedToken) $2; + var variable = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (variable); + } } ; @@ -5817,6 +5822,16 @@ switch_label Error_SyntaxError (yyToken); $$ = new SwitchLabel ((Expression) $2, GetLocation ($1)); } + | CASE pattern_expr_invocation COLON + { + if (lang_version != LanguageVersion.Experimental) + FeatureIsNotAvailable (GetLocation ($2), "pattern matching"); + + $$ = new SwitchLabel ((Expression) $2, GetLocation ($1)) { + PatternMatching = true + }; + lbag.AddLocation ($$, GetLocation ($3)); + } | DEFAULT_COLON { $$ = new SwitchLabel (null, GetLocation ($1)); diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index a8573955cf3..ed2860b7766 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -1807,6 +1807,10 @@ Expression ResolveMatchingExpression (ResolveContext rc) } if (ProbeType is PatternExpression) { + if (!(ProbeType is WildcardPattern) && !Convert.ImplicitConversionExists (rc, ProbeType, Expr.Type)) { + ProbeType.Error_ValueCannotBeConverted (rc, Expr.Type, false); + } + return this; } diff --git a/mcs/mcs/module.cs b/mcs/mcs/module.cs index 68f1b8ece11..138ec61638f 100644 --- a/mcs/mcs/module.cs +++ b/mcs/mcs/module.cs @@ -181,6 +181,7 @@ Method GenerateNumberMatcher () var system_convert = new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Convert", loc); + var expl_block = new ExplicitBlock (top_block, loc, loc); // // var converted = System.Convert.ChangeType (obj, System.Convert.GetTypeCode (value)); @@ -198,7 +199,7 @@ Method GenerateNumberMatcher () var changetype = new Invocation (new MemberAccess (system_convert, "ChangeType", loc), arguments_changetype); - top_block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (lv_converted, loc), changetype, loc))); + expl_block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (lv_converted, loc), changetype, loc))); // @@ -207,7 +208,13 @@ Method GenerateNumberMatcher () var equals_arguments = new Arguments (1); equals_arguments.Add (new Argument (top_block.GetParameterReference (1, loc))); var equals_invocation = new Invocation (new MemberAccess (new LocalVariableReference (lv_converted, loc), "Equals"), equals_arguments); - top_block.AddStatement (new Return (equals_invocation, loc)); + expl_block.AddStatement (new Return (equals_invocation, loc)); + + var catch_block = new ExplicitBlock (top_block, loc, loc); + catch_block.AddStatement (new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc)); + top_block.AddStatement (new TryCatch (expl_block, new List () { + new Catch (catch_block, loc) + }, loc, false)); m.Define (); m.PrepareEmit (); diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs index 441d65780c1..e46dca447eb 100644 --- a/mcs/mcs/statement.cs +++ b/mcs/mcs/statement.cs @@ -4471,6 +4471,8 @@ public Constant Converted { } } + public bool PatternMatching { get; set; } + public bool SectionStart { get; set; } public Label GetILLabel (EmitContext ec) @@ -4508,21 +4510,33 @@ public override bool Resolve (BlockContext bc) // Resolves the expression, reduces it to a literal if possible // and then converts it to the requested type. // - bool ResolveAndReduce (BlockContext rc) + bool ResolveAndReduce (BlockContext bc) { if (IsDefault) return true; - var c = label.ResolveLabelConstant (rc); + var switch_statement = bc.Switch; + + if (PatternMatching) { + label = new Is (switch_statement.ExpressionValue, label, loc).Resolve (bc); + return label != null; + } + + var c = label.ResolveLabelConstant (bc); if (c == null) return false; - if (rc.Switch.IsNullable && c is NullLiteral) { + if (switch_statement.IsNullable && c is NullLiteral) { converted = c; return true; } - converted = c.ImplicitConversionRequired (rc, rc.Switch.SwitchType); + if (switch_statement.IsPatternMatching) { + label = new Is (switch_statement.ExpressionValue, label, loc).Resolve (bc); + return true; + } + + converted = c.ImplicitConversionRequired (bc, switch_statement.SwitchType); return converted != null; } @@ -4728,12 +4742,24 @@ public bool IsNullable { } } + public bool IsPatternMatching { + get { + return new_expr == null && SwitchType != null; + } + } + public List RegisteredLabels { get { return case_labels; } } + public VariableReference ExpressionValue { + get { + return value; + } + } + // // Determines the governing type for a switch. The returned // expression might be the expression from the switch, or an @@ -4843,6 +4869,9 @@ public void RegisterLabel (BlockContext rc, SwitchLabel sl) return; } + if (sl.Converted == null) + return; + try { if (string_labels != null) { string string_value = sl.Converted.GetValue () as string; @@ -4851,7 +4880,7 @@ public void RegisterLabel (BlockContext rc, SwitchLabel sl) else string_labels.Add (string_value, sl); } else { - if (sl.Converted is NullLiteral) { + if (sl.Converted.IsNull) { case_null = sl; } else { labels.Add (sl.Converted.GetValueAsLong (), sl); @@ -5066,39 +5095,44 @@ public override bool Resolve (BlockContext ec) } } + Expression switch_expr; if (new_expr == null) { - if (Expr.Type != InternalType.ErrorType) { - ec.Report.Error (151, loc, - "A switch expression of type `{0}' cannot be converted to an integral type, bool, char, string, enum or nullable type", - Expr.Type.GetSignatureForError ()); - } + if (ec.Module.Compiler.Settings.Version != LanguageVersion.Experimental) { + if (Expr.Type != InternalType.ErrorType) { + ec.Report.Error (151, loc, + "A switch expression of type `{0}' cannot be converted to an integral type, bool, char, string, enum or nullable type", + Expr.Type.GetSignatureForError ()); + } - return false; - } + return false; + } - SwitchType = new_expr.Type; - if (SwitchType.IsNullableType) { - new_expr = unwrap = Nullable.Unwrap.Create (new_expr, true); - SwitchType = Nullable.NullableInfo.GetUnderlyingType (SwitchType); - } + switch_expr = Expr; + SwitchType = Expr.Type; + } else { + switch_expr = new_expr; + SwitchType = new_expr.Type; + if (SwitchType.IsNullableType) { + new_expr = unwrap = Nullable.Unwrap.Create (new_expr, true); + SwitchType = Nullable.NullableInfo.GetUnderlyingType (SwitchType); + } - if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.Bool && ec.Module.Compiler.Settings.Version == LanguageVersion.ISO_1) { - ec.Report.FeatureIsNotAvailable (ec.Module.Compiler, loc, "switch expression of boolean type"); - return false; - } + if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.Bool && ec.Module.Compiler.Settings.Version == LanguageVersion.ISO_1) { + ec.Report.FeatureIsNotAvailable (ec.Module.Compiler, loc, "switch expression of boolean type"); + return false; + } - if (block.Statements.Count == 0) - return true; + if (block.Statements.Count == 0) + return true; - if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.String) { - string_labels = new Dictionary (); - } else { - labels = new Dictionary (); + if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.String) { + string_labels = new Dictionary (); + } else { + labels = new Dictionary (); + } } - case_labels = new List (); - - var constant = new_expr as Constant; + var constant = switch_expr as Constant; // // Don't need extra variable for constant switch or switch with @@ -5108,7 +5142,7 @@ public override bool Resolve (BlockContext ec) // // Store switch expression for comparison purposes // - value = new_expr as VariableReference; + value = switch_expr as VariableReference; if (value == null && !HasOnlyDefaultSection ()) { var current_block = ec.CurrentBlock; ec.CurrentBlock = Block; @@ -5119,6 +5153,8 @@ public override bool Resolve (BlockContext ec) } } + case_labels = new List (); + Switch old_switch = ec.Switch; ec.Switch = this; var parent_los = ec.EnclosingLoopOrSwitch; @@ -5411,6 +5447,11 @@ void EmitShortSwitch (EmitContext ec) var constant = label.Converted; + if (constant == null) { + label.Label.EmitBranchable (ec, label.GetILLabel (ec), true); + continue; + } + if (equal_method != null) { value.Emit (ec); constant.Emit (ec); @@ -5436,6 +5477,11 @@ void EmitShortSwitch (EmitContext ec) void EmitDispatch (EmitContext ec) { + if (IsPatternMatching) { + EmitShortSwitch (ec); + return; + } + if (value == null) { // // Constant switch, we've already done the work if there is only 1 label @@ -5483,12 +5529,14 @@ protected override void DoEmit (EmitContext ec) if (value != null) { ec.Mark (loc); + + var switch_expr = new_expr ?? Expr; if (IsNullable) { unwrap.EmitCheck (ec); ec.Emit (OpCodes.Brfalse, nullLabel); - value.EmitAssign (ec, new_expr, false, false); - } else if (new_expr != value) { - value.EmitAssign (ec, new_expr, false, false); + value.EmitAssign (ec, switch_expr, false, false); + } else if (switch_expr != value) { + value.EmitAssign (ec, switch_expr, false, false); } diff --git a/mcs/tests/test-pattern-06.cs b/mcs/tests/test-pattern-06.cs new file mode 100644 index 00000000000..3b54b840acf --- /dev/null +++ b/mcs/tests/test-pattern-06.cs @@ -0,0 +1,68 @@ +// Compiler options: -langversion:experimental + +using System; + +class RecursiveNamedPattern +{ + public static int Main () + { + if (Switch_1 (null) != 4) + return 1; + + if (Switch_1 ("x") != 5) + return 2; + + if (Switch_1 (1) != 1) + return 3; + + if (Switch_1 (new C1 ()) != 3) + return 4; + + if (Switch_1 ((byte?) 1) != 1) + return 5; + + if (Switch_2 (new C1 ()) != 3) + return 10; + + if (Switch_2 (null) != 2) + return 11; + + Console.WriteLine ("ok"); + return 0; + } + + static int Switch_1 (object o) + { + switch (o) { + case 1: + return 1; + case C1 (3): + return 2; + case C1 (2): + return 3; + case null: + return 4; + default: + return 5; + } + } + + static int Switch_2 (C1 o) + { + switch (o) { + case null: + return 2; + } + + return 3; + } +} + +public class C1 +{ + public static bool operator is (C1 c1, out int i) + { + i = 2; + return true; + } +} diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 3f1b70389a4..12fab60c027 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -68454,7 +68454,7 @@ - 54 + 69 @@ -68520,6 +68520,35 @@ + + + + 182 + + + 149 + + + 28 + + + 7 + + + + + 13 + + + 7 + + + + + 69 + + + From 14f56f6aea714baf0d9925eb1c9e27318540abd5 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 8 Sep 2014 14:50:39 +0200 Subject: [PATCH 043/543] [system.numerics] Unify handling of default ctor and zero. Fixes #22591 --- .../System.Numerics/BigInteger.cs | 80 ++++++++++--------- .../Test/System.Numerics/BigIntegerTest.cs | 8 ++ 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/mcs/class/System.Numerics/System.Numerics/BigInteger.cs b/mcs/class/System.Numerics/System.Numerics/BigInteger.cs index 329f91eed1f..93fb7b939e4 100644 --- a/mcs/class/System.Numerics/System.Numerics/BigInteger.cs +++ b/mcs/class/System.Numerics/System.Numerics/BigInteger.cs @@ -1,10 +1,12 @@ // // System.Numerics.BigInteger // -// Rodrigo Kumpera (rkumpera@novell.com) - +// Authors: +// Rodrigo Kumpera (rkumpera@novell.com) +// Marek Safar // // Copyright (C) 2010 Novell, Inc (http://www.novell.com) +// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -68,7 +70,6 @@ public struct BigInteger : IComparable, IFormattable, IComparable, I readonly uint[] data; readonly short sign; - static readonly uint[] ZERO = new uint [1]; static readonly uint[] ONE = new uint [1] { 1 }; BigInteger (short sign, uint[] data) @@ -81,7 +82,7 @@ public BigInteger (int value) { if (value == 0) { sign = 0; - data = ZERO; + data = null; } else if (value > 0) { sign = 1; data = new uint[] { (uint) value }; @@ -96,7 +97,7 @@ public BigInteger (uint value) { if (value == 0) { sign = 0; - data = ZERO; + data = null; } else { sign = 1; data = new uint [1] { value }; @@ -107,7 +108,7 @@ public BigInteger (long value) { if (value == 0) { sign = 0; - data = ZERO; + data = null; } else if (value > 0) { sign = 1; uint low = (uint)value; @@ -135,7 +136,7 @@ public BigInteger (ulong value) { if (value == 0) { sign = 0; - data = ZERO; + data = null; } else { sign = 1; uint low = (uint)value; @@ -180,7 +181,7 @@ public BigInteger (double value) int exponent = Exponent (bytes); if (exponent == 0) { sign = 0; - data = ZERO; + data = null; return; } @@ -217,7 +218,7 @@ public BigInteger (decimal value) if (size == 0) { sign = 0; - data = ZERO; + data = null; return; } @@ -241,7 +242,7 @@ public BigInteger (byte[] value) if (len == 0 || (len == 1 && value [0] == 0)) { sign = 0; - data = ZERO; + data = null; return; } @@ -254,7 +255,7 @@ public BigInteger (byte[] value) while (value [len - 1] == 0) { if (--len == 0) { sign = 0; - data = ZERO; + data = null; return; } } @@ -456,12 +457,12 @@ public static BigInteger One { } public static BigInteger Zero { - get { return new BigInteger (0, ZERO); } + get { return new BigInteger (0); } } public static explicit operator int (BigInteger value) { - if (value.sign == 0) + if (value.data == null) return 0; if (value.data.Length > 1) throw new OverflowException (); @@ -483,7 +484,7 @@ public static explicit operator int (BigInteger value) [CLSCompliantAttribute (false)] public static explicit operator uint (BigInteger value) { - if (value.sign == 0) + if (value.data == null) return 0; if (value.data.Length > 1 || value.sign == -1) throw new OverflowException (); @@ -527,7 +528,7 @@ public static explicit operator sbyte (BigInteger value) public static explicit operator long (BigInteger value) { - if (value.sign == 0) + if (value.data == null) return 0; if (value.data.Length > 2) @@ -569,7 +570,7 @@ long.MinValue works fine since it's bigint encoding looks like a negative [CLSCompliantAttribute (false)] public static explicit operator ulong (BigInteger value) { - if (value.sign == 0) + if (value.data == null) return 0; if (value.data.Length > 2 || value.sign == -1) throw new OverflowException (); @@ -584,9 +585,10 @@ public static explicit operator ulong (BigInteger value) public static explicit operator double (BigInteger value) { - switch (value.data.Length) { - case 0: + if (value.data == null) return 0.0; + + switch (value.data.Length) { case 1: return BuildDouble (value.sign, value.data [0], 0); case 2: @@ -613,7 +615,7 @@ public static explicit operator float (BigInteger value) public static explicit operator decimal (BigInteger value) { - if (value.sign == 0) + if (value.data == null) return Decimal.Zero; uint[] data = value.data; @@ -703,7 +705,7 @@ public static explicit operator BigInteger (decimal value) int r = CoreCompare (left.data, right.data); if (r == 0) - return new BigInteger (0, ZERO); + return Zero; if (r > 0) //left > right return new BigInteger (left.sign, CoreSub (left.data, right.data)); @@ -722,7 +724,7 @@ public static explicit operator BigInteger (decimal value) int r = CoreCompare (left.data, right.data); if (r == 0) - return new BigInteger (0, ZERO); + return Zero; if (r > 0) //left > right return new BigInteger (left.sign, CoreSub (left.data, right.data)); @@ -736,7 +738,7 @@ public static explicit operator BigInteger (decimal value) public static BigInteger operator* (BigInteger left, BigInteger right) { if (left.sign == 0 || right.sign == 0) - return new BigInteger (0, ZERO); + return Zero; if (left.data [0] == 1 && left.data.Length == 1) { if (left.sign == 1) @@ -797,7 +799,7 @@ public static explicit operator BigInteger (decimal value) int i; for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ; if (i == -1) - return new BigInteger (0, ZERO); + return Zero; if (i < quotient.Length - 1) quotient = Resize (quotient, i + 1); @@ -820,7 +822,7 @@ public static explicit operator BigInteger (decimal value) int i; for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ; if (i == -1) - return new BigInteger (0, ZERO); + return Zero; if (i < remainder_value.Length - 1) remainder_value = Resize (remainder_value, i + 1); @@ -829,7 +831,7 @@ public static explicit operator BigInteger (decimal value) public static BigInteger operator- (BigInteger value) { - if (value.sign == 0) + if (value.data == null) return value; return new BigInteger ((short)-value.sign, value.data); } @@ -841,14 +843,14 @@ public static explicit operator BigInteger (decimal value) public static BigInteger operator++ (BigInteger value) { - if (value.sign == 0) + if (value.data == null) return One; short sign = value.sign; uint[] data = value.data; if (data.Length == 1) { if (sign == -1 && data [0] == 1) - return new BigInteger (0, ZERO); + return Zero; if (sign == 0) return new BigInteger (1, ONE); } @@ -863,14 +865,14 @@ public static explicit operator BigInteger (decimal value) public static BigInteger operator-- (BigInteger value) { - if (value.sign == 0) + if (value.data == null) return MinusOne; short sign = value.sign; uint[] data = value.data; if (data.Length == 1) { if (sign == 1 && data [0] == 1) - return new BigInteger (0, ZERO); + return Zero; if (sign == 0) return new BigInteger (-1, ONE); } @@ -935,7 +937,7 @@ public static explicit operator BigInteger (decimal value) for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ; if (i == -1) - return new BigInteger (0, ZERO); + return Zero; if (i < result.Length - 1) result = Resize (result, i + 1); @@ -995,7 +997,7 @@ public static explicit operator BigInteger (decimal value) for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ; if (i == -1) - return new BigInteger (0, ZERO); + return Zero; if (i < result.Length - 1) result = Resize (result, i + 1); @@ -1055,7 +1057,7 @@ public static explicit operator BigInteger (decimal value) for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ; if (i == -1) - return new BigInteger (0, ZERO); + return Zero; if (i < result.Length - 1) result = Resize (result, i + 1); @@ -1065,7 +1067,7 @@ public static explicit operator BigInteger (decimal value) public static BigInteger operator~ (BigInteger value) { - if (value.sign == 0) + if (value.data == null) return new BigInteger (-1, ONE); uint[] data = value.data; @@ -1099,7 +1101,7 @@ public static explicit operator BigInteger (decimal value) for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ; if (i == -1) - return new BigInteger (0, ZERO); + return Zero; if (i < result.Length - 1) result = Resize (result, i + 1); @@ -1121,7 +1123,7 @@ static int BitScanBackward (uint word) public static BigInteger operator<< (BigInteger value, int shift) { - if (shift == 0 || value.sign == 0) + if (shift == 0 || value.data == null) return value; if (shift < 0) return value >> -shift; @@ -1177,7 +1179,7 @@ static int BitScanBackward (uint word) if (size <= 0) { if (sign == 1) - return new BigInteger (0, ZERO); + return Zero; return new BigInteger (-1, ONE); } @@ -2142,7 +2144,7 @@ public static BigInteger DivRem (BigInteger dividend, BigInteger divisor, out Bi int i; for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ; if (i == -1) { - remainder = new BigInteger (0, ZERO); + remainder = Zero; } else { if (i < remainder_value.Length - 1) remainder_value = Resize (remainder_value, i + 1); @@ -2151,7 +2153,7 @@ public static BigInteger DivRem (BigInteger dividend, BigInteger divisor, out Bi for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ; if (i == -1) - return new BigInteger (0, ZERO); + return Zero; if (i < quotient.Length - 1) quotient = Resize (quotient, i + 1); @@ -2264,7 +2266,7 @@ public static double Log (BigInteger value, Double baseValue) if (baseValue == 0.0d || baseValue == Double.PositiveInfinity) return value.IsOne ? 0 : double.NaN; - if (value.sign == 0) + if (value.data == null) return double.NegativeInfinity; int length = value.data.Length - 1; diff --git a/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs b/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs index 817d13e40c1..c4ad9e811ee 100644 --- a/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs +++ b/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs @@ -625,10 +625,12 @@ public void TestIntCtorProperties () Assert.IsTrue (new BigInteger (1).IsOne, "#7"); Assert.IsTrue (new BigInteger (32).IsPowerOfTwo, "#8"); Assert.IsTrue (new BigInteger (0).IsZero, "#9"); + Assert.IsTrue (new BigInteger ().IsZero, "#9b"); Assert.AreEqual (0, new BigInteger (0).Sign, "#10"); Assert.AreEqual (-1, new BigInteger (-99999).Sign, "#11"); Assert.IsFalse (new BigInteger (0).IsPowerOfTwo, "#12"); + Assert.IsFalse (new BigInteger ().IsPowerOfTwo, "#12b"); Assert.IsFalse (new BigInteger (-16).IsPowerOfTwo, "#13"); Assert.IsTrue (new BigInteger (1).IsPowerOfTwo, "#14"); } @@ -647,6 +649,7 @@ public void TestToStringFmt () Assert.AreEqual ("0000000005", new BigInteger (5).ToString ("d10"), "#2"); Assert.AreEqual ("0A8", new BigInteger (168).ToString ("X"), "#3"); Assert.AreEqual ("0", new BigInteger (0).ToString ("X"), "#4"); + Assert.AreEqual ("0", new BigInteger ().ToString ("X"), "#4b"); Assert.AreEqual ("1", new BigInteger (1).ToString ("X"), "#5"); Assert.AreEqual ("0A", new BigInteger (10).ToString ("X"), "#6"); Assert.AreEqual ("F6", new BigInteger (-10).ToString ("X"), "#7"); @@ -750,6 +753,7 @@ public void TestIntCtorToByteArray () Assert.AreEqual (new byte[] { 0x7F }, new BigInteger (0x7F).ToByteArray (), "#10"); Assert.AreEqual (new byte[] { 0x45, 0xCC, 0xD0 }, new BigInteger (-0x2F33BB).ToByteArray (), "#11"); Assert.AreEqual (new byte[] { 0 }, new BigInteger (0).ToByteArray (), "#12"); + Assert.AreEqual (new byte[] { 0 }, new BigInteger ().ToByteArray (), "#13"); } [Test] @@ -886,6 +890,7 @@ public void DecimalConversion () { Assert.AreEqual (-1m, (decimal)new BigInteger (-1), "#6"); Assert.AreEqual (9999999999999999999999999999m, (decimal)new BigInteger (9999999999999999999999999999m), "#7"); + Assert.AreEqual (0m, (decimal)new BigInteger (), "#8"); } [Test] @@ -1276,6 +1281,9 @@ public void DefaultCtorWorks () a = new BigInteger (); Assert.AreEqual (BigInteger.Zero.GetHashCode (), a.GetHashCode (), "#15"); + + a = new BigInteger (); + Assert.AreEqual (BigInteger.Zero, a, "#16"); } [Test] From d2d338fe261811c5e63bdf340d4672ff890cca91 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 8 Sep 2014 22:09:52 +0800 Subject: [PATCH 044/543] Test UriComponents.SerializationInfoString. Covers #21571. --- mcs/class/System/Test/System/UriTest.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/mcs/class/System/Test/System/UriTest.cs b/mcs/class/System/Test/System/UriTest.cs index f0a67b7a7cd..b3b33170c58 100644 --- a/mcs/class/System/Test/System/UriTest.cs +++ b/mcs/class/System/Test/System/UriTest.cs @@ -1951,6 +1951,23 @@ public void LocalPathWithBaseUrl () Assert.IsTrue (Uri.TryCreate (mainUri, uriPath, out result), "#1"); Assert.AreEqual ("http://www.imdb.com/title/tt0106521", result.ToString (), "#2"); } + + [Test] + public void GetSerializationInfoStringOnRelativeUri () + { + var uri = new Uri ("/relative/path", UriKind.Relative); + var result = uri.GetComponents (UriComponents.SerializationInfoString, UriFormat.UriEscaped); + + Assert.AreEqual (uri.OriginalString, result); + } + + [Test] + [ExpectedException (typeof (ArgumentOutOfRangeException))] + public void GetSerializationInfoStringException () + { + var uri = new Uri ("/relative/path", UriKind.Relative); + uri.GetComponents (UriComponents.SerializationInfoString | UriComponents.Host, UriFormat.UriEscaped); + } } // Tests non default IriParsing From ea6b8960d0d8dc1ea30d626a27f39bcc88ce3ea4 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 8 Sep 2014 22:21:02 +0800 Subject: [PATCH 045/543] Added support for UriComponents.SerializationInfoString. Fixes #21571. --- mcs/class/System/System/Uri.cs | 5 ++++- mcs/class/System/System/UriParser.cs | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mcs/class/System/System/Uri.cs b/mcs/class/System/System/Uri.cs index 105004e39c8..fb9c14eead1 100644 --- a/mcs/class/System/System/Uri.cs +++ b/mcs/class/System/System/Uri.cs @@ -1725,7 +1725,7 @@ protected virtual bool IsReservedCharacter (char character) private UriParser Parser { get { if (parser == null) { - parser = UriParser.GetParser (Scheme); + parser = UriParser.GetParser (scheme); // no specific parser ? then use a default one if (parser == null) parser = new DefaultUriParser ("*"); @@ -1737,6 +1737,9 @@ private UriParser Parser { public string GetComponents (UriComponents components, UriFormat format) { + if ((components & UriComponents.SerializationInfoString) == 0) + EnsureAbsoluteUri (); + return Parser.GetComponents (this, components, format); } diff --git a/mcs/class/System/System/UriParser.cs b/mcs/class/System/System/UriParser.cs index 8abfdc9b359..5eda9aadc17 100644 --- a/mcs/class/System/System/UriParser.cs +++ b/mcs/class/System/System/UriParser.cs @@ -50,6 +50,16 @@ protected internal virtual string GetComponents (Uri uri, UriComponents componen if ((format < UriFormat.UriEscaped) || (format > UriFormat.SafeUnescaped)) throw new ArgumentOutOfRangeException ("format"); + if ((components & UriComponents.SerializationInfoString) != 0) { + if (components != UriComponents.SerializationInfoString) + throw new ArgumentOutOfRangeException ("components", "UriComponents.SerializationInfoString must not be combined with other UriComponents."); + + if (!uri.IsAbsoluteUri) + return UriHelper.FormatRelative (uri.OriginalString, "", format); + + components |= UriComponents.AbsoluteUri; + } + return GetComponentsHelper (uri, components, format); } From 3c920be3e534c8c2d51695f16055e84936fe761e Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Mon, 8 Sep 2014 13:52:32 -0500 Subject: [PATCH 046/543] Use G_BEGIN_DECLS instead of __BEGIN_DECLS. __BEGIN_DECLS isn't available in mingw-w64. This commit licensed as MIT/X11. --- mono/utils/sha1.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mono/utils/sha1.h b/mono/utils/sha1.h index 63eb2beffb4..588518266ca 100644 --- a/mono/utils/sha1.h +++ b/mono/utils/sha1.h @@ -21,7 +21,7 @@ typedef struct { guint8 buffer[SHA1_BLOCK_LENGTH]; } SHA1_CTX; -__BEGIN_DECLS +G_BEGIN_DECLS void SHA1Init(SHA1_CTX *); void SHA1Pad(SHA1_CTX *); void SHA1Transform(guint32 [5], const guint8 [SHA1_BLOCK_LENGTH]); @@ -31,7 +31,7 @@ char *SHA1End(SHA1_CTX *, char *); char *SHA1File(const char *, char *); char *SHA1FileChunk(const char *, char *, off_t, off_t); char *SHA1Data(const guint8 *, size_t, char *); -__END_DECLS +G_END_DECLS #define HTONDIGEST(x) do { \ x[0] = htonl(x[0]); \ From 83924ebb2c8e5a845decd987b7cb53a98e24e07b Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Mon, 8 Sep 2014 15:46:12 -0500 Subject: [PATCH 047/543] Avoid use of vasprintf. This is not available on mingw-w64, and the extra allocation is unnecessary. This commit licensed as MIT/X11. --- mono/mini/aot-compiler.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 5f388de76e8..e54fc05083e 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -308,39 +308,33 @@ get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cac static void aot_printf (MonoAotCompile *acfg, const gchar *format, ...) { - char *msg; + FILE *output; va_list args; - va_start (args, format); - if (vasprintf (&msg, format, args) < 0) - return; - va_end (args); - if (acfg->logfile) - fprintf (acfg->logfile, "%s", msg); + output = acfg->logfile; else - printf ("%s", msg); + output = stdout; - free (msg); + va_start (args, format); + vfprintf (output, format, args); + va_end (args); } static void aot_printerrf (MonoAotCompile *acfg, const gchar *format, ...) { - char *msg; + FILE *output; va_list args; - va_start (args, format); - if (vasprintf (&msg, format, args) < 0) - return; - va_end (args); - if (acfg->logfile) - fprintf (acfg->logfile, "%s", msg); + output = acfg->logfile; else - fprintf (stderr, "%s", msg); + output = stderr; - free (msg); + va_start (args, format); + vfprintf (output, format, args); + va_end (args); } /* Wrappers around the image writer functions */ From 41c28a59bb00204bd54f8d92557f50a681dff32d Mon Sep 17 00:00:00 2001 From: Joel Martinez Date: Mon, 8 Sep 2014 17:52:36 -0400 Subject: [PATCH 048/543] [mdoc] New make test for the --dropns functionality --- mcs/tools/mdoc/Makefile | 19 +++++ mcs/tools/mdoc/Test/DocTest-DropNS-classic.cs | 8 ++ mcs/tools/mdoc/Test/DocTest-DropNS-unified.cs | 8 ++ .../MyFramework.MyNamespace/MyClass.xml | 67 ++++++++++++++++ .../en.expected-dropns-classic-v0/index.xml | 22 +++++ .../ns-MyFramework.MyNamespace.xml | 6 ++ .../MyFramework.MyNamespace/MyClass.xml | 80 +++++++++++++++++++ .../en.expected-dropns-classic-v1/index.xml | 22 +++++ .../ns-MyFramework.MyNamespace.xml | 6 ++ 9 files changed, 238 insertions(+) create mode 100644 mcs/tools/mdoc/Test/DocTest-DropNS-classic.cs create mode 100644 mcs/tools/mdoc/Test/DocTest-DropNS-unified.cs create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/MyFramework.MyNamespace/MyClass.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/index.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/ns-MyFramework.MyNamespace.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClass.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/index.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/ns-MyFramework.MyNamespace.xml diff --git a/mcs/tools/mdoc/Makefile b/mcs/tools/mdoc/Makefile index e4ff1eed87c..f67ddf5b127 100644 --- a/mcs/tools/mdoc/Makefile +++ b/mcs/tools/mdoc/Makefile @@ -90,6 +90,13 @@ cleanup: -rm -Rf Test/en.actual Test/html.actual -rm -f monodocer1.exe* +Test/DocTest-DropNS-classic.dll: + @echo $(value @) + $(CSCOMPILE) $(TEST_CSCFLAGS) -debug -unsafe -target:library -out:$@ Test/DocTest-DropNS-classic.cs + +Test/DocTest-DropNS-unified.dll: + $(CSCOMPILE) $(TEST_CSCFLAGS) -debug -unsafe -target:library -out:$@ Test/DocTest-DropNS-unified.cs + Test/DocTest.dll: $(CSCOMPILE) $(TEST_CSCFLAGS) -debug -unsafe -target:library -out:$@ Test/DocTest.cs @@ -106,6 +113,18 @@ Test/DocTest.dll-v2: -rm -f Test/DocTest.dll $(MAKE) TEST_CSCFLAGS=$(TEST_CSCFLAGS) Test/DocTest.dll +check-monodocer-dropns-classic: $(PROGRAM) + -rm -Rf Test/en.actual + $(MAKE) Test/DocTest-DropNS-classic.dll + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic.dll + $(MAKE) check-monodocer-dropns-unified + diff --exclude=.svn -rup Test/en.expected-dropns-classic-v1 Test/en.actual + +check-monodocer-dropns-unified: $(PROGRAM) + $(MAKE) Test/DocTest-DropNS-unified.dll + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll --dropns=MyFramework + + check-monodocer-update: $(PROGRAM) find Test/en.expected -name \*.xml -exec rm "{}" \; $(MAKE) Test/DocTest.dll-v1 diff --git a/mcs/tools/mdoc/Test/DocTest-DropNS-classic.cs b/mcs/tools/mdoc/Test/DocTest-DropNS-classic.cs new file mode 100644 index 00000000000..32e74fb75e8 --- /dev/null +++ b/mcs/tools/mdoc/Test/DocTest-DropNS-classic.cs @@ -0,0 +1,8 @@ +namespace MyFramework.MyNamespace { + public class MyClass { + public string MyProperty {get;set;} + public float Hello(int value) { + return 0.0f; + } + } +} \ No newline at end of file diff --git a/mcs/tools/mdoc/Test/DocTest-DropNS-unified.cs b/mcs/tools/mdoc/Test/DocTest-DropNS-unified.cs new file mode 100644 index 00000000000..6636f72d95e --- /dev/null +++ b/mcs/tools/mdoc/Test/DocTest-DropNS-unified.cs @@ -0,0 +1,8 @@ +namespace MyNamespace { + public class MyClass { + public string MyProperty {get;set;} + public float Hello(int value) { + return 0.0f; + } + } +} \ No newline at end of file diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/MyFramework.MyNamespace/MyClass.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/MyFramework.MyNamespace/MyClass.xml new file mode 100644 index 00000000000..1e0522f64f7 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/MyFramework.MyNamespace/MyClass.xml @@ -0,0 +1,67 @@ + + + + + DocTest-DropNS-classic + 0.0.0.0 + + + System.Object + + + + To be added. + To be added. + + + + + + Constructor + + 0.0.0.0 + + + + To be added. + To be added. + + + + + + Method + + 0.0.0.0 + + + System.Single + + + + + + To be added. + To be added. + To be added. + To be added. + + + + + + Property + + 0.0.0.0 + + + System.String + + + To be added. + To be added. + To be added. + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/index.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/index.xml new file mode 100644 index 00000000000..4f7838baac6 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/index.xml @@ -0,0 +1,22 @@ + + + + + + System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints) + + + System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true) + + + + + To be added. + To be added. + + + + + + DocTest-DropNS-classic + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/ns-MyFramework.MyNamespace.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/ns-MyFramework.MyNamespace.xml new file mode 100644 index 00000000000..74df75af20b --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v0/ns-MyFramework.MyNamespace.xml @@ -0,0 +1,6 @@ + + + To be added. + To be added. + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClass.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClass.xml new file mode 100644 index 00000000000..e3cda6d9d99 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClass.xml @@ -0,0 +1,80 @@ + + + + + DocTest-DropNS-classic + 0.0.0.0 + + + DocTest-DropNS-unified + 0.0.0.0 + + + System.Object + + + + To be added. + To be added. + + + + + + Constructor + + 0.0.0.0 + + + 0.0.0.0 + + + + To be added. + To be added. + + + + + + Method + + 0.0.0.0 + + + 0.0.0.0 + + + System.Single + + + + + + To be added. + To be added. + To be added. + To be added. + + + + + + Property + + 0.0.0.0 + + + 0.0.0.0 + + + System.String + + + To be added. + To be added. + To be added. + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/index.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/index.xml new file mode 100644 index 00000000000..edacc723f54 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/index.xml @@ -0,0 +1,22 @@ + + + + + + System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints) + + + System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true) + + + + + To be added. + To be added. + + + + + + DocTest-DropNS-classic + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/ns-MyFramework.MyNamespace.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/ns-MyFramework.MyNamespace.xml new file mode 100644 index 00000000000..74df75af20b --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/ns-MyFramework.MyNamespace.xml @@ -0,0 +1,6 @@ + + + To be added. + To be added. + + From f574898b09541ba572366b5598663fd1dbfe95e6 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 8 Sep 2014 20:01:11 -0400 Subject: [PATCH 049/543] [aot] Fix a crash in the aot cache code if MONO_LOG_LEVEL is set. --- mono/mini/aot-runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index ac18c6490c9..8276f3772f8 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1466,7 +1466,7 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) failure_file = fopen (failure_fname, "r"); g_free (failure_fname); if (!failure_file) { - mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT: assembly '%s' previously failed to compile '%s' ('%s')... ", assembly->image->name, failure_fname); + mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT: assembly '%s' previously failed to compile '%s' ('%s')... ", assembly->image->name, fname, failure_fname); return NULL; } else { fclose (failure_file); From 4373bd213ad8d95822c700293ad022d568b7e9bf Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 8 Sep 2014 20:25:49 -0400 Subject: [PATCH 050/543] [aot] Really fix the aot-cache logging. Rework how mscorlib is handled in the aot cache. --- mono/mini/aot-runtime.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 8276f3772f8..272616f04d9 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1399,6 +1399,7 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) MonoDomain *domain = mono_domain_get (); MonoAssembly *entry_assembly = domain->entry_assembly; + // FIXME: This cannot be used for mscorlib during startup, since entry_assembly is not set yet for (l = config->apps; l; l = l->next) { char *n = l->data; @@ -1450,12 +1451,15 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) if (module) return module; - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: not found."); - - if (!strcmp (assembly->aname.name, "mscorlib") && !mono_defaults.corlib) - /* Can't AOT this during startup */ + if (!strcmp (assembly->aname.name, "mscorlib") && !mscorlib_aot_loaded) + /* + * Can't AOT this during startup, so we AOT it when called later from + * mono_aot_get_method (). + */ return NULL; + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: not found."); + /* Only AOT one assembly per run to avoid slowing down execution too much */ if (cache_count > 0) return NULL; @@ -1464,11 +1468,12 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) /* Check for previous failure */ failure_fname = g_strdup_printf ("%s.failure", fname); failure_file = fopen (failure_fname, "r"); - g_free (failure_fname); - if (!failure_file) { + if (failure_file) { mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT: assembly '%s' previously failed to compile '%s' ('%s')... ", assembly->image->name, fname, failure_fname); + g_free (failure_fname); return NULL; } else { + g_free (failure_fname); fclose (failure_file); } @@ -1739,10 +1744,6 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) if (mono_security_cas_enabled ()) return; - if (enable_aot_cache && !strcmp (assembly->aname.name, "mscorlib") && !mono_defaults.corlib && !mono_aot_only) - /* Loaded later from mono_aot_get_method () */ - return; - mono_aot_lock (); if (static_aot_modules) info = g_hash_table_lookup (static_aot_modules, assembly->aname.name); @@ -3796,10 +3797,10 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method) if (enable_aot_cache && !amodule && domain->entry_assembly && klass->image == mono_defaults.corlib) { /* This cannot be AOTed during startup, so do it now */ if (!mscorlib_aot_loaded) { + mscorlib_aot_loaded = TRUE; load_aot_module (klass->image->assembly, NULL); amodule = klass->image->aot_module; } - mscorlib_aot_loaded = TRUE; } if (!amodule) From dc17504d3fe2d440a0b836e5e98ee9b5d4439bab Mon Sep 17 00:00:00 2001 From: Joel Martinez Date: Mon, 8 Sep 2014 20:45:16 -0400 Subject: [PATCH 051/543] [mdoc] New make test, reproduces issue with --dropns when run with a secondary assembly that doesn't drop the specified namespace --- mcs/tools/mdoc/Makefile | 26 +++++- .../Test/DocTest-DropNS-classic-secondary.cs | 9 +++ .../MyFramework.MyNamespace/MyClass.xml | 80 +++++++++++++++++++ .../MyOtherClass.xml | 67 ++++++++++++++++ .../index.xml | 35 ++++++++ .../ns-MyFramework.MyNamespace.xml | 6 ++ .../ns-MyFramework.MyOtherNamespace.xml | 6 ++ 7 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 mcs/tools/mdoc/Test/DocTest-DropNS-classic-secondary.cs create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClass.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyOtherNamespace/MyOtherClass.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/index.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/ns-MyFramework.MyNamespace.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/ns-MyFramework.MyOtherNamespace.xml diff --git a/mcs/tools/mdoc/Makefile b/mcs/tools/mdoc/Makefile index f67ddf5b127..4c5485e3625 100644 --- a/mcs/tools/mdoc/Makefile +++ b/mcs/tools/mdoc/Makefile @@ -90,6 +90,10 @@ cleanup: -rm -Rf Test/en.actual Test/html.actual -rm -f monodocer1.exe* +Test/DocTest-DropNS-classic-secondary.dll: + @echo $(value @) + $(CSCOMPILE) $(TEST_CSCFLAGS) -debug -unsafe -target:library -out:$@ Test/DocTest-DropNS-classic-secondary.cs + Test/DocTest-DropNS-classic.dll: @echo $(value @) $(CSCOMPILE) $(TEST_CSCFLAGS) -debug -unsafe -target:library -out:$@ Test/DocTest-DropNS-classic.cs @@ -114,15 +118,33 @@ Test/DocTest.dll-v2: $(MAKE) TEST_CSCFLAGS=$(TEST_CSCFLAGS) Test/DocTest.dll check-monodocer-dropns-classic: $(PROGRAM) + # tests the simplest --dropns case, a single class where the root namespace was dropped. -rm -Rf Test/en.actual $(MAKE) Test/DocTest-DropNS-classic.dll $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic.dll - $(MAKE) check-monodocer-dropns-unified + $(MAKE) update-monodocer-dropns-unified diff --exclude=.svn -rup Test/en.expected-dropns-classic-v1 Test/en.actual -check-monodocer-dropns-unified: $(PROGRAM) +check-monodocer-dropns-classic-withsecondary: $(PROGRAM) + # tests case where a secondary assembly is included with a --dropns parameter + -rm -Rf Test/en.actual + $(MAKE) Test/DocTest-DropNS-classic.dll + $(MAKE) Test/DocTest-DropNS-classic-secondary.dll + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic.dll Test/DocTest-DropNS-classic-secondary.dll + $(MAKE) update-monodocer-dropns-unified-withsecondary + diff --exclude=.svn -rup Test/en.expected-dropns-classic-withsecondary Test/en.actual + +update-monodocer-dropns-unified: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-unified.dll $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll --dropns=MyFramework + +update-monodocer-dropns-unified-withsecondary: $(PROGRAM) + $(MAKE) Test/DocTest-DropNS-unified.dll + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll Test/DocTest-DropNS-classic-secondary.dll --dropns=MyFramework + +update-monodocer-dropns-classic-secondary: $(PROGRAM) + $(MAKE) Test/DocTest-DropNS-classic-secondary.dll + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic-secondary.dll check-monodocer-update: $(PROGRAM) diff --git a/mcs/tools/mdoc/Test/DocTest-DropNS-classic-secondary.cs b/mcs/tools/mdoc/Test/DocTest-DropNS-classic-secondary.cs new file mode 100644 index 00000000000..5372ead118b --- /dev/null +++ b/mcs/tools/mdoc/Test/DocTest-DropNS-classic-secondary.cs @@ -0,0 +1,9 @@ +namespace MyFramework.MyOtherNamespace { + ///Make sure the namespace in this assembly doesn't get 'dropped' + public class MyOtherClass { + public string MyProperty {get;set;} + public float Hello(int value) { + return 0.0f; + } + } +} \ No newline at end of file diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClass.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClass.xml new file mode 100644 index 00000000000..e3cda6d9d99 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClass.xml @@ -0,0 +1,80 @@ + + + + + DocTest-DropNS-classic + 0.0.0.0 + + + DocTest-DropNS-unified + 0.0.0.0 + + + System.Object + + + + To be added. + To be added. + + + + + + Constructor + + 0.0.0.0 + + + 0.0.0.0 + + + + To be added. + To be added. + + + + + + Method + + 0.0.0.0 + + + 0.0.0.0 + + + System.Single + + + + + + To be added. + To be added. + To be added. + To be added. + + + + + + Property + + 0.0.0.0 + + + 0.0.0.0 + + + System.String + + + To be added. + To be added. + To be added. + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyOtherNamespace/MyOtherClass.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyOtherNamespace/MyOtherClass.xml new file mode 100644 index 00000000000..a178fc47d6e --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyOtherNamespace/MyOtherClass.xml @@ -0,0 +1,67 @@ + + + + + DocTest-DropNS-classic-secondary + 0.0.0.0 + + + System.Object + + + + To be added. + To be added. + + + + + + Constructor + + 0.0.0.0 + + + + To be added. + To be added. + + + + + + Method + + 0.0.0.0 + + + System.Single + + + + + + To be added. + To be added. + To be added. + To be added. + + + + + + Property + + 0.0.0.0 + + + System.String + + + To be added. + To be added. + To be added. + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/index.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/index.xml new file mode 100644 index 00000000000..d0fb593627f --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/index.xml @@ -0,0 +1,35 @@ + + + + + + System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints) + + + System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true) + + + + + + + System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints) + + + System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true) + + + + + To be added. + To be added. + + + + + + + + + Untitled + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/ns-MyFramework.MyNamespace.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/ns-MyFramework.MyNamespace.xml new file mode 100644 index 00000000000..74df75af20b --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/ns-MyFramework.MyNamespace.xml @@ -0,0 +1,6 @@ + + + To be added. + To be added. + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/ns-MyFramework.MyOtherNamespace.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/ns-MyFramework.MyOtherNamespace.xml new file mode 100644 index 00000000000..8bdef1c7778 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/ns-MyFramework.MyOtherNamespace.xml @@ -0,0 +1,6 @@ + + + To be added. + To be added. + + From 2b72c6bdf2cb716db3c39ad3537ac312857e5d6a Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Tue, 9 Sep 2014 15:09:27 +0800 Subject: [PATCH 052/543] [aspnet/ajax] fix bug #6512 (by Mikkel Kruse Johnsen) - don't deserialize GET parameters. --- .../System.Web.Script.Services/LogicalTypeInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.Web.Extensions/System.Web.Script.Services/LogicalTypeInfo.cs b/mcs/class/System.Web.Extensions/System.Web.Script.Services/LogicalTypeInfo.cs index 5f8defbff81..a9b6fc01711 100644 --- a/mcs/class/System.Web.Extensions/System.Web.Script.Services/LogicalTypeInfo.cs +++ b/mcs/class/System.Web.Extensions/System.Web.Script.Services/LogicalTypeInfo.cs @@ -411,7 +411,7 @@ IDictionary BuildInvokeParameters (HttpRequest request) var ret = new Dictionary (); for (int i = nvc.Count - 1; i >= 0; i--) - ret.Add (nvc.GetKey (i), JavaScriptSerializer.DefaultSerializer.DeserializeObjectInternal (nvc.Get (i))); + ret.Add (nvc.GetKey (i), nvc.Get (i)); return ret; } From 749171e917b7231a426691275477b19fdad3532d Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 26 Aug 2014 18:32:23 -0400 Subject: [PATCH 053/543] [sgen] Tweak internal class allocator sizes to add highly used on We observed on multiples benchmarks that most internal allocations are for 8, 16, 296 (32bits), 328 (64bits), 504 (32bits) and 1016 (64bits) bytes of memory. To minimize waste, we added these memory sizes to the default allocator sizes. --- mono/metadata/sgen-internal.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/mono/metadata/sgen-internal.c b/mono/metadata/sgen-internal.c index 37ac5c6f329..9474d7cec5a 100644 --- a/mono/metadata/sgen-internal.c +++ b/mono/metadata/sgen-internal.c @@ -27,11 +27,19 @@ #include "metadata/sgen-memory-governor.h" /* keep each size a multiple of ALLOC_ALIGN */ +#if SIZEOF_VOID_P == 4 static const int allocator_sizes [] = { 8, 16, 24, 32, 40, 48, 64, 80, - 96, 128, 160, 192, 224, 248, 320, 384, - 448, 528, 584, 680, 816, 1088, 1360, 2040, - 2336, 2728, 3272, 4088, 5456, 8184 }; + 96, 128, 160, 192, 224, 248, 296, 320, + 384, 448, 504, 528, 584, 680, 816, 1088, + 1360, 2040, 2336, 2728, 3272, 4088, 5456, 8184 }; +#else +static const int allocator_sizes [] = { + 8, 16, 24, 32, 40, 48, 64, 80, + 96, 128, 160, 192, 224, 248, 320, 328, + 384, 448, 528, 584, 680, 816, 1016, 1088, + 1360, 2040, 2336, 2728, 3272, 4088, 5456, 8184 }; +#endif #define NUM_ALLOCATORS (sizeof (allocator_sizes) / sizeof (int)) From 4f8114aabdb323d635aa47ed4480c80865a1ef50 Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Tue, 9 Sep 2014 11:30:52 +0100 Subject: [PATCH 054/543] Fix "make dist" error ad8236ebb857acf1459d7c87b85df82918dc2313 broke "make dist", by removing Makefile.am.in whilst leaving it in EXTRA_DIST --- mono/metadata/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index 5aa44a4acca..bfa08c4d39c 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -342,4 +342,4 @@ endif endif EXTRA_DIST = make-bundle.pl sample-bundle $(win32_sources) $(unix_sources) $(null_sources) runtime.h \ - tpool-poll.c tpool-epoll.c tpool-kqueue.c Makefile.am.in + tpool-poll.c tpool-epoll.c tpool-kqueue.c From cf7319008babd6a0bb0365331d6be575ff23aaa1 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 9 Sep 2014 12:41:27 +0100 Subject: [PATCH 055/543] Test DateTimeOffset.Parse with format yyyy-dd-MMzzz. Covers #22558. --- mcs/class/corlib/Test/System/DateTimeOffsetTest.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mcs/class/corlib/Test/System/DateTimeOffsetTest.cs b/mcs/class/corlib/Test/System/DateTimeOffsetTest.cs index a898f2db6e9..5d3609cedc9 100644 --- a/mcs/class/corlib/Test/System/DateTimeOffsetTest.cs +++ b/mcs/class/corlib/Test/System/DateTimeOffsetTest.cs @@ -705,6 +705,15 @@ public void TestPartialDateTimeParsing () expected = string.Format ("{0:D2}/{1:D2}/{2} 00:00:45 +00:00", now.Month, now.Day, now.Year); Assert.AreEqual (expected, date.ToString (CultureInfo.InvariantCulture)); } + + [Test] + public void TestDateOnlyWithTimeOffset () + { + var fp = CultureInfo.InvariantCulture; + var date = DateTimeOffset.Parse("2013-11-07+11:00", fp, DateTimeStyles.AssumeUniversal); + var expected = string.Format ("{0:D2}/{1:D2}/{2} 00:00:00 +11:00", 11, 7, 2013); + Assert.AreEqual (expected, date.ToString (CultureInfo.InvariantCulture)); + } } } From a27a42b99b19b069eb66967e2570163dd93e424e Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 9 Sep 2014 12:49:00 +0100 Subject: [PATCH 056/543] Added time format with only offset. Fixes #22558. --- mcs/class/corlib/System/DateTime.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/mcs/class/corlib/System/DateTime.cs b/mcs/class/corlib/System/DateTime.cs index 735599680c5..5a6eae01b3d 100644 --- a/mcs/class/corlib/System/DateTime.cs +++ b/mcs/class/corlib/System/DateTime.cs @@ -108,6 +108,7 @@ public struct DateTime : IFormattable, IConvertible, IComparable, ISerializable, "H:m", "H tt", // Specifies AM to disallow '8'. "H'\u6642'm'\u5206's'\u79D2'", + "zzz" }; // DateTime.Parse date patterns extend ParseExact patterns as follows: From 8602eed8f7f134deff6ed89fb38f8ec4119b3004 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 9 Sep 2014 09:14:37 -0400 Subject: [PATCH 057/543] [cleanup] Remove more old files. --- README.md | 4 - mono/arch/amd64/Makefile.am | 7 +- mono/arch/amd64/tramp.c | 1054 ----------------------------------- mono/arch/ppc/Makefile.am | 8 +- mono/arch/ppc/test.c | 35 -- mono/arch/ppc/tramp.c | 895 ----------------------------- mono/arch/x86/Makefile.am | 6 +- mono/arch/x86/test.c | 225 -------- mono/arch/x86/tramp.c | 545 ------------------ 9 files changed, 3 insertions(+), 2776 deletions(-) delete mode 100644 mono/arch/amd64/tramp.c delete mode 100644 mono/arch/ppc/test.c delete mode 100644 mono/arch/ppc/tramp.c delete mode 100644 mono/arch/x86/test.c delete mode 100644 mono/arch/x86/tramp.c diff --git a/README.md b/README.md index 609b9fa4660..b061956eee2 100644 --- a/README.md +++ b/README.md @@ -494,16 +494,12 @@ Directory Roadmap * `dis/` - CIL executable Disassembler - * `cli/` - Common code for the JIT and the interpreter. - * `io-layer/` - The I/O layer and system abstraction for emulating the .NET IO model. * `cil/` - Common Intermediate Representation, XML definition of the CIL bytecodes. - * `interp/` - Interpreter for CLI executables (obsolete). - * `arch/` - Architecture specific portions. * `man/` - Manual pages for the various Mono commands and programs. diff --git a/mono/arch/amd64/Makefile.am b/mono/arch/amd64/Makefile.am index 3c728263190..47daaaff699 100644 --- a/mono/arch/amd64/Makefile.am +++ b/mono/arch/amd64/Makefile.am @@ -1,7 +1,2 @@ - -AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) - -noinst_LTLIBRARIES = libmonoarch-amd64.la - -libmonoarch_amd64_la_SOURCES = tramp.c amd64-codegen.h +EXTRA_DIST = amd64-codegen.h diff --git a/mono/arch/amd64/tramp.c b/mono/arch/amd64/tramp.c deleted file mode 100644 index 6dbec93e859..00000000000 --- a/mono/arch/amd64/tramp.c +++ /dev/null @@ -1,1054 +0,0 @@ -/* - * Create trampolines to invoke arbitrary functions. - * - * Copyright (C) Ximian Inc. - * - * Author: - * Zalman Stern - * Based on code by: - * Paolo Molaro (lupus@ximian.com) - * Dietmar Maurer (dietmar@ximian.com) - * - * To understand this code, one will want to the calling convention section of the ABI sepc at: - * http://x86-64.org/abi.pdf - * and the AMD64 architecture docs found at amd.com . - */ - -#include "config.h" -#include -#include -#include "amd64-codegen.h" -#include "mono/metadata/class.h" -#include "mono/metadata/tabledefs.h" -#include "mono/interpreter/interp.h" -#include "mono/metadata/appdomain.h" -#include "mono/metadata/marshal.h" - -/* - * The resulting function takes the form: - * void func (void (*callme)(), void *retval, void *this_obj, stackval *arguments); - */ -#define FUNC_ADDR_POS 8 -#define RETVAL_POS 12 -#define THIS_POS 16 -#define ARGP_POS 20 -#define LOC_POS -4 - -#define ARG_SIZE sizeof (stackval) - -#define MAX_INT_ARG_REGS 6 -#define MAX_FLOAT_ARG_REGS 8 - -// TODO get these right. They are upper bounds anyway, so it doesn't much matter. -#define PUSH_INT_STACK_ARG_SIZE 16 -#define MOVE_INT_REG_ARG_SIZE 16 -#define PUSH_FLOAT_STACK_ARG_SIZE 16 -#define MOVE_FLOAT_REG_ARG_SIZE 16 -#define COPY_STRUCT_STACK_ARG_SIZE 16 - -/* Maps an argument number (starting at 0) to the register it is passed in (if it fits). - * E.g. int foo(int bar, int quux) has the foo arg in RDI and the quux arg in RSI - * There is no such map for floating point args as they go in XMM0-XMM7 in order and thus the - * index is the register number. - */ -static int int_arg_regs[] = { AMD64_RDI, AMD64_RSI, AMD64_RDX, AMD64_RCX, AMD64_R8, AMD64_R9 }; - -/* This next block of code resolves the ABI rules for passing structures in the argument registers. - * These basically amount to "Use up to two registers if they are all integer or all floating point. - * If the structure is bigger than two registers or would be in one integer register and one floating point, - * it is passed in memory instead. - * - * It is possible this code needs to be recursive to be correct in the case when one of the structure members - * is itself a structure. - * - * The 80-bit floating point stuff is ignored. - */ -typedef enum { - ARG_IN_MEMORY, - ARG_IN_INT_REGS, - ARG_IN_FLOAT_REGS -} struct_arg_type; - -static struct_arg_type compute_arg_type(MonoType *type) -{ - guint32 simpletype = type->type; - - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_I8: - return ARG_IN_INT_REGS; - break; - case MONO_TYPE_VALUETYPE: { - if (type->data.klass->enumtype) - return ARG_IN_INT_REGS; - return ARG_IN_MEMORY; - break; - } - case MONO_TYPE_R4: - case MONO_TYPE_R8: - return ARG_IN_FLOAT_REGS; - break; - default: - g_error ("Can't trampoline 0x%x", type->type); - } - - return ARG_IN_MEMORY; -} - -static struct_arg_type value_type_info(MonoClass *klass, int *native_size, int *regs_used, int *offset1, int *size1, int *offset2, int *size2) -{ - MonoMarshalType *info = mono_marshal_load_type_info (klass); - - *native_size = info->native_size; - - if (info->native_size > 8 || info->num_fields > 2) - { - *regs_used = 0; - *offset1 = -1; - *offset2 = -1; - return ARG_IN_MEMORY; - } - - if (info->num_fields == 1) - { - struct_arg_type result = compute_arg_type(info->fields[0].field->type); - if (result != ARG_IN_MEMORY) - { - *regs_used = 1; - *offset1 = info->fields[0].offset; - *size1 = mono_marshal_type_size (info->fields[0].field->type, info->fields[0].mspec, NULL, 1, 1); - } - else - { - *regs_used = 0; - *offset1 = -1; - } - - *offset2 = -1; - return result; - } - - struct_arg_type result1 = compute_arg_type(info->fields[0].field->type); - struct_arg_type result2 = compute_arg_type(info->fields[0].field->type); - - if (result1 == result2 && result1 != ARG_IN_MEMORY) - { - *regs_used = 2; - *offset1 = info->fields[0].offset; - *size1 = mono_marshal_type_size (info->fields[0].field->type, info->fields[0].mspec, NULL, 1, 1); - *offset2 = info->fields[1].offset; - *size2 = mono_marshal_type_size (info->fields[1].field->type, info->fields[1].mspec, NULL, 1, 1); - return result1; - } - - return ARG_IN_MEMORY; -} - -MonoPIFunc -mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor) -{ - unsigned char *p, *code_buffer; - guint32 stack_size = 0, code_size = 50; - guint32 arg_pos, simpletype; - int i; - static GHashTable *cache = NULL; - MonoPIFunc res; - - guint32 int_arg_regs_used = 0; - guint32 float_arg_regs_used = 0; - guint32 next_int_arg_reg = 0; - guint32 next_float_arg_reg = 0; - /* Indicates that the return value is filled in inside the called function. */ - int retval_implicit = 0; - char *arg_in_reg_bitvector; /* A set index by argument number saying if it is in a register - (integer or floating point according to type) */ - - if (!cache) - cache = g_hash_table_new ((GHashFunc)mono_signature_hash, - (GCompareFunc)mono_metadata_signature_equal); - - if ((res = (MonoPIFunc)g_hash_table_lookup (cache, sig))) - return res; - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref && !sig->ret->data.klass->enumtype) { - int_arg_regs_used++; - code_size += MOVE_INT_REG_ARG_SIZE; - } - - if (sig->hasthis) { - int_arg_regs_used++; - code_size += MOVE_INT_REG_ARG_SIZE; - } - - /* Run through stuff to calculate code size and argument bytes that will be pushed on stack (stack_size). */ - for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) - simpletype = MONO_TYPE_PTR; - else - simpletype = sig->params [i]->type; -enum_calc_size: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_I8: - if (int_arg_regs_used++ > MAX_INT_ARG_REGS) { - stack_size += 8; - code_size += PUSH_INT_STACK_ARG_SIZE; - } - else - code_size += MOVE_INT_REG_ARG_SIZE; - break; - case MONO_TYPE_VALUETYPE: { - int size; - int arg_type; - int regs_used; - int offset1; - int size1; - int offset2; - int size2; - - if (sig->params [i]->data.klass->enumtype) { - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_calc_size; - } - - arg_type = value_type_info(sig->params [i]->data.klass, &size, ®s_used, &offset1, &size1, &offset2, &size2); - if (arg_type == ARG_IN_INT_REGS && - (int_arg_regs_used + regs_used) <= MAX_INT_ARG_REGS) - { - code_size += MOVE_INT_REG_ARG_SIZE; - int_arg_regs_used += regs_used; - break; - } - - if (arg_type == ARG_IN_FLOAT_REGS && - (float_arg_regs_used + regs_used) <= MAX_FLOAT_ARG_REGS) - { - code_size += MOVE_FLOAT_REG_ARG_SIZE; - float_arg_regs_used += regs_used; - break; - } - - /* Else item is in memory. */ - - stack_size += size + 7; - stack_size &= ~7; - code_size += COPY_STRUCT_STACK_ARG_SIZE; - - break; - } - case MONO_TYPE_R4: - case MONO_TYPE_R8: - if (float_arg_regs_used++ > MAX_FLOAT_ARG_REGS) { - stack_size += 8; - code_size += PUSH_FLOAT_STACK_ARG_SIZE; - } - else - code_size += MOVE_FLOAT_REG_ARG_SIZE; - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - /* - * FIXME: take into account large return values. - * (Comment carried over from IA32 code. Not sure what it means :-) - */ - - code_buffer = p = alloca (code_size); - - /* - * Standard function prolog. - */ - amd64_push_reg (p, AMD64_RBP); - amd64_mov_reg_reg (p, AMD64_RBP, AMD64_RSP, 8); - /* - * and align to 16 byte boundary... - */ - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - retval_implicit = 1; - } - } - - if (sig->ret->byref || string_ctor || !(retval_implicit || sig->ret->type == MONO_TYPE_VOID)) { - /* Push the retval register so it is saved across the call. It will be addressed via RBP later. */ - amd64_push_reg (p, AMD64_RSI); - stack_size += 8; - } - - /* Ensure stack is 16 byte aligned when entering called function as required by calling convention. - * Getting this wrong results in a general protection fault on an SSE load or store somewhere in the - * code called under the trampoline. - */ - if ((stack_size & 15) != 0) - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, 16 - (stack_size & 15)); - - /* - * On entry to generated function: - * RDI has target function address - * RSI has return value location address - * RDX has this pointer address - * RCX has the pointer to the args array. - * - * Inside the stub function: - * R10 holds the pointer to the args - * R11 holds the target function address. - * The return value address is pushed on the stack. - * The this pointer is moved into the first arg register at the start. - * - * Optimization note: we could keep the args pointer in RCX and then - * load over itself at the end. Ditto the callee addres could be left in RDI in some cases. - */ - - /* Move args pointer to temp register. */ - amd64_mov_reg_reg (p, AMD64_R10, AMD64_RCX, 8); - amd64_mov_reg_reg (p, AMD64_R11, AMD64_RDI, 8); - - /* First args register gets return value pointer, if need be. - * Note that "byref" equal true means the called function returns a pointer. - */ - if (retval_implicit) { - amd64_mov_reg_reg (p, int_arg_regs[next_int_arg_reg], AMD64_RSI, 8); - next_int_arg_reg++; - } - - /* this pointer goes in next args register. */ - if (sig->hasthis) { - amd64_mov_reg_reg (p, int_arg_regs[next_int_arg_reg], AMD64_RDX, 8); - next_int_arg_reg++; - } - - /* - * Generate code to handle arguments in registers. Stack arguments will happen in a loop after this. - */ - arg_in_reg_bitvector = (char *)alloca((sig->param_count + 7) / 8); - memset(arg_in_reg_bitvector, 0, (sig->param_count + 7) / 8); - - /* First, load all the arguments that are passed in registers into the appropriate registers. - * Below there is another loop to handle arguments passed on the stack. - */ - for (i = 0; i < sig->param_count; i++) { - arg_pos = ARG_SIZE * i; - - if (sig->params [i]->byref) - simpletype = MONO_TYPE_PTR; - else - simpletype = sig->params [i]->type; -enum_marshal: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_I8: - case MONO_TYPE_U8: - case MONO_TYPE_CLASS: - if (next_int_arg_reg < MAX_INT_ARG_REGS) { - amd64_mov_reg_membase (p, int_arg_regs[next_int_arg_reg], AMD64_R10, arg_pos, 8); - next_int_arg_reg++; - arg_in_reg_bitvector[i >> 3] |= (1 << (i & 7)); - } - break; - case MONO_TYPE_R4: - if (next_float_arg_reg < MAX_FLOAT_ARG_REGS) { - amd64_movss_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos); - next_float_arg_reg++; - arg_in_reg_bitvector[i >> 3] |= (1 << (i & 7)); - } - break; - case MONO_TYPE_R8: - if (next_float_arg_reg < MAX_FLOAT_ARG_REGS) { - amd64_movsd_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos); - next_float_arg_reg++; - arg_in_reg_bitvector[i >> 3] |= (1 << (i & 7)); - } - break; - case MONO_TYPE_VALUETYPE: { - if (!sig->params [i]->data.klass->enumtype) { - int size; - int arg_type; - int regs_used; - int offset1; - int size1; - int offset2; - int size2; - - arg_type = value_type_info(sig->params [i]->data.klass, &size, ®s_used, &offset1, &size1, &offset2, &size2); - - if (arg_type == ARG_IN_INT_REGS && - (next_int_arg_reg + regs_used) <= MAX_INT_ARG_REGS) - { - amd64_mov_reg_membase (p, int_arg_regs[next_int_arg_reg], AMD64_R10, arg_pos + offset1, size1); - next_int_arg_reg++; - if (regs_used > 1) - { - amd64_mov_reg_membase (p, int_arg_regs[next_int_arg_reg], AMD64_R10, arg_pos + offset2, size2); - next_int_arg_reg++; - } - arg_in_reg_bitvector[i >> 3] |= (1 << (i & 7)); - break; - } - - if (arg_type == ARG_IN_FLOAT_REGS && - (next_float_arg_reg + regs_used) <= MAX_FLOAT_ARG_REGS) - { - if (size1 == 4) - amd64_movss_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos + offset1); - else - amd64_movsd_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos + offset1); - next_float_arg_reg++; - - if (regs_used > 1) - { - if (size2 == 4) - amd64_movss_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos + offset2); - else - amd64_movsd_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos + offset2); - next_float_arg_reg++; - } - arg_in_reg_bitvector[i >> 3] |= (1 << (i & 7)); - break; - } - - /* Structs in memory are handled in the next loop. */ - } else { - /* it's an enum value */ - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_marshal; - } - break; - } - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - - /* Handle stack arguments, pushing the rightmost argument first. */ - for (i = sig->param_count; i > 0; --i) { - arg_pos = ARG_SIZE * (i - 1); - if (sig->params [i - 1]->byref) - simpletype = MONO_TYPE_PTR; - else - simpletype = sig->params [i - 1]->type; -enum_marshal2: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_I8: - case MONO_TYPE_U8: - case MONO_TYPE_CLASS: - if ((arg_in_reg_bitvector[(i - 1) >> 3] & (1 << ((i - 1) & 7))) == 0) { - amd64_push_membase (p, AMD64_R10, arg_pos); - } - break; - case MONO_TYPE_R4: - if ((arg_in_reg_bitvector[(i - 1) >> 3] & (1 << ((i - 1) & 7))) == 0) { - amd64_push_membase (p, AMD64_R10, arg_pos); - } - break; - case MONO_TYPE_R8: - if ((arg_in_reg_bitvector[(i - 1) >> 3] & (1 << ((i - 1) & 7))) == 0) { - amd64_push_membase (p, AMD64_R10, arg_pos); - } - break; - case MONO_TYPE_VALUETYPE: - if (!sig->params [i - 1]->data.klass->enumtype) { - if ((arg_in_reg_bitvector[(i - 1) >> 3] & (1 << ((i - 1) & 7))) == 0) - { - int ss = mono_class_native_size (sig->params [i - 1]->data.klass, NULL); - ss += 7; - ss &= ~7; - - amd64_alu_reg_imm(p, X86_SUB, AMD64_RSP, ss); - /* Count register */ - amd64_mov_reg_imm(p, AMD64_RCX, ss); - /* Source register */ - amd64_lea_membase(p, AMD64_RSI, AMD64_R10, arg_pos); - /* Dest register */ - amd64_mov_reg_reg(p, AMD64_RDI, AMD64_RSP, 8); - - /* AMD64 calling convention guarantees direction flag is clear at call boundary. */ - x86_prefix(p, AMD64_REX(AMD64_REX_W)); - x86_prefix(p, X86_REP_PREFIX); - x86_movsb(p); - } - } else { - /* it's an enum value */ - simpletype = sig->params [i - 1]->data.klass->enum_basetype->type; - goto enum_marshal2; - } - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i - 1]->type); - } - } - - /* TODO: Set RAL to number of XMM registers used in case this is a varags function? */ - - /* - * Insert call to function - */ - amd64_call_reg (p, AMD64_R11); - - if (sig->ret->byref || string_ctor || !(retval_implicit || sig->ret->type == MONO_TYPE_VOID)) { - amd64_mov_reg_membase(p, AMD64_RSI, AMD64_RBP, -8, SIZEOF_VOID_P); - } - /* - * Handle retval. - * Small integer and pointer values are in EAX. - * Long integers are in EAX:EDX. - * FP values are on the FP stack. - */ - - if (sig->ret->byref || string_ctor) { - simpletype = MONO_TYPE_PTR; - } else { - simpletype = sig->ret->type; - } - enum_retvalue: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - amd64_mov_regp_reg (p, AMD64_RSI, X86_EAX, 1); - break; - case MONO_TYPE_CHAR: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - amd64_mov_regp_reg (p, AMD64_RSI, X86_EAX, 2); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: - case MONO_TYPE_STRING: - case MONO_TYPE_PTR: - amd64_mov_regp_reg (p, AMD64_RSI, X86_EAX, 8); - break; - case MONO_TYPE_R4: - amd64_movss_regp_reg (p, AMD64_RSI, AMD64_XMM0); - break; - case MONO_TYPE_R8: - amd64_movsd_regp_reg (p, AMD64_RSI, AMD64_XMM0); - break; - case MONO_TYPE_I8: - amd64_mov_regp_reg (p, AMD64_RSI, X86_EAX, 8); - break; - case MONO_TYPE_VALUETYPE: { - int size; - int arg_type; - int regs_used; - int offset1; - int size1; - int offset2; - int size2; - - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - - arg_type = value_type_info(sig->params [i]->data.klass, &size, ®s_used, &offset1, &size1, &offset2, &size2); - - if (arg_type == ARG_IN_INT_REGS) - { - amd64_mov_membase_reg (p, AMD64_RSI, offset1, AMD64_RAX, size1); - if (regs_used > 1) - amd64_mov_membase_reg (p, AMD64_RSI, offset2, AMD64_RDX, size2); - break; - } - - if (arg_type == ARG_IN_FLOAT_REGS) - { - if (size1 == 4) - amd64_movss_membase_reg (p, AMD64_RSI, offset1, AMD64_XMM0); - else - amd64_movsd_membase_reg (p, AMD64_RSI, offset1, AMD64_XMM0); - - if (regs_used > 1) - { - if (size2 == 4) - amd64_movss_membase_reg (p, AMD64_RSI, offset2, AMD64_XMM1); - else - amd64_movsd_membase_reg (p, AMD64_RSI, offset2, AMD64_XMM1); - } - break; - } - - /* Else result should have been stored in place already. */ - break; - } - case MONO_TYPE_VOID: - break; - default: - g_error ("Can't handle as return value 0x%x", sig->ret->type); - } - - /* - * Standard epilog. - */ - amd64_leave (p); - amd64_ret (p); - - g_assert (p - code_buffer < code_size); - res = (MonoPIFunc)g_memdup (code_buffer, p - code_buffer); - - g_hash_table_insert (cache, sig, res); - - return res; -} - -/* - * Returns a pointer to a native function that can be used to - * call the specified method. - * The function created will receive the arguments according - * to the call convention specified in the method. - * This function works by creating a MonoInvocation structure, - * filling the fields in and calling ves_exec_method on it. - * Still need to figure out how to handle the exception stuff - * across the managed/unmanaged boundary. - */ -void * -mono_arch_create_method_pointer (MonoMethod *method) -{ - MonoMethodSignature *sig; - MonoJitInfo *ji; - unsigned char *p, *code_buffer; - guint32 simpletype; - gint32 local_size; - gint32 stackval_pos; - gint32 mono_invocation_pos; - int i, cpos; - int *vtbuf; - int *rbpoffsets; - int int_arg_regs_used = 0; - int float_arg_regs_used = 0; - int stacked_args_size = 0; /* bytes of register passed arguments pushed on stack for safe keeping. Used to get alignment right. */ - int next_stack_arg_rbp_offset = 16; - int retval_ptr_rbp_offset = 0; - int this_reg = -1; /* Remember register this ptr is in. */ - - /* - * If it is a static P/Invoke method, we can just return the pointer - * to the method implementation. - */ - if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && ((MonoMethodPInvoke*) method)->addr) { - ji = g_new0 (MonoJitInfo, 1); - ji->method = method; - ji->code_size = 1; - ji->code_start = ((MonoMethodPInvoke*) method)->addr; - - mono_jit_info_table_add (mono_get_root_domain (), ji); - return ((MonoMethodPInvoke*) method)->addr; - } - - sig = method->signature; - - code_buffer = p = alloca (512); /* FIXME: check for overflows... */ - vtbuf = alloca (sizeof(int)*sig->param_count); - rbpoffsets = alloca (sizeof(int)*sig->param_count); - - - /* - * Standard function prolog. - */ - amd64_push_reg (p, AMD64_RBP); - amd64_mov_reg_reg (p, AMD64_RBP, AMD64_RSP, 8); - - /* If there is an implicit return value pointer in the first args reg, save it now so - * the result can be stored through the pointer at the end. - */ - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref && !sig->ret->data.klass->enumtype) - { - amd64_push_reg (p, int_arg_regs[int_arg_regs_used]); - int_arg_regs_used++; - stacked_args_size += 8; - retval_ptr_rbp_offset = -stacked_args_size; - } - - /* - * If there is a this pointer, remember the number of the register it is in. - */ - if (sig->hasthis) { - this_reg = int_arg_regs[int_arg_regs_used++]; - } - - /* Put all arguments passed in registers on the stack. - * Record offsets from RBP to each argument. - */ - cpos = 0; - - for (i = 0; i < sig->param_count; i++) { - if (sig->params [i]->byref) - simpletype = MONO_TYPE_PTR; - else - simpletype = sig->params [i]->type; -enum_calc_size: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_I8: - if (int_arg_regs_used < MAX_INT_ARG_REGS) { - amd64_push_reg (p, int_arg_regs[int_arg_regs_used]); - int_arg_regs_used++; - stacked_args_size += 8; - rbpoffsets[i] = -stacked_args_size; - } - else - { - rbpoffsets[i] = next_stack_arg_rbp_offset; - next_stack_arg_rbp_offset += 8; - } - break; - case MONO_TYPE_VALUETYPE: { - if (sig->params [i]->data.klass->enumtype) { - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_calc_size; - } - else - { - int size; - int arg_type; - int regs_used; - int offset1; - int size1; - int offset2; - int size2; - - arg_type = value_type_info(sig->params [i]->data.klass, &size, ®s_used, &offset1, &size1, &offset2, &size2); - - if (arg_type == ARG_IN_INT_REGS && - (int_arg_regs_used + regs_used) <= MAX_INT_ARG_REGS) - { - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, size); - stacked_args_size += size; - rbpoffsets[i] = stacked_args_size; - - amd64_mov_reg_membase (p, int_arg_regs[int_arg_regs_used], AMD64_RSP, offset1, size1); - int_arg_regs_used++; - if (regs_used > 1) - { - amd64_mov_reg_membase (p, int_arg_regs[int_arg_regs_used], AMD64_RSP, offset2, size2); - int_arg_regs_used++; - } - break; - } - - if (arg_type == ARG_IN_FLOAT_REGS && - (float_arg_regs_used + regs_used) <= MAX_FLOAT_ARG_REGS) - { - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, size); - stacked_args_size += size; - rbpoffsets[i] = stacked_args_size; - - if (size1 == 4) - amd64_movss_reg_membase (p, float_arg_regs_used, AMD64_RSP, offset1); - else - amd64_movsd_reg_membase (p, float_arg_regs_used, AMD64_RSP, offset1); - float_arg_regs_used++; - - if (regs_used > 1) - { - if (size2 == 4) - amd64_movss_reg_membase (p, float_arg_regs_used, AMD64_RSP, offset2); - else - amd64_movsd_reg_membase (p, float_arg_regs_used, AMD64_RSP, offset2); - float_arg_regs_used++; - } - break; - } - - rbpoffsets[i] = next_stack_arg_rbp_offset; - next_stack_arg_rbp_offset += size; - } - break; - } - case MONO_TYPE_R4: - if (float_arg_regs_used < MAX_FLOAT_ARG_REGS) { - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, 8); - amd64_movss_regp_reg (p, AMD64_RSP, float_arg_regs_used); - float_arg_regs_used++; - stacked_args_size += 8; - rbpoffsets[i] = -stacked_args_size; - } - else - { - rbpoffsets[i] = next_stack_arg_rbp_offset; - next_stack_arg_rbp_offset += 8; - } - break; - case MONO_TYPE_R8: - stacked_args_size += 8; - if (float_arg_regs_used < MAX_FLOAT_ARG_REGS) { - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, 8); - amd64_movsd_regp_reg (p, AMD64_RSP, float_arg_regs_used); - float_arg_regs_used++; - stacked_args_size += 8; - rbpoffsets[i] = -stacked_args_size; - } - else - { - rbpoffsets[i] = next_stack_arg_rbp_offset; - next_stack_arg_rbp_offset += 8; - } - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - - local_size = sizeof (MonoInvocation) + sizeof (stackval) * (sig->param_count + 1) + stacked_args_size; - - local_size += 15; - local_size &= ~15; - - stackval_pos = -local_size; - mono_invocation_pos = stackval_pos + sizeof (stackval) * (sig->param_count + 1); - - /* stacked_args_size has already been pushed onto the stack. Make room for the rest of it. */ - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, local_size - stacked_args_size); - - /* Be careful not to trash any arg regs before saving this_reg to MonoInvocation structure below. */ - - /* - * Initialize MonoInvocation fields, first the ones known now. - */ - amd64_alu_reg_reg (p, X86_XOR, AMD64_RAX, AMD64_RAX); - amd64_mov_membase_reg (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, ex)), AMD64_RAX, SIZEOF_VOID_P); - amd64_mov_membase_reg (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, ex_handler)), AMD64_RAX, SIZEOF_VOID_P); - amd64_mov_membase_reg (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, parent)), AMD64_RAX, SIZEOF_VOID_P); - /* - * Set the method pointer. - */ - amd64_mov_membase_imm (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, method)), (long)method, SIZEOF_VOID_P); - - /* - * Handle this. - */ - if (sig->hasthis) - amd64_mov_membase_reg(p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, obj)), this_reg, SIZEOF_VOID_P); - - /* - * Handle the arguments. stackval_pos is the offset from RBP of the stackval in the MonoInvocation args array . - * arg_pos is the offset from RBP to the incoming arg on the stack. - * We just call stackval_from_data to handle all the (nasty) issues.... - */ - amd64_lea_membase (p, AMD64_RAX, AMD64_RBP, stackval_pos); - amd64_mov_membase_reg (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, stack_args)), AMD64_RAX, SIZEOF_VOID_P); - for (i = 0; i < sig->param_count; ++i) { -/* Need to call stackval_from_data (MonoType *type, stackval *result, char *data, gboolean pinvoke); */ - amd64_mov_reg_imm (p, AMD64_R11, stackval_from_data); - amd64_mov_reg_imm (p, int_arg_regs[0], sig->params[i]); - amd64_lea_membase (p, int_arg_regs[1], AMD64_RBP, stackval_pos); - amd64_lea_membase (p, int_arg_regs[2], AMD64_RBP, rbpoffsets[i]); - amd64_mov_reg_imm (p, int_arg_regs[3], sig->pinvoke); - amd64_call_reg (p, AMD64_R11); - stackval_pos += sizeof (stackval); -#if 0 - /* fixme: alignment */ - if (sig->pinvoke) - arg_pos += mono_type_native_stack_size (sig->params [i], &align); - else - arg_pos += mono_type_stack_size (sig->params [i], &align); -#endif - } - - /* - * Handle the return value storage area. - */ - amd64_lea_membase (p, AMD64_RAX, AMD64_RBP, stackval_pos); - amd64_mov_membase_reg (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, retval)), AMD64_RAX, SIZEOF_VOID_P); - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - amd64_mov_reg_membase (p, AMD64_RCX, AMD64_RBP, retval_ptr_rbp_offset, SIZEOF_VOID_P); - amd64_mov_membase_reg (p, AMD64_RBP, stackval_pos, AMD64_RCX, SIZEOF_VOID_P); - } - } - - /* - * Call the method. - */ - amd64_lea_membase (p, int_arg_regs[0], AMD64_RBP, mono_invocation_pos); - amd64_mov_reg_imm (p, AMD64_R11, ves_exec_method); - amd64_call_reg (p, AMD64_R11); - - /* - * Move the return value to the proper place. - */ - amd64_lea_membase (p, AMD64_RAX, AMD64_RBP, stackval_pos); - if (sig->ret->byref) { - amd64_mov_reg_membase (p, AMD64_RAX, AMD64_RAX, 0, SIZEOF_VOID_P); - } else { - int simpletype = sig->ret->type; - enum_retvalue: - switch (sig->ret->type) { - case MONO_TYPE_VOID: - break; - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - amd64_movzx_reg_membase (p, AMD64_RAX, AMD64_RAX, 0, 1); - break; - case MONO_TYPE_CHAR: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - amd64_movzx_reg_membase (p, AMD64_RAX, AMD64_RAX, 0, 2); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_CLASS: - amd64_movzx_reg_membase (p, AMD64_RAX, AMD64_RAX, 0, 4); - break; - case MONO_TYPE_I8: - amd64_movzx_reg_membase (p, AMD64_RAX, AMD64_RAX, 0, 8); - break; - case MONO_TYPE_R4: - amd64_movss_regp_reg (p, AMD64_RAX, AMD64_XMM0); - break; - case MONO_TYPE_R8: - amd64_movsd_regp_reg (p, AMD64_RAX, AMD64_XMM0); - break; - case MONO_TYPE_VALUETYPE: { - int size; - int arg_type; - int regs_used; - int offset1; - int size1; - int offset2; - int size2; - - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - - arg_type = value_type_info(sig->params [i]->data.klass, &size, ®s_used, &offset1, &size1, &offset2, &size2); - - if (arg_type == ARG_IN_INT_REGS) - { - if (regs_used > 1) - amd64_mov_membase_reg (p, AMD64_RAX, offset2, AMD64_RDX, size2); - amd64_mov_membase_reg (p, AMD64_RAX, offset1, AMD64_RAX, size1); - break; - } - - if (arg_type == ARG_IN_FLOAT_REGS) - { - if (size1 == 4) - amd64_movss_membase_reg (p, AMD64_RAX, offset1, AMD64_XMM0); - else - amd64_movsd_membase_reg (p, AMD64_RAX, offset1, AMD64_XMM0); - - if (regs_used > 1) - { - if (size2 == 4) - amd64_movss_membase_reg (p, AMD64_RAX, offset2, AMD64_XMM1); - else - amd64_movsd_membase_reg (p, AMD64_RAX, offset2, AMD64_XMM1); - } - break; - } - - /* Else result should have been stored in place already. IA32 code has a stackval_to_data call here, which - * looks wrong to me as the pointer in the stack val being converted is setup to point to the output area anyway. - * It all looks a bit suspect anyway. - */ - break; - } - default: - g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type); - break; - } - } - - /* - * Standard epilog. - */ - amd64_leave (p); - amd64_ret (p); - - g_assert (p - code_buffer < 512); - - ji = g_new0 (MonoJitInfo, 1); - ji->method = method; - ji->code_size = p - code_buffer; - ji->code_start = g_memdup (code_buffer, p - code_buffer); - - mono_jit_info_table_add (mono_get_root_domain (), ji); - - return ji->code_start; -} diff --git a/mono/arch/ppc/Makefile.am b/mono/arch/ppc/Makefile.am index 667ad258d73..9b209ef9400 100644 --- a/mono/arch/ppc/Makefile.am +++ b/mono/arch/ppc/Makefile.am @@ -1,7 +1 @@ -AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) - -noinst_LTLIBRARIES = libmonoarch-ppc.la - -libmonoarch_ppc_la_SOURCES = tramp.c ppc-codegen.h - -noinst_PROGRAMS = test +EXTRA_DIST = ppc-codegen.h \ No newline at end of file diff --git a/mono/arch/ppc/test.c b/mono/arch/ppc/test.c deleted file mode 100644 index c19358dcab0..00000000000 --- a/mono/arch/ppc/test.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "ppc-codegen.h" -#include - -/* don't run the resulting program, it will destroy your computer, - * just objdump -d it to inspect we generated the correct assembler. - * On Mac OS X use otool[64] -v -t - */ - -int main() { - guint8 code [16000]; - guint8 *p = code; - guint8 *cp; - - printf (".text\n.align 4\n.globl main\n"); -#ifndef __APPLE__ - printf (".type main,@function\n"); -#endif - printf ("main:\n"); - - ppc_stwu (p, ppc_r1, -32, ppc_r1); - ppc_mflr (p, ppc_r0); - ppc_stw (p, ppc_r31, 28, ppc_r1); - ppc_or (p, ppc_r1, ppc_r2, ppc_r3); - ppc_mr (p, ppc_r31, ppc_r1); - ppc_lwz (p, ppc_r11, 0, ppc_r1); - ppc_mtlr (p, ppc_r0); - ppc_blr (p); - ppc_addi (p, ppc_r6, ppc_r6, 16); - - for (cp = code; cp < p; cp++) { - printf (".byte 0x%x\n", *cp); - } - - return 0; -} diff --git a/mono/arch/ppc/tramp.c b/mono/arch/ppc/tramp.c deleted file mode 100644 index 6bb1896255f..00000000000 --- a/mono/arch/ppc/tramp.c +++ /dev/null @@ -1,895 +0,0 @@ -/* - * Create trampolines to invoke arbitrary functions. - * - * Copyright (C) Radek Doulik - * - */ - -#include "config.h" -#include -#include -#include "ppc-codegen.h" -#include "mono/metadata/class.h" -#include "mono/metadata/tabledefs.h" -#include "mono/interpreter/interp.h" -#include "mono/metadata/appdomain.h" - -#ifdef NEED_MPROTECT -#include -#include /* for PAGESIZE */ -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif -#endif - -#define DEBUG(x) - -/* gpointer -fake_func (gpointer (*callme)(gpointer), stackval *retval, void *this_obj, stackval *arguments) -{ - guint32 i = 0xc002becd; - - callme = (gpointer) 0x100fabcd; - - *(gpointer*)retval = (gpointer)(*callme) (arguments [0].data.p, arguments [1].data.p, arguments [2].data.p); - *(gdouble*) retval = (gdouble)(*callme) (arguments [0].data.f); - - return (gpointer) (*callme) (((MonoType *)arguments [0]. data.p)->data.klass); -} */ - -#define MIN_CACHE_LINE 8 - -static void inline -flush_icache (guint8 *code, guint size) -{ - guint i; - guint8 *p; - - p = code; - for (i = 0; i < size; i += MIN_CACHE_LINE, p += MIN_CACHE_LINE) { - asm ("dcbst 0,%0;" : : "r"(p) : "memory"); - } - asm ("sync"); - p = code; - for (i = 0; i < size; i += MIN_CACHE_LINE, p += MIN_CACHE_LINE) { - asm ("icbi 0,%0; sync;" : : "r"(p) : "memory"); - } - asm ("sync"); - asm ("isync"); -} - -static void -disassemble (guint8 *code, int size) -{ - int i; - FILE *ofd; - const char *tmp = g_getenv("TMP"); - char *as_file; - char *o_file; - char *cmd; - - if (tmp == NULL) - tmp = "/tmp"; - as_file = g_strdup_printf ("%s/test.s", tmp); - - if (!(ofd = fopen (as_file, "w"))) - g_assert_not_reached (); - - fprintf (ofd, "tmp:\n"); - - for (i = 0; i < size; ++i) - fprintf (ofd, ".byte %d\n", (unsigned int) code [i]); - - fclose (ofd); -#ifdef __APPLE__ -#define DIS_CMD "otool -V -v -t" -#else -#define DIS_CMD "objdump -d" -#endif - o_file = g_strdup_printf ("%s/test.o", tmp); - cmd = g_strdup_printf ("as %s -o %s", as_file, o_file); - system (cmd); - g_free (cmd); - cmd = g_strdup_printf (DIS_CMD " %s", o_file); - system (cmd); - g_free (cmd); - g_free (o_file); - g_free (as_file); -} - - -#define NOT_IMPLEMENTED(x) \ - g_error ("FIXME: %s is not yet implemented. (trampoline)", x); - -#define PROLOG_INS 8 -#define CALL_INS 2 -#define EPILOG_INS 6 -#define FLOAT_REGS 8 -#define GENERAL_REGS 8 -#ifdef __APPLE__ -#define MINIMAL_STACK_SIZE 10 -#define ALWAYS_ON_STACK(s) s -#define FP_ALSO_IN_REG(s) s -#define RET_ADDR_OFFSET 8 -#define STACK_PARAM_OFFSET 24 -#else -#define MINIMAL_STACK_SIZE 5 -#define ALWAYS_ON_STACK(s) -#define FP_ALSO_IN_REG(s) s -#define ALIGN_DOUBLES -#define RET_ADDR_OFFSET 4 -#define STACK_PARAM_OFFSET 8 -#endif - -static void inline -add_general (guint *gr, guint *stack_size, guint *code_size, gboolean simple) -{ - if (simple) { - if (*gr >= GENERAL_REGS) { - *stack_size += 4; - *code_size += 8; /* load from stack, save on stack */ - } else { - ALWAYS_ON_STACK (*stack_size += 4); - *code_size += 4; /* load from stack */ - } - } else { - if (*gr >= GENERAL_REGS - 1) { - *stack_size += 8; -#ifdef ALIGN_DOUBLES - *stack_size += (*stack_size % 8); -#endif - *code_size += 16; /* 2x load from stack, 2x save to stack */ - } else { - ALWAYS_ON_STACK (*stack_size += 8); - *code_size += 8; /* 2x load from stack */ - } -#ifdef ALIGN_DOUBLES - if ((*gr) & 1) - (*gr) ++; -#endif - (*gr) ++; - } - (*gr) ++; -} - -static void inline -calculate_sizes (MonoMethodSignature *sig, guint *stack_size, guint *code_size, gboolean string_ctor, gboolean *use_memcpy) -{ - guint i, fr, gr; - guint32 simpletype; - - fr = gr = 0; - *stack_size = MINIMAL_STACK_SIZE*4; - *code_size = (PROLOG_INS + CALL_INS + EPILOG_INS)*4; - - if (sig->hasthis) { - add_general (&gr, stack_size, code_size, TRUE); - } - DEBUG(printf("params: %d\n", sig->param_count)); - for (i = 0; i < sig->param_count; ++i) { - DEBUG(printf("param %d: ", i)); - if (sig->params [i]->byref) { - DEBUG(printf("byref\n")); - add_general (&gr, stack_size, code_size, TRUE); - continue; - } - simpletype = sig->params [i]->type; - enum_calc_size: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - add_general (&gr, stack_size, code_size, TRUE); - break; - case MONO_TYPE_SZARRAY: - add_general (&gr, stack_size, code_size, TRUE); - *code_size += 4; - break; - case MONO_TYPE_VALUETYPE: { - gint size; - if (sig->params [i]->data.klass->enumtype) { - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_calc_size; - } - size = mono_class_value_size (sig->params [i]->data.klass, NULL); - if (size != 4) { - DEBUG(printf ("copy %d bytes struct on stack\n", - mono_class_value_size (sig->params [i]->data.klass, NULL))); - *use_memcpy = TRUE; - *code_size += 8*4; - *stack_size += (size + 3) & (~3); - if (gr > GENERAL_REGS) { - *code_size += 4; - *stack_size += 4; - } - } else { - DEBUG(printf ("load %d bytes struct\n", - mono_class_value_size (sig->params [i]->data.klass, NULL))); - add_general (&gr, stack_size, code_size, TRUE); - *code_size += 4; - } - break; - } - case MONO_TYPE_I8: - add_general (&gr, stack_size, code_size, FALSE); - break; - case MONO_TYPE_R4: - if (fr < 7) { - *code_size += 4; - fr ++; - FP_ALSO_IN_REG (gr ++); - ALWAYS_ON_STACK (*stack_size += 4); - } else { - NOT_IMPLEMENTED ("R4 arg"); - } - break; - case MONO_TYPE_R8: - if (fr < 7) { - *code_size += 4; - fr ++; - FP_ALSO_IN_REG (gr += 2); - ALWAYS_ON_STACK (*stack_size += 8); - } else { - NOT_IMPLEMENTED ("R8 arg"); - } - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - - if (sig->ret->byref || string_ctor) { - *code_size += 8; - } else { - simpletype = sig->ret->type; -enum_retvalue: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_R4: - case MONO_TYPE_R8: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: - case MONO_TYPE_STRING: - *code_size += 8; - break; - case MONO_TYPE_I8: - *code_size += 12; - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - *code_size += 2*4; - break; - case MONO_TYPE_VOID: - break; - default: - g_error ("Can't handle as return value 0x%x", sig->ret->type); - } - } - - if (*use_memcpy) { - *stack_size += 2*4; /* for r14, r15 */ - *code_size += 6*4; - if (sig->hasthis) { - *stack_size += 4; /* for r16 */ - *code_size += 4; - } - } - - /* align stack size to 16 */ - DEBUG (printf (" stack size: %d (%d)\n code size: %d\n", (*stack_size + 15) & ~15, *stack_size, *code_size)); - *stack_size = (*stack_size + 15) & ~15; -} - -static inline guint8 * -emit_prolog (guint8 *p, MonoMethodSignature *sig, guint stack_size) -{ - /* function prolog */ - ppc_stwu (p, ppc_r1, -stack_size, ppc_r1); /* sp <--- sp - stack_size, sp[0] <---- sp save sp, alloc stack */ - ppc_mflr (p, ppc_r0); /* r0 <--- LR */ - ppc_stw (p, ppc_r31, stack_size - 4, ppc_r1); /* sp[+4] <--- r31 save r31 */ - ppc_stw (p, ppc_r0, stack_size + RET_ADDR_OFFSET, ppc_r1); /* sp[-4] <--- LR save return address for "callme" */ - ppc_mr (p, ppc_r31, ppc_r1); /* r31 <--- sp */ - - return p; -} - -#define ARG_BASE ppc_r12 -#define ARG_SIZE sizeof (stackval) -#define SAVE_4_IN_GENERIC_REGISTER \ - if (gr < GENERAL_REGS) { \ - ppc_lwz (p, ppc_r3 + gr, i*ARG_SIZE, ARG_BASE); \ - gr ++; \ - ALWAYS_ON_STACK (stack_par_pos += 4); \ - } else { \ - ppc_lwz (p, ppc_r11, i*ARG_SIZE, ARG_BASE); \ - ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); \ - stack_par_pos += 4; \ - } -#define SAVE_4_VAL_IN_GENERIC_REGISTER \ - if (gr < GENERAL_REGS) { \ - ppc_lwz (p, ppc_r3 + gr, i*ARG_SIZE, ARG_BASE); \ - ppc_lwz (p, ppc_r3 + gr, 0, ppc_r3 + gr); \ - gr ++; \ - ALWAYS_ON_STACK (stack_par_pos += 4); \ - } else { \ - ppc_lwz (p, ppc_r11, i*ARG_SIZE, ARG_BASE); \ - ppc_lwz (p, ppc_r11, 0, ppc_r11); \ - ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); \ - stack_par_pos += 4; \ - } - -inline static guint8* -emit_save_parameters (guint8 *p, MonoMethodSignature *sig, guint stack_size, gboolean use_memcpy) -{ - guint i, fr, gr, stack_par_pos, struct_pos, cur_struct_pos; - guint32 simpletype; - - fr = gr = 0; - stack_par_pos = STACK_PARAM_OFFSET; - - ppc_stw (p, ppc_r4, stack_size - 12, ppc_r31); /* preserve "retval", sp[+8] */ - - if (use_memcpy) { - ppc_stw (p, ppc_r14, stack_size - 16, ppc_r31); /* save r14 */ - ppc_stw (p, ppc_r15, stack_size - 20, ppc_r31); /* save r15 */ - ppc_mr (p, ppc_r14, ppc_r3); /* keep "callme" in register */ - ppc_mr (p, ppc_r15, ppc_r6); /* keep "arguments" in register */ - } else { - ppc_mr (p, ppc_r12, ppc_r6); /* keep "arguments" in register */ - ppc_mr (p, ppc_r0, ppc_r3); /* keep "callme" in register */ - } - - if (sig->hasthis) { - if (use_memcpy) { - ppc_stw (p, ppc_r16, stack_size - 24, ppc_r31); /* save r16 */ - ppc_mr (p, ppc_r16, ppc_r5); - } else - ppc_mr (p, ppc_r3, ppc_r5); - gr ++; - ALWAYS_ON_STACK (stack_par_pos += 4); - } - - if (use_memcpy) { - cur_struct_pos = struct_pos = stack_par_pos; - for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) - continue; - if (sig->params [i]->type == MONO_TYPE_VALUETYPE && !sig->params [i]->data.klass->enumtype) { - gint size; - - size = mono_class_value_size (sig->params [i]->data.klass, NULL); - if (size != 4) { - /* call memcpy */ - ppc_addi (p, ppc_r3, ppc_r1, stack_par_pos); - ppc_lwz (p, ppc_r4, i*16, ppc_r15); - /* FIXME check if size > 0xffff */ - ppc_li (p, ppc_r5, size & 0xffff); - ppc_lis (p, ppc_r0, (guint32) memcpy >> 16); - ppc_ori (p, ppc_r0, ppc_r0, (guint32) memcpy & 0xffff); - ppc_mtlr (p, ppc_r0); - ppc_blrl (p); - stack_par_pos += (size + 3) & (~3); - } - } - } - - if (sig->hasthis) { - ppc_mr (p, ppc_r3, ppc_r16); - ppc_lwz (p, ppc_r16, stack_size - 24, ppc_r31); /* restore r16 */ - } - ppc_mr (p, ppc_r0, ppc_r14); - ppc_mr (p, ppc_r12, ppc_r15); - ppc_lwz (p, ppc_r14, stack_size - 16, ppc_r31); /* restore r14 */ - ppc_lwz (p, ppc_r15, stack_size - 20, ppc_r31); /* restore r15 */ - } - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - gint size = mono_class_native_size (klass, NULL); - - DEBUG(printf ("retval value type size: %d\n", size)); - if (size > 8) { - ppc_lwz (p, ppc_r3, stack_size - 12, ppc_r31); - ppc_lwz (p, ppc_r3, 0, ppc_r3); - gr ++; - ALWAYS_ON_STACK (stack_par_pos += 4); - } else { - NOT_IMPLEMENTED ("retval valuetype <= 8 bytes"); - } - } - } - - for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) { - SAVE_4_IN_GENERIC_REGISTER; - continue; - } - simpletype = sig->params [i]->type; - enum_calc_size: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_SZARRAY: - SAVE_4_IN_GENERIC_REGISTER; - break; - case MONO_TYPE_VALUETYPE: { - gint size; - if (sig->params [i]->data.klass->enumtype) { - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_calc_size; - } - size = mono_class_value_size (sig->params [i]->data.klass, NULL); - if (size == 4) { - SAVE_4_VAL_IN_GENERIC_REGISTER; - } else { - if (gr < GENERAL_REGS) { - ppc_addi (p, ppc_r3 + gr, ppc_r1, cur_struct_pos); - gr ++; - } else { - ppc_lwz (p, ppc_r11, cur_struct_pos, ppc_r1); - ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); - stack_par_pos += 4; - } - cur_struct_pos += (size + 3) & (~3); - } - break; - } - case MONO_TYPE_I8: -DEBUG(printf("Mono_Type_i8. gr = %d, arg_base = %d\n", gr, ARG_BASE)); -#ifdef ALIGN_DOUBLES - if (gr & 1) - gr++; -#endif - if (gr < 7) { - ppc_lwz (p, ppc_r3 + gr, i*ARG_SIZE, ARG_BASE); - ppc_lwz (p, ppc_r3 + gr + 1, i*ARG_SIZE + 4, ARG_BASE); - ALWAYS_ON_STACK (stack_par_pos += 8); - } else if (gr == 7) { - ppc_lwz (p, ppc_r3 + gr, i*ARG_SIZE, ARG_BASE); - ppc_lwz (p, ppc_r11, i*ARG_SIZE + 4, ARG_BASE); - ppc_stw (p, ppc_r11, stack_par_pos + 4, ppc_r1); - stack_par_pos += 8; - } else { - ppc_lwz (p, ppc_r11, i*ARG_SIZE, ARG_BASE); - ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); - ppc_lwz (p, ppc_r11, i*ARG_SIZE + 4, ARG_BASE); - ppc_stw (p, ppc_r11, stack_par_pos + 4, ppc_r1); - stack_par_pos += 8; - } - gr += 2; - break; - case MONO_TYPE_R4: - if (fr < 7) { - ppc_lfs (p, ppc_f1 + fr, i*ARG_SIZE, ARG_BASE); - fr ++; - FP_ALSO_IN_REG (gr ++); - ALWAYS_ON_STACK (stack_par_pos += 4); - } else { - NOT_IMPLEMENTED ("r4 on stack"); - } - break; - case MONO_TYPE_R8: - if (fr < 7) { - ppc_lfd (p, ppc_f1 + fr, i*ARG_SIZE, ARG_BASE); - fr ++; - FP_ALSO_IN_REG (gr += 2); - ALWAYS_ON_STACK (stack_par_pos += 8); - } else { - NOT_IMPLEMENTED ("r8 on stack"); - } - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - - return p; -} - -static inline guint8 * -alloc_code_memory (guint code_size) -{ - guint8 *p; - -#ifdef NEED_MPROTECT - p = g_malloc (code_size + PAGESIZE - 1); - - /* Align to a multiple of PAGESIZE, assumed to be a power of two */ - p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1)); -#else - p = g_malloc (code_size); -#endif - DEBUG (printf (" align: %p (%d)\n", p, (guint)p % 4)); - - return p; -} - -/* static MonoString* -mono_string_new_wrapper (const char *text) -{ - return text ? mono_string_new (mono_domain_get (), text) : NULL; -} */ - -static inline guint8 * -emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig, guint stack_size, gboolean string_ctor) -{ - guint32 simpletype; - - /* call "callme" */ - ppc_mtlr (p, ppc_r0); - ppc_blrl (p); - - /* get return value */ - if (sig->ret->byref || string_ctor) { - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */ - } else { - simpletype = sig->ret->type; -enum_retvalue: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stb (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */ - break; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_sth (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */ - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: - case MONO_TYPE_STRING: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */ - break; - case MONO_TYPE_R4: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stfs (p, ppc_f1, 0, ppc_r9); /* save return value (f1) to "retval" */ - break; - case MONO_TYPE_R8: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stfd (p, ppc_f1, 0, ppc_r9); /* save return value (f1) to "retval" */ - break; - case MONO_TYPE_I8: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */ - ppc_stw (p, ppc_r4, 4, ppc_r9); /* save return value (r3) to "retval" */ - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - break; - case MONO_TYPE_VOID: - break; - default: - g_error ("Can't handle as return value 0x%x", sig->ret->type); - } - } - - return p; -} - -static inline guint8 * -emit_epilog (guint8 *p, MonoMethodSignature *sig, guint stack_size) -{ - /* function epilog */ - ppc_lwz (p, ppc_r11, 0, ppc_r1); /* r11 <--- sp[0] load backchain from caller's function */ - ppc_lwz (p, ppc_r0, RET_ADDR_OFFSET, ppc_r11); /* r0 <--- r11[4] load return address */ - ppc_mtlr (p, ppc_r0); /* LR <--- r0 set return address */ - ppc_lwz (p, ppc_r31, -4, ppc_r11); /* r31 <--- r11[-4] restore r31 */ - ppc_mr (p, ppc_r1, ppc_r11); /* sp <--- r11 restore stack */ - ppc_blr (p); /* return */ - - return p; -} - -MonoPIFunc -mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor) -{ - guint8 *p, *code_buffer; - guint stack_size, code_size; - gboolean use_memcpy = FALSE; - - DEBUG (printf ("\nPInvoke [start emiting]\n")); - calculate_sizes (sig, &stack_size, &code_size, string_ctor, &use_memcpy); - - p = code_buffer = alloc_code_memory (code_size); - p = emit_prolog (p, sig, stack_size); - p = emit_save_parameters (p, sig, stack_size, use_memcpy); - p = emit_call_and_store_retval (p, sig, stack_size, string_ctor); - p = emit_epilog (p, sig, stack_size); - - /* { - guchar *cp; - printf (".text\n.align 4\n.globl main\n.type main,@function\nmain:\n"); - for (cp = code_buffer; cp < p; cp++) { - printf (".byte 0x%x\n", *cp); - } - } */ - -#ifdef NEED_MPROTECT - if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) { - g_error ("Cannot mprotect trampoline\n"); - } -#endif - - DEBUG (printf ("emited code size: %d\n", p - code_buffer)); - flush_icache (code_buffer, p - code_buffer); - - DEBUG (printf ("PInvoke [end emiting]\n")); - - return (MonoPIFunc) code_buffer; - /* return fake_func; */ -} - - -#ifdef __APPLE__ -#define MINV_POS 40 /* MonoInvocation structure offset on stack - STACK_PARAM_OFFSET + 4 pointer args for stackval_from_data */ -#else -#define MINV_POS 8 /* MonoInvocation structure offset on stack */ -#endif -#define STACK_POS (MINV_POS - sizeof (stackval) * sig->param_count) -#define OBJ_POS 8 -#define TYPE_OFFSET (G_STRUCT_OFFSET (stackval, type)) - -/* - * Returns a pointer to a native function that can be used to - * call the specified method. - * The function created will receive the arguments according - * to the call convention specified in the method. - * This function works by creating a MonoInvocation structure, - * filling the fields in and calling ves_exec_method on it. - * Still need to figure out how to handle the exception stuff - * across the managed/unmanaged boundary. - */ -void * -mono_arch_create_method_pointer (MonoMethod *method) -{ - MonoMethodSignature *sig; - MonoJitInfo *ji; - guint8 *p, *code_buffer; - guint i, align = 0, code_size, stack_size, stackval_arg_pos, local_pos, local_start, reg_param = 0, stack_param, - cpos, vt_cur; - gint *vtbuf; - guint32 simpletype; - - code_size = 1024; - stack_size = 1024; - stack_param = 0; - - sig = mono_method_signature (method); - - p = code_buffer = g_malloc (code_size); - - DEBUG (printf ("\nDelegate [start emiting] %s\n", mono_method_get_name (method))); - - /* prolog */ - ppc_stwu (p, ppc_r1, -stack_size, ppc_r1); /* sp <--- sp - stack_size, sp[0] <---- sp save sp, alloc stack */ - ppc_mflr (p, ppc_r0); /* r0 <--- LR */ - ppc_stw (p, ppc_r31, stack_size - 4, ppc_r1); /* sp[+4] <--- r31 save r31 */ - ppc_stw (p, ppc_r0, stack_size + RET_ADDR_OFFSET, ppc_r1); /* sp[-4] <--- LR save return address for "callme" */ - ppc_mr (p, ppc_r31, ppc_r1); /* r31 <--- sp */ - - /* let's fill MonoInvocation */ - /* first zero some fields */ - ppc_li (p, ppc_r0, 0); - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)), ppc_r31); - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)), ppc_r31); - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)), ppc_r31); - - /* set method pointer */ - ppc_lis (p, ppc_r0, (guint32) method >> 16); - ppc_ori (p, ppc_r0, ppc_r0, (guint32) method & 0xffff); - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)), ppc_r31); - - local_start = local_pos = MINV_POS + sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval); - - if (sig->hasthis) { - ppc_stw (p, ppc_r3, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)), ppc_r31); - reg_param = 1; - } - - if (sig->param_count) { - gint save_count = MIN (8, sig->param_count + sig->hasthis); - for (i = reg_param; i < save_count; i ++) { - ppc_stw (p, ppc_r3 + i, local_pos, ppc_r31); - local_pos += 4; - DEBUG (printf ("save r%d\n", 4 + i)); - } - } - - /* prepare space for valuetypes */ - vt_cur = local_pos; - vtbuf = alloca (sizeof(int)*sig->param_count); - cpos = 0; - for (i = 0; i < sig->param_count; i++) { - MonoType *type = sig->params [i]; - vtbuf [i] = -1; - if (type->type == MONO_TYPE_VALUETYPE) { - MonoClass *klass = type->data.klass; - gint size; - - if (klass->enumtype) - continue; - size = mono_class_native_size (klass, &align); - cpos += align - 1; - cpos &= ~(align - 1); - vtbuf [i] = cpos; - cpos += size; - } - } - cpos += 3; - cpos &= ~3; - - local_pos += cpos; - - /* set MonoInvocation::stack_args */ - stackval_arg_pos = MINV_POS + sizeof (MonoInvocation); - ppc_addi (p, ppc_r0, ppc_r31, stackval_arg_pos); - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)), ppc_r31); - - /* add stackval arguments */ - for (i = 0; i < sig->param_count; ++i) { - if (reg_param < 8) { - ppc_addi (p, ppc_r5, ppc_r31, local_start + i*4); - reg_param ++; - } else { - ppc_addi (p, ppc_r5, stack_size + 8 + stack_param, ppc_r31); - stack_param ++; - } - ppc_lis (p, ppc_r3, (guint32) sig->params [i] >> 16); - - if (vtbuf [i] >= 0) { - ppc_addi (p, ppc_r4, ppc_r31, vt_cur); - ppc_stw (p, ppc_r4, stackval_arg_pos, ppc_r31); - ppc_addi (p, ppc_r4, ppc_r31, stackval_arg_pos); - ppc_lwz (p, ppc_r5, 0, ppc_r5); - vt_cur += vtbuf [i]; - } else { - ppc_addi (p, ppc_r4, ppc_r31, stackval_arg_pos); - } - ppc_ori (p, ppc_r3, ppc_r3, (guint32) sig->params [i] & 0xffff); - ppc_lis (p, ppc_r0, (guint32) stackval_from_data >> 16); - ppc_li (p, ppc_r6, sig->pinvoke); - ppc_ori (p, ppc_r0, ppc_r0, (guint32) stackval_from_data & 0xffff); - ppc_mtlr (p, ppc_r0); - ppc_blrl (p); - - stackval_arg_pos += sizeof (stackval); - } - - /* return value storage */ - if (sig->param_count) { - ppc_addi (p, ppc_r0, ppc_r31, stackval_arg_pos); - } - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)), ppc_r31); - - /* call ves_exec_method */ - ppc_lis (p, ppc_r0, (guint32) ves_exec_method >> 16); - ppc_addi (p, ppc_r3, ppc_r31, MINV_POS); - ppc_ori (p, ppc_r0, ppc_r0, (guint32) ves_exec_method & 0xffff); - ppc_mtlr (p, ppc_r0); - ppc_blrl (p); - - /* move retval from stackval to proper place (r3/r4/...) */ - if (sig->ret->byref) { - DEBUG (printf ("ret by ref\n")); - ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31); - } else { - enum_retvalue: - switch (sig->ret->type) { - case MONO_TYPE_VOID: - break; - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - ppc_lbz (p, ppc_r3, stackval_arg_pos, ppc_r31); - break; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - ppc_lhz (p, ppc_r3, stackval_arg_pos, ppc_r31); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_CLASS: - ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31); - break; - case MONO_TYPE_I8: - ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31); - ppc_lwz (p, ppc_r4, stackval_arg_pos + 4, ppc_r31); - break; - case MONO_TYPE_R4: - ppc_lfs (p, ppc_f1, stackval_arg_pos, ppc_r31); - break; - case MONO_TYPE_R8: - ppc_lfd (p, ppc_f1, stackval_arg_pos, ppc_r31); - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - NOT_IMPLEMENTED ("value type as ret val from delegate"); - break; - default: - g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type); - break; - } - } - - /* epilog */ - ppc_lwz (p, ppc_r11, 0, ppc_r1); /* r11 <--- sp[0] load backchain from caller's function */ - ppc_lwz (p, ppc_r0, RET_ADDR_OFFSET, ppc_r11); /* r0 <--- r11[4] load return address */ - ppc_mtlr (p, ppc_r0); /* LR <--- r0 set return address */ - ppc_lwz (p, ppc_r31, -4, ppc_r11); /* r31 <--- r11[-4] restore r31 */ - ppc_mr (p, ppc_r1, ppc_r11); /* sp <--- r11 restore stack */ - ppc_blr (p); /* return */ - - DEBUG (printf ("emited code size: %d\n", p - code_buffer)); - DEBUG (disassemble (code_buffer, p - code_buffer)); - flush_icache (code_buffer, p - code_buffer); - - DEBUG (printf ("Delegate [end emiting]\n")); - - ji = g_new0 (MonoJitInfo, 1); - ji->method = method; - ji->code_size = p - code_buffer; - ji->code_start = code_buffer; - - mono_jit_info_table_add (mono_get_root_domain (), ji); - - return ji->code_start; -} diff --git a/mono/arch/x86/Makefile.am b/mono/arch/x86/Makefile.am index e88506e4cd8..bab0f9e54d6 100644 --- a/mono/arch/x86/Makefile.am +++ b/mono/arch/x86/Makefile.am @@ -1,5 +1 @@ -AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) - -noinst_LTLIBRARIES = libmonoarch-x86.la - -libmonoarch_x86_la_SOURCES = tramp.c x86-codegen.h +EXTRA_DIST = x86-codegen.h \ No newline at end of file diff --git a/mono/arch/x86/test.c b/mono/arch/x86/test.c deleted file mode 100644 index 3511e8fdaf0..00000000000 --- a/mono/arch/x86/test.c +++ /dev/null @@ -1,225 +0,0 @@ -#include "x86-codegen.h" -#include - -/* don't run the resulting program, it will destroy your computer, - * just objdump -d it to inspect we generated the correct assembler. - */ - -int main() { - unsigned char code [16000]; - unsigned char *p = code; - unsigned char *target, *start, *end; - unsigned long mem_addr = 0xdeadbeef; - int size, i; - - printf (".text\n.align 4\n.globl main\n.type main,@function\nmain:\n"); - - x86_prolog (p, 16, X86_CALLER_REGS); - - x86_cmpxchg_reg_reg (p, X86_EAX, X86_EBP); - x86_cmpxchg_membase_reg (p, X86_EAX, 12, X86_EBP); - - x86_xchg_reg_reg (p, X86_EAX, X86_EBP, 4); - x86_xchg_reg_reg (p, X86_EAX, X86_EBP, 1); // FIXME? - x86_xchg_membase_reg (p, X86_EAX, 12, X86_EBP, 4); - x86_xchg_membase_reg (p, X86_EAX, 12, X86_EBP, 2); - x86_xchg_membase_reg (p, X86_EAX, 12, X86_EBX, 1); // FIXME? - - x86_inc_reg (p, X86_EAX); - x86_inc_mem (p, mem_addr); - x86_inc_membase (p, X86_ESP, 4); - - x86_nop (p); - x86_nop (p); - - x86_dec_reg (p, X86_EAX); - x86_dec_reg (p, X86_ECX); - x86_dec_mem (p, mem_addr); - x86_dec_membase (p, X86_ESP, 4); - - x86_not_reg (p, X86_EDX); - x86_not_reg (p, X86_ECX); - x86_not_mem (p, mem_addr); - x86_not_membase (p, X86_ESP, 4); - x86_not_membase (p, X86_ESP, 0x4444444); - x86_not_membase (p, X86_EBP, 0x4444444); - x86_not_membase (p, X86_ECX, 0x4444444); - x86_not_membase (p, X86_EDX, 0); - x86_not_membase (p, X86_EBP, 0); - - x86_neg_reg (p, X86_EAX); - x86_neg_reg (p, X86_ECX); - x86_neg_mem (p, mem_addr); - x86_neg_membase (p, X86_ESP, 8); - - x86_alu_reg_imm (p, X86_ADD, X86_EAX, 5); - x86_alu_reg_imm (p, X86_ADD, X86_EBX, -10); - x86_alu_reg_imm (p, X86_SUB, X86_EDX, 7); - x86_alu_reg_imm (p, X86_OR, X86_ESP, 0xffffedaf); - x86_alu_reg_imm (p, X86_CMP, X86_ECX, 1); - x86_alu_mem_imm (p, X86_ADC, mem_addr, 2); - x86_alu_membase_imm (p, X86_ADC, X86_ESP, -4, 4); - x86_alu_membase_imm (p, X86_ADC, X86_ESP, -12, 0xffffedaf); - - x86_alu_mem_reg (p, X86_SUB, mem_addr, X86_EDX); - x86_alu_reg_reg (p, X86_ADD, X86_EAX, X86_EBX); - x86_alu_reg_mem (p, X86_ADD, X86_EAX, mem_addr); - x86_alu_reg_imm (p, X86_ADD, X86_EAX, 0xdeadbeef); - x86_alu_reg_membase (p, X86_XOR, X86_EDX, X86_ESP, 4); - x86_alu_membase_reg (p, X86_XOR, X86_EBP, 8, X86_ESI); - - x86_test_reg_imm (p, X86_EAX, 16); - x86_test_reg_imm (p, X86_EDX, -16); - x86_test_mem_imm (p, mem_addr, 1); - x86_test_membase_imm (p, X86_EBP, 8, 1); - - x86_test_reg_reg (p, X86_EAX, X86_EDX); - x86_test_mem_reg (p, mem_addr, X86_EDX); - x86_test_membase_reg (p, X86_ESI, 4, X86_EDX); - - x86_shift_reg_imm (p, X86_SHL, X86_EAX, 1); - x86_shift_reg_imm (p, X86_SHL, X86_EDX, 2); - - x86_shift_mem_imm (p, X86_SHL, mem_addr, 2); - x86_shift_membase_imm (p, X86_SHLR, X86_EBP, 8, 4); - - /* - * Shift by CL - */ - x86_shift_reg (p, X86_SHL, X86_EAX); - x86_shift_mem (p, X86_SHL, mem_addr); - - x86_mul_reg (p, X86_EAX, 0); - x86_mul_reg (p, X86_EAX, 1); - x86_mul_membase (p, X86_EBP, 8, 1); - - x86_imul_reg_reg (p, X86_EBX, X86_EDX); - x86_imul_reg_membase (p, X86_EBX, X86_EBP, 12); - - x86_imul_reg_reg_imm (p, X86_EBX, X86_EDX, 10); - x86_imul_reg_mem_imm (p, X86_EBX, mem_addr, 20); - x86_imul_reg_membase_imm (p, X86_EBX, X86_EBP, 16, 300); - - x86_div_reg (p, X86_EDX, 0); - x86_div_reg (p, X86_EDX, 1); - x86_div_mem (p, mem_addr, 1); - x86_div_membase (p, X86_ESI, 4, 1); - - x86_mov_mem_reg (p, mem_addr, X86_EAX, 4); - x86_mov_mem_reg (p, mem_addr, X86_EAX, 2); - x86_mov_mem_reg (p, mem_addr, X86_EAX, 1); - x86_mov_membase_reg (p, X86_EBP, 4, X86_EAX, 1); - - x86_mov_regp_reg (p, X86_EAX, X86_EAX, 4); - x86_mov_membase_reg (p, X86_EAX, 0, X86_EAX, 4); - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 4); - x86_mov_reg_memindex (p, X86_ECX, X86_EAX, 34, X86_EDX, 2, 4); - x86_mov_reg_memindex (p, X86_ECX, X86_NOBASEREG, 34, X86_EDX, 2, 4); - x86_mov_memindex_reg (p, X86_EAX, X86_EAX, 0, X86_EDX, 2, 4); - x86_mov_reg_reg (p, X86_EAX, X86_EAX, 1); - x86_mov_reg_reg (p, X86_EAX, X86_EAX, 4); - x86_mov_reg_mem (p, X86_EAX, mem_addr, 4); - - x86_mov_reg_imm (p, X86_EAX, 10); - x86_mov_mem_imm (p, mem_addr, 54, 4); - x86_mov_mem_imm (p, mem_addr, 54, 1); - - x86_lea_mem (p, X86_EDX, mem_addr); - /* test widen */ - x86_widen_memindex (p, X86_EDX, X86_ECX, 0, X86_EBX, 2, 1, 0); - - x86_cdq (p); - x86_wait (p); - - x86_fp_op_mem (p, X86_FADD, mem_addr, 1); - x86_fp_op_mem (p, X86_FSUB, mem_addr, 0); - x86_fp_op (p, X86_FSUB, 2); - x86_fp_op_reg (p, X86_FMUL, 1, 0); - x86_fstp (p, 2); - x86_fcompp (p); - x86_fnstsw (p); - x86_fnstcw (p, mem_addr); - x86_fnstcw_membase (p, X86_ESP, -8); - - x86_fldcw_membase (p, X86_ESP, -8); - x86_fchs (p); - x86_frem (p); - x86_fxch (p, 3); - x86_fcomip (p, 3); - x86_fld_membase (p, X86_ESP, -8, 1); - x86_fld_membase (p, X86_ESP, -8, 0); - x86_fld80_membase (p, X86_ESP, -8); - x86_fild_membase (p, X86_ESP, -8, 1); - x86_fild_membase (p, X86_ESP, -8, 0); - x86_fld_reg (p, 4); - x86_fldz (p); - x86_fld1 (p); - - x86_fst (p, mem_addr, 1, 0); - x86_fst (p, mem_addr, 1, 1); - x86_fst (p, mem_addr, 0, 1); - - x86_fist_pop_membase (p, X86_EDX, 4, 1); - x86_fist_pop_membase (p, X86_EDX, 4, 0); - - x86_push_reg (p, X86_EBX); - x86_push_membase (p, X86_EBP, 8); - x86_push_imm (p, -1); - x86_pop_reg (p, X86_EBX); - - x86_pushad (p); - x86_pushfd (p); - x86_popfd (p); - x86_popad (p); - - target = p; - - start = p; - x86_jump32 (p, mem_addr); - x86_patch (start, target); - start = p; - x86_jump8 (p, 12); - x86_patch (start, target); - x86_jump_reg (p, X86_EAX); - x86_jump_membase (p, X86_EDX, 16); - - x86_jump_code (p, target); - - x86_branch8 (p, X86_CC_EQ, 54, 1); - x86_branch32 (p, X86_CC_LT, 54, 0); - x86_branch (p, X86_CC_GT, target, 0); - x86_branch_disp (p, X86_CC_NE, -4, 0); - - x86_set_reg (p, X86_CC_EQ, X86_EAX, 0); - x86_set_membase (p, X86_CC_LE, X86_EBP, -8, 0); - - x86_call_code (p, printf); - x86_call_reg (p, X86_ECX); - - x86_sahf (p); - - x86_fsin (p); - x86_fcos (p); - x86_fabs (p); - x86_fpatan (p); - x86_fprem (p); - x86_fprem1 (p); - x86_frndint (p); - x86_fsqrt (p); - x86_fptan (p); - - x86_leave (p); - x86_ret (p); - x86_ret_imm (p, 24); - - x86_cmov_reg (p, X86_CC_GT, 1, X86_EAX, X86_EDX); - x86_cmov_membase (p, X86_CC_GT, 0, X86_EAX, X86_EDX, -4); - - x86_nop (p); - x86_epilog (p, X86_CALLER_REGS); - - size = p-code; - for (i = 0; i < size; ++i) - printf (".byte %d\n", (unsigned int) code [i]); - return 0; -} diff --git a/mono/arch/x86/tramp.c b/mono/arch/x86/tramp.c deleted file mode 100644 index fab5a55325f..00000000000 --- a/mono/arch/x86/tramp.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Create trampolines to invoke arbitrary functions. - * - * Copyright (C) Ximian Inc. - * - * Authors: - * Paolo Molaro (lupus@ximian.com) - * Dietmar Maurer (dietmar@ximian.com) - * - */ - -#include "config.h" -#include -#include -#include "x86-codegen.h" -#include "mono/metadata/class.h" -#include "mono/metadata/tabledefs.h" -#include "mono/interpreter/interp.h" -#include "mono/metadata/appdomain.h" -#include "mono/metadata/marshal.h" - -/* - * The resulting function takes the form: - * void func (void (*callme)(), void *retval, void *this_obj, stackval *arguments); - */ -#define FUNC_ADDR_POS 8 -#define RETVAL_POS 12 -#define THIS_POS 16 -#define ARGP_POS 20 -#define LOC_POS -4 - -#define ARG_SIZE sizeof (stackval) - -MonoPIFunc -mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor) -{ - unsigned char *p, *code_buffer; - guint32 stack_size = 0, code_size = 50; - guint32 arg_pos, simpletype; - int i, stringp; - static GHashTable *cache = NULL; - MonoPIFunc res; - - if (!cache) - cache = g_hash_table_new ((GHashFunc)mono_signature_hash, - (GCompareFunc)mono_metadata_signature_equal); - - if ((res = (MonoPIFunc)g_hash_table_lookup (cache, sig))) - return res; - - if (sig->hasthis) { - stack_size += sizeof (gpointer); - code_size += 10; - } - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref && !sig->ret->data.klass->enumtype) { - stack_size += sizeof (gpointer); - code_size += 5; - } - - for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) { - stack_size += sizeof (gpointer); - code_size += 20; - continue; - } - simpletype = sig->params [i]->type; -enum_calc_size: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - stack_size += 4; - code_size += i < 10 ? 5 : 8; - break; - case MONO_TYPE_VALUETYPE: { - int size; - if (sig->params [i]->data.klass->enumtype) { - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_calc_size; - } - if ((size = mono_class_native_size (sig->params [i]->data.klass, NULL)) != 4) { - stack_size += size + 3; - stack_size &= ~3; - code_size += 32; - } else { - stack_size += 4; - code_size += i < 10 ? 5 : 8; - } - break; - } - case MONO_TYPE_I8: - stack_size += 8; - code_size += i < 10 ? 5 : 8; - break; - case MONO_TYPE_R4: - stack_size += 4; - code_size += i < 10 ? 10 : 13; - break; - case MONO_TYPE_R8: - stack_size += 8; - code_size += i < 10 ? 7 : 10; - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - /* - * FIXME: take into account large return values. - */ - - code_buffer = p = alloca (code_size); - - /* - * Standard function prolog. - */ - x86_push_reg (p, X86_EBP); - x86_mov_reg_reg (p, X86_EBP, X86_ESP, 4); - /* - * and align to 16 byte boundary... - */ - stack_size += 15; - stack_size &= ~15; - - if (stack_size) - x86_alu_reg_imm (p, X86_SUB, X86_ESP, stack_size); - - /* - * EDX has the pointer to the args. - */ - x86_mov_reg_membase (p, X86_EDX, X86_EBP, ARGP_POS, 4); - - /* - * Push arguments in reverse order. - */ - stringp = 0; - for (i = sig->param_count; i; --i) { - arg_pos = ARG_SIZE * (i - 1); - if (sig->params [i - 1]->byref) { - x86_push_membase (p, X86_EDX, arg_pos); - continue; - } - simpletype = sig->params [i - 1]->type; -enum_marshal: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - x86_push_membase (p, X86_EDX, arg_pos); - break; - case MONO_TYPE_R4: - x86_alu_reg_imm (p, X86_SUB, X86_ESP, 4); - x86_fld_membase (p, X86_EDX, arg_pos, TRUE); - x86_fst_membase (p, X86_ESP, 0, FALSE, TRUE); - break; - case MONO_TYPE_CLASS: - x86_push_membase (p, X86_EDX, arg_pos); - break; - case MONO_TYPE_SZARRAY: - x86_push_membase (p, X86_EDX, arg_pos); - break; - case MONO_TYPE_VALUETYPE: - if (!sig->params [i - 1]->data.klass->enumtype) { - int size = mono_class_native_size (sig->params [i - 1]->data.klass, NULL); - if (size == 4) { - /* it's a structure that fits in 4 bytes, need to push the value pointed to */ - x86_mov_reg_membase (p, X86_EAX, X86_EDX, arg_pos, 4); - x86_push_regp (p, X86_EAX); - } else { - int ss = size; - ss += 3; - ss &= ~3; - - x86_alu_reg_imm (p, X86_SUB, X86_ESP, ss); - x86_push_imm (p, size); - x86_push_membase (p, X86_EDX, arg_pos); - x86_lea_membase (p, X86_EAX, X86_ESP, 2*4); - x86_push_reg (p, X86_EAX); - x86_mov_reg_imm (p, X86_EAX, memcpy); - x86_call_reg (p, X86_EAX); - x86_alu_reg_imm (p, X86_ADD, X86_ESP, 12); - /* memcpy might clobber EDX so restore it */ - x86_mov_reg_membase (p, X86_EDX, X86_EBP, ARGP_POS, 4); - } - } else { - /* it's an enum value */ - simpletype = sig->params [i - 1]->data.klass->enum_basetype->type; - goto enum_marshal; - } - break; - case MONO_TYPE_I8: - case MONO_TYPE_U8: - case MONO_TYPE_R8: - x86_push_membase (p, X86_EDX, arg_pos + 4); - x86_push_membase (p, X86_EDX, arg_pos); - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i - 1]->type); - } - } - - if (sig->hasthis) { - if (sig->call_convention != MONO_CALL_THISCALL) { - x86_mov_reg_membase (p, X86_EDX, X86_EBP, THIS_POS, 4); - x86_push_reg (p, X86_EDX); - } else { - x86_mov_reg_membase (p, X86_ECX, X86_EBP, THIS_POS, 4); - } - } - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_push_membase (p, X86_ECX, 0); - } - } - - /* - * Insert call to function - */ - x86_mov_reg_membase (p, X86_EDX, X86_EBP, FUNC_ADDR_POS, 4); - x86_call_reg (p, X86_EDX); - - /* - * Handle retval. - * Small integer and pointer values are in EAX. - * Long integers are in EAX:EDX. - * FP values are on the FP stack. - */ - - if (sig->ret->byref || string_ctor) { - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4); - } else { - simpletype = sig->ret->type; - enum_retvalue: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 1); - break; - case MONO_TYPE_CHAR: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 2); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4); - break; - case MONO_TYPE_STRING: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4); - break; - case MONO_TYPE_R4: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_fst_membase (p, X86_ECX, 0, FALSE, TRUE); - break; - case MONO_TYPE_R8: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_fst_membase (p, X86_ECX, 0, TRUE, TRUE); - break; - case MONO_TYPE_I8: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4); - x86_mov_membase_reg (p, X86_ECX, 4, X86_EDX, 4); - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - case MONO_TYPE_VOID: - break; - default: - g_error ("Can't handle as return value 0x%x", sig->ret->type); - } - } - - /* - * Standard epilog. - */ - x86_leave (p); - x86_ret (p); - - g_assert (p - code_buffer < code_size); - res = (MonoPIFunc)g_memdup (code_buffer, p - code_buffer); - - g_hash_table_insert (cache, sig, res); - - return res; -} - -#define MINV_POS (- sizeof (MonoInvocation)) -#define STACK_POS (MINV_POS - sizeof (stackval) * sig->param_count) -#define TYPE_OFFSET (G_STRUCT_OFFSET (stackval, type)) - -/* - * Returns a pointer to a native function that can be used to - * call the specified method. - * The function created will receive the arguments according - * to the call convention specified in the method. - * This function works by creating a MonoInvocation structure, - * filling the fields in and calling ves_exec_method on it. - * Still need to figure out how to handle the exception stuff - * across the managed/unmanaged boundary. - */ -void * -mono_arch_create_method_pointer (MonoMethod *method) -{ - MonoMethodSignature *sig; - MonoJitInfo *ji; - unsigned char *p, *code_buffer; - gint32 local_size; - gint32 stackval_pos, arg_pos = 8; - int i, size, align, cpos; - int *vtbuf; - - sig = method->signature; - - code_buffer = p = alloca (512); /* FIXME: check for overflows... */ - vtbuf = alloca (sizeof(int)*sig->param_count); - - local_size = sizeof (MonoInvocation) + sizeof (stackval) * (sig->param_count + 1); - - local_size += 7; - local_size &= ~7; - - stackval_pos = -local_size; - - cpos = 0; - for (i = 0; i < sig->param_count; i++) { - MonoType *type = sig->params [i]; - vtbuf [i] = -1; - if (type->type == MONO_TYPE_VALUETYPE) { - MonoClass *klass = type->data.klass; - if (klass->enumtype) - continue; - size = mono_class_native_size (klass, &align); - cpos += align - 1; - cpos &= ~(align - 1); - vtbuf [i] = cpos; - cpos += size; - } - } - - cpos += 7; - cpos &= ~7; - - local_size += cpos; - - /* - * Standard function prolog. - */ - x86_push_reg (p, X86_EBP); - x86_mov_reg_reg (p, X86_EBP, X86_ESP, 4); - x86_alu_reg_imm (p, X86_SUB, X86_ESP, local_size); - - /* - * Initialize MonoInvocation fields, first the ones known now. - */ - x86_mov_reg_imm (p, X86_EAX, 0); - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)), X86_EAX, 4); - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)), X86_EAX, 4); - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)), X86_EAX, 4); - /* - * Set the method pointer. - */ - x86_mov_membase_imm (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)), (int)method, 4); - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref && !sig->ret->data.klass->enumtype) - arg_pos += 4; - - /* - * Handle this. - */ - if (sig->hasthis) { - if (sig->call_convention != MONO_CALL_THISCALL) { - /* - * Grab it from the stack, otherwise it's already in ECX. - */ - x86_mov_reg_membase (p, X86_ECX, X86_EBP, arg_pos, 4); - arg_pos += 4; - } - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)), X86_ECX, 4); - } - /* - * Handle the arguments. stackval_pos is the posset of the stackval array from EBP. - * arg_pos is the offset from EBP to the incoming arg on the stack. - * We just call stackval_from_data to handle all the (nasty) issues.... - */ - x86_lea_membase (p, X86_EAX, X86_EBP, stackval_pos); - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)), X86_EAX, 4); - for (i = 0; i < sig->param_count; ++i) { - if (vtbuf [i] >= 0) { - x86_lea_membase (p, X86_EAX, X86_EBP, - local_size + vtbuf [i]); - x86_mov_membase_reg (p, X86_EBP, stackval_pos, X86_EAX, 4); - } - x86_mov_reg_imm (p, X86_ECX, stackval_from_data); - x86_lea_membase (p, X86_EDX, X86_EBP, arg_pos); - x86_lea_membase (p, X86_EAX, X86_EBP, stackval_pos); - x86_push_imm (p, sig->pinvoke); - x86_push_reg (p, X86_EDX); - x86_push_reg (p, X86_EAX); - x86_push_imm (p, sig->params [i]); - x86_call_reg (p, X86_ECX); - x86_alu_reg_imm (p, X86_SUB, X86_ESP, 16); - stackval_pos += sizeof (stackval); - /* fixme: alignment */ - if (sig->pinvoke) - arg_pos += mono_type_native_stack_size (sig->params [i], &align); - else - arg_pos += mono_type_stack_size (sig->params [i], &align); - } - - /* - * Handle the return value storage area. - */ - x86_lea_membase (p, X86_EAX, X86_EBP, stackval_pos); - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)), X86_EAX, 4); - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - x86_mov_reg_membase (p, X86_ECX, X86_EBP, 8, 4); - x86_mov_membase_reg (p, X86_EBP, stackval_pos, X86_ECX, 4); - } - } - - /* - * Call the method. - */ - x86_lea_membase (p, X86_EAX, X86_EBP, MINV_POS); - x86_push_reg (p, X86_EAX); - x86_mov_reg_imm (p, X86_EDX, ves_exec_method); - x86_call_reg (p, X86_EDX); - - /* - * Move the return value to the proper place. - */ - x86_lea_membase (p, X86_EAX, X86_EBP, stackval_pos); - if (sig->ret->byref) { - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 4); - } else { - int simpletype = sig->ret->type; - enum_retvalue: - switch (sig->ret->type) { - case MONO_TYPE_VOID: - break; - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 1); - break; - case MONO_TYPE_CHAR: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 2); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_CLASS: - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 4); - break; - case MONO_TYPE_I8: - x86_mov_reg_membase (p, X86_EDX, X86_EAX, 4, 4); - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 4); - break; - case MONO_TYPE_R8: - x86_fld_membase (p, X86_EAX, 0, TRUE); - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - - x86_push_imm (p, sig->pinvoke); - x86_push_membase (p, X86_EBP, stackval_pos); - x86_push_reg (p, X86_EAX); - x86_push_imm (p, sig->ret); - x86_mov_reg_imm (p, X86_ECX, stackval_to_data); - x86_call_reg (p, X86_ECX); - x86_alu_reg_imm (p, X86_SUB, X86_ESP, 16); - - break; - default: - g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type); - break; - } - } - - /* - * Standard epilog. - */ - x86_leave (p); - x86_ret (p); - - g_assert (p - code_buffer < 512); - - ji = g_new0 (MonoJitInfo, 1); - ji->method = method; - ji->code_size = p - code_buffer; - ji->code_start = g_memdup (code_buffer, p - code_buffer); - - mono_jit_info_table_add (mono_get_root_domain (), ji); - - return ji->code_start; -} From bb296086c0e1c9bd492076fe348f69a774489088 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 9 Sep 2014 17:44:00 +0100 Subject: [PATCH 058/543] TimeFormat "zzz" is only valid after a date. --- mcs/class/corlib/System/DateTime.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mcs/class/corlib/System/DateTime.cs b/mcs/class/corlib/System/DateTime.cs index 272f6996191..ce698f9c620 100644 --- a/mcs/class/corlib/System/DateTime.cs +++ b/mcs/class/corlib/System/DateTime.cs @@ -107,8 +107,7 @@ public struct DateTime : IFormattable, IConvertible, IComparable, ISerializable, "H:mzzz", "H:m", "H tt", // Specifies AM to disallow '8'. - "H'\u6642'm'\u5206's'\u79D2'", - "zzz" + "H'\u6642'm'\u5206's'\u79D2'" }; // DateTime.Parse date patterns extend ParseExact patterns as follows: @@ -886,6 +885,9 @@ internal static bool CoreParse (string s, IFormatProvider provider, DateTimeStyl if (_DoParse (s, firstPart, ParseTimeFormats [j], false, out result, out dto, dfi, styles, true, ref incompleteFormat, ref longYear)) return true; } + + if (_DoParse (s, firstPart, "zzz", false, out result, out dto, dfi, styles, true, ref incompleteFormat, ref longYear)) + return true; } // From 59be7ba9c58483e9ea24de34bde697862de5093c Mon Sep 17 00:00:00 2001 From: ramtin Date: Tue, 9 Sep 2014 11:50:06 -0700 Subject: [PATCH 059/543] The ShouldTrace conditions are fixed to correctly trace the events based on the Level --- mcs/class/System/System.Diagnostics/SourceSwitch.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mcs/class/System/System.Diagnostics/SourceSwitch.cs b/mcs/class/System/System.Diagnostics/SourceSwitch.cs index d991271478e..3ba6849a44f 100644 --- a/mcs/class/System/System.Diagnostics/SourceSwitch.cs +++ b/mcs/class/System/System.Diagnostics/SourceSwitch.cs @@ -59,15 +59,15 @@ public bool ShouldTrace (TraceEventType eventType) { switch (eventType) { case TraceEventType.Critical: - return (Level & SourceLevels.Critical) != 0; + return (Level & (SourceLevels)TraceEventType.Critical) != 0; case TraceEventType.Error: - return (Level & SourceLevels.Error) != 0; + return (Level & (SourceLevels)TraceEventType.Error) != 0; case TraceEventType.Warning: - return (Level & SourceLevels.Warning) != 0; + return (Level & (SourceLevels)TraceEventType.Warning) != 0; case TraceEventType.Information: - return (Level & SourceLevels.Information) != 0; + return (Level & (SourceLevels)TraceEventType.Information) != 0; case TraceEventType.Verbose: - return (Level & SourceLevels.Verbose) != 0; + return (Level & (SourceLevels)TraceEventType.Verbose) != 0; case TraceEventType.Start: case TraceEventType.Stop: case TraceEventType.Suspend: @@ -78,6 +78,7 @@ public bool ShouldTrace (TraceEventType eventType) } } + protected override void OnValueChanged () { SwitchSetting = (int) Enum.Parse (typeof (SourceLevels), From 2006bf3f44fba54bd9e129e42a8580e4037cd5d8 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 27 Jan 2014 17:45:13 -0500 Subject: [PATCH 060/543] Add deprecation notice for mono_class_get_full. --- mono/metadata/class.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 21e026a59d3..aef1b887f41 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -7118,6 +7118,7 @@ mono_assembly_name_from_token (MonoImage *image, guint32 type_token) * @image: the image where the class resides * @type_token: the token for the class * @context: the generic context used to evaluate generic instantiations in + * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0 * * Returns: the MonoClass that represents @type_token in @image */ From d3da468965cea24ba4cf8a70064b02182fd1c490 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 27 Jan 2014 18:03:47 -0500 Subject: [PATCH 061/543] [runtime] Expose mono_class_inflate_generic_class_checked to the internal API. --- mono/metadata/class-internals.h | 3 +++ mono/metadata/class.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index ab4a5cb5789..3a32e27ccb7 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -1386,4 +1386,7 @@ mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bfla char* mono_class_full_name (MonoClass *klass) MONO_INTERNAL; +MonoClass* +mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error) MONO_INTERNAL; + #endif /* __MONO_METADATA_CLASS_INTERBALS_H__ */ diff --git a/mono/metadata/class.c b/mono/metadata/class.c index aef1b887f41..c4322ce6cad 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -893,7 +893,7 @@ mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoG return inflated; } -static MonoClass* +MonoClass* mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error) { MonoClass *res; From 82c38c44096bd17ce9371eea9015abe75cbc7ec8 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 27 Jan 2014 18:04:14 -0500 Subject: [PATCH 062/543] [metadata] Replace mono_class_get_full with a saner pair of mono_class_get and mono_class_inflate_generic_class_checked. --- mono/metadata/icall.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index ddec8e43053..5df454dc033 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -5442,19 +5442,20 @@ init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_arg } ICALL_EXPORT MonoType* -ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error) +ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error) { MonoClass *klass; int table = mono_metadata_token_table (token); int index = mono_metadata_token_index (token); MonoGenericContext context; + MonoError error; - *error = ResolveTokenError_Other; + *resolve_error = ResolveTokenError_Other; /* Validate token */ if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && (table != MONO_TABLE_TYPESPEC)) { - *error = ResolveTokenError_BadTable; + *resolve_error = ResolveTokenError_BadTable; return NULL; } @@ -5470,16 +5471,18 @@ ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 t } if ((index <= 0) || (index > image->tables [table].rows)) { - *error = ResolveTokenError_OutOfRange; + *resolve_error = ResolveTokenError_OutOfRange; return NULL; } init_generic_context_from_args (&context, type_args, method_args); - klass = mono_class_get_full (image, token, &context); - + klass = mono_class_get (image, token); if (mono_loader_get_last_error ()) mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ())); + klass = mono_class_inflate_generic_class_checked (klass, &context, &error); + mono_error_raise_exception (&error); + if (klass) return &klass->byval_arg; else From efa5a5ad177e01df9dbb31a256f856dc0c74042a Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 28 Jan 2014 14:56:20 -0500 Subject: [PATCH 063/543] [utils] Add mono_error_set_assembly_load_simple to ease producing an error message for ref only assemblies. --- mono/utils/mono-error-internals.h | 3 +++ mono/utils/mono-error.c | 15 +++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/mono/utils/mono-error-internals.h b/mono/utils/mono-error-internals.h index 80672403089..672e2a75afa 100644 --- a/mono/utils/mono-error-internals.h +++ b/mono/utils/mono-error-internals.h @@ -32,6 +32,9 @@ mono_error_set_error (MonoError *error, int error_code, const char *msg_format, void mono_error_set_assembly_load (MonoError *error, const char *assembly_name, const char *msg_format, ...) MONO_INTERNAL; +void +mono_error_set_assembly_load_simple (MonoError *error, const char *assembly_name, gboolean refection_only) MONO_INTERNAL; + void mono_error_set_type_load_class (MonoError *error, MonoClass *klass, const char *msg_format, ...) MONO_INTERNAL; diff --git a/mono/utils/mono-error.c b/mono/utils/mono-error.c index a59de349f30..57184d9d63b 100644 --- a/mono/utils/mono-error.c +++ b/mono/utils/mono-error.c @@ -188,6 +188,16 @@ mono_error_set_assembly_load (MonoError *oerror, const char *assembly_name, cons set_error_message (); } + +void +mono_error_set_assembly_load_simple (MonoError *oerror, const char *assembly_name, gboolean refection_only) +{ + if (refection_only) + mono_error_set_assembly_load (oerror, assembly_name, "Cannot resolve dependency to assembly because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event."); + else + mono_error_set_assembly_load (oerror, assembly_name, "Could not load file or assembly or one of its dependencies."); +} + void mono_error_set_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, ...) { @@ -321,10 +331,7 @@ mono_error_set_from_loader_error (MonoError *oerror) break; case MONO_EXCEPTION_FILE_NOT_FOUND: - if (loader_error->ref_only) - mono_error_set_assembly_load (oerror, loader_error->assembly_name, "Cannot resolve dependency to assembly because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event."); - else - mono_error_set_assembly_load (oerror, loader_error->assembly_name, "Could not load file or assembly or one of its dependencies."); + mono_error_set_assembly_load_simple (oerror, loader_error->assembly_name, loader_error->ref_only); break; case MONO_EXCEPTION_METHOD_ACCESS: From 57cce937d83d7d5efd252b9f07d9d284dc3c1065 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 28 Jan 2014 14:57:39 -0500 Subject: [PATCH 064/543] [runtime] Introduce mono_class_from_typeref_checked and replace usage of the old one with it. This is another step into wiring up MonoError into the typeloading codebase. This is one more function that needs it. --- mono/metadata/class.c | 77 ++++++++++++++++++++++-------------------- mono/metadata/class.h | 4 +++ mono/metadata/loader.c | 15 ++++++-- 3 files changed, 58 insertions(+), 38 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index c4322ce6cad..d282dca5910 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -166,17 +166,25 @@ MonoClass * mono_class_from_typeref (MonoImage *image, guint32 type_token) { MonoError error; + MonoClass *class = mono_class_from_typeref_checked (image, type_token, &error); + g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/ + return class; +} + +MonoClass * +mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error) +{ guint32 cols [MONO_TYPEREF_SIZE]; MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF]; guint32 idx; const char *name, *nspace; - MonoClass *res; + MonoClass *res = NULL; MonoImage *module; - if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, &error)) { - mono_trace_warning (MONO_TRACE_TYPE, "Failed to resolve typeref from %s due to '%s'", image->name, mono_error_get_message (&error)); + mono_error_init (error); + + if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error)) return NULL; - } mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE); @@ -192,33 +200,26 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token) The defacto behavior is that it's just a typedef in disguise. */ /* a typedef in disguise */ - return mono_class_from_name (image, nspace, name); + res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/ + goto done; + case MONO_RESOLTION_SCOPE_MODULEREF: module = mono_image_load_module (image, idx); if (module) - return mono_class_from_name (module, nspace, name); - else { - char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name); - char *human_name; - - human_name = mono_stringify_assembly_name (&image->assembly->aname); - mono_loader_set_error_type_load (msg, human_name); - g_free (msg); - g_free (human_name); - - return NULL; - } + res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/ + goto done; + case MONO_RESOLTION_SCOPE_TYPEREF: { MonoClass *enclosing; GList *tmp; if (idx == mono_metadata_token_index (type_token)) { - mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with self-referencing typeref token %08x.", image->name, type_token)); + mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token); return NULL; } - enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx); - if (!enclosing) + enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error); + if (!mono_error_ok (error)) return NULL; if (enclosing->nested_classes_inited && enclosing->ext) { @@ -236,28 +237,21 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token) guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME); const char *nname = mono_metadata_string_heap (enclosing->image, string_offset); - if (strcmp (nname, name) == 0) { - MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error); - if (!mono_error_ok (&error)) { - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); /*FIXME don't swallow error message.*/ - return NULL; - } - return res; - } + if (strcmp (nname, name) == 0) + return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error); i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1); } } g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name); - return NULL; + goto done; } case MONO_RESOLTION_SCOPE_ASSEMBLYREF: break; } if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) { - mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image->name, idx)); + mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx); return NULL; } @@ -272,13 +266,20 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token) mono_assembly_get_assemblyref (image, idx - 1, &aname); human_name = mono_stringify_assembly_name (&aname); - mono_loader_set_error_assembly_load (human_name, image->assembly ? image->assembly->ref_only : FALSE); - g_free (human_name); - + mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE); return NULL; } - return mono_class_from_name (image->references [idx - 1]->image, nspace, name); + res = mono_class_from_name (image->references [idx - 1]->image, nspace, name); + +done: + /* Generic case, should be avoided for when a better error is possible. */ + if (!res && mono_error_ok (error)) { + char *name = mono_class_name_from_token (image, type_token); + char *assembly = mono_assembly_name_from_token (image, type_token); + mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token); + } + return res; } @@ -7149,7 +7150,11 @@ mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *c } break; case MONO_TOKEN_TYPE_REF: - class = mono_class_from_typeref (image, type_token); + class = mono_class_from_typeref_checked (image, type_token, &error); + if (!mono_error_ok (&error)) { + /*FIXME don't swallow the error message*/ + mono_error_cleanup (&error); + } break; case MONO_TOKEN_TYPE_SPEC: class = mono_class_create_from_typespec (image, type_token, context, &error); diff --git a/mono/metadata/class.h b/mono/metadata/class.h index a65bd4565e9..d9f315139b1 100644 --- a/mono/metadata/class.h +++ b/mono/metadata/class.h @@ -4,6 +4,7 @@ #include #include #include +#include MONO_BEGIN_DECLS @@ -37,6 +38,9 @@ mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int p MONO_API MonoClass * mono_class_from_typeref (MonoImage *image, uint32_t type_token); +MONO_API MonoClass * +mono_class_from_typeref_checked (MonoImage *image, uint32_t type_token, MonoError *error); + MONO_API MonoClass * mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, mono_bool is_mvar); diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index 0f0ab038e96..192e2e93c71 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -436,6 +436,7 @@ field_from_memberref (MonoImage *image, guint32 token, MonoClass **retklass, const char *fname; const char *ptr; guint32 idx = mono_metadata_token_index (token); + MonoError error; mono_metadata_decode_row (&tables [MONO_TABLE_MEMBERREF], idx-1, cols, MONO_MEMBERREF_SIZE); nindex = cols [MONO_MEMBERREF_CLASS] >> MONO_MEMBERREF_PARENT_BITS; @@ -455,7 +456,12 @@ field_from_memberref (MonoImage *image, guint32 token, MonoClass **retklass, break; case MONO_MEMBERREF_PARENT_TYPEREF: class_table = MONO_TOKEN_TYPE_REF; - klass = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | nindex); + klass = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | nindex, &error); + if (!mono_error_ok (&error)) { + /*FIXME don't swallow the error message*/ + mono_error_cleanup (&error); + } + break; case MONO_MEMBERREF_PARENT_TYPESPEC: class_table = MONO_TOKEN_TYPE_SPEC; @@ -940,6 +946,7 @@ method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typesp const char *mname; MonoMethodSignature *sig; const char *ptr; + MonoError error; mono_metadata_decode_row (&tables [MONO_TABLE_MEMBERREF], idx-1, cols, 3); nindex = cols [MONO_MEMBERREF_CLASS] >> MONO_MEMBERREF_PARENT_BITS; @@ -959,7 +966,11 @@ method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typesp switch (class) { case MONO_MEMBERREF_PARENT_TYPEREF: - klass = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | nindex); + klass = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | nindex, &error); + if (!mono_error_ok (&error)) { + /*FIXME don't swallow the error message*/ + mono_error_cleanup (&error); + } if (!klass) { char *name = mono_class_name_from_token (image, MONO_TOKEN_TYPE_REF | nindex); g_warning ("Missing method %s in assembly %s, type %s", mname, image->name, name); From 3ee5d36ec7b308f541894595f0a4d685fe65a684 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Thu, 28 Aug 2014 20:29:10 -0400 Subject: [PATCH 065/543] [runtime] Introduce mono_class_get_checked. --- mono/metadata/class-internals.h | 3 ++ mono/metadata/class.c | 60 +++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 3a32e27ccb7..1b117e22fe5 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -1389,4 +1389,7 @@ mono_class_full_name (MonoClass *klass) MONO_INTERNAL; MonoClass* mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error) MONO_INTERNAL; +MonoClass * +mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error) MONO_INTERNAL; + #endif /* __MONO_METADATA_CLASS_INTERBALS_H__ */ diff --git a/mono/metadata/class.c b/mono/metadata/class.c index d282dca5910..53760778c48 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -7127,53 +7127,63 @@ MonoClass * mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context) { MonoError error; + MonoClass *class; + class = mono_class_get_checked (image, type_token, &error); + g_assert (mono_error_ok (&error)); /*FIXME remove this function */ + + if (context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC) { + class = mono_class_inflate_generic_class_checked (class, context, &error); + g_assert (mono_error_ok (&error)); /*FIXME remove this function */ + } + return class; +} + +/** + * mono_class_get_checked: + * @image: the image where the class resides + * @type_token: the token for the class + * @error: error object to return any error + * + * Returns: the MonoClass that represents @type_token in @image + */ +MonoClass * +mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error) +{ MonoClass *class = NULL; + mono_error_init (error); + if (image_is_dynamic (image)) { int table = mono_metadata_token_table (type_token); if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) { - mono_loader_set_error_bad_image (g_strdup ("Bad type token.")); + mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table); return NULL; } - return mono_lookup_dynamic_token (image, type_token, context); + class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/ + goto done; } switch (type_token & 0xff000000){ case MONO_TOKEN_TYPE_DEF: - class = mono_class_create_from_typedef (image, type_token, &error); - if (!mono_error_ok (&error)) { - mono_loader_set_error_from_mono_error (&error); - /*FIXME don't swallow the error message*/ - mono_error_cleanup (&error); - return NULL; - } + class = mono_class_create_from_typedef (image, type_token, error); break; case MONO_TOKEN_TYPE_REF: - class = mono_class_from_typeref_checked (image, type_token, &error); - if (!mono_error_ok (&error)) { - /*FIXME don't swallow the error message*/ - mono_error_cleanup (&error); - } + class = mono_class_from_typeref_checked (image, type_token, error); break; case MONO_TOKEN_TYPE_SPEC: - class = mono_class_create_from_typespec (image, type_token, context, &error); - if (!mono_error_ok (&error)) { - /*FIXME don't swallow the error message*/ - mono_error_cleanup (&error); - } + class = mono_class_create_from_typespec (image, type_token, NULL, error); break; default: - g_warning ("unknown token type %x", type_token & 0xff000000); - g_assert_not_reached (); + mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000); } - if (!class){ +done: + /* Generic case, should be avoided for when a better error is possible. */ + if (!class && mono_error_ok (error)) { char *name = mono_class_name_from_token (image, type_token); char *assembly = mono_assembly_name_from_token (image, type_token); - mono_loader_set_error_type_load (name, assembly); - g_free (name); - g_free (assembly); + mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token); } return class; From a824dde30f1f8527afd8b0451dc9e8aa10fec41c Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Thu, 28 Aug 2014 20:29:33 -0400 Subject: [PATCH 066/543] [runtime] Change do_mono_metadata_parse_type to use mono_class_get_checked --- mono/metadata/metadata.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index 03cac47ce37..f725edc7f79 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -3200,11 +3200,15 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer case MONO_TYPE_CLASS: { guint32 token; MonoClass *class; + MonoError error; token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr); - class = mono_class_get (m, token); + class = mono_class_get_checked (m, token, &error); type->data.klass = class; - if (!class) + if (!class) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /*FIXME don't swallow the error message*/ return FALSE; + } if (!compare_type_literals (class->byval_arg.type, type->type)) return FALSE; break; From 32e2bb7c3955efd0e047d71e83497c154b842eb7 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Thu, 28 Aug 2014 20:30:17 -0400 Subject: [PATCH 067/543] [runtime] Change mono_type_get_full to use mono_class_get_checked. --- mono/metadata/class.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 53760778c48..c9cdaf1df37 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -7212,21 +7212,30 @@ mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *co return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context)); if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) { - MonoClass *class = mono_class_get_full (image, type_token, context); - return class ? mono_class_get_type (class) : NULL; + MonoClass *class = mono_class_get_checked (image, type_token, &error); + + if (!mono_error_ok (&error)) { + mono_loader_set_error_from_mono_error (&error); + /*FIXME don't swallow the error message*/ + mono_error_cleanup (&error); + return NULL; + } + + g_assert (class); + return mono_class_get_type (class); } type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error); if (!mono_error_ok (&error)) { - /*FIXME don't swalloc the error message.*/ char *name = mono_class_name_from_token (image, type_token); char *assembly = mono_assembly_name_from_token (image, type_token); g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error)); - mono_error_cleanup (&error); mono_loader_set_error_type_load (name, assembly); + /*FIXME don't swallow the error message.*/ + mono_error_cleanup (&error); return NULL; } From 5c8ab13f0c1bd6c311f17d4cf59e51e39f063a6c Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Thu, 28 Aug 2014 20:41:40 -0400 Subject: [PATCH 068/543] Add mono_class_get_checked to mono_class_create_from_typedef. --- mono/metadata/class.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index c9cdaf1df37..b4258069328 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -5682,10 +5682,12 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError class->byval_arg.data.klass = class; class->byval_arg.type = MONO_TYPE_CLASS; } - parent = mono_class_get_full (image, parent_token, context); + parent = mono_class_get_checked (image, parent_token, error); + if (parent && context) + parent = mono_class_inflate_generic_class_checked (parent, context, error); if (parent == NULL) { - mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token)); + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error))); goto parent_failure; } From 6d60ff581c059f3269df4ea6dc93057406811f7b Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Fri, 29 Aug 2014 14:11:51 -0400 Subject: [PATCH 069/543] [runtime] Introduce MonoError to mono_class_get_full. Introduce MonoError into callers of mono_class_get_full. Make mono_class_get not abort on failure until all callers are fixed. --- mono/dis/dump.c | 13 +++++++--- mono/dis/get.c | 7 +++-- mono/dis/main.c | 16 ++++++++---- mono/metadata/class-internals.h | 13 +++++----- mono/metadata/class.c | 41 ++++++++++++++++++++++------- mono/metadata/icall.c | 8 +++--- mono/metadata/loader.c | 24 +++++++++-------- mono/metadata/metadata.c | 46 +++++++++++++-------------------- mono/mini/aot-compiler.c | 4 ++- mono/mini/dwarfwriter.c | 9 ++++--- mono/mini/method-to-ir.c | 13 +++++++--- 11 files changed, 115 insertions(+), 79 deletions(-) diff --git a/mono/dis/dump.c b/mono/dis/dump.c index 2b3a4851de0..391ec7fbc77 100755 --- a/mono/dis/dump.c +++ b/mono/dis/dump.c @@ -566,6 +566,7 @@ dump_table_method (MonoImage *m) current_type = 1; last_m = first_m = 1; for (i = 1; i <= t->rows; i++){ + MonoError error; guint32 cols [MONO_METHOD_SIZE]; char *sig, *impl_flags; const char *sigblob; @@ -583,13 +584,17 @@ dump_table_method (MonoImage *m) mono_metadata_string_heap (m, mono_metadata_decode_row_col (td, current_type - 2, MONO_TYPEDEF_NAME))); first_m = last_m; type_container = mono_metadata_load_generic_params (m, MONO_TOKEN_TYPE_DEF | (current_type - 1), NULL); - if (type_container) - mono_metadata_load_generic_param_constraints (m, MONO_TOKEN_TYPE_DEF | (current_type - 1), type_container); + if (type_container) { + mono_metadata_load_generic_param_constraints_checked (m, MONO_TOKEN_TYPE_DEF | (current_type - 1), type_container, &error); + g_assert (mono_error_ok (&error)); /*FIXME don't swallow the error message*/ + } } method_container = mono_metadata_load_generic_params (m, MONO_TOKEN_METHOD_DEF | i, type_container); - if (method_container) - mono_metadata_load_generic_param_constraints (m, MONO_TOKEN_METHOD_DEF | i, method_container); + if (method_container) { + mono_metadata_load_generic_param_constraints_checked (m, MONO_TOKEN_METHOD_DEF | i, method_container, &error); + g_assert (mono_error_ok (&error)); /*FIXME don't swallow the error message*/ + } mono_metadata_decode_table_row (m, MONO_TABLE_METHOD, i - 1, cols, MONO_METHOD_SIZE); sigblob = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]); mono_metadata_decode_blob_size (sigblob, &sigblob); diff --git a/mono/dis/get.c b/mono/dis/get.c index 34f87b0c8ad..a3f2e7b9cac 100755 --- a/mono/dis/get.c +++ b/mono/dis/get.c @@ -889,11 +889,14 @@ dis_stringify_method_signature_full (MonoImage *m, MonoMethodSignature *method, method_name = mono_metadata_string_heap (m, cols [MONO_METHOD_NAME]); param_index = cols [MONO_METHOD_PARAMLIST]; if (!method) { + MonoError error; const char *sig = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]); container = mono_metadata_load_generic_params (m, MONO_TOKEN_METHOD_DEF | methoddef_row, container); - if (container) - mono_metadata_load_generic_param_constraints (m, MONO_TOKEN_METHOD_DEF | methoddef_row, container); + if (container) { + mono_metadata_load_generic_param_constraints_checked (m, MONO_TOKEN_METHOD_DEF | methoddef_row, container, &error); + g_assert (mono_error_ok (&error)); /*FIXME don't swallow the error message*/ + } mono_metadata_decode_blob_size (sig, &sig); method = mono_metadata_parse_method_signature_full (m, container, methoddef_row, sig, &sig); diff --git a/mono/dis/main.c b/mono/dis/main.c index 42d735b0f75..b56da24c35a 100644 --- a/mono/dis/main.c +++ b/mono/dis/main.c @@ -854,10 +854,13 @@ dis_method_list (const char *klass_name, MonoImage *m, guint32 start, guint32 en mono_metadata_decode_blob_size (sig, &sig); container = mono_metadata_load_generic_params (m, MONO_TOKEN_METHOD_DEF | (i + 1), type_container); - if (container) - mono_metadata_load_generic_param_constraints (m, MONO_TOKEN_METHOD_DEF | (i + 1), container); - else + if (container) { + MonoError error; + mono_metadata_load_generic_param_constraints_checked (m, MONO_TOKEN_METHOD_DEF | (i + 1), container, &error); + g_assert (mono_error_ok (&error)); /*FIXME don't swallow the error message*/ + } else { container = type_container; + } ms = mono_metadata_parse_method_signature_full (m, container, i + 1, sig, &sig); if (ms != NULL){ @@ -1181,8 +1184,11 @@ dis_type (MonoImage *m, int n, int is_nested, int forward) } container = mono_metadata_load_generic_params (m, MONO_TOKEN_TYPE_DEF | (n + 1), NULL); - if (container) - mono_metadata_load_generic_param_constraints (m, MONO_TOKEN_TYPE_DEF | (n + 1), container); + if (container) { + MonoError error; + mono_metadata_load_generic_param_constraints_checked (m, MONO_TOKEN_TYPE_DEF | (n + 1), container, &error); + g_assert (mono_error_ok (&error)); /*FIXME don't swallow the error message*/ + } esname = get_escaped_name (name); if ((cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_CLASS_SEMANTIC_MASK) == TYPE_ATTRIBUTE_CLASS){ diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 1b117e22fe5..5ac81279781 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -1228,13 +1228,9 @@ MONO_API MonoGenericContainer * mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container); -MONO_API void -mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token, - MonoGenericContainer *container); - -gboolean -mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 token, - MonoGenericContainer *container) MONO_INTERNAL; +MONO_API gboolean +mono_metadata_load_generic_param_constraints_checked (MonoImage *image, guint32 token, + MonoGenericContainer *container, MonoError *error); MonoMethodSignature* mono_create_icall_signature (const char *sigstr) MONO_INTERNAL; @@ -1392,4 +1388,7 @@ mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext MonoClass * mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error) MONO_INTERNAL; +MonoClass * +mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error) MONO_INTERNAL; + #endif /* __MONO_METADATA_CLASS_INTERBALS_H__ */ diff --git a/mono/metadata/class.c b/mono/metadata/class.c index b4258069328..c776de2dd91 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -5683,7 +5683,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError class->byval_arg.type = MONO_TYPE_CLASS; } parent = mono_class_get_checked (image, parent_token, error); - if (parent && context) + if (parent && context) /* Always inflate */ parent = mono_class_inflate_generic_class_checked (parent, context, error); if (parent == NULL) { @@ -5804,8 +5804,8 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError * We must do this after the class has been constructed to make certain recursive scenarios * work. */ - if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){ - mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints")); + if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) { + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error))); mono_loader_unlock (); mono_profiler_class_loaded (class, MONO_PROFILE_FAILED); g_assert (!mono_loader_get_last_error ()); @@ -6367,14 +6367,17 @@ mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGener char *name = mono_class_name_from_token (image, type_spec); char *assembly = mono_assembly_name_from_token (image, type_spec); mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec); + mono_loader_clear_error (); /*FIXME don't swallow the error*/ return NULL; } if (context && (context->class_inst || context->method_inst)) { MonoType *inflated = inflate_generic_type (NULL, t, context, error); - if (!mono_error_ok (error)) + if (!mono_error_ok (error)) { + g_assert (!mono_loader_get_last_error ()); return NULL; + } if (inflated) { t = inflated; @@ -7131,15 +7134,31 @@ mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *c MonoError error; MonoClass *class; class = mono_class_get_checked (image, type_token, &error); - g_assert (mono_error_ok (&error)); /*FIXME remove this function */ - if (context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC) { + if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC) class = mono_class_inflate_generic_class_checked (class, context, &error); - g_assert (mono_error_ok (&error)); /*FIXME remove this function */ + + if (!class) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /*FIXME don't swallow this error */ } return class; } + +MonoClass * +mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error) +{ + MonoClass *class; + + mono_error_init (error); + class = mono_class_get_checked (image, type_token, error); + + if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC) + class = mono_class_inflate_generic_class_checked (class, context, error); + + return class; +} /** * mono_class_get_checked: * @image: the image where the class resides @@ -8344,14 +8363,18 @@ mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class, } case MONO_TOKEN_FIELD_DEF: { MonoClass *class; + MonoError error; guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token)); if (!type) return NULL; if (handle_class) *handle_class = mono_defaults.fieldhandle_class; - class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context); - if (!class) + class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error); + if (!class) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /* FIXME Don't swallow the error */ return NULL; + } mono_class_init (class); return mono_class_get_field (class, token); } diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 5df454dc033..ad2b82777a6 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -5476,11 +5476,9 @@ ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 t } init_generic_context_from_args (&context, type_args, method_args); - klass = mono_class_get (image, token); - if (mono_loader_get_last_error ()) - mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ())); - - klass = mono_class_inflate_generic_class_checked (klass, &context, &error); + klass = mono_class_get_checked (image, token, &error); + if (klass) + klass = mono_class_inflate_generic_class_checked (klass, &context, &error); mono_error_raise_exception (&error); if (klass) diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index 192e2e93c71..1ad1a1b650e 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -465,7 +465,11 @@ field_from_memberref (MonoImage *image, guint32 token, MonoClass **retklass, break; case MONO_MEMBERREF_PARENT_TYPESPEC: class_table = MONO_TOKEN_TYPE_SPEC; - klass = mono_class_get_full (image, MONO_TOKEN_TYPE_SPEC | nindex, context); + klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_SPEC | nindex, context, &error); + if (!mono_error_ok (&error)) { + /*FIXME don't swallow the error message*/ + mono_error_cleanup (&error); + } break; default: /*FIXME this must set a loader error!*/ @@ -967,15 +971,9 @@ method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typesp switch (class) { case MONO_MEMBERREF_PARENT_TYPEREF: klass = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | nindex, &error); - if (!mono_error_ok (&error)) { - /*FIXME don't swallow the error message*/ - mono_error_cleanup (&error); - } if (!klass) { - char *name = mono_class_name_from_token (image, MONO_TOKEN_TYPE_REF | nindex); - g_warning ("Missing method %s in assembly %s, type %s", mname, image->name, name); - mono_loader_set_error_type_load (name, image->assembly_name); - g_free (name); + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /* FIXME Don't swallow the error */ return NULL; } break; @@ -983,7 +981,7 @@ method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typesp /* * Parse the TYPESPEC in the parent's context. */ - klass = mono_class_get_full (image, MONO_TOKEN_TYPE_SPEC | nindex, typespec_context); + klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_SPEC | nindex, typespec_context, &error); if (!klass) { char *name = mono_class_name_from_token (image, MONO_TOKEN_TYPE_SPEC | nindex); g_warning ("Missing method %s in assembly %s, type %s", mname, image->name, name); @@ -1770,11 +1768,15 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, if (*sig & 0x10) generic_container = mono_metadata_load_generic_params (image, token, container); if (generic_container) { + MonoError error; result->is_generic = TRUE; generic_container->owner.method = result; /*FIXME put this before the image alloc*/ - if (!mono_metadata_load_generic_param_constraints_full (image, token, generic_container)) + if (!mono_metadata_load_generic_param_constraints_checked (image, token, generic_container, &error)) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /*FIXME don't swallow the error message*/ return NULL; + } container = generic_container; } diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index f725edc7f79..d4dde822b6a 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -4046,15 +4046,19 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono pos = start; while (pos < tdef->rows) { + MonoError error; MonoClass *iface; mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE); if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx) break; - iface = mono_class_get_full ( - meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context); - if (iface == NULL) + iface = mono_class_get_and_inflate_typespec_checked ( + meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context, &error); + if (iface == NULL) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /* FIXME Don't swallow the error */ return FALSE; + } result [pos - start] = iface; ++pos; } @@ -5776,7 +5780,7 @@ mono_guid_to_string (const guint8 *guid) } static gboolean -get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container) +get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container, MonoError *error) { MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT]; guint32 cols [MONO_GENPARCONSTRAINT_SIZE]; @@ -5785,13 +5789,15 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene GSList *cons = NULL, *tmp; MonoGenericContext *context = &container->context; + mono_error_init (error); + *constraints = NULL; found = 0; for (i = 0; i < tdef->rows; ++i) { mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE); if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) { token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]); - klass = mono_class_get_full (image, token, context); + klass = mono_class_get_and_inflate_typespec_checked (image, token, context, error); if (!klass) { g_slist_free (cons); return FALSE; @@ -5870,40 +5876,24 @@ mono_metadata_has_generic_params (MonoImage *image, guint32 token) * Memory is allocated from IMAGE's mempool. */ gboolean -mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 token, - MonoGenericContainer *container) +mono_metadata_load_generic_param_constraints_checked (MonoImage *image, guint32 token, + MonoGenericContainer *container, MonoError *error) { guint32 start_row, i, owner; + mono_error_init (error); + if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner))) return TRUE; for (i = 0; i < container->type_argc; i++) { - if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container)) + if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container, error)) { + g_assert (!mono_loader_get_last_error ()); return FALSE; + } } return TRUE; } -/* - * mono_metadata_load_generic_param_constraints: - * - * @image: metadata context - * @token: metadata token to load the contraints, can be methodef or typedef. - * @container: generic container to load into. - * - * Load the generic parameter constraints for the newly created generic type or method - * represented by @token and @container. The @container is the new container which has - * been returned by a call to mono_metadata_load_generic_params() with this @token. - * Memory is allocated from IMAGE's mempool. - */ -void -mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token, - MonoGenericContainer *container) -{ - mono_metadata_load_generic_param_constraints_full (image, token, container); - /*FIXME this function can potentially exit with a pending loader error and cause all sort of havok */ -} - /* * mono_metadata_load_generic_params: * diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index e54fc05083e..0697d0ba6be 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -2333,7 +2333,9 @@ find_typespec_for_class (MonoAotCompile *acfg, MonoClass *klass) if (!acfg->typespec_classes) { acfg->typespec_classes = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoClass*) * len); for (i = 0; i < len; ++i) { - acfg->typespec_classes [i] = mono_class_get_full (acfg->image, MONO_TOKEN_TYPE_SPEC | (i + 1), NULL); + MonoError error; + acfg->typespec_classes [i] = mono_class_get_and_inflate_typespec_checked (acfg->image, MONO_TOKEN_TYPE_SPEC | (i + 1), NULL, &error); + g_assert (mono_error_ok (&error)); /* FIXME error handling */ } } for (i = 0; i < len; ++i) { diff --git a/mono/mini/dwarfwriter.c b/mono/mini/dwarfwriter.c index 9f68a62683e..67585763b69 100644 --- a/mono/mini/dwarfwriter.c +++ b/mono/mini/dwarfwriter.c @@ -1376,6 +1376,7 @@ static const guint8 *token_handler_ip; static char* token_handler (MonoDisHelper *dh, MonoMethod *method, guint32 token) { + MonoError error; char *res, *desc; MonoMethod *cmethod; MonoClass *klass; @@ -1389,10 +1390,12 @@ token_handler (MonoDisHelper *dh, MonoMethod *method, guint32 token) case CEE_ISINST: case CEE_CASTCLASS: case CEE_LDELEMA: - if (method->wrapper_type) + if (method->wrapper_type) { klass = data; - else - klass = mono_class_get_full (method->klass->image, token, NULL); + } else { + klass = mono_class_get_checked (method->klass->image, token, &error); + g_assert (mono_error_ok (&error)); /* FIXME error handling */ + } res = g_strdup_printf ("<%s>", klass->name); break; case CEE_NEWOBJ: diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 8a52d6a7a23..89982b070a1 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -6338,6 +6338,7 @@ mini_get_method (MonoCompile *cfg, MonoMethod *m, guint32 token, MonoClass *klas static inline MonoClass* mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context) { + MonoError error; MonoClass *klass; if (method->wrapper_type != MONO_WRAPPER_NONE) { @@ -6345,7 +6346,8 @@ mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context) if (context) klass = mono_class_inflate_generic_class (klass, context); } else { - klass = mono_class_get_full (method->klass->image, token, context); + klass = mono_class_get_and_inflate_typespec_checked (method->klass->image, token, context, &error); + mono_error_cleanup (&error); /* FIXME don't swallow the error */ } if (klass) mono_class_init (klass); @@ -10943,7 +10945,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MONO_INST_NEW (cfg, ins, *ip); --sp; CHECK_OPSIZE (5); - klass = mono_class_get_full (image, read32 (ip + 1), generic_context); + klass = mono_class_get_and_inflate_typespec_checked (image, read32 (ip + 1), generic_context, &error); + mono_error_cleanup (&error); /* FIXME don't swallow the error */ CHECK_TYPELOAD (klass); mono_class_init (klass); @@ -10983,7 +10986,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MONO_INST_NEW (cfg, ins, *ip); --sp; CHECK_OPSIZE (5); - klass = mono_class_get_full (image, read32 (ip + 1), generic_context); + klass = mono_class_get_and_inflate_typespec_checked (image, read32 (ip + 1), generic_context, &error); + mono_error_cleanup (&error); /* FIXME don't swallow the error */ CHECK_TYPELOAD (klass); mono_class_init (klass); @@ -12162,7 +12166,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MonoType *type = mono_type_create_from_typespec (image, token); val = mono_type_size (type, &ialign); } else { - MonoClass *klass = mono_class_get_full (image, token, generic_context); + MonoClass *klass = mono_class_get_and_inflate_typespec_checked (image, token, generic_context, &error); + mono_error_cleanup (&error); /* FIXME don't swallow the error */ CHECK_TYPELOAD (klass); mono_class_init (klass); val = mono_type_size (&klass->byval_arg, &ialign); From 5fa8e1abe7357b0f0f5358634cddb21340b5e591 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 1 Sep 2014 00:09:07 -0400 Subject: [PATCH 070/543] [runtime] Plug MonoError into another function. --- mono/metadata/class.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index c776de2dd91..668789fea13 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -1259,7 +1259,7 @@ mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* con * in a separate function since it is cheaper than calling mono_class_setup_fields. */ static MonoType* -mono_class_find_enum_basetype (MonoClass *class) +mono_class_find_enum_basetype (MonoClass *class, MonoError *error) { MonoGenericContainer *container = NULL; MonoImage *m = class->image; @@ -1268,6 +1268,8 @@ mono_class_find_enum_basetype (MonoClass *class) g_assert (class->enumtype); + mono_error_init (error); + if (class->generic_container) container = class->generic_container; else if (class->generic_class) { @@ -1292,27 +1294,41 @@ mono_class_find_enum_basetype (MonoClass *class) if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields continue; - if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) - return NULL; + if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) { + mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]); + goto fail; + } sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]); mono_metadata_decode_value (sig, &sig); /* FIELD signature == 0x06 */ - if (*sig != 0x06) - return NULL; + if (*sig != 0x06) { + mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig); + goto fail; + } ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig); - if (!ftype) - return NULL; + if (!ftype) { + if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/ + mono_error_set_from_loader_error (error); + else + mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]); + goto fail; + } if (class->generic_class) { //FIXME do we leak here? - ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class)); + ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error); + if (!mono_error_ok (error)) + goto fail; ftype->attrs = cols [MONO_FIELD_FLAGS]; } return ftype; } + mono_error_set_type_load_class (error, class, "Could not find base type"); +fail: + g_assert (!mono_loader_get_last_error ()); return NULL; } @@ -5786,11 +5802,11 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError } if (class->enumtype) { - MonoType *enum_basetype = mono_class_find_enum_basetype (class); + MonoType *enum_basetype = mono_class_find_enum_basetype (class, error); if (!enum_basetype) { /*set it to a default value as the whole runtime can't handle this to be null*/ class->cast_class = class->element_class = mono_defaults.int32_class; - mono_class_set_failure_and_error (class, error, "Could not enum basetype"); + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error))); mono_loader_unlock (); mono_profiler_class_loaded (class, MONO_PROFILE_FAILED); g_assert (!mono_loader_get_last_error ()); From 3968beaced07706bf7dc71576b2aede00731e74d Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 1 Sep 2014 05:36:55 -0400 Subject: [PATCH 071/543] [runtime] Introduce MonoError to mono_type_create_from_typespec. --- mono/metadata/class.c | 10 ++-------- mono/metadata/metadata-internals.h | 2 ++ mono/metadata/metadata.c | 27 +++++++++++++++++++++++++-- mono/mini/method-to-ir.c | 6 +++++- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 668789fea13..f45f9450452 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -6374,18 +6374,12 @@ mono_class_from_mono_type (MonoType *type) static MonoType * mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error) { - MonoType *t = mono_type_create_from_typespec (image, type_spec); + MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error); - mono_error_init (error); *did_inflate = FALSE; - if (!t) { - char *name = mono_class_name_from_token (image, type_spec); - char *assembly = mono_assembly_name_from_token (image, type_spec); - mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec); - mono_loader_clear_error (); /*FIXME don't swallow the error*/ + if (!t) return NULL; - } if (context && (context->class_inst || context->method_inst)) { MonoType *inflated = inflate_generic_type (NULL, t, context, error); diff --git a/mono/metadata/metadata-internals.h b/mono/metadata/metadata-internals.h index b04b811d123..c283b7aae36 100644 --- a/mono/metadata/metadata-internals.h +++ b/mono/metadata/metadata-internals.h @@ -800,6 +800,8 @@ MonoMethod *mono_get_method_constrained_with_method (MonoImage *image, MonoMetho void mono_type_set_alignment (MonoTypeEnum type, int align) MONO_INTERNAL; MonoAotCacheConfig *mono_get_aot_cache_config (void) MONO_INTERNAL; +MonoType * +mono_type_create_from_typespec_checked (MonoImage *image, guint32 type_spec, MonoError *error) MONO_INTERNAL; #endif /* __MONO_METADATA_INTERNALS_H__ */ diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index d4dde822b6a..efef401aae7 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -5287,12 +5287,26 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx) /** * @image: context where the image is created * @type_spec: typespec token + * @deprecated use mono_type_create_from_typespec_checked that has proper error handling * * Creates a MonoType representing the TypeSpec indexed by the @type_spec * token. */ MonoType * mono_type_create_from_typespec (MonoImage *image, guint32 type_spec) +{ + MonoError error; + MonoType *type = mono_type_create_from_typespec_checked (image, type_spec, &error); + if (!type) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /* FIXME don't swallow error*/ + } + return type; +} + +MonoType * +mono_type_create_from_typespec_checked (MonoImage *image, guint32 type_spec, MonoError *error) + { guint32 idx = mono_metadata_token_index (type_spec); MonoTableInfo *t; @@ -5301,6 +5315,8 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec) guint32 len; MonoType *type, *type2; + mono_error_init (error); + mono_image_lock (image); type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)); mono_image_unlock (image); @@ -5312,14 +5328,21 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec) mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE); ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]); - if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL)) + if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL)) { + mono_error_set_bad_image (error, image, "Could not verify type spec %08x.", type_spec); return NULL; + } len = mono_metadata_decode_value (ptr, &ptr); type = mono_metadata_parse_type_internal (image, NULL, MONO_PARSE_TYPE, 0, TRUE, ptr, &ptr); - if (!type) + if (!type) { + if (mono_loader_get_last_error ()) + mono_error_set_from_loader_error (error); + else + mono_error_set_bad_image (error, image, "Could not parse type spec %08x.", type_spec); return NULL; + } type2 = mono_metadata_type_dup (image, type); mono_metadata_free_type (type); diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 89982b070a1..b7e2307b23c 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -12163,7 +12163,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b CHECK_OPSIZE (6); token = read32 (ip + 2); if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC && !image_is_dynamic (method->klass->image) && !generic_context) { - MonoType *type = mono_type_create_from_typespec (image, token); + MonoType *type = mono_type_create_from_typespec_checked (image, token, &error); + mono_error_cleanup (&error); /* FIXME don't swallow the error */ + if (!type) + UNVERIFIED; + val = mono_type_size (type, &ialign); } else { MonoClass *klass = mono_class_get_and_inflate_typespec_checked (image, token, generic_context, &error); From 2ed68d65e8a05c349ce264db883004dbfaafab1e Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 1 Sep 2014 05:50:36 -0400 Subject: [PATCH 072/543] [runtime] Change mono_type_get_full to use MonoError properly. --- mono/metadata/class-internals.h | 2 +- mono/metadata/class.c | 37 +++++++++++++++------------------ mono/metadata/verify.c | 4 +++- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 5ac81279781..766488983b2 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -1294,7 +1294,7 @@ MONO_API gboolean mono_class_is_valid_enum (MonoClass *klass); MonoType * -mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context) MONO_INTERNAL; +mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error) MONO_INTERNAL; gboolean mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass) MONO_INTERNAL; diff --git a/mono/metadata/class.c b/mono/metadata/class.c index f45f9450452..98efd9c2021 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -7222,33 +7222,33 @@ mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error) /** - * mono_type_get_full: + * mono_type_get_checked: * @image: the image where the type resides * @type_token: the token for the type * @context: the generic context used to evaluate generic instantiations in + * @error: Error handling context * * This functions exists to fullfill the fact that sometimes it's desirable to have access to the * * Returns: the MonoType that represents @type_token in @image */ MonoType * -mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context) +mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error) { - MonoError error; MonoType *type = NULL; gboolean inflated = FALSE; + mono_error_init (error); + //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then? if (image_is_dynamic (image)) return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context)); if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) { - MonoClass *class = mono_class_get_checked (image, type_token, &error); + MonoClass *class = mono_class_get_checked (image, type_token, error); - if (!mono_error_ok (&error)) { - mono_loader_set_error_from_mono_error (&error); - /*FIXME don't swallow the error message*/ - mono_error_cleanup (&error); + if (!class) { + g_assert (!mono_loader_get_last_error ()); return NULL; } @@ -7256,17 +7256,10 @@ mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *co return mono_class_get_type (class); } - type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error); + type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error); - if (!mono_error_ok (&error)) { - char *name = mono_class_name_from_token (image, type_token); - char *assembly = mono_assembly_name_from_token (image, type_token); - - g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error)); - - mono_loader_set_error_type_load (name, assembly); - /*FIXME don't swallow the error message.*/ - mono_error_cleanup (&error); + if (!type) { + g_assert (!mono_loader_get_last_error ()); return NULL; } @@ -8361,12 +8354,16 @@ mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class, case MONO_TOKEN_TYPE_DEF: case MONO_TOKEN_TYPE_REF: case MONO_TOKEN_TYPE_SPEC: { + MonoError error; MonoType *type; if (handle_class) *handle_class = mono_defaults.typehandle_class; - type = mono_type_get_full (image, token, context); - if (!type) + type = mono_type_get_checked (image, token, context, &error); + if (!type) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /* FIXME Don't swallow the error */ return NULL; + } mono_class_init (mono_class_from_mono_type (type)); /* We return a MonoType* as handle */ return type; diff --git a/mono/metadata/verify.c b/mono/metadata/verify.c index 50781a4bbf4..95bde8efbc5 100644 --- a/mono/metadata/verify.c +++ b/mono/metadata/verify.c @@ -1004,11 +1004,13 @@ verifier_load_type (VerifyContext *ctx, int token, const char *opcode) { MonoClass *class = mono_method_get_wrapper_data (ctx->method, (guint32)token); type = class ? &class->byval_arg : NULL; } else { + MonoError error; if (!IS_TYPE_DEF_OR_REF_OR_SPEC (token) || !token_bounds_check (ctx->image, token)) { ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid type token 0x%08x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE); return NULL; } - type = mono_type_get_full (ctx->image, token, ctx->generic_context); + type = mono_type_get_checked (ctx->image, token, ctx->generic_context, &error); + mono_error_cleanup (&error); /*FIXME don't swallow the error */ } if (!type || mono_loader_get_last_error ()) { From 7dd6476b8e3aaac2a5f9b392cae8008c74232e42 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 1 Sep 2014 22:09:30 -0400 Subject: [PATCH 073/543] [runtime] Use MonoError in exception.c --- mono/metadata/exception.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mono/metadata/exception.c b/mono/metadata/exception.c index 24bfd6ed5ba..cf42445fa78 100644 --- a/mono/metadata/exception.c +++ b/mono/metadata/exception.c @@ -87,10 +87,12 @@ mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, MonoException * mono_exception_from_token (MonoImage *image, guint32 token) { + MonoError error; MonoClass *klass; MonoObject *o; - klass = mono_class_get (image, token); + klass = mono_class_get_checked (image, token, &error); + g_assert (mono_error_ok (&error)); /* FIXME handle the error. */ o = mono_object_new (mono_domain_get (), klass); g_assert (o != NULL); @@ -197,7 +199,9 @@ MonoException * mono_exception_from_token_two_strings (MonoImage *image, guint32 token, MonoString *a1, MonoString *a2) { - MonoClass *klass = mono_class_get (image, token); + MonoError error; + MonoClass *klass = mono_class_get_checked (image, token, &error); + g_assert (mono_error_ok (&error)); /* FIXME handle the error. */ return create_exception_two_strings (klass, a1, a2); } From 4b726a17b810889527e17c46f53feb14affb17eb Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 8 Sep 2014 23:18:20 -0400 Subject: [PATCH 074/543] Introduce mono_class_from_name_case_checked --- mono/metadata/class-internals.h | 3 +++ mono/metadata/class.c | 16 ++++++++++++++-- mono/metadata/reflection.c | 9 ++++++--- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 766488983b2..32b5ef4561e 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -1391,4 +1391,7 @@ mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error) MonoClass * mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error) MONO_INTERNAL; +MonoClass * +mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error) MONO_INTERNAL; + #endif /* __MONO_METADATA_CLASS_INTERBALS_H__ */ diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 98efd9c2021..ec4c2285739 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -7419,6 +7419,7 @@ find_nocase (gpointer key, gpointer value, gpointer user_data) * @image: The MonoImage where the type is looked up in * @name_space: the type namespace * @name: the type short name. + * @deprecated: use the _checked variant * * Obtains a MonoClass with a given namespace and a given name which * is located in the given MonoImage. The namespace and name @@ -7426,6 +7427,15 @@ find_nocase (gpointer key, gpointer value, gpointer user_data) */ MonoClass * mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name) +{ + MonoError error; + MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error); + g_assert (!mono_error_ok (&error)); + return res; +} + +MonoClass * +mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error) { MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF]; guint32 cols [MONO_TYPEDEF_SIZE]; @@ -7433,6 +7443,8 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char const char *nspace; guint32 i, visib; + mono_error_init (error); + if (image_is_dynamic (image)) { guint32 token = 0; FindUserData user_data; @@ -7461,7 +7473,7 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char mono_image_unlock (image); if (token) - return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token); + return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error); else return NULL; @@ -7480,7 +7492,7 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]); nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]); if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0) - return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i); + return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error); } return NULL; } diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index 3691da1b5dd..1c7ac49f584 100644 --- a/mono/metadata/reflection.c +++ b/mono/metadata/reflection.c @@ -7487,10 +7487,13 @@ mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoT if (!image) image = mono_defaults.corlib; - if (ignorecase) - klass = mono_class_from_name_case (image, info->name_space, info->name); - else + if (ignorecase) { + MonoError error; + klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error); + g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */ + } else { klass = mono_class_from_name (image, info->name_space, info->name); + } if (!klass) return NULL; for (mod = info->nested; mod; mod = mod->next) { From ec7be0fd36c7a10b6160f7f1fcef6a4cef83864b Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 8 Sep 2014 23:26:01 -0400 Subject: [PATCH 075/543] [utils] Add mono_error_convert_to_exception. --- mono/utils/mono-error-internals.h | 3 +++ mono/utils/mono-error.c | 31 ++++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/mono/utils/mono-error-internals.h b/mono/utils/mono-error-internals.h index 672e2a75afa..ac2394fa41c 100644 --- a/mono/utils/mono-error-internals.h +++ b/mono/utils/mono-error-internals.h @@ -71,6 +71,9 @@ mono_error_set_from_loader_error (MonoError *error) MONO_INTERNAL; MonoException* mono_error_prepare_exception (MonoError *error, MonoError *error_out) MONO_INTERNAL; +MonoException* +mono_error_convert_to_exception (MonoError *error) MONO_INTERNAL; + void mono_error_raise_exception (MonoError *error) MONO_INTERNAL; diff --git a/mono/utils/mono-error.c b/mono/utils/mono-error.c index 57184d9d63b..63d6fcc00f8 100644 --- a/mono/utils/mono-error.c +++ b/mono/utils/mono-error.c @@ -636,20 +636,18 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) } /* -Raises the exception of @error. -Does nothing if @error has a success error code. -Aborts in case of a double fault. This happens when it can't recover from an error caused by trying -to construct the first exception object. -The error object @error is cleaned up. +Convert this MonoError to an exception if it's faulty or return NULL. +The error object is cleant after. */ -void -mono_error_raise_exception (MonoError *target_error) + +MonoException* +mono_error_convert_to_exception (MonoError *target_error) { MonoError error; MonoException *ex; if (mono_error_ok (target_error)) - return; + return NULL; ex = mono_error_prepare_exception (target_error, &error); if (!mono_error_ok (&error)) { @@ -661,6 +659,21 @@ mono_error_raise_exception (MonoError *target_error) mono_error_cleanup (&error); } mono_error_cleanup (target_error); + return ex; +} - mono_raise_exception (ex); + +/* +Raises the exception of @error. +Does nothing if @error has a success error code. +Aborts in case of a double fault. This happens when it can't recover from an error caused by trying +to construct the first exception object. +The error object @error is cleaned up. +*/ +void +mono_error_raise_exception (MonoError *target_error) +{ + MonoException *ex = mono_error_convert_to_exception (target_error); + if (ex) + mono_raise_exception (ex); } From a94aa47cd81b20d976cb5916170c046fbe8ff130 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 8 Sep 2014 23:32:12 -0400 Subject: [PATCH 076/543] [runtime] Make icall use mono_class_get_checked. --- mono/metadata/icall.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index ad2b82777a6..763b2f638bf 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -907,11 +907,12 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (Mo ICALL_EXPORT void ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image) { - MONO_ARCH_SAVE_REGS; + MonoError error; mono_image_check_for_module_cctor (image); if (image->has_module_cctor) { - MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1); + MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error); + mono_error_raise_exception (&error); /*It's fine to raise the exception here*/ mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE)); } @@ -1673,8 +1674,7 @@ ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *fie { MonoError error; MonoType *type = mono_field_get_type_checked (field->field, &error); - if (!mono_error_ok (&error)) - mono_error_raise_exception (&error); + mono_error_raise_exception (&error); return type_array_from_modifiers (field->field->parent->image, type, optional); } @@ -5161,21 +5161,16 @@ mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **excepti attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS); visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK; if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) { - klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF); + MonoError error; + klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error); + g_assert (!mono_loader_get_last_error ()); /* Plug any leaks */ + if (klass) { mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg)); } else { - MonoLoaderError *error; - MonoException *ex; - - error = mono_loader_get_last_error (); - g_assert (error != NULL); - - ex = mono_loader_error_prepare_exception (error); + MonoException *ex = mono_error_convert_to_exception (&error); mono_array_setref (*exceptions, count, ex); } - if (mono_loader_get_last_error ()) - mono_loader_clear_error (); count++; } } @@ -5266,7 +5261,7 @@ ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, mono_loader_clear_error (); exl = mono_array_new (domain, mono_defaults.exception_class, length); - /* Types for which mono_class_get () succeeded */ + /* Types for which mono_class_get_checked () succeeded */ for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) { MonoException *exc = mono_class_get_exception_for_failure (tmp->data); mono_array_setref (exl, i, exc); @@ -5321,6 +5316,7 @@ ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName * ICALL_EXPORT MonoReflectionType* ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module) { + MonoError error; MonoDomain *domain = mono_object_domain (module); MonoClass *klass; @@ -5332,7 +5328,8 @@ ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module) /* These images do not have a global type */ return NULL; - klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF); + klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error); + mono_error_raise_exception (&error); return mono_type_get_object (domain, &klass->byval_arg); } @@ -7416,6 +7413,8 @@ ves_icall_System_Char_GetDataTablePointers (int category_data_version, /* * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes * and avoid useless allocations. + * + * MAY THROW */ static MonoArray* type_array_from_modifiers (MonoImage *image, MonoType *type, int optional) @@ -7432,7 +7431,9 @@ type_array_from_modifiers (MonoImage *image, MonoType *type, int optional) count = 0; for (i = 0; i < type->num_mods; ++i) { if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) { - MonoClass *klass = mono_class_get (image, type->modifiers [i].token); + MonoError error; + MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error); + mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */ mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg)); count++; } From 6382fd247d34c4b84719a16bf1adeea9e8cd84e4 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 9 Sep 2014 00:28:01 -0400 Subject: [PATCH 077/543] [runtime] Cleanup usage of mono_class_get in loader.c --- mono/metadata/loader.c | 51 +++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index 1ad1a1b650e..09ea19b3d79 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -452,7 +452,12 @@ field_from_memberref (MonoImage *image, guint32 token, MonoClass **retklass, switch (class) { case MONO_MEMBERREF_PARENT_TYPEDEF: class_table = MONO_TOKEN_TYPE_DEF; - klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | nindex); + klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | nindex, &error); + if (!mono_error_ok (&error)) { + /*FIXME don't swallow the error message*/ + mono_error_cleanup (&error); + } + break; case MONO_MEMBERREF_PARENT_TYPEREF: class_table = MONO_TOKEN_TYPE_REF; @@ -522,6 +527,7 @@ MonoClassField* mono_field_from_token (MonoImage *image, guint32 token, MonoClass **retklass, MonoGenericContext *context) { + MonoError error; MonoClass *k; guint32 type; MonoClassField *field; @@ -552,9 +558,12 @@ mono_field_from_token (MonoImage *image, guint32 token, MonoClass **retklass, type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token)); if (!type) return NULL; - k = mono_class_get (image, MONO_TOKEN_TYPE_DEF | type); - if (!k) + k = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | type, &error); + if (!k) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /*FIXME don't swallow the error message*/ return NULL; + } mono_class_init (k); if (retklass) *retklass = k; @@ -983,20 +992,16 @@ method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typesp */ klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_SPEC | nindex, typespec_context, &error); if (!klass) { - char *name = mono_class_name_from_token (image, MONO_TOKEN_TYPE_SPEC | nindex); - g_warning ("Missing method %s in assembly %s, type %s", mname, image->name, name); - mono_loader_set_error_type_load (name, image->assembly_name); - g_free (name); + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /*FIXME don't swallow the error message*/ return NULL; } break; case MONO_MEMBERREF_PARENT_TYPEDEF: - klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | nindex); + klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | nindex, &error); if (!klass) { - char *name = mono_class_name_from_token (image, MONO_TOKEN_TYPE_DEF | nindex); - g_warning ("Missing method %s in assembly %s, type %s", mname, image->name, name); - mono_loader_set_error_type_load (name, image->assembly_name); - g_free (name); + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /*FIXME don't swallow the error message*/ return NULL; } break; @@ -1686,6 +1691,7 @@ static MonoMethod * mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, MonoGenericContext *context, gboolean *used_context) { + MonoError error; MonoMethod *result; int table = mono_metadata_token_table (token); int idx = mono_metadata_token_index (token); @@ -1727,6 +1733,18 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, return NULL; } + if (!klass) { + guint32 type = mono_metadata_typedef_from_method (image, token); + if (!type) + return NULL; + klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | type, &error); + if (klass == NULL) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /*FIXME don't swallow the error message*/ + return NULL; + } + } + mono_metadata_decode_row (&image->tables [MONO_TABLE_METHOD], idx - 1, cols, 6); if ((cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL) || @@ -1739,15 +1757,6 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, mono_stats.method_count ++; - if (!klass) { /*FIXME put this before the image alloc*/ - guint32 type = mono_metadata_typedef_from_method (image, token); - if (!type) - return NULL; - klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | type); - if (klass == NULL) - return NULL; - } - result->slot = -1; result->klass = klass; result->flags = cols [2]; From a17da53c374ea07b9a95f0d26ba6202fb6470914 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 9 Sep 2014 00:35:26 -0400 Subject: [PATCH 078/543] [runtime] Cleanup usage of mono_class_get to object.c --- mono/metadata/object.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/mono/metadata/object.c b/mono/metadata/object.c index daa72aec6f2..a2aa759293b 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -287,8 +287,19 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception) if (!klass->image->checked_module_cctor) { mono_image_check_for_module_cctor (klass->image); if (klass->image->has_module_cctor) { - MonoClass *module_klass = mono_class_get (klass->image, MONO_TOKEN_TYPE_DEF | 1); - MonoVTable *module_vtable = mono_class_vtable_full (vtable->domain, module_klass, raise_exception); + MonoError error; + MonoClass *module_klass; + MonoVTable *module_vtable; + + module_klass = mono_class_get_checked (klass->image, MONO_TOKEN_TYPE_DEF | 1, &error); + if (!module_klass) { + exc = mono_error_convert_to_exception (&error); + if (raise_exception) + mono_raise_exception (exc); + return exc; + } + + module_vtable = mono_class_vtable_full (vtable->domain, module_klass, raise_exception); if (!module_vtable) return NULL; exc = mono_runtime_class_init_full (module_vtable, raise_exception); @@ -4596,9 +4607,11 @@ mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *p MonoObject * mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token) { + MonoError error; MonoClass *class; - class = mono_class_get (image, token); + class = mono_class_get_checked (image, token, &error); + g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ return mono_object_new (domain, class); } From 3bbedfebb754017e8aa6141fad6240c7d3bc604c Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 9 Sep 2014 10:22:51 -0400 Subject: [PATCH 079/543] [runtime] Update marshal.c to use mono_class_get_checked. --- mono/metadata/marshal.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 88bbaeb7a02..0c8fe33f219 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -2739,6 +2739,7 @@ mono_wrapper_info_create (MonoMethodBuilder *mb, WrapperSubtype subtype) static MonoClass* get_wrapper_target_class (MonoImage *image) { + MonoError error; MonoClass *klass; /* @@ -2754,10 +2755,12 @@ get_wrapper_target_class (MonoImage *image) * To avoid these problems, we put the wrappers into the class of * the image. */ - if (image_is_dynamic (image)) + if (image_is_dynamic (image)) { klass = ((MonoDynamicImage*)image)->wrappers_type; - else - klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, 1)); + } else { + klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, 1), &error); + g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ + } g_assert (klass); return klass; @@ -9490,8 +9493,9 @@ mono_marshal_set_callconv_from_modopt (MonoMethod *method, MonoMethodSignature * /* Why is this a modopt ? */ if (sig->ret && sig->ret->num_mods) { for (i = 0; i < sig->ret->num_mods; ++i) { - MonoClass *cmod_class = mono_class_get (method->klass->image, sig->ret->modifiers [i].token); - g_assert (cmod_class); + MonoError error; + MonoClass *cmod_class = mono_class_get_checked (method->klass->image, sig->ret->modifiers [i].token, &error); + g_assert (mono_error_ok (&error)); if ((cmod_class->image == mono_defaults.corlib) && !strcmp (cmod_class->name_space, "System.Runtime.CompilerServices")) { if (!strcmp (cmod_class->name, "CallConvCdecl")) csig->call_convention = MONO_CALL_C; From 666ea5f867dbee265af62feecef1b4477b0799a3 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 9 Sep 2014 10:26:16 -0400 Subject: [PATCH 080/543] [runtime] Update reflection.c to use mono_class_get_checked. --- mono/metadata/reflection.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index 1c7ac49f584..e74fe3f0d65 100644 --- a/mono/metadata/reflection.c +++ b/mono/metadata/reflection.c @@ -1702,8 +1702,10 @@ fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, M if (type->num_mods) { for (i = 0; i < type->num_mods; ++i) { if (field_image) { - MonoClass *class = mono_class_get (field_image, type->modifiers [i].token); - g_assert (class); + MonoError error; + MonoClass *class = mono_class_get_checked (field_image, type->modifiers [i].token, &error); + g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ + token = mono_image_typedef_or_ref (assembly, &class->byval_arg); } else { token = type->modifiers [i].token; @@ -3798,7 +3800,9 @@ mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModu t = &image->tables [MONO_TABLE_TYPEDEF]; for (i = 0; i < t->rows; ++i) { - MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1)); + MonoError error; + MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error); + g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ if (klass->flags & TYPE_ATTRIBUTE_PUBLIC) mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly); @@ -9973,7 +9977,7 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb) mono_class_set_ref_info (klass, tb); - /* Put into cache so mono_class_get () will find it. + /* Put into cache so mono_class_get_checked () will find it. Skip nested types as those should not be available on the global scope. */ if (!tb->nesting_type) mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx); From 00f631312f7d890998c672cabb408fc6b649217c Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 9 Sep 2014 15:54:15 -0400 Subject: [PATCH 081/543] [runtime] Fix error handling in mono_metadata_parse_mh_full. --- mono/metadata/metadata.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index efef401aae7..6b598020f03 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -3381,7 +3381,16 @@ parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr) if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) { ec->data.filter_offset = tof_value; } else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) { - ec->data.catch_class = tof_value? mono_class_get (m, tof_value): 0; + ec->data.catch_class = NULL; + if (tof_value) { + MonoError error; + ec->data.catch_class = mono_class_get_checked (m, tof_value, &error); + if (!mono_error_ok (&error)) { + mono_error_cleanup (&error); /* FIXME don't swallow the error */ + g_free (clauses); + return NULL; + } + } } else { ec->data.catch_class = NULL; } @@ -3484,7 +3493,7 @@ mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *sum MonoMethodHeader * mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr) { - MonoMethodHeader *mh; + MonoMethodHeader *mh = NULL; unsigned char flags = *(const unsigned char *) ptr; unsigned char format = flags & METHOD_HEADER_FORMAT_MASK; guint16 fat_flags; @@ -3540,11 +3549,11 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons if (local_var_sig_tok) { int idx = (local_var_sig_tok & 0xffffff)-1; if (idx >= t->rows || idx < 0) - return NULL; + goto fail; mono_metadata_decode_row (t, idx, cols, 1); if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL)) - return NULL; + goto fail; } if (fat_flags & METHOD_HEADER_MORE_SECTS) clauses = parse_section_data (m, &num_clauses, (const unsigned char*)ptr); @@ -3563,11 +3572,8 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons for (i = 0; i < len; ++i) { mh->locals [i] = mono_metadata_parse_type_internal (m, container, MONO_PARSE_LOCAL, 0, TRUE, locals_ptr, &locals_ptr); - if (!mh->locals [i]) { - g_free (clauses); - g_free (mh); - return NULL; - } + if (!mh->locals [i]) + goto fail; } } else { mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause)); @@ -3585,6 +3591,11 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons mh->num_clauses = num_clauses; } return mh; +fail: + g_free (clauses); + g_free (mh); + return NULL; + } /* From 65f17c2c265f05e65c97fdd42f73aee4f9218a2d Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 9 Sep 2014 16:33:06 -0400 Subject: [PATCH 082/543] [jit] Fix error handling in a few places in the jit. --- mono/mini/aot-compiler.c | 30 ++++++++++++++++++------------ mono/mini/aot-runtime.c | 15 +++++++++++---- mono/mini/jit-icalls.c | 8 ++++---- mono/mini/method-to-ir.c | 4 +++- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 0697d0ba6be..299b6c2cc63 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -3539,14 +3539,15 @@ add_wrappers (MonoAotCompile *acfg) /* delegate-invoke wrappers */ for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) { + MonoError error; MonoClass *klass; MonoCustomAttrInfo *cattr; token = MONO_TOKEN_TYPE_DEF | (i + 1); - klass = mono_class_get (acfg->image, token); + klass = mono_class_get_checked (acfg->image, token, &error); if (!klass) { - mono_loader_clear_error (); + mono_error_cleanup (&error); continue; } @@ -3627,13 +3628,14 @@ add_wrappers (MonoAotCompile *acfg) /* array access wrappers */ for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) { + MonoError error; MonoClass *klass; token = MONO_TOKEN_TYPE_SPEC | (i + 1); - klass = mono_class_get (acfg->image, token); + klass = mono_class_get_checked (acfg->image, token, &error); if (!klass) { - mono_loader_clear_error (); + mono_error_cleanup (&error); continue; } @@ -3810,13 +3812,14 @@ add_wrappers (MonoAotCompile *acfg) /* StructureToPtr/PtrToStructure wrappers */ for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) { + MonoError error; MonoClass *klass; token = MONO_TOKEN_TYPE_DEF | (i + 1); - klass = mono_class_get (acfg->image, token); + klass = mono_class_get_checked (acfg->image, token, &error); if (!klass) { - mono_loader_clear_error (); + mono_error_cleanup (&error); continue; } @@ -4275,13 +4278,14 @@ add_generic_instances (MonoAotCompile *acfg) } for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) { + MonoError error; MonoClass *klass; token = MONO_TOKEN_TYPE_SPEC | (i + 1); - klass = mono_class_get (acfg->image, token); + klass = mono_class_get_checked (acfg->image, token, &error); if (!klass || klass->rank) { - mono_loader_clear_error (); + mono_error_cleanup (&error); continue; } @@ -5602,14 +5606,15 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) static guint32 emit_klass_info (MonoAotCompile *acfg, guint32 token) { - MonoClass *klass = mono_class_get (acfg->image, token); + MonoError error; + MonoClass *klass = mono_class_get_checked (acfg->image, token, &error); guint8 *p, *buf; int i, buf_size, res; gboolean no_special_static, cant_encode; gpointer iter = NULL; if (!klass) { - mono_loader_clear_error (); + mono_error_cleanup (&error); buf_size = 16; @@ -7837,10 +7842,11 @@ emit_class_name_table (MonoAotCompile *acfg) for (i = 0; i < table_size; ++i) g_ptr_array_add (table, NULL); for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) { + MonoError error; token = MONO_TOKEN_TYPE_DEF | (i + 1); - klass = mono_class_get (acfg->image, token); + klass = mono_class_get_checked (acfg->image, token, &error); if (!klass) { - mono_loader_clear_error (); + mono_error_cleanup (&error); continue; } full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME); diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 272616f04d9..98361554a3e 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -405,6 +405,7 @@ decode_generic_context (MonoAotModule *module, MonoGenericContext *ctx, guint8 * static MonoClass* decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf) { + MonoError error; MonoImage *image; MonoClass *klass = NULL, *eklass; guint32 token, rank, idx; @@ -423,21 +424,24 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf) image = load_image (module, 0, TRUE); if (!image) return NULL; - klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF + idx); + klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF + idx, &error); + g_assert (mono_error_ok (&error)); break; case MONO_AOT_TYPEREF_TYPEDEF_INDEX_IMAGE: idx = decode_value (p, &p); image = load_image (module, decode_value (p, &p), TRUE); if (!image) return NULL; - klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF + idx); + klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF + idx, &error); + g_assert (mono_error_ok (&error)); break; case MONO_AOT_TYPEREF_TYPESPEC_TOKEN: token = decode_value (p, &p); image = module->assembly->image; if (!image) return NULL; - klass = mono_class_get (image, token); + klass = mono_class_get_checked (image, token, &error); + g_assert (mono_error_ok (&error)); break; case MONO_AOT_TYPEREF_GINST: { MonoClass *gclass; @@ -2291,8 +2295,11 @@ mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const ch name_space2 = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]); if (!strcmp (name, name2) && !strcmp (name_space, name_space2)) { + MonoError error; amodule_unlock (amodule); - *klass = mono_class_get (image, token); + *klass = mono_class_get_checked (image, token, &error); + if (!mono_error_ok (&error)) + mono_error_cleanup (&error); /* FIXME don't swallow the error */ /* Add to cache */ if (*klass) { diff --git a/mono/mini/jit-icalls.c b/mono/mini/jit-icalls.c index 8c7c00c8322..fcfcf4f3cd1 100644 --- a/mono/mini/jit-icalls.c +++ b/mono/mini/jit-icalls.c @@ -17,7 +17,7 @@ #endif #include "jit-icalls.h" - +#include void* mono_ldftn (MonoMethod *method) { @@ -1022,9 +1022,9 @@ mono_helper_ldstr_mscorlib (guint32 idx) MonoObject* mono_helper_newobj_mscorlib (guint32 idx) { - MonoClass *klass = mono_class_get (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx); - - g_assert (klass); + MonoError error; + MonoClass *klass = mono_class_get_checked (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx, &error); + mono_error_raise_exception (&error); return mono_object_new (mono_domain_get (), klass); } diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index b7e2307b23c..a07fee2fd77 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -11110,10 +11110,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b tclass, MONO_RGCTX_INFO_REFLECTION_TYPE); } else if (cfg->compile_aot) { if (method->wrapper_type) { - if (mono_class_get (tclass->image, tclass->type_token) == tclass && !generic_context) { + mono_error_init (&error); //got to do it since there are multiple conditionals below + if (mono_class_get_checked (tclass->image, tclass->type_token, &error) == tclass && !generic_context) { /* Special case for static synchronized wrappers */ EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, tclass->image, tclass->type_token, generic_context); } else { + mono_error_cleanup (&error); /* FIXME don't swallow the error */ /* FIXME: n is not a normal token */ DISABLE_AOT (cfg); EMIT_NEW_PCONST (cfg, ins, NULL); From 5e9eba8ffbb5b1bf9444a9308a0e74cca7f29e32 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Tue, 9 Sep 2014 23:38:12 +0200 Subject: [PATCH 083/543] [system.net.http] Tokenize dash only in range values. Fixes #22764 --- .../System.Net.Http.Headers/ContentRangeHeaderValue.cs | 2 +- .../System.Net.Http/System.Net.Http.Headers/Lexer.cs | 10 +++++++--- .../System.Net.Http.Headers/RangeHeaderValue.cs | 4 ++-- .../MediaTypeHeaderValueTest.cs | 8 ++++++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentRangeHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentRangeHeaderValue.cs index 118d65085f7..1bea52b76e8 100644 --- a/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentRangeHeaderValue.cs +++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentRangeHeaderValue.cs @@ -170,7 +170,7 @@ public static bool TryParse (string input, out ContentRangeHeaderValue parsedVal } else { value.From = nvalue; - t = lexer.Scan (); + t = lexer.Scan (recognizeDash: true); if (t != Token.Type.SeparatorDash) return false; diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/Lexer.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/Lexer.cs index 5bd7d093acf..622e36b0ec2 100644 --- a/mcs/class/System.Net.Http/System.Net.Http.Headers/Lexer.cs +++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/Lexer.cs @@ -247,7 +247,7 @@ public bool ScanCommentOptional (out string value, out Token readToken) return false; } - public Token Scan () + public Token Scan (bool recognizeDash = false) { int start = pos; if (s == null) @@ -279,8 +279,12 @@ public Token Scan () ttype = Token.Type.SeparatorSlash; break; case '-': - ttype = Token.Type.SeparatorDash; - break; + if (recognizeDash) { + ttype = Token.Type.SeparatorDash; + break; + } + + goto default; case ',': ttype = Token.Type.SeparatorComma; break; diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/RangeHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/RangeHeaderValue.cs index ad8e7e2b4f3..36e9c806157 100644 --- a/mcs/class/System.Net.Http/System.Net.Http.Headers/RangeHeaderValue.cs +++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/RangeHeaderValue.cs @@ -127,7 +127,7 @@ public static bool TryParse (string input, out RangeHeaderValue parsedValue) int number; token_read = false; - t = lexer.Scan (); + t = lexer.Scan (recognizeDash: true); switch (t.Kind) { case Token.Type.SeparatorDash: t = lexer.Scan (); @@ -144,7 +144,7 @@ public static bool TryParse (string input, out RangeHeaderValue parsedValue) switch (values.Length) { case 1: - t = lexer.Scan (); + t = lexer.Scan (recognizeDash: true); from = number; switch (t.Kind) { case Token.Type.SeparatorDash: diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/MediaTypeHeaderValueTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/MediaTypeHeaderValueTest.cs index afbf8274b9f..c4b882467aa 100644 --- a/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/MediaTypeHeaderValueTest.cs +++ b/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/MediaTypeHeaderValueTest.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using NUnit.Framework; using System.Net.Http.Headers; +using System.Linq; namespace MonoTests.System.Net.Http.Headers { @@ -81,6 +82,13 @@ public void Parse () Assert.AreEqual ("mu/m", res.MediaType, "#2"); Assert.AreEqual ("jj'", res.CharSet, "#2b"); Assert.AreEqual ("mu/m; CHarset=jj'", res.ToString (), "#2c"); + + res = MediaTypeHeaderValue.Parse ("multipart/form-data; boundary=----Wk"); + Assert.AreEqual ("multipart/form-data", res.MediaType, "#3"); + Assert.IsNull (res.CharSet, "#3b"); + Assert.AreEqual (1, res.Parameters.Count, "#3c"); + Assert.AreEqual (new NameValueHeaderValue ("boundary", "----Wk"), res.Parameters.First (), "#3d"); + Assert.AreEqual ("multipart/form-data; boundary=----Wk", res.ToString (), "#3e"); } [Test] From 6cb9a04fca7adaf2e912013e2efec35d857228dd Mon Sep 17 00:00:00 2001 From: ramtin Date: Tue, 9 Sep 2014 15:07:14 -0700 Subject: [PATCH 084/543] Unit Tests for SourceSwitch. Counting the number of events traced based on the Trace Level --- .../System.Diagnostics/SourceSwitchTest.cs | 78 +++++++++++++++++ .../TextWriterTraceListenerHelper.cs | 85 +++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs diff --git a/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs b/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs index 05e0a6d1294..af0b6609d27 100644 --- a/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs +++ b/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs @@ -43,6 +43,10 @@ namespace MonoTests.System.Diagnostics [TestFixture] public class SourceSwitchTest { + internal TraceSource traceSource { get; set; } + internal TestTextWriterTraceListener txtTraceListener; + + [Test] public void ConstructorNullName () { @@ -98,6 +102,80 @@ public void ShouldTrace2 () Assert.IsTrue (s.ShouldTrace (TraceEventType.Resume), "#9"); Assert.IsTrue (s.ShouldTrace (TraceEventType.Transfer), "#10"); } + + + [SetUp] + public void InitalizeSourceSwitchTest() + { + // Initializing the TraceSource instance + traceSource = new TraceSource ("LoggingTraceSource"); + traceSource.Listeners.Remove("Default"); + traceSource.Switch = new SourceSwitch ("MySwitch"); + + // Initializing the TraceListener instance + txtTraceListener = new TestTextWriterTraceListener (Console.Out); + traceSource.Listeners.Add (txtTraceListener); + } + + [Test] + public void setSwitchToCritical() + { + traceSource.Switch.Level = SourceLevels.Critical; + LogAllTraceLevels (); + // Switch.Level is Critical so it should log Critical + Assert.AreEqual (1, txtTraceListener.TotalMessageCount); + Assert.AreEqual (1, txtTraceListener.CritialMessageCount); + } + + [Test] + public void setSwitchToError() + { + traceSource.Switch.Level = SourceLevels.Error; + LogAllTraceLevels (); + // Switch.Level is Error so it should log Critical, Error + Assert.AreEqual (2, txtTraceListener.TotalMessageCount); + Assert.AreEqual (1, txtTraceListener.ErrorMessageCount); + } + + [Test] + public void setSwitchToWarning() + { + traceSource.Switch.Level = SourceLevels.Warning; + LogAllTraceLevels (); + // Switch.Level is Warning so it should log Critical, Error, Warning + Assert.AreEqual (3, txtTraceListener.TotalMessageCount); + Assert.AreEqual (1, txtTraceListener.WarningMessageCount); + } + + [Test] + public void setSwitchToInfo() + { + traceSource.Switch.Level = SourceLevels.Information; + LogAllTraceLevels (); + // Switch.Level is Information so it should log Critical, Error, Warning, Information + Assert.AreEqual (4, txtTraceListener.TotalMessageCount); + Assert.AreEqual (1, txtTraceListener.InfoMessageCount); + } + + [Test] + public void setSwitchToVerbose() + { + traceSource.Switch.Level = SourceLevels.Verbose; + LogAllTraceLevels (); + // Switch.Level is Verbose so it should log Critical, Error, Warning, Information, Verbose + Assert.AreEqual (5, txtTraceListener.TotalMessageCount); + Assert.AreEqual (1, txtTraceListener.VerboseMessageCount); + } + + void LogAllTraceLevels () + { + traceSource.TraceEvent (TraceEventType.Critical, 123, "Critical Level message."); + traceSource.TraceEvent (TraceEventType.Error, 123, "Error Level message."); + traceSource.TraceEvent (TraceEventType.Warning, 123, "Warning Level message."); + traceSource.TraceEvent (TraceEventType.Information, 123, "Information Level message."); + traceSource.TraceEvent (TraceEventType.Verbose, 123, "Verbose Level message."); + traceSource.Flush (); + } } } diff --git a/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs b/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs new file mode 100644 index 00000000000..0ea779a23a2 --- /dev/null +++ b/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs @@ -0,0 +1,85 @@ +// TextWriterTraceListenerHelper.cs - +// Test Helper for System.Diagnostics/SourceSwitchTest.cs + +// +// Author: +// Ramtin Raji Kermani +// +// Copyright (C) 2006 Novell, Inc (http://www.novell.com) +// +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Diagnostics; + +namespace MonoTests.System.Diagnostics +{ + public class TestTextWriterTraceListener: TextWriterTraceListener + { + public int TotalMessageCount { set; get;} + public int CritialMessageCount { get; set;} + public int ErrorMessageCount { get; set;} + public int WarningMessageCount { get; set;} + public int InfoMessageCount { get; set;} + public int VerboseMessageCount { set; get;} + + public TestTextWriterTraceListener(System.IO.TextWriter textWriter): base(textWriter) + { + Console.WriteLine ("TextWriterTraceListener is instantiated."); + } + + + public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message) + { + base.TraceEvent (eventCache, source, eventType, id, message); + TotalMessageCount++; + + switch (eventType) { + case TraceEventType.Critical: + CritialMessageCount++; break; + case TraceEventType.Error: + ErrorMessageCount++; break; + case TraceEventType.Warning: + WarningMessageCount++; break; + case TraceEventType.Information: + InfoMessageCount++; break; + case TraceEventType.Verbose: + VerboseMessageCount++; break; + default: + break; + } + } + + public void clearMessageCounters() + { + TotalMessageCount = 0; + CritialMessageCount = 0; + WarningMessageCount = 0; + ErrorMessageCount = 0; + InfoMessageCount = 0; + VerboseMessageCount = 0; + } + + } +} + + From ebe2a3df1d9782c339be86cfd1e0224d70c2fdc8 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Wed, 10 Sep 2014 09:47:22 +0200 Subject: [PATCH 085/543] [system.net.http] Handle Content-Disposition in textual form as well. --- .../System.Net.Http.Headers/HttpHeaders.cs | 1 + .../Test/System.Net.Http/StreamContentTest.cs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs index 5717ddd67dc..4f1137a8ccc 100644 --- a/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs +++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs @@ -96,6 +96,7 @@ static HttpHeaders () HeaderInfo.CreateSingle ("Authorization", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle ("Cache-Control", CacheControlHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), HeaderInfo.CreateMulti ("Connection", CollectionParser.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), + HeaderInfo.CreateSingle ("Content-Disposition", ContentDispositionHeaderValue.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateMulti ("Content-Encoding", CollectionParser.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateMulti ("Content-Language", CollectionParser.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateSingle ("Content-Length", Parser.Long.TryParse, HttpHeaderKind.Content), diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http/StreamContentTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http/StreamContentTest.cs index be0c47c5cc0..5d7cd12490c 100644 --- a/mcs/class/System.Net.Http/Test/System.Net.Http/StreamContentTest.cs +++ b/mcs/class/System.Net.Http/Test/System.Net.Http/StreamContentTest.cs @@ -222,6 +222,7 @@ public void Headers () Assert.AreEqual (330, scm.Headers.ContentLength, "#2"); headers.Allow.Add ("a1"); + headers.ContentDisposition = new ContentDispositionHeaderValue ("cd1"); headers.ContentEncoding.Add ("ce1"); headers.ContentLanguage.Add ("cl1"); headers.ContentLength = 23; @@ -234,6 +235,12 @@ public void Headers () headers.Add ("allow", "a2"); + try { + headers.Add ("content-disposition", "cd2"); + Assert.Fail ("content-disposition"); + } catch (FormatException) { + } + headers.Add ("content-encoding", "ce3"); headers.Add ("content-language", "cl2"); @@ -307,6 +314,7 @@ public void Headers () Assert.AreEqual (new MediaTypeHeaderValue ("multipart/*"), headers.ContentType); Assert.AreEqual (new DateTimeOffset (DateTime.Today), headers.Expires); Assert.AreEqual (new DateTimeOffset (DateTime.Today), headers.LastModified); + Assert.AreEqual (new ContentDispositionHeaderValue ("cd1"), headers.ContentDisposition); } [Test] From 462c6b08e98e1cfce343adb7615be994af95166d Mon Sep 17 00:00:00 2001 From: Marius Ungureanu Date: Wed, 10 Sep 2014 13:04:10 +0300 Subject: [PATCH 086/543] [SourceSwitch] Refactor a piece of code. --- mcs/class/System/System.Diagnostics/SourceSwitch.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mcs/class/System/System.Diagnostics/SourceSwitch.cs b/mcs/class/System/System.Diagnostics/SourceSwitch.cs index 3ba6849a44f..e9b29ca3b85 100644 --- a/mcs/class/System/System.Diagnostics/SourceSwitch.cs +++ b/mcs/class/System/System.Diagnostics/SourceSwitch.cs @@ -59,15 +59,11 @@ public bool ShouldTrace (TraceEventType eventType) { switch (eventType) { case TraceEventType.Critical: - return (Level & (SourceLevels)TraceEventType.Critical) != 0; case TraceEventType.Error: - return (Level & (SourceLevels)TraceEventType.Error) != 0; case TraceEventType.Warning: - return (Level & (SourceLevels)TraceEventType.Warning) != 0; case TraceEventType.Information: - return (Level & (SourceLevels)TraceEventType.Information) != 0; case TraceEventType.Verbose: - return (Level & (SourceLevels)TraceEventType.Verbose) != 0; + return (Level & (SourceLevels)eventType) != 0; case TraceEventType.Start: case TraceEventType.Stop: case TraceEventType.Suspend: From 6e5e8d7915636847b35fbd76284373f103756c2c Mon Sep 17 00:00:00 2001 From: Marius Ungureanu Date: Wed, 10 Sep 2014 13:59:49 +0300 Subject: [PATCH 087/543] Fix build failure caused by #1267. --- mcs/class/System/System_test.dll.sources | 1 + 1 file changed, 1 insertion(+) diff --git a/mcs/class/System/System_test.dll.sources b/mcs/class/System/System_test.dll.sources index e47a4c98214..6ff1a9488a3 100644 --- a/mcs/class/System/System_test.dll.sources +++ b/mcs/class/System/System_test.dll.sources @@ -182,6 +182,7 @@ System.Diagnostics/DelimitedListTraceListenerTest.cs System.Diagnostics/EventLogTest.cs System.Diagnostics/StopwatchTest.cs System.Diagnostics/SourceSwitchTest.cs +System.Diagnostics/TextWriterTraceListenerHelper.cs System.Diagnostics/TextWriterTraceListenerTest.cs System.Diagnostics/TraceSourceTest.cs System.Diagnostics/TraceListenerTest.cs From 0537cb3c2a49aa19299503576d87653f156da27a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Wed, 10 Sep 2014 14:26:36 +0200 Subject: [PATCH 088/543] Fix the build --- .../Test/System.Diagnostics/TextWriterTraceListenerHelper.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs b/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs index 0ea779a23a2..f6643b06c23 100644 --- a/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs +++ b/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs @@ -29,6 +29,7 @@ // using System; +using System.IO; using System.Diagnostics; namespace MonoTests.System.Diagnostics @@ -42,7 +43,7 @@ public class TestTextWriterTraceListener: TextWriterTraceListener public int InfoMessageCount { get; set;} public int VerboseMessageCount { set; get;} - public TestTextWriterTraceListener(System.IO.TextWriter textWriter): base(textWriter) + public TestTextWriterTraceListener(TextWriter textWriter): base(textWriter) { Console.WriteLine ("TextWriterTraceListener is instantiated."); } From bbbcc73bde44595e5bd3767d1afafba0fd53a099 Mon Sep 17 00:00:00 2001 From: Martin Baulig Date: Wed, 10 Sep 2014 17:08:09 +0200 Subject: [PATCH 089/543] [websocket]: Fix ClientWebSocket.ReceiveAsync() with small buffer; bug #22704. When calling ClientWebSocket.ReceiveAsync() with a buffer that's smaller than the received chunk, we need to cache the header until next call. --- .../System.Net.WebSockets/ClientWebSocket.cs | 61 +++++++++++-------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/mcs/class/System/System.Net.WebSockets/ClientWebSocket.cs b/mcs/class/System/System.Net.WebSockets/ClientWebSocket.cs index bfa085885e6..d7e999c46f3 100644 --- a/mcs/class/System/System.Net.WebSockets/ClientWebSocket.cs +++ b/mcs/class/System/System.Net.WebSockets/ClientWebSocket.cs @@ -61,6 +61,7 @@ public class ClientWebSocket : WebSocket, IDisposable const int HeaderMaxLength = 14; byte[] headerBuffer; byte[] sendBuffer; + long remaining; public ClientWebSocket () { @@ -226,32 +227,43 @@ public override Task ReceiveAsync (ArraySegment bu ValidateArraySegment (buffer); return Task.Run (() => { EnsureWebSocketState (WebSocketState.Open, WebSocketState.CloseSent); - // First read the two first bytes to know what we are doing next - connection.Read (req, headerBuffer, 0, 2); - var isLast = (headerBuffer[0] >> 7) > 0; - var isMasked = (headerBuffer[1] >> 7) > 0; - int mask = 0; - var type = WireToMessageType ((byte)(headerBuffer[0] & 0xF)); - long length = headerBuffer[1] & 0x7F; - int offset = 0; - if (length == 126) { - offset = 2; - connection.Read (req, headerBuffer, 2, offset); + + bool isLast; + WebSocketMessageType type; + long length; + + if (remaining == 0) { + // First read the two first bytes to know what we are doing next + connection.Read (req, headerBuffer, 0, 2); + isLast = (headerBuffer[0] >> 7) > 0; + var isMasked = (headerBuffer[1] >> 7) > 0; + int mask = 0; + type = WireToMessageType ((byte)(headerBuffer[0] & 0xF)); + length = headerBuffer[1] & 0x7F; + int offset = 0; + if (length == 126) { + offset = 2; + connection.Read (req, headerBuffer, 2, offset); length = (headerBuffer[2] << 8) | headerBuffer[3]; - } else if (length == 127) { - offset = 8; - connection.Read (req, headerBuffer, 2, offset); - length = 0; - for (int i = 2; i <= 9; i++) - length = (length << 8) | headerBuffer[i]; - } + } else if (length == 127) { + offset = 8; + connection.Read (req, headerBuffer, 2, offset); + length = 0; + for (int i = 2; i <= 9; i++) + length = (length << 8) | headerBuffer[i]; + } - if (isMasked) { - connection.Read (req, headerBuffer, 2 + offset, 4); - for (int i = 0; i < 4; i++) { - var pos = i + offset + 2; - mask = (mask << 8) | headerBuffer[pos]; + if (isMasked) { + connection.Read (req, headerBuffer, 2 + offset, 4); + for (int i = 0; i < 4; i++) { + var pos = i + offset + 2; + mask = (mask << 8) | headerBuffer[pos]; + } } + } else { + isLast = (headerBuffer[0] >> 7) > 0; + type = WireToMessageType ((byte)(headerBuffer[0] & 0xF)); + length = remaining; } if (type == WebSocketMessageType.Close) { @@ -264,8 +276,9 @@ public override Task ReceiveAsync (ArraySegment bu } else { var readLength = (int)(buffer.Count < length ? buffer.Count : length); connection.Read (req, buffer.Array, buffer.Offset, readLength); + remaining = length - readLength; - return new WebSocketReceiveResult ((int)length, type, isLast); + return new WebSocketReceiveResult ((int)readLength, type, isLast && remaining == 0); } }); } From f008d4afb632fb1bcffd7538e2cd93db32a88865 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 10 Sep 2014 16:30:03 +0100 Subject: [PATCH 090/543] Test XmlSerialization of element that requires implicit conversion. Covers #20403. --- .../XmlSerializerTestClasses.cs | 43 +++++++++++++++++++ .../XmlSerializerTests.cs | 16 +++++++ 2 files changed, 59 insertions(+) diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs index 62b3698c837..d486b3bcea8 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs @@ -1117,5 +1117,48 @@ public class Bug9193Class [XmlElement ("Extra", Order=1)] public string[] Extra; } + + public class SimpleObjectA + { + [XmlAttribute] + public string Text + { + get; set; + } + + public static implicit operator SimpleObjectA (SimpleObjectB o) + { + return new SimpleObjectA { Text = o.Text }; + } + + public static implicit operator SimpleObjectB (SimpleObjectA o) + { + return new SimpleObjectB { Text = o.Text }; + } + } + + public class SimpleObjectB + { + [XmlAttribute] + public string Text + { + get; set; + } + } + + public class ObjectWithElementRequiringImplicitCast + { + public ObjectWithElementRequiringImplicitCast () { } + public ObjectWithElementRequiringImplicitCast (string text) + { + Object = new SimpleObjectB { Text = text }; + } + + [XmlElement(Type = typeof (SimpleObjectA))] + public SimpleObjectB Object + { + get; set; + } + } } diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs index 6001f7f2476..28f6827c9b6 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs @@ -3332,6 +3332,22 @@ public void TestClassWithXmlAnyElement () using (var sw = new StringWriter ()) ser.Serialize (sw, c); } + + [Test] + public void ClassWithImplicitlyConvertibleElement () + { + var ser = new XmlSerializer (typeof (ObjectWithElementRequiringImplicitCast)); + + var obj = new ObjectWithElementRequiringImplicitCast ("test"); + + using (var w = new StringWriter ()) { + ser.Serialize (w, obj); + using (var r = new StringReader ( w.ToString ())) { + var desObj = (ObjectWithElementRequiringImplicitCast) ser.Deserialize (r); + Assert.AreEqual (obj.Object.Text, desObj.Object.Text); + } + } + } } // Test generated serialization code. From 0804720aaadd42378dbd2487bf5910a051ad00ad Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 10 Sep 2014 17:13:49 +0100 Subject: [PATCH 091/543] ImplicitConvert was using method with wrong parameter and return type. --- .../XmlSerializationWriterInterpreter.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs index 846848a39a3..595d670b655 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs @@ -359,16 +359,15 @@ object ImplicitConvert (object obj, Type type) { if (obj == null) return null; - for (Type t = type; t != typeof (object); t = t.BaseType) { - MethodInfo mi = t.GetMethod ("op_Implicit", new Type [] {t}); - if (mi != null && mi.ReturnType.IsAssignableFrom (obj.GetType ())) - return mi.Invoke (null, new object [] {obj}); - } for (Type t = obj.GetType (); t != typeof (object); t = t.BaseType) { MethodInfo mi = t.GetMethod ("op_Implicit", new Type [] {t}); if (mi != null && mi.ReturnType == type) return mi.Invoke (null, new object [] {obj}); + + mi = type.GetMethod ("op_Implicit", new Type [] {t}); + if (mi != null && mi.ReturnType == type) + return mi.Invoke (null, new object [] {obj}); } return obj; } From 5fdbad2444ed53b2696518aa19b07acb4d41d662 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 10 Sep 2014 17:24:38 +0100 Subject: [PATCH 092/543] Changed method ImplicitConvert to internal static. --- .../XmlSerializationWriterInterpreter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs index 595d670b655..f361fadd21f 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs @@ -355,7 +355,7 @@ void WriteMemberElement (XmlTypeMapElementInfo elem, object memberValue) } } - object ImplicitConvert (object obj, Type type) + internal static object ImplicitConvert (object obj, Type type) { if (obj == null) return null; From f8ff518ebee96b4ddce8111f0ae4ad6185d164d9 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 10 Sep 2014 17:25:44 +0100 Subject: [PATCH 093/543] When needed serialized objects are now implicitly converted. Fixes #20403. --- .../XmlSerializationReaderInterpreter.cs | 4 ++++ .../XmlSerializationWriterInterpreter.cs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs index a90ae2bfb31..1853ad14976 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs @@ -585,6 +585,10 @@ bool IsReadOnly (XmlTypeMapMember member, TypeData memType, object ob, bool isVa void SetMemberValue (XmlTypeMapMember member, object ob, object value, bool isValueList) { + var memberType = member.TypeData.Type; + if (value != null && !value.GetType().IsAssignableFrom (memberType)) + value = XmlSerializationWriterInterpreter.ImplicitConvert (value, memberType); + if (isValueList) ((object[])ob)[member.GlobalIndex] = value; else diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs index f361fadd21f..cf7985349eb 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs @@ -120,6 +120,10 @@ protected virtual void WriteObject (XmlTypeMapping typeMap, object ob, string el return; } + var obExpectedType = typeMap.TypeData.Type; + if (!ob.GetType().IsAssignableFrom (obExpectedType)) + ob = ImplicitConvert (ob, obExpectedType); + XmlTypeMapping map = typeMap.GetRealTypeMap (ob.GetType()); if (map == null) From 6d07ad8e7a9f5417e0e0e9c82c969ffba5fb10b3 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Wed, 10 Sep 2014 19:04:22 +0200 Subject: [PATCH 094/543] [system.net.http] Encode ContentDisposition name. Fixes #18422 --- .../ContentDispositionHeaderValue.cs | 10 ++++++- .../ContentDispositionHeaderValueTest.cs | 27 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentDispositionHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentDispositionHeaderValue.cs index 0e28b728388..9329ac5796f 100644 --- a/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentDispositionHeaderValue.cs +++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentDispositionHeaderValue.cs @@ -120,9 +120,17 @@ public DateTimeOffset? ModificationDate { public string Name { get { - return FindParameter ("name"); + var value = FindParameter ("name"); + + if (value == null) + return null; + + return DecodeValue (value, false); } set { + if (value != null) + value = EncodeBase64Value (value); + SetValue ("name", value); } } diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/ContentDispositionHeaderValueTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/ContentDispositionHeaderValueTest.cs index b9c8a7796ee..e9a7ab8de0a 100644 --- a/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/ContentDispositionHeaderValueTest.cs +++ b/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/ContentDispositionHeaderValueTest.cs @@ -239,6 +239,33 @@ public void Properties_FileNameStar () Assert.AreEqual (new NameValueHeaderValue ("filename*", "utf-8''%C4%8D"), value.Parameters.First (), "#12"); } + + [Test] + public void Properties_Name () + { + var value = new ContentDispositionHeaderValue ("a"); + + value.Name = "aa"; + Assert.AreEqual ("aa", value.Name, "#1"); + Assert.AreEqual (new NameValueHeaderValue ("name", "aa"), value.Parameters.First (), "#2"); + + value.Name = "č"; + Assert.AreEqual ("č", value.Name, "#11"); + Assert.AreEqual (new NameValueHeaderValue ("name", "\"=?utf-8?B?xI0=?=\""), value.Parameters.First (), "#12"); + + value.Name = "(@)"; + Assert.AreEqual ("\"(@)\"", value.Name, "#21"); + Assert.AreEqual (new NameValueHeaderValue ("name", "\"(@)\""), value.Parameters.First (), "#22"); + + value.Name = "\"č\""; + Assert.AreEqual ("č", value.Name, "#31"); + Assert.AreEqual (new NameValueHeaderValue ("name", "\"=?utf-8?B?xI0=?=\""), value.Parameters.First (), "#32"); + + value.Name = "\"quoted\""; + Assert.AreEqual ("\"quoted\"", value.Name, "#41"); + Assert.AreEqual (new NameValueHeaderValue ("name", "\"quoted\""), value.Parameters.First (), "#42"); + } + [Test] public void Properties_ModificationDate () { From 9050d9cba17623fffe575476124a946d7aa2fd8d Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Wed, 10 Sep 2014 18:22:35 +0200 Subject: [PATCH 095/543] [mcs] Remove value type constrained type parameter instantiation optimization to handle parameterless struct constructors --- mcs/mcs/expression.cs | 46 ++++++----------------------------- mcs/tests/gtest-623-lib.il | 42 ++++++++++++++++++++++++++++++++ mcs/tests/gtest-623.cs | 24 ++++++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 47 +++++++++++++++++++++++------------- 4 files changed, 104 insertions(+), 55 deletions(-) create mode 100644 mcs/tests/gtest-623-lib.il create mode 100644 mcs/tests/gtest-623.cs diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index ed2860b7766..4dce548e362 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -7246,46 +7246,14 @@ protected override Expression DoResolve (ResolveContext ec) return this; } - bool DoEmitTypeParameter (EmitContext ec) + void DoEmitTypeParameter (EmitContext ec) { var m = ec.Module.PredefinedMembers.ActivatorCreateInstance.Resolve (loc); if (m == null) - return true; + return; var ctor_factory = m.MakeGenericMethod (ec.MemberContext, type); - var tparam = (TypeParameterSpec) type; - - if (tparam.IsReferenceType) { - ec.Emit (OpCodes.Call, ctor_factory); - return true; - } - - // Allow DoEmit() to be called multiple times. - // We need to create a new LocalTemporary each time since - // you can't share LocalBuilders among ILGeneators. - LocalTemporary temp = new LocalTemporary (type); - - Label label_activator = ec.DefineLabel (); - Label label_end = ec.DefineLabel (); - - temp.AddressOf (ec, AddressOp.Store); - ec.Emit (OpCodes.Initobj, type); - - temp.Emit (ec); - ec.Emit (OpCodes.Box, type); - ec.Emit (OpCodes.Brfalse, label_activator); - - temp.AddressOf (ec, AddressOp.Store); - ec.Emit (OpCodes.Initobj, type); - temp.Emit (ec); - temp.Release (ec); - ec.Emit (OpCodes.Br_S, label_end); - - ec.MarkLabel (label_activator); - ec.Emit (OpCodes.Call, ctor_factory); - ec.MarkLabel (label_end); - return true; } // @@ -7317,7 +7285,7 @@ bool DoEmitTypeParameter (EmitContext ec) // public virtual bool Emit (EmitContext ec, IMemoryLocation target) { - bool is_value_type = TypeSpec.IsValueType (type); + bool is_value_type = type.IsStructOrEnum; VariableReference vr = target as VariableReference; if (target != null && is_value_type && (vr != null || method == null)) { @@ -7346,8 +7314,10 @@ public virtual bool Emit (EmitContext ec, IMemoryLocation target) } } - if (type is TypeParameterSpec) - return DoEmitTypeParameter (ec); + if (type is TypeParameterSpec) { + DoEmitTypeParameter (ec); + return true; + } ec.MarkCallEntry (loc); ec.Emit (OpCodes.Newobj, method); @@ -7357,7 +7327,7 @@ public virtual bool Emit (EmitContext ec, IMemoryLocation target) public override void Emit (EmitContext ec) { LocalTemporary v = null; - if (method == null && TypeSpec.IsValueType (type)) { + if (method == null && type.IsStructOrEnum) { // TODO: Use temporary variable from pool v = new LocalTemporary (type); } diff --git a/mcs/tests/gtest-623-lib.il b/mcs/tests/gtest-623-lib.il new file mode 100644 index 00000000000..25c5b72ca4f --- /dev/null +++ b/mcs/tests/gtest-623-lib.il @@ -0,0 +1,42 @@ +.assembly extern mscorlib +{ +} + +.assembly 'gtest-623-lib' +{ +} + +.module 'gtest-623-lib.dll' + + .class public sequential ansi sealed beforefieldinit S + extends [mscorlib]System.ValueType + implements I { + + .field public int32 Field + + .method public hidebysig specialname rtspecialname + instance default void '.ctor' () cil managed + { + ldarg.0 + ldc.i4.3 + stfld int32 S::Field + ret + } + + .method public final virtual hidebysig newslot + instance default int32 GetValue () cil managed + { + ldarg.0 + ldfld int32 S::Field + ret + } + } + + .class interface public auto ansi abstract I + { + + .method public virtual hidebysig newslot abstract + instance default int32 GetValue () cil managed + { + } + } diff --git a/mcs/tests/gtest-623.cs b/mcs/tests/gtest-623.cs new file mode 100644 index 00000000000..ce9b79d1bd1 --- /dev/null +++ b/mcs/tests/gtest-623.cs @@ -0,0 +1,24 @@ +// Compiler options: -r:gtest-623-lib.dll + +using System; + +public class C +{ + static bool Test () where T : struct, I + { + var t = new T (); + if (t.GetValue () != 3) + return false; + + return true; + } + + public static int Main () + { + if (!Test ()) + return 1; + + Console.WriteLine ("ok"); + return 0; + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 12fab60c027..e42ef28dad9 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -4727,7 +4727,7 @@ - 44 + 14 7 @@ -6792,10 +6792,10 @@ 86 - 235 + 203 - 114 + 84 20 @@ -7527,7 +7527,7 @@ - 16 + 14 @@ -7580,7 +7580,7 @@ - 57 + 27 @@ -7640,7 +7640,7 @@ - 57 + 27 @@ -12378,7 +12378,7 @@ - 38 + 8 7 @@ -12411,7 +12411,7 @@ - 51 + 21 7 @@ -15212,7 +15212,7 @@ - 43 + 13 7 @@ -15672,7 +15672,7 @@ - 17 + 13 19 @@ -16655,7 +16655,7 @@ - 128 + 35 7 @@ -17477,7 +17477,7 @@ - 18 + 14 15 @@ -17650,7 +17650,7 @@ - 48 + 18 @@ -18081,7 +18081,7 @@ - 61 + 31 7 @@ -18929,7 +18929,7 @@ 26 - 54 + 24 18 @@ -19404,6 +19404,19 @@ + + + + 42 + + + 37 + + + 7 + + + @@ -30572,7 +30585,7 @@ - 44 + 14 22 @@ -61102,7 +61115,7 @@ - 295 + 305 13 From 29abf6790dcf6158e4b9613d7307562be38ca883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Wed, 10 Sep 2014 19:09:34 +0200 Subject: [PATCH 096/543] [System] Fixed Diagnostics.Switch ctor behavior for null parameters Passing null to the displayName or description ctor parameter on MS.NET makes them equal to an empty string. Fixed the Mono behavior to match .NET. --- mcs/class/System/System.Diagnostics/Switch.cs | 4 ++-- .../Test/System.Diagnostics/SourceSwitchTest.cs | 2 +- .../Test/System.Diagnostics/SwitchesTest.cs | 16 +++++++++++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/mcs/class/System/System.Diagnostics/Switch.cs b/mcs/class/System/System.Diagnostics/Switch.cs index 216cde7fa24..94d1f4d19fe 100644 --- a/mcs/class/System/System.Diagnostics/Switch.cs +++ b/mcs/class/System/System.Diagnostics/Switch.cs @@ -64,8 +64,8 @@ public abstract class Switch protected Switch(string displayName, string description) { - this.name = displayName; - this.description = description; + this.name = displayName ?? string.Empty; + this.description = description ?? string.Empty; } protected Switch(string displayName, string description, string defaultSwitchValue) diff --git a/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs b/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs index af0b6609d27..5cfcb1a6f7b 100644 --- a/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs +++ b/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs @@ -51,7 +51,7 @@ public class SourceSwitchTest public void ConstructorNullName () { SourceSwitch s = new SourceSwitch (null); - Assert.IsNull (s.DisplayName); + Assert.IsEmpty (s.DisplayName); } [Test] diff --git a/mcs/class/System/Test/System.Diagnostics/SwitchesTest.cs b/mcs/class/System/Test/System.Diagnostics/SwitchesTest.cs index c21a1ca5248..4c52cb109af 100644 --- a/mcs/class/System/Test/System.Diagnostics/SwitchesTest.cs +++ b/mcs/class/System/Test/System.Diagnostics/SwitchesTest.cs @@ -80,6 +80,12 @@ protected override void OnSwitchSettingChanged () } } + class TestNullSwitch : Switch { + public TestNullSwitch () : base (null, null) + { + } + } + [TestFixture] public class SwitchesTest { @@ -184,8 +190,16 @@ public void BooleanSwitchInvalidDefaultValue () BooleanSwitch s = new BooleanSwitch ("test", "", "hoge"); Assert.IsTrue (!s.Enabled); } + + [Test] + public void NullSwitchHasEmptyDisplayNameAndDescription () + { + var s = new TestNullSwitch (); + Assert.IsEmpty (s.DisplayName); + Assert.IsEmpty (s.Description); + } #endif } } -#endif \ No newline at end of file +#endif From d3624fa2579127346e76c1f01c52cca51a93ad85 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 10 Sep 2014 14:23:57 -0400 Subject: [PATCH 097/543] [runtime] Redirect runtime logging to asl_log only on ios, not when running the cross compiler. --- eglib/src/goutput.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eglib/src/goutput.c b/eglib/src/goutput.c index 1dc8bd6faff..9756b67a47d 100644 --- a/eglib/src/goutput.c +++ b/eglib/src/goutput.c @@ -176,7 +176,7 @@ default_stderr_handler (const gchar *message) } -#elif MONOTOUCH +#elif defined(HOST_IOS) #include static int From 582b370761fe1f5f803a7f536e18a9fcfae689b5 Mon Sep 17 00:00:00 2001 From: Joel Martinez Date: Wed, 10 Sep 2014 12:20:25 -0400 Subject: [PATCH 098/543] [mdoc] added -dropns-assemblies parameter. Will now only replace the namespace when the type or member is in a listed assembly --- mcs/tools/mdoc/Makefile | 9 +- .../mdoc/Mono.Documentation/monodocer.cs | 131 ++++++++++++------ 2 files changed, 91 insertions(+), 49 deletions(-) diff --git a/mcs/tools/mdoc/Makefile b/mcs/tools/mdoc/Makefile index 4c5485e3625..8e91020a90b 100644 --- a/mcs/tools/mdoc/Makefile +++ b/mcs/tools/mdoc/Makefile @@ -136,11 +136,11 @@ check-monodocer-dropns-classic-withsecondary: $(PROGRAM) update-monodocer-dropns-unified: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-unified.dll - $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll --dropns=MyFramework + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll --dropns=MyFramework --dropns-assemblies=Test/DocTest-DropNS-unified.dll update-monodocer-dropns-unified-withsecondary: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-unified.dll - $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll Test/DocTest-DropNS-classic-secondary.dll --dropns=MyFramework + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll Test/DocTest-DropNS-classic-secondary.dll --dropns=MyFramework --dropns-assemblies=Test/DocTest-DropNS-unified.dll update-monodocer-dropns-classic-secondary: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-classic-secondary.dll @@ -303,8 +303,11 @@ check-doc-tools-update: check-monodocer-since-update \ check-monodocer-importecmadoc-update \ check-monodocer-importslashdoc-update \ check-monodocer-update \ + check-monodocer-dropns-classic \ + check-monodocer-dropns-classic-withsecondary \ check-monodocer-delete-update \ check-mdoc-export-html-update \ check-mdoc-export-msxdoc-update \ - check-mdoc-validate-update + check-mdoc-validate-update + diff --git a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs index 75a6d5ca63e..d374b92d7c7 100644 --- a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs +++ b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs @@ -120,7 +120,7 @@ public static string GetTranslatedName(TypeReference t) { string typename = t.FullName; bool isInAssembly = MDocUpdater.IsInAssemblies (t.Module.Name); - if (isInAssembly && MDocUpdater.HasDroppedNamespace () && !typename.StartsWith ("System")) { + if (isInAssembly && !typename.StartsWith ("System") && MDocUpdater.HasDroppedNamespace (t)) { string nameWithDropped = string.Format ("{0}.{1}", MDocUpdater.droppedNamespace, typename); return nameWithDropped; } @@ -166,9 +166,26 @@ class MDocUpdater : MDocCommand HashSet forwardedTypes = new HashSet (); public static string droppedNamespace = string.Empty; - public static bool HasDroppedNamespace() { - return !string.IsNullOrWhiteSpace (droppedNamespace); + + public static bool HasDroppedNamespace(TypeDefinition forType) { + return HasDroppedNamespace(forType.Module); + } + + public static bool HasDroppedNamespace(MemberReference forMember) { + return HasDroppedNamespace(forMember.Module); + } + + public static bool HasDroppedNamespace(AssemblyDefinition forAssembly) { + return HasDroppedNamespace(forAssembly.MainModule); } + + public static bool HasDroppedNamespace(ModuleDefinition forModule) { + return !string.IsNullOrWhiteSpace (droppedNamespace) && droppedAssemblies.Any(da => da == forModule.Name); + } + + + static List droppedAssemblies = new List(); + public string PreserveTag { get; set; } public static MDocUpdater Instance { get; private set; } public static bool SwitchingToMagicTypes { get; private set; } @@ -238,6 +255,9 @@ public override void Run (IEnumerable args) { "dropns=", "Instructs the update process that {NAMESPACE} has been dropped, so that types and members will match existing documentation nodes.", v => droppedNamespace = v }, + { "dropns-assemblies=", + "Comma separated list of the assemblies that are having the namespace dropped. If this is not provided, it is assumed that all are", + v => droppedAssemblies.AddRange(v.Split(',').Select(a => Path.GetFileName(a.Trim()))) }, { "ntypes", "If the new assembly is switching to 'magic types', then this switch should be defined.", v => SwitchingToMagicTypes = true }, @@ -580,7 +600,7 @@ public string DoUpdateType (TypeDefinition type, string basepath, string dest) nsname }; - if (MDocUpdater.HasDroppedNamespace ()) { + if (MDocUpdater.HasDroppedNamespace (type)) { // If dropping namespace, types may have moved into a couple of different places. var newSearchLocations = searchLocations.Union (new string[] { string.Format ("{0}.{1}", droppedNamespace, nsname), @@ -847,10 +867,10 @@ private void DoUpdateAssembly (AssemblyDefinition assembly, XmlElement index_typ // Add namespace and type nodes into the index file as needed AddIndexType (type, index_types); - + // Ensure the namespace index file exists string namespaceToUse = type.Namespace; - if (HasDroppedNamespace()) { + if (HasDroppedNamespace(assembly)) { namespaceToUse = string.Format ("{0}.{1}", droppedNamespace, namespaceToUse); } string onsdoc = DocUtils.PathCombine (dest, namespaceToUse + ".xml"); @@ -974,7 +994,9 @@ private void CleanupFiles (string dest, HashSet goodfiles) XmlDocument doc = new XmlDocument (); doc.Load (typefile.FullName); XmlElement e = doc.SelectSingleNode("/Type") as XmlElement; - if (e != null && !no_assembly_versions && UpdateAssemblyVersions(e, GetAssemblyVersions(), false)) { + string assemblyName = doc.SelectSingleNode ("/Type/AssemblyInfo/AssemblyName").InnerText; + AssemblyDefinition assembly = assemblies.FirstOrDefault (a => a.Name.Name == assemblyName); + if (e != null && !no_assembly_versions && assembly != null && assemblyName != null && UpdateAssemblyVersions(e, assembly, GetAssemblyVersions(assemblyName), false)) { using (TextWriter writer = OpenWrite (typefile.FullName, FileMode.Truncate)) WriteXml(doc.DocumentElement, writer); goodfiles.Add (relTypeFile); @@ -1002,9 +1024,11 @@ private static TextWriter OpenWrite (string path, FileMode mode) return w; } - private string[] GetAssemblyVersions () + private string[] GetAssemblyVersions (string assemblyName) { - return (from a in assemblies select GetAssemblyVersion (a)).ToArray (); + return (from a in assemblies + where a.Name.Name == assemblyName + select GetAssemblyVersion (a)).ToArray (); } private static void CleanupIndexTypes (XmlElement index_types, HashSet goodfiles) @@ -1088,10 +1112,10 @@ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition // Deleted (or signature changed) if (oldmember2 == null) { - if (!no_assembly_versions && UpdateAssemblyVersions (oldmember, new string[]{ GetAssemblyVersion (type.Module.Assembly) }, false)) + if (!no_assembly_versions && UpdateAssemblyVersions (oldmember, type.Module.Assembly, new string[]{ GetAssemblyVersion (type.Module.Assembly) }, false)) continue; - DeleteMember ("Member Removed", output, oldmember, todelete); + DeleteMember ("Member Removed", output, oldmember, todelete, type); continue; } @@ -1101,7 +1125,7 @@ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition // ignore, already seen } else if (DefaultMemberComparer.Compare (oldmember, seenmembers [sig]) == 0) - DeleteMember ("Duplicate Member Found", output, oldmember, todelete); + DeleteMember ("Duplicate Member Found", output, oldmember, todelete, type); else Warning ("TODO: found a duplicate member '{0}', but it's not identical to the prior member found!", sig); continue; @@ -1232,7 +1256,7 @@ private string GetCodeSource (string lang, string file) return null; } - void DeleteMember (string reason, string output, XmlNode member, MyXmlNodeList todelete) + void DeleteMember (string reason, string output, XmlNode member, MyXmlNodeList todelete, TypeDefinition type) { string format = output != null ? "{0}: File='{1}'; Signature='{4}'" @@ -1245,7 +1269,7 @@ void DeleteMember (string reason, string output, XmlNode member, MyXmlNodeList t member.SelectSingleNode ("MemberSignature[@Language='C#']/@Value").Value); if (!delete && MemberDocsHaveUserContent (member)) { Warning ("Member deletions must be enabled with the --delete option."); - } else if (HasDroppedNamespace ()) { + } else if (HasDroppedNamespace (type)) { // if we're dropping the namespace, add the "classic style" var existingAttribute = member.Attributes ["apistyle"]; if (existingAttribute != null) { @@ -1258,7 +1282,7 @@ void DeleteMember (string reason, string output, XmlNode member, MyXmlNodeList t member.Attributes.Append (apistyleAttr); } - } else if (!HasDroppedNamespace () && member.Attributes ["apistyle"] != null && member.Attributes ["apistyle"].Value == "unified") { + } else if (!HasDroppedNamespace (type) && member.Attributes ["apistyle"] != null && member.Attributes ["apistyle"].Value == "unified") { // do nothing if there's an apistyle=new attribute and we haven't dropped the namespace } else if (!string.IsNullOrWhiteSpace (PreserveTag)) { // do nothing @@ -1400,10 +1424,11 @@ public void UpdateType (XmlElement root, TypeDefinition type) var node = WriteElementAttribute (root, element, "Language", f.Language, forceNewElement: true); var newnode = WriteElementAttribute (root, node, "Value", valueToUse); return newnode; - }); + }, + type); } - string assemblyInfoNodeFilter = MDocUpdater.HasDroppedNamespace () ? "[@apistyle='unified']" : "[not(@apistyle) or @apistyle='classic']"; + string assemblyInfoNodeFilter = MDocUpdater.HasDroppedNamespace (type) ? "[@apistyle='unified']" : "[not(@apistyle) or @apistyle='classic']"; AddXmlNode( root.SelectNodes ("AssemblyInfo" + assemblyInfoNodeFilter).Cast ().ToArray (), @@ -1412,12 +1437,13 @@ public void UpdateType (XmlElement root, TypeDefinition type) () => { XmlElement ass = WriteElement(root, "AssemblyInfo", forceNewElement:true); - if (MDocUpdater.HasDroppedNamespace ()) ass.SetAttribute ("apistyle", "unified"); + if (MDocUpdater.HasDroppedNamespace (type)) ass.SetAttribute ("apistyle", "unified"); return ass; - }); + }, + type); foreach(var ass in root.SelectNodes ("AssemblyInfo" + assemblyInfoNodeFilter).Cast ()) { @@ -1448,7 +1474,7 @@ public void UpdateType (XmlElement root, TypeDefinition type) } if (type.IsGenericType ()) { - MakeTypeParameters (root, type.GenericParameters, MDocUpdater.HasDroppedNamespace()); + MakeTypeParameters (root, type.GenericParameters, type, MDocUpdater.HasDroppedNamespace(type)); } else { ClearElement(root, "TypeParameters"); } @@ -1505,9 +1531,10 @@ public void UpdateType (XmlElement root, TypeDefinition type) MakeAttributes (root, GetCustomAttributes (type), type); if (DocUtils.IsDelegate (type)) { - MakeTypeParameters (root, type.GenericParameters, MDocUpdater.HasDroppedNamespace()); - MakeParameters(root, type.GetMethod("Invoke").Parameters); - MakeReturnValue(root, type.GetMethod("Invoke")); + MakeTypeParameters (root, type.GenericParameters, type, MDocUpdater.HasDroppedNamespace(type)); + var member = type.GetMethod ("Invoke"); + MakeParameters(root, member, member.Parameters); + MakeReturnValue(root, member); } DocsNodeInfo typeInfo = new DocsNodeInfo (WriteElement(root, "Docs"), type); @@ -1567,7 +1594,8 @@ private void UpdateMember (DocsNodeInfo info) var node = WriteElementAttribute (me, element, "Language", f.Language, forceNewElement:true); var newNode = WriteElementAttribute (me, node, "Value", valueToUse); return newNode; - }); + }, + mi); } @@ -1582,13 +1610,13 @@ private void UpdateMember (DocsNodeInfo info) MakeAttributes (me, GetCustomAttributes (mi), mi.DeclaringType); - MakeReturnValue(me, mi, MDocUpdater.HasDroppedNamespace()); + MakeReturnValue(me, mi, MDocUpdater.HasDroppedNamespace(mi)); if (mi is MethodReference) { MethodReference mb = (MethodReference) mi; if (mb.IsGenericMethod ()) - MakeTypeParameters (me, mb.GenericParameters, MDocUpdater.HasDroppedNamespace()); + MakeTypeParameters (me, mb.GenericParameters, mi, MDocUpdater.HasDroppedNamespace(mi)); } - MakeParameters(me, mi, MDocUpdater.HasDroppedNamespace()); + MakeParameters(me, mi, MDocUpdater.HasDroppedNamespace(mi)); string fieldValue; if (mi is FieldDefinition && GetFieldConstValue ((FieldDefinition)mi, out fieldValue)) @@ -1600,14 +1628,22 @@ private void UpdateMember (DocsNodeInfo info) UpdateExtensionMethods (me, info); } + static void AddXmlNode (XmlElement[] relevant, Func valueMatches, Action setValue, Func makeNewNode, MemberReference member) { + AddXmlNode (relevant, valueMatches, setValue, makeNewNode, member.Module); + } + + static void AddXmlNode (XmlElement[] relevant, Func valueMatches, Action setValue, Func makeNewNode, TypeDefinition type) { + AddXmlNode (relevant, valueMatches, setValue, makeNewNode, type.Module); + } + /// Adds an xml node, reusing the node if it's available /// The existing set of nodes /// Checks to see if the node's value matches what you're trying to write. /// Sets the node's value /// Creates a new node, if valueMatches returns false. - static void AddXmlNode (XmlElement[] relevant, Func valueMatches, Action setValue, Func makeNewNode) + static void AddXmlNode (XmlElement[] relevant, Func valueMatches, Action setValue, Func makeNewNode, ModuleDefinition module) { - bool shouldDuplicate = MDocUpdater.HasDroppedNamespace (); + bool shouldDuplicate = MDocUpdater.HasDroppedNamespace (module); var styleToUse = shouldDuplicate ? ApiStyle.Unified : ApiStyle.Classic; var existing = relevant; bool done = false; @@ -2164,7 +2200,7 @@ private static bool UpdateAssemblyVersions (XmlElement root, MemberReference mem TypeDefinition type = member as TypeDefinition; if (type == null) type = member.DeclaringType as TypeDefinition; - return UpdateAssemblyVersions(root, new string[]{ GetAssemblyVersion (type.Module.Assembly) }, add); + return UpdateAssemblyVersions(root, type.Module.Assembly, new string[]{ GetAssemblyVersion (type.Module.Assembly) }, add); } private static string GetAssemblyVersion (AssemblyDefinition assembly) @@ -2172,7 +2208,7 @@ private static string GetAssemblyVersion (AssemblyDefinition assembly) return assembly.Name.Version.ToString(); } - private static bool UpdateAssemblyVersions(XmlElement root, string[] assemblyVersions, bool add) + private static bool UpdateAssemblyVersions(XmlElement root, AssemblyDefinition assembly, string[] assemblyVersions, bool add) { XmlElement av = (XmlElement) root.SelectSingleNode ("AssemblyVersions"); if (av != null) { @@ -2182,14 +2218,14 @@ private static bool UpdateAssemblyVersions(XmlElement root, string[] assemblyVer string oldNodeFilter = "AssemblyInfo[not(@apistyle) or @apistyle='classic']"; string newNodeFilter = "AssemblyInfo[@apistyle='unified']"; - string thisNodeFilter = MDocUpdater.HasDroppedNamespace () ? newNodeFilter : oldNodeFilter; - string thatNodeFilter = MDocUpdater.HasDroppedNamespace () ? oldNodeFilter : newNodeFilter; + string thisNodeFilter = MDocUpdater.HasDroppedNamespace (assembly) ? newNodeFilter : oldNodeFilter; + string thatNodeFilter = MDocUpdater.HasDroppedNamespace (assembly) ? oldNodeFilter : newNodeFilter; XmlElement e = (XmlElement) root.SelectSingleNode (thisNodeFilter); if (e == null) { e = root.OwnerDocument.CreateElement("AssemblyInfo"); - if (MDocUpdater.HasDroppedNamespace ()) { + if (MDocUpdater.HasDroppedNamespace (assembly)) { e.SetAttribute ("apistyle", "unified"); } @@ -2197,7 +2233,7 @@ private static bool UpdateAssemblyVersions(XmlElement root, string[] assemblyVer } var thatNode = (XmlElement) root.SelectSingleNode (thatNodeFilter); - if (MDocUpdater.HasDroppedNamespace () && thatNode != null) { + if (MDocUpdater.HasDroppedNamespace (assembly) && thatNode != null) { // there's a classic node, we should add apistyles e.SetAttribute ("apistyle", "unified"); thatNode.SetAttribute ("apistyle", "classic"); @@ -2333,7 +2369,7 @@ static long ToInt64 (object value) return Convert.ToInt64 (value); } - private void MakeParameters (XmlElement root, IList parameters, bool shouldDuplicateWithNew=false) + private void MakeParameters (XmlElement root, MemberReference member, IList parameters, bool shouldDuplicateWithNew=false) { XmlElement e = WriteElement(root, "Parameters"); @@ -2382,13 +2418,14 @@ private void MakeParameters (XmlElement root, IList paramet MakeAttributes (pe, GetCustomAttributes (p.CustomAttributes, "")); return pe; - }); + }, + member); i++; } } - private void MakeTypeParameters (XmlElement root, IList typeParams, bool shouldDuplicateWithNew) + private void MakeTypeParameters (XmlElement root, IList typeParams, MemberReference member, bool shouldDuplicateWithNew) { if (typeParams == null || typeParams.Count == 0) { XmlElement f = (XmlElement) root.SelectSingleNode ("TypeParameters"); @@ -2450,18 +2487,19 @@ private void MakeTypeParameters (XmlElement root, IList typePa } return pe; - }); + }, + member); } } private void MakeParameters (XmlElement root, MemberReference mi, bool shouldDuplicateWithNew) { if (mi is MethodDefinition && ((MethodDefinition) mi).IsConstructor) - MakeParameters (root, ((MethodDefinition)mi).Parameters, shouldDuplicateWithNew); + MakeParameters (root, mi, ((MethodDefinition)mi).Parameters, shouldDuplicateWithNew); else if (mi is MethodDefinition) { MethodDefinition mb = (MethodDefinition) mi; IList parameters = mb.Parameters; - MakeParameters(root, parameters, shouldDuplicateWithNew); + MakeParameters(root, mi, parameters, shouldDuplicateWithNew); if (parameters.Count > 0 && DocUtils.IsExtensionMethod (mb)) { XmlElement p = (XmlElement) root.SelectSingleNode ("Parameters/Parameter[position()=1]"); p.SetAttribute ("RefType", "this"); @@ -2470,7 +2508,7 @@ private void MakeParameters (XmlElement root, MemberReference mi, bool shouldDup else if (mi is PropertyDefinition) { IList parameters = ((PropertyDefinition)mi).Parameters; if (parameters.Count > 0) - MakeParameters(root, parameters, shouldDuplicateWithNew); + MakeParameters(root, mi, parameters, shouldDuplicateWithNew); else return; } @@ -2498,7 +2536,8 @@ private void MakeReturnValue (XmlElement root, TypeReference type, IList GetReflectionMembers (TypeDefiniti { // In case of dropping the namespace, we have to remove the dropped NS // so that docName will match what's in the assembly/type - if (MDocUpdater.HasDroppedNamespace () && docName.StartsWith(MDocUpdater.droppedNamespace + ".")) { + if (MDocUpdater.HasDroppedNamespace (type) && docName.StartsWith(MDocUpdater.droppedNamespace + ".")) { int droppedNsLength = MDocUpdater.droppedNamespace.Length; docName = docName.Substring (droppedNsLength + 1, docName.Length - droppedNsLength - 1); } From 7912295bc9410ce224383f7898bb347afa1e2427 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 10 Sep 2014 19:06:15 -0400 Subject: [PATCH 099/543] [runtime] Fix the RESOLTION_SCOPE->RESOLUTION_SCOPE typo. --- mono/metadata/class.c | 24 ++++++++++++------------ mono/metadata/reflection.c | 14 +++++++------- mono/metadata/row-indexes.h | 10 ++++++++++ 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index ec4c2285739..240792536d3 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -191,9 +191,9 @@ mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]); nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]); - idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS; - switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) { - case MONO_RESOLTION_SCOPE_MODULE: + idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS; + switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) { + case MONO_RESOLUTION_SCOPE_MODULE: /* LAMESPEC The spec says that a null module resolution scope should go through the exported type table. This is not the observed behavior of existing implementations. @@ -203,13 +203,13 @@ mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/ goto done; - case MONO_RESOLTION_SCOPE_MODULEREF: + case MONO_RESOLUTION_SCOPE_MODULEREF: module = mono_image_load_module (image, idx); if (module) res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/ goto done; - case MONO_RESOLTION_SCOPE_TYPEREF: { + case MONO_RESOLUTION_SCOPE_TYPEREF: { MonoClass *enclosing; GList *tmp; @@ -246,7 +246,7 @@ mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name); goto done; } - case MONO_RESOLTION_SCOPE_ASSEMBLYREF: + case MONO_RESOLUTION_SCOPE_ASSEMBLYREF: break; } @@ -7100,18 +7100,18 @@ mono_assembly_name_from_token (MonoImage *image, guint32 type_token) } mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE); - idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS; - switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) { - case MONO_RESOLTION_SCOPE_MODULE: + idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS; + switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) { + case MONO_RESOLUTION_SCOPE_MODULE: /* FIXME: */ return g_strdup (""); - case MONO_RESOLTION_SCOPE_MODULEREF: + case MONO_RESOLUTION_SCOPE_MODULEREF: /* FIXME: */ return g_strdup (""); - case MONO_RESOLTION_SCOPE_TYPEREF: + case MONO_RESOLUTION_SCOPE_TYPEREF: /* FIXME: */ return g_strdup (""); - case MONO_RESOLTION_SCOPE_ASSEMBLYREF: + case MONO_RESOLUTION_SCOPE_ASSEMBLYREF: mono_assembly_get_assemblyref (image, idx - 1, &aname); return mono_stringify_assembly_name (&aname); default: diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index e74fe3f0d65..3ea728173df 100644 --- a/mono/metadata/reflection.c +++ b/mono/metadata/reflection.c @@ -2256,8 +2256,8 @@ resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image) values = table->values + token * MONO_MODULEREF_SIZE; values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name); - token <<= MONO_RESOLTION_SCOPE_BITS; - token |= MONO_RESOLTION_SCOPE_MODULEREF; + token <<= MONO_RESOLUTION_SCOPE_BITS; + token |= MONO_RESOLUTION_SCOPE_MODULEREF; g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token)); return token; @@ -2299,8 +2299,8 @@ resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image) } else { values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0; } - token <<= MONO_RESOLTION_SCOPE_BITS; - token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF; + token <<= MONO_RESOLUTION_SCOPE_BITS; + token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF; g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token)); return token; } @@ -2390,7 +2390,7 @@ mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboo enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE); /* get the typeref idx of the enclosing type */ enclosing >>= MONO_TYPEDEFORREF_BITS; - scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF; + scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF; } else { scope = resolution_scope_from_image (assembly, klass->image); } @@ -3824,8 +3824,8 @@ add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *a forwarder = FALSE; } else { scope = resolution_scope_from_image (assembly, klass->image); - g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF); - scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS; + g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF); + scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS; impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF; } diff --git a/mono/metadata/row-indexes.h b/mono/metadata/row-indexes.h index 4b4ca6dbc96..74fbf6b35c5 100644 --- a/mono/metadata/row-indexes.h +++ b/mono/metadata/row-indexes.h @@ -419,6 +419,16 @@ enum { MONO_CUSTOM_ATTR_TYPE_MASK = 7 }; +enum { + MONO_RESOLUTION_SCOPE_MODULE, + MONO_RESOLUTION_SCOPE_MODULEREF, + MONO_RESOLUTION_SCOPE_ASSEMBLYREF, + MONO_RESOLUTION_SCOPE_TYPEREF, + MONO_RESOLUTION_SCOPE_BITS = 2, + MONO_RESOLUTION_SCOPE_MASK = 3 +}; + +/* Kept for compatibility since this is a public header file */ enum { MONO_RESOLTION_SCOPE_MODULE, MONO_RESOLTION_SCOPE_MODULEREF, From 2c11b2ea4a58bc0c281c4dacedfe4ae1b5f039fb Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 10 Sep 2014 19:14:57 -0400 Subject: [PATCH 100/543] [aot] Avoid a stack overflow if profiler enter-leave events are requested in the full-aot mode. --- mono/mini/aot-runtime.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 98361554a3e..213d5b56ab2 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -3469,8 +3469,12 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM MonoJitInfo *jinfo = NULL; guint8 *code, *info; - if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE) + if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE) { + if (mono_aot_only) + /* The caller cannot handle this */ + g_assert_not_reached (); return NULL; + } if ((domain != mono_get_root_domain ()) && (!(amodule->info.opts & MONO_OPT_SHARED))) /* Non shared AOT code can't be used in other appdomains */ From d2f391c80c7a66ef0fae542a3bd8cc5781eb85ef Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Wed, 10 Sep 2014 08:36:42 +0200 Subject: [PATCH 101/543] Do not hardcode lib path The changes from 3408b8e5f194774e529e223173d68a1a8f880ea5 cause regressions in distros which do not use lib as folder for arch-specific libraries, like Fedora x86_64. Instead, reloc_libdir should be used (as in data/mono.pc.in). This change is released under the MIT/X11 license. --- data/config.in | 2 +- runtime/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/config.in b/data/config.in index fc764c7a029..c337f82f17f 100644 --- a/data/config.in +++ b/data/config.in @@ -10,7 +10,7 @@ - + diff --git a/runtime/Makefile.am b/runtime/Makefile.am index 7c9b6006673..df404acf398 100644 --- a/runtime/Makefile.am +++ b/runtime/Makefile.am @@ -168,7 +168,7 @@ CLEANFILES = etc/mono/config # depend on $(symlinks) to ensure 'etc/mono' directory exists etc/mono/config: ../data/config Makefile $(symlinks) d=`cd ../support && pwd`; \ - sed 's,target="$(prefix)/lib/libMonoPosixHelper$(libsuffix)",target="'$$d'/libMonoPosixHelper.la",' ../data/config > $@t + sed 's,target="$(prefix)/$(reloc_libdir)/libMonoPosixHelper$(libsuffix)",target="'$$d'/libMonoPosixHelper.la",' ../data/config > $@t if test -z "$(libgdiplus_loc)"; then :; else \ sed 's,target="[^"]*libgdiplus[^"]*",target="$(libgdiplus_loc)",' $@t > $@tt; \ mv -f $@tt $@t; fi From 1eb9ba45c4b42cd9d7e4377797395f22150c5755 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 11 Sep 2014 10:30:58 +0200 Subject: [PATCH 102/543] [system] Fixes failing test --- mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs b/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs index 5cfcb1a6f7b..820e84d2a89 100644 --- a/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs +++ b/mcs/class/System/Test/System.Diagnostics/SourceSwitchTest.cs @@ -31,6 +31,8 @@ #if !MOBILE +#define TRACE + using NUnit.Framework; using System; using System.Text; From 1242b4b82c903cf677fac1a92707b614ec2f7dd0 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 11 Sep 2014 11:20:44 +0200 Subject: [PATCH 103/543] [corlib] Enumerate all subdirectories including the first one. Fixes #22857 --- mcs/class/corlib/System.IO/DirectoryInfo.cs | 28 ++++++++----------- .../Test/System.IO/DirectoryInfoTest.cs | 18 ++++++++++++ 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/mcs/class/corlib/System.IO/DirectoryInfo.cs b/mcs/class/corlib/System.IO/DirectoryInfo.cs index ce558743516..09ed552f62e 100644 --- a/mcs/class/corlib/System.IO/DirectoryInfo.cs +++ b/mcs/class/corlib/System.IO/DirectoryInfo.cs @@ -6,10 +6,12 @@ // Jim Richardson, develop@wtfo-guru.com // Dan Lewis, dihlewis@yahoo.co.uk // Sebastien Pouliot +// Marek Safar // // Copyright (C) 2002 Ximian, Inc. // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com) +// Copyright (C) 2014 Xamarin, Inc (http://www.xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -441,25 +443,19 @@ static internal IEnumerable EnumerateFileSystemInfos (string ful throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error); try { - if (((rattr & FileAttributes.ReparsePoint) == 0)){ - if ((rattr & FileAttributes.Directory) != 0) - yield return new DirectoryInfo (s); - else - yield return new FileInfo (s); - } - - while ((s = MonoIO.FindNext (handle, out rattr, out error)) != null){ - if ((rattr & FileAttributes.ReparsePoint) != 0) - continue; - if ((rattr & FileAttributes.Directory) != 0) - yield return new DirectoryInfo (s); - else - yield return new FileInfo (s); - + do { + if (((rattr & FileAttributes.ReparsePoint) == 0)){ + if ((rattr & FileAttributes.Directory) != 0) + yield return new DirectoryInfo (s); + else + yield return new FileInfo (s); + } + if (((rattr & FileAttributes.Directory) != 0) && subdirs) foreach (FileSystemInfo child in EnumerateFileSystemInfos (s, searchPattern, searchOption)) yield return child; - } + + } while ((s = MonoIO.FindNext (handle, out rattr, out error)) != null); } finally { MonoIO.FindClose (handle); } diff --git a/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs b/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs index cbb58727eb4..3e34c81352a 100644 --- a/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs +++ b/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs @@ -10,6 +10,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; @@ -1059,6 +1060,23 @@ public void ToStringTest () Assert.AreEqual (TempFolder + DSC + "ToString.Test", info.ToString ()); } +#if NET_4_0 + [Test] + public void EnumerateFileSystemInfosTest () + { + var dirInfo = new DirectoryInfo (TempFolder); + dirInfo.CreateSubdirectory ("1").CreateSubdirectory ("a"); + dirInfo.CreateSubdirectory ("2").CreateSubdirectory ("b"); + + var l = new List (); + foreach (var info in dirInfo.EnumerateFileSystemInfos ("*", SearchOption.AllDirectories)) + l.Add (info.Name); + + l.Sort (); + Assert.AreEqual ("1,2,a,b", string.Join (",", l), "#1"); + } +#endif + #if !MOBILE [Test] public void Serialization () From 924a954d1f1fcb997dc613a06ad055879c36e746 Mon Sep 17 00:00:00 2001 From: Ungureanu Marius Date: Thu, 11 Sep 2014 13:39:52 +0300 Subject: [PATCH 104/543] Add concurrent hashtable test to gitignore. --- mono/unit-tests/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/mono/unit-tests/.gitignore b/mono/unit-tests/.gitignore index 0b2579b6eae..aee3344f537 100644 --- a/mono/unit-tests/.gitignore +++ b/mono/unit-tests/.gitignore @@ -8,3 +8,4 @@ /test-gc-memfuncs /test-mono-linked-list-set /test-sgen-qsort +/test-conc-hashtable From da04211894550f94b9e7af5e23b7283215d5e78c Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 11 Sep 2014 12:53:25 +0100 Subject: [PATCH 105/543] Test Calendar.DaysInYear. Covers #21930. --- .../Test/System.Globalization/CalendarTest.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/mcs/class/corlib/Test/System.Globalization/CalendarTest.cs b/mcs/class/corlib/Test/System.Globalization/CalendarTest.cs index 0987da7aed6..c1b34196e95 100644 --- a/mcs/class/corlib/Test/System.Globalization/CalendarTest.cs +++ b/mcs/class/corlib/Test/System.Globalization/CalendarTest.cs @@ -3,6 +3,7 @@ // (C) 2002 Ulrich Kunitz // +using System.Collections.Generic; using NUnit.Framework; using System; using System.Globalization; @@ -797,6 +798,44 @@ public void TestToFourDigitYear2 () Assert.AreEqual (4363, kc.ToFourDigitYear (4363), "#4-4"); } + public void TestDaysInYear (Calendar calendar, int year) + { + var daysInYear = calendar.GetDaysInYear (year); + var daysInMonths = 0; + var monthInYear = calendar.GetMonthsInYear (year); + for (var m = 1; m <= monthInYear; m++) + daysInMonths += calendar.GetDaysInMonth (year, m); + + Assert.AreEqual (daysInYear, daysInMonths, string.Format("Calendar:{0} Year:{1}",calendar.GetType(), year)); + } + + [Test] + public void DaysInYear () + { + var calendars = new List (acal) { + new UmAlQuraCalendar () + }; + + foreach (var calendar in calendars) { + var minYear = calendar.GetYear (calendar.MinSupportedDateTime); + var maxYear = calendar.GetYear (calendar.MaxSupportedDateTime) - 1 ; + var midYear = calendar.GetYear (DateTime.Now); + var yearsTested = Math.Min (1000, (maxYear - minYear) / 2); + + midYear -= yearsTested / 2; + + int y1 = minYear, y2 = maxYear, y3 = midYear; + for (var i = 0; i < yearsTested; i++) { + TestDaysInYear (calendar, y1); + TestDaysInYear (calendar, y2); + if (y3 > minYear && y3 < maxYear) + TestDaysInYear (calendar, y3); + + y1++; y2--; y3++; + } + } + } + // TODO: more tests :-) } // class CalendarTest From 468160e712268441015e7b046977db91594d7164 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 11 Sep 2014 12:26:47 +0100 Subject: [PATCH 106/543] Improved CalendricalCalculations fixed_from_dmy methods. Fixes #21930. In some cases fixed_from_dmy is used with the month parameter greater than the number of months of that year. Year is now incremented until month parameter is valid. --- .../CalendricalCalculations.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/mcs/class/corlib/System.Globalization/CalendricalCalculations.cs b/mcs/class/corlib/System.Globalization/CalendricalCalculations.cs index 685c0f372fa..accba935b62 100644 --- a/mcs/class/corlib/System.Globalization/CalendricalCalculations.cs +++ b/mcs/class/corlib/System.Globalization/CalendricalCalculations.cs @@ -466,6 +466,11 @@ public static bool is_leap_year(int year) { /// An integer value representing the fixed day number. /// public static int fixed_from_dmy(int day, int month, int year) { + if (month > 12) { + year += CCMath.div_mod (out month, month - 1, 12); + month++; + } + int k = epoch - 1; k += 365 * (year-1); k += CCMath.div(year-1, 4); @@ -944,6 +949,12 @@ public static bool is_leap_year(int year) { /// public static int fixed_from_dmy(int day, int month, int year) { int y = year < 0 ? year+1 : year; + + if (month > 12) { + y += CCMath.div_mod (out month, month - 1, 12); + month++; + } + int k = epoch - 1; k += 365 * (y-1); k += CCMath.div(y-1, 4); @@ -1371,6 +1382,13 @@ public static int days_in_year(int year) { /// An integer value representing the fixed day number. /// public static int fixed_from_dmy(int day, int month, int year) { + var lastMonth = last_month_of_year (year); + while (month > lastMonth) { + year++; + month -= lastMonth; + lastMonth = last_month_of_year (year); + } + int m; int k = epoch-1; k += elapsed_days(year); @@ -1686,6 +1704,11 @@ public static bool is_leap_year(int year) { /// An integer value representing the fixed day number. /// public static int fixed_from_dmy(int day, int month, int year) { + if (month > 12) { + year += CCMath.div_mod (out month, month - 1, 12); + month++; + } + int k = epoch - 1; k += 354 * (year-1); k += CCMath.div(3+11*year, 30); From b818408b166c5548680428b689e6050537cccff5 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 11 Sep 2014 15:11:42 +0100 Subject: [PATCH 107/543] Test that offset is zero when date ends with GMT. Covers #22851. --- mcs/class/corlib/Test/System/DateTimeOffsetTest.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mcs/class/corlib/Test/System/DateTimeOffsetTest.cs b/mcs/class/corlib/Test/System/DateTimeOffsetTest.cs index 5d3609cedc9..13564426aed 100644 --- a/mcs/class/corlib/Test/System/DateTimeOffsetTest.cs +++ b/mcs/class/corlib/Test/System/DateTimeOffsetTest.cs @@ -714,6 +714,14 @@ public void TestDateOnlyWithTimeOffset () var expected = string.Format ("{0:D2}/{1:D2}/{2} 00:00:00 +11:00", 11, 7, 2013); Assert.AreEqual (expected, date.ToString (CultureInfo.InvariantCulture)); } + + [Test] + public void GMTDateTime () + { + var date = DateTimeOffset.Parse ("Wed, 10 Sep 2014 22:01:40 GMT", CultureInfo.InvariantCulture); + var expected = "09/10/2014 22:01:40 +00:00"; + Assert.AreEqual (expected, date.ToString (CultureInfo.InvariantCulture)); + } } } From e73499b33768bf9aaeb5d5845742457a839e2807 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 11 Sep 2014 15:12:36 +0100 Subject: [PATCH 108/543] GMT DateTimeOffset is now properly parsed. Fixes #22851. GMT date formats set useutc to true, so now useutc is checked to init DateTimeOffset with a zero offset. --- mcs/class/corlib/System/DateTime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/corlib/System/DateTime.cs b/mcs/class/corlib/System/DateTime.cs index ce698f9c620..8ff4901e4a3 100644 --- a/mcs/class/corlib/System/DateTime.cs +++ b/mcs/class/corlib/System/DateTime.cs @@ -1744,7 +1744,7 @@ private static bool _DoParse (string s, if (tzsign == -1) { if (result != DateTime.MinValue) { try { - if ((style & DateTimeStyles.AssumeUniversal) != 0) { + if (((style & DateTimeStyles.AssumeUniversal) != 0) || useutc) { dto = new DateTimeOffset (result, TimeSpan.Zero); } else if ((style & DateTimeStyles.AssumeLocal) != 0) { var offset = use_invariant ? From 550d314e51f91fa8438388288b857804580941ff Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 11 Sep 2014 18:52:43 +0200 Subject: [PATCH 109/543] Don't throw TimeZoneNotFoundExceptions when iOS gives us invalid data. iOS 8 GM lists "Asia/Chita" among its time zones, but when requesting the time zone data for that time zone, no data is returned. With this change we ignore time zones without any data when fetching all the timezones on the system. --- mcs/class/System.Core/System/TimeZoneInfo.MonoTouch.cs | 9 ++++++--- mcs/class/System.Core/System/TimeZoneInfo.cs | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.MonoTouch.cs b/mcs/class/System.Core/System/TimeZoneInfo.MonoTouch.cs index b0b5faa8af2..70b077de98c 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.MonoTouch.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.MonoTouch.cs @@ -64,12 +64,15 @@ static ReadOnlyCollection GetMonoTouchNames () [DllImport ("__Internal")] extern static IntPtr monotouch_timezone_get_data (string name, ref int size); - static Stream GetMonoTouchData (string name) + static Stream GetMonoTouchData (string name, bool throw_on_error = true) { int size = 0; IntPtr data = monotouch_timezone_get_data (name, ref size); - if (size <= 0) - throw new TimeZoneNotFoundException (); + if (size <= 0) { + if (throw_on_error) + throw new TimeZoneNotFoundException (); + return null; + } unsafe { var s = new UnmanagedMemoryStream ((byte*) data, size); diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index f9422ca9b83..aead18c764f 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -651,7 +651,9 @@ public static ReadOnlyCollection GetSystemTimeZones () #elif MONOTOUCH if (systemTimeZones.Count == 0) { foreach (string name in GetMonoTouchNames ()) { - using (Stream stream = GetMonoTouchData (name)) { + using (Stream stream = GetMonoTouchData (name, false)) { + if (stream == null) + continue; systemTimeZones.Add (BuildFromStream (name, stream)); } } From 9fd3c7ac4bca1442e7aa28da8ef19a3ac97ccce3 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 11 Sep 2014 19:40:06 +0200 Subject: [PATCH 110/543] [mcs] property pattern --- mcs/mcs/cs-parser.jay | 31 ++++++ mcs/mcs/expression.cs | 210 +++++++++++++++++++++++++++-------- mcs/tests/test-pattern-07.cs | 53 +++++++++ mcs/tests/ver-il-net_4_5.xml | 35 ++++++ 4 files changed, 285 insertions(+), 44 deletions(-) create mode 100644 mcs/tests/test-pattern-07.cs diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index 45f719a3738..a69e356668d 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -4358,6 +4358,7 @@ pattern_expr $$ = new WildcardPattern (GetLocation ($1)); } | pattern_expr_invocation + | pattern_property ; pattern_expr_invocation @@ -4367,6 +4368,36 @@ pattern_expr_invocation } ; +pattern_property + : type_name_expression OPEN_BRACE pattern_property_list CLOSE_BRACE + { + $$ = new PropertyPattern ((ATypeNameExpression) $1, (List) $3, GetLocation ($2)); + } + ; + +pattern_property_list + : pattern_property_entry + { + var list = new List (); + list.Add ((PropertyPatternMember) $1); + $$ = list; + } + | pattern_property_list COMMA pattern_property_entry + { + var list = (List) $1; + list.Add ((PropertyPatternMember) $3); + $$ = list; + } + ; + +pattern_property_entry + : identifier_inside_body IS pattern + { + var lt = (LocatedToken) $1; + $$ = new PropertyPatternMember (lt.Value, (Expression) $3, lt.Location); + } + ; + pattern : pattern_expr | pattern_type_expr opt_identifier diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 4dce548e362..6c345e0f1c8 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -1607,8 +1607,9 @@ void EmitPatternMatch (EmitContext ec) ec.Emit (OpCodes.Dup); ec.Emit (OpCodes.Brfalse, no_match); - var rp = ProbeType as RecursivePattern; - if (rp != null) + bool complex_pattern = ProbeType is ComplexPatternExpression; + Label prev = ec.RecursivePatternLabel; + if (complex_pattern) ec.RecursivePatternLabel = ec.DefineLabel (); if (number_mg != null) { @@ -1619,7 +1620,7 @@ void EmitPatternMatch (EmitContext ec) ec.Emit (OpCodes.Unbox_Any, probe_type); ProbeType.Emit (ec); - if (rp != null) { + if (complex_pattern) { ec.EmitInt (1); } else { ec.Emit (OpCodes.Ceq); @@ -1630,9 +1631,11 @@ void EmitPatternMatch (EmitContext ec) ec.Emit (OpCodes.Pop); - if (rp != null) + if (complex_pattern) ec.MarkLabel (ec.RecursivePatternLabel); + ec.RecursivePatternLabel = prev; + ec.EmitInt (0); ec.MarkLabel (end); } @@ -1985,23 +1988,19 @@ public override void Emit (EmitContext ec) } } - class RecursivePattern : PatternExpression + class RecursivePattern : ComplexPatternExpression { MethodGroupExpr operator_mg; - Expression[] args_comparison; Arguments operator_args; public RecursivePattern (ATypeNameExpression typeExpresion, Arguments arguments, Location loc) - : base (loc) + : base (typeExpresion, loc) { Arguments = arguments; - TypeExpression = typeExpresion; } public Arguments Arguments { get; private set; } - public ATypeNameExpression TypeExpression { get; private set; } - protected override Expression DoResolve (ResolveContext rc) { type = TypeExpression.ResolveAsType (rc); @@ -2042,8 +2041,8 @@ protected override Expression DoResolve (ResolveContext rc) var lt = new LocalTemporary (op_types [i + 1]); operator_args.Add (new Argument (lt, Argument.AType.Out)); - if (args_comparison == null) - args_comparison = new Expression[Arguments.Count]; + if (comparisons == null) + comparisons = new Expression[Arguments.Count]; int arg_comp_index; Expression expr; @@ -2058,27 +2057,7 @@ protected override Expression DoResolve (ResolveContext rc) expr = arg.Expr; } - if (expr is WildcardPattern) { - args_comparison [arg_comp_index] = new EmptyExpression (expr.Type); - continue; - } - - var recursive = expr as RecursivePattern; - if (recursive != null) { - recursive.SetParentInstance (lt); - } - - expr = Convert.ImplicitConversionRequired (rc, expr, lt.Type, expr.Location); - if (expr == null) - continue; - - if (expr is RecursivePattern) { - args_comparison [arg_comp_index] = expr; - continue; - } - - // TODO: Better error handling - args_comparison [arg_comp_index] = new Binary (Binary.Operator.Equality, lt, expr, expr.Location).Resolve (rc); + comparisons [arg_comp_index] = ResolveComparison (rc, expr, lt); } operator_mg = MethodGroupExpr.CreatePredefined (op, type, loc); @@ -2096,7 +2075,7 @@ List FindMatchingOverloads (IList members) if (pm.Count != arg_count) continue; - // TODO: Needs more thorough checks elsewhere to avoid doing this every time + // TODO: Needs more thorough operator checks elsewhere to avoid doing this every time bool ok = true; for (int ii = 1; ii < pm.Count; ++ii) { if ((pm.FixedParameters [ii].ModFlags & Parameter.Modifier.OUT) == 0) { @@ -2152,28 +2131,144 @@ MethodSpec FindBestOverload (ResolveContext rc, List methods) return methods [0]; } - public override void Emit (EmitContext ec) + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) { - EmitBranchable (ec, ec.RecursivePatternLabel, false); + operator_mg.EmitCall (ec, operator_args, false); + ec.Emit (OpCodes.Brfalse, target); + + base.EmitBranchable (ec, target, on_true); } - public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + static Expression ResolveComparison (ResolveContext rc, Expression expr, LocalTemporary lt) { - operator_mg.EmitCall (ec, operator_args, false); - ec.Emit (OpCodes.Brfalse, ec.RecursivePatternLabel); - if (args_comparison != null) { - foreach (var ac in args_comparison) { - ac.EmitBranchable (ec, ec.RecursivePatternLabel, false); - } + if (expr is WildcardPattern) + return new EmptyExpression (expr.Type); + + var recursive = expr as RecursivePattern; + expr = Convert.ImplicitConversionRequired (rc, expr, lt.Type, expr.Location); + if (expr == null) + return null; + + if (recursive != null) { + recursive.SetParentInstance (lt); + return expr; } + + // TODO: Better error handling + return new Binary (Binary.Operator.Equality, lt, expr, expr.Location).Resolve (rc); } - void SetParentInstance (LocalTemporary instance) + public void SetParentInstance (Expression instance) { operator_args [0] = new Argument (instance); } } + class PropertyPattern : ComplexPatternExpression + { + LocalTemporary instance; + + public PropertyPattern (ATypeNameExpression typeExpresion, List members, Location loc) + : base (typeExpresion, loc) + { + Members = members; + } + + public List Members { get; private set; } + + protected override Expression DoResolve (ResolveContext rc) + { + type = TypeExpression.ResolveAsType (rc); + if (type == null) + return null; + + comparisons = new Expression[Members.Count]; + + // TODO: optimize when source is VariableReference, it'd save dup+pop + instance = new LocalTemporary (type); + + for (int i = 0; i < Members.Count; i++) { + var lookup = Members [i]; + + var member = MemberLookup (rc, false, type, lookup.Name, 0, Expression.MemberLookupRestrictions.ExactArity, loc); + if (member == null) { + member = MemberLookup (rc, true, type, lookup.Name, 0, Expression.MemberLookupRestrictions.ExactArity, loc); + if (member != null) { + Expression.ErrorIsInaccesible (rc, member.GetSignatureForError (), loc); + continue; + } + } + + if (member == null) { + Expression.Error_TypeDoesNotContainDefinition (rc, Location, Type, lookup.Name); + continue; + } + + var pe = member as PropertyExpr; + if (pe == null || member is FieldExpr) { + rc.Report.Error (-2001, lookup.Location, "`{0}' is not a valid pattern member", lookup.Name); + continue; + } + + // TODO: Obsolete checks + // TODO: check accessibility + if (pe != null && !pe.PropertyInfo.HasGet) { + rc.Report.Error (-2002, lookup.Location, "Property `{0}.get' accessor is required", pe.GetSignatureForError ()); + continue; + } + + var expr = lookup.Expr.Resolve (rc); + if (expr == null) + continue; + + var me = (MemberExpr)member; + me.InstanceExpression = instance; + + comparisons [i] = ResolveComparison (rc, expr, me); + } + + eclass = ExprClass.Value; + return this; + } + + static Expression ResolveComparison (ResolveContext rc, Expression expr, Expression instance) + { + if (expr is WildcardPattern) + return new EmptyExpression (expr.Type); + + var res = Convert.ImplicitConversionRequired (rc, expr, instance.Type, expr.Location); + if (res == null) + return null; + + if (expr is ComplexPatternExpression) + return new Is (instance, res, expr.Location).Resolve (rc); + + // TODO: Better error handling + return new Binary (Binary.Operator.Equality, instance, res, expr.Location).Resolve (rc); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + instance.Store (ec); + + base.EmitBranchable (ec, target, on_true); + } + } + + class PropertyPatternMember + { + public PropertyPatternMember (string name, Expression expr, Location loc) + { + Name = name; + Expr = expr; + Location = loc; + } + + public string Name { get; private set; } + public Expression Expr { get; private set; } + public Location Location { get; private set; } + } + abstract class PatternExpression : Expression { protected PatternExpression (Location loc) @@ -2187,6 +2282,33 @@ public override Expression CreateExpressionTree (ResolveContext ec) } } + abstract class ComplexPatternExpression : PatternExpression + { + protected Expression[] comparisons; + + protected ComplexPatternExpression (ATypeNameExpression typeExpresion, Location loc) + : base (loc) + { + TypeExpression = typeExpresion; + } + + public ATypeNameExpression TypeExpression { get; private set; } + + public override void Emit (EmitContext ec) + { + EmitBranchable (ec, ec.RecursivePatternLabel, false); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + if (comparisons != null) { + foreach (var comp in comparisons) { + comp.EmitBranchable (ec, target, false); + } + } + } + } + /// /// Implementation of the `as' operator. /// diff --git a/mcs/tests/test-pattern-07.cs b/mcs/tests/test-pattern-07.cs new file mode 100644 index 00000000000..8743b35c5e7 --- /dev/null +++ b/mcs/tests/test-pattern-07.cs @@ -0,0 +1,53 @@ +// Compiler options: -langversion:experimental + +using System; + +class PropertyPattern +{ + static int Main () + { + object o = new DateTime (2014, 8, 30); + + if (!(o is DateTime { Day is 30 })) + return 1; + + if (!(o is DateTime { Month is 8, Day is 30, Year is * })) + return 2; + + if (o is X { Field is 30 }) + return 3; + + object o2 = new X () { + Field = new Y () { + Prop = 'f' + } + }; + + bool res2 = o2 is X { Field is Y { Prop is 'f' }, Field is Y (4) }; + if (!res2) + return 4; + + res2 = o2 is X { Field is Y { Prop is 'g' } }; + if (res2) + return 5; + + Console.WriteLine("ok"); + return 0; + } +} + +class X +{ + public object Field { get; set; } +} + +class Y +{ + public char Prop { get; set; } + + public static bool operator is (Y y, out int x) + { + x = 4; + return true; + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index e42ef28dad9..755aa7e0604 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -68562,6 +68562,41 @@ + + + + 444 + + + 7 + + + + + 14 + + + 8 + + + 7 + + + + + 14 + + + 8 + + + 13 + + + 7 + + + From c842249d72b824f5e6ebac13d98d85c0f5e524a5 Mon Sep 17 00:00:00 2001 From: Joel Martinez Date: Thu, 11 Sep 2014 15:43:28 -0400 Subject: [PATCH 111/543] [mdoc] Formatting feedback from pull #1273 --- .../mdoc/Mono.Documentation/monodocer.cs | 20 +++++++++++-------- .../Test/DocTest-DropNS-classic-secondary.cs | 2 +- mcs/tools/mdoc/Test/DocTest-DropNS-classic.cs | 2 +- mcs/tools/mdoc/Test/DocTest-DropNS-unified.cs | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs index d374b92d7c7..1515adde2d7 100644 --- a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs +++ b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs @@ -167,19 +167,23 @@ class MDocUpdater : MDocCommand public static string droppedNamespace = string.Empty; - public static bool HasDroppedNamespace(TypeDefinition forType) { + public static bool HasDroppedNamespace(TypeDefinition forType) + { return HasDroppedNamespace(forType.Module); } - public static bool HasDroppedNamespace(MemberReference forMember) { + public static bool HasDroppedNamespace(MemberReference forMember) + { return HasDroppedNamespace(forMember.Module); } - public static bool HasDroppedNamespace(AssemblyDefinition forAssembly) { + public static bool HasDroppedNamespace(AssemblyDefinition forAssembly) + { return HasDroppedNamespace(forAssembly.MainModule); } - public static bool HasDroppedNamespace(ModuleDefinition forModule) { + public static bool HasDroppedNamespace(ModuleDefinition forModule) + { return !string.IsNullOrWhiteSpace (droppedNamespace) && droppedAssemblies.Any(da => da == forModule.Name); } @@ -257,7 +261,7 @@ public override void Run (IEnumerable args) v => droppedNamespace = v }, { "dropns-assemblies=", "Comma separated list of the assemblies that are having the namespace dropped. If this is not provided, it is assumed that all are", - v => droppedAssemblies.AddRange(v.Split(',').Select(a => Path.GetFileName(a.Trim()))) }, + v => droppedAssemblies.AddRange (v.Split (',').Select (a => Path.GetFileName (a.Trim ()))) }, { "ntypes", "If the new assembly is switching to 'magic types', then this switch should be defined.", v => SwitchingToMagicTypes = true }, @@ -1112,7 +1116,7 @@ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition // Deleted (or signature changed) if (oldmember2 == null) { - if (!no_assembly_versions && UpdateAssemblyVersions (oldmember, type.Module.Assembly, new string[]{ GetAssemblyVersion (type.Module.Assembly) }, false)) + if (!no_assembly_versions && UpdateAssemblyVersions (oldmember, type.Module.Assembly, new string[]{ GetAssemblyVersion (type.Module.Assembly) }, false)) continue; DeleteMember ("Member Removed", output, oldmember, todelete, type); @@ -1256,7 +1260,7 @@ private string GetCodeSource (string lang, string file) return null; } - void DeleteMember (string reason, string output, XmlNode member, MyXmlNodeList todelete, TypeDefinition type) + void DeleteMember (string reason, string output, XmlNode member, MyXmlNodeList todelete, TypeDefinition type) { string format = output != null ? "{0}: File='{1}'; Signature='{4}'" @@ -2200,7 +2204,7 @@ private static bool UpdateAssemblyVersions (XmlElement root, MemberReference mem TypeDefinition type = member as TypeDefinition; if (type == null) type = member.DeclaringType as TypeDefinition; - return UpdateAssemblyVersions(root, type.Module.Assembly, new string[]{ GetAssemblyVersion (type.Module.Assembly) }, add); + return UpdateAssemblyVersions(root, type.Module.Assembly, new string[]{ GetAssemblyVersion (type.Module.Assembly) }, add); } private static string GetAssemblyVersion (AssemblyDefinition assembly) diff --git a/mcs/tools/mdoc/Test/DocTest-DropNS-classic-secondary.cs b/mcs/tools/mdoc/Test/DocTest-DropNS-classic-secondary.cs index 5372ead118b..3f929d6a75c 100644 --- a/mcs/tools/mdoc/Test/DocTest-DropNS-classic-secondary.cs +++ b/mcs/tools/mdoc/Test/DocTest-DropNS-classic-secondary.cs @@ -6,4 +6,4 @@ public float Hello(int value) { return 0.0f; } } -} \ No newline at end of file +} diff --git a/mcs/tools/mdoc/Test/DocTest-DropNS-classic.cs b/mcs/tools/mdoc/Test/DocTest-DropNS-classic.cs index 32e74fb75e8..a279b0e85a7 100644 --- a/mcs/tools/mdoc/Test/DocTest-DropNS-classic.cs +++ b/mcs/tools/mdoc/Test/DocTest-DropNS-classic.cs @@ -5,4 +5,4 @@ public float Hello(int value) { return 0.0f; } } -} \ No newline at end of file +} diff --git a/mcs/tools/mdoc/Test/DocTest-DropNS-unified.cs b/mcs/tools/mdoc/Test/DocTest-DropNS-unified.cs index 6636f72d95e..8ee5e8a6ffd 100644 --- a/mcs/tools/mdoc/Test/DocTest-DropNS-unified.cs +++ b/mcs/tools/mdoc/Test/DocTest-DropNS-unified.cs @@ -5,4 +5,4 @@ public float Hello(int value) { return 0.0f; } } -} \ No newline at end of file +} From 41339d95c67328c654323e46d44971812bc74519 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 11 Sep 2014 17:57:00 -0400 Subject: [PATCH 112/543] [jit] Always pass the imt arg to interface calls in gsharedvt methods. Fixes #22624. --- mono/mini/gshared.cs | 41 ++++++++++++++++++++++++++++++++++++++++ mono/mini/method-to-ir.c | 5 +++++ 2 files changed, 46 insertions(+) diff --git a/mono/mini/gshared.cs b/mono/mini/gshared.cs index 27149e9085d..d0ee4fac40d 100644 --- a/mono/mini/gshared.cs +++ b/mono/mini/gshared.cs @@ -944,6 +944,47 @@ public static int test_0_virtual_generic () { return 0; } + public interface IFace1 { + void m1 (); + void m2 (); + void m3 (); + void m4 (); + void m5 (); + } + + public class ClassIFace : IFace1 { + public void m1 () { + } + public void m2 () { + } + public void m3 () { + } + public void m4 () { + } + public void m5 () { + } + } + + interface IFaceIFaceCall { + void call (IFace1 iface); + } + + class MakeIFaceCall : IFaceIFaceCall { + public void call (IFace1 iface) { + iface.m1 (); + } + } + + // Check normal interface calls from gsharedvt call to fully instantiated methods + public static int test_0_instatiated_iface_call () { + ClassIFace c1 = new ClassIFace (); + + IFaceIFaceCall c = new MakeIFaceCall (); + + c.call (c1); + return 0; + } + [MethodImplAttribute (MethodImplOptions.NoInlining)] static string to_string(T t, T2 t2) { return t.ToString (); diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index a07fee2fd77..5dd518b9c0b 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -8434,6 +8434,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b cmethod, MONO_RGCTX_INFO_METHOD); /* This is not needed, as the trampoline code will pass one, and it might be passed in the same reg as the imt arg */ vtable_arg = NULL; + } else if ((cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) && !imt_arg) { + /* This can happen when we call a fully instantiated iface method */ + imt_arg = emit_get_rgctx_method (cfg, context_used, + cmethod, MONO_RGCTX_INFO_METHOD); + vtable_arg = NULL; } } From 90bb9c6d00f14b93197d917dcb0e673f1a465c3c Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Thu, 11 Sep 2014 20:43:21 -0400 Subject: [PATCH 113/543] [System] Fix building unit tests under the mobile profile --- .../Test/System.Diagnostics/TextWriterTraceListenerHelper.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs b/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs index f6643b06c23..248e2ee0814 100644 --- a/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs +++ b/mcs/class/System/Test/System.Diagnostics/TextWriterTraceListenerHelper.cs @@ -28,6 +28,8 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +#if !MOBILE + using System; using System.IO; using System.Diagnostics; @@ -83,4 +85,4 @@ public void clearMessageCounters() } } - +#endif \ No newline at end of file From 300876b229fb73f6b6e13bda3081318b43c72971 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Fri, 12 Sep 2014 15:18:53 +0200 Subject: [PATCH 114/543] [mcs] Don't use `1 naming for compiler generated second level and deeper nested types. Fixes #22893 --- mcs/mcs/class.cs | 14 +-- mcs/mcs/decl.cs | 5 - mcs/mcs/eval.cs | 2 +- mcs/mcs/namespace.cs | 5 +- mcs/tests/test-async-75.cs | 26 +++++ mcs/tests/ver-il-net_4_5.xml | 199 ++++++++++++++++++++--------------- 6 files changed, 147 insertions(+), 104 deletions(-) create mode 100644 mcs/tests/test-async-75.cs diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs index e84aef93322..e9194d4f1f8 100644 --- a/mcs/mcs/class.cs +++ b/mcs/mcs/class.cs @@ -44,7 +44,6 @@ namespace Mono.CSharp public abstract class TypeContainer : MemberCore { public readonly MemberKind Kind; - public readonly string Basename; protected List containers; @@ -62,9 +61,6 @@ protected TypeContainer (TypeContainer parent, MemberName name, Attributes attrs : base (parent, name, attrs) { this.Kind = kind; - if (name != null) - this.Basename = name.Basename; - defined_names = new Dictionary (); } @@ -111,7 +107,7 @@ public void AddCompilerGeneratedClass (CompilerGeneratedContainer c) public virtual void AddPartial (TypeDefinition next_part) { MemberCore mc; - (PartialContainer ?? this).defined_names.TryGetValue (next_part.Basename, out mc); + (PartialContainer ?? this).defined_names.TryGetValue (next_part.MemberName.Basename, out mc); AddPartial (next_part, mc as TypeDefinition); } @@ -380,7 +376,7 @@ public virtual void RemoveContainer (TypeContainer cont) containers.Remove (cont); var tc = Parent == Module ? Module : this; - tc.defined_names.Remove (cont.Basename); + tc.defined_names.Remove (cont.MemberName.Basename); } public virtual void VerifyMembers () @@ -772,7 +768,7 @@ public void AddMember (MemberCore symbol) public override void AddTypeContainer (TypeContainer tc) { - AddNameToContainer (tc, tc.Basename); + AddNameToContainer (tc, tc.MemberName.Basename); base.AddTypeContainer (tc); } @@ -1295,7 +1291,7 @@ bool CreateTypeBuilder () CreateMetadataName (sb); TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size); } else { - TypeBuilder = parent_def.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size); + TypeBuilder = parent_def.TypeBuilder.DefineNestedType (MemberName.Basename, TypeAttr, null, type_size); } if (DeclaringAssembly.Importer != null) @@ -1795,7 +1791,7 @@ public override void RemoveContainer (TypeContainer cont) { base.RemoveContainer (cont); Members.Remove (cont); - Cache.Remove (cont.Basename); + Cache.Remove (cont.MemberName.Basename); } protected virtual bool DoResolveTypeParameters () diff --git a/mcs/mcs/decl.cs b/mcs/mcs/decl.cs index 56d423ad23d..302c21a2c7a 100644 --- a/mcs/mcs/decl.cs +++ b/mcs/mcs/decl.cs @@ -195,11 +195,6 @@ public static string MakeName (string name, TypeParameters args) return name + "`" + args.Count; } - - public static string MakeName (string name, int count) - { - return name + "`" + count; - } } public class SimpleMemberName diff --git a/mcs/mcs/eval.cs b/mcs/mcs/eval.cs index 30c42c1af82..059ffb82d1d 100644 --- a/mcs/mcs/eval.cs +++ b/mcs/mcs/eval.cs @@ -1277,7 +1277,7 @@ public void AddTypeContainer (TypeContainer current_container, TypeDefinition tc if (current_container.Containers != null) { - var existing = current_container.Containers.FirstOrDefault (l => l.Basename == tc.Basename); + var existing = current_container.Containers.FirstOrDefault (l => l.MemberName.Basename == tc.MemberName.Basename); if (existing != null) { current_container.RemoveContainer (existing); undo_actions.Add (() => current_container.AddTypeContainer (existing)); diff --git a/mcs/mcs/namespace.cs b/mcs/mcs/namespace.cs index 970e2ca024e..0a35cc4c61e 100644 --- a/mcs/mcs/namespace.cs +++ b/mcs/mcs/namespace.cs @@ -503,7 +503,7 @@ public void RemoveContainer (TypeContainer tc) } } - cached_types.Remove (tc.Basename); + cached_types.Remove (tc.MemberName.Basename); } public void SetBuiltinType (BuiltinTypeSpec pts) @@ -804,9 +804,8 @@ public override void AddPartial (TypeDefinition next_part) public override void AddTypeContainer (TypeContainer tc) { - string name = tc.Basename; - var mn = tc.MemberName; + var name = mn.Basename; while (mn.Left != null) { mn = mn.Left; name = mn.Name; diff --git a/mcs/tests/test-async-75.cs b/mcs/tests/test-async-75.cs new file mode 100644 index 00000000000..ead75c4dcb7 --- /dev/null +++ b/mcs/tests/test-async-75.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; +using System.Runtime.CompilerServices; +using System.Reflection; + +class CorrectEncodingOfNestedTypes +{ + static async Task GetAsync(string s) where T : new() + { + return await Task.Factory.StartNew(async () => { + var response = await Task.FromResult (s); + return (T)new object(); + }).Unwrap(); + } + + public static int Main () + { + var t = typeof (CorrectEncodingOfNestedTypes).GetNestedTypes (BindingFlags.NonPublic) [0].GetNestedTypes (BindingFlags.NonPublic) [0]; + var m = t.GetMethods (BindingFlags.NonPublic | BindingFlags.Instance) [0]; + var ca = (AsyncStateMachineAttribute) m.GetCustomAttributes (true) [0]; + if (ca.StateMachineType.GetGenericArguments ().Length != 1) + return 1; + + return 0; + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 755aa7e0604..c366610f146 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -2853,11 +2853,6 @@ 7 - - - 7 - - 46 @@ -2868,11 +2863,6 @@ 114 - - - 118 - - 0 @@ -2897,6 +2887,14 @@ 105 + + + 118 + + + 7 + + @@ -21851,11 +21849,6 @@ 7 - - - 7 - - 30 @@ -21869,6 +21862,11 @@ 14 + + + 7 + + @@ -21913,11 +21911,6 @@ 7 - - - 7 - - 37 @@ -21931,6 +21924,11 @@ 14 + + + 7 + + @@ -51309,14 +51307,6 @@ 7 - - - 7 - - - 51 - - 0 @@ -51333,6 +51323,14 @@ 0 + + + 51 + + + 7 + + @@ -52035,14 +52033,6 @@ 7 - - - 7 - - - 66 - - 0 @@ -52059,6 +52049,14 @@ 0 + + + 66 + + + 7 + + @@ -52967,14 +52965,6 @@ 7 - - - 7 - - - 51 - - 0 @@ -52991,6 +52981,14 @@ 0 + + + 51 + + + 7 + + @@ -53261,16 +53259,16 @@ 7 - - - 7 - - 48 + + + 7 + + @@ -53589,29 +53587,25 @@ 7 - - - 7 - - - - - 7 + + + 24 - + 52 + + 7 + - + 35 - - - - 24 + + 7 @@ -54291,25 +54285,25 @@ 7 - - - 7 + + + 0 + + + 0 - + 7 + + 52 - - - - 0 - - - 0 + + 7 @@ -61471,22 +61465,10 @@ 7 - - - - 7 - - - 26 - - - 14 - - 13 @@ -61502,6 +61484,14 @@ 13 + + + 14 + + + 7 + + @@ -63935,6 +63925,43 @@ + + + + 41 + + + 91 + + + 7 + + + + + 218 + + + 13 + + + + + 41 + + + 7 + + + + + 190 + + + 13 + + + From 3f740f3d94c00f0edd4f0bb317bd3133ac279da0 Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Fri, 12 Sep 2014 11:19:05 -0400 Subject: [PATCH 115/543] Fixes 19752 - Users have been complaining about strange errors arising when using the OracleClient classes. I have tracked it down to the OciDefineHandle and OciDefineByPos calls, and OracleParameter handling of amanged objects by unmanaged code. Currently two of the parameters passed to the above OCI call are short variables. They are passed as "ref" fields as Oracle uses their address to put size and indicator data once the data is fetched. However, being defined as short means that they are eligible for being moved during garbage collection. Thus if that field is moved between the OciDefineByPos call and the fetch of the data then what Oracle is pointing to may no longer be variable. I'm thinking it may be better to define these fields as IntPtr and allocate them and retrieve their values via Marshal.ReadInt16. As for OracleParameter, it uses a managed object "indicator" that is also used in a similar way. This reference is replaced by a IntPtr and a get/set method to access the contents. --- .../System.Data.OracleClient.Oci/OciCalls.cs | 56 ++++++++-------- .../OciDefineHandle.cs | 62 ++++++++++-------- .../OracleParameter.cs | 64 ++++++++++++++----- 3 files changed, 111 insertions(+), 71 deletions(-) diff --git a/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs b/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs index 3e1ce930785..e6125bf5c91 100644 --- a/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs +++ b/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs @@ -95,7 +95,7 @@ internal static extern int OCIBindByName (IntPtr stmtp, IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -111,7 +111,7 @@ internal static extern int OCIBindByNameRef (IntPtr stmtp, ref IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -127,7 +127,7 @@ internal static extern int OCIBindByNameBytes (IntPtr stmtp, byte[] valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -142,7 +142,7 @@ internal static extern int OCIBindByPos (IntPtr stmtp, IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -157,7 +157,7 @@ internal static extern int OCIBindByPosBytes (IntPtr stmtp, byte[] valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -172,7 +172,7 @@ internal static extern int OCIBindByPosRef (IntPtr stmtp, ref IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -193,8 +193,8 @@ internal static extern int OCIDefineByPos (IntPtr stmtp, IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U4)] OciDataType dty, - ref short indp, - ref short rlenp, + IntPtr indp, + IntPtr rlenp, IntPtr rcodep, uint mode); @@ -206,8 +206,8 @@ internal static extern int OCIDefineByPosPtr (IntPtr stmtp, ref IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U4)] OciDataType dty, - ref short indp, - ref short rlenp, + IntPtr indp, + IntPtr rlenp, IntPtr rcodep, uint mode); @@ -547,7 +547,7 @@ internal static int OCIBindByName (IntPtr stmtp, IntPtr valuep, int value_sz, OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -558,7 +558,7 @@ internal static int OCIBindByName (IntPtr stmtp, Trace.WriteLineIf(traceOci, "OCIBindByName", "OCI"); #endif return OciNativeCalls.OCIBindByName (stmtp, out bindpp, errhp, placeholder, placeh_len, valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } internal static int OCIBindByNameRef (IntPtr stmtp, @@ -569,7 +569,7 @@ internal static int OCIBindByNameRef (IntPtr stmtp, ref IntPtr valuep, int value_sz, OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -580,7 +580,7 @@ internal static int OCIBindByNameRef (IntPtr stmtp, Trace.WriteLineIf(traceOci, "OCIBindByName", "OCI"); #endif return OciNativeCalls.OCIBindByNameRef (stmtp, out bindpp, errhp, placeholder, placeh_len, ref valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } internal static int OCIBindByNameBytes (IntPtr stmtp, @@ -591,7 +591,7 @@ internal static int OCIBindByNameBytes (IntPtr stmtp, byte[] valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -602,7 +602,7 @@ internal static int OCIBindByNameBytes (IntPtr stmtp, Trace.WriteLineIf(traceOci, "OCIBindByName", "OCI"); #endif return OciNativeCalls.OCIBindByNameBytes (stmtp, out bindpp, errhp, placeholder, placeh_len, valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } internal static int OCIBindByPos (IntPtr stmtp, @@ -612,7 +612,7 @@ internal static int OCIBindByPos (IntPtr stmtp, IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -623,7 +623,7 @@ internal static int OCIBindByPos (IntPtr stmtp, Trace.WriteLineIf(traceOci, "OCIBindByPos", "OCI"); #endif return OciNativeCalls.OCIBindByPos (stmtp, out bindpp, errhp, position, valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } internal static int OCIBindByPosRef (IntPtr stmtp, @@ -633,7 +633,7 @@ internal static int OCIBindByPosRef (IntPtr stmtp, ref IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -644,7 +644,7 @@ internal static int OCIBindByPosRef (IntPtr stmtp, Trace.WriteLineIf(traceOci, "OCIBindByPos", "OCI"); #endif return OciNativeCalls.OCIBindByPosRef (stmtp, out bindpp, errhp, position, ref valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } internal static int OCIBindByPosBytes (IntPtr stmtp, @@ -654,7 +654,7 @@ internal static int OCIBindByPosBytes (IntPtr stmtp, byte[] valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -665,7 +665,7 @@ internal static int OCIBindByPosBytes (IntPtr stmtp, Trace.WriteLineIf(traceOci, "OCIBindByPos", "OCI"); #endif return OciNativeCalls.OCIBindByPosBytes (stmtp, out bindpp, errhp, position, valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } [DllImport ("oci")] @@ -723,8 +723,8 @@ internal static int OCIDefineByPos (IntPtr stmtp, IntPtr valuep, int value_sz, OciDataType dty, - ref short indp, - ref short rlenp, + IntPtr indp, + IntPtr rlenp, IntPtr rcodep, uint mode) { @@ -732,7 +732,7 @@ internal static int OCIDefineByPos (IntPtr stmtp, Trace.WriteLineIf(traceOci, "OCIDefineByPos", "OCI"); #endif return OciNativeCalls.OCIDefineByPos (stmtp, out defnpp, errhp, position, valuep, - value_sz, dty, ref indp, ref rlenp, rcodep, mode); + value_sz, dty, indp, rlenp, rcodep, mode); } internal static int OCIDefineByPosPtr (IntPtr stmtp, @@ -742,8 +742,8 @@ internal static int OCIDefineByPosPtr (IntPtr stmtp, ref IntPtr valuep, int value_sz, OciDataType dty, - ref short indp, - ref short rlenp, + IntPtr indp, + IntPtr rlenp, IntPtr rcodep, uint mode) { @@ -751,7 +751,7 @@ internal static int OCIDefineByPosPtr (IntPtr stmtp, Trace.WriteLineIf(traceOci, "OCIDefineByPosPtr", "OCI"); #endif return OciNativeCalls.OCIDefineByPosPtr (stmtp, out defnpp, errhp, position, ref valuep, - value_sz, dty, ref indp, ref rlenp, rcodep, mode); + value_sz, dty, indp, rlenp, rcodep, mode); } internal static int OCIDescriptorFree (IntPtr hndlp, diff --git a/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciDefineHandle.cs b/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciDefineHandle.cs index baf90c1865f..9f46f98509b 100644 --- a/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciDefineHandle.cs +++ b/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciDefineHandle.cs @@ -32,16 +32,16 @@ internal sealed class OciDefineHandle : OciHandle, IDisposable //IntPtr handle; IntPtr value; - short indicator; + IntPtr indicator; //OracleType type; OciDataType ociType; OciDataType definedType; int definedSize; - short rlenp = 0; + IntPtr rlenp; //short precision; short scale; Type fieldType; - //string name; + string name; // Oracle defines the LONG VARCHAR and LONG VARRAW to have a size of 2 to the 31 power - 5 // see DefineLongVarChar and DefineLongVarRaw @@ -70,11 +70,13 @@ internal void DefineByPosition (int position, OracleConnection connection) { OciParameterDescriptor parameter = ((OciStatementHandle) Parent).GetParameter (position); - //name = parameter.GetName (); + name = parameter.GetName (); definedType = parameter.GetDataType (); definedSize = parameter.GetDataSize (); //precision = parameter.GetPrecision (); scale = parameter.GetScale (); + rlenp = OciCalls.AllocateClear (sizeof(short)); + indicator = OciCalls.AllocateClear (sizeof(short)); Define (position, connection); @@ -103,7 +105,7 @@ internal OciErrorHandle ErrorHandle { } internal bool IsNull { - get { return (indicator == -1); } + get { return (Indicator == -1); } } internal short Scale { @@ -111,7 +113,13 @@ internal short Scale { } internal short Size { - get { return rlenp; } + get { return(Marshal.ReadInt16(rlenp)); } + set { Marshal.WriteInt16(rlenp, value); } + } + + internal short Indicator { + get { return(Marshal.ReadInt16(indicator)); } + set { Marshal.WriteInt16(indicator, value); } } internal IntPtr Value { @@ -192,8 +200,8 @@ void DefineTimeStamp (int position, OracleConnection connection) ref value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); @@ -222,8 +230,8 @@ void DefineDate (int position, OracleConnection connection) value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); @@ -261,11 +269,11 @@ void DefineLongVarChar (int position, OracleConnection connection) value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); - rlenp = (short) definedSize; + Size = (short) definedSize; if (status != 0) { OciErrorInfo info = ErrorHandle.HandleError (); @@ -291,8 +299,8 @@ void DefineChar (int position, OracleConnection connection) value, maxByteCount, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); OciErrorHandle.ThrowExceptionIfError (ErrorHandle, status); @@ -312,10 +320,10 @@ void DefineNumber (int position, OracleConnection connection) ErrorHandle, position + 1, value, - definedSize * 2, + definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); @@ -357,8 +365,8 @@ void DefineLob (int position, OciDataType type, OracleConnection connection) ref value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); @@ -386,8 +394,8 @@ void DefineRaw (int position, OracleConnection connection) value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); if (status != 0) { @@ -415,8 +423,8 @@ void DefineLongVarRaw (int position, OracleConnection connection) value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); if (status != 0) { @@ -459,8 +467,8 @@ void DefineInterval (int position, OciDataType type, OracleConnection connection ref value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); @@ -487,6 +495,8 @@ protected override void Dispose (bool disposing) } disposed = true; } finally { + Marshal.FreeHGlobal (indicator); + Marshal.FreeHGlobal (rlenp); base.Dispose (disposing); value = IntPtr.Zero; } diff --git a/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs b/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs index 6f11d970f0d..ef5eb270207 100644 --- a/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs +++ b/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs @@ -37,12 +37,13 @@ namespace System.Data.OracleClient { [TypeConverter (typeof(OracleParameter.OracleParameterConverter))] - public sealed class OracleParameter : + public sealed class OracleParameter : #if NET_2_0 - DbParameter, IDbDataParameter, ICloneable + DbParameter, IDbDataParameter, ICloneable, #else - MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable + MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable, #endif + IDisposable { #region Fields @@ -66,6 +67,7 @@ public sealed class OracleParameter : object value = DBNull.Value; OciLobLocator lobLocator; // only if Blob or Clob IntPtr bindOutValue = IntPtr.Zero; + IntPtr indicator = IntPtr.Zero; OciDateTimeDescriptor dateTimeDesc; IntPtr cursor = IntPtr.Zero; @@ -77,7 +79,6 @@ public sealed class OracleParameter : bool useRef; OciDataType bindType; - short indicator; int bindSize; bool sizeManuallySet; @@ -104,6 +105,7 @@ private OracleParameter (OracleParameter value) this.value = value.value; this.lobLocator = value.lobLocator; this.oracleTypeSet = value.oracleTypeSet; + this.indicator = OciCalls.AllocateClear (sizeof(short)); } public OracleParameter () @@ -119,6 +121,7 @@ public OracleParameter () this.srcVersion = DataRowVersion.Current; this.value = null; this.oracleTypeSet = false; + this.indicator = OciCalls.AllocateClear (sizeof(short)); } public OracleParameter (string name, object value) @@ -129,6 +132,7 @@ public OracleParameter (string name, object value) srcColumn = string.Empty; SourceVersion = DataRowVersion.Current; InferOracleType (value); + this.indicator = OciCalls.AllocateClear (sizeof(short)); #if NET_2_0 // Find the OciType before inferring for the size if (value != null && value != DBNull.Value) { @@ -173,6 +177,7 @@ public OracleParameter (string name, OracleType oracleType, int size, ParameterD OracleType = oracleType; SourceColumn = sourceColumn; SourceVersion = sourceVersion; + this.indicator = OciCalls.AllocateClear (sizeof(short)); } #endif @@ -199,6 +204,12 @@ public OracleParameter (string name, OracleType oracleType, int size, ParameterD OracleType = oracleType; SourceColumn = srcColumn; SourceVersion = srcVersion; + this.indicator = OciCalls.AllocateClear (sizeof(short)); + } + + ~OracleParameter () + { + Dispose(false); } #endregion // Constructors @@ -210,6 +221,11 @@ internal OracleParameterCollection Container { set { container = value; } } + internal short Indicator { + get { return (Marshal.ReadInt16(indicator)); } + set { Marshal.WriteInt16(indicator, value); } + } + #if !NET_2_0 [Browsable (false)] [RefreshProperties (RefreshProperties.All)] @@ -453,7 +469,6 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos } if (isnull == true && direction == ParameterDirection.Input) { - indicator = 0; bindType = OciDataType.VarChar2; bindSize = 0; } else { @@ -465,7 +480,6 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos case OciDataType.CharZ: case OciDataType.OciString: bindType = OciDataType.String; - indicator = 0; svalue = "\0"; // convert value from managed type to type to marshal if (direction == ParameterDirection.Input || @@ -558,7 +572,7 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos dt = DateTime.MinValue; sDate = ""; if (isnull) - indicator = -1; + Indicator = -1; else if (v is String) { sDate = (string) v; dt = DateTime.Parse (sDate); @@ -594,7 +608,7 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos case OciDataType.Float: case OciDataType.Number: bindType = OciDataType.String; - indicator = 0; + Indicator = 0; svalue = "\0"; // convert value from managed type to type to marshal if (direction == ParameterDirection.Input || @@ -638,7 +652,7 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos bindSize = Size + 5; // 4 bytes prepended for length, bytes, 1 byte NUL character - indicator = 0; + Indicator = 0; svalue = "\0"; // convert value from managed type to type to marshal if (direction == ParameterDirection.Input || @@ -758,7 +772,7 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos case OciDataType.VarRaw: bindType = OciDataType.VarRaw; bindSize = Size + 2; // include 2 bytes prepended to hold the length - indicator = 0; + Indicator = 0; bytes = new byte [bindSize]; if (direction == ParameterDirection.Input || direction == ParameterDirection.InputOutput) { @@ -784,7 +798,7 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos case OciDataType.LongVarRaw: bindType = OciDataType.LongVarRaw; bindSize = Size + 4; // include 4 bytes prepended to hold the length - indicator = 0; + Indicator = 0; bytes = new byte [bindSize]; if (direction == ParameterDirection.Input || direction == ParameterDirection.InputOutput) { @@ -854,7 +868,7 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos ref bindValue, bindSize, bindType, - ref indicator, + indicator, IntPtr.Zero, IntPtr.Zero, 0, @@ -870,7 +884,7 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos ref bindValue, bindSize, bindType, - ref indicator, + indicator, IntPtr.Zero, IntPtr.Zero, 0, @@ -887,7 +901,7 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos ref cursor, bindSize, bindType, - ref indicator, + indicator, IntPtr.Zero, IntPtr.Zero, 0, @@ -903,7 +917,7 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos bytes, bindSize, bindType, - ref indicator, + indicator, IntPtr.Zero, IntPtr.Zero, 0, @@ -919,7 +933,7 @@ internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos bindValue, bindSize, bindType, - ref indicator, + indicator, IntPtr.Zero, IntPtr.Zero, 0, @@ -1251,7 +1265,7 @@ private void GetOutValue (OracleCommand cmd) // used to update the parameter value // for Output, the output of InputOutput, and Return parameters value = DBNull.Value; - if (indicator == -1) + if (Indicator == -1) return; int rsize = 0; @@ -1453,6 +1467,22 @@ private byte[] PackDate (DateTime dateValue) return buffer; } + public void Dispose () + { + Dispose (true); + } + + void Dispose (bool disposing) + { + if (disposing) { + GC.SuppressFinalize(this); + } + if (indicator != IntPtr.Zero) { + Marshal.FreeHGlobal (indicator); + indicator = IntPtr.Zero; + } + } + #endregion // Methods internal sealed class OracleParameterConverter : ExpandableObjectConverter From f065a289f69be29d4d6c310b6949c2cd9429c355 Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Fri, 12 Sep 2014 11:37:52 -0400 Subject: [PATCH 116/543] Maximum large object size should be limited by SSIZE_MAX not SIZE_MAX. The latter appears to be a hangover from 32-bit systems. --- mono/metadata/sgen-los.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mono/metadata/sgen-los.c b/mono/metadata/sgen-los.c index 1e38006cac7..8e823b05537 100644 --- a/mono/metadata/sgen-los.c +++ b/mono/metadata/sgen-los.c @@ -336,13 +336,13 @@ sgen_los_alloc_large_inner (MonoVTable *vtable, size_t size) g_assert ((size & 1) == 0); /* - * size + sizeof (LOSObject) <= SIZE_MAX - (mono_pagesize () - 1) + * size + sizeof (LOSObject) <= SSIZE_MAX - (mono_pagesize () - 1) * * therefore: * - * size <= SIZE_MAX - (mono_pagesize () - 1) - sizeof (LOSObject) + * size <= SSIZE_MAX - (mono_pagesize () - 1) - sizeof (LOSObject) */ - if (size > SIZE_MAX - (mono_pagesize () - 1) - sizeof (LOSObject)) + if (size > SSIZE_MAX - (mono_pagesize () - 1) - sizeof (LOSObject)) return NULL; #ifdef LOS_DUMMY From a8392ba567cb8038111beff25ee1c61aeae3232d Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Fri, 12 Sep 2014 14:15:55 -0400 Subject: [PATCH 117/543] [runtime] Improve thread dumping reliability by doing it while holding the fat locks. We take the loader and the root domain locks before doing a thread dump. This reduces the odds of us suspending a thread that holds either of them and deadlocking, for example, while decoding AOT JIs. --- mono/metadata/threads.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index a0e5f8469d6..c189ab3e9f2 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -3265,14 +3265,19 @@ mono_threads_perform_thread_dump (void) printf ("Full thread dump:\n"); - /* - * Make a copy of the hashtable since we can't do anything with - * threads while threads_mutex is held. - */ + /* We take the loader lock and the root domain lock as to increase our odds of not deadlocking if + something needs then in the process. + */ + mono_loader_lock (); + mono_domain_lock (mono_get_root_domain ()); + mono_threads_lock (); mono_g_hash_table_foreach (threads, dump_thread, NULL); mono_threads_unlock (); + mono_domain_unlock (mono_get_root_domain ()); + mono_loader_unlock (); + thread_dump_requested = FALSE; } From 6c1bf0d17e7e4e943a5f4983e11e5da698870c80 Mon Sep 17 00:00:00 2001 From: Joel Martinez Date: Fri, 12 Sep 2014 17:22:06 -0400 Subject: [PATCH 118/543] [mdoc] consolidated dropns and dropns-assemblies into a single parameter. Based on pull request feedback, this is a simpler usage, and meets our required use-case. A sample version of this parameter would be: `--dropns MyUnifiedAssembly=MyDroppedPrefix` --- mcs/tools/mdoc/Makefile | 4 ++-- mcs/tools/mdoc/Mono.Documentation/monodocer.cs | 15 ++++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/mcs/tools/mdoc/Makefile b/mcs/tools/mdoc/Makefile index 8e91020a90b..ad24c3d2d4e 100644 --- a/mcs/tools/mdoc/Makefile +++ b/mcs/tools/mdoc/Makefile @@ -136,11 +136,11 @@ check-monodocer-dropns-classic-withsecondary: $(PROGRAM) update-monodocer-dropns-unified: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-unified.dll - $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll --dropns=MyFramework --dropns-assemblies=Test/DocTest-DropNS-unified.dll + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll --dropns Test/DocTest-DropNS-unified.dll=MyFramework update-monodocer-dropns-unified-withsecondary: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-unified.dll - $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll Test/DocTest-DropNS-classic-secondary.dll --dropns=MyFramework --dropns-assemblies=Test/DocTest-DropNS-unified.dll + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll Test/DocTest-DropNS-classic-secondary.dll --dropns Test/DocTest-DropNS-unified.dll=MyFramework update-monodocer-dropns-classic-secondary: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-classic-secondary.dll diff --git a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs index 1515adde2d7..09763096e55 100644 --- a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs +++ b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs @@ -257,11 +257,16 @@ public override void Run (IEnumerable args) "Only update documentation for {TYPE}.", v => types.Add (v) }, { "dropns=", - "Instructs the update process that {NAMESPACE} has been dropped, so that types and members will match existing documentation nodes.", - v => droppedNamespace = v }, - { "dropns-assemblies=", - "Comma separated list of the assemblies that are having the namespace dropped. If this is not provided, it is assumed that all are", - v => droppedAssemblies.AddRange (v.Split (',').Select (a => Path.GetFileName (a.Trim ()))) }, + "When processing assembly {ASSEMBLY}, strip off leading namespace {PREFIX}:\n" + + " e.g. --dropns ASSEMBLY=PREFIX", + v => { + var parts = v.Split ('='); + if (parts.Length != 2) { Console.Error.WriteLine ("Invalid dropns input"); return; } + var assembly = Path.GetFileName (parts [0].Trim ()); + var prefix = parts [1].Trim(); + droppedAssemblies.Add (assembly); + droppedNamespace = prefix; + } }, { "ntypes", "If the new assembly is switching to 'magic types', then this switch should be defined.", v => SwitchingToMagicTypes = true }, From a1f58d35be58a5bc61cbc297c8deef08b7504d00 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 12 Sep 2014 20:07:05 -0400 Subject: [PATCH 119/543] [runtime] Fix the windows build. Define _WINSOCKAPI_ to fix the compilation problems when windows.h is included before winsock2.h: http://stackoverflow.com/questions/1372480/c-redefinition-header-files. --- mono/utils/mono-compiler.h | 4 +++- mono/utils/mono-poll.c | 5 +++++ msvc/mono.def | 1 - msvc/mono.props | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) mode change 100644 => 100755 mono/utils/mono-poll.c diff --git a/mono/utils/mono-compiler.h b/mono/utils/mono-compiler.h index c1d0e27a49c..2b330b9bb9d 100644 --- a/mono/utils/mono-compiler.h +++ b/mono/utils/mono-compiler.h @@ -198,10 +198,12 @@ #endif #include -#define isnan(x) _isnan(x) #define trunc(x) (((x) < 0) ? ceil((x)) : floor((x))) +#if _MSC_VER < 1800 /* VS 2013 */ +#define isnan(x) _isnan(x) #define isinf(x) (_isnan(x) ? 0 : (_fpclass(x) == _FPCLASS_NINF) ? -1 : (_fpclass(x) == _FPCLASS_PINF) ? 1 : 0) #define isnormal(x) _finite(x) +#endif #define popen _popen #define pclose _pclose diff --git a/mono/utils/mono-poll.c b/mono/utils/mono-poll.c old mode 100644 new mode 100755 index 7326254c35b..5e5adfe2f00 --- a/mono/utils/mono-poll.c +++ b/mono/utils/mono-poll.c @@ -20,6 +20,11 @@ mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout) } #else +#ifdef HOST_WIN32 +/* For select */ +#include +#endif + int mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout) { diff --git a/msvc/mono.def b/msvc/mono.def index 61d1779c336..72c3c4c0d7e 100644 --- a/msvc/mono.def +++ b/msvc/mono.def @@ -537,7 +537,6 @@ mono_metadata_guid_heap mono_metadata_implmap_from_method mono_metadata_init mono_metadata_interfaces_from_typedef -mono_metadata_load_generic_param_constraints mono_metadata_load_generic_params mono_metadata_locate mono_metadata_locate_token diff --git a/msvc/mono.props b/msvc/mono.props index 7fe3206e248..ef26f9180d7 100644 --- a/msvc/mono.props +++ b/msvc/mono.props @@ -1,4 +1,4 @@ - + $(MSBuildProjectDirectory)\.. @@ -9,7 +9,7 @@ - __default_codegen__;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;GC_NOT_DLL;WIN32_THREADS;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;_UNICODE;UNICODE;WIN32_THREADS;FD_SETSIZE=1024;$(PreprocessorDefinitions) + __default_codegen__;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;GC_NOT_DLL;WIN32_THREADS;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;_UNICODE;UNICODE;WIN32_THREADS;FD_SETSIZE=1024;$(PreprocessorDefinitions);_WINSOCKAPI_ Mswsock.lib;ws2_32.lib;ole32.lib;oleaut32.lib;psapi.lib;version.lib;advapi32.lib;winmm.lib;kernel32.lib;$(AdditionalDependencies) From 7f2825301e7dd60ea5aaddac4c298c6449a6c488 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Sat, 13 Sep 2014 12:43:16 +0200 Subject: [PATCH 120/543] [mcs] nullable property pattern --- mcs/mcs/cs-parser.jay | 5 +++++ mcs/mcs/expression.cs | 14 +++++--------- mcs/tests/test-pattern-07.cs | 26 ++++++++++++++++++++++++-- mcs/tests/ver-il-net_4_5.xml | 25 +++++++++++++++++++++++-- 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index a69e356668d..35dc0a9cf02 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -4353,6 +4353,11 @@ pattern_expr } | sizeof_expression | default_value_expression + | OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression + { + $$ = new Cast ((FullNamedExpression) $2, (Expression) $4, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + } | STAR { $$ = new WildcardPattern (GetLocation ($1)); diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 6c345e0f1c8..823c95c3141 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -1791,6 +1791,10 @@ Expression ResolveMatchingExpression (ResolveContext rc) if (Expr.Type.IsNullableType) { expr_unwrap = new Nullable.Unwrap (Expr); expr_unwrap.Resolve (rc); + ProbeType = Convert.ImplicitConversion (rc, ProbeType, expr_unwrap.Type, loc); + } else if (ProbeType.Type == Expr.Type) { + // TODO: Better error handling + return new Binary (Binary.Operator.Equality, Expr, mc, loc).Resolve (rc); } else if (ProbeType.Type.IsEnum || (ProbeType.Type.BuiltinType >= BuiltinTypeSpec.Type.Byte && ProbeType.Type.BuiltinType <= BuiltinTypeSpec.Type.Decimal)) { var helper = rc.Module.CreatePatterMatchingHelper (); number_mg = helper.NumberMatcher.Spec; @@ -2236,15 +2240,7 @@ static Expression ResolveComparison (ResolveContext rc, Expression expr, Express if (expr is WildcardPattern) return new EmptyExpression (expr.Type); - var res = Convert.ImplicitConversionRequired (rc, expr, instance.Type, expr.Location); - if (res == null) - return null; - - if (expr is ComplexPatternExpression) - return new Is (instance, res, expr.Location).Resolve (rc); - - // TODO: Better error handling - return new Binary (Binary.Operator.Equality, instance, res, expr.Location).Resolve (rc); + return new Is (instance, expr, expr.Location).Resolve (rc); } public override void EmitBranchable (EmitContext ec, Label target, bool on_true) diff --git a/mcs/tests/test-pattern-07.cs b/mcs/tests/test-pattern-07.cs index 8743b35c5e7..bc7dfda0a89 100644 --- a/mcs/tests/test-pattern-07.cs +++ b/mcs/tests/test-pattern-07.cs @@ -31,6 +31,24 @@ static int Main () if (res2) return 5; + object o3 = new X () { + Value = 5 + }; + + if (o3 is X { Value is 6 }) + return 6; + + if (!(o3 is X { Value is 5 })) + return 7; + + object o4 = new X () { + NullableValue = 4 + }; + + bool res3 = o4 is X { NullableValue is (byte) 4 }; + if (!res3) + return 8; + Console.WriteLine("ok"); return 0; } @@ -39,6 +57,10 @@ static int Main () class X { public object Field { get; set; } + + public object Value { get; set; } + + public long? NullableValue { get; set; } } class Y @@ -49,5 +71,5 @@ public static bool operator is (Y y, out int x) { x = 4; return true; - } -} \ No newline at end of file + } +} diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index c366610f146..de7c52cde3b 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -68486,7 +68486,7 @@ - 633 + 609 7 @@ -68592,7 +68592,7 @@ - 444 + 684 7 @@ -68623,6 +68623,27 @@ 7 + + + 14 + + + 8 + + + + + 69 + + + + + 14 + + + 8 + + From 777f69153c51bd36bdc2fcb88d116309e78f55ef Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sat, 13 Sep 2014 13:56:18 -0400 Subject: [PATCH 121/543] [runtime] Remove an unused interpreter file. --- mono/arch/unknown.c | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 mono/arch/unknown.c diff --git a/mono/arch/unknown.c b/mono/arch/unknown.c deleted file mode 100644 index d865299001c..00000000000 --- a/mono/arch/unknown.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "mono/interpreter/interp.h" -#ifdef NO_PORT -MonoPIFunc -mono_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor) -{ - g_error ("Unsupported arch"); - return NULL; -} - -void * -mono_create_method_pointer (MonoMethod *method) -{ - g_error ("Unsupported arch"); - return NULL; -} - -#endif - From 6354f74888a549075c639349147dc83bb10d5b72 Mon Sep 17 00:00:00 2001 From: Marc-Andre Ferland Date: Sat, 13 Sep 2014 00:10:59 -0400 Subject: [PATCH 122/543] Missing setting disposed to true --- mcs/class/corlib/System.Security.Cryptography/HMAC.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/mcs/class/corlib/System.Security.Cryptography/HMAC.cs b/mcs/class/corlib/System.Security.Cryptography/HMAC.cs index e83eb67e69e..eb165dc56cb 100644 --- a/mcs/class/corlib/System.Security.Cryptography/HMAC.cs +++ b/mcs/class/corlib/System.Security.Cryptography/HMAC.cs @@ -117,6 +117,7 @@ private byte[] KeySetup (byte[] key, byte padding) protected override void Dispose (bool disposing) { if (!_disposed) { + _disposed = true; base.Dispose (disposing); } } From 8b9c60075f7b97fe88c3c588968977ff9bcf8c28 Mon Sep 17 00:00:00 2001 From: Marc-Andre Ferland Date: Fri, 12 Sep 2014 21:40:30 -0400 Subject: [PATCH 123/543] Missing Args checks. --- .../Mono.Security/Mono.Security.Cryptography/CryptoTools.cs | 4 ++++ .../corlib/System.Security.Cryptography/HashAlgorithm.cs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoTools.cs b/mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoTools.cs index d57ce5ae55c..054038731ae 100644 --- a/mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoTools.cs +++ b/mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoTools.cs @@ -88,6 +88,10 @@ public BlockProcessor (ICryptoTransform transform) // block size (which isn't their real internal block size) public BlockProcessor (ICryptoTransform transform, int blockSize) { + if (transform == null) + throw new ArgumentNullException ("transform"); + if (blockSize <= 0) + throw new ArgumentOutOfRangeException ("blockSize"); this.transform = transform; this.blockSize = blockSize; block = new byte [blockSize]; diff --git a/mcs/class/corlib/System.Security.Cryptography/HashAlgorithm.cs b/mcs/class/corlib/System.Security.Cryptography/HashAlgorithm.cs index 07074f8aef3..150cac95bef 100644 --- a/mcs/class/corlib/System.Security.Cryptography/HashAlgorithm.cs +++ b/mcs/class/corlib/System.Security.Cryptography/HashAlgorithm.cs @@ -98,6 +98,8 @@ public byte[] ComputeHash (Stream inputStream) // don't read stream unless object is ready to use if (disposed) throw new ObjectDisposedException ("HashAlgorithm"); + if (inputStream == null) + throw new ArgumentNullException ("InputStream"); byte[] buffer = new byte [4096]; int len = inputStream.Read (buffer, 0, 4096); From d77664ceb0b3b1a3799e5666bcb77b4caafde6bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Sun, 14 Sep 2014 00:07:26 +0200 Subject: [PATCH 124/543] [System] Add performanceCounters element to System.Diagnostics app.config configuration section See http://msdn.microsoft.com/en-us/library/ms229387(v=vs.110).aspx for details about the element. The value that is set by the element isn't currently used in Mono, but applications using it in their app.config crash otherwise (e.g. http://stackoverflow.com/questions/25741651). --- .../DiagnosticsConfigurationHandler.cs | 20 ++++++++++++++++ .../DiagnosticsConfigurationHandlerTest.cs | 24 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/mcs/class/System/System.Diagnostics/DiagnosticsConfigurationHandler.cs b/mcs/class/System/System.Diagnostics/DiagnosticsConfigurationHandler.cs index 149ad3bc5ba..c3937530f66 100644 --- a/mcs/class/System/System.Diagnostics/DiagnosticsConfigurationHandler.cs +++ b/mcs/class/System/System.Diagnostics/DiagnosticsConfigurationHandler.cs @@ -94,6 +94,7 @@ public class DiagnosticsConfigurationHandler : IConfigurationSectionHandler public DiagnosticsConfigurationHandler () { elementHandlers ["assert"] = new ElementHandler (AddAssertNode); + elementHandlers ["performanceCounters"] = new ElementHandler (AddPerformanceCountersNode); elementHandlers ["switches"] = new ElementHandler (AddSwitchesNode); elementHandlers ["trace"] = new ElementHandler (AddTraceNode); elementHandlers ["sources"] = new ElementHandler (AddSourcesNode); @@ -181,6 +182,25 @@ private void AddAssertNode (IDictionary d, XmlNode node) ThrowUnrecognizedElement (node.ChildNodes[0]); } + private void AddPerformanceCountersNode (IDictionary d, XmlNode node) + { + XmlAttributeCollection c = node.Attributes; + string filemappingsize = GetAttribute (c, "filemappingsize", false, node); + ValidateInvalidAttributes (c, node); + if (filemappingsize != null) { + try { + d ["filemappingsize"] = int.Parse (filemappingsize); + } + catch (Exception e) { + throw new ConfigurationException ("The `filemappingsize' attribute must be an integral value.", + e, node); + } + } + + if (node.ChildNodes.Count > 0) + ThrowUnrecognizedElement (node.ChildNodes[0]); + } + // name and value attributes are required // Docs do not define "remove" or "clear" elements, but .NET recognizes // them diff --git a/mcs/class/System/Test/System.Diagnostics/DiagnosticsConfigurationHandlerTest.cs b/mcs/class/System/Test/System.Diagnostics/DiagnosticsConfigurationHandlerTest.cs index 9af93d5a2f8..8c9049470d7 100644 --- a/mcs/class/System/Test/System.Diagnostics/DiagnosticsConfigurationHandlerTest.cs +++ b/mcs/class/System/Test/System.Diagnostics/DiagnosticsConfigurationHandlerTest.cs @@ -159,6 +159,30 @@ public void AssertTag () ValidateExceptions ("#TAT:BadChildren", "{0}", badChildren); } + [Test] + [Category ("NotDotNet")] + public void PerformanceCountersTag () + { + string[] goodAttributes = { + "", + "filemappingsize=\"1048576\"", + "filemappingsize=\"0\"" + }; + ValidateSuccess ("#PCT:Good", "", goodAttributes); + + string[] badAttributes = { + "FileMappingSize=\"1048576\"", + "filemappingsize=\"\"", + "filemappingsize=\"non-int-value\"" + }; + ValidateExceptions ("#PCT:BadAttrs", "", badAttributes); + + string[] badChildren = { + "" + }; + ValidateExceptions ("#PCT:BadChildren", "{0}", badChildren); + } + [Test] [Category ("NotDotNet")] public void TraceTag_Attributes () From b50e4a87283dc0b08e7af5b850dc062158410c9b Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Mon, 2 Jun 2014 23:08:24 +0100 Subject: [PATCH 125/543] Allow CLR binaries to be passed to Process.Start On *nix files are not executable by default where on Windows they are. This causes problems if installing a NuGet package on *nix that contains .exe files intended to be used by build tasks. On Windows the build will invoke these without complaining whereas on *nix the build will fail with "Native error: cannot find file specified". On mono, the action that will be taken is to pass the path to the .exe file to mono as a command-line argument. If this was done in a shell it would succeed whether or not the .exe file has the executable bit set, so it seems that this should also succeed within a program. With thanks to @akoeplinger for help designing the test. I release this under the MIT license. --- mono/io-layer/processes.c | 32 +++++++++++++++++++++----- mono/tests/Makefile.am | 11 ++++++++- mono/tests/bug-17537-helper.cs | 10 +++++++++ mono/tests/bug-17537.cs | 41 ++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 mono/tests/bug-17537-helper.cs create mode 100644 mono/tests/bug-17537.cs diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index c65bf23813c..590233e0b69 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -521,6 +521,19 @@ gboolean CreateProcessWithLogonW (const gunichar2 *username, return CreateProcess (appname, cmdline, NULL, NULL, FALSE, create_flags, env, cwd, startup, process_info); } +static gboolean +is_readable (const char *prog) +{ + struct stat buf; + if (access (prog, R_OK) != 0) + return FALSE; + if (stat (prog, &buf)) + return FALSE; + if (S_ISREG (buf.st_mode)) + return TRUE; + return FALSE; +} + static gboolean is_executable (const char *prog) { @@ -655,7 +668,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, prog = g_strdup (unquoted); /* Executable existing ? */ - if (!is_executable (prog)) { + if (!is_readable (prog)) { DEBUG ("%s: Couldn't find executable %s", __func__, prog); g_free (unquoted); @@ -671,8 +684,8 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, prog = g_strdup_printf ("%s/%s", curdir, unquoted); g_free (curdir); - /* And make sure it's executable */ - if (!is_executable (prog)) { + /* And make sure it's readable */ + if (!is_readable (prog)) { DEBUG ("%s: Couldn't find executable %s", __func__, prog); g_free (unquoted); @@ -763,7 +776,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, prog = g_strdup (token); /* Executable existing ? */ - if (!is_executable (prog)) { + if (!is_readable (prog)) { DEBUG ("%s: Couldn't find executable %s", __func__, token); g_free (token); @@ -785,8 +798,10 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, /* I assume X_OK is the criterion to use, * rather than F_OK + * + * X_OK is too strict *if* the target is a CLR binary */ - if (!is_executable (prog)) { + if (!is_readable (prog)) { g_free (prog); prog = g_find_program_in_path (token); if (prog == NULL) { @@ -843,6 +858,13 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, goto free_strings; } } + } else { + if (!is_executable (prog)) { + DEBUG ("%s: Executable permisson not set on %s", __func__, prog); + g_free (prog); + SetLastError (ERROR_ACCESS_DENIED); + goto free_strings; + } } if (args_after_prog != NULL && *args_after_prog) { diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 7d448d374ad..38d49066666 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -400,7 +400,8 @@ BASE_TEST_CS_SRC= \ unload-appdomain-on-shutdown.cs \ block_guard_restore_aligment_on_exit.cs \ thread_static_gc_layout.cs \ - sleep.cs + sleep.cs \ + bug-17537.cs TEST_CS_SRC_DIST= \ $(BASE_TEST_CS_SRC) \ @@ -1188,6 +1189,14 @@ bug-382986-lib.dll: bug-382986-lib.cs bug-382986.exe: bug-382986.cs bug-382986-lib.dll $(MCS) -out:$@ -r:bug-382986-lib.dll $(srcdir)/bug-382986.cs +EXTRA_DIST += bug-17537-helper.cs +bug-17537-helper.exe: bug-17537-helper.cs + $(MCS) -out:$@ $(srcdir)/bug-17537-helper.cs + chmod -x $@ + +bug-17537.exe: bug-17537.cs bug-17537-helper.exe + $(MCS) -out:$@ $(srcdir)/bug-17537.cs + EXTRA_DIST += coreclr-security.cs coreclr-security.exe : coreclr-security.cs diff --git a/mono/tests/bug-17537-helper.cs b/mono/tests/bug-17537-helper.cs new file mode 100644 index 00000000000..315bb47f4e4 --- /dev/null +++ b/mono/tests/bug-17537-helper.cs @@ -0,0 +1,10 @@ +using System; +using System.IO; + +public class Test { + public static int Main(string[] args) + { + Console.WriteLine ("Hello from bug-17537-helper!"); + return 0; + } +} diff --git a/mono/tests/bug-17537.cs b/mono/tests/bug-17537.cs new file mode 100644 index 00000000000..747ac361f80 --- /dev/null +++ b/mono/tests/bug-17537.cs @@ -0,0 +1,41 @@ +using System; +using System.IO; +using System.Diagnostics; + +public class Test { + public static int Main(string[] args) + { + // Only run this test on Unix + int pl = (int) Environment.OSVersion.Platform; + if ((pl != 4) && (pl != 6) && (pl != 128)) { + return 0; + } + + // Try to invoke the helper assembly + // Return 0 only if it is successful + try + { + var name = "bug-17537-helper.exe"; + Console.WriteLine ("Launching subprocess: {0}", name); + var p = new Process(); + p.StartInfo.FileName = Path.Combine (AppDomain.CurrentDomain.BaseDirectory + name); + p.StartInfo.UseShellExecute = false; + + var result = p.Start(); + p.WaitForExit(1000); + if (result) { + Console.WriteLine ("Subprocess started successfully"); + return 0; + } else { + Console.WriteLine ("Subprocess failure"); + return 1; + } + } + catch (Exception e) + { + Console.WriteLine ("Subprocess exception"); + Console.WriteLine (e.Message); + return 1; + } + } +} From 7439e997ac1f2e40c6b9e1fab43d24b8c07f0561 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 15 Sep 2014 13:37:56 +0200 Subject: [PATCH 126/543] [xbuild] Use ToolPath when building ToolTask execution path. Fixes #22981 --- .../Microsoft.Build.Utilities/ToolTask.cs | 39 +++++- .../Microsoft.Build.Utilities/ToolTaskTest.cs | 125 ++++++++++++++++++ 2 files changed, 160 insertions(+), 4 deletions(-) diff --git a/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs b/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs index ded4b425c6c..d2570426a3e 100644 --- a/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs +++ b/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs @@ -1,12 +1,14 @@ // // ToolTask.cs: Base class for command line tool tasks. // -// Author: +// Authors: // Marek Sieradzki (marek.sieradzki@gmail.com) // Ankit Jain (jankit@novell.com) +// Marek Safar (marek.safar@gmail.com) // // (C) 2005 Marek Sieradzki // Copyright 2009 Novell, Inc (http://www.novell.com) +// Copyright 2014 Xamarin Inc // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -90,12 +92,41 @@ protected virtual bool CallHostObjectToExecute () return true; } + string CreateToolPath () + { + string tp; + if (string.IsNullOrEmpty (ToolPath)) { + tp = GenerateFullPathToTool (); + if (string.IsNullOrEmpty (tp)) + return null; + + tp = Path.GetDirectoryName (tp); + if (string.IsNullOrEmpty (tp)) + tp = Directory.GetCurrentDirectory (); + + } else { + tp = ToolPath; + } + + var path = Path.Combine (tp, ToolExe); + if (!File.Exists (path)) { + Log.LogError ("Tool executable '{0}' could not be found", path); + return null; + } + + return path; + } + public override bool Execute () { if (SkipTaskExecution ()) return true; - exitCode = ExecuteTool (GenerateFullPathToTool (), GenerateResponseFileCommands (), + var tool_path = CreateToolPath (); + if (tool_path == null) + return false; + + exitCode = ExecuteTool (tool_path, GenerateResponseFileCommands (), GenerateCommandLineCommands ()); // HandleTaskExecutionErrors is called only if exitCode != 0 @@ -289,14 +320,14 @@ protected virtual void LogEventsFromTextOutput (string singleLine, MessageImport protected virtual string GenerateCommandLineCommands () { - return null; + return ""; } protected abstract string GenerateFullPathToTool (); protected virtual string GenerateResponseFileCommands () { - return null; + return ""; } protected virtual string GetResponseFileSwitch (string responseFilePath) diff --git a/mcs/class/Microsoft.Build.Utilities/Test/Microsoft.Build.Utilities/ToolTaskTest.cs b/mcs/class/Microsoft.Build.Utilities/Test/Microsoft.Build.Utilities/ToolTaskTest.cs index ec1e34768b3..bfd7c038eae 100644 --- a/mcs/class/Microsoft.Build.Utilities/Test/Microsoft.Build.Utilities/ToolTaskTest.cs +++ b/mcs/class/Microsoft.Build.Utilities/Test/Microsoft.Build.Utilities/ToolTaskTest.cs @@ -26,6 +26,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; +using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -424,6 +425,53 @@ public void ToolExeAndPath () Assert.AreEqual (a.ToolPath, "Bar", "#5"); a.ToolPath = ""; Assert.AreEqual (a.ToolPath, "", "#6"); + + a.Execute (); + } + + [Test] + public void Execute_1 () + { + var t = new TestExecuteToolTask (); + t.OnExecuteTool = delegate { Assert.Fail ("#1"); }; + t.BuildEngine = new MockBuildEngine (); + Assert.IsFalse (t.Execute (), "result"); + } + + [Test] + public void Execute_2 () + { + var t = new TestExecuteToolTask (); + t.BuildEngine = new MockBuildEngine (); + t.ToolPath = Directory.GetCurrentDirectory (); + t.ToolExe = "Makefile"; + + t.OnExecuteTool = (pathToTool, responseFileCommands, commandLineCommands) => { + Assert.AreEqual (Path.Combine (Directory.GetCurrentDirectory (), "Makefile"), pathToTool, "#1"); + Assert.AreEqual ("", responseFileCommands, "#2"); + Assert.AreEqual ("", commandLineCommands, "#3"); + + }; + + Assert.IsTrue (t.Execute (), "result"); + } + + [Test] + public void Execute_3 () + { + var t = new TestExecuteToolTask (); + t.FullPathToTool = "fpt"; + t.BuildEngine = new MockBuildEngine (); + t.ToolExe = "Makefile"; + + t.OnExecuteTool = (pathToTool, responseFileCommands, commandLineCommands) => { + Assert.AreEqual (Path.Combine (Directory.GetCurrentDirectory (), "Makefile"), pathToTool, "#1"); + Assert.AreEqual ("", responseFileCommands, "#2"); + Assert.AreEqual ("", commandLineCommands, "#3"); + + }; + + Assert.IsTrue (t.Execute (), "result"); } } @@ -548,9 +596,86 @@ protected override string ToolName { } protected override string GenerateFullPathToTool () + { + return ""; + } + } + + class MockBuildEngine : IBuildEngine + { + public int ColumnNumberOfTaskNode { + get { + return 0; + } + } + + public bool ContinueOnError { + get { + throw new NotImplementedException (); + } + } + + public int LineNumberOfTaskNode { + get { + return 0; + } + } + + public string ProjectFileOfTaskNode { + get { + return "ProjectFileOfTaskNode"; + } + } + + public bool BuildProjectFile (string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs) { throw new NotImplementedException (); } + + public void LogCustomEvent (CustomBuildEventArgs e) + { + } + + public void LogErrorEvent (BuildErrorEventArgs e) + { + Console.WriteLine (e.Message); + } + + public void LogMessageEvent (BuildMessageEventArgs e) + { + } + + public void LogWarningEvent (BuildWarningEventArgs e) + { + } + } + + class TestExecuteToolTask : ToolTask + { + public Action OnExecuteTool; + public string FullPathToTool; + + protected override string ToolName { + get { return "TestTool.exe"; } + } + + protected override bool CallHostObjectToExecute () + { + return base.CallHostObjectToExecute (); + } + + protected override string GenerateFullPathToTool () + { + return FullPathToTool; + } + + protected override int ExecuteTool (string pathToTool, string responseFileCommands, string commandLineCommands) + { + if (OnExecuteTool != null) + OnExecuteTool (pathToTool, responseFileCommands, commandLineCommands); + + return 0; + } } } From 1ec4bd5c26a6813ecaea6045da00d9e182c70251 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 5 Sep 2014 20:05:12 +0800 Subject: [PATCH 127/543] Fixed NullReferenceException. --- mcs/class/System.XML/System.Xml.Serialization/TypeData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.XML/System.Xml.Serialization/TypeData.cs b/mcs/class/System.XML/System.Xml.Serialization/TypeData.cs index 861fcc11de6..79c89c25670 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/TypeData.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/TypeData.cs @@ -255,7 +255,7 @@ public static string ToCSharpName (Type type, bool full) sb.Append (type.Name); } else { - if (full && type.Namespace.Length > 0) + if (full && !string.IsNullOrEmpty(type.Namespace)) sb.Append (type.Namespace).Append ('.'); sb.Append (type.Name); } From 17ad50a1659be3049f94ee59c1f2b0f8d4161b24 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 5 Sep 2014 20:47:48 +0800 Subject: [PATCH 128/543] Added test for optional {V}Specified and ShouldSerialize{V}. {V}Specified is a property or field and ShouldSerialize{V} is a method that can be set to false if we do not want to serialize an attribute with name {V}. --- .../XmlSerializerTests.cs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs index 28f6827c9b6..442ce4b08f5 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs @@ -3348,6 +3348,69 @@ public void ClassWithImplicitlyConvertibleElement () } } } + + public class ClassWithOptionalMethods + { + private readonly bool shouldSerializeX; + private readonly bool xSpecified; + + [XmlAttribute] + public int X { get; set; } + + public bool ShouldSerializeX () { return shouldSerializeX; } + + public bool XSpecified + { + get { return xSpecified; } + } + + public ClassWithOptionalMethods () + { + } + + public ClassWithOptionalMethods (int x, bool shouldSerializeX, bool xSpecified) + { + this.X = x; + this.shouldSerializeX = shouldSerializeX; + this.xSpecified = xSpecified; + } + } + + [Test] + public void OptionalMethods () + { + var ser = new XmlSerializer (typeof (ClassWithOptionalMethods)); + + var expectedValueWithoutX = Infoset ("" + Environment.NewLine + + ""); + + var expectedValueWithX = Infoset ("" + Environment.NewLine + + ""); + + using (var t = new StringWriter ()) { + var obj = new ClassWithOptionalMethods (11, false, false); + ser.Serialize (t, obj); + Assert.AreEqual (expectedValueWithoutX, Infoset (t.ToString ())); + } + + using (var t = new StringWriter ()) { + var obj = new ClassWithOptionalMethods (11, true, false); + ser.Serialize (t, obj); + Assert.AreEqual (expectedValueWithoutX, Infoset (t.ToString ())); + } + + using (var t = new StringWriter ()) { + var obj = new ClassWithOptionalMethods (11, false, true); + ser.Serialize (t, obj); + Assert.AreEqual (expectedValueWithoutX, Infoset (t.ToString ())); + } + + using (var t = new StringWriter ()) { + var obj = new ClassWithOptionalMethods (11, true, true); + ser.Serialize (t, obj); + Assert.AreEqual (expectedValueWithX, Infoset (t.ToString ())); + } + } } // Test generated serialization code. From 79de2b62f92caadc0dedaac59e67bf84f72a440b Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 5 Sep 2014 20:58:22 +0800 Subject: [PATCH 129/543] Added optional serialization based on ShouldSerialize{V}. SerializationCodeGenerator and XmlSerializationWriterInterpreter will no longer serialize an attribute named {V} if its object has a method named ShouldSerialize{V}() that returns false. {V}Specified now is also checked to be true before serializating the attribute even if it is a property that is not settable. Fixes #1852. --- .../SerializationCodeGenerator.cs | 13 +++-- .../XmlTypeMapMember.cs | 51 +++++++++++++++---- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs b/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs index 0ac2cd5e0ba..baedf04c7ec 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs @@ -1242,8 +1242,15 @@ string GenerateMemberHasValueCondition (XmlTypeMapMember member, string ob, bool else return mem + " != " + GetLiteral (member.DefaultValue); } - else if (member.IsOptionalValueType) - return ob + ".@" + member.Name + "Specified"; + else if (member.HasSpecified) { + var sb = new StringBuilder (); + sb.AppendFormat ("{0}.@{1}Specified", ob, member.Name); + if (member.HasShouldSerialize) + sb.AppendFormat (" && {0}.@ShouldSerialize{1} ()", ob, member.Name); + return sb.ToString (); + } else if (member.HasShouldSerialize) + return ob + ".@ShouldSerialize" + member.Name + " ()"; + return null; } @@ -2137,7 +2144,7 @@ void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, b } else { WriteLine (ob + ".@" + member.Name + " = " + value + ";"); - if (member.IsOptionalValueType) { + if (member.IsOptionalValueType && member.IsValueSpecifiedSettable ()) { string val = initializingMember ? "false" : "true"; WriteLine (ob + "." + member.Name + "Specified = " + val + ";"); } diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs index e023321ba40..eac0984ab97 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs @@ -46,6 +46,7 @@ internal class XmlTypeMapMember TypeData _typeData; MemberInfo _member; MemberInfo _specifiedMember; + MethodInfo _shouldSerialize; object _defaultValue = System.DBNull.Value; string documentation; int _flags; @@ -118,8 +119,12 @@ void InitMember (Type type) mems = type.GetMember (_name + "Specified", BindingFlags.Instance|BindingFlags.Public); if (mems.Length > 0) _specifiedMember = mems[0]; - if (_specifiedMember is PropertyInfo && !((PropertyInfo) _specifiedMember).CanWrite) + if (_specifiedMember is PropertyInfo && !((PropertyInfo) _specifiedMember).CanRead) _specifiedMember = null; + + var method = type.GetMethod ("ShouldSerialize" + _name, BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); + if (method != null && method.ReturnType == typeof (bool)) + _shouldSerialize = method; } public TypeData TypeData @@ -167,7 +172,7 @@ public void CheckOptionalValueType (Type type) { // Used when reflecting a type if (_member == null) InitMember (type); - IsOptionalValueType = (_specifiedMember != null); + IsOptionalValueType = (_specifiedMember != null || _shouldSerialize != null); } public void CheckOptionalValueType (XmlReflectionMember[] members) @@ -182,26 +187,54 @@ public void CheckOptionalValueType (XmlReflectionMember[] members) } } } - + + public bool HasSpecified { + get { return _specifiedMember != null; } + } + + public bool HasShouldSerialize { + get { return _shouldSerialize != null; } + } + public bool GetValueSpecified (object ob) { if (_specifiedGlobalIndex != -1) { object[] array = (object[])ob; return _specifiedGlobalIndex < array.Length && (bool) array [_specifiedGlobalIndex]; } - else if (_specifiedMember is PropertyInfo) - return (bool) ((PropertyInfo)_specifiedMember).GetValue (ob, null); - else - return (bool) ((FieldInfo)_specifiedMember).GetValue (ob); + bool specified = true; + + if (_specifiedMember != null) { + if (_specifiedMember is PropertyInfo) + specified = (bool)((PropertyInfo)_specifiedMember).GetValue (ob, null); + else + specified = (bool)((FieldInfo)_specifiedMember).GetValue (ob); + } + if (_shouldSerialize != null) + specified = specified && (bool)_shouldSerialize.Invoke (ob, new object [] {}); + + return specified; + } + + public bool IsValueSpecifiedSettable () { + if (_specifiedMember is PropertyInfo) + return ((PropertyInfo) _specifiedMember).CanWrite; + + if (_specifiedMember is FieldInfo) + return ((FieldInfo) _specifiedMember).IsInitOnly; + + return false; } public void SetValueSpecified (object ob, bool value) { if (_specifiedGlobalIndex != -1) ((object[])ob) [_specifiedGlobalIndex] = value; - else if (_specifiedMember is PropertyInfo) + else if (_specifiedMember is PropertyInfo) { + if (!((PropertyInfo) _specifiedMember).CanWrite) + return; ((PropertyInfo)_specifiedMember).SetValue (ob, value, null); - else + } else if (_specifiedMember is FieldInfo) ((FieldInfo)_specifiedMember).SetValue (ob, value); } From 85650c7528ad5401d4c32f916e7965b460255158 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 8 Sep 2014 23:16:08 +0800 Subject: [PATCH 130/543] Test serialization wen class has method bool ShouldSerialize(). .NET throws an exception but it should have no effect on the serialization. --- .../XmlSerializerTests.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs index 442ce4b08f5..0b0ddbe561b 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs @@ -3411,6 +3411,30 @@ public void OptionalMethods () Assert.AreEqual (expectedValueWithX, Infoset (t.ToString ())); } } + + public class ClassWithShouldSerializeGeneric + { + [XmlAttribute] + public int X { get; set; } + + public bool ShouldSerializeX () { return false; } + } + + [Test] + [Category("NotDotNet")] + public void ShouldSerializeGeneric () + { + var ser = new XmlSerializer (typeof (ClassWithShouldSerializeGeneric)); + + var expectedValueWithX = Infoset ("" + Environment.NewLine + + ""); + + using (var t = new StringWriter ()) { + var obj = new ClassWithShouldSerializeGeneric { X = 11 }; + ser.Serialize (t, obj); + Assert.AreEqual (expectedValueWithX, Infoset (t.ToString ())); + } + } } // Test generated serialization code. From be02242f8bcf47b546f54ba1ee9dd8c2c80f2e7a Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 8 Sep 2014 23:21:01 +0800 Subject: [PATCH 131/543] Ignore method ShouldSerialize if it is a generic. --- .../System.XML/System.Xml.Serialization/XmlTypeMapMember.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs index eac0984ab97..df6d3361a46 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs @@ -123,7 +123,7 @@ void InitMember (Type type) _specifiedMember = null; var method = type.GetMethod ("ShouldSerialize" + _name, BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); - if (method != null && method.ReturnType == typeof (bool)) + if (method != null && method.ReturnType == typeof (bool) && !method.IsGenericMethod) _shouldSerialize = method; } From 1afc866f8727e58f13f2f80568e0741afabadc23 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 15 Sep 2014 17:37:16 +0200 Subject: [PATCH 132/543] [xbuild] Workaround for null log service (which should never be null) --- .../Microsoft.Build.Utilities/ToolTask.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs b/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs index d2570426a3e..74dfe4ee4fb 100644 --- a/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs +++ b/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs @@ -110,7 +110,8 @@ string CreateToolPath () var path = Path.Combine (tp, ToolExe); if (!File.Exists (path)) { - Log.LogError ("Tool executable '{0}' could not be found", path); + if (Log != null) + Log.LogError ("Tool executable '{0}' could not be found", path); return null; } From 8790297c85db9c63cdf1c5816c275ccde0c417e0 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 15 Sep 2014 16:55:31 +0100 Subject: [PATCH 133/543] Test xml serialization of nullable array items. Covers #19012. --- .../XmlSerializerTestClasses.cs | 18 ++++++ .../XmlSerializerTests.cs | 60 +++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs index d486b3bcea8..b4ec87869e6 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs @@ -1160,5 +1160,23 @@ public SimpleObjectB Object get; set; } } + + public class ObjectWithNullableArrayItems + { + [XmlArrayItem ("Element", IsNullable = true)] + public List Elements; + } + + public class ObjectWithNonNullableArrayItems + { + [XmlArrayItem ("Element", IsNullable = false)] + public List Elements; + } + + public class ObjectWithNotSpecifiedNullableArrayItems + { + [XmlArrayItem ("Element")] + public List Elements; + } } diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs index 0b0ddbe561b..8f03b0c2223 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs @@ -3435,6 +3435,66 @@ public void ShouldSerializeGeneric () Assert.AreEqual (expectedValueWithX, Infoset (t.ToString ())); } } + + [Test] + public void NullableArrayItems () + { + var ser = new XmlSerializer (typeof (ObjectWithNullableArrayItems)); + + var obj = new ObjectWithNullableArrayItems (); + obj.Elements = new List (); + obj.Elements.Add (new SimpleClass { something = "Hello" }); + obj.Elements.Add (null); + obj.Elements.Add (new SimpleClass { something = "World" }); + + using (var w = new StringWriter ()) { + ser.Serialize (w, obj); + using (var r = new StringReader ( w.ToString ())) { + var desObj = (ObjectWithNullableArrayItems) ser.Deserialize (r); + Assert.IsNull (desObj.Elements [1]); + } + } + } + + [Test] + public void NonNullableArrayItems () + { + var ser = new XmlSerializer (typeof (ObjectWithNonNullableArrayItems)); + + var obj = new ObjectWithNonNullableArrayItems (); + obj.Elements = new List (); + obj.Elements.Add (new SimpleClass { something = "Hello" }); + obj.Elements.Add (null); + obj.Elements.Add (new SimpleClass { something = "World" }); + + using (var w = new StringWriter ()) { + ser.Serialize (w, obj); + using (var r = new StringReader ( w.ToString ())) { + var desObj = (ObjectWithNonNullableArrayItems) ser.Deserialize (r); + Assert.IsNotNull (desObj.Elements [1]); + } + } + } + + [Test] + public void NotSpecifiedNullableArrayItems () + { + var ser = new XmlSerializer (typeof (ObjectWithNotSpecifiedNullableArrayItems)); + + var obj = new ObjectWithNotSpecifiedNullableArrayItems (); + obj.Elements = new List (); + obj.Elements.Add (new SimpleClass { something = "Hello" }); + obj.Elements.Add (null); + obj.Elements.Add (new SimpleClass { something = "World" }); + + using (var w = new StringWriter ()) { + ser.Serialize (w, obj); + using (var r = new StringReader ( w.ToString ())) { + var desObj = (ObjectWithNotSpecifiedNullableArrayItems) ser.Deserialize (r); + Assert.IsNull (desObj.Elements [1]); + } + } + } } // Test generated serialization code. From 5fc6ecd7c7e8d6da39798b3ea5839bb4a68cfda5 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 15 Sep 2014 15:49:46 +0100 Subject: [PATCH 134/543] If not specified assume that array items are nullable. Fixes #19012. --- .../System.Xml.Serialization/XmlReflectionImporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs index 14afa1d0610..554d673251d 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs @@ -516,7 +516,7 @@ XmlTypeMapping ImportListMapping (TypeData typeData, XmlRootAttribute root, stri elem.Form = att.Form; if (att.Form == XmlSchemaForm.Unqualified) elem.Namespace = string.Empty; - elem.IsNullable = att.IsNullable && CanBeNull (elem.TypeData); + elem.IsNullable = (!att.IsNullableSpecified || att.IsNullable) && CanBeNull (elem.TypeData); elem.NestingLevel = att.NestingLevel; if (isMultiArray) { From 8b10d9bb0bb1d9e71be4226431b3d271469f21c9 Mon Sep 17 00:00:00 2001 From: Martin Baulig Date: Mon, 15 Sep 2014 17:11:21 +0200 Subject: [PATCH 135/543] [WCF]: Copy out/ref parameters on async call; bug #22129. --- .../ClientRuntimeChannel.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs index 3fa8170565c..419892a58ce 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs @@ -436,9 +436,16 @@ public IExtensionCollection Extensions { #region Request/Output processing + class OperationParameters + { + public object[] Parameters; + public object UserData; + } + public IAsyncResult BeginProcess (MethodBase method, string operationName, object [] parameters, AsyncCallback callback, object asyncState) { - return _processDelegate.BeginInvoke (method, operationName, parameters, OperationContext.Current, callback, asyncState); + var p = new OperationParameters { Parameters = parameters, UserData = asyncState }; + return _processDelegate.BeginInvoke (method, operationName, parameters, OperationContext.Current, callback, p); } public object EndProcess (MethodBase method, string operationName, object [] parameters, IAsyncResult result) @@ -447,8 +454,14 @@ public object EndProcess (MethodBase method, string operationName, object [] par throw new ArgumentNullException ("result"); if (parameters == null) throw new ArgumentNullException ("parameters"); - // FIXME: the method arguments should be verified to be - // identical to the arguments in the corresponding begin method. + + var p = (OperationParameters)result.AsyncState; + if (p.Parameters.Length != parameters.Length) + throw new ArgumentException ("Parameter array has invalid length.", "parameters"); + + for (int i = 0; i < parameters.Length; i++) + parameters [i] = p.Parameters [i]; + return _processDelegate.EndInvoke (result); } From 2320d0dc409cfa14865ffb2c5ed9ef2bc624f3cd Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 15 Sep 2014 18:33:15 +0200 Subject: [PATCH 136/543] [mcs] Revert usage of closed delegates for compiler generated anonymous method --- mcs/mcs/anonymous.cs | 6 +- mcs/tests/test-anon-172.cs | 30 + mcs/tests/ver-il-net_4_5.xml | 1542 +++++++++++++++++----------------- 3 files changed, 815 insertions(+), 763 deletions(-) create mode 100644 mcs/tests/test-anon-172.cs diff --git a/mcs/mcs/anonymous.cs b/mcs/mcs/anonymous.cs index a0cf7d9eb9a..847cbcfd5d8 100644 --- a/mcs/mcs/anonymous.cs +++ b/mcs/mcs/anonymous.cs @@ -1792,8 +1792,10 @@ AnonymousMethodMethod DoCreateMethodHost (EmitContext ec) // this argument is generated during compilation which speeds up dispatch // by about 25% // - method_parameters = ParametersCompiled.Prefix (method_parameters, - new Parameter (null, null, 0, null, loc), ec.Module.Compiler.BuiltinTypes.Object); + // Unused as it breaks compatibility + // + // method_parameters = ParametersCompiled.Prefix (method_parameters, + // new Parameter (null, null, 0, null, loc), ec.Module.Compiler.BuiltinTypes.Object); } if (storey == null && hoisted_tparams == null) diff --git a/mcs/tests/test-anon-172.cs b/mcs/tests/test-anon-172.cs new file mode 100644 index 00000000000..c316a1ba240 --- /dev/null +++ b/mcs/tests/test-anon-172.cs @@ -0,0 +1,30 @@ +using System; +using System.Reflection.Emit; +using System.Reflection; + +class MainClass +{ + public static int Main () + { + var dynMethod = new DynamicMethod ("Metoda", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, + null, Type.EmptyTypes, typeof (MainClass), true); + var generator = dynMethod.GetILGenerator (); + + generator.Emit (OpCodes.Ldc_I4_7); + GenerateCodeCall (generator, (int a) => { + Console.WriteLine (a); + }); + + generator.Emit (OpCodes.Ret); + + var deleg = (Action)dynMethod.CreateDelegate (typeof (Action)); + deleg (); + return 0; + } + + static void GenerateCodeCall (ILGenerator generator, Action a) + { + generator.Emit (OpCodes.Call, a.Method); + } +} + diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index de7c52cde3b..224e5111e27 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -475,255 +475,255 @@ - + 14 - + 14 - + 14 - + 14 - + 73 - + 68 - + 73 - + 73 - + 73 - + 73 - + 74 - + 74 - + 73 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 74 - + 58 - + 58 - + 58 - + 58 - + 67 - + 93 - + 112 - + 75 - + 102 - + 74 - + 128 - + 92 - + 94 - + 93 - + 111 - + 112 - + 111 - + 91 - + 112 - + 125 - + 140 - + 102 - + 69 - + 77 - + 55 - + 55 - + 55 - + 55 - + 55 - + 59 - + 55 - + 59 - + 60 - + 69 - + 60 - + 69 - + 60 - + 68 - + 60 - + 60 - + 69 - + 60 - + 74 - + 20 - + 15 - + 15 - + 12 @@ -1369,19 +1369,19 @@ 69 - + 12 - + 20 - + 15 - + 15 - + 12 @@ -1591,31 +1591,31 @@ - + 9 - + 112 - + 2 - + 9 - + 10 - + 20 - + 15 - + 15 - + 12 @@ -1901,7 +1901,7 @@ - + 10 @@ -2085,7 +2085,7 @@ - + 9 @@ -2656,13 +2656,13 @@ - + 11 - + 11 - + 14 @@ -2691,7 +2691,7 @@ - + 12 @@ -2879,14 +2879,6 @@ 0 - - - 103 - - - 105 - - 118 @@ -2895,6 +2887,14 @@ 7 + + + 103 + + + 105 + + @@ -2980,7 +2980,7 @@ 7 - + 14 @@ -3143,25 +3143,25 @@ - + 86 - + 92 - + 106 - + 20 - + 15 - + 15 - + 12 @@ -5065,7 +5065,7 @@ - + 25 @@ -6536,7 +6536,7 @@ - + 21 @@ -6708,7 +6708,7 @@ - + 25 @@ -7627,10 +7627,10 @@ - + 10 - + 10 @@ -7755,7 +7755,7 @@ 16 - + 22 @@ -8407,7 +8407,7 @@ 7 - + 20 @@ -11221,7 +11221,7 @@ - + 10 @@ -11677,7 +11677,7 @@ - + 8 @@ -13394,10 +13394,10 @@ - + 2 - + 2 @@ -14063,7 +14063,7 @@ - + 10 @@ -14326,7 +14326,7 @@ - + 9 @@ -14460,13 +14460,13 @@ - - 10 - 44 - + + 10 + + 2 @@ -14504,13 +14504,13 @@ 7 - + 14 - + 14 - + 18 @@ -18683,7 +18683,7 @@ - + 15 @@ -19959,10 +19959,10 @@ - + 21 - + 15 @@ -20305,10 +20305,10 @@ 69 - + 13 - + 13 @@ -21517,34 +21517,34 @@ 185 - + 2 - + 2 - + 2 - + 2 - + 2 - + 25 - + 20 - + 15 - + 15 - + 12 @@ -22087,7 +22087,7 @@ - + 9 @@ -23046,7 +23046,7 @@ 2 - + 15 @@ -23806,7 +23806,7 @@ 68 - + 2 @@ -24125,7 +24125,7 @@ - + 37 @@ -25362,7 +25362,7 @@ 14 - + 2 @@ -25749,7 +25749,7 @@ - + 22 @@ -25804,13 +25804,13 @@ - + 12 - + 11 - + 9 @@ -25863,7 +25863,7 @@ - + 19 @@ -25897,7 +25897,7 @@ - + 14 @@ -25931,10 +25931,10 @@ - + 14 - + 15 @@ -26028,10 +26028,10 @@ - + 38 - + 38 @@ -26139,7 +26139,7 @@ - + 31 @@ -26198,22 +26198,22 @@ - + 2 - + 2 - + 2 - + 2 - + 2 - + 2 @@ -26229,25 +26229,25 @@ 7 - + 12 - + 12 - + 11 - + 12 - + 11 - + 13 - + 12 @@ -26303,13 +26303,13 @@ - + 13 - + 14 - + 13 @@ -26473,18 +26473,18 @@ - + 6 - + 14 - + 9 - + 7 @@ -26500,7 +26500,7 @@ 7 - + 9 @@ -26531,7 +26531,7 @@ - + 14 @@ -26657,7 +26657,7 @@ - + 7 @@ -26679,13 +26679,13 @@ 7 - + 14 - + 9 - + 7 @@ -26733,18 +26733,18 @@ - + 15 - + 10 - + 56 - + 14 @@ -26760,7 +26760,7 @@ 7 - + 20 @@ -26795,7 +26795,7 @@ 7 - + 13 @@ -26817,7 +26817,7 @@ - + 13 @@ -26833,7 +26833,7 @@ 7 - + 2 @@ -26852,10 +26852,10 @@ 7 - + 14 - + 14 @@ -26876,7 +26876,7 @@ 7 - + 9 @@ -26903,13 +26903,13 @@ 7 - + 2 - + 2 - + 2 @@ -26935,7 +26935,7 @@ - + 33 @@ -26961,7 +26961,7 @@ 7 - + 13 @@ -27023,17 +27023,17 @@ 161 - - 9 + + 7 - + 9 - + 9 - - 7 + + 9 @@ -27199,183 +27199,183 @@ - + 10 - + 10 - + 10 - + 10 - + 10 - + 18 - + 10 - + 10 - + 10 - + 10 - + 10 - + 10 - + 10 - + 10 - + 15 - + 10 - + 10 - + 15 - + 10 - + 10 - + 15 - + 16 - + 15 - + 15 - + 15 - + 10 - + 10 - + 10 - + 10 - + 10 - + 10 - + 10 - + 10 - + 10 - + 10 - + 10 - + 18 - + 15 - + 18 - + 23 - + 20 - + 10 - + 10 - + 16 - + 10 - + 15 - + 16 - + 10 - + 15 - + 16 - + 10 - + 15 - + 10 - + 10 - + 10 - + 10 - + 17 - + 10 - + 10 @@ -27388,16 +27388,16 @@ 7 - + 10 - + 11 - + 10 - + 11 @@ -27410,13 +27410,13 @@ 7 - + 13 - + 13 - + 12 @@ -27429,16 +27429,16 @@ 7 - + 12 - + 10 - + 12 - + 10 @@ -27473,55 +27473,55 @@ - + 10 - + 10 - + 10 - + 12 - + 10 - + 15 - + 15 - + 15 - + 15 - + 15 - + 19 - + 15 - + 15 - + 19 - + 15 - + 15 - + 10 @@ -27576,22 +27576,22 @@ - + 18 - + 15 - + 18 - + 23 - + 26 - + 15 @@ -27686,25 +27686,25 @@ - + 16 - + 13 - + 16 - + 16 - + 15 - + 33 - + 16 @@ -27730,10 +27730,10 @@ 7 - + 10 - + 25 @@ -27790,52 +27790,52 @@ - + 15 - + 15 - + 31 - + 15 - + 15 - + 16 - + 30 - + 41 - + 15 - + 15 - + 31 - + 15 - + 15 - + 16 - + 20 - + 15 @@ -27900,43 +27900,43 @@ - + 15 - + 15 - + 16 - + 20 - + 47 - + 15 - + 15 - + 16 - + 20 - + 47 - + 15 - + 15 - + 10 @@ -27949,19 +27949,19 @@ 7 - + 13 - + 13 - + 12 - + 13 - + 12 @@ -28039,37 +28039,37 @@ - + 20 - + 117 - + 18 - + 44 - + 21 - + 118 - + 16 - + 14 - + 14 - + 17 - + 15 @@ -28113,7 +28113,7 @@ - + 10 @@ -28209,10 +28209,10 @@ - + 14 - + 13 @@ -28279,17 +28279,17 @@ - + 33 - + 16 - + 16 @@ -28302,7 +28302,7 @@ 7 - + 10 @@ -28493,58 +28493,58 @@ - + 50 - + 19 - + 39 - + 39 - + 39 - + 39 - + 39 - + 18 - + 23 - + 39 - + 23 - + 20 - + 39 - + 39 - + 10 - + 39 - + 39 - + 10 @@ -28560,7 +28560,7 @@ 28 - + 10 @@ -28632,16 +28632,16 @@ - + 15 - + 16 - + 15 - + 24 @@ -28745,13 +28745,13 @@ 362 - + 15 - + 15 - + 15 @@ -28775,7 +28775,7 @@ 7 - + 14 @@ -28849,19 +28849,19 @@ - + 162 - + 15 - + 16 - + 75 - + 26 @@ -28892,10 +28892,10 @@ 7 - + 15 - + 14 @@ -28950,15 +28950,15 @@ - + 9 - + 55 - + 15 @@ -28993,13 +28993,13 @@ - + 54 - + 15 - + 10 @@ -29028,7 +29028,7 @@ - + 9 @@ -29444,7 +29444,7 @@ 7 - + 14 @@ -29520,10 +29520,10 @@ 7 - + 14 - + 14 @@ -29649,10 +29649,10 @@ - + 17 - + 24 @@ -29674,7 +29674,7 @@ 2 - + 11 @@ -29763,7 +29763,7 @@ 7 - + 9 @@ -30235,7 +30235,7 @@ - + 2 @@ -30365,7 +30365,7 @@ - + 7 @@ -30561,7 +30561,7 @@ - + 14 @@ -36259,10 +36259,10 @@ - + 11 - + 10 @@ -37582,7 +37582,7 @@ - + 14 @@ -41167,7 +41167,7 @@ - + 2 @@ -41195,7 +41195,7 @@ - + 5 @@ -41657,7 +41657,7 @@ - + 10 @@ -42330,7 +42330,7 @@ - + 36 @@ -42501,7 +42501,7 @@ - + 2 @@ -43360,7 +43360,7 @@ - + 10 @@ -45551,7 +45551,7 @@ - + 10 @@ -48149,7 +48149,7 @@ - + 2 @@ -48396,7 +48396,7 @@ 7 - + 7 @@ -49543,7 +49543,7 @@ 7 - + 2 @@ -51223,7 +51223,7 @@ 18 - + 27 @@ -51727,7 +51727,7 @@ - + 12 @@ -51790,16 +51790,16 @@ - + 2 - + 2 - + 2 - + 2 @@ -51968,7 +51968,7 @@ - + 15 @@ -51987,7 +51987,7 @@ 7 - + 10 @@ -52092,7 +52092,7 @@ - + 2 @@ -52128,10 +52128,10 @@ - + 10 - + 10 @@ -52173,16 +52173,16 @@ - + 10 - + 24 - + 14 - + 14 @@ -52211,7 +52211,7 @@ - + 114 @@ -52245,7 +52245,7 @@ - + 20 @@ -52271,7 +52271,7 @@ - + 6 @@ -52375,7 +52375,7 @@ - + 10 @@ -52457,19 +52457,19 @@ - + 17 - + 17 - + 62 - + 54 - + 35 @@ -52734,10 +52734,10 @@ 7 - + 20 - + 20 @@ -53006,7 +53006,7 @@ 7 - + 2 @@ -53063,7 +53063,7 @@ - + 24 @@ -53147,17 +53147,17 @@ - + 17 - + 9 - + 17 @@ -53435,10 +53435,10 @@ 45 - + 15 - + 15 @@ -53470,7 +53470,7 @@ - + 12 @@ -53486,7 +53486,7 @@ 7 - + 18 @@ -53510,7 +53510,7 @@ 7 - + 2 @@ -53536,7 +53536,7 @@ - + 32 @@ -53587,11 +53587,6 @@ 7 - - - 24 - - 52 @@ -53608,6 +53603,11 @@ 7 + + + 24 + + @@ -53737,7 +53737,7 @@ - + 21 @@ -53902,7 +53902,7 @@ - + 17 @@ -53977,7 +53977,7 @@ - + 9 @@ -54064,7 +54064,7 @@ - + 8 @@ -54141,7 +54141,7 @@ - + 7 @@ -54218,7 +54218,7 @@ - + 7 @@ -54246,7 +54246,7 @@ - + 9 @@ -54463,7 +54463,7 @@ - + 77 @@ -54489,7 +54489,7 @@ - + 39 @@ -54508,7 +54508,7 @@ 7 - + 89 @@ -54549,13 +54549,13 @@ - + 51 - + 46 - + 42 @@ -54626,7 +54626,7 @@ - + 18 @@ -54751,6 +54751,22 @@ + + + + 133 + + + 19 + + + 8 + + + 7 + + + @@ -55115,7 +55131,7 @@ - + 12 @@ -55242,10 +55258,10 @@ - + 8 - + 8 @@ -55325,7 +55341,7 @@ - + 26 @@ -55570,7 +55586,7 @@ - + 2 @@ -55602,7 +55618,7 @@ - + 12 @@ -55901,10 +55917,10 @@ - + 45 - + 9 @@ -56081,7 +56097,7 @@ - + 8 @@ -56353,7 +56369,7 @@ - + 12 @@ -56586,7 +56602,7 @@ - + 12 @@ -56981,7 +56997,7 @@ - + 2 @@ -57158,10 +57174,10 @@ - + 2 - + 9 @@ -57267,7 +57283,7 @@ - + 17 @@ -57383,10 +57399,10 @@ - + 16 - + 32 @@ -57419,7 +57435,7 @@ - + 42 @@ -57477,7 +57493,7 @@ - + 10 @@ -57611,7 +57627,7 @@ - + 19 @@ -57690,7 +57706,7 @@ 18 - + 2 @@ -57900,21 +57916,21 @@ - + 28 - + 2 - + 32 - + 29 - + 10 @@ -57936,7 +57952,7 @@ 42 - + 2 @@ -57970,7 +57986,7 @@ - + 12 @@ -58159,7 +58175,7 @@ - + 4 @@ -58407,7 +58423,7 @@ - + 13 @@ -58718,7 +58734,7 @@ - + 63 @@ -58750,7 +58766,7 @@ - + 62 @@ -59042,7 +59058,7 @@ - + 41 @@ -59129,7 +59145,7 @@ - + 41 @@ -59193,29 +59209,29 @@ - + 33 - + 33 - + 33 - + 33 - + 9 - + 9 - + 9 @@ -59234,9 +59250,6 @@ 7 - - 33 - @@ -59246,6 +59259,11 @@ 13 + + + 33 + + @@ -59359,49 +59377,49 @@ - + 21 - + 13 - + 13 - + 9 - + 9 - + 17 - + 9 - + 9 - + 9 - + 9 - + 9 @@ -59528,27 +59546,27 @@ - + 9 - + 9 - + 9 - + 9 - + 9 @@ -59575,13 +59593,13 @@ 13 - + 17 - + 10 - + 9 @@ -60550,485 +60568,485 @@ - + 45 - + 15 - + 15 - + 12 - + 9 - + 9 - + 9 - + 9 - + 9 - + 17 - + 9 - + 9 - + 19 - + 9 - + 19 - + 9 - + 13 - + 9 - + 10 - + 9 - + 9 - + 10 - + 9 - + 9 - + 10 - + 9 - + 10 - + 9 - + 25 - + 9 - + 9 - + 9 - + 9 - + 17 - + 9 - + 9 - + 17 - + 10 - + 10 - + 14 - + 17 - + 17 - + 14 - + 17 - + 14 - + 14 - + 17 - + 20 - + 17 - + 17 - + 10 - + 9 - + 17 - + 10 - + 9 - + 15 - + 9 - + 13 - + 17 - + 9 - + 9 - + 9 - + 9 - + 9 - + 9 - + 9 - + 11 - + 9 - + 9 - + 9 - + 9 - + 9 - + 9 - + 9 - + 10 - + 10 - + 10 - + 9 - + 10 - + 13 - + 14 - + 13 - + 13 - + 13 - + 13 - + 13 - + 10 - + 10 - + 13 - + 2 - + 9 - + 10 - + 10 - + 10 - + 10 - + 10 - + 10 - + 13 - + 13 - + 10 - + 10 - + 9 - + 9 - + 9 - + 9 - + 9 - + 9 - + 25 - + 9 - + 9 - + 9 - + 10 - + 9 - + 9 - + 13 - + 13 - + 9 - + 9 - + 9 - + 9 - + 9 @@ -61066,17 +61084,17 @@ - + 33 - + 9 - + 9 @@ -61137,12 +61155,12 @@ - + 10 - + 9 @@ -61207,40 +61225,40 @@ - + 20 - + 15 - + 15 - + 12 - + 13 - + 13 - + 13 - + 13 - + 13 - + 36 @@ -61361,56 +61379,56 @@ - + 20 - + 15 - + 15 - + 12 - + 7 - + 7 - + 33 - + 9 - + 7 - + 7 - + 7 - + 7 @@ -61600,36 +61618,36 @@ - + 20 - + 15 - + 15 - + 12 - + 9 - + 9 - + 13 - + 13 @@ -61918,13 +61936,13 @@ - + 2 - + 2 - + 2 @@ -61969,7 +61987,7 @@ 13 - + 21 @@ -61998,7 +62016,7 @@ 13 - + 10 @@ -62024,7 +62042,7 @@ - + 9 @@ -62053,10 +62071,10 @@ - + 47 - + 9 @@ -62080,7 +62098,7 @@ 13 - + 10 @@ -62104,7 +62122,7 @@ 13 - + 10 @@ -62525,21 +62543,21 @@ - + 33 - + 24 - + 24 - + 24 - + 27 @@ -62587,7 +62605,7 @@ 13 - + 7 @@ -62638,7 +62656,7 @@ 13 - + 2 @@ -62672,12 +62690,12 @@ - + 35 - + 2 @@ -62711,16 +62729,6 @@ 13 - - - 9 - - - - - 33 - - 162 @@ -62729,6 +62737,16 @@ 13 + + + 9 + + + + + 33 + + @@ -63158,7 +63176,7 @@ 13 - + 2 @@ -63215,7 +63233,7 @@ - + 33 @@ -63601,7 +63619,7 @@ - + 9 @@ -63627,7 +63645,7 @@ - + 33 @@ -63695,7 +63713,7 @@ 13 - + 9 @@ -65004,13 +65022,13 @@ - + 6 - + 7 - + 7 @@ -65099,7 +65117,7 @@ - + 10 @@ -65159,15 +65177,15 @@ - + 2 - + 9 - + 9 @@ -65319,7 +65337,7 @@ 7 - + 13 @@ -65627,9 +65645,6 @@ 21 - - 13 - 29 @@ -65642,6 +65657,11 @@ 7 + + + 13 + + @@ -67635,12 +67655,12 @@ 88 - - 10 - 42 + + 10 + @@ -68258,7 +68278,7 @@ - + 7 @@ -68919,7 +68939,7 @@ 7 - + 14 From 1531798bbe3124306216ff292299db6ed88f2918 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 15 Sep 2014 18:58:52 +0100 Subject: [PATCH 137/543] Added missing files to projects csproj files. --- mcs/class/System/System-bare-net_4_5.csproj | 1 + mcs/class/System/System-net_4_5.csproj | 1 + mcs/class/System/System-secxml-net_4_5.csproj | 1 + mcs/class/corlib/corlib-net_4_5.csproj | 2 ++ 4 files changed, 5 insertions(+) diff --git a/mcs/class/System/System-bare-net_4_5.csproj b/mcs/class/System/System-bare-net_4_5.csproj index 26714d1f7bb..8790db08575 100644 --- a/mcs/class/System/System-bare-net_4_5.csproj +++ b/mcs/class/System/System-bare-net_4_5.csproj @@ -1124,6 +1124,7 @@ + diff --git a/mcs/class/System/System-net_4_5.csproj b/mcs/class/System/System-net_4_5.csproj index 8367ee9e16b..d8abc97e11a 100644 --- a/mcs/class/System/System-net_4_5.csproj +++ b/mcs/class/System/System-net_4_5.csproj @@ -1124,6 +1124,7 @@ + diff --git a/mcs/class/System/System-secxml-net_4_5.csproj b/mcs/class/System/System-secxml-net_4_5.csproj index 2e69308ad30..b13fc18c245 100644 --- a/mcs/class/System/System-secxml-net_4_5.csproj +++ b/mcs/class/System/System-secxml-net_4_5.csproj @@ -1124,6 +1124,7 @@ + diff --git a/mcs/class/corlib/corlib-net_4_5.csproj b/mcs/class/corlib/corlib-net_4_5.csproj index 43e03fbfa33..d80870fca6f 100644 --- a/mcs/class/corlib/corlib-net_4_5.csproj +++ b/mcs/class/corlib/corlib-net_4_5.csproj @@ -1399,6 +1399,8 @@ + + From 64f6eb2d1dcf6999e9ad3813c469bdf6fc85ca17 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 15 Sep 2014 15:31:25 -0400 Subject: [PATCH 138/543] [aot] Use gsharedvt for collection types instantiated with generic structs as well. --- mono/mini/aot-compiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 299b6c2cc63..5311224cc3e 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -3860,7 +3860,7 @@ is_vt_inst (MonoGenericInst *inst) for (i = 0; i < inst->type_argc; ++i) { MonoType *t = inst->type_argv [i]; - if (t->type == MONO_TYPE_VALUETYPE) + if (MONO_TYPE_ISSTRUCT (t) || t->type == MONO_TYPE_VALUETYPE) return TRUE; } return FALSE; From 240cf239a2fc6edfd9edcc7a1ac11b62b11471a5 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 15 Sep 2014 22:23:30 +0200 Subject: [PATCH 139/543] [xbuild] More tweaks to tool path setup --- .../Microsoft.Build.Utilities/ToolTask.cs | 9 ++++++--- .../Test/Microsoft.Build.Utilities/ToolTaskTest.cs | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs b/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs index 74dfe4ee4fb..572c75c1bfa 100644 --- a/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs +++ b/mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs @@ -100,10 +100,13 @@ string CreateToolPath () if (string.IsNullOrEmpty (tp)) return null; - tp = Path.GetDirectoryName (tp); - if (string.IsNullOrEmpty (tp)) - tp = Directory.GetCurrentDirectory (); + // + // GenerateFullPathToTool can return path including tool name + // + if (string.IsNullOrEmpty (ToolExe)) + return tp; + tp = Path.GetDirectoryName (tp); } else { tp = ToolPath; } diff --git a/mcs/class/Microsoft.Build.Utilities/Test/Microsoft.Build.Utilities/ToolTaskTest.cs b/mcs/class/Microsoft.Build.Utilities/Test/Microsoft.Build.Utilities/ToolTaskTest.cs index bfd7c038eae..7c2a3843b62 100644 --- a/mcs/class/Microsoft.Build.Utilities/Test/Microsoft.Build.Utilities/ToolTaskTest.cs +++ b/mcs/class/Microsoft.Build.Utilities/Test/Microsoft.Build.Utilities/ToolTaskTest.cs @@ -462,16 +462,16 @@ public void Execute_3 () var t = new TestExecuteToolTask (); t.FullPathToTool = "fpt"; t.BuildEngine = new MockBuildEngine (); - t.ToolExe = "Makefile"; + t.ToolExe = "Makefile.mk"; t.OnExecuteTool = (pathToTool, responseFileCommands, commandLineCommands) => { - Assert.AreEqual (Path.Combine (Directory.GetCurrentDirectory (), "Makefile"), pathToTool, "#1"); + Assert.AreEqual ("Makefile.mk", pathToTool, "#1"); Assert.AreEqual ("", responseFileCommands, "#2"); Assert.AreEqual ("", commandLineCommands, "#3"); }; - Assert.IsTrue (t.Execute (), "result"); + Assert.IsFalse (t.Execute (), "result"); } } From fad438976c9a21ebbf4d71ae19ccb071d6cc10a4 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 15 Sep 2014 17:34:54 -0400 Subject: [PATCH 140/543] [runtime] Fix an assert in w32_dlerror () on winx64. --- mono/utils/mono-dl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/utils/mono-dl.c b/mono/utils/mono-dl.c index b59ab2d5aae..04e9165b7c0 100644 --- a/mono/utils/mono-dl.c +++ b/mono/utils/mono-dl.c @@ -124,7 +124,7 @@ w32_dlerror (void) wchar_t* buf = NULL; DWORD code = GetLastError (); - if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, + if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL)) { ret = g_utf16_to_utf8 (buf, wcslen(buf), NULL, NULL, NULL); From ae030203e760b3fb5745d1feda18adce0e7ec08b Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 15 Sep 2014 18:09:43 -0400 Subject: [PATCH 141/543] [arm64] Increase some opcode sizes. Fixes #23026. --- mono/mini/cpu-arm64.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mono/mini/cpu-arm64.md b/mono/mini/cpu-arm64.md index 7d9e40b2266..f45b72123aa 100644 --- a/mono/mini/cpu-arm64.md +++ b/mono/mini/cpu-arm64.md @@ -321,9 +321,9 @@ icompare_imm: src1:i len:12 long_conv_to_ovf_i4_2: dest:i src1:i src2:i len:36 -vcall2: len:32 clob:c -vcall2_reg: src1:i len:32 clob:c -vcall2_membase: src1:b len:32 clob:c +vcall2: len:40 clob:c +vcall2_reg: src1:i len:40 clob:c +vcall2_membase: src1:b len:40 clob:c dyn_call: src1:i src2:i len:120 clob:c # This is different from the original JIT opcodes From 02f48039b160782ec74f57ad992d28277e958f41 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 15 Sep 2014 19:14:09 -0400 Subject: [PATCH 142/543] [runtime] Add support for setting the thread name on windows. On windows, this will only work when running under a debugger. --- mono/metadata/appdomain.c | 4 ++++ mono/utils/mono-threads-windows.c | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) mode change 100644 => 100755 mono/utils/mono-threads-windows.c diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index 45b9a606ab6..c46bdfa2db4 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -2415,6 +2415,7 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc) unload_data *thread_data; MonoNativeThreadId tid; MonoDomain *caller_domain = mono_domain_get (); + char *name; /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, GetCurrentThreadId ()); */ @@ -2466,7 +2467,10 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc) thread_handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)unload_thread_main, thread_data, 0, CREATE_SUSPENDED, &tid); if (thread_handle == NULL) return; + name = g_strdup_printf ("Unload thread for domain %x", domain); + mono_thread_info_set_name (tid, name); mono_thread_info_resume (tid); + g_free (name); /* Wait for the thread */ while (!thread_data->done && WaitForSingleObjectEx (thread_handle, INFINITE, TRUE) == WAIT_IO_COMPLETION) { diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c old mode 100644 new mode 100755 index 2ab2e6596e5..d0d81c5b8f4 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -263,9 +263,36 @@ mono_threads_core_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) return OpenThread (THREAD_ALL_ACCESS, TRUE, tid); } +#if !defined(__GNUC__) +const DWORD MS_VC_EXCEPTION=0x406D1388; +#pragma pack(push,8) +typedef struct tagTHREADNAME_INFO +{ + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. +} THREADNAME_INFO; +#pragma pack(pop) +#endif + void mono_threads_core_set_name (MonoNativeThreadId tid, const char *name) { +#if !defined(__GNUC__) + /* http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx */ + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name; + info.dwThreadID = tid; + info.dwFlags = 0; + + __try { + RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); + } + __except(EXCEPTION_EXECUTE_HANDLER) { + } +#endif } #endif From 557390ee4600ed375a3f303d33ded29e0b3e5c6f Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 15 Sep 2014 22:10:23 -0400 Subject: [PATCH 143/543] [runtime] Fix the my_g_bit_nth_msf () function for win64. --- mono/metadata/decimal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mono/metadata/decimal.c b/mono/metadata/decimal.c index 39d226d3b25..3bbd0058032 100644 --- a/mono/metadata/decimal.c +++ b/mono/metadata/decimal.c @@ -577,7 +577,7 @@ my_g_bit_nth_msf (gsize mask) if (_BitScanReverse (&bIndex, mask)) return bIndex; return -1; -#elif defined(__x86_64__) && defined(_MSC_VER) +#elif defined(_M_X64) && defined(_MSC_VER) unsigned long bIndex = 0; if (_BitScanReverse64 (&bIndex, mask)) return bIndex; @@ -597,7 +597,7 @@ my_g_bit_nth_msf (gsize mask) i = sizeof (gsize) * 8; while (i > 0) { i --; - if (mask & (1UL << i)) + if (mask & (1ULL << i)) return i; } return -1; From 80b14d356ffd8fc8a46d74eb7b6428082519f59c Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 15 Sep 2014 23:30:40 -0400 Subject: [PATCH 144/543] [runtime] Disable VS warnings C4273 (inconsistent dll linkage), and C4005 (macro redefinition). The former occurs becase we mark exported function declarations using MONO_API, but not the definitions. The latter occurs because we define _WINSOCKAPI_. --- msvc/mono.props | 1 + 1 file changed, 1 insertion(+) diff --git a/msvc/mono.props b/msvc/mono.props index ef26f9180d7..46b4dde2c8f 100644 --- a/msvc/mono.props +++ b/msvc/mono.props @@ -10,6 +10,7 @@ __default_codegen__;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;GC_NOT_DLL;WIN32_THREADS;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;_UNICODE;UNICODE;WIN32_THREADS;FD_SETSIZE=1024;$(PreprocessorDefinitions);_WINSOCKAPI_ + 4273;4005 Mswsock.lib;ws2_32.lib;ole32.lib;oleaut32.lib;psapi.lib;version.lib;advapi32.lib;winmm.lib;kernel32.lib;$(AdditionalDependencies) From 9aed010782d9ea3ad18021bafcfedc89d27a1faf Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Tue, 16 Sep 2014 19:19:04 +0200 Subject: [PATCH 145/543] [mcs] struct parameterless instance constructors --- mcs/errors/cs0111-12.cs | 15 +++++ mcs/errors/cs0516-3.cs | 9 +++ mcs/errors/cs0516.cs | 10 ++-- mcs/errors/cs0568.cs | 14 ----- mcs/errors/cs0619-58.cs | 20 +++++++ mcs/errors/cs1644-45.cs | 10 ++++ mcs/errors/cs1644-46.cs | 8 +++ mcs/errors/cs8054-2.cs | 6 -- mcs/errors/cs8054-3.cs | 6 -- mcs/errors/cs8054.cs | 7 --- mcs/errors/cs8075.cs | 9 +++ mcs/mcs/class.cs | 39 +++++++------ mcs/mcs/cs-parser.jay | 14 +++++ mcs/mcs/ecore.cs | 11 ++++ mcs/mcs/expression.cs | 6 -- mcs/mcs/method.cs | 21 ------- mcs/tests/gtest-autoproperty-10.cs | 16 ++++++ mcs/tests/gtest-etree-01.cs | 19 +++++++ mcs/tests/test-906.cs | 75 +++++++++++++++++++++++++ mcs/tests/test-primary-ctor-07.cs | 24 ++++++++ mcs/tests/ver-il-net_4_5.xml | 89 +++++++++++++++++++++++++++++- 21 files changed, 342 insertions(+), 86 deletions(-) create mode 100644 mcs/errors/cs0111-12.cs create mode 100644 mcs/errors/cs0516-3.cs delete mode 100644 mcs/errors/cs0568.cs create mode 100644 mcs/errors/cs0619-58.cs create mode 100644 mcs/errors/cs1644-45.cs create mode 100644 mcs/errors/cs1644-46.cs delete mode 100644 mcs/errors/cs8054-2.cs delete mode 100644 mcs/errors/cs8054-3.cs delete mode 100644 mcs/errors/cs8054.cs create mode 100644 mcs/errors/cs8075.cs create mode 100644 mcs/tests/gtest-autoproperty-10.cs create mode 100644 mcs/tests/test-906.cs diff --git a/mcs/errors/cs0111-12.cs b/mcs/errors/cs0111-12.cs new file mode 100644 index 00000000000..034963c22a0 --- /dev/null +++ b/mcs/errors/cs0111-12.cs @@ -0,0 +1,15 @@ +// CS0111: A member `S3.S3(string)' is already defined. Rename this member or use different parameter types +// Line: 6 + +struct S3 (string s) +{ + public S3 (string s) + : this (1) + { + } + + public S3 (int i) + : this ("") + { + } +} diff --git a/mcs/errors/cs0516-3.cs b/mcs/errors/cs0516-3.cs new file mode 100644 index 00000000000..1ff6d062893 --- /dev/null +++ b/mcs/errors/cs0516-3.cs @@ -0,0 +1,9 @@ +// CS0516: Constructor `Sample.Sample()' cannot call itself +// Line: 6 + +struct Sample { + public Sample () + : this () + { + } +} diff --git a/mcs/errors/cs0516.cs b/mcs/errors/cs0516.cs index 47b0fdee730..5c41f8dc4e7 100644 --- a/mcs/errors/cs0516.cs +++ b/mcs/errors/cs0516.cs @@ -1,9 +1,9 @@ // CS0516: Constructor `Sample.Sample()' cannot call itself -// Line: 5 +// Line: 6 class Sample { - public Sample (): this () {} + public Sample () + : this () + { + } } - - - diff --git a/mcs/errors/cs0568.cs b/mcs/errors/cs0568.cs deleted file mode 100644 index 944d7a90b79..00000000000 --- a/mcs/errors/cs0568.cs +++ /dev/null @@ -1,14 +0,0 @@ -// CS0568: Structs cannot contain explicit parameterless constructors -// Line: 5 -struct A { - int a; - A () { a = 1; } -} - -class D { - static void Main () - { - A [] a = new A [10]; - - } -} diff --git a/mcs/errors/cs0619-58.cs b/mcs/errors/cs0619-58.cs new file mode 100644 index 00000000000..faf79c7dab8 --- /dev/null +++ b/mcs/errors/cs0619-58.cs @@ -0,0 +1,20 @@ +// CS0619: `S.S()' is obsolete: `ctor' +// Line: 18 + +using System; + +struct S +{ + [Obsolete ("ctor", true)] + public S () + { + } +} + +class C +{ + public static void Main () + { + new S (); + } +} diff --git a/mcs/errors/cs1644-45.cs b/mcs/errors/cs1644-45.cs new file mode 100644 index 00000000000..3aa2033141d --- /dev/null +++ b/mcs/errors/cs1644-45.cs @@ -0,0 +1,10 @@ +// CS1644: Feature `struct parameterless instance constructor' cannot be used because it is not part of the C# 5.0 language specification +// Line: 12 +// Compiler options: -langversion:5 + +struct S +{ + public S () + { + } +} \ No newline at end of file diff --git a/mcs/errors/cs1644-46.cs b/mcs/errors/cs1644-46.cs new file mode 100644 index 00000000000..a62e6d1f2d3 --- /dev/null +++ b/mcs/errors/cs1644-46.cs @@ -0,0 +1,8 @@ +// CS1644: Feature `struct instance member initializer' cannot be used because it is not part of the C# 5.0 language specification +// Line: 12 +// Compiler options: -langversion:5 + +struct S +{ + int i = 0; +} \ No newline at end of file diff --git a/mcs/errors/cs8054-2.cs b/mcs/errors/cs8054-2.cs deleted file mode 100644 index e633f176068..00000000000 --- a/mcs/errors/cs8054-2.cs +++ /dev/null @@ -1,6 +0,0 @@ -// CS0573: `A.a': Structs without explicit constructors cannot contain members with initializers -// Line: 5 - -partial struct A { - int a = 1; -} diff --git a/mcs/errors/cs8054-3.cs b/mcs/errors/cs8054-3.cs deleted file mode 100644 index b06047fb6ee..00000000000 --- a/mcs/errors/cs8054-3.cs +++ /dev/null @@ -1,6 +0,0 @@ -// CS0573: `A.a': Structs without explicit constructors cannot contain members with initializers -// Line: 5 - -struct A { - int a = 1; -} diff --git a/mcs/errors/cs8054.cs b/mcs/errors/cs8054.cs deleted file mode 100644 index 4b8fc2ed446..00000000000 --- a/mcs/errors/cs8054.cs +++ /dev/null @@ -1,7 +0,0 @@ -// CS8054: `S.P': Structs without explicit constructors cannot contain members with initializers -// Line: 6 - -struct S -{ - public decimal P { get; } = -3; -} \ No newline at end of file diff --git a/mcs/errors/cs8075.cs b/mcs/errors/cs8075.cs new file mode 100644 index 00000000000..93333f7187b --- /dev/null +++ b/mcs/errors/cs8075.cs @@ -0,0 +1,9 @@ +// CS8075: `A.A()': Structs parameterless instance constructor must be public +// Line: 6 + +struct A +{ + A () + { + } +} diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs index e9194d4f1f8..37b93b7141a 100644 --- a/mcs/mcs/class.cs +++ b/mcs/mcs/class.cs @@ -963,7 +963,7 @@ public bool IsComImport { } } - public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression) + public void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression) { if (IsPartialPart) PartialContainer.RegisterFieldForInitialization (field, expression); @@ -976,6 +976,10 @@ public virtual void RegisterFieldForInitialization (MemberCore field, FieldIniti initialized_static_fields.Add (expression); } else { + if (Kind == MemberKind.Struct && Compiler.Settings.Version < LanguageVersion.V_6) { + Report.FeatureIsNotAvailable (Compiler, expression.Location, "struct instance member initializer"); + } + if (initialized_fields == null) initialized_fields = new List (4); @@ -1046,7 +1050,7 @@ public void ResolveFieldInitializers (BlockContext ec) // // Field is re-initialized to its default value => removed // - if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize) + if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize) continue; ec.AssignmentInfoOffset += fi.AssignmentOffset; @@ -2660,8 +2664,10 @@ protected virtual Constructor DefineDefaultConstructor (bool is_static) if (Kind == MemberKind.Class) c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments); - if (PrimaryConstructorParameters != null && !is_static) + if (PrimaryConstructorParameters != null && !is_static) { c.IsPrimaryConstructor = true; + c.caching_flags |= Flags.MethodOverloadsExist; + } AddConstructor (c, true); if (PrimaryConstructorBlock == null) { @@ -2680,6 +2686,7 @@ protected override bool DoDefineMembers () CheckProtectedModifier (); if (PrimaryConstructorParameters != null) { + foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) { if (p.Name == MemberName.Name) { Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type", @@ -3064,10 +3071,14 @@ static bool CheckFieldTypeCycle (TypeSpec ts) protected override bool DoDefineMembers () { - if (PrimaryConstructorParameters != null) + var res = base.DoDefineMembers (); + + if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) { generated_primary_constructor = DefineDefaultConstructor (false); + generated_primary_constructor.Define (); + } - return base.DoDefineMembers (); + return res; } public override void Emit () @@ -3077,14 +3088,14 @@ public override void Emit () base.Emit (); } - bool HasExplicitConstructor () + bool HasUserDefaultConstructor () { - foreach (var m in Members) { + foreach (var m in PartialContainer.Members) { var c = m as Constructor; if (c == null) continue; - if (!c.ParameterInfo.IsEmpty) + if (!c.IsStatic && c.ParameterInfo.IsEmpty) return true; } @@ -3143,18 +3154,6 @@ protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_cla base_type = Compiler.BuiltinTypes.ValueType; return ifaces; } - - public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression) - { - if ((field.ModFlags & Modifiers.STATIC) == 0 && !HasExplicitConstructor ()) { - Report.Error (8054, field.Location, "`{0}': Structs without explicit constructors cannot contain members with initializers", - field.GetSignatureForError ()); - - return; - } - - base.RegisterFieldForInitialization (field, expression); - } } /// diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index 35dc0a9cf02..d90cc01eb21 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -2363,11 +2363,25 @@ constructor_declarator if (lt.Value != current_container.MemberName.Name) { report.Error (1520, c.Location, "Class, struct, or interface method must have a return type"); } else if ((mods & Modifiers.STATIC) != 0) { + if (!current_local_parameters.IsEmpty) { + report.Error (132, c.Location, "`{0}': The static constructor must be parameterless", + c.GetSignatureForError ()); + } + if ((mods & Modifiers.AccessibilityMask) != 0){ report.Error (515, c.Location, "`{0}': static constructor cannot have an access modifier", c.GetSignatureForError ()); } + } else { + if (current_type.Kind == MemberKind.Struct && current_local_parameters.IsEmpty) { + if (lang_version < LanguageVersion.V_6) + FeatureIsNotAvailable (GetLocation ($3), "struct parameterless instance constructor"); + + if ((mods & Modifiers.PUBLIC) == 0) { + report.Error (8075, c.Location, "`{0}': Structs parameterless instance constructor must be public", c.GetSignatureForError ()); + } + } } current_type.AddConstructor (c); diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index ee0fce56191..8c6355386c3 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -764,6 +764,10 @@ public static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, re if (ctors == null) { switch (type.Kind) { case MemberKind.Struct: + // Every struct has implicit default constructor if not provided by user + if (args == null) + return null; + rc.Report.SymbolRelatedToPreviousError (type); // Report meaningful error for struct as they always have default ctor in C# context OverloadResolver.Error_ConstructorMismatch (rc, type, args == null ? 0 : args.Count, loc); @@ -5370,6 +5374,13 @@ public T ResolveMember (ResolveContext rc, ref Arguments args) where T : Memb if (best_candidate_rate == 0) break; + // + // We don't include implicit struct constructors in member-cache. Hence + // we need explicit check during lookup + // + if (args_count == 0 && (restrictions & Restrictions.NoBaseMembers) != 0 && best_candidate != null && best_candidate.Kind == MemberKind.Constructor && best_candidate.DeclaringType.IsStruct) + return null; + // // Try extension methods lookup when no ordinary method match was found and provider enables it // diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 823c95c3141..1d6a082094c 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -7341,12 +7341,6 @@ protected override Expression DoResolve (ResolveContext ec) return null; } - // - // Any struct always defines parameterless constructor - // - if (type.IsStruct && arguments == null) - return this; - bool dynamic; if (arguments != null) { arguments.Resolve (ec, out dynamic); diff --git a/mcs/mcs/method.cs b/mcs/mcs/method.cs index a78b99c6419..bd1a6aabb96 100644 --- a/mcs/mcs/method.cs +++ b/mcs/mcs/method.cs @@ -1498,15 +1498,6 @@ protected override Expression DoResolve (ResolveContext ec) "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ()); return this; } - } else { - // - // It is legal to have "this" initializers that take no arguments - // in structs - // - // struct D { public D (int a) : this () {} - // - if (ec.CurrentType.IsStruct && argument_list == null) - return this; } base_ctor = ConstructorLookup (ec, type, ref argument_list, loc); @@ -1663,12 +1654,6 @@ public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] protected override bool CheckBase () { if ((ModFlags & Modifiers.STATIC) != 0) { - if (!parameters.IsEmpty) { - Report.Error (132, Location, "`{0}': The static constructor must be parameterless", - GetSignatureForError ()); - return false; - } - if ((caching_flags & Flags.MethodOverloadsExist) != 0) Parent.MemberCache.CheckExistingMembersOverloads (this, parameters); @@ -1683,12 +1668,6 @@ protected override bool CheckBase () if ((caching_flags & Flags.MethodOverloadsExist) != 0) Parent.MemberCache.CheckExistingMembersOverloads (this, parameters); - if (Parent.PartialContainer.Kind == MemberKind.Struct && parameters.IsEmpty) { - Report.Error (568, Location, - "Structs cannot contain explicit parameterless constructors"); - return false; - } - CheckProtectedModifier (); return true; diff --git a/mcs/tests/gtest-autoproperty-10.cs b/mcs/tests/gtest-autoproperty-10.cs new file mode 100644 index 00000000000..a7308568468 --- /dev/null +++ b/mcs/tests/gtest-autoproperty-10.cs @@ -0,0 +1,16 @@ +struct S +{ + public decimal P { get; } = -3; +} + +class X +{ + public static int Main () + { + var s = new S (); + if (s.P != -3) + return 1; + + return 0; + } +} \ No newline at end of file diff --git a/mcs/tests/gtest-etree-01.cs b/mcs/tests/gtest-etree-01.cs index e538021cd0a..43f605e6b5b 100644 --- a/mcs/tests/gtest-etree-01.cs +++ b/mcs/tests/gtest-etree-01.cs @@ -210,6 +210,14 @@ public static implicit operator short (MyTypeImplicitOnly m) } } +struct StructWithUserConstructor +{ + public StructWithUserConstructor () + { + + } +} + class MemberAccessData { public bool BoolValue; @@ -2190,6 +2198,17 @@ void NewTest_7 () Assert (0, e.Compile ().Invoke ()); } + void NewTest_8 () + { + Expression> e = () => new DateTime (); + AssertNodeType (e, ExpressionType.New); + Assert (null, ((NewExpression)e.Body).Constructor, "default ctor"); + + Expression> e2 = () => new StructWithUserConstructor (); + AssertNodeType (e2, ExpressionType.New); + Assert ("Void .ctor()", ((NewExpression)e2.Body).Constructor.ToString (), "user ctor"); + } + void NotTest () { Expression> e = (bool a) => !a; diff --git a/mcs/tests/test-906.cs b/mcs/tests/test-906.cs new file mode 100644 index 00000000000..2af641f84c2 --- /dev/null +++ b/mcs/tests/test-906.cs @@ -0,0 +1,75 @@ +using System; + +struct S1 +{ + public readonly int Value; + + public S1 () + { + Value = 17; + } +} + +struct S2 +{ + public readonly int Value = 23; +} + +struct S3 +{ + public readonly int Value = 11; + + public S3 () + { + Value = 5; + } +} + +struct S4 +{ + public readonly int Value = 11; + + public S4 (int v) + { + } +} + +struct S5 +{ + public readonly int Value = 7; + + public S5 (int v) + : this () + { + this.Value += v; + } +} + +class C +{ + static int Main () + { + var s = new S1 (); + if (s.Value != 17) + return 1; + + var s2 = new S2 (); + if (s2.Value != 23) + return 2; + + var s3 = new S3 (); + if (s3.Value != 5) + return 3; + + var s4 = new S4 (5); + if (s4.Value != 11) + return 4; + + var s5 = new S5 (2); + if (s5.Value != 9) + return 5; + + Console.WriteLine ("ok"); + return 0; + } +} \ No newline at end of file diff --git a/mcs/tests/test-primary-ctor-07.cs b/mcs/tests/test-primary-ctor-07.cs index 233cfd0d03c..2e2fc7adbbe 100644 --- a/mcs/tests/test-primary-ctor-07.cs +++ b/mcs/tests/test-primary-ctor-07.cs @@ -14,6 +14,21 @@ static S () } } +struct S2 (int arg) +{ + public readonly int v = arg; +} + +struct S3 (string s = "arg") +{ + public readonly string V2 = s; + + public S3 (int i, string s = "arg2") + : this (s) + { + } +} + class X { public static int Main () @@ -24,6 +39,15 @@ public static int Main () if (new S ('x').y != 1) return 2; + if (new S2 (2).v != 2) + return 3; + + if (new S3 ("x").V2 != "x") + return 4; + + if (new S3 (0).V2 != "arg2") + return 5; + return 0; } } \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 224e5111e27..4f1559e99ac 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -20246,6 +20246,29 @@ 13 + + + 15 + + + + + + + 14 + + + 14 + + + + + 48 + + + 7 + + @@ -21548,6 +21571,16 @@ 12 + + + 2 + + + + + 140 + + @@ -50652,6 +50685,47 @@ + + + + 10 + + + + + 9 + + + + + 17 + + + + + 10 + + + 9 + + + + + 22 + + + 8 + + + + + 161 + + + 7 + + + @@ -68798,12 +68872,25 @@ - 69 + 180 7 + + + 8 + + + + + 9 + + + 8 + + From 4e1e37519aba2c466ce16ce6ce6c2492aaef0df5 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 16 Sep 2014 15:07:35 -0400 Subject: [PATCH 146/543] [runtime] Make stack walks done by the sampling profiler async safe. --- mono/metadata/loader.c | 12 ++++++++++++ mono/metadata/loader.h | 3 +++ mono/profiler/proflog.c | 15 +++++++++------ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index 09ea19b3d79..f7dc1497a01 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -2278,6 +2278,18 @@ mono_stack_walk_no_il (MonoStackWalk func, gpointer user_data) mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (stack_walk_adapter, NULL, MONO_UNWIND_DEFAULT, &ud); } +/* + * mono_stack_walk_async_safe: + * + * Async safe version callable from signal handlers. + */ +void +mono_stack_walk_async_safe (MonoStackWalk func, gpointer user_data) +{ + StackWalkUserData ud = { func, user_data }; + mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (stack_walk_adapter, NULL, MONO_UNWIND_NONE, &ud); +} + static gboolean last_managed (MonoMethod *m, gint no, gint ilo, gboolean managed, gpointer data) { diff --git a/mono/metadata/loader.h b/mono/metadata/loader.h index b159dee727a..ae0ca441773 100644 --- a/mono/metadata/loader.h +++ b/mono/metadata/loader.h @@ -90,6 +90,9 @@ mono_stack_walk (MonoStackWalk func, void* user_data); MONO_API void mono_stack_walk_no_il (MonoStackWalk func, void* user_data); +MONO_API void +mono_stack_walk_async_safe (MonoStackWalk func, void* user_data); + MONO_END_DECLS #endif diff --git a/mono/profiler/proflog.c b/mono/profiler/proflog.c index 9021a00b24d..520b3b228d5 100644 --- a/mono/profiler/proflog.c +++ b/mono/profiler/proflog.c @@ -831,10 +831,13 @@ walk_stack (MonoMethod *method, int32_t native_offset, int32_t il_offset, mono_b * event, hence the collect_bt/emit_bt split. */ static void -collect_bt (FrameData *data) +collect_bt (FrameData *data, gboolean async_safe) { data->count = 0; - mono_stack_walk_no_il (walk_stack, data); + if (async_safe) + mono_stack_walk_async_safe (walk_stack, data); + else + mono_stack_walk_no_il (walk_stack, data); } static void @@ -867,7 +870,7 @@ gc_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass) len += 7; len &= ~7; if (do_bt) - collect_bt (&data); + collect_bt (&data, FALSE); logbuffer = ensure_logbuf (32 + MAX_FRAMES * 8); now = current_time (); ENTER_LOG (logbuffer, "gcalloc"); @@ -1132,7 +1135,7 @@ throw_exc (MonoProfiler *prof, MonoObject *object) FrameData data; LogBuffer *logbuffer; if (do_bt) - collect_bt (&data); + collect_bt (&data, FALSE); logbuffer = ensure_logbuf (16 + MAX_FRAMES * 8); now = current_time (); ENTER_LOG (logbuffer, "throw"); @@ -1168,7 +1171,7 @@ monitor_event (MonoProfiler *profiler, MonoObject *object, MonoProfilerMonitorEv FrameData data; LogBuffer *logbuffer; if (do_bt) - collect_bt (&data); + collect_bt (&data, FALSE); logbuffer = ensure_logbuf (16 + MAX_FRAMES * 8); now = current_time (); ENTER_LOG (logbuffer, "monitor"); @@ -1230,7 +1233,7 @@ mono_sample_hit (MonoProfiler *profiler, unsigned char *ip, void *context) if (in_shutdown) return; now = current_time (); - collect_bt (&bt_data); + collect_bt (&bt_data, TRUE); elapsed = (now - profiler->startup_time) / 10000; if (do_debug) { int len; From 87622fc7118eb87e958f865353da4c14053f1808 Mon Sep 17 00:00:00 2001 From: Martin Baulig Date: Tue, 16 Sep 2014 21:30:34 +0200 Subject: [PATCH 147/543] [WCF]: Update to my last fix for bug #22129. The problem already starts when creating the OperationDescription; we need to also look at the End* method here to correctly parse the reply parameters. Then ClientRuntimeChannel.Process needs to distinguish between sync/async and copy the out/byref parameters when needed. --- .../ContractDescription.cs | 3 + .../ContractDescriptionGenerator.cs | 16 +++-- .../BaseMessagesFormatter.cs | 3 +- .../ClientRuntimeChannel.cs | 58 +++++++++++-------- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescription.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescription.cs index 6c0c3366f75..805053196d4 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescription.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescription.cs @@ -234,6 +234,9 @@ void PopulateClientOperation (ClientRuntime proxy, OperationDescription od, bool foreach (var fd in od.Faults) o.FaultContractInfos.Add (new FaultContractInfo (fd.Action, fd.DetailType)); + o.BeginMethod = od.BeginMethod; + o.EndMethod = od.EndMethod; + // FIXME: at initialization time it does not seem to // fill default formatter. It should be filled after // applying all behaviors. (Tthat causes regression, so diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescriptionGenerator.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescriptionGenerator.cs index 929a450d22b..a7665b8cab6 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescriptionGenerator.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescriptionGenerator.cs @@ -237,7 +237,6 @@ static void FillOperationsForInterface (ContractDescription cd, Type exactContra for (int i = 0; i < contractMethods.Length; ++i) { - MethodInfo mi = contractMethods [i]; OperationContractAttribute oca = GetOperationContractAttribute (mi); if (oca == null) @@ -253,7 +252,7 @@ static void FillOperationsForInterface (ContractDescription cd, Type exactContra if (GetOperationContractAttribute (end) != null) throw new InvalidOperationException ("Async 'End' method must not have OperationContractAttribute. It is automatically treated as the EndMethod of the corresponding 'Begin' method."); } - OperationDescription od = GetOrCreateOperation (cd, mi, serviceMethods [i], oca, end != null ? end.ReturnType : null, isCallback, givenServiceType); + OperationDescription od = GetOrCreateOperation (cd, mi, serviceMethods [i], oca, end, isCallback, givenServiceType); if (end != null) od.EndMethod = end; } @@ -286,7 +285,7 @@ static IEnumerable GetAllInterfaceTypes (Type type) static OperationDescription GetOrCreateOperation ( ContractDescription cd, MethodInfo mi, MethodInfo serviceMethod, OperationContractAttribute oca, - Type asyncReturnType, + MethodInfo endMethod, bool isCallback, Type givenServiceType) { @@ -311,7 +310,8 @@ static OperationDescription GetOrCreateOperation ( od.Messages.Add (GetMessage (od, mi, oca, true, isCallback, null)); if (!od.IsOneWay) { - var md = GetMessage (od, mi, oca, false, isCallback, asyncReturnType); + var asyncReturnType = endMethod != null ? endMethod.ReturnType : null; + var md = GetMessage (od, endMethod ?? mi, oca, false, isCallback, asyncReturnType); od.Messages.Add (md); var mpa = mi.ReturnParameter.GetCustomAttribute (true); if (mpa != null) { @@ -522,8 +522,12 @@ public static MessageDescription CreateMessageDescription ( int index = 0; foreach (ParameterInfo pi in plist) { // AsyncCallback and state are extraneous. - if (oca.AsyncPattern && pi.Position == plist.Length - 2) - break; + if (oca.AsyncPattern) { + if (isRequest && pi.Position == plist.Length - 2) + break; + if (!isRequest && pi.Position == plist.Length - 1) + break; + } // They are ignored: // - out parameter in request diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs index f512ea37553..db1c49650c1 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs @@ -281,9 +281,10 @@ public object DeserializeReply (Message message, object [] parameters) } else { int index = ParamsOffset (md.Body); - foreach (ParameterInfo pi in requestMethodParams) + foreach (ParameterInfo pi in replyMethodParams) { if (pi.IsOut || pi.ParameterType.IsByRef) parameters [pi.Position] = parts [index++]; + } return HasReturnValue (md.Body) ? parts [0] : null; } } diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs index 419892a58ce..043b2ab7af0 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs @@ -71,7 +71,7 @@ class ClientRuntimeChannel #region delegates readonly ProcessDelegate _processDelegate; - delegate object ProcessDelegate (MethodBase method, string operationName, object [] parameters, OperationContext context); + delegate object ProcessDelegate (MethodBase method, string operationName, bool isAsync, ref object [] parameters, OperationContext context); readonly RequestDelegate requestDelegate; @@ -436,16 +436,13 @@ public IExtensionCollection Extensions { #region Request/Output processing - class OperationParameters - { - public object[] Parameters; - public object UserData; - } - public IAsyncResult BeginProcess (MethodBase method, string operationName, object [] parameters, AsyncCallback callback, object asyncState) { - var p = new OperationParameters { Parameters = parameters, UserData = asyncState }; - return _processDelegate.BeginInvoke (method, operationName, parameters, OperationContext.Current, callback, p); + var p = parameters; + var retval = _processDelegate.BeginInvoke (method, operationName, true, ref p, OperationContext.Current, callback, asyncState); + if (p != parameters) + throw new InvalidOperationException (); + return retval; } public object EndProcess (MethodBase method, string operationName, object [] parameters, IAsyncResult result) @@ -455,24 +452,34 @@ public object EndProcess (MethodBase method, string operationName, object [] par if (parameters == null) throw new ArgumentNullException ("parameters"); - var p = (OperationParameters)result.AsyncState; - if (p.Parameters.Length != parameters.Length) - throw new ArgumentException ("Parameter array has invalid length.", "parameters"); + object[] p = parameters; + var retval = _processDelegate.EndInvoke (ref p, result); + if (p == parameters) + return retval; - for (int i = 0; i < parameters.Length; i++) - parameters [i] = p.Parameters [i]; - - return _processDelegate.EndInvoke (result); + if (p.Length != parameters.Length) + throw new InvalidOperationException (); + Array.Copy (p, parameters, p.Length); + return retval; } public object Process (MethodBase method, string operationName, object [] parameters, OperationContext context) + { + var p = parameters; + var retval = Process (method, operationName, false, ref p, context); + if (p != parameters) + throw new InvalidOperationException (); + return retval; + } + + object Process (MethodBase method, string operationName, bool isAsync, ref object [] parameters, OperationContext context) { var previousContext = OperationContext.Current; try { // Inherit the context from the calling thread OperationContext.Current = context; - return DoProcess (method, operationName, parameters, context); + return DoProcess (method, operationName, isAsync, ref parameters, context); } catch (Exception ex) { throw; } finally { @@ -481,7 +488,7 @@ public object Process (MethodBase method, string operationName, object [] parame } } - object DoProcess (MethodBase method, string operationName, object [] parameters, OperationContext context) + object DoProcess (MethodBase method, string operationName, bool isAsync, ref object [] parameters, OperationContext context) { if (AllowInitializationUI) DisplayInitializationUI (); @@ -491,7 +498,7 @@ object DoProcess (MethodBase method, string operationName, object [] parameters, Open (); if (!od.IsOneWay) - return Request (od, parameters, context); + return Request (od, isAsync, ref parameters, context); else { Output (od, parameters, context); return null; @@ -517,7 +524,7 @@ void Output (OperationDescription od, object [] parameters, OperationContext con Send (CreateRequest (op, parameters, context), OperationTimeout); } - object Request (OperationDescription od, object [] parameters, OperationContext context) + object Request (OperationDescription od, bool isAsync, ref object [] parameters, OperationContext context) { ClientOperation op = runtime.Operations [od.Name]; object [] inspections = new object [runtime.MessageInspectors.Count]; @@ -558,10 +565,15 @@ object Request (OperationDescription od, object [] parameters, OperationContext for (int i = 0; i < inspections.Length; i++) runtime.MessageInspectors [i].AfterReceiveReply (ref res, inspections [i]); - if (op.DeserializeReply) - return op.Formatter.DeserializeReply (res, parameters); - else + if (!op.DeserializeReply) return res; + + if (isAsync && od.EndMethod != null) { + var endParams = od.EndMethod.GetParameters (); + parameters = new object [endParams.Length - 1]; + } + + return op.Formatter.DeserializeReply (res, parameters); } #region Message-based Request() and Send() From 2804d6af37c1833118cb28bc8f3e452f1b720bd0 Mon Sep 17 00:00:00 2001 From: Michael Hutchinson Date: Tue, 16 Sep 2014 16:22:02 -0400 Subject: [PATCH 148/543] Fix mobile and mobile_static profiles And bring them to parity with monodroid and monotouch --- mcs/Makefile | 2 + mcs/build/profiles/mobile.make | 17 ++- mcs/build/profiles/mobile_static.make | 19 ++- mcs/build/profiles/monodroid.make | 19 ++- mcs/build/profiles/monotouch.make | 22 +++- mcs/class/Makefile | 41 ++++--- mcs/class/Mono.CSharp/Makefile | 4 +- .../mobile_static_Mono.CSharp.dll.sources | 13 ++ .../monotouch_Mono.CSharp.dll.sources | 15 +-- mcs/class/Mono.Dynamic.Interpreter/Makefile | 6 +- .../Makefile | 2 +- .../Makefile | 2 +- ...ComponentModel.DataAnnotations.dll.sources | 1 + mcs/class/System.Core/Makefile | 11 +- .../mobile_System.Core.dll.sources | 111 +----------------- .../mobile_common_System.Core.dll.sources | 108 +++++++++++++++++ .../mobile_static_System.Core.dll.sources | 2 + .../monodroid_System.Core.dll.sources | 2 +- .../monotouch_System.Core.dll.sources | 2 +- .../xammac_System.Core.dll.sources | 2 +- ...le_System.Data.Services.Client.dll.sources | 3 +- mcs/class/System.Interactive.Async/Makefile | 2 +- .../System.Interactive.Providers/Makefile | 2 +- mcs/class/System.Interactive/Makefile | 2 +- mcs/class/System.Reactive.Core/Makefile | 2 +- mcs/class/System.Reactive.Debugger/Makefile | 2 +- .../System.Reactive.Experimental/Makefile | 2 +- mcs/class/System.Reactive.Interfaces/Makefile | 2 +- mcs/class/System.Reactive.Linq/Makefile | 2 +- .../System.Reactive.PlatformServices/Makefile | 2 +- mcs/class/System.XML/Makefile | 4 +- mcs/class/System.Xaml/Makefile | 2 +- mcs/class/System/Makefile | 8 +- 33 files changed, 257 insertions(+), 179 deletions(-) create mode 100644 mcs/class/Mono.CSharp/mobile_static_Mono.CSharp.dll.sources create mode 100644 mcs/class/System.ComponentModel.DataAnnotations/mobile_System.ComponentModel.DataAnnotations.dll.sources create mode 100644 mcs/class/System.Core/mobile_common_System.Core.dll.sources create mode 100644 mcs/class/System.Core/mobile_static_System.Core.dll.sources diff --git a/mcs/Makefile b/mcs/Makefile index af4495e9195..9bcf32ea2fb 100644 --- a/mcs/Makefile +++ b/mcs/Makefile @@ -12,6 +12,7 @@ monotouch_SUBDIRS := build class monotouch_runtime_SUBDIRS := build class xammac_SUBDIRS := build class mobile_SUBDIRS := build class +mobile_static_SUBDIRS := build class net_3_5_SUBDIRS := build class tools/xbuild net_4_0_SUBDIRS := build class net_4_5_SUBDIRS := build mcs class nunit24 ilasm tools tests errors docs @@ -114,6 +115,7 @@ $(_boot_:%=profile-do--monotouch--%): profile-do--monotouch--%: $(_boot_:%=profile-do--monotouch_runtime--%): profile-do--monotouch_runtime--%: profile-do--build--% $(_boot_:%=profile-do--xammac--%): profile-do--xammac--%: profile-do--build--% $(_boot_:%=profile-do--mobile--%): profile-do--mobile--%: profile-do--build--% +$(_boot_:%=profile-do--mobile_static--%): profile-do--mobile_static--%: profile-do--build--% $(_boot_:%=profile-do--net_2_0--%): profile-do--net_2_0--%: profile-do--build--% $(_boot_:%=profile-do--build--%): profile-do--build--%: profile-do--basic--% diff --git a/mcs/build/profiles/mobile.make b/mcs/build/profiles/mobile.make index 87c51f407c8..117ac605151 100644 --- a/mcs/build/profiles/mobile.make +++ b/mcs/build/profiles/mobile.make @@ -12,7 +12,22 @@ profile-check: @: DEFAULT_REFERENCES = -r:mscorlib.dll -PROFILE_MCS_FLAGS = -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:MOBILE -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -nowarn:1699 -nostdlib -lib:$(topdir)/class/lib/$(PROFILE) $(DEFAULT_REFERENCES) $(PLATFORM_DEBUG_FLAGS) + +PROFILE_MCS_FLAGS = \ + -d:NET_1_1 \ + -d:NET_2_0 \ + -d:NET_2_1 \ + -d:MOBILE \ + -d:MOBILE_DYNAMIC \ + -d:NET_3_5 \ + -d:NET_4_0 \ + -d:NET_4_5 \ + -nowarn:1699 \ + -nostdlib \ + -lib:$(topdir)/class/lib/$(PROFILE) \ + $(DEFAULT_REFERENCES) \ + $(PLATFORM_DEBUG_FLAGS) + FRAMEWORK_VERSION = 2.1 NO_INSTALL = yes diff --git a/mcs/build/profiles/mobile_static.make b/mcs/build/profiles/mobile_static.make index 59505666ad7..b7898235194 100644 --- a/mcs/build/profiles/mobile_static.make +++ b/mcs/build/profiles/mobile_static.make @@ -12,7 +12,24 @@ profile-check: @: DEFAULT_REFERENCES = -r:mscorlib.dll -PROFILE_MCS_FLAGS = -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MOBILE -d:FULL_AOT_RUNTIME -d:DISABLE_REMOTING -d:DISABLE_COM -nowarn:1699 -nostdlib -lib:$(topdir)/class/lib/$(PROFILE) $(DEFAULT_REFERENCES) $(PLATFORM_DEBUG_FLAGS) + +PROFILE_MCS_FLAGS = \ + -d:NET_1_1 \ + -d:NET_2_0 \ + -d:NET_2_1 \ + -d:NET_3_5 \ + -d:NET_4_0 \ + -d:NET_4_5 \ + -d:MOBILE \ + -d:FULL_AOT_RUNTIME \ + -d:DISABLE_REMOTING \ + -d:DISABLE_COM \ + -nowarn:1699 \ + -nostdlib \ + -lib:$(topdir)/class/lib/$(PROFILE) \ + $(DEFAULT_REFERENCES) \ + $(PLATFORM_DEBUG_FLAGS) + FRAMEWORK_VERSION = 2.1 NO_TEST = yes diff --git a/mcs/build/profiles/monodroid.make b/mcs/build/profiles/monodroid.make index 7336ced7b7b..c14f61c6087 100644 --- a/mcs/build/profiles/monodroid.make +++ b/mcs/build/profiles/monodroid.make @@ -12,7 +12,24 @@ profile-check: @: DEFAULT_REFERENCES = -r:mscorlib.dll -PROFILE_MCS_FLAGS = -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MOBILE -d:MOBILE_DYNAMIC -d:MONODROID -nowarn:1699 -nostdlib -lib:$(topdir)/class/lib/$(PROFILE) $(DEFAULT_REFERENCES) $(PLATFORM_DEBUG_FLAGS) + +PROFILE_MCS_FLAGS = \ + -d:NET_1_1 \ + -d:NET_2_0 \ + -d:NET_2_1 \ + -d:NET_3_5 \ + -d:NET_4_0 \ + -d:NET_4_5 \ + -d:MOBILE \ + -d:MOBILE_DYNAMIC \ + -d:MONODROID \ + -d:ANDROID \ + -nowarn:1699 \ + -nostdlib \ + -lib:$(topdir)/class/lib/$(PROFILE) \ + $(DEFAULT_REFERENCES) \ + $(PLATFORM_DEBUG_FLAGS) + FRAMEWORK_VERSION = 2.1 NO_TEST = yes diff --git a/mcs/build/profiles/monotouch.make b/mcs/build/profiles/monotouch.make index b841a1027ae..706463d748c 100644 --- a/mcs/build/profiles/monotouch.make +++ b/mcs/build/profiles/monotouch.make @@ -12,9 +12,27 @@ profile-check: @: DEFAULT_REFERENCES = -r:mscorlib.dll -PROFILE_MCS_FLAGS = -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MOBILE -d:MONOTOUCH -d:DISABLE_REMOTING -d:DISABLE_COM -d:FULL_AOT_RUNTIME -nowarn:1699 -nostdlib -lib:$(topdir)/class/lib/$(PROFILE) $(DEFAULT_REFERENCES) $(PLATFORM_DEBUG_FLAGS) + +PROFILE_MCS_FLAGS = \ + -d:NET_1_1 \ + -d:NET_2_0 \ + -d:NET_2_1 \ + -d:NET_3_5 \ + -d:NET_4_0 \ + -d:NET_4_5 \ + -d:MOBILE \ + -d:MONOTOUCH \ + -d:DISABLE_REMOTING \ + -d:DISABLE_COM \ + -d:FULL_AOT_RUNTIME \ + -nowarn:1699 \ + -nostdlib \ + -lib:$(topdir)/class/lib/$(PROFILE) \ + $(DEFAULT_REFERENCES) \ + $(PLATFORM_DEBUG_FLAGS) + FRAMEWORK_VERSION = 2.1 NO_TEST = yes # the tuner takes care of the install -NO_INSTALL = yes \ No newline at end of file +NO_INSTALL = yes diff --git a/mcs/class/Makefile b/mcs/class/Makefile index 47cf334888e..8ca914dca53 100644 --- a/mcs/class/Makefile +++ b/mcs/class/Makefile @@ -106,7 +106,7 @@ net_2_0_only_dirs := \ pcl_facade_dirs := Facades -mobile_dirs := \ +mobile_common_dirs := \ corlib \ System \ System.Core \ @@ -134,19 +134,27 @@ mobile_dirs := \ System.Net \ System.Windows \ System.Xml.Serialization \ + Mono.CSharp \ + Microsoft.CSharp \ $(pcl_facade_dirs) -monodroid_dirs := \ +mobile_static_dirs := \ + $(mobile_common_dirs) \ + Mono.Dynamic.Interpreter + +mobile_dynamic_dirs := \ + $(mobile_common_dirs) \ Mono.CompilerServices.SymbolWriter \ - Mono.CSharp \ - Microsoft.CSharp \ System.Net.Http xammac_dirs := \ - Mono.CompilerServices.SymbolWriter \ - Mono.CSharp \ - Microsoft.CSharp \ - System.Net.Http + $(mobile_dynamic_dirs) + +monodroid_dirs := \ + $(mobile_dynamic_dirs) + +monotouch_dirs := \ + $(mobile_static_dirs) monotouch_runtime_dirs := \ corlib \ @@ -155,11 +163,6 @@ monotouch_runtime_dirs := \ System.XML \ Mono.CSharp -monotouch_dirs := \ - Mono.CSharp \ - Microsoft.CSharp \ - Mono.Dynamic.Interpreter - net_4_0_dirs := \ System.Numerics \ Microsoft.CSharp \ @@ -229,12 +232,12 @@ xbuild_4_0_dirs := \ Microsoft.Build net_2_0_SUBDIRS := $(net_2_0_dirs) $(net_2_0_only_dirs) $(xbuild_2_0_dirs) aot-compiler -monodroid_SUBDIRS := $(mobile_dirs) $(monodroid_dirs) -monotouch_SUBDIRS := $(mobile_dirs) $(monotouch_dirs) +monodroid_SUBDIRS := $(monodroid_dirs) +monotouch_SUBDIRS := $(monotouch_dirs) monotouch_runtime_SUBDIRS := $(monotouch_runtime_dirs) -mobile_static_SUBDIRS := $(mobile_dirs) -mobile_SUBDIRS := $(mobile_dirs) -xammac_SUBDIRS := $(mobile_dirs) $(xammac_dirs) +mobile_static_SUBDIRS := $(mobile_static_dirs) +mobile_SUBDIRS := $(mobile_dynamic_dirs) +xammac_SUBDIRS := $(xammac_dirs) net_3_5_SUBDIRS := $(xbuild_2_0_dirs) net_4_0_SUBDIRS := $(net_2_0_dirs) $(net_4_0_dirs) $(net_4_0_only_dirs) $(xbuild_4_0_dirs) net_4_5_SUBDIRS := $(net_2_0_dirs) $(net_4_0_dirs) $(net_4_5_dirs) $(xbuild_4_0_dirs) aot-compiler @@ -242,7 +245,7 @@ xbuild_12_SUBDIRS := $(xbuild_4_0_dirs) include ../build/rules.make -SUBDIRS = $(net_2_0_dirs) $(net_2_0_only_dirs) $(mobile_dirs) $(monotouch_dirs) $(net_4_0_dirs) $(net_4_0_only_dirs) $(net_4_5_dirs) +SUBDIRS = $(net_2_0_dirs) $(net_2_0_only_dirs) $(mobile_static_dirs) $(mobile_dynamic_dirs) $(monotouch_dirs) $(monodroid_dirs) $(xammac_dirs) $(net_4_0_dirs) $(net_4_0_only_dirs) $(net_4_5_dirs) DIST_ONLY_SUBDIRS = dlr aot-compiler $(xbuild_4_0_dirs) diff --git a/mcs/class/Mono.CSharp/Makefile b/mcs/class/Mono.CSharp/Makefile index 85b86e0f466..35ee0a302bc 100644 --- a/mcs/class/Mono.CSharp/Makefile +++ b/mcs/class/Mono.CSharp/Makefile @@ -6,7 +6,9 @@ LIBRARY = Mono.CSharp.dll LIB_MCS_FLAGS = -r:System.Core.dll -r:System.Xml.dll -r:System.dll -ifeq (monotouch, $(PROFILE)) +MOBILE_STATIC := $(filter mobile_static monotouch, $(PROFILE)) + +ifdef MOBILE_STATIC LIB_MCS_FLAGS += -d:IOS_REFLECTION endif diff --git a/mcs/class/Mono.CSharp/mobile_static_Mono.CSharp.dll.sources b/mcs/class/Mono.CSharp/mobile_static_Mono.CSharp.dll.sources new file mode 100644 index 00000000000..6e4c34213be --- /dev/null +++ b/mcs/class/Mono.CSharp/mobile_static_Mono.CSharp.dll.sources @@ -0,0 +1,13 @@ +#include Mono.CSharp.dll.sources +../corlib/System.Reflection.Emit/AssemblyBuilderAccess.cs +../corlib/System.Reflection.Emit/FlowControl.cs +../corlib/System.Reflection.Emit/OpCode.cs +../corlib/System.Reflection.Emit/OpCodeNames.cs +../corlib/System.Reflection.Emit/OpCodes.cs +../corlib/System.Reflection.Emit/OpCodeType.cs +../corlib/System.Reflection.Emit/OperandType.cs +../corlib/System.Reflection.Emit/PEFileKinds.cs +../corlib/System.Reflection.Emit/Label.cs +../corlib/System.Reflection.Emit/MethodToken.cs +../corlib/System.Reflection.Emit/StackBehaviour.cs +monotouch.cs \ No newline at end of file diff --git a/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources b/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources index 6e4c34213be..d04d5f08d95 100644 --- a/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources +++ b/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources @@ -1,13 +1,2 @@ -#include Mono.CSharp.dll.sources -../corlib/System.Reflection.Emit/AssemblyBuilderAccess.cs -../corlib/System.Reflection.Emit/FlowControl.cs -../corlib/System.Reflection.Emit/OpCode.cs -../corlib/System.Reflection.Emit/OpCodeNames.cs -../corlib/System.Reflection.Emit/OpCodes.cs -../corlib/System.Reflection.Emit/OpCodeType.cs -../corlib/System.Reflection.Emit/OperandType.cs -../corlib/System.Reflection.Emit/PEFileKinds.cs -../corlib/System.Reflection.Emit/Label.cs -../corlib/System.Reflection.Emit/MethodToken.cs -../corlib/System.Reflection.Emit/StackBehaviour.cs -monotouch.cs \ No newline at end of file +#include mobil_static_Mono.CSharp.dll.sources +monotouch.cs diff --git a/mcs/class/Mono.Dynamic.Interpreter/Makefile b/mcs/class/Mono.Dynamic.Interpreter/Makefile index 76777611827..bbb733bf693 100644 --- a/mcs/class/Mono.Dynamic.Interpreter/Makefile +++ b/mcs/class/Mono.Dynamic.Interpreter/Makefile @@ -9,7 +9,9 @@ LIB_MCS_FLAGS = -r:System.dll -r:System.Core.dll \ -d:MONO_INTERPRETER \ -delaysign -keyfile:../mono.pub -ifeq (monotouch, $(subst _runtime,,$(PROFILE))) +MOBILE_STATIC := $(filter mobile_static monotouch monotouch_runtime, $(PROFILE)) + +ifdef MOBILE_STATIC mono_dynamic_interpreter_deps = $(the_libdir_base)plaincore/System.Core.dll LIB_MCS_FLAGS += -lib:$(the_libdir_base)plaincore endif @@ -21,4 +23,4 @@ $(the_libdir_base)Mono.Dynamic.Interpreter.dll: $(mono_dynamic_interpreter_deps) $(the_libdir_base)plaincore/System.Core.dll: (cd ../System.Core; $(MAKE) $@) -.NOTPARALLEL: $(the_libdir_base)plaincore/System.Core.dll \ No newline at end of file +.NOTPARALLEL: $(the_libdir_base)plaincore/System.Core.dll diff --git a/mcs/class/System.ComponentModel.Composition.4.5/Makefile b/mcs/class/System.ComponentModel.Composition.4.5/Makefile index 4fe0fee915e..b71beeab45d 100644 --- a/mcs/class/System.ComponentModel.Composition.4.5/Makefile +++ b/mcs/class/System.ComponentModel.Composition.4.5/Makefile @@ -12,7 +12,7 @@ CLEAN_FILES += $(STRING_MESSAGES) EXTRA_DISTFILES = \ src/ComponentModel/Strings.resx -VALID_PROFILE := $(filter net_4_0 net_4_5 monotouch monodroid xammac mobile_static, $(PROFILE)) +VALID_PROFILE := $(filter net_4_0 net_4_5 monotouch monodroid xammac mobile mobile_static, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.ComponentModel.Composition.dll NO_INSTALL = yes diff --git a/mcs/class/System.ComponentModel.DataAnnotations/Makefile b/mcs/class/System.ComponentModel.DataAnnotations/Makefile index 713754ccdb3..3d9ff9e2586 100644 --- a/mcs/class/System.ComponentModel.DataAnnotations/Makefile +++ b/mcs/class/System.ComponentModel.DataAnnotations/Makefile @@ -18,7 +18,7 @@ endif TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) # This is a .NET 3.5+ assembly -VALID_PROFILE := $(filter net_2_0 net_4_0 net_4_5 monotouch monodroid xammac mobile_static, $(PROFILE)) +VALID_PROFILE := $(filter net_2_0 net_4_0 net_4_5 monotouch monodroid xammac mobile mobile_static, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.ComponentModel.DataAnnotations.dll NO_INSTALL = yes diff --git a/mcs/class/System.ComponentModel.DataAnnotations/mobile_System.ComponentModel.DataAnnotations.dll.sources b/mcs/class/System.ComponentModel.DataAnnotations/mobile_System.ComponentModel.DataAnnotations.dll.sources new file mode 100644 index 00000000000..3de14f5e0a7 --- /dev/null +++ b/mcs/class/System.ComponentModel.DataAnnotations/mobile_System.ComponentModel.DataAnnotations.dll.sources @@ -0,0 +1 @@ +#include net_4_5_System.ComponentModel.DataAnnotations.dll.sources diff --git a/mcs/class/System.Core/Makefile b/mcs/class/System.Core/Makefile index c8836d3125b..f8cc33c7e8b 100644 --- a/mcs/class/System.Core/Makefile +++ b/mcs/class/System.Core/Makefile @@ -10,17 +10,16 @@ ifneq (2.1, $(FRAMEWORK_VERSION)) LIB_MCS_FLAGS += -d:NET_3_5 -nowarn:1720 endif -ifeq (monodroid, $(PROFILE)) -LIB_MCS_FLAGS += -d:FEATURE_CORE_DLR,FEATURE_REFEMIT,ANDROID -endif +MOBILE_DYNAMIC := $(filter monodroid xammac mobile, $(PROFILE)) +MOBILE_STATIC := $(filter mobile_static monotouch monotouch_runtime, $(PROFILE)) -ifeq (xammac, $(PROFILE)) +ifdef MOBILE_DYNAMIC LIB_MCS_FLAGS += -d:FEATURE_CORE_DLR,FEATURE_REFEMIT endif system_core_plain_libdir = $(the_libdir_base)plaincore -ifeq (monotouch, $(subst _runtime,,$(PROFILE))) +ifdef MOBILE_STATIC extra_test_flags := -exclude:NotWorkingInterpreter system_core_library_deps = $(the_libdir_base)Mono.Dynamic.Interpreter.dll $(system_core_plain_libdir)/System.Core.dll LIB_MCS_FLAGS += -d:FEATURE_CORE_DLR @@ -72,4 +71,4 @@ ifneq ($(PROFILE),basic) csproj-local: $(MAKE) csproj-local intermediate=plaincore/ endif -endif \ No newline at end of file +endif diff --git a/mcs/class/System.Core/mobile_System.Core.dll.sources b/mcs/class/System.Core/mobile_System.Core.dll.sources index dee2534a29b..5cd8ddf660b 100644 --- a/mcs/class/System.Core/mobile_System.Core.dll.sources +++ b/mcs/class/System.Core/mobile_System.Core.dll.sources @@ -1,109 +1,4 @@ -Assembly/AssemblyInfo.cs -System/Actions.cs -System/Funcs.cs -System/InvalidTimeZoneException.cs -System/TimeZoneInfo.AdjustmentRule.cs -System/TimeZoneInfo.cs -System/TimeZoneInfo.Serialization.cs -System/TimeZoneInfo.TransitionTime.cs -System/TimeZoneNotFoundException.cs -System/Util.cs -System.Runtime.CompilerServices/DynamicAttribute.cs -System.Runtime.CompilerServices/ExecutionScope.cs -System.Runtime.CompilerServices/ExtensionAttribute.cs -System.Runtime.CompilerServices/IStrongBox.cs -System.Runtime.CompilerServices/StrongBox_T.cs -System.Linq/Check.cs -System.Linq/Enumerable.cs -System.Linq/QueryableEnumerable.cs -System.Linq/QueryableTransformer.cs -System.Linq/Grouping.cs -System.Linq/IGrouping.cs -System.Linq/IOrderedQueryable.cs -System.Linq/IOrderedQueryable_T.cs -System.Linq/IOrderedEnumerable_T.cs -System.Linq/IQueryable.cs -System.Linq/IQueryable_T.cs -System.Linq/Lookup.cs -System.Linq/ILookup_T.cs -System.Linq/OrderedEnumerable.cs -System.Linq/OrderedSequence.cs -System.Linq/Queryable.cs -System.Linq/QuickSort.cs -System.Linq/SortContext.cs -System.Linq/SortDirection.cs -System.Linq/SortSequenceContext.cs -System.Linq/IQueryProvider.cs -System.Collections.Generic/HashSet.cs -System.Security.Cryptography/Aes.cs -System.Threading/LockRecursionPolicy.cs -System.Threading/ReaderWriterLockSlim.cs -System.Threading/ThreadLockState.cs -System.Threading/ReaderWriterLockSlimExtensions.cs -System.Linq.Parallel.QueryNodes/QueryBaseNode.cs -System.Linq.Parallel.QueryNodes/QueryCastNode.cs -System.Linq.Parallel.QueryNodes/QueryChildNode.cs -System.Linq.Parallel.QueryNodes/QueryConcatNode.cs -System.Linq.Parallel.QueryNodes/QueryDefaultEmptyNode.cs -System.Linq.Parallel.QueryNodes/QueryGroupByNode.cs -System.Linq.Parallel.QueryNodes/QueryHeadWorkerNode.cs -System.Linq.Parallel.QueryNodes/QueryJoinNode.cs -System.Linq.Parallel.QueryNodes/QueryMuxNode.cs -System.Linq.Parallel.QueryNodes/QueryOptionNode.cs -System.Linq.Parallel.QueryNodes/QueryOrderByNode.cs -System.Linq.Parallel.QueryNodes/QueryOrderGuardNode.cs -System.Linq.Parallel.QueryNodes/QueryOrderedStreamNode.cs -System.Linq.Parallel.QueryNodes/QueryReverseNode.cs -System.Linq.Parallel.QueryNodes/QuerySelectManyNode.cs -System.Linq.Parallel.QueryNodes/QuerySelectNode.cs -System.Linq.Parallel.QueryNodes/QuerySetNode.cs -System.Linq.Parallel.QueryNodes/QueryStartNode.cs -System.Linq.Parallel.QueryNodes/QueryStreamNode.cs -System.Linq.Parallel.QueryNodes/QueryWhereNode.cs -System.Linq.Parallel.QueryNodes/QueryZipNode.cs -System.Linq.Parallel.QueryNodes/SetInclusion.cs -System.Linq.Parallel.QueryNodes/WrapHelper.cs -System.Linq.Parallel/AggregationList.cs -System.Linq.Parallel/ConcurrentGrouping.cs -System.Linq.Parallel/ConcurrentLookup.cs -System.Linq.Parallel/INodeVisitor.cs -System.Linq.Parallel/IVisitableNode.cs -System.Linq.Parallel/OrderingEnumerator.cs -System.Linq.Parallel/ParallelExecuter.cs -System.Linq.Parallel/ParallelPartitioner.cs -System.Linq.Parallel/ParallelQueryEnumerator.cs -System.Linq.Parallel/ParallelQuickSort.cs -System.Linq.Parallel/QueryCheckerVisitor.cs -System.Linq.Parallel/QueryIsOrderedVisitor.cs -System.Linq.Parallel/QueryOptions.cs -System.Linq.Parallel/RangeList.cs -System.Linq.Parallel/RepeatList.cs -System.Linq.Parallel/ReverseList.cs -System.Linq.Parallel/StripPartitioner.cs -System.Linq.Parallel/TemporaryArea.cs -System.Linq/EnumerableExecutor.cs -System.Linq/EnumerableExecutor_T.cs -System.Linq/EnumerableQuery.cs -System.Linq/EnumerableQuery_T.cs -System.Linq/OrderedParallelQuery.cs -System.Linq/ParallelEnumerable.cs -System.Linq/ParallelExecutionMode.cs -System.Linq/ParallelMergeOptions.cs -System.Linq/ParallelQuery.cs -System.IO.MemoryMappedFiles/MemoryMappedFile.cs -System.IO.MemoryMappedFiles/MemoryMappedFileAccess.cs -System.IO.MemoryMappedFiles/MemoryMappedFileOptions.cs -System.IO.MemoryMappedFiles/MemoryMappedFileRights.cs -System.IO.MemoryMappedFiles/MemoryMappedFileSecurity.cs -System.IO.MemoryMappedFiles/MemoryMappedViewStream.cs -System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cs -Microsoft.Win32.SafeHandles/SafeMemoryMappedFileHandle.cs -Microsoft.Win32.SafeHandles/SafeMemoryMappedViewHandle.cs -System.IO/HandleInheritability.cs -System.Threading.Tasks/TaskExtensions.cs -System.Linq.Expressions/Extensions.cs -System.Linq.Expressions/ExpressionTransformer.cs -../dlr/Runtime/Microsoft.Scripting.Core/Ast/DynamicExpression.cs -../dlr/Runtime/Microsoft.Scripting.Core/Compiler/Closure.cs -System.Linq.Expressions/DynamicExpressionVisitor.cs +#include mobile_common_System.Core.dll.sources + +#include dynamic_System.Core.dll.sources diff --git a/mcs/class/System.Core/mobile_common_System.Core.dll.sources b/mcs/class/System.Core/mobile_common_System.Core.dll.sources new file mode 100644 index 00000000000..10e86231252 --- /dev/null +++ b/mcs/class/System.Core/mobile_common_System.Core.dll.sources @@ -0,0 +1,108 @@ +Assembly/AssemblyInfo.cs +System/Actions.cs +System/Funcs.cs +System/InvalidTimeZoneException.cs +System/TimeZoneInfo.AdjustmentRule.cs +System/TimeZoneInfo.cs +System/TimeZoneInfo.Serialization.cs +System/TimeZoneInfo.TransitionTime.cs +System/TimeZoneNotFoundException.cs +System/Util.cs +System.Runtime.CompilerServices/DynamicAttribute.cs +System.Runtime.CompilerServices/ExecutionScope.cs +System.Runtime.CompilerServices/ExtensionAttribute.cs +System.Runtime.CompilerServices/IStrongBox.cs +System.Runtime.CompilerServices/StrongBox_T.cs +System.Linq/Check.cs +System.Linq/Enumerable.cs +System.Linq/QueryableEnumerable.cs +System.Linq/QueryableTransformer.cs +System.Linq/Grouping.cs +System.Linq/IGrouping.cs +System.Linq/IOrderedQueryable.cs +System.Linq/IOrderedQueryable_T.cs +System.Linq/IOrderedEnumerable_T.cs +System.Linq/IQueryable.cs +System.Linq/IQueryable_T.cs +System.Linq/Lookup.cs +System.Linq/ILookup_T.cs +System.Linq/OrderedEnumerable.cs +System.Linq/OrderedSequence.cs +System.Linq/Queryable.cs +System.Linq/QuickSort.cs +System.Linq/SortContext.cs +System.Linq/SortDirection.cs +System.Linq/SortSequenceContext.cs +System.Linq/IQueryProvider.cs +System.Collections.Generic/HashSet.cs +System.Security.Cryptography/Aes.cs +System.Threading/LockRecursionPolicy.cs +System.Threading/ReaderWriterLockSlim.cs +System.Threading/ThreadLockState.cs +System.Threading/ReaderWriterLockSlimExtensions.cs +System.Linq.Parallel.QueryNodes/QueryBaseNode.cs +System.Linq.Parallel.QueryNodes/QueryCastNode.cs +System.Linq.Parallel.QueryNodes/QueryChildNode.cs +System.Linq.Parallel.QueryNodes/QueryConcatNode.cs +System.Linq.Parallel.QueryNodes/QueryDefaultEmptyNode.cs +System.Linq.Parallel.QueryNodes/QueryGroupByNode.cs +System.Linq.Parallel.QueryNodes/QueryHeadWorkerNode.cs +System.Linq.Parallel.QueryNodes/QueryJoinNode.cs +System.Linq.Parallel.QueryNodes/QueryMuxNode.cs +System.Linq.Parallel.QueryNodes/QueryOptionNode.cs +System.Linq.Parallel.QueryNodes/QueryOrderByNode.cs +System.Linq.Parallel.QueryNodes/QueryOrderGuardNode.cs +System.Linq.Parallel.QueryNodes/QueryOrderedStreamNode.cs +System.Linq.Parallel.QueryNodes/QueryReverseNode.cs +System.Linq.Parallel.QueryNodes/QuerySelectManyNode.cs +System.Linq.Parallel.QueryNodes/QuerySelectNode.cs +System.Linq.Parallel.QueryNodes/QuerySetNode.cs +System.Linq.Parallel.QueryNodes/QueryStartNode.cs +System.Linq.Parallel.QueryNodes/QueryStreamNode.cs +System.Linq.Parallel.QueryNodes/QueryWhereNode.cs +System.Linq.Parallel.QueryNodes/QueryZipNode.cs +System.Linq.Parallel.QueryNodes/SetInclusion.cs +System.Linq.Parallel.QueryNodes/WrapHelper.cs +System.Linq.Parallel/AggregationList.cs +System.Linq.Parallel/ConcurrentGrouping.cs +System.Linq.Parallel/ConcurrentLookup.cs +System.Linq.Parallel/INodeVisitor.cs +System.Linq.Parallel/IVisitableNode.cs +System.Linq.Parallel/OrderingEnumerator.cs +System.Linq.Parallel/ParallelExecuter.cs +System.Linq.Parallel/ParallelPartitioner.cs +System.Linq.Parallel/ParallelQueryEnumerator.cs +System.Linq.Parallel/ParallelQuickSort.cs +System.Linq.Parallel/QueryCheckerVisitor.cs +System.Linq.Parallel/QueryIsOrderedVisitor.cs +System.Linq.Parallel/QueryOptions.cs +System.Linq.Parallel/RangeList.cs +System.Linq.Parallel/RepeatList.cs +System.Linq.Parallel/ReverseList.cs +System.Linq.Parallel/StripPartitioner.cs +System.Linq.Parallel/TemporaryArea.cs +System.Linq/EnumerableExecutor.cs +System.Linq/EnumerableExecutor_T.cs +System.Linq/EnumerableQuery.cs +System.Linq/EnumerableQuery_T.cs +System.Linq/OrderedParallelQuery.cs +System.Linq/ParallelEnumerable.cs +System.Linq/ParallelExecutionMode.cs +System.Linq/ParallelMergeOptions.cs +System.Linq/ParallelQuery.cs +System.IO.MemoryMappedFiles/MemoryMappedFile.cs +System.IO.MemoryMappedFiles/MemoryMappedFileAccess.cs +System.IO.MemoryMappedFiles/MemoryMappedFileOptions.cs +System.IO.MemoryMappedFiles/MemoryMappedFileRights.cs +System.IO.MemoryMappedFiles/MemoryMappedFileSecurity.cs +System.IO.MemoryMappedFiles/MemoryMappedViewStream.cs +System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cs +Microsoft.Win32.SafeHandles/SafeMemoryMappedFileHandle.cs +Microsoft.Win32.SafeHandles/SafeMemoryMappedViewHandle.cs +System.IO/HandleInheritability.cs +System.Threading.Tasks/TaskExtensions.cs +System.Linq.Expressions/Extensions.cs +System.Linq.Expressions/ExpressionTransformer.cs +../dlr/Runtime/Microsoft.Scripting.Core/Ast/DynamicExpression.cs +../dlr/Runtime/Microsoft.Scripting.Core/Compiler/Closure.cs +System.Linq.Expressions/DynamicExpressionVisitor.cs diff --git a/mcs/class/System.Core/mobile_static_System.Core.dll.sources b/mcs/class/System.Core/mobile_static_System.Core.dll.sources new file mode 100644 index 00000000000..6da190e2546 --- /dev/null +++ b/mcs/class/System.Core/mobile_static_System.Core.dll.sources @@ -0,0 +1,2 @@ +#include mobile_common_System.Core.dll.sources +#include interpreter_System.Core.dll.sources diff --git a/mcs/class/System.Core/monodroid_System.Core.dll.sources b/mcs/class/System.Core/monodroid_System.Core.dll.sources index c681f5a1f8b..7228e910c42 100644 --- a/mcs/class/System.Core/monodroid_System.Core.dll.sources +++ b/mcs/class/System.Core/monodroid_System.Core.dll.sources @@ -1,4 +1,4 @@ -#include mobile_System.Core.dll.sources +#include mobile_common_System.Core.dll.sources #include dynamic_System.Core.dll.sources diff --git a/mcs/class/System.Core/monotouch_System.Core.dll.sources b/mcs/class/System.Core/monotouch_System.Core.dll.sources index fad05a08f1c..1296c8186d0 100644 --- a/mcs/class/System.Core/monotouch_System.Core.dll.sources +++ b/mcs/class/System.Core/monotouch_System.Core.dll.sources @@ -1,3 +1,3 @@ -#include mobile_System.Core.dll.sources +#include mobile_common_System.Core.dll.sources #include interpreter_System.Core.dll.sources System/TimeZoneInfo.MonoTouch.cs diff --git a/mcs/class/System.Core/xammac_System.Core.dll.sources b/mcs/class/System.Core/xammac_System.Core.dll.sources index 6ede304927a..5cd8ddf660b 100644 --- a/mcs/class/System.Core/xammac_System.Core.dll.sources +++ b/mcs/class/System.Core/xammac_System.Core.dll.sources @@ -1,4 +1,4 @@ -#include mobile_System.Core.dll.sources +#include mobile_common_System.Core.dll.sources #include dynamic_System.Core.dll.sources diff --git a/mcs/class/System.Data.Services.Client/mobile_System.Data.Services.Client.dll.sources b/mcs/class/System.Data.Services.Client/mobile_System.Data.Services.Client.dll.sources index 5ad9459d88a..37dc2990c8d 100644 --- a/mcs/class/System.Data.Services.Client/mobile_System.Data.Services.Client.dll.sources +++ b/mcs/class/System.Data.Services.Client/mobile_System.Data.Services.Client.dll.sources @@ -1,2 +1 @@ -#include System.Data.Services.Client.dll.sources -./Client/AssemblyAttributes.cs +#include net_4_5_System.Data.Services.Client.dll.sources diff --git a/mcs/class/System.Interactive.Async/Makefile b/mcs/class/System.Interactive.Async/Makefile index 70740170701..71e2b0dfc58 100644 --- a/mcs/class/System.Interactive.Async/Makefile +++ b/mcs/class/System.Interactive.Async/Makefile @@ -21,7 +21,7 @@ TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) EXTRA_DISTFILES = more_build_args -VALID_PROFILE := $(filter monotouch monodroid xammac net_4_0 net_4_5, $(PROFILE)) +VALID_PROFILE := $(filter monotouch monodroid mobile mobile_static xammac net_4_0 net_4_5, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.System.Interactive.Async.dll NO_SIGN_ASSEMBLY = yes diff --git a/mcs/class/System.Interactive.Providers/Makefile b/mcs/class/System.Interactive.Providers/Makefile index c74dccb7271..ae8749cc694 100644 --- a/mcs/class/System.Interactive.Providers/Makefile +++ b/mcs/class/System.Interactive.Providers/Makefile @@ -22,7 +22,7 @@ TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) EXTRA_DISTFILES = more_build_args -VALID_PROFILE := $(filter monotouch monodroid xammac net_4_0 net_4_5, $(PROFILE)) +VALID_PROFILE := $(filter monotouch monodroid xammac mobile mobile_static net_4_0 net_4_5, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.System.Interactive.Providers.dll NO_SIGN_ASSEMBLY = yes diff --git a/mcs/class/System.Interactive/Makefile b/mcs/class/System.Interactive/Makefile index ec5cd5c01df..1429c533ef9 100644 --- a/mcs/class/System.Interactive/Makefile +++ b/mcs/class/System.Interactive/Makefile @@ -21,7 +21,7 @@ TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) EXTRA_DISTFILES = more_build_args -VALID_PROFILE := $(filter monotouch monodroid xammac net_4_0 net_4_5, $(PROFILE)) +VALID_PROFILE := $(filter monotouch monodroid xammac mobile mobile_static net_4_0 net_4_5, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.System.Interactive.dll NO_SIGN_ASSEMBLY = yes diff --git a/mcs/class/System.Reactive.Core/Makefile b/mcs/class/System.Reactive.Core/Makefile index 3f74f8bf98e..624018c1098 100644 --- a/mcs/class/System.Reactive.Core/Makefile +++ b/mcs/class/System.Reactive.Core/Makefile @@ -35,7 +35,7 @@ TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) EXTRA_DISTFILES = more_build_args $(RESX_RESOURCES:.resources=.resx) $(PREBUILT) -VALID_PROFILE := $(filter monotouch monodroid xammac net_4_0 net_4_5, $(PROFILE)) +VALID_PROFILE := $(filter monotouch monodroid xammac mobile mobile_static net_4_0 net_4_5, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.System.Reactive.Core.dll NO_SIGN_ASSEMBLY = yes diff --git a/mcs/class/System.Reactive.Debugger/Makefile b/mcs/class/System.Reactive.Debugger/Makefile index c603f89a68a..3e308212455 100644 --- a/mcs/class/System.Reactive.Debugger/Makefile +++ b/mcs/class/System.Reactive.Debugger/Makefile @@ -24,7 +24,7 @@ TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) EXTRA_DISTFILES = more_build_args -VALID_PROFILE := $(filter monotouch monodroid xammac net_4_0 net_4_5, $(PROFILE)) +VALID_PROFILE := $(filter monotouch monodroid xammac mobile mobile_static net_4_0 net_4_5, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.System.Reactive.Debugger.dll NO_SIGN_ASSEMBLY = yes diff --git a/mcs/class/System.Reactive.Experimental/Makefile b/mcs/class/System.Reactive.Experimental/Makefile index 234a63b12d9..834240acccc 100644 --- a/mcs/class/System.Reactive.Experimental/Makefile +++ b/mcs/class/System.Reactive.Experimental/Makefile @@ -24,7 +24,7 @@ TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) EXTRA_DISTFILES = more_build_args -VALID_PROFILE := $(filter monotouch monodroid xammac net_4_0 net_4_5, $(PROFILE)) +VALID_PROFILE := $(filter monotouch monodroid xammac mobile mobile_static net_4_0 net_4_5, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.System.Reactive.Experimental.dll NO_SIGN_ASSEMBLY = yes diff --git a/mcs/class/System.Reactive.Interfaces/Makefile b/mcs/class/System.Reactive.Interfaces/Makefile index acee40d2960..fae46634976 100644 --- a/mcs/class/System.Reactive.Interfaces/Makefile +++ b/mcs/class/System.Reactive.Interfaces/Makefile @@ -21,7 +21,7 @@ TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) EXTRA_DISTFILES = more_build_args -VALID_PROFILE := $(filter monotouch monodroid xammac net_4_0 net_4_5, $(PROFILE)) +VALID_PROFILE := $(filter monotouch monodroid xammac mobile mobile_static net_4_0 net_4_5, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.System.Reactive.Interfaces.dll NO_SIGN_ASSEMBLY = yes diff --git a/mcs/class/System.Reactive.Linq/Makefile b/mcs/class/System.Reactive.Linq/Makefile index 18a3360dafe..3906cfc6adc 100644 --- a/mcs/class/System.Reactive.Linq/Makefile +++ b/mcs/class/System.Reactive.Linq/Makefile @@ -36,7 +36,7 @@ TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) EXTRA_DISTFILES = more_build_args $(RESX_RESOURCES:.resources=.resx) $(PREBUILT) -VALID_PROFILE := $(filter monotouch monodroid xammac net_4_0 net_4_5, $(PROFILE)) +VALID_PROFILE := $(filter monotouch monodroid xammac mobile mobile_static net_4_0 net_4_5, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.System.Reactive.Linq.dll NO_SIGN_ASSEMBLY = yes diff --git a/mcs/class/System.Reactive.PlatformServices/Makefile b/mcs/class/System.Reactive.PlatformServices/Makefile index 187dd7702ff..6fccc274c42 100644 --- a/mcs/class/System.Reactive.PlatformServices/Makefile +++ b/mcs/class/System.Reactive.PlatformServices/Makefile @@ -42,7 +42,7 @@ TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) -r:Mono.Reactive.Tests.dll EXTRA_DISTFILES = more_build_args $(RESX_RESOURCES:.resources=.resx) $(PREBUILT) -VALID_PROFILE := $(filter monotouch monodroid xammac net_4_0 net_4_5, $(PROFILE)) +VALID_PROFILE := $(filter monotouch monodroid xammac mobile mobile_static net_4_0 net_4_5, $(PROFILE)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.System.Reactive.PlatformServices.dll NO_SIGN_ASSEMBLY = yes diff --git a/mcs/class/System.XML/Makefile b/mcs/class/System.XML/Makefile index c52a56468ff..f44d93a6f0e 100644 --- a/mcs/class/System.XML/Makefile +++ b/mcs/class/System.XML/Makefile @@ -13,7 +13,7 @@ ifdef USE_BOOT_COMPILE LIBRARY_COMPILE = $(BOOT_COMPILE) endif -PROFILE_ANY_MOBILE := $(filter monotouch monotouch_runtime monodroid xammac, $(PROFILE)) +PROFILE_ANY_MOBILE := $(filter monotouch monotouch_runtime monodroid xammac mobile mobile_static, $(PROFILE)) LIB_MCS_FLAGS = -r:$(corlib) -r:System.dll -nowarn:0618,0612,0642 ifeq (2.1, $(FRAMEWORK_VERSION)) @@ -127,4 +127,4 @@ ifneq ($(PROFILE),basic) csproj-local: $(MAKE) csproj-local intermediate=bare/ endif -endif \ No newline at end of file +endif diff --git a/mcs/class/System.Xaml/Makefile b/mcs/class/System.Xaml/Makefile index 17d16132910..5104e87b042 100644 --- a/mcs/class/System.Xaml/Makefile +++ b/mcs/class/System.Xaml/Makefile @@ -18,7 +18,7 @@ TEST_EXTRA_DISTFILES = \ Test/XmlFiles/*.xml \ Test/XmlFiles/*.xaml -VALID_PROFILE := $(filter 4 monodroid monotouch, $(FRAMEWORK_VERSION_MAJOR)) +VALID_PROFILE := $(filter 4 monodroid monotouch mobile mobile_static, $(FRAMEWORK_VERSION_MAJOR)) ifndef VALID_PROFILE LIBRARY_NAME = dummy-System.Xaml.dll NO_INSTALL = yes diff --git a/mcs/class/System/Makefile b/mcs/class/System/Makefile index 50bc1fce7d1..cfa7564d4b6 100644 --- a/mcs/class/System/Makefile +++ b/mcs/class/System/Makefile @@ -24,14 +24,10 @@ TEST_MCS_FLAGS = -r:System.Drawing.dll -r:Mono.Security.dll -r:System.Data -r:Sy LIB_MCS_FLAGS = -nowarn:618 -d:CONFIGURATION_2_0 -unsafe $(RESOURCE_FILES:%=-resource:%) TEST_MCS_FLAGS += -r:System.Configuration -PROFILE_ANY_MOBILE := $(filter monotouch monotouch_runtime monodroid xammac, $(PROFILE)) -NOT_SL := $(filter net_2_0 net_4_0 net_4_5 monotouch_runtime mobile xammac, $(PROFILE)) +PROFILE_ANY_MOBILE := $(filter monotouch monotouch_runtime monodroid xammaci mobile mobile_static, $(PROFILE)) ifeq (2.1, $(FRAMEWORK_VERSION)) LIB_MCS_FLAGS += -d:INSIDE_SYSTEM -ifeq (moonlight_raw, $(PROFILE)) -LIB_MCS_FLAGS += -d:SECURITY_DEP -endif endif ifeq (monotouch, $(subst _runtime,,$(PROFILE))) LIB_MCS_FLAGS += -d:SECURITY_DEP @@ -154,4 +150,4 @@ csproj-local: $(MAKE) csproj-local intermediate=bare/ $(MAKE) csproj-local intermediate=secxml/ endif -endif \ No newline at end of file +endif From 5dbf97e66057f8626c53fcea30f1988d6627e5a2 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 16 Sep 2014 23:17:39 -0400 Subject: [PATCH 149/543] [jit] Make calls from gshared to gsharedvt sharable methods indirect since otherwise at runtime we might find an instantiation and we cannot patch the call, leading to performance problems. Fixes #23021. --- mono/mini/method-to-ir.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 5dd518b9c0b..f035037d64e 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -8474,10 +8474,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } /* Generic sharing */ - /* FIXME: only do this for generic methods if - they are not shared! */ + + /* + * Use this if the callee is gsharedvt sharable too, since + * at runtime we might find an instantiation so the call cannot + * be patched (the 'no_patch' code path in mini-trampolines.c). + */ if (context_used && !imt_arg && !array_rank && !delegate_invoke && - (!mono_method_is_generic_sharable (cmethod, TRUE) || + (!mono_method_is_generic_sharable_full (cmethod, TRUE, FALSE, FALSE) || !mono_class_generic_sharing_enabled (cmethod->klass)) && (!virtual || MONO_METHOD_IS_FINAL (cmethod) || !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))) { From 4f719f9ce95a8afa765d6b17c2ee1f06506d49a1 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Wed, 17 Sep 2014 11:19:05 +0200 Subject: [PATCH 150/543] [xbuild] Fix few crashes when task loading fails --- .../ConsoleLogger.cs | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConsoleLogger.cs b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConsoleLogger.cs index 5fb7d21899c..0d776b9fbb2 100644 --- a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConsoleLogger.cs +++ b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConsoleLogger.cs @@ -1018,13 +1018,27 @@ public void ExecuteFinishedHandler (BuildStatusEventArgs finished_args) if (!StartHandlerHasExecuted) return; - if (EventArgs is ProjectStartedEventArgs) - ConsoleLogger.ProjectFinishedHandler (Sender, finished_args as ProjectFinishedEventArgs); - else if (EventArgs is TargetStartedEventArgs) - ConsoleLogger.TargetFinishedHandler (Sender, finished_args as TargetFinishedEventArgs); - else if (EventArgs is TaskStartedEventArgs) - ConsoleLogger.TaskFinishedHandler (Sender, finished_args as TaskFinishedEventArgs); - else if (!(EventArgs is BuildStartedEventArgs)) + if (EventArgs is ProjectStartedEventArgs) { + var pfa = finished_args as ProjectFinishedEventArgs; + // FIXME: BuildFinishedHandlerActual sends us BuildFinishedEventArgs via PopEvent + if (pfa == null) + return; + + ConsoleLogger.ProjectFinishedHandler (Sender, pfa); + } else if (EventArgs is TargetStartedEventArgs) { + var fa = finished_args as TargetFinishedEventArgs; + // FIXME: BuildFinishedHandlerActual sends us BuildFinishedEventArgs via PopEvent + if (fa == null) + return; + + ConsoleLogger.TargetFinishedHandler (Sender, fa); + } else if (EventArgs is TaskStartedEventArgs) { + // FIXME: BuildFinishedHandlerActual sends us BuildFinishedEventArgs via PopEvent + if (!(finished_args is TaskFinishedEventArgs)) + return; + + ConsoleLogger.TaskFinishedHandler (Sender, (TaskFinishedEventArgs) finished_args); + } else if (!(EventArgs is BuildStartedEventArgs)) throw new InvalidOperationException ("Unexpected event on the stack, type: " + EventArgs.GetType ()); } } From 753f233a31f93506d18ee6efe0d4e1c3b505790d Mon Sep 17 00:00:00 2001 From: Andoni Morales Alastruey Date: Wed, 17 Sep 2014 16:17:33 +0200 Subject: [PATCH 151/543] [mkbundle] Fix check for dos2unix This fixes the command to check for dos2unix and makes mkbundle usable again with mingw. We need first to redirect the standard input, otherwise the check always fails with an InvalidOperationException and set CreateNoWindow=false to avoid spawning a new window. --- mcs/tools/mkbundle/mkbundle.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mcs/tools/mkbundle/mkbundle.cs b/mcs/tools/mkbundle/mkbundle.cs index f13ce63d029..6e118995377 100755 --- a/mcs/tools/mkbundle/mkbundle.cs +++ b/mcs/tools/mkbundle/mkbundle.cs @@ -715,9 +715,14 @@ static int Execute (string cmdLine) if (use_dos2unix == null) { use_dos2unix = false; try { - var dos2unix = Process.Start ("dos2unix"); + var info = new ProcessStartInfo ("dos2unix"); + info.CreateNoWindow = true; + info.RedirectStandardInput = true; + info.UseShellExecute = false; + var dos2unix = Process.Start (info); dos2unix.StandardInput.WriteLine ("aaa"); dos2unix.StandardInput.WriteLine ("\u0004"); + dos2unix.StandardInput.Close (); dos2unix.WaitForExit (); if (dos2unix.ExitCode == 0) use_dos2unix = true; From 818b81ef40c7a216f0178124969a5b8e8a866dd0 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Wed, 17 Sep 2014 12:56:44 -0400 Subject: [PATCH 152/543] [runtime] Use statfs(2) on Android. Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=23077 Reverts commit 53ce92470. Commit 53ce92470 disabled use of statfs(2) on Android, for unspecified reasons. (My *suspicion* is that the Android version mono was originally ported to didn't have statfs(2), but I can neither confirm nor deny that guess.) Android has supported statfs(2) since API-4 Android v1.6 (in that statfs(2) is in the header files); what's missing is MNT_RDONLY. What IS present is MS_RDONLY, which appears to serve the same purpose. Re-enable use of statfs(2) and use MS_RDONLY when building against the Android NDK. --- mono/io-layer/io.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mono/io-layer/io.c b/mono/io-layer/io.c index 169cb07617a..03672d4197e 100644 --- a/mono/io-layer/io.c +++ b/mono/io-layer/io.c @@ -3904,7 +3904,7 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf) } #endif -#if (defined(HAVE_STATVFS) || defined(HAVE_STATFS)) && !defined(PLATFORM_ANDROID) +#if defined(HAVE_STATVFS) || defined(HAVE_STATFS) gboolean GetDiskFreeSpaceEx(const gunichar2 *path_name, WapiULargeInteger *free_bytes_avail, WapiULargeInteger *total_number_of_bytes, WapiULargeInteger *total_number_of_free_bytes) @@ -3943,7 +3943,11 @@ gboolean GetDiskFreeSpaceEx(const gunichar2 *path_name, WapiULargeInteger *free_ block_size = fsstat.f_frsize; #elif defined(HAVE_STATFS) ret = statfs (utf8_path_name, &fsstat); +#if defined (MNT_RDONLY) isreadonly = ((fsstat.f_flags & MNT_RDONLY) == MNT_RDONLY); +#elif defined (MS_RDONLY) + isreadonly = ((fsstat.f_flags & MS_RDONLY) == MS_RDONLY); +#endif block_size = fsstat.f_bsize; #endif } while(ret == -1 && errno == EINTR); From d62679a4a4d62fd89248f945629bdcb488c3ac1a Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Wed, 17 Sep 2014 20:20:35 +0200 Subject: [PATCH 153/543] [xbuild] Workaround for issues with CreateItem task where metadata are not generated due to up-to-data inputs. Fixes #23022 --- .../TargetBatchingImpl.cs | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/TargetBatchingImpl.cs b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/TargetBatchingImpl.cs index 76284d1660e..8597b026b34 100644 --- a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/TargetBatchingImpl.cs +++ b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/TargetBatchingImpl.cs @@ -99,8 +99,12 @@ bool RunTargetWithBucket (Dictionary bucket, Target targ try { TaskExecutionMode taskExecutionMode; string reason; - if (!BuildTargetNeeded (out reason)) { + bool skip_completely; + if (!BuildTargetNeeded (out reason, out skip_completely)) { LogTargetSkipped (target, reason); + if (skip_completely) + return true; + taskExecutionMode = TaskExecutionMode.SkipAndSetOutput; } else { taskExecutionMode = TaskExecutionMode.Complete; @@ -113,8 +117,27 @@ bool RunTargetWithBucket (Dictionary bucket, Target targ //FIXME: parsing attributes repeatedly IBuildTask bt = target.BuildTasks [i]; + // HACK: need some form of cross references checks + var tem = taskExecutionMode; + if (tem == TaskExecutionMode.SkipAndSetOutput) { + var bti = bt as BuildTask; + + // + // BuildTargetNeeded checks only files timestamps but ignores any metadata dependencies + // that way we can end up in the situation when output metadata are populated but from + // incomplete dependencies. + // + // E.g. + // + // + // + // + if (bti != null && bti.Name == "CreateItem") + tem = TaskExecutionMode.Complete; + } + TaskBatchingImpl batchingImpl = new TaskBatchingImpl (project); - bool task_result = batchingImpl.Build (bt, taskExecutionMode, out executeOnErrors); + bool task_result = batchingImpl.Build (bt, tem, out executeOnErrors); if (task_result) continue; @@ -149,15 +172,17 @@ void ParseTargetAttributes (Target target) ParseAttribute (outputs); } - bool BuildTargetNeeded (out string reason) + bool BuildTargetNeeded (out string reason, out bool skipCompletely) { reason = String.Empty; ITaskItem [] inputFiles; ITaskItem [] outputFiles; DateTime youngestInput, oldestOutput; + skipCompletely = false; - if (String.IsNullOrEmpty (inputs.Trim ())) + if (String.IsNullOrEmpty (inputs.Trim ())) { return true; + } if (String.IsNullOrEmpty (outputs.Trim ())) { project.ParentEngine.LogError ("Target {0} has inputs but no outputs specified.", name); @@ -178,6 +203,7 @@ bool BuildTargetNeeded (out string reason) } if (inputFiles == null || inputFiles.Length == 0) { + skipCompletely = true; reason = String.Format ("No input files were specified for target {0}, skipping.", name); return false; } From 28179361ecc48233b3bd67e95f4b4ed008c677b4 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 17 Sep 2014 15:20:59 -0400 Subject: [PATCH 154/543] [sdb] Implement support for win64. --- mono/mini/mini-amd64.c | 14 ++++++++++---- mono/mini/mini-amd64.h | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 3cefc22c87d..212b8a283c3 100644 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -8425,8 +8425,11 @@ gboolean mono_arch_is_breakpoint_event (void *info, void *sigctx) { #ifdef HOST_WIN32 - EXCEPTION_RECORD* einfo = (EXCEPTION_RECORD*)info; - return FALSE; + EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; + if (einfo->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && einfo->ExceptionInformation [1] == bp_trigger_page) + return TRUE; + else + return FALSE; #else siginfo_t* sinfo = (siginfo_t*) info; /* Sometimes the address is off by 4 */ @@ -8486,8 +8489,11 @@ gboolean mono_arch_is_single_step_event (void *info, void *sigctx) { #ifdef HOST_WIN32 - EXCEPTION_RECORD* einfo = (EXCEPTION_RECORD*)info; - return FALSE; + EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; + if (einfo->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && einfo->ExceptionInformation [1] == ss_trigger_page) + return TRUE; + else + return FALSE; #else siginfo_t* sinfo = (siginfo_t*) info; /* Sometimes the address is off by 4 */ diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index b7c974e3acd..e942f578226 100644 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -381,7 +381,7 @@ typedef struct { #define MONO_ARCH_HAVE_GET_TRAMPOLINES 1 #define MONO_ARCH_AOT_SUPPORTED 1 -#if !defined( HOST_WIN32 ) && !defined( __native_client__ ) +#if !defined( __native_client__ ) #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1 #endif From 4fc8068d2a112feed50b32da1948920b173df8cb Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 17 Sep 2014 18:25:00 -0400 Subject: [PATCH 155/543] [runtime] Implement the new suspend infrastructure on windows. --- mono/mini/mini-windows.c | 91 ++++++++++++++++++++++++- mono/utils/mono-context.h | 2 - mono/utils/mono-threads-windows.c | 108 +++++++++++++++++++++++++++++- mono/utils/mono-threads.c | 3 +- 4 files changed, 194 insertions(+), 10 deletions(-) diff --git a/mono/mini/mini-windows.c b/mono/mini/mini-windows.c index c43b1d0102f..125b4e4e7dc 100644 --- a/mono/mini/mini-windows.c +++ b/mono/mini/mini-windows.c @@ -123,7 +123,7 @@ mono_runtime_setup_stat_profiler (void) if (timeBeginPeriod (1) != TIMERR_NOERROR) return; - if ((win32_timer = timeSetEvent (1, 0, win32_time_proc, 0, TIME_PERIODIC)) == 0) { + if ((win32_timer = timeSetEvent (1, 0, (LPTIMECALLBACK)win32_time_proc, (DWORD_PTR)NULL, TIME_PERIODIC)) == 0) { timeEndPeriod (1); return; } @@ -137,7 +137,92 @@ mono_runtime_shutdown_stat_profiler (void) gboolean mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info) { - g_error ("Windows systems haven't been ported to support mono_thread_state_init_from_handle"); - return FALSE; + DWORD id = mono_thread_info_get_tid (info); + HANDLE handle; + CONTEXT context; + DWORD result; + MonoContext *ctx; + MonoJitTlsData *jit_tls; + void *domain; + MonoLMF *lmf = NULL; + gpointer *addr; + + tctx->valid = FALSE; + tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = NULL; + tctx->unwind_data [MONO_UNWIND_DATA_LMF] = NULL; + tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = NULL; + + g_assert (id != GetCurrentThreadId ()); + + handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id); + g_assert (handle); + + context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; + + if (!GetThreadContext (handle, &context)) { + CloseHandle (handle); + return FALSE; + } + + g_assert (context.ContextFlags & CONTEXT_INTEGER); + g_assert (context.ContextFlags & CONTEXT_CONTROL); + + ctx = &tctx->ctx; + + memset (ctx, 0, sizeof (MonoContext)); +#ifdef TARGET_AMD64 + ctx->rip = context.Rip; + ctx->rax = context.Rax; + ctx->rcx = context.Rcx; + ctx->rdx = context.Rdx; + ctx->rbx = context.Rbx; + ctx->rsp = context.Rsp; + ctx->rbp = context.Rbp; + ctx->rsi = context.Rsi; + ctx->rdi = context.Rdi; + ctx->r8 = context.R8; + ctx->r9 = context.R9; + ctx->r10 = context.R10; + ctx->r11 = context.R11; + ctx->r12 = context.R12; + ctx->r13 = context.R13; + ctx->r14 = context.R14; + ctx->r15 = context.R15; +#else + ctx->edi = context.Edi; + ctx->esi = context.Esi; + ctx->ebx = context.Ebx; + ctx->edx = context.Edx; + ctx->ecx = context.Ecx; + ctx->eax = context.Eax; + ctx->ebp = context.Ebp; + ctx->esp = context.Esp; +#endif + + /* mono_set_jit_tls () sets this */ + jit_tls = mono_thread_info_tls_get (info, TLS_KEY_JIT_TLS); + /* SET_APPDOMAIN () sets this */ + domain = mono_thread_info_tls_get (info, TLS_KEY_DOMAIN); + + /*Thread already started to cleanup, can no longer capture unwind state*/ + if (!jit_tls || !domain) + return FALSE; + + /* + * The current LMF address is kept in a separate TLS variable, and its hard to read its value without + * arch-specific code. But the address of the TLS variable is stored in another TLS variable which + * can be accessed through MonoThreadInfo. + */ + /* mono_set_lmf_addr () sets this */ + addr = mono_thread_info_tls_get (info, TLS_KEY_LMF_ADDR); + if (addr) + lmf = *addr; + + tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = domain; + tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls; + tctx->unwind_data [MONO_UNWIND_DATA_LMF] = lmf; + tctx->valid = TRUE; + + return TRUE; } diff --git a/mono/utils/mono-context.h b/mono/utils/mono-context.h index 11254802fc4..1a38146b324 100755 --- a/mono/utils/mono-context.h +++ b/mono/utils/mono-context.h @@ -236,9 +236,7 @@ extern void mono_context_get_current (void *); : "rdx", "memory") #endif -#if !defined(HOST_WIN32) #define MONO_ARCH_HAS_MONO_CONTEXT 1 -#endif #elif (defined(__arm__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM)) /* defined(__x86_64__) */ diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index d0d81c5b8f4..c9ba893f410 100755 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -20,10 +20,23 @@ mono_threads_init_platform (void) { } +static void CALLBACK +interrupt_apc (ULONG_PTR param) +{ +} + void mono_threads_core_interrupt (MonoThreadInfo *info) { - g_assert (0); + DWORD id = mono_thread_info_get_tid (info); + HANDLE handle; + + handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id); + g_assert (handle); + + QueueUserAPC ((PAPCFUNC)interrupt_apc, handle, (ULONG_PTR)NULL); + + CloseHandle (handle); } void @@ -46,13 +59,102 @@ mono_threads_core_self_suspend (MonoThreadInfo *info) gboolean mono_threads_core_suspend (MonoThreadInfo *info) { - g_assert_not_reached (); + DWORD id = mono_thread_info_get_tid (info); + HANDLE handle; + DWORD result; + gboolean res; + + g_assert (id != GetCurrentThreadId ()); + + handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id); + g_assert (handle); + + result = SuspendThread (handle); + if (result == (DWORD)-1) { + fprintf (stderr, "could not suspend thread %x (handle %p): %d\n", id, handle, GetLastError ()); fflush (stderr); + CloseHandle (handle); + return FALSE; + } + + CloseHandle (handle); + + res = mono_threads_get_runtime_callbacks ()->thread_state_init_from_handle (&info->suspend_state, info); + g_assert (res); + + return TRUE; } gboolean mono_threads_core_resume (MonoThreadInfo *info) { - g_assert_not_reached (); + DWORD id = mono_thread_info_get_tid (info); + HANDLE handle; + DWORD result; + + handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id); + g_assert (handle); + + if (info->async_target) { + MonoContext ctx; + CONTEXT context; + gboolean res; + + ctx = info->suspend_state.ctx; + mono_threads_get_runtime_callbacks ()->setup_async_callback (&ctx, info->async_target, info->user_data); + info->async_target = info->user_data = NULL; + + context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; + + if (!GetThreadContext (handle, &context)) { + CloseHandle (handle); + return FALSE; + } + + g_assert (context.ContextFlags & CONTEXT_INTEGER); + g_assert (context.ContextFlags & CONTEXT_CONTROL); + + // FIXME: This should be in mini-windows.c + context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; +#ifdef TARGET_AMD64 + context.Rip = ctx.rip; + context.Rax = ctx.rax; + context.Rcx = ctx.rcx; + context.Rdx = ctx.rdx; + context.Rbx = ctx.rbx; + context.Rsp = ctx.rsp; + context.Rbp = ctx.rbp; + context.Rsi = ctx.rsi; + context.Rdi = ctx.rdi; + context.R8 = ctx.r8; + context.R9 = ctx.r9; + context.R10 = ctx.r10; + context.R11 = ctx.r11; + context.R12 = ctx.r12; + context.R13 = ctx.r13; + context.R14 = ctx.r14; + context.R15 = ctx.r15; +#else + context.Eip = ctx.eip; + context.Edi = ctx.edi; + context.Esi = ctx.esi; + context.Ebx = ctx.ebx; + context.Edx = ctx.edx; + context.Ecx = ctx.ecx; + context.Eax = ctx.eax; + context.Ebp = ctx.ebp; + context.Esp = ctx.esp; +#endif + + res = SetThreadContext (handle, &context); + g_assert (res); + } + + result = ResumeThread (handle); + g_assert (result != (DWORD)-1); + + CloseHandle (handle); + + return result != (DWORD)-1; } void diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index cbb768aea8c..0b754ab4a61 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -731,9 +731,8 @@ mono_thread_info_new_interrupt_enabled (void) #if defined (HAVE_BOEHM_GC) && !defined (USE_INCLUDED_LIBGC) return FALSE; #endif - /*port not done*/ #if defined(HOST_WIN32) - return FALSE; + return !disable_new_interrupt; #endif #if defined (__i386__) return !disable_new_interrupt; From 8ed233ef0627546c6a825c317f6109c807dbc965 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 17 Sep 2014 22:37:18 -0400 Subject: [PATCH 156/543] [runtime] Use the windows CONTEXT<->MonoContext conversion code to mono-context.c, simplify some code. --- mono/mini/exceptions-amd64.c | 43 ++----------------- mono/mini/exceptions-x86.c | 36 ++-------------- mono/mini/mini-windows.c | 29 +------------ mono/mini/mini.h | 1 + mono/utils/mono-context.c | 71 +++++++++++++++++++++++++++++++ mono/utils/mono-context.h | 11 +++++ mono/utils/mono-threads-windows.c | 33 +------------- 7 files changed, 93 insertions(+), 131 deletions(-) diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 12b4ef31dde..592969a5256 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -45,7 +45,7 @@ LPTOP_LEVEL_EXCEPTION_FILTER mono_old_win_toplevel_exception_filter; void *mono_win_vectored_exception_handle; #define W32_SEH_HANDLE_EX(_ex) \ - if (_ex##_handler) _ex##_handler(0, ep, sctx) + if (_ex##_handler) _ex##_handler(0, ep, ctx) static LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep) { @@ -68,7 +68,6 @@ static LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) { EXCEPTION_RECORD* er; CONTEXT* ctx; - MonoContext* sctx; LONG res; MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); @@ -81,22 +80,6 @@ static LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) er = ep->ExceptionRecord; ctx = ep->ContextRecord; - sctx = g_malloc(sizeof(MonoContext)); - - /* Copy Win32 context to UNIX style context */ - sctx->rax = ctx->Rax; - sctx->rbx = ctx->Rbx; - sctx->rcx = ctx->Rcx; - sctx->rdx = ctx->Rdx; - sctx->rbp = ctx->Rbp; - sctx->rsp = ctx->Rsp; - sctx->rsi = ctx->Rsi; - sctx->rdi = ctx->Rdi; - sctx->rip = ctx->Rip; - sctx->r12 = ctx->R12; - sctx->r13 = ctx->R13; - sctx->r14 = ctx->R14; - sctx->r15 = ctx->R15; switch (er->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: @@ -126,30 +109,8 @@ static LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) * can correctly chain the exception. */ res = EXCEPTION_CONTINUE_SEARCH; - } else { - /* Copy context back */ - /* Nonvolatile */ - ctx->Rsp = sctx->rsp; - ctx->Rdi = sctx->rdi; - ctx->Rsi = sctx->rsi; - ctx->Rbx = sctx->rbx; - ctx->Rbp = sctx->rbp; - ctx->R12 = sctx->r12; - ctx->R13 = sctx->r13; - ctx->R14 = sctx->r14; - ctx->R15 = sctx->r15; - ctx->Rip = sctx->rip; - - /* Volatile But should not matter?*/ - ctx->Rax = sctx->rax; - ctx->Rcx = sctx->rcx; - ctx->Rdx = sctx->rdx; } - /* TODO: Find right place to free this in stack overflow case */ - if (er->ExceptionCode != EXCEPTION_STACK_OVERFLOW) - g_free (sctx); - return res; } @@ -841,6 +802,8 @@ mono_arch_ip_from_context (void *sigctx) ucontext_t *ctx = (ucontext_t*)sigctx; return (gpointer)UCONTEXT_REG_RIP (ctx); +#elif defined(HOST_WIN32) + return ((CONTEXT*)sigctx)->Rip; #else MonoContext *ctx = sigctx; return (gpointer)ctx->rip; diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index d335d7ea5c6..9c46d34bd20 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -49,7 +49,7 @@ extern int (*gUnhandledExceptionHandler)(EXCEPTION_POINTERS*); #endif #define W32_SEH_HANDLE_EX(_ex) \ - if (_ex##_handler) _ex##_handler(0, ep, sctx) + if (_ex##_handler) _ex##_handler(0, ep, ctx) LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep) { @@ -189,7 +189,6 @@ LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) { EXCEPTION_RECORD* er; CONTEXT* ctx; - struct sigcontext* sctx; LONG res; MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); @@ -202,18 +201,6 @@ LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) er = ep->ExceptionRecord; ctx = ep->ContextRecord; - sctx = g_malloc(sizeof(struct sigcontext)); - - /* Copy Win32 context to UNIX style context */ - sctx->eax = ctx->Eax; - sctx->ebx = ctx->Ebx; - sctx->ecx = ctx->Ecx; - sctx->edx = ctx->Edx; - sctx->ebp = ctx->Ebp; - sctx->esp = ctx->Esp; - sctx->esi = ctx->Esi; - sctx->edi = ctx->Edi; - sctx->eip = ctx->Eip; switch (er->ExceptionCode) { case EXCEPTION_STACK_OVERFLOW: @@ -246,23 +233,8 @@ LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) * can correctly chain the exception. */ res = EXCEPTION_CONTINUE_SEARCH; - } else { - /* Copy context back */ - ctx->Eax = sctx->eax; - ctx->Ebx = sctx->ebx; - ctx->Ecx = sctx->ecx; - ctx->Edx = sctx->edx; - ctx->Ebp = sctx->ebp; - ctx->Esp = sctx->esp; - ctx->Esi = sctx->esi; - ctx->Edi = sctx->edi; - ctx->Eip = sctx->eip; } - /* TODO: Find right place to free this in stack overflow case */ - if (er->ExceptionCode != EXCEPTION_STACK_OVERFLOW) - g_free (sctx); - return res; } @@ -952,15 +924,15 @@ mono_arch_ip_from_context (void *sigctx) #if defined(__native_client__) printf("WARNING: mono_arch_ip_from_context() called!\n"); return (NULL); -#else -#ifdef MONO_ARCH_USE_SIGACTION +#elif defined(MONO_ARCH_USE_SIGACTION) ucontext_t *ctx = (ucontext_t*)sigctx; return (gpointer)UCONTEXT_REG_EIP (ctx); +#elif defined(HOST_WIN32) + return ((CONTEXT*)sigctx)->Eip; #else struct sigcontext *ctx = sigctx; return (gpointer)ctx->SC_EIP; #endif -#endif /* __native_client__ */ } /* diff --git a/mono/mini/mini-windows.c b/mono/mini/mini-windows.c index 125b4e4e7dc..614f7af6fed 100644 --- a/mono/mini/mini-windows.c +++ b/mono/mini/mini-windows.c @@ -170,34 +170,7 @@ mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo ctx = &tctx->ctx; memset (ctx, 0, sizeof (MonoContext)); -#ifdef TARGET_AMD64 - ctx->rip = context.Rip; - ctx->rax = context.Rax; - ctx->rcx = context.Rcx; - ctx->rdx = context.Rdx; - ctx->rbx = context.Rbx; - ctx->rsp = context.Rsp; - ctx->rbp = context.Rbp; - ctx->rsi = context.Rsi; - ctx->rdi = context.Rdi; - ctx->r8 = context.R8; - ctx->r9 = context.R9; - ctx->r10 = context.R10; - ctx->r11 = context.R11; - ctx->r12 = context.R12; - ctx->r13 = context.R13; - ctx->r14 = context.R14; - ctx->r15 = context.R15; -#else - ctx->edi = context.Edi; - ctx->esi = context.Esi; - ctx->ebx = context.Ebx; - ctx->edx = context.Edx; - ctx->ecx = context.Ecx; - ctx->eax = context.Eax; - ctx->ebp = context.Ebp; - ctx->esp = context.Esp; -#endif + mono_sigctx_to_monoctx (&context, ctx); /* mono_set_jit_tls () sets this */ jit_tls = mono_thread_info_tls_get (info, TLS_KEY_JIT_TLS); diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 4bb5ad1d7d4..31f7ee138e0 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2822,6 +2822,7 @@ void mono_cross_helpers_run (void) MONO_INTERNAL; #ifndef GET_CONTEXT #ifdef HOST_WIN32 +/* seh_vectored_exception_handler () passes in a CONTEXT* */ #define GET_CONTEXT \ void *ctx = context; #else diff --git a/mono/utils/mono-context.c b/mono/utils/mono-context.c index bc0286485fc..02fa8c8701c 100644 --- a/mono/utils/mono-context.c +++ b/mono/utils/mono-context.c @@ -15,6 +15,10 @@ #include +#ifdef HOST_WIN32 +#include +#endif + #ifdef __sun #define REG_EAX EAX #define REG_EBX EBX @@ -53,6 +57,17 @@ mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) mctx->esi = UCONTEXT_REG_ESI (ctx); mctx->edi = UCONTEXT_REG_EDI (ctx); mctx->eip = UCONTEXT_REG_EIP (ctx); +#elif defined(HOST_WIN32) + CONTEXT *context = (CONTEXT*)sigctx; + + mctx->edi = context->Edi; + mctx->esi = context->Esi; + mctx->ebx = context->Ebx; + mctx->edx = context->Edx; + mctx->ecx = context->Ecx; + mctx->eax = context->Eax; + mctx->ebp = context->Ebp; + mctx->esp = context->Esp; #else struct sigcontext *ctx = (struct sigcontext *)sigctx; @@ -85,6 +100,18 @@ mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) UCONTEXT_REG_ESI (ctx) = mctx->esi; UCONTEXT_REG_EDI (ctx) = mctx->edi; UCONTEXT_REG_EIP (ctx) = mctx->eip; +#elif defined(HOST_WIN32) + CONTEXT *context = (CONTEXT*)sigctx; + + context->Eip = mctx->eip; + context->Edi = mctx->edi; + context->Esi = mctx->esi; + context->Ebx = mctx->ebx; + context->Edx = mctx->edx; + context->Ecx = mctx->ecx; + context->Eax = mctx->eax; + context->Ebp = mctx->ebp; + context->Esp = mctx->esp; #else struct sigcontext *ctx = (struct sigcontext *)sigctx; @@ -104,6 +131,10 @@ mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) #include +#ifdef HOST_WIN32 +#include +#endif + void mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) { @@ -131,6 +162,26 @@ mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) mctx->r14 = UCONTEXT_REG_R14 (ctx); mctx->r15 = UCONTEXT_REG_R15 (ctx); mctx->rip = UCONTEXT_REG_RIP (ctx); +#elif defined(HOST_WIN32) + CONTEXT *context = (CONTEXT*)sigctx; + + mctx->rip = context->Rip; + mctx->rax = context->Rax; + mctx->rcx = context->Rcx; + mctx->rdx = context->Rdx; + mctx->rbx = context->Rbx; + mctx->rsp = context->Rsp; + mctx->rbp = context->Rbp; + mctx->rsi = context->Rsi; + mctx->rdi = context->Rdi; + mctx->r8 = context->R8; + mctx->r9 = context->R9; + mctx->r10 = context->R10; + mctx->r11 = context->R11; + mctx->r12 = context->R12; + mctx->r13 = context->R13; + mctx->r14 = context->R14; + mctx->r15 = context->R15; #else MonoContext *ctx = (MonoContext *)sigctx; @@ -181,6 +232,26 @@ mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) UCONTEXT_REG_R14 (ctx) = mctx->r14; UCONTEXT_REG_R15 (ctx) = mctx->r15; UCONTEXT_REG_RIP (ctx) = mctx->rip; +#elif defined(HOST_WIN32) + CONTEXT *context = (CONTEXT*)sigctx; + + context->Rip = mctx->rip; + context->Rax = mctx->rax; + context->Rcx = mctx->rcx; + context->Rdx = mctx->rdx; + context->Rbx = mctx->rbx; + context->Rsp = mctx->rsp; + context->Rbp = mctx->rbp; + context->Rsi = mctx->rsi; + context->Rdi = mctx->rdi; + context->R8 = mctx->r8; + context->R9 = mctx->r9; + context->R10 = mctx->r10; + context->R11 = mctx->r11; + context->R12 = mctx->r12; + context->R13 = mctx->r13; + context->R14 = mctx->r14; + context->R15 = mctx->r15; #else MonoContext *ctx = (MonoContext *)sigctx; diff --git a/mono/utils/mono-context.h b/mono/utils/mono-context.h index 1a38146b324..251e58111d1 100755 --- a/mono/utils/mono-context.h +++ b/mono/utils/mono-context.h @@ -544,7 +544,18 @@ typedef struct ucontext MonoContext; #endif +/* + * The naming is misleading, the SIGCTX argument should be the platform's context + * structure (ucontext_c on posix, CONTEXT on windows). + */ void mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) MONO_INTERNAL; + +/* + * This will not completely initialize SIGCTX since MonoContext contains less + * information that the system context. The caller should obtain a SIGCTX from + * the system, and use this function to override the parts of it which are + * also in MonoContext. + */ void mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) MONO_INTERNAL; #endif /* __MONO_MONO_CONTEXT_H__ */ diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index c9ba893f410..892a8f5dc5c 100755 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -113,38 +113,9 @@ mono_threads_core_resume (MonoThreadInfo *info) g_assert (context.ContextFlags & CONTEXT_INTEGER); g_assert (context.ContextFlags & CONTEXT_CONTROL); - // FIXME: This should be in mini-windows.c - context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; -#ifdef TARGET_AMD64 - context.Rip = ctx.rip; - context.Rax = ctx.rax; - context.Rcx = ctx.rcx; - context.Rdx = ctx.rdx; - context.Rbx = ctx.rbx; - context.Rsp = ctx.rsp; - context.Rbp = ctx.rbp; - context.Rsi = ctx.rsi; - context.Rdi = ctx.rdi; - context.R8 = ctx.r8; - context.R9 = ctx.r9; - context.R10 = ctx.r10; - context.R11 = ctx.r11; - context.R12 = ctx.r12; - context.R13 = ctx.r13; - context.R14 = ctx.r14; - context.R15 = ctx.r15; -#else - context.Eip = ctx.eip; - context.Edi = ctx.edi; - context.Esi = ctx.esi; - context.Ebx = ctx.ebx; - context.Edx = ctx.edx; - context.Ecx = ctx.ecx; - context.Eax = ctx.eax; - context.Ebp = ctx.ebp; - context.Esp = ctx.esp; -#endif + mono_monoctx_to_sigctx (&ctx, &context); + context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; res = SetThreadContext (handle, &context); g_assert (res); } From a4024ba4ae9ae65c195e17908c10b2ab0d4d1649 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 17 Sep 2014 22:49:02 -0400 Subject: [PATCH 157/543] [sdb] Use new style interrupt on win32 if available. --- mono/mini/debugger-agent.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 59194301869..58d66c88f48 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -2776,9 +2776,6 @@ notify_thread (gpointer key, gpointer value, gpointer user_data) #endif /* This is _not_ equivalent to ves_icall_System_Threading_Thread_Abort () */ -#ifdef HOST_WIN32 - QueueUserAPC (notify_thread_apc, thread->handle, (ULONG_PTR)NULL); -#else if (mono_thread_info_new_interrupt_enabled ()) { MonoThreadInfo *info; MonoJitInfo *ji; @@ -2798,6 +2795,10 @@ notify_thread (gpointer key, gpointer value, gpointer user_data) mono_thread_info_finish_suspend_and_resume (info); } } else { +#ifdef HOST_WIN32 + // FIXME: Remove this since new interrupt is used on win32 now + QueueUserAPC (notify_thread_apc, thread->handle, (ULONG_PTR)NULL); +#else res = mono_thread_kill (thread, mono_thread_get_abort_signal ()); if (res) { DEBUG(1, fprintf (log_file, "[%p] mono_thread_kill () failed for %p: %d...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid, res)); @@ -2806,8 +2807,8 @@ notify_thread (gpointer key, gpointer value, gpointer user_data) */ tls->terminated = TRUE; } - } #endif + } } static void From 548dca473040521f38617313b791fe15336d4c56 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 18 Sep 2014 10:10:04 +0200 Subject: [PATCH 158/543] [mcs] Better check for parameterless constructor overload --- mcs/mcs/ecore.cs | 19 ++++++++++++------- mcs/tests/gtest-optional-34.cs | 14 ++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 15 +++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 mcs/tests/gtest-optional-34.cs diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 8c6355386c3..0b0beee715c 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -788,6 +788,18 @@ public static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, re return null; } + if (args == null && type.IsStruct) { + bool includes_empty = false; + foreach (MethodSpec ctor in ctors) { + if (ctor.Parameters.IsEmpty) { + includes_empty = true; + } + } + + if (!includes_empty) + return null; + } + var r = new OverloadResolver (ctors, OverloadResolver.Restrictions.NoBaseMembers, loc); if (!rc.HasSet (ResolveContext.Options.BaseInitializer)) { r.InstanceQualifier = new ConstructorInstanceQualifier (type); @@ -5374,13 +5386,6 @@ public T ResolveMember (ResolveContext rc, ref Arguments args) where T : Memb if (best_candidate_rate == 0) break; - // - // We don't include implicit struct constructors in member-cache. Hence - // we need explicit check during lookup - // - if (args_count == 0 && (restrictions & Restrictions.NoBaseMembers) != 0 && best_candidate != null && best_candidate.Kind == MemberKind.Constructor && best_candidate.DeclaringType.IsStruct) - return null; - // // Try extension methods lookup when no ordinary method match was found and provider enables it // diff --git a/mcs/tests/gtest-optional-34.cs b/mcs/tests/gtest-optional-34.cs new file mode 100644 index 00000000000..bf865a7bbe9 --- /dev/null +++ b/mcs/tests/gtest-optional-34.cs @@ -0,0 +1,14 @@ +public struct S +{ + public S (double left = 0, double top = 0) + : this () + { + } +} + +class X +{ + public static void Main () + { + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 4f1559e99ac..d2eacfb5553 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -29918,6 +29918,21 @@ + + + + 9 + + + + + 2 + + + 7 + + + From eb6781f3cd464a78fabbec486ce1036db8277f26 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 18 Sep 2014 14:47:19 +0200 Subject: [PATCH 159/543] [mcs] Fix output type inference when parameters after first one depend on fixed first set. Fixes #23024 --- mcs/mcs/generic.cs | 4 +-- mcs/tests/gtest-lambda-36.cs | 26 +++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 61 ++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 mcs/tests/gtest-lambda-36.cs diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs index d369ccf816d..98ac9dabc6e 100644 --- a/mcs/mcs/generic.cs +++ b/mcs/mcs/generic.cs @@ -3034,8 +3034,8 @@ bool AllTypesAreFixed (TypeSpec[] types) continue; } - if (TypeManager.IsGenericType (t)) - return AllTypesAreFixed (TypeManager.GetTypeArguments (t)); + if (t.IsGeneric && !AllTypesAreFixed (t.TypeArguments)) + return false; } return true; diff --git a/mcs/tests/gtest-lambda-36.cs b/mcs/tests/gtest-lambda-36.cs new file mode 100644 index 00000000000..0d4d772c697 --- /dev/null +++ b/mcs/tests/gtest-lambda-36.cs @@ -0,0 +1,26 @@ +using System; + +class D +{ + public void S (Func ftu, Func ftuv) + { + } +} + +class Test +{ + static D Factory (V v) + { + return new D (); + } + + static void Main () + { + var danon = Factory (new { q = 5 }); + + danon.S ( + () => "x", + (l, str) => new { str } + ); + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index d2eacfb5553..d6569ccdbef 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -27070,6 +27070,67 @@ + + + + 2 + + + 7 + + + + + 14 + + + 78 + + + 13 + + + 14 + + + 7 + + + + + 7 + + + 39 + + + 63 + + + 67 + + + 14 + + + + + 7 + + + 39 + + + 63 + + + 67 + + + 14 + + + From 3552179bdafe770787aaa94949077d04aea317f8 Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Thu, 18 Sep 2014 17:32:06 +0100 Subject: [PATCH 160/543] Put KeyPairPersistence load into a try{}catch{} block. Kpp.Load() will throw an unhandled exception if _filename (a folder to use as the key store) does not exist and it cannot be created. This is an entirely valid thing to have happen - cert importing into the machine store (mozroots --import --machine --sync) as root will create a /usr/share/.mono/certs/ folder, but will not create /usr/share/.mono/keypairs - and since the root user owns /usr/share/.mono/, if the user tries to enumerate the certificates in /usr/share/.mono/certs/, they get 0 certificates returned due to the unhandled exception dropping each loaded certificate on the floor. Closes: Xamarin bug 23015 --- mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs b/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs index c4bb4b99afc..b22f1b5ae25 100644 --- a/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs +++ b/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs @@ -236,8 +236,13 @@ private X509Certificate LoadCertificate (string filename) cspParams.Flags = CspProviderFlags.UseMachineKeyStore; KeyPairPersistence kpp = new KeyPairPersistence (cspParams); - if (!kpp.Load ()) + try { + if (!kpp.Load ()) + return cert; + } + catch { return cert; + } if (cert.RSA != null) cert.RSA = new RSACryptoServiceProvider (cspParams); From d1ffd5a7944401adfbe1cdebbc87626a5ef0408a Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Thu, 18 Sep 2014 16:39:53 -0400 Subject: [PATCH 161/543] [utils] Use MONO_ALWAYS_INLINE + Add MONO_NEVER_INLINE --- mono/metadata/sgen-copy-object.h | 11 +++++------ mono/metadata/sgen-minor-copy-object.h | 14 ++++---------- mono/mini/exceptions-arm.c | 6 ++---- mono/mini/mini-trampolines.c | 12 +++++------- mono/mini/xdebug.c | 13 ++++--------- mono/profiler/perf_event.h | 4 +++- mono/utils/mono-compiler.h | 8 ++++++++ mono/utils/mono-threads-windows.c | 4 ++-- 8 files changed, 33 insertions(+), 39 deletions(-) diff --git a/mono/metadata/sgen-copy-object.h b/mono/metadata/sgen-copy-object.h index dec0d073fe0..3c5abaca7c5 100644 --- a/mono/metadata/sgen-copy-object.h +++ b/mono/metadata/sgen-copy-object.h @@ -18,6 +18,9 @@ * License 2.0 along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "mono/utils/mono-compiler.h" + extern long long stat_copy_object_called_nursery; extern long long stat_objects_copied_nursery; @@ -31,7 +34,7 @@ extern long long stat_slots_allocated_in_vain; * This function can be used even if the vtable of obj is not valid * anymore, which is the case in the parallel collector. */ -static inline void +static MONO_ALWAYS_INLINE void par_copy_object_no_checks (char *destination, MonoVTable *vt, void *obj, mword objsize, SgenGrayQueue *queue) { #ifdef __GNUC__ @@ -99,11 +102,7 @@ par_copy_object_no_checks (char *destination, MonoVTable *vt, void *obj, mword o /* * This can return OBJ itself on OOM. */ -#ifdef _MSC_VER -static __declspec(noinline) void* -#else -static G_GNUC_UNUSED void* __attribute__((noinline)) -#endif +static MONO_NEVER_INLINE void* copy_object_no_checks (void *obj, SgenGrayQueue *queue) { MonoVTable *vt = ((MonoObject*)obj)->vtable; diff --git a/mono/metadata/sgen-minor-copy-object.h b/mono/metadata/sgen-minor-copy-object.h index 782bbdf8de2..187988e7def 100644 --- a/mono/metadata/sgen-minor-copy-object.h +++ b/mono/metadata/sgen-minor-copy-object.h @@ -25,6 +25,8 @@ extern long long stat_nursery_copy_object_failed_to_space; /* from sgen-gc.c */ +#include "mono/utils/mono-compiler.h" + #include "sgen-copy-object.h" /* @@ -47,11 +49,7 @@ extern long long stat_nursery_copy_object_failed_to_space; /* from sgen-gc.c */ * copy_object could be made into a macro once debugged (use inline for now). */ -#ifdef _MSC_VER -static __forceinline void -#else -static inline void __attribute__((always_inline)) -#endif +static MONO_ALWAYS_INLINE void SERIAL_COPY_OBJECT (void **obj_slot, SgenGrayQueue *queue) { char *forwarded; @@ -107,11 +105,7 @@ SERIAL_COPY_OBJECT (void **obj_slot, SgenGrayQueue *queue) * * Similar to SERIAL_COPY_OBJECT, but assumes that OBJ_SLOT is part of an object, so it handles global remsets as well. */ -#ifdef _MSC_VER -static __forceinline void -#else -static inline void __attribute__((always_inline)) -#endif +static MONO_ALWAYS_INLINE void SERIAL_COPY_OBJECT_FROM_OBJ (void **obj_slot, SgenGrayQueue *queue) { char *forwarded; diff --git a/mono/mini/exceptions-arm.c b/mono/mini/exceptions-arm.c index d7fd3318f3d..e39248ceda1 100644 --- a/mono/mini/exceptions-arm.c +++ b/mono/mini/exceptions-arm.c @@ -36,6 +36,7 @@ #include "mini.h" #include "mini-arm.h" #include "mono/utils/mono-sigcontext.h" +#include "mono/utils/mono-compiler.h" /* * arch_get_restore_context: @@ -536,10 +537,7 @@ handle_signal_exception (gpointer obj) * This works around a gcc 4.5 bug: * https://bugs.launchpad.net/ubuntu/+source/gcc-4.5/+bug/721531 */ -#if defined(__GNUC__) -__attribute__((noinline)) -#endif -static gpointer +static MONO_NEVER_INLINE gpointer get_handle_signal_exception_addr (void) { return handle_signal_exception; diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index f65dab8c1e7..4434564ee79 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "mini.h" @@ -140,18 +141,15 @@ mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr) /* * Either IMPL_METHOD or AOT_ADDR will be set on return. - */ -static gpointer* -#ifdef __GNUC__ -/* + * + * MONO_NEVER_INLINE : * This works against problems when compiling with gcc 4.6 on arm. The 'then' part of * this line gets executed, even when the condition is false: * if (impl && mono_method_needs_static_rgctx_invoke (impl, FALSE)) * *need_rgctx_tramp = TRUE; */ -__attribute__ ((noinline)) -#endif - mono_convert_imt_slot_to_vtable_slot (gpointer* slot, mgreg_t *regs, guint8 *code, MonoMethod *method, gboolean lookup_aot, MonoMethod **impl_method, gboolean *need_rgctx_tramp, gboolean *variance_used, gpointer *aot_addr) +static MONO_NEVER_INLINE gpointer* +mono_convert_imt_slot_to_vtable_slot (gpointer* slot, mgreg_t *regs, guint8 *code, MonoMethod *method, gboolean lookup_aot, MonoMethod **impl_method, gboolean *need_rgctx_tramp, gboolean *variance_used, gpointer *aot_addr) { MonoObject *this_argument = mono_arch_get_this_arg_from_call (regs, code); MonoVTable *vt = this_argument->vtable; diff --git a/mono/mini/xdebug.c b/mono/mini/xdebug.c index 9e415ca3390..167b2b9e2b7 100644 --- a/mono/mini/xdebug.c +++ b/mono/mini/xdebug.c @@ -51,6 +51,8 @@ #include "image-writer.h" #include "dwarfwriter.h" +#include "mono/utils/mono-compiler.h" + #define USE_GDB_JIT_INTERFACE /* The recommended gdb macro is: */ @@ -95,15 +97,8 @@ struct jit_descriptor struct jit_code_entry *first_entry; }; - -#ifdef _MSC_VER -#define MONO_NOINLINE __declspec (noinline) -#else -#define MONO_NOINLINE __attribute__((noinline)) -#endif - /* GDB puts a breakpoint in this function. */ -void MONO_NOINLINE __jit_debug_register_code(void); +void MONO_NEVER_INLINE __jit_debug_register_code(void); #if !defined(MONO_LLVM_LOADED) && defined(ENABLE_LLVM) && !defined(MONO_CROSS_COMPILE) @@ -114,7 +109,7 @@ extern struct jit_descriptor __jit_debug_descriptor; #else /* gcc seems to inline/eliminate calls to noinline functions, thus the asm () */ -void MONO_NOINLINE __jit_debug_register_code(void) { +void MONO_NEVER_INLINE __jit_debug_register_code(void) { #if defined(__GNUC__) asm (""); #endif diff --git a/mono/profiler/perf_event.h b/mono/profiler/perf_event.h index 057bf22a832..3137aea7980 100644 --- a/mono/profiler/perf_event.h +++ b/mono/profiler/perf_event.h @@ -18,6 +18,8 @@ #include #include +#include "mono/utils/mono-compiler.h" + /* * User-space ABI bits: */ @@ -1004,7 +1006,7 @@ static inline void perf_fetch_caller_regs(struct pt_regs *regs) perf_arch_fetch_caller_regs(regs, CALLER_ADDR0); } -static __always_inline void +static MONO_ALWAYS_INLINE void perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) { struct pt_regs hot_regs; diff --git a/mono/utils/mono-compiler.h b/mono/utils/mono-compiler.h index 2b330b9bb9d..e8a6a27cc7b 100644 --- a/mono/utils/mono-compiler.h +++ b/mono/utils/mono-compiler.h @@ -247,5 +247,13 @@ typedef SSIZE_T ssize_t; #define MONO_ALWAYS_INLINE #endif +#ifdef __GNUC__ +#define MONO_NEVER_INLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define MONO_NEVER_INLINE __declspec(noinline) +#else +#define MONO_NEVER_INLINE +#endif + #endif /* __UTILS_MONO_COMPILER_H__*/ diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index 892a8f5dc5c..69e1ac0e9f8 100755 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -12,6 +12,7 @@ #if defined(HOST_WIN32) #include +#include #include @@ -248,8 +249,7 @@ mono_threads_core_resume_created (MonoThreadInfo *info, MonoNativeThreadId tid) } #if HAVE_DECL___READFSDWORD==0 -static __inline__ __attribute__((always_inline)) -unsigned long long +static MONO_ALWAYS_INLINE unsigned long long __readfsdword (unsigned long offset) { unsigned long value; From 7ad366c25a7fc180a57dcf88f28064ec3db619b6 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Fri, 19 Sep 2014 00:08:04 +0200 Subject: [PATCH 162/543] [mcs] Improve scoring of failed overload resolution. Fixes #22989 --- mcs/errors/cs1501-18.cs | 30 ++++++++++++++++++++++++++++ mcs/mcs/ecore.cs | 43 +++++++++++++++++++++++++++-------------- mcs/mcs/generic.cs | 12 ++++++------ 3 files changed, 64 insertions(+), 21 deletions(-) create mode 100644 mcs/errors/cs1501-18.cs diff --git a/mcs/errors/cs1501-18.cs b/mcs/errors/cs1501-18.cs new file mode 100644 index 00000000000..6f445564e94 --- /dev/null +++ b/mcs/errors/cs1501-18.cs @@ -0,0 +1,30 @@ +// CS1501: No overload for method `Bar' takes `2' arguments +// Line: 25 + +using System; + +class T +{ + void Foo (int arg, Action a) + { + } + + void Foo (string title, Action a) + { + } + + static void Mismatch (string s) + { + } + + public static void Main () + { + } + + void Bar () + { + Foo (arg: 1, a: () => { + Bar ("a", "b"); + }); + } +} \ No newline at end of file diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 0b0beee715c..94f4bcb129b 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -4735,11 +4735,23 @@ public static void Error_ConstructorMismatch (ResolveContext rc, TypeSpec type, // one being the virtual base for the parameter types and modifiers. // // A return value rates candidate method compatibility, - // 0 = the best, int.MaxValue = the worst // -1 = fatal error + // 0 = the best, int.MaxValue = the worst // int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref MemberSpec candidate, IParametersMember pm, ref bool params_expanded_form, ref bool dynamicArgument, ref TypeSpec returnType, bool errorMode) { + // + // Each step has allocated 10 values, it can overflow for + // more than 10 arguments but that's ok as it's used for + // better error reporting only + // + const int ArgumentCountMismatch = 1000000000; + const int NamedArgumentsMismatch = 100000000; + const int DefaultArgumentMismatch = 10000000; + const int UnexpectedTypeArguments = 1000000; + const int TypeArgumentsMismatch = 100000; + const int InflatedTypesMismatch = 10000; + // Parameters of most-derived type used mainly for named and optional parameters var pd = pm.Parameters; @@ -4772,17 +4784,17 @@ int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref param_count--; } else if (arg_count > param_count) { int args_gap = System.Math.Abs (arg_count - param_count); - return int.MaxValue - 10000 + args_gap; + return ArgumentCountMismatch + args_gap; } else if (arg_count < param_count - optional_count) { int args_gap = System.Math.Abs (param_count - optional_count - arg_count); - return int.MaxValue - 10000 + args_gap; + return ArgumentCountMismatch + args_gap; } } else if (arg_count != param_count) { int args_gap = System.Math.Abs (arg_count - param_count); if (!cpd.HasParams) - return int.MaxValue - 10000 + args_gap; + return ArgumentCountMismatch + args_gap; if (arg_count < param_count - 1) - return int.MaxValue - 10000 + args_gap; + return ArgumentCountMismatch + args_gap; } // Resize to fit optional arguments @@ -4819,7 +4831,7 @@ int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref // Named parameter not found if (index < 0) - return (i + 1) * 3; + return NamedArgumentsMismatch - i; // already reordered if (index == i) @@ -4835,8 +4847,8 @@ int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref ++arg_count; temp = null; } else { - if (index == arg_count) - return (i + 1) * 3; + if (index == arg_count) + return NamedArgumentsMismatch - i - 1; temp = arguments [index]; @@ -4873,7 +4885,7 @@ int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref // Don't do any expensive checks when the candidate cannot succeed // if (arg_count != param_count && !cpd.HasParams) - return (param_count - arg_count) * 2 + 1; + return DefaultArgumentMismatch - System.Math.Abs (param_count - arg_count); var dep = candidate.GetMissingDependencies (); if (dep != null) { @@ -4890,7 +4902,7 @@ int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref if (type_arguments != null) { var g_args_count = ms.Arity; if (g_args_count != type_arguments.Count) - return int.MaxValue - 20000 + System.Math.Abs (type_arguments.Count - g_args_count); + return TypeArgumentsMismatch - System.Math.Abs (type_arguments.Count - g_args_count); if (type_arguments.Arguments != null) ms = ms.MakeGenericMethod (ec, type_arguments.Arguments); @@ -4922,7 +4934,7 @@ int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref TypeSpec[] i_args = ti.InferMethodArguments (ec, ms); if (i_args == null) - return ti.InferenceScore - 20000; + return TypeArgumentsMismatch - ti.InferenceScore; // // Clear any error messages when the result was success @@ -4932,9 +4944,10 @@ int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref if (i_args.Length != 0) { if (!errorMode) { - foreach (var ta in i_args) { + for (int i = 0; i < i_args.Length; ++i) { + var ta = i_args [i]; if (!ta.IsAccessible (ec)) - return ti.InferenceScore - 10000; + return TypeArgumentsMismatch - i; } } @@ -4947,7 +4960,7 @@ int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref // if (!CheckInflatedArguments (ms)) { candidate = ms; - return int.MaxValue - 25000; + return InflatedTypesMismatch; } // @@ -4970,7 +4983,7 @@ int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref ptypes = pd.Types; } else { if (type_arguments != null) - return int.MaxValue - 15000; + return UnexpectedTypeArguments; ptypes = cpd.Types; } diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs index 98ac9dabc6e..f9fc7525667 100644 --- a/mcs/mcs/generic.cs +++ b/mcs/mcs/generic.cs @@ -2758,7 +2758,7 @@ class TypeInference // // Tracks successful rate of type inference // - int score = int.MaxValue; + int score; readonly Arguments arguments; readonly int arg_count; @@ -2831,12 +2831,12 @@ bool InferInPhases (ResolveContext ec, TypeInferenceContext tic, AParametersColl AnonymousMethodExpression am = a.Expr as AnonymousMethodExpression; if (am != null) { if (am.ExplicitTypeInference (tic, method_parameter)) - --score; + ++score; continue; } if (a.IsByRef) { - score -= tic.ExactInference (a.Type, method_parameter); + score += tic.ExactInference (a.Type, method_parameter); continue; } @@ -2844,14 +2844,14 @@ bool InferInPhases (ResolveContext ec, TypeInferenceContext tic, AParametersColl continue; if (TypeSpec.IsValueType (method_parameter)) { - score -= tic.LowerBoundInference (a.Type, method_parameter); + score += tic.LowerBoundInference (a.Type, method_parameter); continue; } // // Otherwise an output type inference is made // - score -= tic.OutputTypeInference (ec, a.Expr, method_parameter); + score += tic.OutputTypeInference (ec, a.Expr, method_parameter); } // @@ -2901,7 +2901,7 @@ bool DoSecondPhase (ResolveContext ec, TypeInferenceContext tic, TypeSpec[] meth if (arguments[i] == null) continue; - score -= tic.OutputTypeInference (ec, arguments[i].Expr, t_i); + score += tic.OutputTypeInference (ec, arguments[i].Expr, t_i); } } From fcb9de513afcb651b050fc7af5587e052be7352a Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 19 Sep 2014 09:45:03 -0400 Subject: [PATCH 163/543] [utils] Fix force inlining compilation error with gcc on linux [02131] CC libmonoruntimesgen_la-sgen-marksweep.lo [02131] In file included from sgen-major-copy-object.h:35:0, [02131] from sgen-marksweep.c:1128: [02131] sgen-copy-object.h:38:1: warning: always_inline function might not be inlinable [-Wattributes] [02131] par_copy_object_no_checks (char *destination, MonoVTable *vt, void *obj, mword objsize, SgenGrayQueue *queue) [02131] ^ [02131] sgen-marksweep.c: In function 'par_copy_object_no_checks': [02131] sgen-copy-object.h:38:1: error: function 'par_copy_object_no_checks' can never be copied because it saves address of local label in a static variable [02131] make[3]: *** [libmonoruntimesgen_la-sgen-marksweep.lo] Error 1 [02131] make[3]: Leaving directory `/root/rpmbuild/BUILD/mono-3.10.1/mono/metadata' [02131] make[2]: *** [all-recursive] Error 1 [02131] make[2]: Leaving directory `/root/rpmbuild/BUILD/mono-3.10.1/mono' [02131] make[1]: *** [all-recursive] Error 1 [02131] make[1]: Leaving directory `/root/rpmbuild/BUILD/mono-3.10.1' [02131] make: *** [all] Error 2 [02131] error: Bad exit status from /var/tmp/rpm-tmp.YxcUOE (%build) --- mono/metadata/sgen-copy-object.h | 39 ++++++++++---------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/mono/metadata/sgen-copy-object.h b/mono/metadata/sgen-copy-object.h index 3c5abaca7c5..dba9ed1459e 100644 --- a/mono/metadata/sgen-copy-object.h +++ b/mono/metadata/sgen-copy-object.h @@ -37,10 +37,6 @@ extern long long stat_slots_allocated_in_vain; static MONO_ALWAYS_INLINE void par_copy_object_no_checks (char *destination, MonoVTable *vt, void *obj, mword objsize, SgenGrayQueue *queue) { -#ifdef __GNUC__ - static const void *copy_labels [] = { &&LAB_0, &&LAB_1, &&LAB_2, &&LAB_3, &&LAB_4, &&LAB_5, &&LAB_6, &&LAB_7, &&LAB_8 }; -#endif - SGEN_ASSERT (9, vt->klass->inited, "vtable %p for class %s:%s was not initialized", vt, vt->klass->name_space, vt->klass->name); SGEN_LOG (9, " (to %p, %s size: %lu)", destination, ((MonoObject*)obj)->vtable->klass->name, (unsigned long)objsize); binary_protocol_copy (obj, destination, vt, objsize); @@ -56,32 +52,21 @@ par_copy_object_no_checks (char *destination, MonoVTable *vt, void *obj, mword o #ifdef __GNUC__ if (objsize <= sizeof (gpointer) * 8) { mword *dest = (mword*)destination; - goto *copy_labels [objsize / sizeof (gpointer)]; - LAB_8: - (dest) [7] = ((mword*)obj) [7]; - LAB_7: - (dest) [6] = ((mword*)obj) [6]; - LAB_6: - (dest) [5] = ((mword*)obj) [5]; - LAB_5: - (dest) [4] = ((mword*)obj) [4]; - LAB_4: - (dest) [3] = ((mword*)obj) [3]; - LAB_3: - (dest) [2] = ((mword*)obj) [2]; - LAB_2: - (dest) [1] = ((mword*)obj) [1]; - LAB_1: - ; - LAB_0: - ; - } else { + switch (objsize / sizeof (gpointer)) { + case 8: (dest) [7] = ((mword*)obj) [7]; + case 7: (dest) [6] = ((mword*)obj) [6]; + case 6: (dest) [5] = ((mword*)obj) [5]; + case 5: (dest) [4] = ((mword*)obj) [4]; + case 4: (dest) [3] = ((mword*)obj) [3]; + case 3: (dest) [2] = ((mword*)obj) [2]; + case 2: (dest) [1] = ((mword*)obj) [1]; + } + } else +#endif + { /*can't trust memcpy doing word copies */ mono_gc_memmove_aligned (destination + sizeof (mword), (char*)obj + sizeof (mword), objsize - sizeof (mword)); } -#else - mono_gc_memmove_aligned (destination + sizeof (mword), (char*)obj + sizeof (mword), objsize - sizeof (mword)); -#endif /* adjust array->bounds */ SGEN_ASSERT (9, vt->gc_descr, "vtable %p for class %s:%s has no gc descriptor", vt, vt->klass->name_space, vt->klass->name); From 05d341392c0b03fe77c18089653673a987306bb3 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 19 Sep 2014 11:13:24 -0400 Subject: [PATCH 164/543] [sgen] Fix wbarrier use if we define SGEN_HEAVY_BINARY_PROTOCOL, HEAVY_STATISTICS or XDOMAIN_CHECKS_IN_WBARRIER --- mono/metadata/sgen-cardtable.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mono/metadata/sgen-cardtable.c b/mono/metadata/sgen-cardtable.c index aab3bcb6153..472244b6312 100644 --- a/mono/metadata/sgen-cardtable.c +++ b/mono/metadata/sgen-cardtable.c @@ -455,6 +455,9 @@ sgen_card_table_finish_scan_remsets (void *start_nursery, void *end_nursery, Sge guint8* mono_gc_get_card_table (int *shift_bits, gpointer *mask) { +#ifndef MANAGED_WBARRIER + return NULL; +#else if (!sgen_cardtable) return NULL; @@ -466,6 +469,7 @@ mono_gc_get_card_table (int *shift_bits, gpointer *mask) #endif return sgen_cardtable; +#endif } gboolean From a83e9cf4aaaef69d3eabbca2de74005ed207374f Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Fri, 19 Sep 2014 11:42:55 -0400 Subject: [PATCH 165/543] Add SqlCredential support - - Tds.cs: Use SecureString objects for passwords; Add method to retrieve string from SecureString - Tds42.cs: Use SecureString for passwords - Tds50.cs: Use SecureString for passwords - Tds70.cs: Use SecureString for passwords - TdsConnectionParameters.cs: Use SecureString for passwords; Initialize Password parameter as cleared string; Add indicator for when password is set - SqlConnection.cs: Use SecureString for passwords; Add SqlConnect method that accepts an SqlCredential along with the Connection string; Perform checking of parameters to ensure user/password not specified in connection string if credentials have been specified or using credentials when domain login is specified. - SqlCredential.cs: Add new class with support for credentials - System.Data.dll.sources: Add SqlCredential.cs to the build list --- .../Mono.Data.Tds.Protocol/Tds.cs | 18 ++++- .../Mono.Data.Tds.Protocol/Tds42.cs | 5 +- .../Mono.Data.Tds.Protocol/Tds50.cs | 5 +- .../Mono.Data.Tds.Protocol/Tds70.cs | 6 +- .../TdsConnectionParameters.cs | 7 +- .../System.Data.SqlClient/SqlConnection.cs | 34 ++++++++- .../System.Data.SqlClient/SqlCredential.cs | 76 +++++++++++++++++++ mcs/class/System.Data/System.Data.dll.sources | 1 + 8 files changed, 142 insertions(+), 10 deletions(-) create mode 100644 mcs/class/System.Data/System.Data.SqlClient/SqlCredential.cs diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds.cs b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds.cs index 6865df9adbe..f06932c8026 100644 --- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds.cs +++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds.cs @@ -41,7 +41,9 @@ using System.Diagnostics; using System.Net.Sockets; using System.Globalization; +using System.Security; using System.Text; +using System.Runtime.InteropServices; namespace Mono.Data.Tds.Protocol { @@ -1468,7 +1470,7 @@ protected internal int ProcessAuthentication () t3.Domain = this.connectionParms.DefaultDomain; t3.Host = this.connectionParms.Hostname; t3.Username = this.connectionParms.User; - t3.Password = this.connectionParms.Password; + t3.Password = GetPlainPassword(this.connectionParms.Password); Comm.StartPacket (TdsPacketType.SspAuth); // 0x11 Comm.Append (t3.GetBytes ()); @@ -1919,6 +1921,20 @@ protected virtual void ProcessReturnStatus () comm.Skip(4); } + public static string GetPlainPassword(SecureString secPass) + { + IntPtr plainString = IntPtr.Zero; + try + { + plainString = Marshal.SecureStringToGlobalAllocUnicode(secPass); + return Marshal.PtrToStringUni(plainString); + } + finally + { + Marshal.ZeroFreeGlobalAllocUnicode(plainString); + } + } + #endregion // Private Methods #if NET_2_0 diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds42.cs b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds42.cs index fdca83087b1..fb517d013d5 100644 --- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds42.cs +++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds42.cs @@ -29,6 +29,7 @@ // using System; +using System.Security; namespace Mono.Data.Tds.Protocol { public sealed class Tds42 : Tds @@ -77,7 +78,7 @@ public override bool Connect (TdsConnectionParameters connectionParameters) Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30)); // password (offset 62 0x3e) - tmp = Comm.Append (connectionParameters.Password, 30, pad); + tmp = Comm.Append (GetPlainPassword(connectionParameters.Password), 30, pad); Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30)); // hostproc (offset 93 0x5d) @@ -145,7 +146,7 @@ public override bool Connect (TdsConnectionParameters connectionParameters) // remote passwords Comm.Append (empty, 2, pad); - tmp = Comm.Append (connectionParameters.Password, 253, pad); + tmp = Comm.Append (GetPlainPassword(connectionParameters.Password), 253, pad); Comm.Append ((byte) (tmp.Length < 253 ? tmp.Length + 2 : 253 + 2)); // tds version diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds50.cs b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds50.cs index 0d0e86c023d..88219125df5 100644 --- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds50.cs +++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds50.cs @@ -31,6 +31,7 @@ using Mono.Data.Tds; using System; using System.Text; +using System.Security; namespace Mono.Data.Tds.Protocol { @@ -118,7 +119,7 @@ public override bool Connect (TdsConnectionParameters connectionParameters) // password (offset 62 0x3e) // 62-92 - tmp = Comm.Append (connectionParameters.Password, 30, pad); + tmp = Comm.Append (GetPlainPassword(connectionParameters.Password), 30, pad); Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30)); // hostproc (offset 93 0x5d) @@ -187,7 +188,7 @@ public override bool Connect (TdsConnectionParameters connectionParameters) // remote passwords // 202-457 Comm.Append (empty, 2, pad); - tmp = Comm.Append (connectionParameters.Password, 253, pad); + tmp = Comm.Append (GetPlainPassword(connectionParameters.Password), 253, pad); Comm.Append ((byte) (tmp.Length < 253 ? tmp.Length + 2 : 253 + 2)); // tds version diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs index c67b6e8c3bb..991727bbc00 100644 --- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs +++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs @@ -37,6 +37,7 @@ using System; using System.Globalization; using System.Text; +using System.Security; using Mono.Security.Protocol.Ntlm; @@ -392,11 +393,12 @@ public override bool Connect (TdsConnectionParameters connectionParameters) return IsConnected; } - private static string EncryptPassword (string pass) + private static string EncryptPassword (SecureString secPass) { int xormask = 0x5a5a; - int len = pass.Length; + int len = secPass.Length; char[] chars = new char[len]; + string pass = GetPlainPassword(secPass); for (int i = 0; i < len; ++i) { int c = ((int) (pass[i])) ^ xormask; diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/TdsConnectionParameters.cs b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/TdsConnectionParameters.cs index 19f676077d7..e3b83aa257c 100644 --- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/TdsConnectionParameters.cs +++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/TdsConnectionParameters.cs @@ -31,6 +31,7 @@ // using System; +using System.Security; namespace Mono.Data.Tds.Protocol { @@ -42,7 +43,8 @@ public class TdsConnectionParameters public string Hostname; public string Language; public string LibraryName; - public string Password; + public SecureString Password; + public bool PasswordSet; public string ProgName; public string User; public bool DomainLogin; @@ -62,7 +64,8 @@ public void Reset () Hostname = System.Net.Dns.GetHostName(); Language = String.Empty; LibraryName = "Mono"; - Password = String.Empty; + Password = new SecureString(); + PasswordSet = false; ProgName = "Mono"; User = String.Empty; DomainLogin = false; diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs index 8712eca6cf9..e1fa878c4ca 100644 --- a/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs @@ -56,6 +56,7 @@ #if NET_2_0 using System.Collections.Generic; #endif +using System.Security; namespace System.Data.SqlClient { @@ -93,6 +94,9 @@ public sealed class SqlConnection : Component, IDbConnection, ICloneable // The connection string that identifies this connection string connectionString; + // The connection credentials + SqlCredential credentials; + // The transaction object for the current transaction SqlTransaction transaction; @@ -133,6 +137,12 @@ public SqlConnection (string connectionString) ConnectionString = connectionString; } + public SqlConnection (string connectionString, SqlCredential cred) + { + ConnectionString = connectionString; + Credentials = cred; + } + #endregion // Constructors #region Properties @@ -155,6 +165,15 @@ public override string ConnectionString { } } + public SqlCredential Credentials { + get { + return credentials; + } + set { + credentials = value; + } + } + #if !NET_2_0 [DataSysDescription ("Current connection timeout value, 'Connect Timeout=X' in the ConnectionString.")] #endif @@ -563,6 +582,16 @@ void Open () if (!tds.IsConnected) { try { + if (Credentials != null) { + if (parms.User != String.Empty) + throw new ArgumentException("UserID already specified"); + if (parms.PasswordSet) + throw new ArgumentException("Password already specified"); + if (parms.DomainLogin != false) + throw new ArgumentException("Cannot use credentials with DomainLogin"); + parms.User = Credentials.UserId; + parms.Password = Credentials.Password; + } tds.Connect (parms); } catch { if (pooling) @@ -879,7 +908,10 @@ private void SetProperties (string name , string value) break; case "password" : case "pwd" : - parms.Password = value; + parms.Password = new SecureString(); + foreach (char c in value) + parms.Password.AppendChar(c); + parms.PasswordSet = true; break; case "persistsecurityinfo" : case "persist security info" : diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlCredential.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlCredential.cs new file mode 100644 index 00000000000..5b15b48cb66 --- /dev/null +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlCredential.cs @@ -0,0 +1,76 @@ +// +// System.Data.SqlClient.SqlCredential.cs +// +// Author: +// Neale Ferguson (neale@sinenomine.net) +// +// Copyright (C) Neale Ferguson, 2014 +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Data; +using System.Runtime.InteropServices; +using System.Security; + +namespace System.Data.SqlClient { + /// + /// Describes an error from a SQL database. + /// + [Serializable] + public sealed class SqlCredential + { + #region Fields + + string uid = ""; + SecureString pwd = null; + + #endregion // Fields + + #region Constructors + + public SqlCredential (string user, SecureString password) + { + if (user == null) + throw new ArgumentNullException("UserID"); + if (password == null) + throw new ArgumentNullException("Password"); + this.uid = user; + this.pwd = password; + } + + #endregion // Constructors + + #region Properties + + public string UserId { + get { return uid; } + } + + public SecureString Password { + get { return pwd; } + } + + #endregion + } +} diff --git a/mcs/class/System.Data/System.Data.dll.sources b/mcs/class/System.Data/System.Data.dll.sources index aeae903dbc9..5ec88803ea6 100644 --- a/mcs/class/System.Data/System.Data.dll.sources +++ b/mcs/class/System.Data/System.Data.dll.sources @@ -289,6 +289,7 @@ System.Data.SqlClient/SqlCommand.cs System.Data.SqlClient/SqlCommandBuilder.cs System.Data.SqlClient/SqlConnection.cs System.Data.SqlClient/SqlConnectionStringBuilder.cs +System.Data.SqlClient/SqlCredential.cs System.Data.SqlClient/SqlDataAdapter.cs System.Data.SqlClient/SqlDataReader.cs System.Data.SqlClient/SqlDataSourceConverter.cs From 64b8e0c06379960b8e03ffdfb4fc0872026ed01d Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Fri, 19 Sep 2014 16:30:16 -0400 Subject: [PATCH 166/543] [System.Numerics] Fix unit test to succeed on different culture (XI runs tests them on several cultures) --- .../Test/System.Numerics/BigIntegerTest.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs b/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs index c4ad9e811ee..e9b81a71cd9 100644 --- a/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs +++ b/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs @@ -70,6 +70,7 @@ public void SetUpFixture() NfiUser.PercentNegativePattern = 2; NfiUser.PercentPositivePattern = 2; NfiUser.PercentSymbol = "%%%"; + NfiUser.NumberDecimalSeparator = "."; } [Test] @@ -893,6 +894,13 @@ public void DecimalConversion () { Assert.AreEqual (0m, (decimal)new BigInteger (), "#8"); } + [SetCulture ("pt-BR")] + [Test] + public void Parse_pt_BR () + { + Parse (); + } + [Test] public void Parse () { try { @@ -943,7 +951,8 @@ public void Parse () { Assert.AreEqual (-23, (int)BigInteger.Parse(" -23 ", NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite), "#19"); Assert.AreEqual (300000, (int)BigInteger.Parse("3E5", NumberStyles.AllowExponent), "#20"); - Assert.AreEqual (250, (int)BigInteger.Parse("2"+Nfi.NumberDecimalSeparator+"5E2", NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint), "#21");//2.5E2 = 250 + var dsep = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator; + Assert.AreEqual (250, (int)BigInteger.Parse("2" + dsep + "5E2", NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint), "#21");//2.5E2 = 250 Assert.AreEqual (25, (int)BigInteger.Parse("2500E-2", NumberStyles.AllowExponent), "#22"); Assert.AreEqual ("136236974127783066520110477975349088954559032721408", BigInteger.Parse("136236974127783066520110477975349088954559032721408", NumberStyles.None).ToString(), "#23"); @@ -956,7 +965,7 @@ public void Parse () { } try { - Int32.Parse ("2.09E1", NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent); + Int32.Parse ("2" + dsep + "09E1", NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent); Assert.Fail ("#26"); } catch (OverflowException) { } From 23042a0aa36121cafeb269a656311ba6a9abd37e Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Fri, 19 Sep 2014 16:48:37 -0400 Subject: [PATCH 167/543] Fix typo (and XI builds) --- mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources b/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources index d04d5f08d95..6a71501e34c 100644 --- a/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources +++ b/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources @@ -1,2 +1,2 @@ -#include mobil_static_Mono.CSharp.dll.sources +#include mobile_static_Mono.CSharp.dll.sources monotouch.cs From d4b4c2dbbc019bc3b25e197f1faa0ba4506df05d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 19 Sep 2014 17:51:02 -0400 Subject: [PATCH 168/543] [runtime] Add wrappers around the wapi interrupt functions to mono-threads to reduce the amount of #ifdef WIN32 blocks in threads.c. --- mono/metadata/threads.c | 43 +++++++++---------------------- mono/utils/mono-threads-posix.c | 24 +++++++++++++++++ mono/utils/mono-threads-windows.c | 22 ++++++++++++++++ mono/utils/mono-threads.c | 41 ++++++++++++++++++++++++++++- mono/utils/mono-threads.h | 19 ++++++++++++++ 5 files changed, 117 insertions(+), 32 deletions(-) diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index c189ab3e9f2..280ac95ac77 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -30,9 +30,6 @@ #include #include #include -#ifndef HOST_WIN32 -#include -#endif #include #include #include @@ -2028,12 +2025,12 @@ static void signal_thread_state_change (MonoInternalThread *thread) * functions in the io-layer until the signal handler calls QueueUserAPC which will * make it return. */ - wait_handle = wapi_prepare_interrupt_thread (thread->handle); + wait_handle = mono_thread_info_prepare_interrupt (thread->handle); /* fixme: store the state somewhere */ mono_thread_kill (thread, mono_thread_get_abort_signal ()); - wapi_finish_interrupt_thread (wait_handle); + mono_thread_info_finish_interrupt (wait_handle); #endif /* HOST_WIN32 */ } @@ -2956,9 +2953,7 @@ void mono_thread_manage (void) * to get correct user and system times from getrusage/wait/time(1)). * This could be removed if we avoid pthread_detach() and use pthread_join(). */ -#ifndef HOST_WIN32 mono_thread_info_yield (); -#endif } static void terminate_thread (gpointer key, gpointer value, gpointer user) @@ -4115,10 +4110,8 @@ static MonoException* mono_thread_execute_interruption (MonoInternalThread *thre WaitForSingleObjectEx (GetCurrentThread(), 0, TRUE); #endif InterlockedDecrement (&thread_interruption_requested); -#ifndef HOST_WIN32 /* Clear the interrupted flag of the thread so it can wait again */ - wapi_clear_interruption (); -#endif + mono_thread_info_clear_interruption (); } if ((thread->state & ThreadState_AbortRequested) != 0) { @@ -4208,7 +4201,7 @@ mono_thread_request_interruption (gboolean running_managed) #ifdef HOST_WIN32 QueueUserAPC ((PAPCFUNC)dummy_apc, thread->handle, (ULONG_PTR)NULL); #else - wapi_self_interrupt (); + mono_thread_info_self_interrupt (); #endif return NULL; } @@ -4241,9 +4234,8 @@ mono_thread_resume_interruption (void) return NULL; InterlockedIncrement (&thread_interruption_requested); -#ifndef HOST_WIN32 - wapi_self_interrupt (); -#endif + mono_thread_info_self_interrupt (); + return mono_thread_execute_interruption (thread); } @@ -4560,9 +4552,7 @@ abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception, MonoException *exc = mono_thread_request_interruption (can_raise_exception); if (exc) mono_raise_exception (exc); -#ifndef HOST_WIN32 - wapi_interrupt_thread (thread->handle); -#endif + mono_thread_info_interrupt (thread->handle); return; } @@ -4601,14 +4591,11 @@ abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception, * functions in the io-layer until the signal handler calls QueueUserAPC which will * make it return. */ -#ifndef HOST_WIN32 gpointer interrupt_handle; - interrupt_handle = wapi_prepare_interrupt_thread (thread->handle); -#endif + + interrupt_handle = mono_thread_info_prepare_interrupt (thread->handle); mono_thread_info_finish_suspend_and_resume (info); -#ifndef HOST_WIN32 - wapi_finish_interrupt_thread (interrupt_handle); -#endif + mono_thread_info_finish_interrupt (interrupt_handle); } /*FIXME we need to wait for interruption to complete -- figure out how much into interruption we should wait for here*/ } @@ -4661,21 +4648,15 @@ suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt) if (running_managed && !protected_wrapper) { transition_to_suspended (thread, info); } else { -#ifndef HOST_WIN32 gpointer interrupt_handle; -#endif if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 0) InterlockedIncrement (&thread_interruption_requested); -#ifndef HOST_WIN32 if (interrupt) - interrupt_handle = wapi_prepare_interrupt_thread (thread->handle); -#endif + interrupt_handle = mono_thread_info_prepare_interrupt (thread->handle); mono_thread_info_finish_suspend_and_resume (info); -#ifndef HOST_WIN32 if (interrupt) - wapi_finish_interrupt_thread (interrupt_handle); -#endif + mono_thread_info_finish_interrupt (interrupt_handle); UNLOCK_THREAD (thread); } } diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index ce087bbc36b..80f283f8878 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -236,6 +236,30 @@ mono_threads_core_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) return handle; } +gpointer +mono_threads_core_prepare_interrupt (HANDLE thread_handle) +{ + return wapi_prepare_interrupt_thread (thread_handle); +} + +void +mono_threads_core_finish_interrupt (gpointer wait_handle) +{ + wapi_finish_interrupt_thread (wait_handle); +} + +void +mono_threads_core_self_interrupt (void) +{ + wapi_self_interrupt (); +} + +void +mono_threads_core_clear_interruption (void) +{ + wapi_clear_interruption (); +} + #if !defined (__MACH__) #if !defined(__native_client__) diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index 69e1ac0e9f8..04430fb021f 100755 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -368,4 +368,26 @@ mono_threads_core_set_name (MonoNativeThreadId tid, const char *name) #endif } + +gpointer +mono_threads_core_prepare_interrupt (HANDLE thread_handle) +{ + return NULL; +} + +void +mono_threads_core_finish_interrupt (gpointer wait_handle) +{ +} + +void +mono_threads_core_self_interrupt (void) +{ +} + +void +mono_threads_core_clear_interruption (void) +{ +} + #endif diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index 0b754ab4a61..5965b577cfc 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -851,7 +852,7 @@ mono_thread_info_open_handle (void) } /* - * mono_thread_info_open_handle: + * mono_threads_open_thread_handle: * * Return a io-layer/win32 handle for the thread identified by HANDLE/TID. * The handle need to be closed by calling CloseHandle () when it is no @@ -868,3 +869,41 @@ mono_thread_info_set_name (MonoNativeThreadId tid, const char *name) { mono_threads_core_set_name (tid, name); } + +/* + * mono_thread_info_prepare_interrupt: + * + * See wapi_prepare_interrupt (). + */ +gpointer +mono_thread_info_prepare_interrupt (HANDLE thread_handle) +{ + return mono_threads_core_prepare_interrupt (thread_handle); +} + +void +mono_thread_info_finish_interrupt (gpointer wait_handle) +{ + mono_threads_core_finish_interrupt (wait_handle); +} + +void +mono_thread_info_interrupt (HANDLE thread_handle) +{ + gpointer wait_handle; + + wait_handle = mono_thread_info_prepare_interrupt (thread_handle); + mono_thread_info_finish_interrupt (wait_handle); +} + +void +mono_thread_info_self_interrupt (void) +{ + mono_threads_core_self_interrupt (); +} + +void +mono_thread_info_clear_interruption (void) +{ + mono_threads_core_clear_interruption (); +} diff --git a/mono/utils/mono-threads.h b/mono/utils/mono-threads.h index d97543313c9..91a7df5f0fc 100644 --- a/mono/utils/mono-threads.h +++ b/mono/utils/mono-threads.h @@ -302,6 +302,21 @@ mono_thread_info_exit (void); HANDLE mono_thread_info_open_handle (void); +gpointer +mono_thread_info_prepare_interrupt (HANDLE thread_handle); + +void +mono_thread_info_finish_interrupt (gpointer wait_handle); + +void +mono_thread_info_interrupt (HANDLE thread_handle); + +void +mono_thread_info_self_interrupt (void); + +void +mono_thread_info_clear_interruption (void); + HANDLE mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid); @@ -339,6 +354,10 @@ void mono_threads_core_unregister (THREAD_INFO_TYPE *info) MONO_INTERNAL; HANDLE mono_threads_core_open_handle (void) MONO_INTERNAL; HANDLE mono_threads_core_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) MONO_INTERNAL; void mono_threads_core_set_name (MonoNativeThreadId tid, const char *name) MONO_INTERNAL; +gpointer mono_threads_core_prepare_interrupt (HANDLE thread_handle); +void mono_threads_core_finish_interrupt (gpointer wait_handle); +void mono_threads_core_self_interrupt (void); +void mono_threads_core_clear_interruption (void); MonoNativeThreadId mono_native_thread_id_get (void) MONO_INTERNAL; From ca51c3b0262c29731ea05c6d37b36791ea7687d8 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sat, 20 Sep 2014 02:43:47 -0400 Subject: [PATCH 169/543] [runtime] Enable the new interrupt code on arm linux. --- mono/utils/mono-context.h | 2 ++ mono/utils/mono-threads.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/mono/utils/mono-context.h b/mono/utils/mono-context.h index 251e58111d1..619e574e424 100755 --- a/mono/utils/mono-context.h +++ b/mono/utils/mono-context.h @@ -279,6 +279,8 @@ typedef struct { ctx.pc = ctx.regs [15]; \ } while (0) +#define MONO_ARCH_HAS_MONO_CONTEXT 1 + #elif (defined(__aarch64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM64)) #include diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index 5965b577cfc..c6c10ab5ba7 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -737,6 +737,9 @@ mono_thread_info_new_interrupt_enabled (void) #endif #if defined (__i386__) return !disable_new_interrupt; +#endif +#if defined(__arm__) && !defined(__APPLE__) + return !disable_new_interrupt; #endif return FALSE; } From edca3467ce0034ec11a70c6249d0a258a87a2a56 Mon Sep 17 00:00:00 2001 From: rjvdboon Date: Sat, 20 Sep 2014 22:44:34 +0200 Subject: [PATCH 170/543] Added System.IdentityModel.Tokens.BootstrapContext including tests. --- .../BootstrapContext.cs | 101 +++++++++ .../System.IdentityModel.dll.sources | 1 + .../System.IdentityModel_test.dll.sources | 1 + .../BootstrapContextTest.cs | 197 ++++++++++++++++++ 4 files changed, 300 insertions(+) create mode 100644 mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs create mode 100644 mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs new file mode 100644 index 00000000000..4312b649271 --- /dev/null +++ b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs @@ -0,0 +1,101 @@ +// +// BootstrapContext.cs +// +// Author: +// Robert J. van der Boon (rjvdboon@gmail.com) +// +// Copyright (C) 2014 Robert J. van der Boon +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#if NET_4_5 +using System; +using System.Runtime.Serialization; + +namespace System.IdentityModel.Tokens +{ + [Serializable] + public class BootstrapContext : ISerializable + { + /// Gets the string that was used to initialize the context. + public string Token { get; private set; } + /// Gets the array that was used to initialize the context. + public byte[] TokenBytes { get; private set; } + /// Gets the security token that was used to initialize the context. + public SecurityToken SecurityToken { get; private set; } + /// Gets the token handler that was used to initialize the context. + public SecurityTokenHandler SecurityTokenHandler { get; private set; } + + /// Initializes a new instance of the class by using the specified string. + public BoostrapContext (string token) { + if (token == null) throw new ArgumentNullException("token"); + Token = token; + } + + /// Initializes a new instance of the class by using the specified array. + public BoostrapContext (byte[] token) { + if (token == null) throw new ArgumentNullException("token"); + TokenBytes = token; + } + + /// Initializes a new instance of the class by using the specified security token and token handler. + public BoostrapContext (SecurityToken token, SecurityTokenHandler handler) { + if (token == null) throw new ArgumentNullException("token"); + if (handler == null) throw new ArgumentNullException("handler"); + SecurityToken = token; + SecurityTokenHandler = handler; + } + + /// Initializes a new instance of the class from a stream. + protected BootstrapContext(SerializationInfo info, SerializationContext context) { + if (info == null) throw new ArgumentNullException("info"); + char type = info.GetChar("K"); + switch (type) { + case 'S': + Token = info.GetString("V"); + break; + case 'B': + TokenBytes = (byte[])info.GetValue("V"); + break; + case 'T': + Token = Convert.FromBase64String(info.GetString("V")); + break; + } + } + + /// Populates the with data needed to serialize the current object. + public void GetObjectData(SerializationInfo info, SerializationContext context) { + if (info == null) throw new ArgumentNullException("info"); + if (Token != null) { + info.AddValue("K", 'S'); + info.AddValue("T", Token); + } else if (TokenBytes != null) { + info.AddValue("K", 'B'); + info.AddValue("T", TokenBytes); + } else if (SecurityToken != null && SecurityTokenHandler != null) { + info.AddValue("K", 'T'); + // Serialize SecurityToken using SecurityTokenHandler + info.AddValue("T", Token); + } + } + + } +} +#endif \ No newline at end of file diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources b/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources index 32942efdb5c..2c86355259a 100755 --- a/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources +++ b/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources @@ -54,6 +54,7 @@ System.IdentityModel.Tokens/AudienceRestriction.cs System.IdentityModel.Tokens/AuthenticationContext.cs System.IdentityModel.Tokens/AuthenticationInformation.cs System.IdentityModel.Tokens/BinaryKeyIdentifierClause.cs +System.IdentityModel.Tokens/BootstrapContext.cs System.IdentityModel.Tokens/EncryptedKeyIdentifierClause.cs System.IdentityModel.Tokens/EncryptingCredentials.cs System.IdentityModel.Tokens/GenericXmlSecurityToken.cs diff --git a/mcs/class/System.IdentityModel/System.IdentityModel_test.dll.sources b/mcs/class/System.IdentityModel/System.IdentityModel_test.dll.sources index 86d286ce11c..2fcb687a3a5 100644 --- a/mcs/class/System.IdentityModel/System.IdentityModel_test.dll.sources +++ b/mcs/class/System.IdentityModel/System.IdentityModel_test.dll.sources @@ -12,6 +12,7 @@ System.IdentityModel.Selectors/SecurityTokenResolverTest.cs System.IdentityModel.Selectors/TestEvaluationContext.cs System.IdentityModel.Selectors/X509SecurityTokenAuthenticatorTest.cs System.IdentityModel.Selectors/X509SecurityTokenProviderTest.cs +System.IdentityModel.Tokens/BootstrapContextTest.cs System.IdentityModel.Tokens/EncryptedKeyIdentifierClauseTest.cs System.IdentityModel.Tokens/InMemorySymmetricSecurityKeyTest.cs System.IdentityModel.Tokens/LocalIdKeyIdentifierClauseTest.cs diff --git a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs new file mode 100644 index 00000000000..767410ecff6 --- /dev/null +++ b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs @@ -0,0 +1,197 @@ +// +// BootstrapContextTest.cs - NUnit Test Cases for System.IdentityModel.Tokens.BootstrapContext +// + +#if NET_4_5 +using System; +using System.IO; +using System.IdentityModel.Tokens; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using NUnit.Framework; + +namespace MonoTests.System.IdentityModel.Tokens.net_4_5 +{ + [TestFixture] + public class BootstrapContextTest + { + // The following byte arrays are the serialized bytes as emitted on Microsoft .Net 4.5. + private static readonly byte[] SerializedBootstrapContextByteArray = new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x07, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x42, 0x09, 0x03, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x0B }; + private static readonly byte[] SerializedBootstrapContextString = new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x53, 0x06, 0x03, 0x00, 0x00, 0x00, 0x05, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x0B }; + + // Put in some non-ascii/latin1 characters to test the encoding scheme + // \u018E == Latin capital letter Reversed E + private const string user = "us\u018Er"; + // \u00BD == Vulgar Fraction one half + private const string password = "pass\u00BDword"; + private static readonly string SerializedBootstrapContextSecurityTokenString = ""+user+""+password+""; + private static readonly byte[] SerializedBootstrapContextSecurityToken = new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x54, 0x06, 0x03, 0x00, 0x00, 0x00, 0xB8, 0x04, 0x50, 0x46, 0x56, 0x7A, 0x5A, 0x58, 0x4A, 0x75, 0x59, 0x57, 0x31, 0x6C, 0x56, 0x47, 0x39, 0x72, 0x5A, 0x57, 0x34, 0x67, 0x59, 0x54, 0x70, 0x4A, 0x5A, 0x44, 0x30, 0x69, 0x64, 0x58, 0x56, 0x70, 0x5A, 0x43, 0x30, 0x35, 0x4D, 0x6A, 0x64, 0x6A, 0x4D, 0x47, 0x49, 0x35, 0x4F, 0x43, 0x31, 0x69, 0x59, 0x54, 0x45, 0x34, 0x4C, 0x54, 0x51, 0x35, 0x5A, 0x44, 0x49, 0x74, 0x59, 0x54, 0x59, 0x31, 0x4D, 0x79, 0x30, 0x7A, 0x4D, 0x44, 0x5A, 0x6B, 0x4E, 0x6A, 0x42, 0x6D, 0x4F, 0x44, 0x55, 0x33, 0x4E, 0x54, 0x45, 0x74, 0x4D, 0x79, 0x49, 0x67, 0x65, 0x47, 0x31, 0x73, 0x62, 0x6E, 0x4D, 0x39, 0x49, 0x6D, 0x68, 0x30, 0x64, 0x48, 0x41, 0x36, 0x4C, 0x79, 0x39, 0x6B, 0x62, 0x32, 0x4E, 0x7A, 0x4C, 0x6D, 0x39, 0x68, 0x63, 0x32, 0x6C, 0x7A, 0x4C, 0x57, 0x39, 0x77, 0x5A, 0x57, 0x34, 0x75, 0x62, 0x33, 0x4A, 0x6E, 0x4C, 0x33, 0x64, 0x7A, 0x63, 0x79, 0x38, 0x79, 0x4D, 0x44, 0x41, 0x30, 0x4C, 0x7A, 0x41, 0x78, 0x4C, 0x32, 0x39, 0x68, 0x63, 0x32, 0x6C, 0x7A, 0x4C, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x51, 0x77, 0x4D, 0x53, 0x31, 0x33, 0x63, 0x33, 0x4D, 0x74, 0x64, 0x33, 0x4E, 0x7A, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x31, 0x7A, 0x5A, 0x57, 0x4E, 0x6C, 0x65, 0x48, 0x51, 0x74, 0x4D, 0x53, 0x34, 0x77, 0x4C, 0x6E, 0x68, 0x7A, 0x5A, 0x43, 0x49, 0x67, 0x65, 0x47, 0x31, 0x73, 0x62, 0x6E, 0x4D, 0x36, 0x59, 0x54, 0x30, 0x69, 0x61, 0x48, 0x52, 0x30, 0x63, 0x44, 0x6F, 0x76, 0x4C, 0x32, 0x52, 0x76, 0x59, 0x33, 0x4D, 0x75, 0x62, 0x32, 0x46, 0x7A, 0x61, 0x58, 0x4D, 0x74, 0x62, 0x33, 0x42, 0x6C, 0x62, 0x69, 0x35, 0x76, 0x63, 0x6D, 0x63, 0x76, 0x64, 0x33, 0x4E, 0x7A, 0x4C, 0x7A, 0x49, 0x77, 0x4D, 0x44, 0x51, 0x76, 0x4D, 0x44, 0x45, 0x76, 0x62, 0x32, 0x46, 0x7A, 0x61, 0x58, 0x4D, 0x74, 0x4D, 0x6A, 0x41, 0x77, 0x4E, 0x44, 0x41, 0x78, 0x4C, 0x58, 0x64, 0x7A, 0x63, 0x79, 0x31, 0x33, 0x63, 0x33, 0x4E, 0x6C, 0x59, 0x33, 0x56, 0x79, 0x61, 0x58, 0x52, 0x35, 0x4C, 0x58, 0x56, 0x30, 0x61, 0x57, 0x78, 0x70, 0x64, 0x48, 0x6B, 0x74, 0x4D, 0x53, 0x34, 0x77, 0x4C, 0x6E, 0x68, 0x7A, 0x5A, 0x43, 0x49, 0x2B, 0x50, 0x46, 0x56, 0x7A, 0x5A, 0x58, 0x4A, 0x75, 0x59, 0x57, 0x31, 0x6C, 0x50, 0x6E, 0x56, 0x7A, 0x78, 0x6F, 0x35, 0x79, 0x50, 0x43, 0x39, 0x56, 0x63, 0x32, 0x56, 0x79, 0x62, 0x6D, 0x46, 0x74, 0x5A, 0x54, 0x34, 0x38, 0x55, 0x47, 0x46, 0x7A, 0x63, 0x33, 0x64, 0x76, 0x63, 0x6D, 0x51, 0x67, 0x56, 0x48, 0x6C, 0x77, 0x5A, 0x54, 0x30, 0x69, 0x61, 0x48, 0x52, 0x30, 0x63, 0x44, 0x6F, 0x76, 0x4C, 0x32, 0x52, 0x76, 0x59, 0x33, 0x4D, 0x75, 0x62, 0x32, 0x46, 0x7A, 0x61, 0x58, 0x4D, 0x74, 0x62, 0x33, 0x42, 0x6C, 0x62, 0x69, 0x35, 0x76, 0x63, 0x6D, 0x63, 0x76, 0x64, 0x33, 0x4E, 0x7A, 0x4C, 0x7A, 0x49, 0x77, 0x4D, 0x44, 0x51, 0x76, 0x4D, 0x44, 0x45, 0x76, 0x62, 0x32, 0x46, 0x7A, 0x61, 0x58, 0x4D, 0x74, 0x4D, 0x6A, 0x41, 0x77, 0x4E, 0x44, 0x41, 0x78, 0x4C, 0x58, 0x64, 0x7A, 0x63, 0x79, 0x31, 0x31, 0x63, 0x32, 0x56, 0x79, 0x62, 0x6D, 0x46, 0x74, 0x5A, 0x53, 0x31, 0x30, 0x62, 0x32, 0x74, 0x6C, 0x62, 0x69, 0x31, 0x77, 0x63, 0x6D, 0x39, 0x6D, 0x61, 0x57, 0x78, 0x6C, 0x4C, 0x54, 0x45, 0x75, 0x4D, 0x43, 0x4E, 0x51, 0x59, 0x58, 0x4E, 0x7A, 0x64, 0x32, 0x39, 0x79, 0x5A, 0x46, 0x52, 0x6C, 0x65, 0x48, 0x51, 0x69, 0x50, 0x6E, 0x42, 0x68, 0x63, 0x33, 0x50, 0x43, 0x76, 0x58, 0x64, 0x76, 0x63, 0x6D, 0x51, 0x38, 0x4C, 0x31, 0x42, 0x68, 0x63, 0x33, 0x4E, 0x33, 0x62, 0x33, 0x4A, 0x6B, 0x50, 0x6A, 0x77, 0x76, 0x56, 0x58, 0x4E, 0x6C, 0x63, 0x6D, 0x35, 0x68, 0x62, 0x57, 0x56, 0x55, 0x62, 0x32, 0x74, 0x6C, 0x62, 0x6A, 0x34, 0x3D, 0x0B }; + + [Test] + public void Ctor_StringToken_Works() + { + BootstrapContext bootstrapContext = new BootstrapContext("token"); + + Assert.AreEqual("token", bootstrapContext.Token, "#1"); + Assert.IsNull(bootstrapContext.TokenBytes, "#2"); + Assert.IsNull(bootstrapContext.SecurityToken, "#3"); + Assert.IsNull(bootstrapContext.SecurityTokenHandler, "#4"); + } + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void Ctor_StringToken_NullToken_Throws() + { + BootstrapContext bootstrapContext = new BootstrapContext((string)null); + Assert.Fail("Should have thrown"); + } + + [Test] + public void Serialize_StringToken_Works() + { + BootstrapContext bootstrapContext = new BootstrapContext("token"); + BinaryFormatter binaryFormatter = new BinaryFormatter(); + using (var s = new MemoryStream()) + { + binaryFormatter.Serialize(s, bootstrapContext); + Assert.AreEqual(SerializedBootstrapContextString, s.ToArray(), "#1"); + } + } + + [Test] + public void Deserialize_StringToken_Works() + { + BinaryFormatter binaryFormatter = new BinaryFormatter(); + using (var s = new MemoryStream(SerializedBootstrapContextString)) + { + BootstrapContext bootstrapContext = binaryFormatter.Deserialize(s) as BootstrapContext; + Assert.IsNotNull(bootstrapContext, "#1"); + Assert.AreEqual("token", bootstrapContext.Token, "#2"); + Assert.IsNull(bootstrapContext.TokenBytes, "#3"); + Assert.IsNull(bootstrapContext.SecurityToken, "#4"); + Assert.IsNull(bootstrapContext.SecurityTokenHandler, "#5"); + } + } + + [Test] + public void Ctor_ByteArrayToken_Works() + { + BootstrapContext bootstrapContext = new BootstrapContext(new byte[]{0x01}); + + Assert.IsNotNull(bootstrapContext.TokenBytes, "#1"); + Assert.AreEqual(1, bootstrapContext.TokenBytes.Length, "#2"); + Assert.AreEqual(1, bootstrapContext.TokenBytes[0], "#3"); + Assert.IsNull(bootstrapContext.Token, "#4"); + Assert.IsNull(bootstrapContext.SecurityToken, "#5"); + Assert.IsNull(bootstrapContext.SecurityTokenHandler, "#6"); + } + + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void Ctor_ByteArrayToken_NullToken_Throws() + { + BootstrapContext bootstrapContext = new BootstrapContext((byte[])null); + Assert.Fail("Should have thrown"); + } + + [Test] + public void Serialize_ByteArrayToken_Works() + { + BootstrapContext bootstrapContext = new BootstrapContext(new byte[]{0x1}); + BinaryFormatter binaryFormatter = new BinaryFormatter(); + using (var s = new MemoryStream()) + { + binaryFormatter.Serialize(s, bootstrapContext); + Assert.AreEqual(SerializedBootstrapContextByteArray, s.ToArray(), "#1"); + } + } + + [Test] + public void Deserialize_ByteArrayToken_Works() + { + BinaryFormatter binaryFormatter = new BinaryFormatter(); + using (var s = new MemoryStream(SerializedBootstrapContextByteArray)) + { + BootstrapContext bootstrapContext = binaryFormatter.Deserialize(s) as BootstrapContext; + Assert.IsNotNull(bootstrapContext, "#1"); + Assert.IsNotNull(bootstrapContext.TokenBytes, "#2"); + Assert.AreEqual(1, bootstrapContext.TokenBytes.Length, "#3"); + Assert.AreEqual(1, bootstrapContext.TokenBytes[0], "#4"); + Assert.IsNull(bootstrapContext.Token, "#5"); + Assert.IsNull(bootstrapContext.SecurityToken, "#6"); + Assert.IsNull(bootstrapContext.SecurityTokenHandler, "#7"); + } + } + + [Test] + public void Ctor_SecurityToken_Works() + { + var securityToken = new UserNameSecurityToken(user, password); + var securityTokenHandler = new SimpleSecurityTokenHandler(); + BootstrapContext bootstrapContext = new BootstrapContext(securityToken, securityTokenHandler); + + Assert.IsNotNull(bootstrapContext.SecurityToken, "#1"); + Assert.AreEqual(user, securityToken.UserName, "#2"); + Assert.AreEqual(password, securityToken.Password, "#3"); + Assert.AreEqual(securityTokenHandler, bootstrapContext.SecurityTokenHandler, "#4"); + + Assert.IsNull(bootstrapContext.Token, "#5"); + Assert.IsNull(bootstrapContext.TokenBytes, "#6"); + } + + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void Ctor_SecurityToken_NullToken_Throws() + { + BootstrapContext bootstrapContext = new BootstrapContext(null, new SimpleSecurityTokenHandler()); + Assert.Fail("Should have thrown"); + } + + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void Ctor_SecurityToken_NullHandler_Throws() + { + BootstrapContext bootstrapContext = new BootstrapContext(new UserNameSecurityToken("user", "password"), null); + Assert.Fail("Should have thrown"); + } + + [Test] + public void Serialize_SecurityTokenAndHandler_Works() + { + var securityToken = new UserNameSecurityToken(user, password, "uuid-927c0b98-ba18-49d2-a653-306d60f85751-3"); + var securityTokenHandler = new SimpleSecurityTokenHandler(); + BootstrapContext bootstrapContext = new BootstrapContext(securityToken, securityTokenHandler); + + BinaryFormatter binaryFormatter = new BinaryFormatter(); + using (var s = new MemoryStream()) + { + binaryFormatter.Serialize(s, bootstrapContext); + Assert.AreEqual(SerializedBootstrapContextSecurityToken, s.ToArray(), "#1"); + } + } + + [Test] + public void Deserialize_SecurityTokenAndHandler_Works() + { + BinaryFormatter binaryFormatter = new BinaryFormatter(); + using (var s = new MemoryStream(SerializedBootstrapContextSecurityToken)) + { + BootstrapContext bootstrapContext = binaryFormatter.Deserialize(s) as BootstrapContext; + Assert.IsNotNull(bootstrapContext, "#1"); + Assert.AreEqual(SerializedBootstrapContextSecurityTokenString, bootstrapContext.Token, "#2"); + Assert.IsNull(bootstrapContext.SecurityToken, "#3"); + Assert.IsNull(bootstrapContext.SecurityTokenHandler, "#4"); + Assert.IsNull(bootstrapContext.TokenBytes, "#5"); + } + } + + private class SimpleSecurityTokenHandler : UserNameSecurityTokenHandler + { + public override bool RetainPassword + { + get { return true; } + set { base.RetainPassword = true; } + } + } + } +} +#endif \ No newline at end of file From e2e74c95e634ec68c943cd9e5c50c1d10da27a8d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 21 Sep 2014 14:54:24 -0400 Subject: [PATCH 171/543] [runtime] Fix the unregistration of our exception handler on windows. Fixes #23221. --- mono/mini/exceptions-x86.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index 9c46d34bd20..21a2840e5f6 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -250,8 +250,9 @@ void win32_seh_init() void win32_seh_cleanup() { - if (mono_old_win_toplevel_exception_filter) SetUnhandledExceptionFilter(mono_old_win_toplevel_exception_filter); - RemoveVectoredExceptionHandler (seh_unhandled_exception_filter); + if (mono_old_win_toplevel_exception_filter) + SetUnhandledExceptionFilter(mono_old_win_toplevel_exception_filter); + RemoveVectoredExceptionHandler (mono_win_vectored_exception_handle); } void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler) From 558750f0536cc6ddd0ab589851e16954be6d4a8e Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 21 Sep 2014 17:42:45 -0400 Subject: [PATCH 172/543] [runtime] Fix the windows build. --- mono/utils/mono-threads.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index c6c10ab5ba7..ce0e5be87ef 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -15,7 +15,6 @@ #include #include #include -#include #include From ea77b1f9fbdca61100254750d22ecad5c42b9654 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 01:42:31 +0200 Subject: [PATCH 173/543] [jit] Enable monitor fast paths on win64. --- mono/mini/mini-amd64.h | 9 ++--- mono/mini/tramp-amd64.c | 83 +++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 46 deletions(-) mode change 100644 => 100755 mono/mini/mini-amd64.h mode change 100644 => 100755 mono/mini/tramp-amd64.c diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h old mode 100644 new mode 100755 index e942f578226..1d8a8e0d8ba --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -33,7 +33,7 @@ void amd64_nacl_membase_handler (guint8** code, gint8 basereg, gint32 offset, gi #include #endif - +#if !defined(_MSC_VER) /* sigcontext surrogate */ struct sigcontext { guint64 eax; @@ -46,6 +46,7 @@ struct sigcontext { guint64 edi; guint64 eip; }; +#endif typedef void (* MonoW32ExceptionHandler) (int _dummy, EXCEPTION_POINTERS *info, void *context); void win32_seh_init(void); @@ -340,9 +341,11 @@ typedef struct { #ifdef HOST_WIN32 #define MONO_AMD64_ARG_REG1 AMD64_RCX #define MONO_AMD64_ARG_REG2 AMD64_RDX +#define MONO_AMD64_ARG_REG3 AMD64_R8 #else #define MONO_AMD64_ARG_REG1 AMD64_RDI #define MONO_AMD64_ARG_REG2 AMD64_RSI +#define MONO_AMD64_ARG_REG3 AMD64_RDX #endif #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS @@ -375,9 +378,7 @@ typedef struct { #define MONO_ARCH_HAVE_LIVERANGE_OPS 1 #define MONO_ARCH_HAVE_XP_UNWIND 1 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1 -#if !defined(HOST_WIN32) #define MONO_ARCH_MONITOR_OBJECT_REG MONO_AMD64_ARG_REG1 -#endif #define MONO_ARCH_HAVE_GET_TRAMPOLINES 1 #define MONO_ARCH_AOT_SUPPORTED 1 @@ -385,9 +386,7 @@ typedef struct { #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1 #endif -#if !defined(HOST_WIN32) || defined(__sun) #define MONO_ARCH_ENABLE_MONITOR_IL_FASTPATH 1 -#endif #define MONO_ARCH_SUPPORT_TASKLETS 1 diff --git a/mono/mini/tramp-amd64.c b/mono/mini/tramp-amd64.c old mode 100644 new mode 100755 index 9ba8502250f..eea2ce661b8 --- a/mono/mini/tramp-amd64.c +++ b/mono/mini/tramp-amd64.c @@ -946,8 +946,6 @@ mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean a return buf; } -#ifdef MONO_ARCH_MONITOR_OBJECT_REG - gpointer mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot) { @@ -958,8 +956,11 @@ mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot) int owner_offset, nest_offset, dummy; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; + int obj_reg = MONO_AMD64_ARG_REG1; + int sync_reg = MONO_AMD64_ARG_REG2; + int tid_reg = MONO_AMD64_ARG_REG3; - g_assert (MONO_ARCH_MONITOR_OBJECT_REG == AMD64_RDI); + g_assert (MONO_ARCH_MONITOR_OBJECT_REG == obj_reg); mono_monitor_threads_sync_members_offset (&owner_offset, &nest_offset, &dummy); g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (owner_offset) == sizeof (gpointer)); @@ -974,50 +975,51 @@ mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot) unwind_ops = mono_arch_get_cie_program (); if (!aot && mono_thread_get_tls_offset () != -1) { - /* MonoObject* obj is in RDI */ + /* MonoObject* obj is in obj_reg */ /* is obj null? */ - amd64_test_reg_reg (code, AMD64_RDI, AMD64_RDI); + amd64_test_reg_reg (code, obj_reg, obj_reg); /* if yes, jump to actual trampoline */ jump_obj_null = code; amd64_branch8 (code, X86_CC_Z, -1, 1); - /* load obj->synchronization to RCX */ - amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RDI, MONO_STRUCT_OFFSET (MonoObject, synchronisation), 8); + /* load obj->synchronization to sync_reg */ + amd64_mov_reg_membase (code, sync_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, synchronisation), 8); if (mono_gc_is_moving ()) { /*if bit zero is set it's a thin hash*/ /*FIXME use testb encoding*/ - amd64_test_reg_imm (code, AMD64_RCX, 0x01); + amd64_test_reg_imm (code, sync_reg, 0x01); jump_sync_thin_hash = code; amd64_branch8 (code, X86_CC_NE, -1, 1); /*clear bits used by the gc*/ - amd64_alu_reg_imm (code, X86_AND, AMD64_RCX, ~0x3); + amd64_alu_reg_imm (code, X86_AND, sync_reg, ~0x3); } /* is synchronization null? */ - amd64_test_reg_reg (code, AMD64_RCX, AMD64_RCX); + amd64_test_reg_reg (code, sync_reg, sync_reg); /* if yes, jump to actual trampoline */ jump_sync_null = code; amd64_branch8 (code, X86_CC_Z, -1, 1); - /* load MonoInternalThread* into RDX */ - code = mono_amd64_emit_tls_get (code, AMD64_RDX, mono_thread_get_tls_offset ()); - /* load TID into RDX */ - amd64_mov_reg_membase (code, AMD64_RDX, AMD64_RDX, MONO_STRUCT_OFFSET (MonoInternalThread, tid), 8); + /* load MonoInternalThread* into tid_reg */ + code = mono_amd64_emit_tls_get (code, tid_reg, mono_thread_get_tls_offset ()); + /* load TID into tid_reg */ + amd64_mov_reg_membase (code, tid_reg, tid_reg, MONO_STRUCT_OFFSET (MonoInternalThread, tid), 8); /* is synchronization->owner null? */ - amd64_alu_membase_imm_size (code, X86_CMP, AMD64_RCX, owner_offset, 0, 8); + amd64_alu_membase_imm_size (code, X86_CMP, sync_reg, owner_offset, 0, 8); /* if not, jump to next case */ jump_tid = code; amd64_branch8 (code, X86_CC_NZ, -1, 1); /* if yes, try a compare-exchange with the TID */ + g_assert (tid_reg != X86_EAX); /* zero RAX */ amd64_alu_reg_reg (code, X86_XOR, AMD64_RAX, AMD64_RAX); /* compare and exchange */ amd64_prefix (code, X86_LOCK_PREFIX); - amd64_cmpxchg_membase_reg_size (code, AMD64_RCX, owner_offset, AMD64_RDX, 8); + amd64_cmpxchg_membase_reg_size (code, sync_reg, owner_offset, tid_reg, 8); /* if not successful, jump to actual trampoline */ jump_cmpxchg_failed = code; amd64_branch8 (code, X86_CC_NZ, -1, 1); @@ -1027,12 +1029,12 @@ mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot) /* next case: synchronization->owner is not null */ x86_patch (jump_tid, code); /* is synchronization->owner == TID? */ - amd64_alu_membase_reg_size (code, X86_CMP, AMD64_RCX, owner_offset, AMD64_RDX, 8); + amd64_alu_membase_reg_size (code, X86_CMP, sync_reg, owner_offset, tid_reg, 8); /* if not, jump to actual trampoline */ jump_other_owner = code; amd64_branch8 (code, X86_CC_NZ, -1, 1); /* if yes, increment nest */ - amd64_inc_membase_size (code, AMD64_RCX, nest_offset, 4); + amd64_inc_membase_size (code, sync_reg, nest_offset, 4); /* return */ amd64_ret (code); @@ -1045,9 +1047,8 @@ mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot) } /* jump to the actual trampoline */ -#if MONO_AMD64_ARG_REG1 != AMD64_RDI - amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, AMD64_RDI); -#endif + if (MONO_AMD64_ARG_REG1 != obj_reg) + amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, obj_reg, sizeof (mgreg_t)); if (aot) { code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "specific_trampoline_monitor_enter"); @@ -1081,8 +1082,10 @@ mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot) int owner_offset, nest_offset, entry_count_offset; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; + int obj_reg = MONO_AMD64_ARG_REG1; + int sync_reg = MONO_AMD64_ARG_REG2; - g_assert (MONO_ARCH_MONITOR_OBJECT_REG == AMD64_RDI); + g_assert (obj_reg == MONO_ARCH_MONITOR_OBJECT_REG); mono_monitor_threads_sync_members_offset (&owner_offset, &nest_offset, &entry_count_offset); g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (owner_offset) == sizeof (gpointer)); @@ -1099,63 +1102,63 @@ mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot) unwind_ops = mono_arch_get_cie_program (); if (!aot && mono_thread_get_tls_offset () != -1) { - /* MonoObject* obj is in RDI */ + /* MonoObject* obj is in obj_reg */ /* is obj null? */ - amd64_test_reg_reg (code, AMD64_RDI, AMD64_RDI); + amd64_test_reg_reg (code, obj_reg, obj_reg); /* if yes, jump to actual trampoline */ jump_obj_null = code; amd64_branch8 (code, X86_CC_Z, -1, 1); /* load obj->synchronization to RCX */ - amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RDI, MONO_STRUCT_OFFSET (MonoObject, synchronisation), 8); + amd64_mov_reg_membase (code, sync_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, synchronisation), 8); if (mono_gc_is_moving ()) { /*if bit zero is set it's a thin hash*/ /*FIXME use testb encoding*/ - amd64_test_reg_imm (code, AMD64_RCX, 0x01); + amd64_test_reg_imm (code, sync_reg, 0x01); jump_sync_thin_hash = code; amd64_branch8 (code, X86_CC_NE, -1, 1); /*clear bits used by the gc*/ - amd64_alu_reg_imm (code, X86_AND, AMD64_RCX, ~0x3); + amd64_alu_reg_imm (code, X86_AND, sync_reg, ~0x3); } /* is synchronization null? */ - amd64_test_reg_reg (code, AMD64_RCX, AMD64_RCX); + amd64_test_reg_reg (code, sync_reg, sync_reg); /* if yes, jump to actual trampoline */ jump_sync_null = code; amd64_branch8 (code, X86_CC_Z, -1, 1); /* next case: synchronization is not null */ - /* load MonoInternalThread* into RDX */ - code = mono_amd64_emit_tls_get (code, AMD64_RDX, mono_thread_get_tls_offset ()); - /* load TID into RDX */ - amd64_mov_reg_membase (code, AMD64_RDX, AMD64_RDX, MONO_STRUCT_OFFSET (MonoInternalThread, tid), 8); + /* load MonoInternalThread* into RAX */ + code = mono_amd64_emit_tls_get (code, AMD64_RAX, mono_thread_get_tls_offset ()); + /* load TID into RAX */ + amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, MONO_STRUCT_OFFSET (MonoInternalThread, tid), 8); /* is synchronization->owner == TID */ - amd64_alu_membase_reg_size (code, X86_CMP, AMD64_RCX, owner_offset, AMD64_RDX, 8); + amd64_alu_membase_reg_size (code, X86_CMP, sync_reg, owner_offset, AMD64_RAX, 8); /* if no, jump to actual trampoline */ jump_not_owned = code; amd64_branch8 (code, X86_CC_NZ, -1, 1); /* next case: synchronization->owner == TID */ /* is synchronization->nest == 1 */ - amd64_alu_membase_imm_size (code, X86_CMP, AMD64_RCX, nest_offset, 1, 4); + amd64_alu_membase_imm_size (code, X86_CMP, sync_reg, nest_offset, 1, 4); /* if not, jump to next case */ jump_next = code; amd64_branch8 (code, X86_CC_NZ, -1, 1); /* if yes, is synchronization->entry_count zero? */ - amd64_alu_membase_imm_size (code, X86_CMP, AMD64_RCX, entry_count_offset, 0, 4); + amd64_alu_membase_imm_size (code, X86_CMP, sync_reg, entry_count_offset, 0, 4); /* if not, jump to actual trampoline */ jump_have_waiters = code; amd64_branch8 (code, X86_CC_NZ, -1 , 1); /* if yes, set synchronization->owner to null and return */ - amd64_mov_membase_imm (code, AMD64_RCX, owner_offset, 0, 8); + amd64_mov_membase_imm (code, sync_reg, owner_offset, 0, 8); amd64_ret (code); /* next case: synchronization->nest is not 1 */ x86_patch (jump_next, code); /* decrease synchronization->nest and return */ - amd64_dec_membase_size (code, AMD64_RCX, nest_offset, 4); + amd64_dec_membase_size (code, sync_reg, nest_offset, 4); amd64_ret (code); x86_patch (jump_obj_null, code); @@ -1165,9 +1168,8 @@ mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot) } /* jump to the actual trampoline */ -#if MONO_AMD64_ARG_REG1 != AMD64_RDI - amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, AMD64_RDI); -#endif + if (MONO_AMD64_ARG_REG1 != obj_reg) + amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, obj_reg, sizeof (mgreg_t)); if (aot) { code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "specific_trampoline_monitor_exit"); @@ -1187,7 +1189,6 @@ mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot) return buf; } -#endif void mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg) From dfb8d2ac8e8a2b7a86e673cd2c306febb1cc2fa5 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 21 Sep 2014 22:00:52 -0400 Subject: [PATCH 174/543] [jit] Implement the pushless call code on winx64. --- mono/mini/cpu-amd64.md | 4 ++-- mono/mini/mini-amd64.c | 24 ++++++++++++++---------- 2 files changed, 16 insertions(+), 12 deletions(-) mode change 100644 => 100755 mono/mini/cpu-amd64.md mode change 100644 => 100755 mono/mini/mini-amd64.c diff --git a/mono/mini/cpu-amd64.md b/mono/mini/cpu-amd64.md old mode 100644 new mode 100755 index bb6f32f9e6b..be535210a6d --- a/mono/mini/cpu-amd64.md +++ b/mono/mini/cpu-amd64.md @@ -114,7 +114,7 @@ cgt: dest:c len:8 cgt.un: dest:c len:8 clt: dest:c len:8 clt.un: dest:c len:8 -localloc: dest:i src1:i len:84 +localloc: dest:i src1:i len:96 compare: src1:i src2:i len:3 lcompare: src1:i src2:i len:3 icompare: src1:i src2:i len:3 @@ -511,7 +511,7 @@ vcall2_membase: src1:b len:64 clob:c dyn_call: src1:i src2:i len:64 clob:c nacl:128 -localloc_imm: dest:i len:84 +localloc_imm: dest:i len:96 load_mem: dest:i len:16 loadi8_mem: dest:i len:16 diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c old mode 100644 new mode 100755 index 212b8a283c3..9461265a1a6 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -85,7 +85,7 @@ static int breakpoint_fault_size; /* The size of the single step instruction causing the actual fault */ static int single_step_fault_size; -#ifdef HOST_WIN32 +#if defined(HOST_WIN32) && !defined(MONO_AMD64_NO_PUSHES) /* On Win64 always reserve first 32 bytes for first four arguments */ #define ARGS_OFFSET 48 #else @@ -940,6 +940,11 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign gr = 0; fr = 0; +#if defined(HOST_WIN32) && defined(MONO_AMD64_NO_PUSHES) + /* Reserve space where the callee can save the argument registers */ + stack_size = 4 * sizeof (mgreg_t); +#endif + /* return value */ { ret_type = mini_type_get_underlying_type (gsctx, sig->ret); @@ -1107,6 +1112,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign add_valuetype (gsctx, sig, ainfo, sig->params [i], FALSE, &gr, &fr, &stack_size); break; case MONO_TYPE_U8: + case MONO_TYPE_I8: add_general (&gr, &stack_size, ainfo); break; @@ -1129,7 +1135,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign add_general (&gr, &stack_size, &cinfo->sig_cookie); } -#ifdef HOST_WIN32 +#if defined(HOST_WIN32) && !defined(MONO_AMD64_NO_PUSHES) // There always is 32 bytes reserved on the stack when calling on Winx64 stack_size += 0x20; #endif @@ -1991,16 +1997,14 @@ mono_arch_create_vars (MonoCompile *cfg) cfg->arch.ss_trigger_page_var = ins; } -#ifdef MONO_AMD64_NO_PUSHES /* * When this is set, we pass arguments on the stack by moves, and by allocating * a bigger stack frame, instead of pushes. * Pushes complicate exception handling because the arguments on the stack have * to be popped each time a frame is unwound. They also make fp elimination * impossible. - * FIXME: This doesn't work inside filter/finally clauses, since those execute - * on a new frame which doesn't include a param area. */ +#ifdef MONO_AMD64_NO_PUSHES cfg->arch.no_pushes = TRUE; #endif @@ -2441,7 +2445,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } } -#ifdef HOST_WIN32 +#if defined(HOST_WIN32) && !defined(MONO_AMD64_NO_PUSHES) if (call->inst.opcode != OP_TAILCALL) { MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 0x20); } @@ -2494,8 +2498,6 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) MonoInst *vtaddr, *load; vtaddr = mono_compile_create_var (cfg, &ins->klass->byval_arg, OP_LOCAL); - g_assert (!cfg->arch.no_pushes); - MONO_INST_NEW (cfg, load, OP_LDADDR); cfg->has_indirection = TRUE; load->inst_p0 = vtaddr; @@ -2513,6 +2515,8 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) arg->inst_imm = 0; MONO_ADD_INS (cfg->cbb, arg); mono_call_inst_add_outarg_reg (cfg, call, arg->dreg, ainfo->pair_regs [0], FALSE); + } else if (cfg->arch.no_pushes) { + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, ainfo->offset, load->dreg); } else { MONO_INST_NEW (cfg, arg, OP_X86_PUSH); arg->sreg1 = load->dreg; @@ -8426,7 +8430,7 @@ mono_arch_is_breakpoint_event (void *info, void *sigctx) { #ifdef HOST_WIN32 EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; - if (einfo->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && einfo->ExceptionInformation [1] == bp_trigger_page) + if (einfo->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && (gpointer)einfo->ExceptionInformation [1] == bp_trigger_page) return TRUE; else return FALSE; @@ -8490,7 +8494,7 @@ mono_arch_is_single_step_event (void *info, void *sigctx) { #ifdef HOST_WIN32 EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; - if (einfo->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && einfo->ExceptionInformation [1] == ss_trigger_page) + if (einfo->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && (gpointer)einfo->ExceptionInformation [1] == ss_trigger_page) return TRUE; else return FALSE; From d5a18ba292367e375d215ca2351cf1fa9b0a1d8e Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 21 Sep 2014 22:21:41 -0400 Subject: [PATCH 175/543] [jit] Enable the pushless call code on windows too, get rid of the non-pushless code. --- mono/mini/mini-amd64.c | 181 ++++++++++------------------------------- mono/mini/mini-amd64.h | 6 +- 2 files changed, 42 insertions(+), 145 deletions(-) diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 9461265a1a6..93e657da00e 100755 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -85,12 +85,8 @@ static int breakpoint_fault_size; /* The size of the single step instruction causing the actual fault */ static int single_step_fault_size; -#if defined(HOST_WIN32) && !defined(MONO_AMD64_NO_PUSHES) -/* On Win64 always reserve first 32 bytes for first four arguments */ -#define ARGS_OFFSET 48 -#else +/* Offset between fp and the first argument in the callee */ #define ARGS_OFFSET 16 -#endif #define GP_SCRATCH_REG AMD64_R11 /* @@ -940,7 +936,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign gr = 0; fr = 0; -#if defined(HOST_WIN32) && defined(MONO_AMD64_NO_PUSHES) +#ifdef HOST_WIN32 /* Reserve space where the callee can save the argument registers */ stack_size = 4 * sizeof (mgreg_t); #endif @@ -1135,19 +1131,6 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign add_general (&gr, &stack_size, &cinfo->sig_cookie); } -#if defined(HOST_WIN32) && !defined(MONO_AMD64_NO_PUSHES) - // There always is 32 bytes reserved on the stack when calling on Winx64 - stack_size += 0x20; -#endif - -#ifndef MONO_AMD64_NO_PUSHES - if (stack_size & 0x8) { - /* The AMD64 ABI requires each stack frame to be 16 byte aligned */ - cinfo->need_stack_align = TRUE; - stack_size += 8; - } -#endif - cinfo->stack_usage = stack_size; cinfo->reg_usage = gr; cinfo->freg_usage = fr; @@ -1997,17 +1980,6 @@ mono_arch_create_vars (MonoCompile *cfg) cfg->arch.ss_trigger_page_var = ins; } - /* - * When this is set, we pass arguments on the stack by moves, and by allocating - * a bigger stack frame, instead of pushes. - * Pushes complicate exception handling because the arguments on the stack have - * to be popped each time a frame is unwound. They also make fp elimination - * impossible. - */ -#ifdef MONO_AMD64_NO_PUSHES - cfg->arch.no_pushes = TRUE; -#endif - if (cfg->method->save_lmf) cfg->create_lmf_var = TRUE; @@ -2019,7 +1991,7 @@ mono_arch_create_vars (MonoCompile *cfg) #endif } -#ifndef MONO_AMD64_NO_PUSHES +#ifndef HOST_WIN32 cfg->arch_eh_jit_info = 1; #endif } @@ -2106,13 +2078,7 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) sig_reg = mono_alloc_ireg (cfg); MONO_EMIT_NEW_SIGNATURECONST (cfg, sig_reg, tmp_sig); - if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, cinfo->sig_cookie.offset, sig_reg); - } else { - MONO_INST_NEW (cfg, arg, OP_X86_PUSH); - arg->sreg1 = sig_reg; - MONO_ADD_INS (cfg->cbb, arg); - } + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, cinfo->sig_cookie.offset, sig_reg); } static inline LLVMArgStorage @@ -2249,43 +2215,36 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) return; } - if (cinfo->need_stack_align) { - if (!cfg->arch.no_pushes) - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 8); - } - /* * Emit all arguments which are passed on the stack to prevent register * allocation problems. */ - if (cfg->arch.no_pushes) { - for (i = 0; i < n; ++i) { - MonoType *t; - ainfo = cinfo->args + i; + for (i = 0; i < n; ++i) { + MonoType *t; + ainfo = cinfo->args + i; - in = call->args [i]; + in = call->args [i]; - if (sig->hasthis && i == 0) - t = &mono_defaults.object_class->byval_arg; - else - t = sig->params [i - sig->hasthis]; + if (sig->hasthis && i == 0) + t = &mono_defaults.object_class->byval_arg; + else + t = sig->params [i - sig->hasthis]; - if (ainfo->storage == ArgOnStack && !MONO_TYPE_ISSTRUCT (t) && !call->tail_call) { - if (!t->byref) { - if (t->type == MONO_TYPE_R4) - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, AMD64_RSP, ainfo->offset, in->dreg); - else if (t->type == MONO_TYPE_R8) - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, AMD64_RSP, ainfo->offset, in->dreg); - else - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, ainfo->offset, in->dreg); - } else { + if (ainfo->storage == ArgOnStack && !MONO_TYPE_ISSTRUCT (t) && !call->tail_call) { + if (!t->byref) { + if (t->type == MONO_TYPE_R4) + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, AMD64_RSP, ainfo->offset, in->dreg); + else if (t->type == MONO_TYPE_R8) + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, AMD64_RSP, ainfo->offset, in->dreg); + else MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, ainfo->offset, in->dreg); - } - if (cfg->compute_gc_maps) { - MonoInst *def; + } else { + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, ainfo->offset, in->dreg); + } + if (cfg->compute_gc_maps) { + MonoInst *def; - EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t); - } + EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t); } } } @@ -2362,27 +2321,6 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) arg->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo)); memcpy (arg->inst_p1, ainfo, sizeof (ArgInfo)); - MONO_ADD_INS (cfg->cbb, arg); - } - } else { - if (cfg->arch.no_pushes) { - /* Already done */ - } else { - MONO_INST_NEW (cfg, arg, OP_X86_PUSH); - arg->sreg1 = in->dreg; - if (!sig->params [i - sig->hasthis]->byref) { - if (sig->params [i - sig->hasthis]->type == MONO_TYPE_R4) { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 8); - arg->opcode = OP_STORER4_MEMBASE_REG; - arg->inst_destbasereg = X86_ESP; - arg->inst_offset = 0; - } else if (sig->params [i - sig->hasthis]->type == MONO_TYPE_R8) { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 8); - arg->opcode = OP_STORER8_MEMBASE_REG; - arg->inst_destbasereg = X86_ESP; - arg->inst_offset = 0; - } - } MONO_ADD_INS (cfg->cbb, arg); } } @@ -2445,12 +2383,6 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } } -#if defined(HOST_WIN32) && !defined(MONO_AMD64_NO_PUSHES) - if (call->inst.opcode != OP_TAILCALL) { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 0x20); - } -#endif - if (cfg->method->save_lmf) { MONO_INST_NEW (cfg, arg, OP_AMD64_SAVE_SP_TO_LMF); MONO_ADD_INS (cfg->cbb, arg); @@ -2515,45 +2447,20 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) arg->inst_imm = 0; MONO_ADD_INS (cfg->cbb, arg); mono_call_inst_add_outarg_reg (cfg, call, arg->dreg, ainfo->pair_regs [0], FALSE); - } else if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, ainfo->offset, load->dreg); } else { - MONO_INST_NEW (cfg, arg, OP_X86_PUSH); - arg->sreg1 = load->dreg; - MONO_ADD_INS (cfg->cbb, arg); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, ainfo->offset, load->dreg); } } else { if (size == 8) { - if (cfg->arch.no_pushes) { - int dreg = mono_alloc_ireg (cfg); + int dreg = mono_alloc_ireg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, 0); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, ainfo->offset, dreg); - } else { - /* Can't use this for < 8 since it does an 8 byte memory load */ - MONO_INST_NEW (cfg, arg, OP_X86_PUSH_MEMBASE); - arg->inst_basereg = src->dreg; - arg->inst_offset = 0; - MONO_ADD_INS (cfg->cbb, arg); - } + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, 0); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, ainfo->offset, dreg); } else if (size <= 40) { - if (cfg->arch.no_pushes) { - mini_emit_memcpy (cfg, AMD64_RSP, ainfo->offset, src->dreg, 0, size, 4); - } else { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, ALIGN_TO (size, 8)); - mini_emit_memcpy (cfg, X86_ESP, 0, src->dreg, 0, size, 4); - } + mini_emit_memcpy (cfg, AMD64_RSP, ainfo->offset, src->dreg, 0, size, 4); } else { - if (cfg->arch.no_pushes) { - // FIXME: Code growth - mini_emit_memcpy (cfg, AMD64_RSP, ainfo->offset, src->dreg, 0, size, 4); - } else { - MONO_INST_NEW (cfg, arg, OP_X86_PUSH_OBJ); - arg->inst_basereg = src->dreg; - arg->inst_offset = 0; - arg->inst_imm = size; - MONO_ADD_INS (cfg->cbb, arg); - } + // FIXME: Code growth + mini_emit_memcpy (cfg, AMD64_RSP, ainfo->offset, src->dreg, 0, size, 4); } if (cfg->compute_gc_maps) { @@ -3465,7 +3372,7 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree) amd64_alu_reg_reg (code, X86_XOR, AMD64_RAX, AMD64_RAX); amd64_lea_membase (code, AMD64_RDI, AMD64_RSP, offset); - if (cfg->param_area && cfg->arch.no_pushes) + if (cfg->param_area) amd64_alu_reg_imm (code, X86_ADD, AMD64_RDI, cfg->param_area); amd64_cld (code); #if defined(__default_codegen__) @@ -4775,8 +4682,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, call->fptr, FALSE); ins->flags |= MONO_INST_GC_CALLSITE; ins->backend.pc_offset = code - cfg->native_code; - if (call->stack_usage && !CALLCONV_IS_STDCALL (call->signature->call_convention) && !cfg->arch.no_pushes) - amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, call->stack_usage); code = emit_move_return_value (cfg, ins, code); break; case OP_FCALL_REG: @@ -4825,8 +4730,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_call_reg (code, ins->sreg1); ins->flags |= MONO_INST_GC_CALLSITE; ins->backend.pc_offset = code - cfg->native_code; - if (call->stack_usage && !CALLCONV_IS_STDCALL (call->signature->call_convention) && !cfg->arch.no_pushes) - amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, call->stack_usage); code = emit_move_return_value (cfg, ins, code); break; case OP_FCALL_MEMBASE: @@ -4840,8 +4743,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_call_membase (code, ins->sreg1, ins->inst_offset); ins->flags |= MONO_INST_GC_CALLSITE; ins->backend.pc_offset = code - cfg->native_code; - if (call->stack_usage && !CALLCONV_IS_STDCALL (call->signature->call_convention) && !cfg->arch.no_pushes) - amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, call->stack_usage); code = emit_move_return_value (cfg, ins, code); break; case OP_DYN_CALL: { @@ -4879,22 +4780,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; } case OP_X86_PUSH: - g_assert (!cfg->arch.no_pushes); + g_assert_not_reached (); amd64_push_reg (code, ins->sreg1); break; case OP_X86_PUSH_IMM: - g_assert (!cfg->arch.no_pushes); + g_assert_not_reached (); g_assert (amd64_is_imm32 (ins->inst_imm)); amd64_push_imm (code, ins->inst_imm); break; case OP_X86_PUSH_MEMBASE: - g_assert (!cfg->arch.no_pushes); + g_assert_not_reached (); amd64_push_membase (code, ins->inst_basereg, ins->inst_offset); break; case OP_X86_PUSH_OBJ: { int size = ALIGN_TO (ins->inst_imm, 8); - g_assert (!cfg->arch.no_pushes); + g_assert_not_reached (); amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, size); amd64_push_reg (code, AMD64_RDI); @@ -4929,7 +4830,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ~(MONO_ARCH_FRAME_ALIGNMENT - 1)); code = mono_emit_stack_alloc (cfg, code, ins); amd64_mov_reg_reg (code, ins->dreg, AMD64_RSP, 8); - if (cfg->param_area && cfg->arch.no_pushes) + if (cfg->param_area) amd64_alu_reg_imm (code, X86_ADD, ins->dreg, cfg->param_area); break; case OP_LOCALLOC_IMM: { @@ -4957,7 +4858,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, size); amd64_mov_reg_reg (code, ins->dreg, AMD64_RSP, 8); } - if (cfg->param_area && cfg->arch.no_pushes) + if (cfg->param_area) amd64_alu_reg_imm (code, X86_ADD, ins->dreg, cfg->param_area); break; } @@ -4995,7 +4896,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) if ((MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_FINALLY) || MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_FINALLY)) && - cfg->param_area && cfg->arch.no_pushes) { + cfg->param_area) { amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); } break; @@ -6597,7 +6498,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* The param area is always at offset 0 from sp */ /* This needs to be allocated here, since it has to come after the spill area */ - if (cfg->arch.no_pushes && cfg->param_area) { + if (cfg->param_area) { if (cfg->arch.omit_fp) // FIXME: g_assert_not_reached (); diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index 1d8a8e0d8ba..2a017149f1f 100755 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -192,7 +192,7 @@ typedef struct MonoCompileArch { gint32 stack_alloc_size; gint32 sp_fp_offset; guint32 saved_iregs; - gboolean omit_fp, omit_fp_computed, no_pushes; + gboolean omit_fp, omit_fp_computed; gpointer cinfo; gint32 async_point_count; gpointer vret_addr_loc; @@ -390,10 +390,6 @@ typedef struct { #define MONO_ARCH_SUPPORT_TASKLETS 1 -#ifndef HOST_WIN32 -#define MONO_AMD64_NO_PUSHES 1 -#endif - #define MONO_ARCH_GSHARED_SUPPORTED 1 #define MONO_ARCH_DYN_CALL_SUPPORTED 1 #define MONO_ARCH_DYN_CALL_PARAM_AREA 0 From ac2e2c770317a710453043b732a7e48a668b019d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 21 Sep 2014 22:48:42 -0400 Subject: [PATCH 176/543] [runtime] Disable a few more tests on windows which hang on winx64. --- mono/tests/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 7d448d374ad..9675e71b5cb 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -435,7 +435,8 @@ endif if X86 if HOST_WIN32 -PLATFORM_DISABLED_TESTS=async-exc-compilation.exe finally_guard.exe finally_block_ending_in_dead_bb.exe +PLATFORM_DISABLED_TESTS=async-exc-compilation.exe finally_guard.exe finally_block_ending_in_dead_bb.exe \ + bug-18026.exe monitor.exe threadpool-exceptions5.exe endif endif From 12dc660454c583583ea472d8ed9eab030feed48b Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 21 Sep 2014 23:07:30 -0400 Subject: [PATCH 177/543] [runtime] Enable fp elimination on winx64. --- mono/mini/mini-amd64.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 93e657da00e..ffdc7c973ba 100755 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -1396,10 +1396,6 @@ mono_arch_compute_omit_fp (MonoCompile *cfg) cfg->arch.omit_fp = FALSE; #endif -#ifdef HOST_WIN32 - cfg->arch.omit_fp = FALSE; -#endif - if (cfg->disable_omit_fp) cfg->arch.omit_fp = FALSE; From e0a408f702b948e8c8d50c8ee3303ff0360c03fc Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 06:40:26 +0200 Subject: [PATCH 178/543] [runtime] Treat the tls key as the tls offset on windows, since they are the same. --- mono/metadata/domain.c | 8 ++++++-- mono/mini/mini.c | 19 +++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) mode change 100644 => 100755 mono/metadata/domain.c mode change 100644 => 100755 mono/mini/mini.c diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c old mode 100644 new mode 100755 index b1b912f4e9b..013e73b6910 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -160,9 +160,13 @@ gint32 mono_domain_get_tls_offset (void) { int offset = -1; + +#ifdef HOST_WIN32 + if (appdomain_thread_id) + offset = appdomain_thread_id; +#else MONO_THREAD_VAR_OFFSET (tls_appdomain, offset); -/* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:" - : "=r" (offset));*/ +#endif return offset; } diff --git a/mono/mini/mini.c b/mono/mini/mini.c old mode 100644 new mode 100755 index a31e9003a13..e2e385568f3 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -2629,17 +2629,20 @@ MONO_FAST_TLS_DECLARE(mono_lmf); #endif #endif -MonoNativeTlsKey -mono_get_jit_tls_key (void) -{ - return mono_jit_tls_id; -} - gint32 mono_get_jit_tls_offset (void) { int offset; + +#ifdef HOST_WIN32 + if (mono_jit_tls_id) + offset = mono_jit_tls_id; + else + /* FIXME: Happens during startup */ + offset = -1; +#else MONO_THREAD_VAR_OFFSET (mono_jit_tls, offset); +#endif return offset; } @@ -2952,11 +2955,7 @@ mini_get_tls_offset (MonoTlsKey key) offset = mono_thread_get_tls_offset (); break; case TLS_KEY_JIT_TLS: -#ifdef HOST_WIN32 - offset = mono_get_jit_tls_key (); -#else offset = mono_get_jit_tls_offset (); -#endif break; case TLS_KEY_DOMAIN: offset = mono_domain_get_tls_offset (); From f930824ea9b04dd7dfc2bcc41998bc0614b5b472 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 06:41:23 +0200 Subject: [PATCH 179/543] [runtime] Enable the fastpath in CEE_MONO_JIT_ATTACH on windows. --- mono/mini/method-to-ir.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) mode change 100644 => 100755 mono/mini/method-to-ir.c diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c old mode 100644 new mode 100755 index f035037d64e..4db81265757 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -11608,7 +11608,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } case CEE_MONO_JIT_ATTACH: { MonoInst *args [16], *domain_ins; - MonoInst *ad_ins, *lmf_ins; + MonoInst *ad_ins, *jit_tls_ins; MonoBasicBlock *next_bb = NULL, *call_bb = NULL; cfg->orig_domain_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL); @@ -11616,15 +11616,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b EMIT_NEW_PCONST (cfg, ins, NULL); MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg); -#if TARGET_WIN32 - ad_ins = NULL; - lmf_ins = NULL; -#else ad_ins = mono_get_domain_intrinsic (cfg); - lmf_ins = mono_get_lmf_intrinsic (cfg); -#endif + jit_tls_ins = mono_get_jit_tls_intrinsic (cfg); - if (MONO_ARCH_HAVE_TLS_GET && ad_ins && lmf_ins) { + if (MONO_ARCH_HAVE_TLS_GET && ad_ins && jit_tls_ins) { NEW_BBLOCK (cfg, next_bb); NEW_BBLOCK (cfg, call_bb); @@ -11638,8 +11633,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, ad_ins->dreg, domain_ins->dreg); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, call_bb); - MONO_ADD_INS (cfg->cbb, lmf_ins); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, lmf_ins->dreg, 0); + MONO_ADD_INS (cfg->cbb, jit_tls_ins); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, jit_tls_ins->dreg, 0); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, call_bb); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, next_bb); From 12bceb1700a2663fa88933113d482fcc70f7fbfa Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 06:41:52 +0200 Subject: [PATCH 180/543] [jit] Fix the handler block trampolines on windows. --- mono/mini/tramp-amd64.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mono/mini/tramp-amd64.c b/mono/mini/tramp-amd64.c index eea2ce661b8..cfc14ee2a4e 100755 --- a/mono/mini/tramp-amd64.c +++ b/mono/mini/tramp-amd64.c @@ -522,7 +522,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf amd64_mov_reg_imm (code, AMD64_R11, 0); amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, 8); } else { - amd64_mov_reg_imm (code, AMD64_RDI, tramp_type); + amd64_mov_reg_imm (code, MONO_AMD64_ARG_REG1, tramp_type); amd64_mov_reg_imm (code, AMD64_R11, stack_unaligned); amd64_call_reg (code, AMD64_R11); } @@ -1227,18 +1227,18 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot) /* This trampoline restore the call chain of the handler block then jumps into the code that deals with it. */ - if (mono_get_jit_tls_offset () != -1) { - code = mono_amd64_emit_tls_get (code, AMD64_RDI, mono_get_jit_tls_offset ()); - amd64_mov_reg_membase (code, AMD64_RDI, AMD64_RDI, MONO_STRUCT_OFFSET (MonoJitTlsData, handler_block_return_address), 8); + code = mono_amd64_emit_tls_get (code, MONO_AMD64_ARG_REG1, mono_get_jit_tls_offset ()); + amd64_mov_reg_membase (code, MONO_AMD64_ARG_REG1, MONO_AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoJitTlsData, handler_block_return_address), 8); /* Simulate a call */ amd64_push_reg (code, AMD64_RAX); amd64_jump_code (code, tramp); } else { /*Slow path uses a c helper*/ - amd64_mov_reg_reg (code, AMD64_RDI, AMD64_RSP, 8); + amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, AMD64_RSP, 8); amd64_mov_reg_imm (code, AMD64_RAX, tramp); amd64_push_reg (code, AMD64_RAX); + amd64_push_reg (code, AMD64_RAX); amd64_jump_code (code, handler_block_trampoline_helper); } From ab5dda7fbac5bb462f3f0ebceb992636711d3075 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 06:46:23 +0200 Subject: [PATCH 181/543] Fix warnings. --- mono/mini/mini-amd64.c | 1 - mono/mini/mini-sparc.c | 2 +- mono/mini/mini.h | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) mode change 100644 => 100755 mono/mini/mini-sparc.c mode change 100644 => 100755 mono/mini/mini.h diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index ffdc7c973ba..8a69db7f005 100755 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -2051,7 +2051,6 @@ arg_storage_to_load_membase (ArgStorage storage) static void emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) { - MonoInst *arg; MonoMethodSignature *tmp_sig; int sig_reg; diff --git a/mono/mini/mini-sparc.c b/mono/mini/mini-sparc.c old mode 100644 new mode 100755 index 3b95fd97033..21c2b0cda1b --- a/mono/mini/mini-sparc.c +++ b/mono/mini/mini-sparc.c @@ -4354,7 +4354,7 @@ mono_arch_tls_init (void) } - jit_tls = pthread_getspecific (mono_get_jit_tls_key ()); + jit_tls = mono_get_jit_tls (); #ifdef MONO_SPARC_THR_TLS thr_setspecific (lmf_addr_key, &jit_tls->lmf); diff --git a/mono/mini/mini.h b/mono/mini/mini.h old mode 100644 new mode 100755 index 31f7ee138e0..e5e81db8aaf --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2052,7 +2052,6 @@ void mono_set_lmf (MonoLMF *lmf) MONO_INTERNAL; MonoJitTlsData* mono_get_jit_tls (void) MONO_INTERNAL; MONO_API MonoDomain *mono_jit_thread_attach (MonoDomain *domain); MONO_API void mono_jit_set_domain (MonoDomain *domain); -MonoNativeTlsKey mono_get_jit_tls_key (void) MONO_INTERNAL; gint32 mono_get_jit_tls_offset (void) MONO_INTERNAL; gint32 mono_get_lmf_tls_offset (void) MONO_INTERNAL; gint32 mono_get_lmf_addr_tls_offset (void) MONO_INTERNAL; From df43380ea671e3255081af9eb19c79d36f805797 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 01:01:11 -0400 Subject: [PATCH 182/543] [runtime] Fix the win32 build. --- mono/mini/exceptions-x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 mono/mini/exceptions-x86.c diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c old mode 100644 new mode 100755 index 21a2840e5f6..841b4580a6b --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -204,7 +204,7 @@ LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) switch (er->ExceptionCode) { case EXCEPTION_STACK_OVERFLOW: - win32_handle_stack_overflow (ep, sctx); + win32_handle_stack_overflow (ep, ctx); break; case EXCEPTION_ACCESS_VIOLATION: W32_SEH_HANDLE_EX(segv); From 5f9c74f4c5188d5dd56397a8e84126a5fb6e6ec0 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 01:16:00 -0400 Subject: [PATCH 183/543] [runtime] Fix mono_sigctx_to_monoctx () on win32. --- mono/utils/mono-context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mono/utils/mono-context.c b/mono/utils/mono-context.c index 02fa8c8701c..c52d0442f46 100644 --- a/mono/utils/mono-context.c +++ b/mono/utils/mono-context.c @@ -60,6 +60,7 @@ mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) #elif defined(HOST_WIN32) CONTEXT *context = (CONTEXT*)sigctx; + mctx->eip = context->Eip; mctx->edi = context->Edi; mctx->esi = context->Esi; mctx->ebx = context->Ebx; From 452073b91e0b6fc642b8c6ba14e60ac9cb1794c5 Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Mon, 22 Sep 2014 13:37:36 +0100 Subject: [PATCH 184/543] Add a tool which can sync the Mono cert store from an arbitrary cert bundle (i.e. every trusted CA.pem in one big text file). This is a format used by most Linux distributions, so allows Mono packagers to automatically integrate the Mono cert store with the OS cert store. --- mcs/tools/security/Makefile | 2 +- mcs/tools/security/cert-sync.cs | 226 ++++++++++++++++++++++++++++++++ scripts/Makefile.am | 1 + 3 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 mcs/tools/security/cert-sync.cs diff --git a/mcs/tools/security/Makefile b/mcs/tools/security/Makefile index c9baa67ccfe..ba771b51660 100644 --- a/mcs/tools/security/Makefile +++ b/mcs/tools/security/Makefile @@ -6,7 +6,7 @@ include ../../build/rules.make LOCAL_MCS_FLAGS = /lib:$(topdir)/class/lib/$(PROFILE) -r:Mono.Security.dll SECURITY_PROGRAMS = secutil.exe cert2spc.exe sn.exe makecert.exe chktrust.exe crlupdate.exe \ - signcode.exe setreg.exe certmgr.exe caspol.exe permview.exe mozroots.exe + signcode.exe setreg.exe certmgr.exe caspol.exe permview.exe mozroots.exe cert-sync.exe SECURITY_PROGRAMS_2_0 = httpcfg.exe HELPER_SOURCES = AssemblyInfo.cs $(topdir)/build/common/Consts.cs diff --git a/mcs/tools/security/cert-sync.cs b/mcs/tools/security/cert-sync.cs new file mode 100644 index 00000000000..44280675dd1 --- /dev/null +++ b/mcs/tools/security/cert-sync.cs @@ -0,0 +1,226 @@ +// +// cert-sync.cs: Import the root certificates from Linux SSL store into Mono +// +// Authors: +// Sebastien Pouliot +// Jo Shields +// +// Copyright (C) 2005 Novell, Inc (http://www.novell.com) +// Copyright (C) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections; +using System.IO; +using System.Net; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; + +using Mono.Security.X509; + +[assembly: AssemblyTitle ("Linux Cert Store Sync")] +[assembly: AssemblyDescription ("Synchronize local certs with certs from local Linux trust store.")] + +namespace Mono.Tools +{ + + class CertSync + { + + static string inputFile; + static bool quiet; + + static X509Certificate DecodeCertificate (string s) + { + byte[] rawdata = Convert.FromBase64String (s); + return new X509Certificate (rawdata); + } + + static Stream GetFile () + { + try { + if (inputFile != null) { + return File.OpenRead (inputFile); + } else { + return null; + } + } catch { + return null; + } + } + + static X509CertificateCollection DecodeCollection () + { + X509CertificateCollection roots = new X509CertificateCollection (); + StringBuilder sb = new StringBuilder (); + bool processing = false; + + using (Stream s = GetFile ()) { + if (s == null) { + WriteLine ("Couldn't retrieve the file using the supplied information."); + return null; + } + + StreamReader sr = new StreamReader (s); + while (true) { + string line = sr.ReadLine (); + if (line == null) + break; + + if (processing) { + if (line.StartsWith ("-----END CERTIFICATE-----")) { + processing = false; + X509Certificate root = DecodeCertificate (sb.ToString ()); + roots.Add (root); + + sb = new StringBuilder (); + continue; + } + sb.Append (line); + } else { + processing = line.StartsWith ("-----BEGIN CERTIFICATE-----"); + } + } + return roots; + } + } + + static int Process () + { + X509CertificateCollection roots = DecodeCollection (); + if (roots == null) { + return 1; + } else if (roots.Count == 0) { + WriteLine ("No certificates were found."); + return 0; + } + + X509Stores stores = (X509StoreManager.LocalMachine); + X509CertificateCollection trusted = stores.TrustedRoot.Certificates; + int additions = 0; + WriteLine ("I already trust {0}, your new list has {1}", trusted.Count, roots.Count); + foreach (X509Certificate root in roots) { + if (!trusted.Contains (root)) { + try { + stores.TrustedRoot.Import (root); + WriteLine ("Certificate added: {0}", root.SubjectName); + } catch { + WriteLine ("Warning: Could not import {0}"); + } + additions++; + } + } + if (additions > 0) + WriteLine ("{0} new root certificates were added to your trust store.", additions); + + X509CertificateCollection removed = new X509CertificateCollection (); + foreach (X509Certificate trust in trusted) { + if (!roots.Contains (trust)) { + removed.Add (trust); + } + } + if (removed.Count > 0) { + WriteLine ("{0} previously trusted certificates were removed.", removed.Count); + + foreach (X509Certificate old in removed) { + stores.TrustedRoot.Remove (old); + WriteLine ("Certificate removed: {0}", old.SubjectName); + } + } + WriteLine ("Import process completed."); + return 0; + } + + static string Thumbprint (string algorithm, X509Certificate certificate) + { + HashAlgorithm hash = HashAlgorithm.Create (algorithm); + byte[] digest = hash.ComputeHash (certificate.RawData); + return BitConverter.ToString (digest); + } + + static bool ParseOptions (string[] args) + { + if (args.Length < 1) + return false; + + for (int i = 0; i < args.Length - 1; i++) { + switch (args [i]) { + case "--quiet": + quiet = true; + break; + default: + WriteLine ("Unknown option '{0}'."); + return false; + } + } + inputFile = args [args.Length - 1]; + if (!File.Exists (inputFile)) { + WriteLine ("Unknown option or file not found '{0}'."); + return false; + } + return true; + } + + static void Header () + { + Console.WriteLine (new AssemblyInfo ().ToString ()); + } + + static void Help () + { + Console.WriteLine ("Usage: cert-sync [--quiet] system-ca-bundle.crt"); + Console.WriteLine ("Where system-ca-bundle.crt is in PEM format"); + } + + static void WriteLine (string str) + { + if (!quiet) + Console.WriteLine (str); + } + + static void WriteLine (string format, params object[] args) + { + if (!quiet) + Console.WriteLine (format, args); + } + + static int Main (string[] args) + { + try { + if (!ParseOptions (args)) { + Header (); + Help (); + return 1; + } + if (!quiet) { + Header (); + } + return Process (); + } catch (Exception e) { + // ignore quiet on exception + Console.WriteLine ("Error: {0}", e); + return 1; + } + } + } +} \ No newline at end of file diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 93adea143ed..ac0e3a9a957 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -76,6 +76,7 @@ scripts_4_0 = \ prj2make$(SCRIPT_SUFFIX) \ soapsuds$(SCRIPT_SUFFIX) \ caspol$(SCRIPT_SUFFIX) \ + cert-sync$(SCRIPT_SUFFIX) \ cert2spc$(SCRIPT_SUFFIX) \ certmgr$(SCRIPT_SUFFIX) \ chktrust$(SCRIPT_SUFFIX) \ From 5ad92e6b10d5c19dd9974ecd762ab97fb811b29a Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 22 Sep 2014 17:26:55 +0200 Subject: [PATCH 185/543] [mcs] declaration expression after ref/out argument --- mcs/errors/cs0411-24.cs | 15 +++++ mcs/errors/cs0815-7.cs | 15 +++++ mcs/errors/cs0841-5.cs | 15 +++++ mcs/errors/cs1501-18.cs | 10 +--- mcs/errors/cs1503-17.cs | 14 +++++ mcs/errors/cs1615-3.cs | 18 ++++++ mcs/errors/cs1644-47.cs | 11 ++++ mcs/errors/cs8046.cs | 19 ++++++ mcs/errors/cs8047.cs | 19 ++++++ mcs/mcs/cs-parser.jay | 57 +++++++++++++++++- mcs/mcs/dynamic.cs | 7 +++ mcs/mcs/ecore.cs | 59 ++++++++++++++----- mcs/mcs/expression.cs | 104 ++++++++++++++++++++++++++++++++- mcs/mcs/generic.cs | 2 +- mcs/mcs/typespec.cs | 1 + mcs/tests/test-decl-expr-01.cs | 65 +++++++++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 22 +++++++ 17 files changed, 424 insertions(+), 29 deletions(-) create mode 100644 mcs/errors/cs0411-24.cs create mode 100644 mcs/errors/cs0815-7.cs create mode 100644 mcs/errors/cs0841-5.cs create mode 100644 mcs/errors/cs1503-17.cs create mode 100644 mcs/errors/cs1615-3.cs create mode 100644 mcs/errors/cs1644-47.cs create mode 100644 mcs/errors/cs8046.cs create mode 100644 mcs/errors/cs8047.cs create mode 100644 mcs/tests/test-decl-expr-01.cs diff --git a/mcs/errors/cs0411-24.cs b/mcs/errors/cs0411-24.cs new file mode 100644 index 00000000000..1462cbac233 --- /dev/null +++ b/mcs/errors/cs0411-24.cs @@ -0,0 +1,15 @@ +// CS0411: The type arguments for method `C.Foo(out T)' cannot be inferred from the usage. Try specifying the type arguments explicitly +// Line: 8 + +public class C +{ + public static void Main () + { + Foo (out var y); + } + + static void Foo (out T t) + { + t = default (T); + } +} \ No newline at end of file diff --git a/mcs/errors/cs0815-7.cs b/mcs/errors/cs0815-7.cs new file mode 100644 index 00000000000..ae41a72d91a --- /dev/null +++ b/mcs/errors/cs0815-7.cs @@ -0,0 +1,15 @@ +// CS0815: An implicitly typed local variable declaration cannot be initialized with `void' +// Line: 8 + +class X +{ + public static void Main () + { + Foo (out var x = Main ()); + } + + static void Foo (out int i) + { + i = 0; + } +} \ No newline at end of file diff --git a/mcs/errors/cs0841-5.cs b/mcs/errors/cs0841-5.cs new file mode 100644 index 00000000000..798b33547c8 --- /dev/null +++ b/mcs/errors/cs0841-5.cs @@ -0,0 +1,15 @@ +// CS0841: A local variable `x' cannot be used before it is declared +// Line: 8 + +class X +{ + public static void Main () + { + Foo (x, out var x); + } + + static void Foo (int arg, out int value) + { + value = 3; + } +} \ No newline at end of file diff --git a/mcs/errors/cs1501-18.cs b/mcs/errors/cs1501-18.cs index 6f445564e94..b22ab55c406 100644 --- a/mcs/errors/cs1501-18.cs +++ b/mcs/errors/cs1501-18.cs @@ -1,5 +1,5 @@ // CS1501: No overload for method `Bar' takes `2' arguments -// Line: 25 +// Line: 19 using System; @@ -13,14 +13,6 @@ void Foo (string title, Action a) { } - static void Mismatch (string s) - { - } - - public static void Main () - { - } - void Bar () { Foo (arg: 1, a: () => { diff --git a/mcs/errors/cs1503-17.cs b/mcs/errors/cs1503-17.cs new file mode 100644 index 00000000000..26766c0ade7 --- /dev/null +++ b/mcs/errors/cs1503-17.cs @@ -0,0 +1,14 @@ +// CS1501: Argument `#1' cannot convert `ref string' expression to type `ref int' +// Line: 8 + +class C +{ + public static void Main () + { + Foo (ref var x = ""); + } + + static void Foo (ref int i) + { + } +} \ No newline at end of file diff --git a/mcs/errors/cs1615-3.cs b/mcs/errors/cs1615-3.cs new file mode 100644 index 00000000000..c64fb7fe842 --- /dev/null +++ b/mcs/errors/cs1615-3.cs @@ -0,0 +1,18 @@ +// CS1615: Argument `#1' does not require `out' modifier. Consider removing `out' modifier +// Line: 8 + +public class C +{ + public static void Main () + { + Foo (out var y); + } + + static void Foo (int x) + { + } + + static void Foo (string x) + { + } +} \ No newline at end of file diff --git a/mcs/errors/cs1644-47.cs b/mcs/errors/cs1644-47.cs new file mode 100644 index 00000000000..b756cd7b60c --- /dev/null +++ b/mcs/errors/cs1644-47.cs @@ -0,0 +1,11 @@ +// CS1644: Feature `declaration expression' cannot be used because it is not part of the C# 5.0 language specification +// Line: 12 +// Compiler options: -langversion:5 + +class C +{ + public static void Main () + { + int.TryParse ("0", out var v); + } +} \ No newline at end of file diff --git a/mcs/errors/cs8046.cs b/mcs/errors/cs8046.cs new file mode 100644 index 00000000000..f8b9ad556f0 --- /dev/null +++ b/mcs/errors/cs8046.cs @@ -0,0 +1,19 @@ +// CS8046: An expression tree cannot contain a declaration expression +// Line: 11 + +using System; +using System.Linq.Expressions; + +class C +{ + static void Main() + { + Expression> e = () => Out (out int x); + } + + static bool Out (out int value) + { + value = 3; + return true; + } +} \ No newline at end of file diff --git a/mcs/errors/cs8047.cs b/mcs/errors/cs8047.cs new file mode 100644 index 00000000000..7171d569ce3 --- /dev/null +++ b/mcs/errors/cs8047.cs @@ -0,0 +1,19 @@ +// CS8047: Declaration expression cannot be used in this context +// Line: 8 + +public class C +{ + public static void Main () + { + dynamic target = 3; + var x = new Test (target, out var y); + } +} + +class Test +{ + public Test (int x, out int y) + { + y = 0; + } +} \ No newline at end of file diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index d90cc01eb21..2db083886ca 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -871,7 +871,7 @@ named_attribute_argument ; named_argument - : identifier_inside_body COLON opt_named_modifier expression_or_error + : identifier_inside_body COLON opt_named_modifier named_argument_expr { if (lang_version <= LanguageVersion.V_3) FeatureIsNotAvailable (GetLocation ($1), "named argument"); @@ -884,6 +884,11 @@ named_argument lbag.AddLocation ($$, GetLocation($2)); } ; + +named_argument_expr + : expression_or_error + | declaration_expression + ; opt_named_modifier : /* empty */ { $$ = null; } @@ -3606,11 +3611,19 @@ non_simple_argument $$ = new Argument ((Expression) $2, Argument.AType.Ref); lbag.AddLocation ($$, GetLocation ($1)); } + | REF declaration_expression + { + $$ = new Argument ((Expression) $2, Argument.AType.Ref); + } | OUT variable_reference { $$ = new Argument ((Expression) $2, Argument.AType.Out); lbag.AddLocation ($$, GetLocation ($1)); } + | OUT declaration_expression + { + $$ = new Argument ((Expression) $2, Argument.AType.Out); + } | ARGLIST OPEN_PARENS argument_list CLOSE_PARENS { $$ = new Argument (new Arglist ((Arguments) $3, GetLocation ($1))); @@ -3623,6 +3636,48 @@ non_simple_argument } ; +declaration_expression + : OPEN_PARENS declaration_expression CLOSE_PARENS + { + $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } +/* + | CHECKED open_parens_any declaration_expression CLOSE_PARENS + { + $$ = new CheckedExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + | UNCHECKED open_parens_any declaration_expression CLOSE_PARENS + { + $$ = new UnCheckedExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } +*/ + | variable_type identifier_inside_body + { + if (lang_version < LanguageVersion.V_6) + FeatureIsNotAvailable (GetLocation ($1), "declaration expression"); + + var lt = (LocatedToken) $2; + var lv = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (lv); + $$ = new DeclarationExpression ((FullNamedExpression) $1, lv); + } + | variable_type identifier_inside_body ASSIGN expression + { + if (lang_version < LanguageVersion.V_6) + FeatureIsNotAvailable (GetLocation ($1), "declaration expression"); + + var lt = (LocatedToken) $2; + var lv = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (lv); + $$ = new DeclarationExpression ((FullNamedExpression) $1, lv) { + Initializer = (Expression) $4 + }; + } + ; + variable_reference : expression ; diff --git a/mcs/mcs/dynamic.cs b/mcs/mcs/dynamic.cs index 5604a3fcdc9..8a9a0c87de2 100644 --- a/mcs/mcs/dynamic.cs +++ b/mcs/mcs/dynamic.cs @@ -289,6 +289,13 @@ protected override Expression DoResolve (ResolveContext rc) protected bool DoResolveCore (ResolveContext rc) { + foreach (var arg in arguments) { + if (arg.Type == InternalType.VarOutType) { + // Should be special error message about dynamic dispatch + rc.Report.Error (8047, arg.Expr.Location, "Declaration expression cannot be used in this context"); + } + } + if (rc.CurrentTypeParameters != null && rc.CurrentTypeParameters[0].IsMethodTypeParameter) context_mvars = rc.CurrentTypeParameters; diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 94f4bcb129b..7c2537c8bc7 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -5144,31 +5144,36 @@ int IsArgumentCompatible (ResolveContext ec, Argument argument, Parameter.Modifi // is used and argument is not of dynamic type // if (((argument.Modifier | param_mod) & Parameter.Modifier.RefOutMask) != 0) { - if (argument.Type != parameter) { + var arg_type = argument.Type; + + if ((argument.Modifier & Parameter.Modifier.RefOutMask) != (param_mod & Parameter.Modifier.RefOutMask)) { + // + // Using dynamic for ref/out parameter can still succeed at runtime + // + if (arg_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (argument.Modifier & Parameter.Modifier.RefOutMask) == 0 && (restrictions & Restrictions.CovariantDelegate) == 0) + return -1; + + return 1; + } + + if (arg_type != parameter) { + if (arg_type == InternalType.VarOutType) + return 0; + // // Do full equality check after quick path // - if (!TypeSpecComparer.IsEqual (argument.Type, parameter)) { + if (!TypeSpecComparer.IsEqual (arg_type, parameter)) { // // Using dynamic for ref/out parameter can still succeed at runtime // - if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (argument.Modifier & Parameter.Modifier.RefOutMask) == 0 && (restrictions & Restrictions.CovariantDelegate) == 0) + if (arg_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (argument.Modifier & Parameter.Modifier.RefOutMask) == 0 && (restrictions & Restrictions.CovariantDelegate) == 0) return -1; return 2; } } - if ((argument.Modifier & Parameter.Modifier.RefOutMask) != (param_mod & Parameter.Modifier.RefOutMask)) { - // - // Using dynamic for ref/out parameter can still succeed at runtime - // - if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (argument.Modifier & Parameter.Modifier.RefOutMask) == 0 && (restrictions & Restrictions.CovariantDelegate) == 0) - return -1; - - return 1; - } - } else { if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (restrictions & Restrictions.CovariantDelegate) == 0) return -1; @@ -5741,10 +5746,20 @@ bool VerifyArguments (ResolveContext ec, ref Arguments args, MemberSpec member, if ((a.Modifier & Parameter.Modifier.RefOutMask) != (p_mod & Parameter.Modifier.RefOutMask)) break; - if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt)) + var arg_type = a.Type; + if (arg_type == pt) continue; - break; + if (arg_type == InternalType.VarOutType) { + // + // Set underlying variable type based on parameter type + // + ((DeclarationExpression)a.Expr).Variable.Type = pt; + continue; + } + + if (!TypeSpecComparer.IsEqual (arg_type, pt)) + break; } NamedArgument na = a as NamedArgument; @@ -5816,6 +5831,20 @@ bool VerifyArguments (ResolveContext ec, ref Arguments args, MemberSpec member, } if (a_idx != arg_count) { + // + // Convert all var out argument to error type for less confusing error reporting + // when no matching overload is found + // + for (; a_idx < arg_count; a_idx++) { + var arg = args [a_idx]; + if (arg == null) + continue; + + if (arg.Type == InternalType.VarOutType) { + ((DeclarationExpression)arg.Expr).Variable.Type = InternalType.ErrorType; + } + } + ReportArgumentMismatch (ec, a_pos, member, a, pd, pt); return false; } diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 1d6a082094c..c784f62d1c1 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -2493,6 +2493,96 @@ protected override Expression DoResolve (ResolveContext ec) return expr; } } + + public class DeclarationExpression : Expression, IMemoryLocation + { + LocalVariableReference lvr; + + public DeclarationExpression (FullNamedExpression variableType, LocalVariable variable) + { + VariableType = variableType; + Variable = variable; + this.loc = variable.Location; + } + + public LocalVariable Variable { get; set; } + public Expression Initializer { get; set; } + public FullNamedExpression VariableType { get; set; } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + Variable.CreateBuilder (ec); + + if (Initializer != null) { + lvr.EmitAssign (ec, Initializer, false, false); + } + + lvr.AddressOf (ec, mode); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + var target = (DeclarationExpression) t; + + target.VariableType = (FullNamedExpression) VariableType.Clone (clonectx); + + if (Initializer != null) + target.Initializer = Initializer.Clone (clonectx); + } + + public override Expression CreateExpressionTree (ResolveContext rc) + { + rc.Report.Error (8046, loc, "An expression tree cannot contain a declaration expression"); + return null; + } + + bool DoResolveCommon (ResolveContext rc) + { + var var_expr = VariableType as VarExpr; + if (var_expr != null) { + type = InternalType.VarOutType; + } else { + type = VariableType.ResolveAsType (rc); + if (type == null) + return false; + } + + if (Initializer != null) { + Initializer = Initializer.Resolve (rc); + + if (var_expr != null && Initializer != null && var_expr.InferType (rc, Initializer)) { + type = var_expr.Type; + } + } + + Variable.Type = type; + lvr = new LocalVariableReference (Variable, loc); + + eclass = ExprClass.Variable; + return true; + } + + protected override Expression DoResolve (ResolveContext rc) + { + if (DoResolveCommon (rc)) + lvr.Resolve (rc); + + return this; + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + if (lvr == null && DoResolveCommon (rc)) + lvr.ResolveLValue (rc, right_side); + + return this; + } + + public override void Emit (EmitContext ec) + { + throw new NotImplementedException (); + } + } // // C# 2.0 Default value expression @@ -6472,6 +6562,9 @@ public override void SetHasAddressTaken () void DoResolveBase (ResolveContext ec) { + eclass = ExprClass.Variable; + type = local_info.Type; + // // If we are referencing a variable from the external block // flag it for capturing @@ -6490,9 +6583,6 @@ void DoResolveBase (ResolveContext ec) storey.CaptureLocalVariable (ec, local_info); } } - - eclass = ExprClass.Variable; - type = local_info.Type; } protected override Expression DoResolve (ResolveContext ec) @@ -6500,6 +6590,14 @@ protected override Expression DoResolve (ResolveContext ec) local_info.SetIsUsed (); DoResolveBase (ec); + + if (local_info.Type == InternalType.VarOutType) { + ec.Report.Error (8048, loc, "Cannot use uninitialized variable `{0}'", + GetSignatureForError ()); + + type = InternalType.ErrorType; + } + return this; } diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs index f9fc7525667..17dc329cee0 100644 --- a/mcs/mcs/generic.cs +++ b/mcs/mcs/generic.cs @@ -3008,7 +3008,7 @@ void AddToBounds (BoundInfo bound, int index, bool voidAllowed) // Some types cannot be used as type arguments // if ((bound.Type.Kind == MemberKind.Void && !voidAllowed) || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType || - bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod) + bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod || bound.Type == InternalType.VarOutType) return; var a = bounds [index]; diff --git a/mcs/mcs/typespec.cs b/mcs/mcs/typespec.cs index a33159d8478..6b42112f9ed 100644 --- a/mcs/mcs/typespec.cs +++ b/mcs/mcs/typespec.cs @@ -1446,6 +1446,7 @@ class InternalType : TypeSpec, ITypeDefinition public static readonly InternalType FakeInternalType = new InternalType (""); public static readonly InternalType Namespace = new InternalType (""); public static readonly InternalType ErrorType = new InternalType (""); + public static readonly InternalType VarOutType = new InternalType ("var out"); readonly string name; diff --git a/mcs/tests/test-decl-expr-01.cs b/mcs/tests/test-decl-expr-01.cs new file mode 100644 index 00000000000..15e781dbf22 --- /dev/null +++ b/mcs/tests/test-decl-expr-01.cs @@ -0,0 +1,65 @@ +using System; + +class DeclarationExpression +{ + public static int Main () + { + Out (out int o); + if (o != 3) + return 1; + + if (Out (out int o1)) { + if (o1 != 3) + return 2; + } + + Out (out int o2 = 2); + if (o2 != 3) + return 3; + + Out (out var o3); + if (o3 != 3) + return 4; + + Ref (ref int r = 2); + if (r != 7) + return 5; + + Ref (ref ((var r2 = 3))); + if (r2 != 8) + return 6; + + Out2 (str: "b", v: out var o5); + if (o5 != 9) + return 7; + + Out3 (out var o6 = 9m); + if (o6.GetType () != typeof (decimal)) + return 8; + + Console.WriteLine ("ok"); + return 0; + } + + static bool Out (out int value) + { + value = 3; + return true; + } + + static bool Out2 (out int v, string str) + { + v = 9; + return true; + } + + static void Out3 (out T t) + { + t = default (T); + } + + static void Ref (ref int arg) + { + arg += 5; + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index d6569ccdbef..45d8c130549 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -65586,6 +65586,28 @@ + + + + 252 + + + 13 + + + 14 + + + 17 + + + 8 + + + 7 + + + From ef94fbfd9c93ea5702e0a855bc01104217c75fa4 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 22 Sep 2014 17:28:53 +0200 Subject: [PATCH 186/543] [corlib] Update en-NZ designators. Fixes #22212 --- mono/metadata/culture-info-tables.h | 2 +- tools/locale-builder/Driver.cs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mono/metadata/culture-info-tables.h b/mono/metadata/culture-info-tables.h index 5df6721ed4d..6d3cae22a29 100644 --- a/mono/metadata/culture-info-tables.h +++ b/mono/metadata/culture-info-tables.h @@ -223,7 +223,7 @@ static const DateTimeFormatEntry datetime_format_entries [] = { {3943, 2309, 323, 331, 44, 55, 0, 0, {0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}, {36041, 36052, 13523, 36063, 36074, 36081, 36090, 36103, 36110, 36123, 36136, 36149, 0}, {36041, 36052, 13523, 36063, 36074, 36081, 36090, 36103, 36110, 36123, 36136, 36149, 0}, {36041, 36052, 13523, 36063, 36074, 36081, 36090, 36103, 36110, 36123, 36136, 36149, 0}, {36041, 36052, 13523, 36063, 36074, 36081, 36090, 36103, 36110, 36123, 36136, 36149, 0}, 0, 6, 2541, 241, {2309,1236,1210,0,0,0,0,0,0,0,0,0,0,0},{3943,254,0,0,0,0,0,0},{331,274,35,0,0,0,0,0,0,0,0,0},{323,280,23,0,0,0,0,0,0}}, {1344, 2927, 323, 331, 1375, 1391, 1404, 1411, {1418, 1428, 1438, 1448, 1458, 1468, 1478}, {34903, 34910, 34917, 34924, 34931, 34938, 34945}, {1537, 1541, 1545, 1549, 1553, 1557, 1561}, {1655, 1660, 1665, 1670, 1675, 1680, 1685, 1690, 1695, 1700, 1706, 1712, 0}, {1655, 1660, 1665, 1670, 1675, 1680, 1685, 1690, 1695, 1700, 1706, 1712, 0}, {1655, 1660, 1665, 1670, 1675, 1680, 1685, 1690, 1695, 1700, 1706, 1712, 0}, {1655, 1660, 1665, 1670, 1675, 1680, 1685, 1690, 1695, 1700, 1706, 1712, 0}, 0, 0, 239, 241, {2927,1229,14,1765,1779,1366,1736,1210,0,0,0,0,0,0},{1344,36162,36189,2543,0,0,0,0},{331,274,0,0,0,0,0,0,0,0,0,0},{323,280,0,0,0,0,0,0,0}}, {2568, 2587, 280, 274, 1906, 1916, 2598, 2604, {2611, 2619, 2626, 2635, 2644, 2655, 2663}, {2671, 2674, 2677, 2680, 2683, 2686, 2689}, {2018, 2403, 2692, 2403, 2692, 2409, 2018}, {2694, 2701, 2709, 2715, 2721, 2725, 2730, 2735, 2742, 2752, 2760, 2769, 0}, {2694, 2701, 2709, 2715, 2721, 2725, 2730, 2735, 2742, 2752, 2760, 2769, 0}, {2778, 2782, 2786, 2791, 2721, 2795, 2799, 2803, 2807, 2811, 2815, 2819, 0}, {2778, 2782, 2786, 2791, 2721, 2795, 2799, 2803, 2807, 2811, 2815, 2819, 0}, 2, 1, 754, 241, {2587,1245,2835,35120,2843,1210,0,0,0,0,0,0,0,0},{2568,1882,35130,0,0,0,0,0},{274,331,8214,8204,2862,8237,8242,8223,8229,0,0,0},{280,323,8274,8287,2887,2873,2902,0,0}}, - {2909, 14812, 2936, 2947, 1906, 352, 7992, 21969, {3719, 3726, 3733, 3741, 3751, 3760, 3767}, {3776, 3780, 3784, 3788, 3792, 3796, 3800}, {2018, 2403, 2405, 3804, 2405, 2409, 2018}, {3806, 3814, 3823, 2715, 3829, 3833, 3838, 2735, 2742, 3843, 2760, 3851, 0}, {3806, 3814, 3823, 2715, 3829, 3833, 3838, 2735, 2742, 3843, 2760, 3851, 0}, {2778, 2782, 3860, 2791, 3829, 2795, 2799, 2803, 2807, 3864, 2815, 3868, 0}, {2778, 2782, 3860, 2791, 3829, 2795, 2799, 2803, 2807, 3864, 2815, 3868, 0}, 0, 0, 239, 241, {14812,1221,14,2835,1210,0,0,0,0,0,0,0,0,0},{2909,3672,0,0,0,0,0,0},{2947,35,274,331,0,0,0,0,0,0,0,0},{2936,23,280,323,0,0,0,0,0}}, + {2909, 14812, 2936, 2947, 1906, 352, 7218, 21969, {3719, 3726, 3733, 3741, 3751, 3760, 3767}, {3776, 3780, 3784, 3788, 3792, 3796, 3800}, {2018, 2403, 2405, 3804, 2405, 2409, 2018}, {3806, 3814, 3823, 2715, 3829, 3833, 3838, 2735, 2742, 3843, 2760, 3851, 0}, {3806, 3814, 3823, 2715, 3829, 3833, 3838, 2735, 2742, 3843, 2760, 3851, 0}, {2778, 2782, 3860, 2791, 3829, 2795, 2799, 2803, 2807, 3864, 2815, 3868, 0}, {2778, 2782, 3860, 2791, 3829, 2795, 2799, 2803, 2807, 3864, 2815, 3868, 0}, 0, 0, 239, 241, {14812,1221,14,2835,1210,0,0,0,0,0,0,0,0,0},{2909,3672,0,0,0,0,0,0},{2947,35,274,331,0,0,0,0,0,0,0,0},{2936,23,280,323,0,0,0,0,0}}, {4342, 243, 23, 35, 947, 3985, 962, 968, {3997, 4005, 4011, 4018, 4029, 4036, 4044}, {4052, 4057, 4062, 4067, 4073, 4078, 4083}, {2692, 2411, 2403, 2403, 4089, 4091, 2018}, {4093, 4099, 4107, 4113, 4119, 4124, 4130, 4136, 4143, 4154, 4162, 4172, 0}, {4182, 4188, 4196, 1102, 4202, 4207, 4213, 4219, 4226, 1140, 4237, 4247, 0}, {4257, 4262, 4062, 4267, 4272, 4277, 4282, 4287, 4292, 4298, 4303, 4308, 0}, {4257, 4262, 4062, 4267, 4272, 4277, 4282, 4287, 4292, 4298, 4303, 4308, 0}, 0, 1, 239, 241, {243,14,1229,1236,1210,0,0,0,0,0,0,0,0,0},{4313,4342,4369,0,0,0,0,0},{35,2947,331,274,0,0,0,0,0,0,0,0},{23,2936,323,280,0,0,0,0,0}}, {36205, 243, 280, 274, 1906, 352, 1924, 1927, {4874, 4883, 4889, 4895, 4904, 4910, 4919}, {4926, 4931, 4936, 4941, 4946, 4951, 4956}, {2692, 2411, 2403, 2403, 4089, 4091, 2018}, {4961, 4969, 4978, 4983, 4989, 4993, 4998, 5006, 5012, 5022, 1148, 5030, 0}, {4961, 4969, 4978, 4983, 4989, 4993, 4998, 5006, 5012, 5022, 1148, 5030, 0}, {5040, 5046, 4978, 5053, 4989, 4993, 5058, 5006, 5064, 1195, 1200, 5070, 0}, {5040, 5046, 4978, 5053, 4989, 4993, 5058, 5006, 5064, 1195, 1200, 5070, 0}, 2, 1, 239, 241, {243,14,1245,1236,1210,0,0,0,0,0,0,0,0,0},{4857,5076,3672,0,0,0,0,0},{274,331,5085,5091,5101,0,0,0,0,0,0,0},{280,323,0,0,0,0,0,0,0}}, {1882, 2261, 323, 331, 1906, 11991, 36228, 36238, {9068, 9077, 9089, 9096, 9104, 9114, 9120}, {9127, 9131, 9135, 9139, 9143, 9148, 9152}, {0, 0, 0, 0, 0, 0, 0}, {2413, 2420, 15113, 2434, 2440, 2444, 2449, 11959, 36246, 36256, 36264, 36273, 0}, {2413, 2420, 15113, 2434, 2440, 2444, 2449, 11959, 36246, 36256, 36264, 36273, 0}, {2497, 2501, 2505, 2509, 2440, 2513, 2517, 11966, 2525, 2529, 2533, 2537, 0}, {2497, 2501, 2505, 2509, 2440, 2513, 2517, 11966, 2525, 2529, 2533, 2537, 0}, 0, 1, 754, 241, {2261,2843,1895,2587,9640,1245,11970,1210,0,0,0,0,0,0},{1882,2554,2568,0,0,0,0,0},{331,274,0,0,0,0,0,0,0,0,0,0},{323,280,0,0,0,0,0,0,0}}, diff --git a/tools/locale-builder/Driver.cs b/tools/locale-builder/Driver.cs index 1a44d5eb7e1..6a2505a4c74 100644 --- a/tools/locale-builder/Driver.cs +++ b/tools/locale-builder/Driver.cs @@ -1073,10 +1073,14 @@ Cannot really be used it's too different to .NET and most app rely on it // Apply global rule first el = node.SelectSingleNode ("dayPeriods/dayPeriodContext/dayPeriodWidth[@type='wide']/dayPeriod[@type='am']"); + // Manual edits for exact .net compatiblity switch (ci.Name) { case "en-AU": df.AMDesignator = "AM"; break; + case "en-NZ": + df.AMDesignator = "a.m."; + break; default: if (el != null) df.AMDesignator = el.InnerText; @@ -1092,6 +1096,9 @@ Cannot really be used it's too different to .NET and most app rely on it case "en-AU": df.PMDesignator = "PM"; break; + case "en-NZ": + df.AMDesignator = "p.m."; + break; default: if (el != null) df.PMDesignator = el.InnerText; From 32318db8cf837f6d2dea99852fe6bd4c0bde24b3 Mon Sep 17 00:00:00 2001 From: Marius Ungureanu Date: Mon, 22 Sep 2014 21:16:13 +0300 Subject: [PATCH 187/543] Fixup to ef94fbfd9c93ea5702e0a855bc01104217c75fa4 Thanks @ezavaleta --- tools/locale-builder/Driver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/locale-builder/Driver.cs b/tools/locale-builder/Driver.cs index 6a2505a4c74..f42f5cf90b4 100644 --- a/tools/locale-builder/Driver.cs +++ b/tools/locale-builder/Driver.cs @@ -1097,7 +1097,7 @@ Cannot really be used it's too different to .NET and most app rely on it df.PMDesignator = "PM"; break; case "en-NZ": - df.AMDesignator = "p.m."; + df.PMDesignator = "p.m."; break; default: if (el != null) From b99e7ab9573ceb11e363021f48a8bef8225ce3d6 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 22 Sep 2014 22:08:20 +0200 Subject: [PATCH 188/543] Fixes commit ef94fbfd9c93ea5702e0a855bc01104217c75fa4 --- mono/metadata/culture-info-tables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/culture-info-tables.h b/mono/metadata/culture-info-tables.h index 6d3cae22a29..bdbeb1daf6b 100644 --- a/mono/metadata/culture-info-tables.h +++ b/mono/metadata/culture-info-tables.h @@ -223,7 +223,7 @@ static const DateTimeFormatEntry datetime_format_entries [] = { {3943, 2309, 323, 331, 44, 55, 0, 0, {0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}, {36041, 36052, 13523, 36063, 36074, 36081, 36090, 36103, 36110, 36123, 36136, 36149, 0}, {36041, 36052, 13523, 36063, 36074, 36081, 36090, 36103, 36110, 36123, 36136, 36149, 0}, {36041, 36052, 13523, 36063, 36074, 36081, 36090, 36103, 36110, 36123, 36136, 36149, 0}, {36041, 36052, 13523, 36063, 36074, 36081, 36090, 36103, 36110, 36123, 36136, 36149, 0}, 0, 6, 2541, 241, {2309,1236,1210,0,0,0,0,0,0,0,0,0,0,0},{3943,254,0,0,0,0,0,0},{331,274,35,0,0,0,0,0,0,0,0,0},{323,280,23,0,0,0,0,0,0}}, {1344, 2927, 323, 331, 1375, 1391, 1404, 1411, {1418, 1428, 1438, 1448, 1458, 1468, 1478}, {34903, 34910, 34917, 34924, 34931, 34938, 34945}, {1537, 1541, 1545, 1549, 1553, 1557, 1561}, {1655, 1660, 1665, 1670, 1675, 1680, 1685, 1690, 1695, 1700, 1706, 1712, 0}, {1655, 1660, 1665, 1670, 1675, 1680, 1685, 1690, 1695, 1700, 1706, 1712, 0}, {1655, 1660, 1665, 1670, 1675, 1680, 1685, 1690, 1695, 1700, 1706, 1712, 0}, {1655, 1660, 1665, 1670, 1675, 1680, 1685, 1690, 1695, 1700, 1706, 1712, 0}, 0, 0, 239, 241, {2927,1229,14,1765,1779,1366,1736,1210,0,0,0,0,0,0},{1344,36162,36189,2543,0,0,0,0},{331,274,0,0,0,0,0,0,0,0,0,0},{323,280,0,0,0,0,0,0,0}}, {2568, 2587, 280, 274, 1906, 1916, 2598, 2604, {2611, 2619, 2626, 2635, 2644, 2655, 2663}, {2671, 2674, 2677, 2680, 2683, 2686, 2689}, {2018, 2403, 2692, 2403, 2692, 2409, 2018}, {2694, 2701, 2709, 2715, 2721, 2725, 2730, 2735, 2742, 2752, 2760, 2769, 0}, {2694, 2701, 2709, 2715, 2721, 2725, 2730, 2735, 2742, 2752, 2760, 2769, 0}, {2778, 2782, 2786, 2791, 2721, 2795, 2799, 2803, 2807, 2811, 2815, 2819, 0}, {2778, 2782, 2786, 2791, 2721, 2795, 2799, 2803, 2807, 2811, 2815, 2819, 0}, 2, 1, 754, 241, {2587,1245,2835,35120,2843,1210,0,0,0,0,0,0,0,0},{2568,1882,35130,0,0,0,0,0},{274,331,8214,8204,2862,8237,8242,8223,8229,0,0,0},{280,323,8274,8287,2887,2873,2902,0,0}}, - {2909, 14812, 2936, 2947, 1906, 352, 7218, 21969, {3719, 3726, 3733, 3741, 3751, 3760, 3767}, {3776, 3780, 3784, 3788, 3792, 3796, 3800}, {2018, 2403, 2405, 3804, 2405, 2409, 2018}, {3806, 3814, 3823, 2715, 3829, 3833, 3838, 2735, 2742, 3843, 2760, 3851, 0}, {3806, 3814, 3823, 2715, 3829, 3833, 3838, 2735, 2742, 3843, 2760, 3851, 0}, {2778, 2782, 3860, 2791, 3829, 2795, 2799, 2803, 2807, 3864, 2815, 3868, 0}, {2778, 2782, 3860, 2791, 3829, 2795, 2799, 2803, 2807, 3864, 2815, 3868, 0}, 0, 0, 239, 241, {14812,1221,14,2835,1210,0,0,0,0,0,0,0,0,0},{2909,3672,0,0,0,0,0,0},{2947,35,274,331,0,0,0,0,0,0,0,0},{2936,23,280,323,0,0,0,0,0}}, + {2909, 14812, 2936, 2947, 1906, 352, 7213, 7218, {3719, 3726, 3733, 3741, 3751, 3760, 3767}, {3776, 3780, 3784, 3788, 3792, 3796, 3800}, {2018, 2403, 2405, 3804, 2405, 2409, 2018}, {3806, 3814, 3823, 2715, 3829, 3833, 3838, 2735, 2742, 3843, 2760, 3851, 0}, {3806, 3814, 3823, 2715, 3829, 3833, 3838, 2735, 2742, 3843, 2760, 3851, 0}, {2778, 2782, 3860, 2791, 3829, 2795, 2799, 2803, 2807, 3864, 2815, 3868, 0}, {2778, 2782, 3860, 2791, 3829, 2795, 2799, 2803, 2807, 3864, 2815, 3868, 0}, 0, 0, 239, 241, {14812,1221,14,2835,1210,0,0,0,0,0,0,0,0,0},{2909,3672,0,0,0,0,0,0},{2947,35,274,331,0,0,0,0,0,0,0,0},{2936,23,280,323,0,0,0,0,0}}, {4342, 243, 23, 35, 947, 3985, 962, 968, {3997, 4005, 4011, 4018, 4029, 4036, 4044}, {4052, 4057, 4062, 4067, 4073, 4078, 4083}, {2692, 2411, 2403, 2403, 4089, 4091, 2018}, {4093, 4099, 4107, 4113, 4119, 4124, 4130, 4136, 4143, 4154, 4162, 4172, 0}, {4182, 4188, 4196, 1102, 4202, 4207, 4213, 4219, 4226, 1140, 4237, 4247, 0}, {4257, 4262, 4062, 4267, 4272, 4277, 4282, 4287, 4292, 4298, 4303, 4308, 0}, {4257, 4262, 4062, 4267, 4272, 4277, 4282, 4287, 4292, 4298, 4303, 4308, 0}, 0, 1, 239, 241, {243,14,1229,1236,1210,0,0,0,0,0,0,0,0,0},{4313,4342,4369,0,0,0,0,0},{35,2947,331,274,0,0,0,0,0,0,0,0},{23,2936,323,280,0,0,0,0,0}}, {36205, 243, 280, 274, 1906, 352, 1924, 1927, {4874, 4883, 4889, 4895, 4904, 4910, 4919}, {4926, 4931, 4936, 4941, 4946, 4951, 4956}, {2692, 2411, 2403, 2403, 4089, 4091, 2018}, {4961, 4969, 4978, 4983, 4989, 4993, 4998, 5006, 5012, 5022, 1148, 5030, 0}, {4961, 4969, 4978, 4983, 4989, 4993, 4998, 5006, 5012, 5022, 1148, 5030, 0}, {5040, 5046, 4978, 5053, 4989, 4993, 5058, 5006, 5064, 1195, 1200, 5070, 0}, {5040, 5046, 4978, 5053, 4989, 4993, 5058, 5006, 5064, 1195, 1200, 5070, 0}, 2, 1, 239, 241, {243,14,1245,1236,1210,0,0,0,0,0,0,0,0,0},{4857,5076,3672,0,0,0,0,0},{274,331,5085,5091,5101,0,0,0,0,0,0,0},{280,323,0,0,0,0,0,0,0}}, {1882, 2261, 323, 331, 1906, 11991, 36228, 36238, {9068, 9077, 9089, 9096, 9104, 9114, 9120}, {9127, 9131, 9135, 9139, 9143, 9148, 9152}, {0, 0, 0, 0, 0, 0, 0}, {2413, 2420, 15113, 2434, 2440, 2444, 2449, 11959, 36246, 36256, 36264, 36273, 0}, {2413, 2420, 15113, 2434, 2440, 2444, 2449, 11959, 36246, 36256, 36264, 36273, 0}, {2497, 2501, 2505, 2509, 2440, 2513, 2517, 11966, 2525, 2529, 2533, 2537, 0}, {2497, 2501, 2505, 2509, 2440, 2513, 2517, 11966, 2525, 2529, 2533, 2537, 0}, 0, 1, 754, 241, {2261,2843,1895,2587,9640,1245,11970,1210,0,0,0,0,0,0},{1882,2554,2568,0,0,0,0,0},{331,274,0,0,0,0,0,0,0,0,0,0},{323,280,0,0,0,0,0,0,0}}, From 0f36581baabe0d6908392be9b9e320056a8a0108 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 22 Sep 2014 22:11:39 +0200 Subject: [PATCH 189/543] [mcs] Populate inherited constraints member cache from types not only base types. Fixes #23017 --- mcs/mcs/generic.cs | 14 ++++++++---- mcs/tests/gtest-624.cs | 36 +++++++++++++++++++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 42 ++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 mcs/tests/gtest-624.cs diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs index 17dc329cee0..f549432b29a 100644 --- a/mcs/mcs/generic.cs +++ b/mcs/mcs/generic.cs @@ -1325,16 +1325,22 @@ protected override void InitializeMemberCache (bool onlyTypes) foreach (var ta in targs) { var tps = ta as TypeParameterSpec; IList ifaces; + TypeSpec b_type; if (tps != null) { - var b_type = tps.GetEffectiveBase (); - if (b_type != null && b_type.BuiltinType != BuiltinTypeSpec.Type.Object && b_type.BuiltinType != BuiltinTypeSpec.Type.ValueType) - cache.AddBaseType (b_type); - + b_type = tps.GetEffectiveBase (); ifaces = tps.InterfacesDefined; } else { + b_type = ta; ifaces = ta.Interfaces; } + // + // Don't add base type which was inflated from base constraints but it's not valid + // in C# context + // + if (b_type != null && b_type.BuiltinType != BuiltinTypeSpec.Type.Object && b_type.BuiltinType != BuiltinTypeSpec.Type.ValueType && !b_type.IsStructOrEnum) + cache.AddBaseType (b_type); + if (ifaces != null) { foreach (var iface_type in ifaces) { cache.AddInterface (iface_type); diff --git a/mcs/tests/gtest-624.cs b/mcs/tests/gtest-624.cs new file mode 100644 index 00000000000..0299d095e02 --- /dev/null +++ b/mcs/tests/gtest-624.cs @@ -0,0 +1,36 @@ +using System; + +class Model +{ + public int Value; +} + +class C1 +{ + public void Add (Func t) + { + } +} + +abstract class C2 +{ + public abstract void ApplyImpl (C1 c1) where U : TModel; +} + +class C3 : C2 +{ + public override void ApplyImpl (C1 c1) + { + c1.Add (t => t.Value); + } +} + +class Program +{ + static void Main () + { + var v1 = new C1 (); + var c3 = new C3 (); + c3.ApplyImpl (v1); + } +} diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 45d8c130549..d423fd25a71 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -19415,6 +19415,48 @@ + + + + 7 + + + + + 2 + + + 7 + + + + + 0 + + + 7 + + + + + 20 + + + 19 + + + 7 + + + + + 21 + + + 7 + + + From 74b76bdc1169a730c8a4cce90fd97a43560bc86b Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 16:20:12 -0400 Subject: [PATCH 190/543] [runtime] Fix the lookup of nested types which have a namespace. Fixes #21653. --- mono/metadata/reflection.c | 48 ++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index 3ea728173df..1b7570ef8cb 100644 --- a/mono/metadata/reflection.c +++ b/mono/metadata/reflection.c @@ -7508,14 +7508,52 @@ mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoT mono_class_init (parent); while ((klass = mono_class_get_nested_types (parent, &iter))) { - if (ignorecase) { - if (mono_utf8_strcasecmp (klass->name, mod->data) == 0) - break; + char *lastp; + char *nested_name, *nested_nspace; + gboolean match = TRUE; + + lastp = strrchr (mod->data, '.'); + if (lastp) { + /* Nested classes can have namespaces */ + int nspace_len; + + nested_name = g_strdup (lastp + 1); + nspace_len = lastp - (char*)mod->data; + nested_nspace = g_malloc (nspace_len + 1); + memcpy (nested_nspace, mod->data, nspace_len); + nested_nspace [nspace_len] = '\0'; + } else { - if (strcmp (klass->name, mod->data) == 0) - break; + nested_name = mod->data; + nested_nspace = NULL; } + + if (nested_nspace) { + if (ignorecase) { + if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0)) + match = FALSE; + } else { + if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0)) + match = FALSE; + } + } + if (match) { + if (ignorecase) { + if (mono_utf8_strcasecmp (klass->name, nested_name) != 0) + match = FALSE; + } else { + if (strcmp (klass->name, nested_name) != 0) + match = FALSE; + } + } + if (lastp) { + g_free (nested_name); + g_free (nested_nspace); + } + if (match) + break; } + if (!klass) break; } From 16d9d078218d3188428d103e67315add70a1c368 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 17:07:26 -0400 Subject: [PATCH 191/543] [runtime] Allow renaming of threadpool threads. Fixes #23206. --- .../Test/System.Threading/ThreadTest.cs | 35 +++++++++++++++++-- mono/metadata/threads.c | 6 +++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/mcs/class/corlib/Test/System.Threading/ThreadTest.cs b/mcs/class/corlib/Test/System.Threading/ThreadTest.cs index 8c82931acc5..11e611563c8 100644 --- a/mcs/class/corlib/Test/System.Threading/ThreadTest.cs +++ b/mcs/class/corlib/Test/System.Threading/ThreadTest.cs @@ -526,13 +526,42 @@ public void Name () [Test] [ExpectedException (typeof (InvalidOperationException))] - public void ReName () + public void Rename () { - Thread t = new Thread (new ThreadStart (ReName)); + Thread t = new Thread (new ThreadStart (Rename)); t.Name = "a"; t.Name = "b"; } + bool rename_finished; + bool rename_failed; + + [Test] + public void RenameTpThread () + { + object monitor = new object (); + ThreadPool.QueueUserWorkItem (new WaitCallback (Rename_callback), monitor); + lock (monitor) { + if (!rename_finished) + Monitor.Wait (monitor); + } + Assert.IsFalse (rename_failed); + } + + void Rename_callback (object o) { + Thread.CurrentThread.Name = "a"; + try { + Thread.CurrentThread.Name = "b"; + } catch (Exception) { + rename_failed = true; + } + object monitor = o; + lock (monitor) { + rename_finished = true; + Monitor.Pulse (monitor); + } + } + [Test] public void TestNestedThreads1() { @@ -1225,6 +1254,8 @@ public void ParametrizedThreadStart () Assert.AreEqual (this, arg, "obj"); } + bool set_name_failed; + [Test] public void SetNameTpThread () { ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc)); diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index 280ac95ac77..b5583952036 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -1207,12 +1207,16 @@ mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, g { LOCK_THREAD (this_obj); - if (this_obj->flags & MONO_THREAD_FLAG_NAME_SET) { + if ((this_obj->flags & MONO_THREAD_FLAG_NAME_SET) && !this_obj->threadpool_thread) { UNLOCK_THREAD (this_obj); mono_raise_exception (mono_get_exception_invalid_operation ("Thread.Name can only be set once.")); return; } + if (this_obj->name) { + g_free (this_obj->name); + this_obj->name_len = 0; + } if (name) { this_obj->name = g_new (gunichar2, mono_string_length (name)); memcpy (this_obj->name, mono_string_chars (name), mono_string_length (name) * 2); From 24013364b7808d0b703a4551b8c5a6a94b9271d7 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Thu, 18 Sep 2014 16:06:09 -0400 Subject: [PATCH 192/543] [sgen] Use memcpy to copy object It is faster by around 5-6% on copy heavy gc stress tests. --- mono/metadata/sgen-copy-object.h | 20 ++---------------- mono/tests/Makefile.am | 1 + mono/tests/gc-copy-stress.cs | 35 ++++++++++++++++++++++++++++++++ mono/tests/stress-runner.pl | 7 +++++++ 4 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 mono/tests/gc-copy-stress.cs diff --git a/mono/metadata/sgen-copy-object.h b/mono/metadata/sgen-copy-object.h index dba9ed1459e..adad2514d08 100644 --- a/mono/metadata/sgen-copy-object.h +++ b/mono/metadata/sgen-copy-object.h @@ -49,24 +49,8 @@ par_copy_object_no_checks (char *destination, MonoVTable *vt, void *obj, mword o } #endif -#ifdef __GNUC__ - if (objsize <= sizeof (gpointer) * 8) { - mword *dest = (mword*)destination; - switch (objsize / sizeof (gpointer)) { - case 8: (dest) [7] = ((mword*)obj) [7]; - case 7: (dest) [6] = ((mword*)obj) [6]; - case 6: (dest) [5] = ((mword*)obj) [5]; - case 5: (dest) [4] = ((mword*)obj) [4]; - case 4: (dest) [3] = ((mword*)obj) [3]; - case 3: (dest) [2] = ((mword*)obj) [2]; - case 2: (dest) [1] = ((mword*)obj) [1]; - } - } else -#endif - { - /*can't trust memcpy doing word copies */ - mono_gc_memmove_aligned (destination + sizeof (mword), (char*)obj + sizeof (mword), objsize - sizeof (mword)); - } + memcpy (destination + sizeof (mword), (char*)obj + sizeof (mword), objsize - sizeof (mword)); + /* adjust array->bounds */ SGEN_ASSERT (9, vt->gc_descr, "vtable %p for class %s:%s has no gc descriptor", vt, vt->klass->name_space, vt->klass->name); diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 9675e71b5cb..58392b04acd 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -43,6 +43,7 @@ STRESS_TESTS_SRC= \ monitor-stress.cs \ thread-stress.cs \ gc-stress.cs \ + gc-copy-stress.cs \ gc-graystack-stress.cs \ exit-stress.cs \ process-stress.cs \ diff --git a/mono/tests/gc-copy-stress.cs b/mono/tests/gc-copy-stress.cs new file mode 100644 index 00000000000..130f33f8284 --- /dev/null +++ b/mono/tests/gc-copy-stress.cs @@ -0,0 +1,35 @@ +using System; + +class T { + + static int count = 1000000; + static int loops = 20; + static int persist_factor = 10; + + static object obj; + + static object[] persist; + static int persist_idx; + + static void work () { + persist = new object[count / persist_factor + 1]; + persist_idx = 0; + for (int i = 0; i < count; ++i) { + obj = new object (); + if (i % persist_factor == 0) + persist[persist_idx++] = obj; + } + } + + static void Main (string[] args) { + if (args.Length > 0) + loops = int.Parse (args [0]); + if (args.Length > 1) + count = int.Parse (args [1]); + if (args.Length > 2) + persist_factor = int.Parse (args [2]); + for (int i = 0; i < loops; ++i) { + work (); + } + } +} diff --git a/mono/tests/stress-runner.pl b/mono/tests/stress-runner.pl index 24d5b9db8d5..165b1d877a3 100755 --- a/mono/tests/stress-runner.pl +++ b/mono/tests/stress-runner.pl @@ -72,6 +72,13 @@ 'arg-knob' => 2, # loops 'ratio' => 10, }, + 'gc-copy-stress' => { + 'program' => 'gc-copy-stress.exe', + # loops, count, persist_factor + 'args' => [250, 500000, 10], + 'arg-knob' => 1, # count + 'ratio' => 4, + }, 'thread-stress' => { 'program' => 'thread-stress.exe', # loops From 40ca3ae2492861a4752f0c0ac9d89073233b2a77 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 18:52:40 -0400 Subject: [PATCH 193/543] [llvm] Fix support for unaligned offsets in the store_membase_imm opcodes. Fixes #23267. --- mono/mini/mini-llvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index df6de20bab4..6551f78e021 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -3156,7 +3156,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE); addr = LLVMBuildGEP (builder, convert (ctx, values [ins->inst_destbasereg], LLVMPointerType (t, 0)), &index, 1, ""); } - emit_store (ctx, bb, &builder, size, convert (ctx, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), t), addr, is_volatile); + emit_store (ctx, bb, &builder, size, convert (ctx, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), t), convert (ctx, addr, LLVMPointerType (t, 0)), is_volatile); break; } From 82c15fa592b23cf466b0683cc3f02f30d7ea8828 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 20:03:48 -0400 Subject: [PATCH 194/543] [aot] Add an 'llvm' aot option which does the same as --llvm. This allows running the AOT compiler with LLVM enabled in aot cache mode. --- mono/mini/aot-compiler.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 5311224cc3e..c358ce4a9f4 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -136,6 +136,7 @@ typedef struct MonoAotOptions { gboolean use_trampolines_page; gboolean no_instances; gboolean gnu_asm; + gboolean llvm; int nthreads; int ntrampolines; int nrgctx_trampolines; @@ -6392,6 +6393,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) opts->instances_logfile_path = g_strdup (arg + strlen ("log-instances=")); } else if (str_begins_with (arg, "log-instances")) { opts->log_instances = TRUE; + } else if (str_begins_with (arg, "llvm")) { + opts->llvm = TRUE; } else if (str_begins_with (arg, "internal-logfile=")) { opts->logfile = g_strdup (arg + strlen ("internal-logfile=")); } else if (str_begins_with (arg, "mtriple=")) { @@ -8867,7 +8870,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) acfg->flags |= MONO_AOT_FILE_FLAG_DEBUG; } - if (mono_use_llvm) { + if (mono_use_llvm || acfg->aot_opts.llvm) { acfg->llvm = TRUE; acfg->aot_opts.asm_writer = TRUE; acfg->flags |= MONO_AOT_FILE_FLAG_WITH_LLVM; From 19619d925ebab08f7a59e859bf073ae084e80d57 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 20:11:22 -0400 Subject: [PATCH 195/543] [aot] Fix a regression introduced by 82c15fa592b23cf466b0683cc3f02f30d7ea8828. --- mono/mini/aot-compiler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index c358ce4a9f4..29239c88c1f 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -6393,14 +6393,14 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) opts->instances_logfile_path = g_strdup (arg + strlen ("log-instances=")); } else if (str_begins_with (arg, "log-instances")) { opts->log_instances = TRUE; - } else if (str_begins_with (arg, "llvm")) { - opts->llvm = TRUE; } else if (str_begins_with (arg, "internal-logfile=")) { opts->logfile = g_strdup (arg + strlen ("internal-logfile=")); } else if (str_begins_with (arg, "mtriple=")) { opts->mtriple = g_strdup (arg + strlen ("mtriple=")); } else if (str_begins_with (arg, "llvm-path=")) { opts->llvm_path = g_strdup (arg + strlen ("llvm-path=")); + } else if (!strcmp (arg, "llvm")) { + opts->llvm = TRUE; } else if (str_begins_with (arg, "readonly-value=")) { add_readonly_value (opts, arg + strlen ("readonly-value=")); } else if (str_begins_with (arg, "info")) { From 627fc398ada27b7a59d255e2126eccd178963a3d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 20:18:33 -0400 Subject: [PATCH 196/543] [aot] Make --aot=llvm actually work by passing the flag down to the JIT. --- mono/mini/aot-compiler.c | 8 +++++++- mono/mini/mini.c | 3 ++- mono/mini/mini.h | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 29239c88c1f..dfc2b62e560 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -6588,6 +6588,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) gboolean skip; int index, depth; MonoMethod *wrapped; + JitFlags flags; if (acfg->aot_opts.metadata_only) return; @@ -6632,7 +6633,12 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) * the runtime will not see AOT methods during AOT compilation,so it * does not need to support them by creating a fake GOT etc. */ - cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), acfg->aot_opts.full_aot ? (JIT_FLAG_AOT|JIT_FLAG_FULL_AOT) : (JIT_FLAG_AOT), 0); + flags = JIT_FLAG_AOT; + if (acfg->aot_opts.full_aot) + flags |= JIT_FLAG_FULL_AOT; + if (acfg->llvm) + flags |= JIT_FLAG_LLVM; + cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0); mono_loader_clear_error (); if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) { diff --git a/mono/mini/mini.c b/mono/mini/mini.c index e2e385568f3..b489216a885 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -4934,6 +4934,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl gboolean run_cctors = (flags & JIT_FLAG_RUN_CCTORS) ? 1 : 0; gboolean compile_aot = (flags & JIT_FLAG_AOT) ? 1 : 0; gboolean full_aot = (flags & JIT_FLAG_FULL_AOT) ? 1 : 0; + gboolean llvm = (flags & JIT_FLAG_LLVM) ? 1 : 0; InterlockedIncrement (&mono_jit_stats.methods_compiled); if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION) @@ -4975,7 +4976,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl } #ifdef ENABLE_LLVM - try_llvm = mono_use_llvm; + try_llvm = mono_use_llvm || llvm; #endif restart_compile: diff --git a/mono/mini/mini.h b/mono/mini/mini.h index e5e81db8aaf..9200a64c3a5 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -1320,7 +1320,9 @@ typedef enum { /* Whenever this is an AOT compilation */ JIT_FLAG_AOT = (1 << 1), /* Whenever this is a full AOT compilation */ - JIT_FLAG_FULL_AOT = (1 << 2) + JIT_FLAG_FULL_AOT = (1 << 2), + /* Whenever to compile with LLVM */ + JIT_FLAG_LLVM = (1 << 3), } JitFlags; /* Bit-fields in the MonoBasicBlock.region */ From b0523c4ee87d00dbadc44442300aad30560b5560 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 20:52:53 -0400 Subject: [PATCH 197/543] [aot] Add more verbose aot cache logging, fix failure detection. --- mono/mini/aot-runtime.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 213d5b56ab2..1d99200c79c 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1452,8 +1452,10 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: loading from cache: '%s'.", fname); module = mono_dl_open (fname, MONO_DL_LAZY, NULL); - if (module) + if (module) { + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: found in cache: '%s'.", fname); return module; + } if (!strcmp (assembly->aname.name, "mscorlib") && !mscorlib_aot_loaded) /* @@ -1481,7 +1483,7 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) fclose (failure_file); } - mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT: compiling assembly '%s'... ", assembly->image->name); + mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT: compiling assembly '%s', logfile: '%s.log'... ", assembly->image->name, fname); /* * We need to invoke the AOT compiler here. There are multiple approaches: @@ -1495,11 +1497,14 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) aot_options = g_strdup_printf ("outfile=%s,internal-logfile=%s.log", fname, fname); /* Maybe due this in another thread ? */ res = mono_compile_assembly (assembly, mono_parse_default_optimizations (NULL), aot_options); - if (!res) { + if (res) { + mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT: compilation failed."); failure_fname = g_strdup_printf ("%s.failure", fname); failure_file = fopen (failure_fname, "a+"); fclose (failure_file); g_free (failure_fname); + } else { + mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT: compilation succeeded."); } } else { /* From 745a2b16ec1e05205f13f26dfe9c38370a67d058 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 22 Sep 2014 21:11:03 -0400 Subject: [PATCH 198/543] [aot] Add an 'options' argument to the AOT cache configuration where additional --aot= options can be passed. --- mono/metadata/metadata-internals.h | 1 + mono/metadata/mono-config.c | 3 ++- mono/mini/aot-compiler.c | 2 +- mono/mini/aot-runtime.c | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mono/metadata/metadata-internals.h b/mono/metadata/metadata-internals.h index c283b7aae36..c738d53654e 100644 --- a/mono/metadata/metadata-internals.h +++ b/mono/metadata/metadata-internals.h @@ -535,6 +535,7 @@ typedef struct { */ GSList *apps; GSList *assemblies; + char *aot_options; } MonoAotCacheConfig; #define MONO_SIZEOF_METHOD_SIGNATURE (sizeof (struct _MonoMethodSignature) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P) diff --git a/mono/metadata/mono-config.c b/mono/metadata/mono-config.c index 1e85012dd0f..c9e9e030b8c 100644 --- a/mono/metadata/mono-config.c +++ b/mono/metadata/mono-config.c @@ -375,7 +375,6 @@ aot_cache_start (gpointer user_data, for (i = 0; attribute_names [i]; ++i) { if (!strcmp (attribute_names [i], "app")) { config->apps = g_slist_prepend (config->apps, g_strdup (attribute_values [i])); - return; } } @@ -391,6 +390,8 @@ aot_cache_start (gpointer user_data, config->assemblies = g_slist_prepend (config->assemblies, g_strdup (part)); } g_strfreev (parts); + } else if (!strcmp (attribute_names [i], "options")) { + config->aot_options = g_strdup (attribute_values [i]); } } } diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index dfc2b62e560..2331d6a7a69 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -9011,7 +9011,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) res = emit_llvm_file (acfg); if (!res) - return FALSE; + return 1; } #endif diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 1d99200c79c..81d58e784a6 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1494,7 +1494,7 @@ aot_cache_load_module (MonoAssembly *assembly, char **aot_name) * - fork a new process and do the work there. */ if (in_process) { - aot_options = g_strdup_printf ("outfile=%s,internal-logfile=%s.log", fname, fname); + aot_options = g_strdup_printf ("outfile=%s,internal-logfile=%s.log%s%s", fname, fname, config->aot_options ? "," : "", config->aot_options ? config->aot_options : ""); /* Maybe due this in another thread ? */ res = mono_compile_assembly (assembly, mono_parse_default_optimizations (NULL), aot_options); if (res) { From ac52aece46d7d03bf7cc28a70193719f6e19fefd Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 12:13:57 +0100 Subject: [PATCH 199/543] Test Uri.UserInfo with escaped 'a'. --- mcs/class/System/Test/System/UriTest.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mcs/class/System/Test/System/UriTest.cs b/mcs/class/System/Test/System/UriTest.cs index b3b33170c58..22bac808f63 100644 --- a/mcs/class/System/Test/System/UriTest.cs +++ b/mcs/class/System/Test/System/UriTest.cs @@ -1968,6 +1968,13 @@ public void GetSerializationInfoStringException () var uri = new Uri ("/relative/path", UriKind.Relative); uri.GetComponents (UriComponents.SerializationInfoString | UriComponents.Host, UriFormat.UriEscaped); } + + [Test] + public void UserInfo_EscapedLetter () + { + var uri = new Uri ("https://first%61second@host"); + Assert.AreEqual ("firstasecond", uri.UserInfo); + } } // Tests non default IriParsing From 2cf751f7f7de19f52f7baa1783425d740e9f426d Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 12:18:12 +0100 Subject: [PATCH 200/543] Fixed additional Uri.UserInfo char consumed after an escaped char. --- mcs/class/System/System/UriParseComponents.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/mcs/class/System/System/UriParseComponents.cs b/mcs/class/System/System/UriParseComponents.cs index 0de6d8f91ef..7462817f347 100644 --- a/mcs/class/System/System/UriParseComponents.cs +++ b/mcs/class/System/System/UriParseComponents.cs @@ -337,6 +337,7 @@ private static bool ParseUser (ParserState state) if (!Uri.IsHexEncoding (part, index)) return false; ch = Uri.HexUnescape (part, ref index); + index--; } if (Char.IsLetterOrDigit (ch) || IsUnreserved (ch) || IsSubDelim (ch) || ch == ':'){ From b63c44670af1f73577b9da3c5783b02a7b4a6eed Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 12:32:17 +0100 Subject: [PATCH 201/543] Test Uri.UserInfo with percentage encoded '@'. --- mcs/class/System/Test/System/UriTest.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mcs/class/System/Test/System/UriTest.cs b/mcs/class/System/Test/System/UriTest.cs index 22bac808f63..4cf95d4456b 100644 --- a/mcs/class/System/Test/System/UriTest.cs +++ b/mcs/class/System/Test/System/UriTest.cs @@ -1975,6 +1975,14 @@ public void UserInfo_EscapedLetter () var uri = new Uri ("https://first%61second@host"); Assert.AreEqual ("firstasecond", uri.UserInfo); } + + [Test] + public void UserInfo_EscapedAt () + { + var userinfo = "first%40second"; + var uri = new Uri ("https://" + userinfo + "@host"); + Assert.AreEqual (userinfo, uri.UserInfo); + } } // Tests non default IriParsing From e074772e92216bc68d5b180dd922bde80d7eccb6 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 12:33:54 +0100 Subject: [PATCH 202/543] UriParseComponents no longer decodes '@' in UserInfo. Fixes 23246. --- mcs/class/System/System/UriParseComponents.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mcs/class/System/System/UriParseComponents.cs b/mcs/class/System/System/UriParseComponents.cs index 7462817f347..5e94d3bdf53 100644 --- a/mcs/class/System/System/UriParseComponents.cs +++ b/mcs/class/System/System/UriParseComponents.cs @@ -336,8 +336,13 @@ private static bool ParseUser (ParserState state) if (ch == '%'){ if (!Uri.IsHexEncoding (part, index)) return false; + var oldIndex = index; ch = Uri.HexUnescape (part, ref index); index--; + if (ch == '@') { + sb.Append (part.Substring (oldIndex, index - oldIndex + 1)); + continue; + } } if (Char.IsLetterOrDigit (ch) || IsUnreserved (ch) || IsSubDelim (ch) || ch == ':'){ From f6f80d5e4df8edfeabe16295dbed7938d270db20 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 14:27:35 +0100 Subject: [PATCH 203/543] Test that Uri made from UNIX path and RelativeOrAbsolute is relative. --- mcs/class/System/Test/System/UriTest.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mcs/class/System/Test/System/UriTest.cs b/mcs/class/System/Test/System/UriTest.cs index b3b33170c58..b1332125db8 100644 --- a/mcs/class/System/Test/System/UriTest.cs +++ b/mcs/class/System/Test/System/UriTest.cs @@ -1940,6 +1940,13 @@ public void GetComponents_Fragment () Assert.AreEqual ("id=1%262&sort=asc", escaped, "UriEscaped"); } + [Test] + public void RelativeOrAbsoluteUnixPath () + { + var uri = new Uri ("/abc", UriKind.RelativeOrAbsolute); + Assert.IsFalse (uri.IsAbsoluteUri); + } + [Test] // Bug #12631 public void LocalPathWithBaseUrl () From b6874fa16b011aa18b726b9a62c0f6ba0be0de80 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 14:32:59 +0100 Subject: [PATCH 204/543] Uri made from UNIX path and RelativeOrAbsolute is now relative. Fixes 22954. --- mcs/class/System/System/UriParseComponents.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System/System/UriParseComponents.cs b/mcs/class/System/System/UriParseComponents.cs index 0de6d8f91ef..347b859ccd8 100644 --- a/mcs/class/System/System/UriParseComponents.cs +++ b/mcs/class/System/System/UriParseComponents.cs @@ -206,7 +206,7 @@ private static bool ParseUnixFilePath (ParserState state) state.elements.scheme = Uri.UriSchemeFile; state.elements.delimiter = "://"; state.elements.isUnixFilePath = true; - state.elements.isAbsoluteUri = (state.kind == UriKind.Relative)? false : true; + state.elements.isAbsoluteUri = state.kind == UriKind.Absolute; if (part.Length >= 2 && part [0] == '/' && part [1] == '/') { part = part.TrimStart (new char [] {'/'}); From b89b5c46d67118c88e18d766811bd63df4436a18 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 15:30:50 +0100 Subject: [PATCH 205/543] Test WebClient.UploadFileTaskAsync ContentType. Covers 19529. --- .../System/Test/System.Net/WebClientTest.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/mcs/class/System/Test/System.Net/WebClientTest.cs b/mcs/class/System/Test/System.Net/WebClientTest.cs index 48722d45510..ef3f6817425 100644 --- a/mcs/class/System/Test/System.Net/WebClientTest.cs +++ b/mcs/class/System/Test/System.Net/WebClientTest.cs @@ -2221,6 +2221,28 @@ public void UploadFileAsyncCancelEvent () webClient.UploadFileAsync (uri, "PUT", tempFile); }); } + + [Test] + public void UploadFileAsyncContentType () + { + var serverUri = "http://localhost:13370/"; + var filename = Path.GetTempFileName (); + + HttpListener listener = new HttpListener (); + listener.Prefixes.Add (serverUri); + listener.Start (); + + using (var client = new WebClient ()) + { + client.UploadFileTaskAsync (new Uri (serverUri), filename); + var request = listener.GetContext ().Request; + + var expected = "multipart/form-data; boundary=------------"; + Assert.AreEqual (expected.Length + 15, request.ContentType.Length); + Assert.AreEqual (expected, request.ContentType.Substring (0, expected.Length)); + } + listener.Close (); + } #endif #if NET_4_0 From 0699e4da361230476c55a0dd7251ad115d186153 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Tue, 23 Sep 2014 10:55:57 -0400 Subject: [PATCH 206/543] Fix warnings in mscorlib's Test suite + bring a couple more tests + fix thread rename test --- .../System.Reflection.Emit/DynamicMethodTest.cs | 4 +++- .../GenericTypeParameterBuilderTest.cs | 2 -- .../System.Reflection.Emit/TypeBuilderTest.cs | 4 ++-- .../Test/System.Reflection/AssemblyNameCas.cs | 1 - .../Test/System.Reflection/FieldInfoTest.cs | 16 +++++++++++++++- .../Test/System.Reflection/MethodInfoTest.cs | 5 ++++- .../System.Reflection/MonoGenericClassTest.cs | 2 +- .../Test/System.Reflection/ReflectedTypeTest.cs | 2 ++ .../ConditionalWeakTableTest.cs | 5 ++++- .../RuntimeHelpersTest.cs | 8 +++++++- .../TaskAwaiterTest.cs | 5 +++++ .../GCHandleTest.cs | 5 ++++- .../MarshalTest.cs | 14 +++++++------- .../SerializationTest.cs | 2 ++ .../CryptoStreamTest.cs | 2 -- .../HMACSHA384Test.cs | 6 +++--- .../HMACSHA512Test.cs | 6 +++--- .../RegistryPermissionTest.cs | 1 - .../UrlIdentityPermissionTest.cs | 6 ------ .../corlib/Test/System.Threading/ThreadTest.cs | 12 ++++++------ mcs/class/corlib/Test/System/AppDomainTest.cs | 13 ++++++++++++- mcs/class/corlib/Test/System/SByteTest.cs | 12 +++++++++--- mcs/class/corlib/Test/System/TypeTest.cs | 14 ++++++++++++-- 23 files changed, 101 insertions(+), 46 deletions(-) diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/DynamicMethodTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/DynamicMethodTest.cs index 271412269c0..f65ac28ef5e 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/DynamicMethodTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/DynamicMethodTest.cs @@ -317,10 +317,12 @@ public void Circular_Refs () { m1.Invoke(null, new object[] { 5 }); } + // Disabl known warning, the Field is never used directly from C# + #pragma warning disable 414 class Host { static string Field = "foo"; } - + #pragma warning restore 414 [Test] [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297416 public void TestOwnerMemberAccess () diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/GenericTypeParameterBuilderTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/GenericTypeParameterBuilderTest.cs index 1559d66369a..7f9db3b99fd 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/GenericTypeParameterBuilderTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/GenericTypeParameterBuilderTest.cs @@ -27,7 +27,6 @@ public class GenericTypeParameterBuilderTest { AssemblyBuilder assembly; ModuleBuilder module; - int typeCount; static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.TypeBuilderTest"; [SetUp] @@ -46,7 +45,6 @@ protected void SetUp (AssemblyBuilderAccess mode) assemblyName, mode, Path.GetTempPath ()); module = assembly.DefineDynamicModule ("module1"); - typeCount = 0; } [Test] diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs index 382f3f25527..b1b7cf320f3 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs @@ -92,8 +92,8 @@ public interface IDestroyable } public class Tuple { - A a; - B b; + public A a; + public B b; } private AssemblyBuilder assembly; diff --git a/mcs/class/corlib/Test/System.Reflection/AssemblyNameCas.cs b/mcs/class/corlib/Test/System.Reflection/AssemblyNameCas.cs index a24a4868d9b..087297b6f24 100644 --- a/mcs/class/corlib/Test/System.Reflection/AssemblyNameCas.cs +++ b/mcs/class/corlib/Test/System.Reflection/AssemblyNameCas.cs @@ -42,7 +42,6 @@ namespace MonoCasTests.System.Reflection { public class AssemblyNameCas { private MonoTests.System.Reflection.AssemblyNameTest ant; - private AssemblyName main; [TestFixtureSetUp] public void FixtureSetUp () diff --git a/mcs/class/corlib/Test/System.Reflection/FieldInfoTest.cs b/mcs/class/corlib/Test/System.Reflection/FieldInfoTest.cs index ccd923fa59c..a3639864f6a 100644 --- a/mcs/class/corlib/Test/System.Reflection/FieldInfoTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/FieldInfoTest.cs @@ -73,6 +73,8 @@ public class Class3 : Class2 { } + // Disable this warning, as the purpose of this struct is to poke at the internal via reflection + #pragma warning disable 649 class FieldInvokeMatrix { public Byte field_Byte; @@ -102,6 +104,7 @@ class FieldInvokeMatrix public Int64Enum field_Int64Enum; public UInt64Enum field_UInt64Enum; } + #pragma warning restore 649 public enum ByteEnum : byte { @@ -376,10 +379,13 @@ public void PseudoCustomAttributes () Assert.AreEqual (typeof (Marshal1), Type.GetType (attr.MarshalType), "#I4"); } + // Disable "field not used warning", this is intended. +#pragma warning disable 649 class Foo { public static int static_field; public int field; } +#pragma warning restore 649 [ExpectedException (typeof (ArgumentException))] public void GetValueWrongObject () @@ -1359,16 +1365,24 @@ public enum LongEnum : long { } + // We do not refernece the field, that is expected +#pragma warning disable 169 // Helper classes class RefOnlyFieldClass { // Helper property static int RefOnlyField; } - +#pragma warning restore 169 + class NonPublicFieldClass { protected int protectedField; + + public void Dummy () + { + protectedField = 1; + } } public class FieldInfoTest diff --git a/mcs/class/corlib/Test/System.Reflection/MethodInfoTest.cs b/mcs/class/corlib/Test/System.Reflection/MethodInfoTest.cs index 65adf97aa51..00349880e1f 100644 --- a/mcs/class/corlib/Test/System.Reflection/MethodInfoTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/MethodInfoTest.cs @@ -42,9 +42,12 @@ #endif namespace A.B.C { + // Disable expected warning +#pragma warning disable 169 public struct MethodInfoTestStruct { int p; } +#pragma warning restore 169 } namespace MonoTests.System.Reflection { @@ -253,7 +256,7 @@ public void ToStringWithPointerSignatures () //bug #409583 public struct SimpleStruct { - int a; + public int a; } public static unsafe SimpleStruct* PtrFunc2 (SimpleStruct* a, A.B.C.MethodInfoTestStruct *b) diff --git a/mcs/class/corlib/Test/System.Reflection/MonoGenericClassTest.cs b/mcs/class/corlib/Test/System.Reflection/MonoGenericClassTest.cs index 0b02596ec5b..e47b5e1eb79 100644 --- a/mcs/class/corlib/Test/System.Reflection/MonoGenericClassTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/MonoGenericClassTest.cs @@ -178,7 +178,7 @@ public void ClassMustNotBeRegisteredAfterTypeBuilderIsFinished () } public class Bar { - public class Foo {} + public class Foo {} } [Test] diff --git a/mcs/class/corlib/Test/System.Reflection/ReflectedTypeTest.cs b/mcs/class/corlib/Test/System.Reflection/ReflectedTypeTest.cs index bcc814e04d3..8347b4dabf7 100644 --- a/mcs/class/corlib/Test/System.Reflection/ReflectedTypeTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/ReflectedTypeTest.cs @@ -29,6 +29,8 @@ using System.Reflection; using NUnit.Framework; +// Various fields in this class are not used directly by the C# code, they are only here to be reflected upon +#pragma warning disable 649 namespace MonoTests.System.Reflection { [TestFixture] diff --git a/mcs/class/corlib/Test/System.Runtime.CompilerServices/ConditionalWeakTableTest.cs b/mcs/class/corlib/Test/System.Runtime.CompilerServices/ConditionalWeakTableTest.cs index 92d19fe367e..f6f4dabe2ba 100644 --- a/mcs/class/corlib/Test/System.Runtime.CompilerServices/ConditionalWeakTableTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.CompilerServices/ConditionalWeakTableTest.cs @@ -402,9 +402,12 @@ public void PromotedCwtPointingToYoungStuff () { static int reachable = 0; public class FinalizableLink { + // The sole purpose of this object is to keep a reference to another object, so it is fine to not use it. + #pragma warning disable 414 object obj; - ConditionalWeakTable cwt; int id; + #pragma warning restore 414 + ConditionalWeakTable cwt; public FinalizableLink (int id, object obj, ConditionalWeakTable cwt) { this.id = id; diff --git a/mcs/class/corlib/Test/System.Runtime.CompilerServices/RuntimeHelpersTest.cs b/mcs/class/corlib/Test/System.Runtime.CompilerServices/RuntimeHelpersTest.cs index fc4010bd21c..593305d4a67 100644 --- a/mcs/class/corlib/Test/System.Runtime.CompilerServices/RuntimeHelpersTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.CompilerServices/RuntimeHelpersTest.cs @@ -94,8 +94,10 @@ public void RunClassConstructor_Default () RuntimeHelpers.RunClassConstructor (rth); } + // Expected the handle here is that way, because we are going to test for an ArgumentException being thrown +#pragma warning disable 649 static RuntimeTypeHandle handle; - +#pragma warning restore 649 [Test] [ExpectedException (typeof (ArgumentException))] public void RunClassConstructor_Uninitialized () @@ -122,7 +124,11 @@ class Fielder { } static RuntimeFieldHandle rfh = typeof (Fielder).GetField ("array").FieldHandle; + + // Disable expected warning: the point of the test is to validate that an exception is thrown for something with a null (the default value in this case) + #pragma warning disable 649 static RuntimeFieldHandle static_rfh; + #pragma warning restore 649 [Test] [ExpectedException (typeof (ArgumentNullException))] diff --git a/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs b/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs index 5237e377e38..1bc9d384147 100644 --- a/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs @@ -72,6 +72,11 @@ protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQ Interlocked.Increment (ref ic); return false; } + + public override string ToString () + { + return "Scheduler-" + name; + } } class SingleThreadSynchronizationContext : SynchronizationContext diff --git a/mcs/class/corlib/Test/System.Runtime.InteropServices/GCHandleTest.cs b/mcs/class/corlib/Test/System.Runtime.InteropServices/GCHandleTest.cs index 1ac8a825b64..17fe0d9045d 100644 --- a/mcs/class/corlib/Test/System.Runtime.InteropServices/GCHandleTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.InteropServices/GCHandleTest.cs @@ -18,8 +18,11 @@ namespace MonoTests.System.Runtime.InteropServices [TestFixture] public class GCHandleTest { + // Expected warning, the tests that reference this handle are testing for the default values of the object + #pragma warning disable 649 static GCHandle handle; - + #pragma warning restore 649 + [Test] public void DefaultZeroValue_Allocated () { diff --git a/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs b/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs index d6f2a49bf38..28943159aa1 100644 --- a/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs @@ -28,7 +28,7 @@ class ClsSequential { public int field; } - class ClsNoLayout { + public class ClsNoLayout { public int field; } @@ -173,12 +173,12 @@ public void AllocHGlobalZeroSize () Marshal.FreeHGlobal (ptr); } - struct Foo { - int a; - static int b; - long c; - static char d; - int e; + public struct Foo { + public int a; + public static int b; + public long c; + public static char d; + public int e; } [Test] diff --git a/mcs/class/corlib/Test/System.Runtime.Serialization/SerializationTest.cs b/mcs/class/corlib/Test/System.Runtime.Serialization/SerializationTest.cs index 90b2d3f73fc..48e686ab8dd 100644 --- a/mcs/class/corlib/Test/System.Runtime.Serialization/SerializationTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.Serialization/SerializationTest.cs @@ -637,6 +637,8 @@ public void CheckEquals (SomeValues obj, string context) Assert.AreEqual (_char, obj._char, context + "._char"); Assert.AreEqual (_dateTime, obj._dateTime, context + "._dateTime"); Assert.AreEqual (_decimal, obj._decimal, context + "._decimal"); + Assert.AreEqual (_double, obj._double, context + "._double"); + Assert.AreEqual (_short, obj._short, context = "._short"); Assert.AreEqual (_int, obj._int, context + "._int"); Assert.AreEqual (_long, obj._long, context + "._long"); Assert.AreEqual (_sbyte, obj._sbyte, context + "._sbyte"); diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/CryptoStreamTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/CryptoStreamTest.cs index 10328b8e60f..3ad6cce71f9 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/CryptoStreamTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/CryptoStreamTest.cs @@ -144,7 +144,6 @@ public class CryptoStreamTest { Stream readStream; Stream writeStream; ICryptoTransform encryptor; - ICryptoTransform decryptor; CryptoStream cs; SymmetricAlgorithm aes; @@ -156,7 +155,6 @@ public void SetUp () writeStream = new MemoryStream (new byte [0], true); aes = SymmetricAlgorithm.Create (); encryptor = aes.CreateEncryptor (); - decryptor = aes.CreateEncryptor (); } } diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/HMACSHA384Test.cs b/mcs/class/corlib/Test/System.Security.Cryptography/HMACSHA384Test.cs index 115bdf30cc4..e243712d80c 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/HMACSHA384Test.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/HMACSHA384Test.cs @@ -28,6 +28,9 @@ public int BlockSize { public class SelectableHmacSha384: HMAC { + // legacy parameter: + // http://blogs.msdn.com/shawnfa/archive/2007/01/31/please-do-not-use-the-net-2-0-hmacsha512-and-hmacsha384-classes.aspx + public SelectableHmacSha384 (byte[] key, bool legacy) { HashName = "SHA384"; @@ -45,7 +48,6 @@ public SelectableHmacSha384 (byte[] key, bool legacy) public class HMACSHA384Test : KeyedHashAlgorithmTest { protected HMACSHA384 algo; - private bool legacy; [SetUp] public override void SetUp () @@ -53,8 +55,6 @@ public override void SetUp () algo = new HMACSHA384 (); algo.Key = new byte [8]; hash = algo; - // http://blogs.msdn.com/shawnfa/archive/2007/01/31/please-do-not-use-the-net-2-0-hmacsha512-and-hmacsha384-classes.aspx - legacy = (new HS384 ().BlockSize == 64); } // the hash algorithm only exists as a managed implementation diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/HMACSHA512Test.cs b/mcs/class/corlib/Test/System.Security.Cryptography/HMACSHA512Test.cs index 04497415d0e..55a7b87589c 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/HMACSHA512Test.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/HMACSHA512Test.cs @@ -26,6 +26,9 @@ public int BlockSize { public class SelectableHmacSha512: HMAC { + // Legacy parameter explanation: + // http://blogs.msdn.com/shawnfa/archive/2007/01/31/please-do-not-use-the-net-2-0-hmacsha512-and-hmacsha384-classes.aspx + public SelectableHmacSha512 (byte[] key, bool legacy) { HashName = "SHA512"; @@ -43,7 +46,6 @@ public SelectableHmacSha512 (byte[] key, bool legacy) public class HMACSHA512Test : KeyedHashAlgorithmTest { protected HMACSHA512 algo; - private bool legacy; [SetUp] public override void SetUp () @@ -51,8 +53,6 @@ public override void SetUp () algo = new HMACSHA512 (); algo.Key = new byte [8]; hash = algo; - // http://blogs.msdn.com/shawnfa/archive/2007/01/31/please-do-not-use-the-net-2-0-hmacsha512-and-hmacsha384-classes.aspx - legacy = (new HS512 ().BlockSize == 64); } // the hash algorithm only exists as a managed implementation diff --git a/mcs/class/corlib/Test/System.Security.Permissions/RegistryPermissionTest.cs b/mcs/class/corlib/Test/System.Security.Permissions/RegistryPermissionTest.cs index fb3770db4b4..f95691c7f54 100644 --- a/mcs/class/corlib/Test/System.Security.Permissions/RegistryPermissionTest.cs +++ b/mcs/class/corlib/Test/System.Security.Permissions/RegistryPermissionTest.cs @@ -38,7 +38,6 @@ public class RegistryPermissionTest { private static string className = "System.Security.Permissions.RegistryPermission, "; private static string keyCurrentUser = @"HKEY_CURRENT_USER\Software\Novell iFolder\spouliot\Home"; - private static string keyCurrentUserSubset = @"HKEY_CURRENT_USER\Software\Novell iFolder\"; private static string keyLocalMachine = @"HKEY_LOCAL_MACHINE\SOFTWARE\Novell\Novell iFolder\1.00.000"; private static string keyLocalMachineSubset = @"HKEY_LOCAL_MACHINE\SOFTWARE\Novell\"; diff --git a/mcs/class/corlib/Test/System.Security.Permissions/UrlIdentityPermissionTest.cs b/mcs/class/corlib/Test/System.Security.Permissions/UrlIdentityPermissionTest.cs index 62a0c35e1cd..f9a7d8ae21a 100644 --- a/mcs/class/corlib/Test/System.Security.Permissions/UrlIdentityPermissionTest.cs +++ b/mcs/class/corlib/Test/System.Security.Permissions/UrlIdentityPermissionTest.cs @@ -51,12 +51,6 @@ public class UrlIdentityPermissionTest { "*", }; - // accepted as Url but fails to work (as expected) in some methods - static string[] SemiBadUrls = { - "www.mono-project.com:80", - String.Empty, - }; - [Test] public void PermissionState_None () { diff --git a/mcs/class/corlib/Test/System.Threading/ThreadTest.cs b/mcs/class/corlib/Test/System.Threading/ThreadTest.cs index 11e611563c8..9fa19ee4060 100644 --- a/mcs/class/corlib/Test/System.Threading/ThreadTest.cs +++ b/mcs/class/corlib/Test/System.Threading/ThreadTest.cs @@ -85,10 +85,10 @@ public static void CopyOnNewThread () [Category("MobileNotWorking")] // Abort #10240 public class ThreadTest { - TimeSpan Infinite = new TimeSpan (-10000); // -10000 ticks == -1 ms + //TimeSpan Infinite = new TimeSpan (-10000); // -10000 ticks == -1 ms TimeSpan SmallNegative = new TimeSpan (-2); // between 0 and -1.0 (infinite) ms TimeSpan Negative = new TimeSpan (-20000); // really negative - TimeSpan MaxValue = TimeSpan.FromMilliseconds ((long) Int32.MaxValue); + //TimeSpan MaxValue = TimeSpan.FromMilliseconds ((long) Int32.MaxValue); TimeSpan TooLarge = TimeSpan.FromMilliseconds ((long) Int32.MaxValue + 1); static bool is_win32; @@ -545,14 +545,16 @@ public void RenameTpThread () if (!rename_finished) Monitor.Wait (monitor); } - Assert.IsFalse (rename_failed); + Assert.IsTrue (rename_failed); } void Rename_callback (object o) { Thread.CurrentThread.Name = "a"; try { Thread.CurrentThread.Name = "b"; - } catch (Exception) { + Console.WriteLine ("Thread name is: {0}", Thread.CurrentThread.Name); + } catch (Exception e) { + Console.Error.WriteLine (e); rename_failed = true; } object monitor = o; @@ -1254,8 +1256,6 @@ public void ParametrizedThreadStart () Assert.AreEqual (this, arg, "obj"); } - bool set_name_failed; - [Test] public void SetNameTpThread () { ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc)); diff --git a/mcs/class/corlib/Test/System/AppDomainTest.cs b/mcs/class/corlib/Test/System/AppDomainTest.cs index 8772d7afdea..0836640057e 100644 --- a/mcs/class/corlib/Test/System/AppDomainTest.cs +++ b/mcs/class/corlib/Test/System/AppDomainTest.cs @@ -3240,6 +3240,7 @@ private static Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sende } #endif + public class StuffToPick { public StuffToPick () {} @@ -3248,6 +3249,11 @@ public void Method () {} public event Action Event; public int Field; public void GenericMethod () {} + + public void Dummy () + { + Event += delegate {}; + } } public class StuffToPick @@ -3257,7 +3263,12 @@ public void Method () {} public int Property { get; set; } public event Action Event; public int Field; - public void GenericMethod () {} + public void GenericMethod () {} + + public void Dummy () + { + Event += delegate {}; + } } static void TestSerialization (CrossDomainTester tester, object o) diff --git a/mcs/class/corlib/Test/System/SByteTest.cs b/mcs/class/corlib/Test/System/SByteTest.cs index 9bf4d31a1cd..c8d40396c29 100644 --- a/mcs/class/corlib/Test/System/SByteTest.cs +++ b/mcs/class/corlib/Test/System/SByteTest.cs @@ -24,12 +24,15 @@ public class SByteTest private const string MyString3 = "127"; private string[] Formats1 = {"c", "d", "e", "f", "g", "n", "p", "x" }; private string[] Formats2 = {"c5", "d5", "e5", "f5", "g5", "n5", "p5", "x5" }; +#if false + // These are not currently being tested against, due to the locale-specific nature of the test, we need a different way of doing this private string[] Results1 = {"("+NumberFormatInfo.CurrentInfo.CurrencySymbol+"128.00)", "-128", "-1.280000e+002", "-128.00", "-128", "-128.00", "-12,800.00 %", "80"}; private string[] Results2 = {NumberFormatInfo.CurrentInfo.CurrencySymbol+"127.00000", "00127", "1.27000e+002", "127.00000", "127", "127.00000", "12,700.00000 %", "0007f"}; +#endif private string[] ResultsNfi1 = {"("+NumberFormatInfo.InvariantInfo.CurrencySymbol+"128.00)", "-128", "-1.280000e+002", "-128.00", "-128", "-128.00", "-12,800.00 %", "80"}; @@ -161,14 +164,17 @@ public void TestToString() Assert.IsTrue(String.Compare(MyString2, MySByte2.ToString()) == 0, "MyString2, MySByte2.ToString()"); Assert.IsTrue(String.Compare(MyString3, MySByte3.ToString()) == 0, "MyString3, MySByte3.ToString()"); //test ToString(string format) + +#if false /* - TODO: These tests depend on the culture of the system running the test. - So, this needs to be tested in a different way. + * TODO: These tests depend on the culture of the system running the test. + * So, this needs to be tested in a different way. + / for (int i=0; i < Formats1.Length; i++) { Assert.IsTrue("i="+i+", Results1[i]="+Results1[i]+", MySByte2.ToString(Formats1[i])="+MySByte2.ToString(Formats1[i]), String.Compare(Results1[i], MySByte2.ToString(Formats1[i])) == 0); Assert.IsTrue(String.Compare(Results2[i], MySByte3.ToString(Formats2[i])) == 0, "Results2[i], MySByte3.ToString(Formats2[i])"); } - */ +#endif //test ToString(string format, IFormatProvider provider); for (int i=0; i < Formats1.Length; i++) { Assert.IsTrue(String.Compare(ResultsNfi1[i], MySByte2.ToString(Formats1[i], Nfi)) == 0, "i="+i+", ResultsNfi1[i]="+ResultsNfi1[i]+", MySByte2.ToString(Formats1[i]="+Formats1[i]+"): Expected "+ResultsNfi1[i]+" but got "+MySByte2.ToString(Formats1[i], Nfi)); diff --git a/mcs/class/corlib/Test/System/TypeTest.cs b/mcs/class/corlib/Test/System/TypeTest.cs index 00131c8d47f..6acbac2dd9f 100644 --- a/mcs/class/corlib/Test/System/TypeTest.cs +++ b/mcs/class/corlib/Test/System/TypeTest.cs @@ -143,6 +143,10 @@ public virtual int Foo { } public event EventHandler E; + public void Dummy () + { + E += delegate {}; + } } class Derived1 : Base1 @@ -159,7 +163,11 @@ class Derived2 : Base1 set { } } - public event Action E; + public new event Action E; + public new void Dummy () + { + E += delegate {}; + } } public class Foo @@ -1860,7 +1868,9 @@ public void TestAssemblyQualifiedName () struct B { + #pragma warning disable 169 int value; + #pragma warning restore 169 } [Test] @@ -2153,7 +2163,7 @@ public static void OutTest (out string[] a1) a1 = new string [10]; } - class X + public class X { public static int Value; } From d56a23750b47eea8ce13b095ccd1339346b635a8 Mon Sep 17 00:00:00 2001 From: Jonathan Chambers Date: Tue, 23 Sep 2014 12:41:44 -0400 Subject: [PATCH 207/543] Fix Win32 call in IsUserProtected. Usage was incorrect and freeing the wrong parameter causing a memory corruption. --- mono/metadata/security.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mono/metadata/security.c b/mono/metadata/security.c index c61eab99f7b..65a562da72c 100644 --- a/mono/metadata/security.c +++ b/mono/metadata/security.c @@ -701,9 +701,10 @@ IsUserProtected (gunichar2 *path) gboolean success = FALSE; PACL pDACL = NULL; PSID pEveryoneSid = NULL; + PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; DWORD dwRes = GetNamedSecurityInfoW (path, SE_FILE_OBJECT, - DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL, NULL, NULL); + DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL, NULL, &pSecurityDescriptor); if (dwRes != ERROR_SUCCESS) return FALSE; @@ -720,8 +721,8 @@ IsUserProtected (gunichar2 *path) /* Note: we don't need to check our own access - we'll know soon enough when reading the file */ - if (pDACL) - LocalFree (pDACL); + if (pSecurityDescriptor) + LocalFree (pSecurityDescriptor); return success; } From 116f4d2749b4babd6637259799877b30480c9b47 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 18:01:38 +0100 Subject: [PATCH 208/543] Uri made from UNIX path and RelativeOrAbsolute is now relative. This was changed because the path might be a relative http path and should take precedence over an absolute UNIX path. --- mcs/class/System/Test/System/UriTypeConverterTest.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/mcs/class/System/Test/System/UriTypeConverterTest.cs b/mcs/class/System/Test/System/UriTypeConverterTest.cs index b37d5a86578..fa92b2d04ac 100644 --- a/mcs/class/System/Test/System/UriTypeConverterTest.cs +++ b/mcs/class/System/Test/System/UriTypeConverterTest.cs @@ -230,13 +230,8 @@ public void ConvertFromString () Assert.AreEqual ("~/SomeUri.txt", (o as Uri).ToString (), "CFS_02"); o = converter.ConvertFrom ("/SomeUri.txt"); - if (isWin32) { - Assert.IsFalse ((o as Uri).IsAbsoluteUri, "CFS_03_WIN"); - Assert.AreEqual ("/SomeUri.txt", (o as Uri).ToString (), "CFS_04_WIN"); - } else { - Assert.IsTrue ((o as Uri).IsAbsoluteUri, "CFS_03_UNIX"); - Assert.AreEqual ("file:///SomeUri.txt", (o as Uri).ToString (), "CFS_04_UNIX"); - } + Assert.IsFalse ((o as Uri).IsAbsoluteUri, "CFS_03"); + Assert.AreEqual ("/SomeUri.txt", (o as Uri).ToString (), "CFS_04"); } [Test] From 6a249a56115feae7baf9a53b519e468583d8a137 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 31 Jul 2014 12:13:52 +0100 Subject: [PATCH 209/543] Test connection reuse. --- .../Test/System.Net/HttpListenerTest.cs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/mcs/class/System/Test/System.Net/HttpListenerTest.cs b/mcs/class/System/Test/System.Net/HttpListenerTest.cs index 25f7b96a9b9..f99fc536a8c 100644 --- a/mcs/class/System/Test/System.Net/HttpListenerTest.cs +++ b/mcs/class/System/Test/System.Net/HttpListenerTest.cs @@ -450,6 +450,57 @@ public void Dispose () Event.Close (); } } + + [Test] + public void ConnectionReuse () + { + var uri = "http://localhost:1338/"; + + HttpListener listener = new HttpListener (); + listener.Prefixes.Add (uri); + listener.Start (); + + IPEndPoint expectedIpEndPoint = CreateListenerRequest (listener, uri); + + Assert.AreEqual (expectedIpEndPoint, CreateListenerRequest (listener, uri), "reuse1"); + Assert.AreEqual (expectedIpEndPoint, CreateListenerRequest (listener, uri), "reuse2"); + } + + public IPEndPoint CreateListenerRequest (HttpListener listener, string uri) + { + IPEndPoint ipEndPoint = null; + listener.BeginGetContext ((result) => ipEndPoint = ListenerCallback (result), listener); + + var request = (HttpWebRequest) WebRequest.Create (uri); + request.Method = "POST"; + + // We need to write something + request.GetRequestStream ().Write (new byte [] {(byte)'a'}, 0, 1); + request.GetRequestStream ().Dispose (); + + // Send request, socket is created or reused. + var response = request.GetResponse (); + + // Close response so socket can be reused. + response.Close (); + + return ipEndPoint; + } + + public static IPEndPoint ListenerCallback (IAsyncResult result) + { + var listener = (HttpListener) result.AsyncState; + var context = listener.EndGetContext (result); + var clientEndPoint = context.Request.RemoteEndPoint; + + // Disposing InputStream should not avoid socket reuse + context.Request.InputStream.Dispose (); + + // Close OutputStream to send response + context.Response.OutputStream.Close (); + + return clientEndPoint; + } } } #endif From 30ec69fd50053812792c1eb474eea4529e6765cf Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 31 Jul 2014 13:04:06 +0100 Subject: [PATCH 210/543] Allow stream reuse when InputStream has been disposed. If InputStream is disposed FlushInput now sets it to null so a new one can be created. --- mcs/class/System/System.Net/HttpListenerRequest.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mcs/class/System/System.Net/HttpListenerRequest.cs b/mcs/class/System/System.Net/HttpListenerRequest.cs index 23a17199bf9..d1133f9c342 100644 --- a/mcs/class/System/System.Net/HttpListenerRequest.cs +++ b/mcs/class/System/System.Net/HttpListenerRequest.cs @@ -329,6 +329,9 @@ internal bool FlushInput () return false; if (InputStream.EndRead (ares) <= 0) return true; + } catch (ObjectDisposedException e) { + input_stream = null; + return true; } catch { return false; } From 42173889e7fbb51adca0e40e186055b2ef22f75b Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 23 Sep 2014 14:15:59 -0400 Subject: [PATCH 211/543] [jit] Fix EH on amd64 which got broken by d5a18ba292367e375d215ca2351cf1fa9b0a1d8e. --- mono/mini/exceptions-amd64.c | 6 ------ mono/mini/mini-amd64.c | 4 ---- 2 files changed, 10 deletions(-) diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 592969a5256..98ebc58dd3c 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -606,12 +606,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, /* Adjust IP */ new_ctx->rip --; -#ifndef MONO_AMD64_NO_PUSHES - /* Pop arguments off the stack */ - if (ji->has_arch_eh_info) - new_ctx->rsp += mono_jit_info_get_arch_eh_info (ji)->stack_size; -#endif - return TRUE; } else if (*lmf) { guint64 rip; diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 8a69db7f005..faa8cafd322 100755 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -1986,10 +1986,6 @@ mono_arch_create_vars (MonoCompile *cfg) cfg->lmf_ir_mono_lmf = TRUE; #endif } - -#ifndef HOST_WIN32 - cfg->arch_eh_jit_info = 1; -#endif } static void From d127a1a911858f2ebdba1e0c8ac2d1bf752d531a Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Tue, 23 Sep 2014 14:03:18 -0400 Subject: [PATCH 212/543] [System.Data] Add new file to the mobile_* sources build (to fix XI build) --- mcs/class/System.Data/mobile_System.Data.dll.sources | 1 + 1 file changed, 1 insertion(+) diff --git a/mcs/class/System.Data/mobile_System.Data.dll.sources b/mcs/class/System.Data/mobile_System.Data.dll.sources index b1174b83615..5a5ed877c55 100644 --- a/mcs/class/System.Data/mobile_System.Data.dll.sources +++ b/mcs/class/System.Data/mobile_System.Data.dll.sources @@ -225,6 +225,7 @@ System.Data.SqlClient/SqlCommand.cs System.Data.SqlClient/SqlCommandBuilder.cs System.Data.SqlClient/SqlConnection.cs System.Data.SqlClient/SqlConnectionStringBuilder.cs +System.Data.SqlClient/SqlCredential.cs System.Data.SqlClient/SqlDataAdapter.cs System.Data.SqlClient/SqlDataReader.cs System.Data.SqlClient/SqlDataSourceConverter.cs From 18186487ee41c796852004ecbfdbea557da75c63 Mon Sep 17 00:00:00 2001 From: Michael Hutchinson Date: Tue, 23 Sep 2014 14:53:58 -0400 Subject: [PATCH 213/543] Environment.IsRunningOnWindows can be true on MOBILE --- mcs/class/corlib/System/Environment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/corlib/System/Environment.cs b/mcs/class/corlib/System/Environment.cs index 12260621239..f864785b9ef 100644 --- a/mcs/class/corlib/System/Environment.cs +++ b/mcs/class/corlib/System/Environment.cs @@ -884,7 +884,7 @@ public static extern int ProcessorCount { } // private methods -#if MOBILE +#if (MONOTOUCH || MONODROID || XAMMAC) internal const bool IsRunningOnWindows = false; #else internal static bool IsRunningOnWindows { From 7d3eaf50a88dc9d564c55936e8b39836b0cd7e68 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 23 Sep 2014 17:05:30 -0400 Subject: [PATCH 214/543] Revert "Uri made from UNIX path and RelativeOrAbsolute is now relative." --- mcs/class/System/System/UriParseComponents.cs | 2 +- mcs/class/System/Test/System/UriTest.cs | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/mcs/class/System/System/UriParseComponents.cs b/mcs/class/System/System/UriParseComponents.cs index 39c26a8588f..5e94d3bdf53 100644 --- a/mcs/class/System/System/UriParseComponents.cs +++ b/mcs/class/System/System/UriParseComponents.cs @@ -206,7 +206,7 @@ private static bool ParseUnixFilePath (ParserState state) state.elements.scheme = Uri.UriSchemeFile; state.elements.delimiter = "://"; state.elements.isUnixFilePath = true; - state.elements.isAbsoluteUri = state.kind == UriKind.Absolute; + state.elements.isAbsoluteUri = (state.kind == UriKind.Relative)? false : true; if (part.Length >= 2 && part [0] == '/' && part [1] == '/') { part = part.TrimStart (new char [] {'/'}); diff --git a/mcs/class/System/Test/System/UriTest.cs b/mcs/class/System/Test/System/UriTest.cs index be0c0370b13..4cf95d4456b 100644 --- a/mcs/class/System/Test/System/UriTest.cs +++ b/mcs/class/System/Test/System/UriTest.cs @@ -1940,13 +1940,6 @@ public void GetComponents_Fragment () Assert.AreEqual ("id=1%262&sort=asc", escaped, "UriEscaped"); } - [Test] - public void RelativeOrAbsoluteUnixPath () - { - var uri = new Uri ("/abc", UriKind.RelativeOrAbsolute); - Assert.IsFalse (uri.IsAbsoluteUri); - } - [Test] // Bug #12631 public void LocalPathWithBaseUrl () From feacff01857b069c04021b16ae4dcacd3dd2dba8 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 22:27:12 +0100 Subject: [PATCH 215/543] Revert "Uri made from UNIX path and RelativeOrAbsolute is now relative." This reverts commit 116f4d2749b4babd6637259799877b30480c9b47. --- mcs/class/System/Test/System/UriTypeConverterTest.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mcs/class/System/Test/System/UriTypeConverterTest.cs b/mcs/class/System/Test/System/UriTypeConverterTest.cs index fa92b2d04ac..b37d5a86578 100644 --- a/mcs/class/System/Test/System/UriTypeConverterTest.cs +++ b/mcs/class/System/Test/System/UriTypeConverterTest.cs @@ -230,8 +230,13 @@ public void ConvertFromString () Assert.AreEqual ("~/SomeUri.txt", (o as Uri).ToString (), "CFS_02"); o = converter.ConvertFrom ("/SomeUri.txt"); - Assert.IsFalse ((o as Uri).IsAbsoluteUri, "CFS_03"); - Assert.AreEqual ("/SomeUri.txt", (o as Uri).ToString (), "CFS_04"); + if (isWin32) { + Assert.IsFalse ((o as Uri).IsAbsoluteUri, "CFS_03_WIN"); + Assert.AreEqual ("/SomeUri.txt", (o as Uri).ToString (), "CFS_04_WIN"); + } else { + Assert.IsTrue ((o as Uri).IsAbsoluteUri, "CFS_03_UNIX"); + Assert.AreEqual ("file:///SomeUri.txt", (o as Uri).ToString (), "CFS_04_UNIX"); + } } [Test] From c30a3e46d2f94682b4ec1cac42b7c7ddb0a39059 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 23 Sep 2014 18:26:01 -0400 Subject: [PATCH 216/543] [aot] Fix running with a loadable llvm module in aot-cache mode. --- mono/mini/aot-compiler.c | 2 ++ mono/mini/mini.c | 35 +++++++++++++++++++++++++++++++++++ mono/mini/mini.h | 2 ++ 3 files changed, 39 insertions(+) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 2331d6a7a69..2f51e54d000 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -8885,6 +8885,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) aot_printerrf (acfg, "The 'soft-debug' option is not supported when compiling with LLVM.\n"); return 1; } + + mini_llvm_init (); } if (acfg->aot_opts.full_aot) diff --git a/mono/mini/mini.c b/mono/mini/mini.c index b489216a885..e39a667f970 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -7274,6 +7274,41 @@ mini_free_jit_domain_info (MonoDomain *domain) domain->runtime_info = NULL; } +static gboolean +llvm_init_inner (void) +{ + if (!mono_llvm_load (NULL)) + return FALSE; + + mono_llvm_init (); + return TRUE; +} + +/* + * mini_llvm_init: + * + * Load and initialize LLVM support. + * Return TRUE on success. + */ +gboolean +mini_llvm_init (void) +{ +#ifdef ENABLE_LLVM + static gboolean llvm_inited; + static gboolean init_result; + + mono_loader_lock_if_inited (); + if (!llvm_inited) { + init_result = llvm_init_inner (); + llvm_inited = TRUE; + } + mono_loader_unlock_if_inited (); + return init_result; +#else + return FALSE; +#endif +} + MonoDomain * mini_init (const char *filename, const char *runtime_version) { diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 9200a64c3a5..a0cadfb6bb6 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2202,6 +2202,8 @@ void mono_llvm_emit_aot_module (const char *filename, int got_size) void mono_llvm_check_method_supported (MonoCompile *cfg) MONO_LLVM_INTERNAL; void mono_llvm_free_domain_info (MonoDomain *domain) MONO_LLVM_INTERNAL; +gboolean mini_llvm_init (void); + gboolean mono_method_blittable (MonoMethod *method) MONO_INTERNAL; gboolean mono_method_same_domain (MonoJitInfo *caller, MonoJitInfo *callee) MONO_INTERNAL; From a8185f3374a164bd143ee808f1b016f743ced8ba Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 23 Sep 2014 18:36:23 -0400 Subject: [PATCH 217/543] [jit] Fix LLVM support on amd64 which got broken by the epilog size changes. --- mono/mini/exceptions-amd64.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 98ebc58dd3c..f6cd5155e0f 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -552,7 +552,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, guint8 *cfa; guint32 unwind_info_len; guint8 *unwind_info; - guint8 *epilog; + guint8 *epilog = NULL; frame->type = FRAME_TYPE_MANAGED; @@ -565,7 +565,9 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, printf ("%s %p %p\n", ji->d.method->name, ji->code_start, ip); mono_print_unwind_info (unwind_info, unwind_info_len); */ - epilog = (guint8*)ji->code_start + ji->code_size - mono_jinfo_get_epilog_size (ji); + /* LLVM compiled code doesn't have this info */ + if (ji->has_arch_eh_info) + epilog = (guint8*)ji->code_start + ji->code_size - mono_jinfo_get_epilog_size (ji); regs [AMD64_RAX] = new_ctx->rax; regs [AMD64_RBX] = new_ctx->rbx; @@ -583,7 +585,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, (guint8*)ji->code_start + ji->code_size, - ip, &epilog, regs, MONO_MAX_IREGS + 1, + ip, epilog ? &epilog : NULL, regs, MONO_MAX_IREGS + 1, save_locations, MONO_MAX_IREGS, &cfa); new_ctx->rax = regs [AMD64_RAX]; From 2b5078c30637b87e30a26919e49c819d4e7a7e32 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 23 Sep 2014 18:40:34 -0400 Subject: [PATCH 218/543] [bcl] Fix the RenameTpThread test, renaming a tp thread should not fail. --- mcs/class/corlib/Test/System.Threading/ThreadTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mcs/class/corlib/Test/System.Threading/ThreadTest.cs b/mcs/class/corlib/Test/System.Threading/ThreadTest.cs index 9fa19ee4060..67bcd941d45 100644 --- a/mcs/class/corlib/Test/System.Threading/ThreadTest.cs +++ b/mcs/class/corlib/Test/System.Threading/ThreadTest.cs @@ -545,16 +545,16 @@ public void RenameTpThread () if (!rename_finished) Monitor.Wait (monitor); } - Assert.IsTrue (rename_failed); + Assert.IsTrue (!rename_failed); } void Rename_callback (object o) { Thread.CurrentThread.Name = "a"; try { Thread.CurrentThread.Name = "b"; - Console.WriteLine ("Thread name is: {0}", Thread.CurrentThread.Name); + //Console.WriteLine ("Thread name is: {0}", Thread.CurrentThread.Name); } catch (Exception e) { - Console.Error.WriteLine (e); + //Console.Error.WriteLine (e); rename_failed = true; } object monitor = o; From db5275ca56005303caa73d0162f80b35b2bba7d0 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Wed, 24 Sep 2014 15:30:32 +0800 Subject: [PATCH 219/543] [xlinq] fix bug #23318 - XComment.ToString() accepts "invalid" values. Before it passes the value to XmlWriter.WriteComment(), it replaces invalid values to valid form. --- .../System.Xml.Linq/XComment.cs | 5 +- .../System.Xml.Linq_test.dll.sources | 1 + .../Test/System.Xml.Linq/XCommentTest.cs | 66 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XCommentTest.cs diff --git a/mcs/class/System.Xml.Linq/System.Xml.Linq/XComment.cs b/mcs/class/System.Xml.Linq/System.Xml.Linq/XComment.cs index edab3fb4775..f7b5e7b6c66 100644 --- a/mcs/class/System.Xml.Linq/System.Xml.Linq/XComment.cs +++ b/mcs/class/System.Xml.Linq/System.Xml.Linq/XComment.cs @@ -25,6 +25,7 @@ // using System; +using System.Linq; using System.Xml; namespace System.Xml.Linq @@ -54,7 +55,9 @@ public string Value { public override void WriteTo (XmlWriter writer) { - writer.WriteComment (value); + var v = value.Replace ("--", "- -"); + v = v.LastOrDefault () == '-' ? v.Substring (0, v.Length - 1) +"D;" : v; + writer.WriteComment (v); } } } diff --git a/mcs/class/System.Xml.Linq/System.Xml.Linq_test.dll.sources b/mcs/class/System.Xml.Linq/System.Xml.Linq_test.dll.sources index 77007ae238d..693d4a2e296 100644 --- a/mcs/class/System.Xml.Linq/System.Xml.Linq_test.dll.sources +++ b/mcs/class/System.Xml.Linq/System.Xml.Linq_test.dll.sources @@ -1,5 +1,6 @@ System.Xml.Linq/ExtensionsTest.cs System.Xml.Linq/XAttributeTest.cs +System.Xml.Linq/XCommentTest.cs System.Xml.Linq/XDocumentTest.cs System.Xml.Linq/XElementTest.cs System.Xml.Linq/XNameTest.cs diff --git a/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XCommentTest.cs b/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XCommentTest.cs new file mode 100644 index 00000000000..b324bb68fcc --- /dev/null +++ b/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XCommentTest.cs @@ -0,0 +1,66 @@ +// +// Authors: +// Atsushi Enomoto +// +// Copyright 2014 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; +using System.Xml; +using System.Xml.Linq; +using System.Linq; + +using NUnit.Framework; + +namespace MonoTests.System.Xml.Linq +{ + [TestFixture] + public class XCommentTest + { + [Test] + public void EscapeSequentialDashes () + { + XComment c; + + c = new XComment ("<--foo-->"); + Assert.AreEqual ("<--foo-->", c.Value, "#1"); + // bug #23318 + // Unlike XmlWriter.WriteComment(), XComment.ToString() seems to accept "--" in the value. + Assert.AreEqual ("", c.ToString (), "#2"); + // make sure if it can be read... + XmlReader.Create (new StringReader (c.ToString ())).Read (); + + // The last '-' causes some glitch... + c = new XComment ("--foo--"); + Assert.AreEqual ("--foo--", c.Value, "#3"); + Assert.AreEqual ("", c.ToString (), "#4"); + XmlReader.Create (new StringReader (c.ToString ())).Read (); + + // What if "); + Assert.AreEqual ("", c.Value, "#5"); + Assert.AreEqual ("", c.ToString (), "#6"); + XmlReader.Create (new StringReader (c.ToString ())).Read (); + } + } +} From ff165854bde268b46dcb5c2a2ef03241e6f2432a Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Wed, 24 Sep 2014 10:40:03 +0100 Subject: [PATCH 220/543] Move llvm_init_inner inside #ifdef ENABLE_LLVM This should fix c30a3e46d2f94682b4ec1cac42b7c7ddb0a39059 failing to link properly with ld 2.22 and GCC 4.9.1, on Linux, with non-LLVM builds. ./.libs/libmini.a(libmini_la-mini.o): In function `llvm_init_inner': mini.c:(.text+0x1182b): undefined reference to `mono_llvm_init' /usr/bin/ld: .libs/libmonoboehm-2.0.so.1.0.0: hidden symbol `mono_llvm_init' isn't defined /usr/bin/ld: final link failed: Bad value --- mono/mini/mini.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mono/mini/mini.c b/mono/mini/mini.c index e39a667f970..551cde41403 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -7274,6 +7274,7 @@ mini_free_jit_domain_info (MonoDomain *domain) domain->runtime_info = NULL; } +#ifdef ENABLE_LLVM static gboolean llvm_init_inner (void) { @@ -7283,6 +7284,7 @@ llvm_init_inner (void) mono_llvm_init (); return TRUE; } +#endif /* * mini_llvm_init: From 1d94d1770d31b69bf24c4661945351969b58cbf3 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Wed, 24 Sep 2014 12:25:45 +0200 Subject: [PATCH 221/543] [mcs] More tweaks to conditional tokenizer. Fixes #23319 --- mcs/mcs/cs-tokenizer.cs | 7 ++++++- mcs/tests/gtest-409.cs | 5 +++++ mcs/tests/ver-il-net_4_5.xml | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mcs/mcs/cs-tokenizer.cs b/mcs/mcs/cs-tokenizer.cs index 2147c145e6c..9647a4bd7e6 100644 --- a/mcs/mcs/cs-tokenizer.cs +++ b/mcs/mcs/cs-tokenizer.cs @@ -1268,6 +1268,7 @@ int TokenizePossibleNullableType () int next_token; int parens = 0; int generics = 0; + int brackets = 0; var nt = xtoken (); switch (nt) { @@ -1333,6 +1334,11 @@ int TokenizePossibleNullableType () ++parens; goto default; + case Token.OPEN_BRACKET: + case Token.OPEN_BRACKET_EXPR: + ++brackets; + goto default; + case Token.CLOSE_PARENS: --parens; goto default; @@ -1348,7 +1354,6 @@ int TokenizePossibleNullableType () int interrs = 1; int colons = 0; int braces = 0; - int brackets = 0; // // All shorcuts failed, do it hard way // diff --git a/mcs/tests/gtest-409.cs b/mcs/tests/gtest-409.cs index 2071b625c3a..2f5ea10ae8f 100644 --- a/mcs/tests/gtest-409.cs +++ b/mcs/tests/gtest-409.cs @@ -155,6 +155,11 @@ void Test_18 (bool b, Action a) var e = b ? () => { } : a; } + void Test_19 (int[,] table) + { + var x = 1 > 0 ? table[5, 1] : 0; + } + static void Helper (T arg) { } diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index d423fd25a71..e193e7b42b3 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -14469,6 +14469,9 @@ 2 + + 11 + From de0543fbea667ef8d85aae180c949b44ce6aba24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Matos?= Date: Wed, 24 Sep 2014 12:18:27 +0100 Subject: [PATCH 222/543] Added support for cross-compiling to x86 Linux/Android. --- configure.ac | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/configure.ac b/configure.ac index 0de87159a12..c6c36c9eefb 100644 --- a/configure.ac +++ b/configure.ac @@ -2806,6 +2806,20 @@ if test "x$host" != "x$target"; then ;; esac ;; + i686*-linux-*) + TARGET=X86; + arch_target=x86; + AC_DEFINE(TARGET_X86, 1, [...]) + AC_DEFINE(TARGET_ANDROID, 1, [...]) + JIT_SUPPORTED=yes + CPPFLAGS="$CPPFLAGS" + jit_wanted=true + sgen_supported=true + # Can't use tls, since it depends on the runtime detection of tls offsets + # in mono-compiler.h + with_tls=pthread + target_mach=no + ;; aarch64-*) TARGET=ARM64 JIT_SUPPORTED=yes From e150fde4e28868cb7b665cefd002fd710e1aa116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Matos?= Date: Wed, 24 Sep 2014 12:21:00 +0100 Subject: [PATCH 223/543] Fixed TLS detection to check for TARGET_MACH instead of __APPLE__. In the case of cross-compiling to x86 Linux from OSX we'd hit compilation issues here. --- mono/utils/mono-compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/utils/mono-compiler.h b/mono/utils/mono-compiler.h index e8a6a27cc7b..d3c41ba44df 100644 --- a/mono/utils/mono-compiler.h +++ b/mono/utils/mono-compiler.h @@ -161,7 +161,7 @@ #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1 #endif -#elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)) +#elif defined(TARGET_MACH) && (defined(__i386__) || defined(__x86_64__)) #define MONO_HAVE_FAST_TLS #define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y) From 67ea9985cbbaaeea43ff4a708a32f210917d02b6 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 24 Sep 2014 12:15:44 +0100 Subject: [PATCH 224/543] UriParserTest.GetComponents_Ftp2 now uses the variable 'ftp2'. --- mcs/class/System/Test/System/UriParserTest.cs | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/mcs/class/System/Test/System/UriParserTest.cs b/mcs/class/System/Test/System/UriParserTest.cs index 79111f90fc4..0373ef20c4c 100644 --- a/mcs/class/System/Test/System/UriParserTest.cs +++ b/mcs/class/System/Test/System/UriParserTest.cs @@ -217,28 +217,28 @@ public void GetComponents_Ftp () public void GetComponents_Ftp2 () { UnitTestUriParser p = new UnitTestUriParser (); - Assert.AreEqual ("ftp", p._GetComponents (ftp, UriComponents.Scheme, UriFormat.Unescaped), "ftp.Scheme"); - Assert.AreEqual ("username:password", p._GetComponents (ftp, UriComponents.UserInfo, UriFormat.Unescaped), "ftp.UserInfo"); - Assert.AreEqual ("ftp.go-mono.com", p._GetComponents (ftp, UriComponents.Host, UriFormat.Unescaped), "ftp.Host"); - Assert.AreEqual (String.Empty, p._GetComponents (ftp, UriComponents.Port, UriFormat.Unescaped), "ftp.Port"); - Assert.AreEqual ("with some spaces/mono.tgz", p._GetComponents (ftp, UriComponents.Path, UriFormat.Unescaped), "ftp.Path"); - Assert.AreEqual ("with%20some%20spaces/mono.tgz", p._GetComponents (ftp, UriComponents.Path, UriFormat.UriEscaped), "ftp.Path-UriEscaped"); - Assert.AreEqual ("with some spaces/mono.tgz", p._GetComponents (ftp, UriComponents.Path, UriFormat.SafeUnescaped), "ftp.Path-SafeUnescaped"); - Assert.AreEqual (String.Empty, p._GetComponents (ftp, UriComponents.Query, UriFormat.Unescaped), "ftp.Query"); - Assert.AreEqual (String.Empty, p._GetComponents (ftp, UriComponents.Fragment, UriFormat.Unescaped), "ftp.Fragment"); - Assert.AreEqual ("21", p._GetComponents (ftp, UriComponents.StrongPort, UriFormat.Unescaped), "ftp.StrongPort"); - Assert.AreEqual (String.Empty, p._GetComponents (ftp, UriComponents.KeepDelimiter, UriFormat.Unescaped), "http.KeepDelimiter"); - Assert.AreEqual ("ftp.go-mono.com:21", p._GetComponents (ftp, UriComponents.HostAndPort, UriFormat.Unescaped), "http.HostAndPort"); - Assert.AreEqual ("username:password@ftp.go-mono.com:21", p._GetComponents (ftp, UriComponents.StrongAuthority, UriFormat.Unescaped), "http.StrongAuthority"); - Assert.AreEqual ("ftp://username:password@ftp.go-mono.com/with some spaces/mono.tgz", p._GetComponents (ftp, UriComponents.AbsoluteUri, UriFormat.Unescaped), "http.AbsoluteUri"); - Assert.AreEqual ("/with some spaces/mono.tgz", p._GetComponents (ftp, UriComponents.PathAndQuery, UriFormat.Unescaped), "http.PathAndQuery"); - Assert.AreEqual ("ftp://ftp.go-mono.com/with some spaces/mono.tgz", p._GetComponents (ftp, UriComponents.HttpRequestUrl, UriFormat.Unescaped), "http.HttpRequestUrl"); - Assert.AreEqual ("ftp://ftp.go-mono.com", p._GetComponents (ftp, UriComponents.SchemeAndServer, UriFormat.Unescaped), "http.SchemeAndServer"); - Assert.AreEqual ("ftp://username:password@ftp.go-mono.com/with some spaces/mono.tgz", p._GetComponents (ftp, UriComponents.SerializationInfoString, UriFormat.Unescaped), "http.SerializationInfoString"); + Assert.AreEqual ("ftp", p._GetComponents (ftp2, UriComponents.Scheme, UriFormat.Unescaped), "ftp.Scheme"); + Assert.AreEqual ("username:password", p._GetComponents (ftp2, UriComponents.UserInfo, UriFormat.Unescaped), "ftp.UserInfo"); + Assert.AreEqual ("ftp.go-mono.com", p._GetComponents (ftp2, UriComponents.Host, UriFormat.Unescaped), "ftp.Host"); + Assert.AreEqual (String.Empty, p._GetComponents (ftp2, UriComponents.Port, UriFormat.Unescaped), "ftp.Port"); + Assert.AreEqual ("with some spaces/mono.tgz", p._GetComponents (ftp2, UriComponents.Path, UriFormat.Unescaped), "ftp.Path"); + Assert.AreEqual ("with%20some%20spaces/mono.tgz", p._GetComponents (ftp2, UriComponents.Path, UriFormat.UriEscaped), "ftp.Path-UriEscaped"); + Assert.AreEqual ("with some spaces/mono.tgz", p._GetComponents (ftp2, UriComponents.Path, UriFormat.SafeUnescaped), "ftp.Path-SafeUnescaped"); + Assert.AreEqual (String.Empty, p._GetComponents (ftp2, UriComponents.Query, UriFormat.Unescaped), "ftp.Query"); + Assert.AreEqual (String.Empty, p._GetComponents (ftp2, UriComponents.Fragment, UriFormat.Unescaped), "ftp.Fragment"); + Assert.AreEqual ("21", p._GetComponents (ftp2, UriComponents.StrongPort, UriFormat.Unescaped), "ftp.StrongPort"); + Assert.AreEqual (String.Empty, p._GetComponents (ftp2, UriComponents.KeepDelimiter, UriFormat.Unescaped), "http.KeepDelimiter"); + Assert.AreEqual ("ftp.go-mono.com:21", p._GetComponents (ftp2, UriComponents.HostAndPort, UriFormat.Unescaped), "http.HostAndPort"); + Assert.AreEqual ("username:password@ftp.go-mono.com:21", p._GetComponents (ftp2, UriComponents.StrongAuthority, UriFormat.Unescaped), "http.StrongAuthority"); + Assert.AreEqual ("ftp://username:password@ftp.go-mono.com/with some spaces/mono.tgz", p._GetComponents (ftp2, UriComponents.AbsoluteUri, UriFormat.Unescaped), "http.AbsoluteUri"); + Assert.AreEqual ("/with some spaces/mono.tgz", p._GetComponents (ftp2, UriComponents.PathAndQuery, UriFormat.Unescaped), "http.PathAndQuery"); + Assert.AreEqual ("ftp://ftp.go-mono.com/with some spaces/mono.tgz", p._GetComponents (ftp2, UriComponents.HttpRequestUrl, UriFormat.Unescaped), "http.HttpRequestUrl"); + Assert.AreEqual ("ftp://ftp.go-mono.com", p._GetComponents (ftp2, UriComponents.SchemeAndServer, UriFormat.Unescaped), "http.SchemeAndServer"); + Assert.AreEqual ("ftp://username:password@ftp.go-mono.com/with some spaces/mono.tgz", p._GetComponents (ftp2, UriComponents.SerializationInfoString, UriFormat.Unescaped), "http.SerializationInfoString"); Assert.AreSame (p, p._OnNewUri (), "OnNewUri"); // strange mixup - Assert.AreEqual ("ftp://username:password@", p._GetComponents (ftp, UriComponents.Scheme | UriComponents.UserInfo, UriFormat.Unescaped), "ftp.Scheme+UserInfo"); - Assert.AreEqual (":21/with some spaces/mono.tgz", p._GetComponents (ftp, UriComponents.Path | UriComponents.StrongPort, UriFormat.Unescaped), "ftp.Path+StrongPort"); + Assert.AreEqual ("ftp://username:password@", p._GetComponents (ftp2, UriComponents.Scheme | UriComponents.UserInfo, UriFormat.Unescaped), "ftp.Scheme+UserInfo"); + Assert.AreEqual (":21/with some spaces/mono.tgz", p._GetComponents (ftp2, UriComponents.Path | UriComponents.StrongPort, UriFormat.Unescaped), "ftp.Path+StrongPort"); } // Test case for Xamarin#17665 From c6ab8995956872767d059d603513f3c35215003d Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Wed, 24 Sep 2014 10:43:46 -0400 Subject: [PATCH 225/543] [System] Fix most warnings on the System test suite --- .../Test/System.CodeDom.Compiler/CodeDomProviderCas.cs | 4 ++-- .../BlockingCollectionTests.cs | 2 +- .../InstanceDescriptorTest.cs | 2 +- .../System/Test/System.ComponentModel/CharConverterTest.cs | 2 -- .../System/Test/System.ComponentModel/ContainerTest.cs | 4 ---- mcs/class/System/Test/System.Diagnostics/ProcessTest.cs | 4 ++-- mcs/class/System/Test/System.Net.Sockets/TcpClientCas.cs | 1 - mcs/class/System/Test/System.Net.Sockets/UdpClientTest.cs | 2 +- .../Test/System.Net.WebSockets/ClientWebSocketTest.cs | 7 +++++++ mcs/class/System/Test/System.Net/DnsCas.cs | 3 +-- mcs/class/System/Test/System.Net/HttpListenerTest.cs | 2 +- .../X500DistinguishedNameTest.cs | 6 ++++-- .../X509ChainTest.cs | 4 ++-- .../System.Text.RegularExpressions/RegexReplaceTests.cs | 2 +- .../System.Text.RegularExpressions/RegexResultTests.cs | 2 +- mcs/class/System/Test/System/UriTest.cs | 2 +- 16 files changed, 25 insertions(+), 24 deletions(-) diff --git a/mcs/class/System/Test/System.CodeDom.Compiler/CodeDomProviderCas.cs b/mcs/class/System/Test/System.CodeDom.Compiler/CodeDomProviderCas.cs index 979734af059..a9d536085bb 100644 --- a/mcs/class/System/Test/System.CodeDom.Compiler/CodeDomProviderCas.cs +++ b/mcs/class/System/Test/System.CodeDom.Compiler/CodeDomProviderCas.cs @@ -317,7 +317,7 @@ public void LinkDemand_GetLanguageFromExtension_Deny_Anything () [ExpectedException (typeof (SecurityException))] public void LinkDemand_IsDefinedExtension_Deny_Anything () { - MethodInfo mi = mi = typeof (CodeDomProvider).GetMethod ("IsDefinedExtension"); + MethodInfo mi = typeof (CodeDomProvider).GetMethod ("IsDefinedExtension"); Assert.IsNotNull (mi, "IsDefinedExtension"); Assert.IsFalse ((bool) mi.Invoke (null, new object[1] { String.Empty }), "IsDefinedExtension('')"); // requires full trust (i.e. unrestricted permission set) @@ -328,7 +328,7 @@ public void LinkDemand_IsDefinedExtension_Deny_Anything () [ExpectedException (typeof (SecurityException))] public void LinkDemand_IsDefinedLanguage_Deny_Anything () { - MethodInfo mi = mi = typeof (CodeDomProvider).GetMethod ("IsDefinedLanguage"); + MethodInfo mi = typeof (CodeDomProvider).GetMethod ("IsDefinedLanguage"); Assert.IsNotNull (mi, "IsDefinedLanguage"); Assert.IsFalse ((bool) mi.Invoke (null, new object[1] { String.Empty }), "IsDefinedLanguage('')"); // requires full trust (i.e. unrestricted permission set) diff --git a/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs b/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs index 9f0e9b0190d..b33a5b4385f 100644 --- a/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs +++ b/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs @@ -237,7 +237,7 @@ public void TakeAnyCancellable () t = Task.Factory.StartNew (() => { try { return BlockingCollection.TakeFromAny (arr, out res, cts.Token); - } catch (OperationCanceledException WE_GOT_CANCELED) { + } catch (OperationCanceledException) { res = "canceled"; return -10; } diff --git a/mcs/class/System/Test/System.ComponentModel.Design.Serialization/InstanceDescriptorTest.cs b/mcs/class/System/Test/System.ComponentModel.Design.Serialization/InstanceDescriptorTest.cs index 16d12af943c..dbc4110cb20 100644 --- a/mcs/class/System/Test/System.ComponentModel.Design.Serialization/InstanceDescriptorTest.cs +++ b/mcs/class/System/Test/System.ComponentModel.Design.Serialization/InstanceDescriptorTest.cs @@ -277,7 +277,7 @@ public static string Name { } } - class InstanceField + public class InstanceField { public string Name; } diff --git a/mcs/class/System/Test/System.ComponentModel/CharConverterTest.cs b/mcs/class/System/Test/System.ComponentModel/CharConverterTest.cs index d0b78f97fba..815a9a62554 100644 --- a/mcs/class/System/Test/System.ComponentModel/CharConverterTest.cs +++ b/mcs/class/System/Test/System.ComponentModel/CharConverterTest.cs @@ -20,7 +20,6 @@ namespace MonoTests.System.ComponentModel public class CharConverterTest { private CharConverter converter; - private string pattern; [SetUp] public void SetUp () @@ -28,7 +27,6 @@ public void SetUp () converter = new CharConverter (); DateTimeFormatInfo info = CultureInfo.CurrentCulture.DateTimeFormat; - pattern = info.ShortDatePattern + " " + info.ShortTimePattern; } [Test] diff --git a/mcs/class/System/Test/System.ComponentModel/ContainerTest.cs b/mcs/class/System/Test/System.ComponentModel/ContainerTest.cs index 16a6a4124dc..46706fd348e 100644 --- a/mcs/class/System/Test/System.ComponentModel/ContainerTest.cs +++ b/mcs/class/System/Test/System.ComponentModel/ContainerTest.cs @@ -733,10 +733,6 @@ public Container CreateContainer () container.Add (this); return container; } - - public Container Container { - get { return container; } - } } class MyContainer : IContainer diff --git a/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs b/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs index 88de1d72a8c..d6ae37eb0f6 100644 --- a/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs +++ b/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs @@ -722,7 +722,7 @@ static bool RunningOnUnix { } } - int bytesRead = -1; + public int bytesRead = -1; #if NET_2_0 // Not technically a 2.0 only test, but I use lambdas, so I need gmcs @@ -836,7 +836,7 @@ public void Handle_ThrowsOnNotStarted () try { var x = p.Handle; Assert.Fail ("Handle should throw for unstated procs, but returned " + x); - } catch (InvalidOperationException ex) { + } catch (InvalidOperationException) { } } } diff --git a/mcs/class/System/Test/System.Net.Sockets/TcpClientCas.cs b/mcs/class/System/Test/System.Net.Sockets/TcpClientCas.cs index 9b2577c41e2..e245fcd5b06 100644 --- a/mcs/class/System/Test/System.Net.Sockets/TcpClientCas.cs +++ b/mcs/class/System/Test/System.Net.Sockets/TcpClientCas.cs @@ -29,7 +29,6 @@ public class TcpClientCas { static ManualResetEvent reset; private string message; - private string uri = "http://www.google.com"; [TestFixtureSetUp] public void FixtureSetUp () diff --git a/mcs/class/System/Test/System.Net.Sockets/UdpClientTest.cs b/mcs/class/System/Test/System.Net.Sockets/UdpClientTest.cs index 9b2453bd6f1..51c3ac795b5 100644 --- a/mcs/class/System/Test/System.Net.Sockets/UdpClientTest.cs +++ b/mcs/class/System/Test/System.Net.Sockets/UdpClientTest.cs @@ -936,7 +936,7 @@ public void CloseInReceive () try { client = new UdpClient (port); break; - } catch (Exception ex) { + } catch (Exception) { if (i == 5) throw; } diff --git a/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs b/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs index e193a5f5307..2140daac9bb 100644 --- a/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs +++ b/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs @@ -49,7 +49,10 @@ public void Teardown () [Test] public void ServerHandshakeReturnCrapStatusCodeTest () { + // On purpose, + #pragma warning disable 4014 HandleHttpRequestAsync ((req, resp) => resp.StatusCode = 418); + #pragma warning restore 4014 try { Assert.IsTrue (socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait (5000)); } catch (AggregateException e) { @@ -62,10 +65,12 @@ public void ServerHandshakeReturnCrapStatusCodeTest () [Test] public void ServerHandshakeReturnWrongUpgradeHeader () { + #pragma warning disable 4014 HandleHttpRequestAsync ((req, resp) => { resp.StatusCode = 101; resp.Headers["Upgrade"] = "gtfo"; }); + #pragma warning restore 4014 try { Assert.IsTrue (socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait (5000)); } catch (AggregateException e) { @@ -78,12 +83,14 @@ public void ServerHandshakeReturnWrongUpgradeHeader () [Test] public void ServerHandshakeReturnWrongConnectionHeader () { + #pragma warning disable 4014 HandleHttpRequestAsync ((req, resp) => { resp.StatusCode = 101; resp.Headers["Upgrade"] = "websocket"; // Mono http request doesn't like the forcing, test still valid since the default connection header value is empty //ForceSetHeader (resp.Headers, "Connection", "Foo"); }); + #pragma warning restore 4014 try { Assert.IsTrue (socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait (5000)); } catch (AggregateException e) { diff --git a/mcs/class/System/Test/System.Net/DnsCas.cs b/mcs/class/System/Test/System.Net/DnsCas.cs index f362e8291ea..b532428fd53 100644 --- a/mcs/class/System/Test/System.Net/DnsCas.cs +++ b/mcs/class/System/Test/System.Net/DnsCas.cs @@ -30,14 +30,13 @@ public class DnsCas { static ManualResetEvent reset; private string message; private string hostname; - private IPAddress ip; [TestFixtureSetUp] public void FixtureSetUp () { reset = new ManualResetEvent (false); hostname = Dns.GetHostName (); - ip = Dns.Resolve (site).AddressList[0]; + var ip = Dns.Resolve (site).AddressList[0]; } [TestFixtureTearDown] diff --git a/mcs/class/System/Test/System.Net/HttpListenerTest.cs b/mcs/class/System/Test/System.Net/HttpListenerTest.cs index 25f7b96a9b9..05ff63ce8ea 100644 --- a/mcs/class/System/Test/System.Net/HttpListenerTest.cs +++ b/mcs/class/System/Test/System.Net/HttpListenerTest.cs @@ -115,7 +115,7 @@ private bool CanOpenPort(int port) socket.Listen(1); } } - catch(Exception ex) { + catch(Exception) { //Can be AccessDeniedException(ports 80/443 need root access) or //SocketException because other application is listening return false; diff --git a/mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X500DistinguishedNameTest.cs b/mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X500DistinguishedNameTest.cs index 88bd3b1cddc..799152f5bbd 100644 --- a/mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X500DistinguishedNameTest.cs +++ b/mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X500DistinguishedNameTest.cs @@ -52,6 +52,7 @@ public class X500DistinguishedNameTest { private static byte[] cert_a_issuer_raw = new byte[] { 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x17, 0x52, 0x53, 0x41, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 }; +#if false private static byte[] cert_b = { 0x30,0x82,0x03,0x04,0x30,0x82,0x02,0xC4,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x03,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x38,0x04,0x03,0x30,0x51,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04,0x0A,0x13,0x0F,0x55,0x2E,0x53,0x2E,0x20,0x47,0x6F,0x76,0x65,0x72,0x6E,0x6D,0x65,0x6E,0x74,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x0B,0x13,0x03,0x44,0x6F,0x44,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x41,0x72,0x6D,0x65,0x64,0x20,0x46,0x6F, 0x72,0x63,0x65,0x73,0x20,0x52,0x6F,0x6F,0x74,0x30,0x1E,0x17,0x0D,0x30,0x30,0x31,0x30,0x32,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x30,0x33,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x51,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04,0x0A,0x13,0x0F,0x55,0x2E,0x53,0x2E,0x20,0x47,0x6F,0x76,0x65,0x72,0x6E,0x6D,0x65,0x6E,0x74,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x0B,0x13,0x03,0x44,0x6F,0x44,0x31,0x1A,0x30,0x18, 0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x41,0x72,0x6D,0x65,0x64,0x20,0x46,0x6F,0x72,0x63,0x65,0x73,0x20,0x52,0x6F,0x6F,0x74,0x30,0x82,0x01,0xB6,0x30,0x82,0x01,0x2B,0x06,0x07,0x2A,0x86,0x48,0xCE,0x38,0x04,0x01,0x30,0x82,0x01,0x1E,0x02,0x81,0x81,0x00,0x90,0x89,0x3E,0x18,0x1B,0xFE,0xA3,0x1D,0x16,0x89,0x00,0xB4,0xD5,0x40,0x82,0x4C,0x2E,0xEC,0x3D,0x66,0x0D,0x0D,0xB9,0x17,0x40,0x6E,0x3A,0x5C,0x03,0x7B,0x1B,0x93,0x28,0x0C,0xEF,0xB9,0x97,0xE3,0xA1,0xEB,0xE2,0xA3,0x7C,0x61,0xDD,0x6F,0xD5,0xAD,0x15,0x69,0x00, @@ -60,6 +61,7 @@ public class X500DistinguishedNameTest { 0x54,0x4B,0xC0,0xA8,0x40,0xEF,0x71,0xE8,0x56,0x6B,0xA2,0x29,0xCB,0x1E,0x09,0x7D,0x27,0x39,0x91,0x3B,0x20,0x4F,0x98,0x39,0xE8,0x39,0xCA,0x98,0xC5,0xAF,0x54,0x03,0x81,0x84,0x00,0x02,0x81,0x80,0x54,0xA8,0x88,0xB5,0x8F,0x01,0x56,0xCE,0x18,0x8F,0xA6,0xD6,0x7C,0x29,0x29,0x75,0x45,0xE8,0x31,0xA4,0x07,0x17,0xED,0x1E,0x5D,0xB2,0x7B,0xBB,0xCE,0x3C,0x97,0x67,0x1E,0x88,0x0A,0xFE,0x7D,0x00,0x22,0x27,0x1D,0x66,0xEE,0xF6,0x1B,0xB6,0x95,0x7F,0x5A,0xFF,0x06,0x34,0x02,0x43,0xC3,0x83,0xC4,0x66,0x2C,0xA1,0x05,0x0E, 0x68,0xB3,0xCA,0xDC,0xD3,0xF9,0x0C,0xC0,0x66,0xDF,0x85,0x84,0x4B,0x20,0x5D,0x41,0xAC,0xC0,0xEC,0x37,0x92,0x0E,0x97,0x19,0xBF,0x53,0x35,0x63,0x27,0x18,0x33,0x35,0x42,0x4D,0xF0,0x2D,0x6D,0xA7,0xA4,0x98,0xAA,0x57,0xF3,0xD2,0xB8,0x6E,0x4E,0x8F,0xFF,0xBE,0x6F,0x4E,0x0F,0x0B,0x44,0x24,0xEE,0xDF,0x4C,0x22,0x5B,0x44,0x98,0x94,0xCB,0xB8,0xA3,0x2F,0x30,0x2D,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x9D,0x2D,0x73,0xC3,0xB8,0xE3,0x4D,0x29,0x28,0xC3,0x65,0xBE,0xA9,0x98,0xCB,0xD6,0x8A,0x06,0x68, 0x9C,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x38,0x04,0x03,0x03,0x2F,0x00,0x30,0x2C,0x02,0x14,0x5A,0x1B,0x2D,0x08,0x0E,0xE6,0x99,0x38,0x8F,0xB5,0x09,0xC9,0x89,0x79,0x7E,0x01,0x30,0xBD,0xCE,0xF0,0x02,0x14,0x71,0x7B,0x08,0x51,0x97,0xCE,0x4D,0x1F,0x6A,0x84,0x47,0x3A,0xC0,0xBD,0x13,0x89,0x81,0xB9,0x01,0x97 }; +#endif static public byte[] RFC3280MandatoryAttributeTypesCACert_crt = { 0x30, 0x82, 0x02, 0xC1, 0x30, 0x82, 0x02, 0x2A, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x60, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x40, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x41, 0x6E, 0x63, 0x68, 0x6F, 0x72, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x31, 0x30, 0x34, 0x31, 0x39, 0x31, 0x34, 0x35, 0x37, 0x32, 0x30, 0x5A, 0x17, 0x0D, 0x31, 0x31, 0x30, 0x34, 0x31, 0x39, 0x31, 0x34, 0x35, 0x37, 0x32, 0x30, 0x5A, 0x30, 0x81, 0x8E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x31, 0x13, 0x30, 0x11, 0x06, 0x0A, 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19, 0x16, 0x03, 0x67, 0x6F, 0x76, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x0A, 0x09, @@ -82,13 +84,13 @@ public class X500DistinguishedNameTest { static public AsnEncodedData emptyData = new AsnEncodedData (new byte[0]); private X509Certificate2 x509a; - private X509Certificate2 x509b; + //private X509Certificate2 x509b; [TestFixtureSetUp] public void FixtureSetUp () { x509a = new X509Certificate2 (cert_a); - x509b = new X509Certificate2 (cert_b); + //x509b = new X509Certificate2 (cert_b); } private void Empty (X500DistinguishedName dn) diff --git a/mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X509ChainTest.cs b/mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X509ChainTest.cs index 9439f666cc8..0ef6418bc14 100644 --- a/mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X509ChainTest.cs +++ b/mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X509ChainTest.cs @@ -41,7 +41,7 @@ namespace MonoTests.System.Security.Cryptography.X509Certificates { [TestFixture] public class X509ChainTest { - private X509Certificate2Collection empty; + //private X509Certificate2Collection empty; private X509Certificate2Collection collection; private X509Certificate2 cert_empty; @@ -56,7 +56,7 @@ public void FixtureSetUp () cert1 = new X509Certificate2 (X509Certificate2Test.farscape_pfx, "farscape", X509KeyStorageFlags.Exportable); cert2 = new X509Certificate2 (Encoding.ASCII.GetBytes (X509Certificate2Test.base64_cert)); - empty = new X509Certificate2Collection (); + //empty = new X509Certificate2Collection (); collection = new X509Certificate2Collection (); collection.Add (cert1); collection.Add (cert2); diff --git a/mcs/class/System/Test/System.Text.RegularExpressions/RegexReplaceTests.cs b/mcs/class/System/Test/System.Text.RegularExpressions/RegexReplaceTests.cs index 5d30f5d7ed0..55dd1e6d05d 100644 --- a/mcs/class/System/Test/System.Text.RegularExpressions/RegexReplaceTests.cs +++ b/mcs/class/System/Test/System.Text.RegularExpressions/RegexReplaceTests.cs @@ -22,7 +22,7 @@ public void Execute () { try { result = Regex.Replace (original, pattern, replacement); } - catch (Exception e) { + catch (Exception) { result = "Error."; } Assert.AreEqual (expected, result, "rr#: {0} ~ s,{1},{2},", diff --git a/mcs/class/System/Test/System.Text.RegularExpressions/RegexResultTests.cs b/mcs/class/System/Test/System.Text.RegularExpressions/RegexResultTests.cs index 1cf18ee74da..4129b75a125 100644 --- a/mcs/class/System/Test/System.Text.RegularExpressions/RegexResultTests.cs +++ b/mcs/class/System/Test/System.Text.RegularExpressions/RegexResultTests.cs @@ -24,7 +24,7 @@ public void Execute () { Match match = Regex.Match (original, pattern); result = match.Result (replacement); } - catch (Exception e) { + catch (Exception) { result = "Error."; } Assert.AreEqual (expected, result, "rr#: {0} ~ s,{1},{2},", diff --git a/mcs/class/System/Test/System/UriTest.cs b/mcs/class/System/Test/System/UriTest.cs index 4cf95d4456b..fa76c2a67d4 100644 --- a/mcs/class/System/Test/System/UriTest.cs +++ b/mcs/class/System/Test/System/UriTest.cs @@ -1993,7 +1993,7 @@ public class UriTestAux : UriTest private bool originalIriParsing; [TestFixtureSetUp] - public void GetReady () + public void GetReady2 () { isWin32 = (Path.DirectorySeparatorChar == '\\'); From f5f69e540e19bae73021c71ff769b98878a478be Mon Sep 17 00:00:00 2001 From: Lluis Sanchez Date: Wed, 24 Sep 2014 16:50:15 +0200 Subject: [PATCH 226/543] [System.Net] Add support for .pac proxy config scripts on mac --- mcs/class/System/System.Net/MacProxy.cs | 112 +++++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/mcs/class/System/System.Net/MacProxy.cs b/mcs/class/System/System.Net/MacProxy.cs index 45740306db5..0b5d6a76e4b 100644 --- a/mcs/class/System/System.Net/MacProxy.cs +++ b/mcs/class/System/System.Net/MacProxy.cs @@ -225,6 +225,14 @@ public CFRange (int loc, int len) } } + internal struct CFStreamClientContext { + public IntPtr Version; + public IntPtr Info; + public IntPtr Retain; + public IntPtr Release; + public IntPtr CopyDescription; + } + internal class CFString : CFObject { string str; @@ -361,6 +369,52 @@ public static CFUrl Create (string absolute) } } + internal class CFRunLoop : CFObject + { + [DllImport (CFObject.CoreFoundationLibrary)] + static extern void CFRunLoopAddSource (IntPtr rl, IntPtr source, IntPtr mode); + + [DllImport (CFObject.CoreFoundationLibrary)] + static extern void CFRunLoopRemoveSource (IntPtr rl, IntPtr source, IntPtr mode); + + [DllImport (CFObject.CoreFoundationLibrary)] + static extern int CFRunLoopRunInMode (IntPtr mode, double seconds, bool returnAfterSourceHandled); + + [DllImport (CFObject.CoreFoundationLibrary)] + static extern IntPtr CFRunLoopGetCurrent (); + + [DllImport (CFObject.CoreFoundationLibrary)] + static extern void CFRunLoopStop (IntPtr rl); + + public CFRunLoop (IntPtr handle, bool own): base (handle, own) + { + } + + public static CFRunLoop CurrentRunLoop { + get { return new CFRunLoop (CFRunLoopGetCurrent (), false); } + } + + public void AddSource (IntPtr source, CFString mode) + { + CFRunLoopAddSource (Handle, source, mode.Handle); + } + + public void RemoveSource (IntPtr source, CFString mode) + { + CFRunLoopRemoveSource (Handle, source, mode.Handle); + } + + public int RunInMode (CFString mode, double seconds, bool returnAfterSourceHandled) + { + return CFRunLoopRunInMode (mode.Handle, seconds, returnAfterSourceHandled); + } + + public void Stop () + { + CFRunLoopStop (Handle); + } + } + internal enum CFProxyType { None, AutoConfigurationUrl, @@ -615,6 +669,10 @@ internal static class CFNetwork { // CFArrayRef CFNetworkCopyProxiesForAutoConfigurationScript (CFStringRef proxyAutoConfigurationScript, CFURLRef targetURL, CFErrorRef* error); extern static IntPtr CFNetworkCopyProxiesForAutoConfigurationScriptSequential (IntPtr proxyAutoConfigurationScript, IntPtr targetURL, out IntPtr error); + [DllImport (CFNetworkLibrary)] + extern static IntPtr CFNetworkExecuteProxyAutoConfigurationURL (IntPtr proxyAutoConfigURL, IntPtr targetURL, CFProxyAutoConfigurationResultCallback cb, ref CFStreamClientContext clientContext); + + class GetProxyData : IDisposable { public IntPtr script; public IntPtr targetUri; @@ -737,6 +795,45 @@ public static CFProxy[] GetProxiesForAutoConfigurationScript (IntPtr proxyAutoCo return proxies; } + + delegate void CFProxyAutoConfigurationResultCallback (IntPtr client, IntPtr proxyList, IntPtr error); + + public static CFProxy[] ExecuteProxyAutoConfigurationURL (IntPtr proxyAutoConfigURL, Uri targetURL) + { + CFUrl url = CFUrl.Create (targetURL.AbsoluteUri); + if (url == null) + return null; + + CFProxy[] proxies = null; + + var runLoop = CFRunLoop.CurrentRunLoop; + + // Callback that will be called after executing the configuration script + CFProxyAutoConfigurationResultCallback cb = delegate (IntPtr client, IntPtr proxyList, IntPtr error) { + if (proxyList != IntPtr.Zero) { + var array = new CFArray (proxyList, false); + proxies = new CFProxy [array.Count]; + for (int i = 0; i < proxies.Length; i++) { + CFDictionary dict = new CFDictionary (array[i], false); + proxies[i] = new CFProxy (dict); + } + array.Dispose (); + } + runLoop.Stop (); + }; + + var clientContext = new CFStreamClientContext (); + var loopSource = CFNetworkExecuteProxyAutoConfigurationURL (proxyAutoConfigURL, url.Handle, cb, ref clientContext); + + // Create a private mode + var mode = CFString.Create ("Mono.MacProxy"); + + runLoop.AddSource (loopSource, mode); + runLoop.RunInMode (mode, double.MaxValue, false); + runLoop.RemoveSource (loopSource, mode); + + return proxies; + } [DllImport (CFNetworkLibrary)] // CFArrayRef CFNetworkCopyProxiesForURL (CFURLRef url, CFDictionaryRef proxySettings); @@ -859,7 +956,18 @@ static Uri GetProxyUri (CFProxy proxy, out NetworkCredential credentials) static Uri GetProxyUriFromScript (IntPtr script, Uri targetUri, out NetworkCredential credentials) { CFProxy[] proxies = CFNetwork.GetProxiesForAutoConfigurationScript (script, targetUri); - + return SelectProxy (proxies, targetUri, out credentials); + } + + static Uri ExecuteProxyAutoConfigurationURL (IntPtr proxyAutoConfigURL, Uri targetUri, out NetworkCredential credentials) + { + CFProxy[] proxies = CFNetwork.ExecuteProxyAutoConfigurationURL (proxyAutoConfigURL, targetUri); + return SelectProxy (proxies, targetUri, out credentials); + } + + + static Uri SelectProxy (CFProxy[] proxies, Uri targetUri, out NetworkCredential credentials) + { if (proxies == null) { credentials = null; return targetUri; @@ -907,7 +1015,7 @@ public Uri GetProxy (Uri targetUri) proxy = GetProxyUriFromScript (proxies[i].AutoConfigurationJavaScript, targetUri, out credentials); break; case CFProxyType.AutoConfigurationUrl: - // unsupported proxy type (requires fetching script from remote url) + proxy = ExecuteProxyAutoConfigurationURL (proxies[i].AutoConfigurationUrl, targetUri, out credentials); break; case CFProxyType.HTTPS: case CFProxyType.HTTP: From 5d4b1f978beff0ffe07452cd918922a4e3c10d4a Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 26 Aug 2014 12:06:08 -0400 Subject: [PATCH 227/543] [sgen] Add major concurrent collector stw time to "Major GC time" counter --- mono/metadata/sgen-gc.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 890001a8cb2..b9cf9945485 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -2997,8 +2997,8 @@ major_finish_collection (const char *reason, size_t old_next_pin_slot, gboolean static gboolean major_do_collection (const char *reason) { - TV_DECLARE (all_atv); - TV_DECLARE (all_btv); + TV_DECLARE (time_start); + TV_DECLARE (time_end); size_t old_next_pin_slot; if (disable_major_collections) @@ -3010,13 +3010,13 @@ major_do_collection (const char *reason) } /* world must be stopped already */ - TV_GETTIME (all_atv); + TV_GETTIME (time_start); major_start_collection (FALSE, &old_next_pin_slot); major_finish_collection (reason, old_next_pin_slot, FALSE); - TV_GETTIME (all_btv); - gc_stats.major_gc_time += TV_ELAPSED (all_atv, all_btv); + TV_GETTIME (time_end); + gc_stats.major_gc_time += TV_ELAPSED (time_start, time_end); /* FIXME: also report this to the user, preferably in gc-end. */ if (major_collector.get_and_reset_num_major_objects_marked) @@ -3028,11 +3028,15 @@ major_do_collection (const char *reason) static void major_start_concurrent_collection (const char *reason) { + TV_DECLARE (time_start); + TV_DECLARE (time_end); long long num_objects_marked; if (disable_major_collections) return; + TV_GETTIME (time_start); + num_objects_marked = major_collector.get_and_reset_num_major_objects_marked (); g_assert (num_objects_marked == 0); @@ -3048,15 +3052,24 @@ major_start_concurrent_collection (const char *reason) num_objects_marked = major_collector.get_and_reset_num_major_objects_marked (); MONO_GC_CONCURRENT_START_END (GENERATION_OLD, num_objects_marked); + TV_GETTIME (time_end); + gc_stats.major_gc_time += TV_ELAPSED (time_start, time_end); + current_collection_generation = -1; } static gboolean major_update_or_finish_concurrent_collection (gboolean force_finish) { + TV_DECLARE (total_start); + TV_DECLARE (total_end); + TV_DECLARE (minor_start); + TV_DECLARE (minor_end); SgenGrayQueue unpin_queue; memset (&unpin_queue, 0, sizeof (unpin_queue)); + TV_GETTIME (total_start); + MONO_GC_CONCURRENT_UPDATE_FINISH_BEGIN (GENERATION_OLD, major_collector.get_and_reset_num_major_objects_marked ()); binary_protocol_concurrent_update_finish (); @@ -3067,6 +3080,10 @@ major_update_or_finish_concurrent_collection (gboolean force_finish) sgen_los_update_cardtable_mod_union (); MONO_GC_CONCURRENT_UPDATE_END (GENERATION_OLD, major_collector.get_and_reset_num_major_objects_marked ()); + + TV_GETTIME (total_end); + gc_stats.major_gc_time += TV_ELAPSED (total_start, total_end); + return FALSE; } @@ -3081,7 +3098,9 @@ major_update_or_finish_concurrent_collection (gboolean force_finish) major_collector.update_cardtable_mod_union (); sgen_los_update_cardtable_mod_union (); + TV_GETTIME (minor_start); collect_nursery (&unpin_queue, TRUE); + TV_GETTIME (minor_end); if (mod_union_consistency_check) sgen_check_mod_union_consistency (); @@ -3097,6 +3116,9 @@ major_update_or_finish_concurrent_collection (gboolean force_finish) MONO_GC_CONCURRENT_FINISH_END (GENERATION_OLD, major_collector.get_and_reset_num_major_objects_marked ()); + TV_GETTIME (total_end); + gc_stats.major_gc_time += TV_ELAPSED (total_start, total_end) - TV_ELAPSED (minor_start, minor_end); + current_collection_generation = -1; return TRUE; From 546831886ec0fb7afd085bc4c1797765cf49667a Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 26 Aug 2014 12:07:09 -0400 Subject: [PATCH 228/543] [sgen] Add concurrent collector counter for time spent during concurrent phase --- mono/metadata/gc-internal.h | 1 + mono/metadata/gc.c | 1 + mono/metadata/sgen-gc.c | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/mono/metadata/gc-internal.h b/mono/metadata/gc-internal.h index f2e59acb844..f5e9ba95dc0 100644 --- a/mono/metadata/gc-internal.h +++ b/mono/metadata/gc-internal.h @@ -21,6 +21,7 @@ typedef struct { int major_gc_count; long long minor_gc_time; long long major_gc_time; + long long major_gc_time_concurrent; #ifdef HEAVY_STATISTICS unsigned long long gray_queue_section_alloc; unsigned long long gray_queue_section_free; diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 03b182b99f4..95073555641 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -1154,6 +1154,7 @@ mono_gc_init (void) mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.major_gc_count); mono_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time); mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time); + mono_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent); #ifdef HEAVY_STATISTICS mono_counters_register ("Gray Queue alloc section", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_section_alloc); mono_counters_register ("Gray Queue free section", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_section_free); diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index b9cf9945485..ad459484cc9 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -347,6 +347,9 @@ static long long time_major_los_sweep = 0; static long long time_major_sweep = 0; static long long time_major_fragment_creation = 0; +static SGEN_TV_DECLARE (time_major_conc_collection_start); +static SGEN_TV_DECLARE (time_major_conc_collection_end); + int gc_debug_level = 0; FILE* gc_debug_file; @@ -3036,6 +3039,7 @@ major_start_concurrent_collection (const char *reason) return; TV_GETTIME (time_start); + SGEN_TV_GETTIME (time_major_conc_collection_start); num_objects_marked = major_collector.get_and_reset_num_major_objects_marked (); g_assert (num_objects_marked == 0); @@ -3095,6 +3099,9 @@ major_update_or_finish_concurrent_collection (gboolean force_finish) */ wait_for_workers_to_finish (); + SGEN_TV_GETTIME (time_major_conc_collection_end); + gc_stats.major_gc_time_concurrent += SGEN_TV_ELAPSED (time_major_conc_collection_start, time_major_conc_collection_end); + major_collector.update_cardtable_mod_union (); sgen_los_update_cardtable_mod_union (); From 294e5214b2238e7556bc9cc1b2bdd756b7003a86 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Mon, 22 Sep 2014 18:08:36 -0700 Subject: [PATCH 229/543] [sgen] Don't get time twice at the same time. --- mono/metadata/sgen-gc.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index ad459484cc9..545d14f23bc 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -350,6 +350,9 @@ static long long time_major_fragment_creation = 0; static SGEN_TV_DECLARE (time_major_conc_collection_start); static SGEN_TV_DECLARE (time_major_conc_collection_end); +static SGEN_TV_DECLARE (last_minor_collection_start_tv); +static SGEN_TV_DECLARE (last_minor_collection_end_tv); + int gc_debug_level = 0; FILE* gc_debug_file; @@ -2227,14 +2230,15 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) ScanThreadDataJobData *stdjd; mword fragment_total; ScanCopyContext ctx; - TV_DECLARE (all_atv); - TV_DECLARE (all_btv); TV_DECLARE (atv); TV_DECLARE (btv); if (disable_minor_collections) return TRUE; + TV_GETTIME (last_minor_collection_start_tv); + atv = last_minor_collection_start_tv; + MONO_GC_BEGIN (GENERATION_NURSERY); binary_protocol_collection_begin (gc_stats.minor_gc_count, GENERATION_NURSERY); @@ -2267,9 +2271,6 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) g_assert (nursery_section->size >= max_garbage_amount); /* world must be stopped already */ - TV_GETTIME (all_atv); - atv = all_atv; - TV_GETTIME (btv); time_minor_pre_collection_fragment_clear += TV_ELAPSED (atv, btv); @@ -2449,8 +2450,8 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) major_collector.finish_nursery_collection (); - TV_GETTIME (all_btv); - gc_stats.minor_gc_time += TV_ELAPSED (all_atv, all_btv); + TV_GETTIME (last_minor_collection_end_tv); + gc_stats.minor_gc_time += TV_ELAPSED (last_minor_collection_start_tv, last_minor_collection_end_tv); if (heap_dump_file) dump_heap ("minor", gc_stats.minor_gc_count - 1, NULL); @@ -3067,8 +3068,6 @@ major_update_or_finish_concurrent_collection (gboolean force_finish) { TV_DECLARE (total_start); TV_DECLARE (total_end); - TV_DECLARE (minor_start); - TV_DECLARE (minor_end); SgenGrayQueue unpin_queue; memset (&unpin_queue, 0, sizeof (unpin_queue)); @@ -3105,9 +3104,7 @@ major_update_or_finish_concurrent_collection (gboolean force_finish) major_collector.update_cardtable_mod_union (); sgen_los_update_cardtable_mod_union (); - TV_GETTIME (minor_start); collect_nursery (&unpin_queue, TRUE); - TV_GETTIME (minor_end); if (mod_union_consistency_check) sgen_check_mod_union_consistency (); @@ -3124,7 +3121,7 @@ major_update_or_finish_concurrent_collection (gboolean force_finish) MONO_GC_CONCURRENT_FINISH_END (GENERATION_OLD, major_collector.get_and_reset_num_major_objects_marked ()); TV_GETTIME (total_end); - gc_stats.major_gc_time += TV_ELAPSED (total_start, total_end) - TV_ELAPSED (minor_start, minor_end); + gc_stats.major_gc_time += TV_ELAPSED (total_start, total_end) - TV_ELAPSED (last_minor_collection_start_tv, last_minor_collection_end_tv); current_collection_generation = -1; From 5ddcc07c67d2d04c682594b3d1dd19a5fd120601 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 25 Sep 2014 13:36:40 +0100 Subject: [PATCH 230/543] Test Rss20ItemFormatter.ReadFrom Guid. Covers 23262. --- .../Rss20ItemFormatterTest.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Syndication/Rss20ItemFormatterTest.cs b/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Syndication/Rss20ItemFormatterTest.cs index 3b83d230cb4..d0ea17ff6ad 100644 --- a/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Syndication/Rss20ItemFormatterTest.cs +++ b/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Syndication/Rss20ItemFormatterTest.cs @@ -351,6 +351,24 @@ public void GetSchema () { Assert.IsNull (((IXmlSerializable) new Rss20ItemFormatter ()).GetSchema ()); } + + [Test] + public void ReadFromGuidPermaLink () + { + const string xml1 = "urn:myid"; + using (XmlReader r = CreateReader (xml1)) { + var rss = new Rss20ItemFormatter (); + rss.ReadFrom (r); + Assert.AreEqual ("urn:myid", rss.Item.Id); + } + + const string xml2 = "urn:myid"; + using (XmlReader r = CreateReader (xml2)) { + var rss = new Rss20ItemFormatter (); + rss.ReadFrom (r); + Assert.AreEqual ("urn:myid", rss.Item.Id); + } + } } } #endif \ No newline at end of file From d7c598b74c4e0eb1f9097382ef13abfd7bc4f382 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 25 Sep 2014 13:38:59 +0100 Subject: [PATCH 231/543] Rss20ItemFormatter.ReadFrom now sets Id when guid is PermaLink. Fixes 23262. --- .../System.ServiceModel.Syndication/Rss20ItemFormatter.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Syndication/Rss20ItemFormatter.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Syndication/Rss20ItemFormatter.cs index cd4c1ffccdf..cd586fa05c3 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Syndication/Rss20ItemFormatter.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Syndication/Rss20ItemFormatter.cs @@ -203,10 +203,9 @@ void ReadXml (XmlReader reader, bool fromSerializable) Item.Links.Add (l); continue; case "guid": + Item.Id = reader.ReadElementContentAsString (); if (reader.GetAttribute ("isPermaLink") == "true") - Item.AddPermalink (CreateUri (reader.ReadElementContentAsString ())); - else - Item.Id = reader.ReadElementContentAsString (); + Item.AddPermalink (CreateUri (Item.Id)); continue; case "pubDate": Item.PublishDate = FromRFC822DateString (reader.ReadElementContentAsString ()); From ee71f0a1e6b75e42cae1fe358fd50c11432e575d Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 25 Sep 2014 15:15:38 +0100 Subject: [PATCH 232/543] Test Json deserialization of a floating-point number as object. Covers 21583. --- .../JsonReaderTest.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/JsonReaderTest.cs b/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/JsonReaderTest.cs index 0ca6f2fb050..de884aeac9a 100644 --- a/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/JsonReaderTest.cs +++ b/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/JsonReaderTest.cs @@ -855,5 +855,16 @@ public void UnicodeEncodingAutoDetect () r.ReadStartElement (); r.Read (); } + + [Test] + public void ReadNumberAsObject () + { + const double testValue = 42.42D; + var serializer = new DataContractJsonSerializer (typeof (object)); + var serializedStream = GetInput (testValue.ToString (CultureInfo.InvariantCulture)); + var deserializedValue = serializer.ReadObject (serializedStream); + Assert.AreEqual (typeof (decimal), deserializedValue.GetType ()); + Assert.AreEqual (testValue, (decimal) deserializedValue); + } } } From 92a4fd26ac859887cc62bb7a0a5b3685546e27a9 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 25 Sep 2014 15:30:46 +0100 Subject: [PATCH 233/543] Improved Json deserialization of floating-point numbers. When DataContractJsonSerializer was created from type object, deserialization of floating.point numbers was not possible. Fixes 21583. --- .../JsonSerializationReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs index 8f8fe7171fe..55d03402ad2 100644 --- a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs +++ b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs @@ -264,7 +264,7 @@ object ReadInstanceDrivenObject () if (double.TryParse (v, NumberStyles.None, CultureInfo.InvariantCulture, out dbl)) return dbl; decimal dec; - if (decimal.TryParse (v, NumberStyles.None, CultureInfo.InvariantCulture, out dec)) + if (decimal.TryParse (v, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out dec)) return dec; throw SerializationError (String.Format ("Invalid JSON input: {0}", v)); default: From 8f2377e855f91a5ffff8def94409eceb6270c880 Mon Sep 17 00:00:00 2001 From: Joel Martinez Date: Wed, 24 Sep 2014 15:16:05 -0400 Subject: [PATCH 234/543] [mdoc] No longer documenting explicitly implemented private interface members. https://bugzilla.xamarin.com/show_bug.cgi?id=18411 If a class explicitly implements an internal interface, those members will no longer be documented, nor will the interface show up in the class' signature. This allows for a library to hide internal implementation details that an end user would not be able to take advantage of (ie. can't cast to internal interface to call methods). Includes test (check-monodocer-internal-interface) added to makefile. --- mcs/tools/mdoc/Makefile | 12 +++- .../mdoc/Mono.Documentation/monodocer.cs | 27 +++++++- .../mdoc/Test/DocTest-InternalInterface.cs | 17 +++++ .../MyNamespace/MyClass.xml | 63 +++++++++++++++++++ .../en.expected-internal-interface/index.xml | 22 +++++++ .../ns-MyNamespace.xml | 6 ++ 6 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 mcs/tools/mdoc/Test/DocTest-InternalInterface.cs create mode 100644 mcs/tools/mdoc/Test/en.expected-internal-interface/MyNamespace/MyClass.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-internal-interface/index.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-internal-interface/ns-MyNamespace.xml diff --git a/mcs/tools/mdoc/Makefile b/mcs/tools/mdoc/Makefile index ad24c3d2d4e..3b7e698d604 100644 --- a/mcs/tools/mdoc/Makefile +++ b/mcs/tools/mdoc/Makefile @@ -104,6 +104,9 @@ Test/DocTest-DropNS-unified.dll: Test/DocTest.dll: $(CSCOMPILE) $(TEST_CSCFLAGS) -debug -unsafe -target:library -out:$@ Test/DocTest.cs +Test/DocTest-InternalInterface.dll: + $(CSCOMPILE) $(TEST_CSCFLAGS) -debug -unsafe -target:library -out:$@ Test/DocTest-InternalInterface.cs + Test/DocTest.dll-v1: -rm -f Test/DocTest.cs cp Test/DocTest-v1.cs Test/DocTest.cs @@ -145,7 +148,13 @@ update-monodocer-dropns-unified-withsecondary: $(PROGRAM) update-monodocer-dropns-classic-secondary: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-classic-secondary.dll $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic-secondary.dll - + +check-monodocer-internal-interface: $(PROGRAM) + # Tests to make sure internal interfaces that are explicitly implemented are not documented + -rm -Rf Test/en.actual + $(MAKE) Test/DocTest-InternalInterface.dll + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-InternalInterface.dll + diff --exclude=.svn -rup Test/en.expected-internal-interface Test/en.actual check-monodocer-update: $(PROGRAM) find Test/en.expected -name \*.xml -exec rm "{}" \; @@ -305,6 +314,7 @@ check-doc-tools-update: check-monodocer-since-update \ check-monodocer-update \ check-monodocer-dropns-classic \ check-monodocer-dropns-classic-withsecondary \ + check-monodocer-internal-interface \ check-monodocer-delete-update \ check-mdoc-export-html-update \ check-mdoc-export-msxdoc-update \ diff --git a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs index 09763096e55..842a4ae439f 100644 --- a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs +++ b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs @@ -980,7 +980,7 @@ private static string GetTypeKind (TypeDefinition type) throw new ArgumentException ("Unknown kind for type: " + type.FullName); } - private static bool IsPublic (TypeDefinition type) + public static bool IsPublic (TypeDefinition type) { TypeDefinition decl = type; while (decl != null) { @@ -1164,6 +1164,27 @@ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition string sig = memberFormatters [0].GetDeclaration (m); if (sig == null) return false; if (seenmembers.ContainsKey(sig)) return false; + + // Verify that the member isn't an explicitly implemented + // member of an internal interface, in which case we shouldn't return true. + MethodDefinition methdef = null; + if (m is MethodDefinition) + methdef = m as MethodDefinition; + else if (m is PropertyDefinition) { + var prop = m as PropertyDefinition; + methdef = prop.GetMethod ?? prop.SetMethod; + } + + if (methdef != null) { + TypeReference iface; + MethodReference imethod; + + if (methdef.Overrides.Count == 1) { + DocUtils.GetInfoForExplicitlyImplementedMethod (methdef, out iface, out imethod); + if (!IsPublic (iface.Resolve ())) return false; + } + } + return true; }) .ToArray(); @@ -3023,7 +3044,7 @@ public static IEnumerable GetUserImplementedInterfaces (TypeDefin if (!inheritedInterfaces.Contains (GetQualifiedTypeName (lookup))) userInterfaces.Add (iface); } - return userInterfaces; + return userInterfaces.Where (i => MDocUpdater.IsPublic (i.Resolve ())); } private static string GetQualifiedTypeName (TypeReference type) @@ -4351,7 +4372,7 @@ protected override string GetTypeDeclaration (TypeDefinition type) buf.Append (full.GetName (type.BaseType).Substring ("class ".Length)); } bool first = true; - foreach (var name in type.Interfaces + foreach (var name in type.Interfaces.Where (i => MDocUpdater.IsPublic (i.Resolve ())) .Select (i => full.GetName (i)) .OrderBy (n => n)) { if (first) { diff --git a/mcs/tools/mdoc/Test/DocTest-InternalInterface.cs b/mcs/tools/mdoc/Test/DocTest-InternalInterface.cs new file mode 100644 index 00000000000..5d65c34c82c --- /dev/null +++ b/mcs/tools/mdoc/Test/DocTest-InternalInterface.cs @@ -0,0 +1,17 @@ +namespace MyNamespace { + internal interface MyInternalInterface { + bool Foo {get;set;} + string FooSet {set;} + void FooMeth (); + void BarMeth (); + } + + public class MyClass : MyInternalInterface { + public string Bar {get;set;} + public void BarMeth () {} // part of the interface, but publicly implemented + + string MyInternalInterface.FooSet {set {}} + bool MyInternalInterface.Foo {get;set;} + void MyInternalInterface.FooMeth () {} + } +} diff --git a/mcs/tools/mdoc/Test/en.expected-internal-interface/MyNamespace/MyClass.xml b/mcs/tools/mdoc/Test/en.expected-internal-interface/MyNamespace/MyClass.xml new file mode 100644 index 00000000000..614b7b7d59d --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-internal-interface/MyNamespace/MyClass.xml @@ -0,0 +1,63 @@ + + + + + DocTest-InternalInterface + 0.0.0.0 + + + System.Object + + + + To be added. + To be added. + + + + + + Constructor + + 0.0.0.0 + + + + To be added. + To be added. + + + + + + Property + + 0.0.0.0 + + + System.String + + + To be added. + To be added. + To be added. + + + + + + Method + + 0.0.0.0 + + + System.Void + + + + To be added. + To be added. + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-internal-interface/index.xml b/mcs/tools/mdoc/Test/en.expected-internal-interface/index.xml new file mode 100644 index 00000000000..5b49f3c71d2 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-internal-interface/index.xml @@ -0,0 +1,22 @@ + + + + + + System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints) + + + System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true) + + + + + To be added. + To be added. + + + + + + DocTest-InternalInterface + diff --git a/mcs/tools/mdoc/Test/en.expected-internal-interface/ns-MyNamespace.xml b/mcs/tools/mdoc/Test/en.expected-internal-interface/ns-MyNamespace.xml new file mode 100644 index 00000000000..bd8d43168a3 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-internal-interface/ns-MyNamespace.xml @@ -0,0 +1,6 @@ + + + To be added. + To be added. + + From 8d405e7aa12aed67f1b0e09b72316dc57480e63a Mon Sep 17 00:00:00 2001 From: rjvdboon Date: Thu, 25 Sep 2014 21:33:22 +0200 Subject: [PATCH 235/543] Change unittest to not use the UserNameSecurityTokenHandler base class (as it does not-exist in mono) --- .../BootstrapContextTest.cs | 53 ++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs index 767410ecff6..cf044a8126f 100644 --- a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs +++ b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs @@ -8,6 +8,8 @@ using System.IdentityModel.Tokens; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Xml; using NUnit.Framework; namespace MonoTests.System.IdentityModel.Tokens.net_4_5 @@ -24,8 +26,8 @@ public class BootstrapContextTest private const string user = "us\u018Er"; // \u00BD == Vulgar Fraction one half private const string password = "pass\u00BDword"; - private static readonly string SerializedBootstrapContextSecurityTokenString = ""+user+""+password+""; - private static readonly byte[] SerializedBootstrapContextSecurityToken = new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x54, 0x06, 0x03, 0x00, 0x00, 0x00, 0xB8, 0x04, 0x50, 0x46, 0x56, 0x7A, 0x5A, 0x58, 0x4A, 0x75, 0x59, 0x57, 0x31, 0x6C, 0x56, 0x47, 0x39, 0x72, 0x5A, 0x57, 0x34, 0x67, 0x59, 0x54, 0x70, 0x4A, 0x5A, 0x44, 0x30, 0x69, 0x64, 0x58, 0x56, 0x70, 0x5A, 0x43, 0x30, 0x35, 0x4D, 0x6A, 0x64, 0x6A, 0x4D, 0x47, 0x49, 0x35, 0x4F, 0x43, 0x31, 0x69, 0x59, 0x54, 0x45, 0x34, 0x4C, 0x54, 0x51, 0x35, 0x5A, 0x44, 0x49, 0x74, 0x59, 0x54, 0x59, 0x31, 0x4D, 0x79, 0x30, 0x7A, 0x4D, 0x44, 0x5A, 0x6B, 0x4E, 0x6A, 0x42, 0x6D, 0x4F, 0x44, 0x55, 0x33, 0x4E, 0x54, 0x45, 0x74, 0x4D, 0x79, 0x49, 0x67, 0x65, 0x47, 0x31, 0x73, 0x62, 0x6E, 0x4D, 0x39, 0x49, 0x6D, 0x68, 0x30, 0x64, 0x48, 0x41, 0x36, 0x4C, 0x79, 0x39, 0x6B, 0x62, 0x32, 0x4E, 0x7A, 0x4C, 0x6D, 0x39, 0x68, 0x63, 0x32, 0x6C, 0x7A, 0x4C, 0x57, 0x39, 0x77, 0x5A, 0x57, 0x34, 0x75, 0x62, 0x33, 0x4A, 0x6E, 0x4C, 0x33, 0x64, 0x7A, 0x63, 0x79, 0x38, 0x79, 0x4D, 0x44, 0x41, 0x30, 0x4C, 0x7A, 0x41, 0x78, 0x4C, 0x32, 0x39, 0x68, 0x63, 0x32, 0x6C, 0x7A, 0x4C, 0x54, 0x49, 0x77, 0x4D, 0x44, 0x51, 0x77, 0x4D, 0x53, 0x31, 0x33, 0x63, 0x33, 0x4D, 0x74, 0x64, 0x33, 0x4E, 0x7A, 0x5A, 0x57, 0x4E, 0x31, 0x63, 0x6D, 0x6C, 0x30, 0x65, 0x53, 0x31, 0x7A, 0x5A, 0x57, 0x4E, 0x6C, 0x65, 0x48, 0x51, 0x74, 0x4D, 0x53, 0x34, 0x77, 0x4C, 0x6E, 0x68, 0x7A, 0x5A, 0x43, 0x49, 0x67, 0x65, 0x47, 0x31, 0x73, 0x62, 0x6E, 0x4D, 0x36, 0x59, 0x54, 0x30, 0x69, 0x61, 0x48, 0x52, 0x30, 0x63, 0x44, 0x6F, 0x76, 0x4C, 0x32, 0x52, 0x76, 0x59, 0x33, 0x4D, 0x75, 0x62, 0x32, 0x46, 0x7A, 0x61, 0x58, 0x4D, 0x74, 0x62, 0x33, 0x42, 0x6C, 0x62, 0x69, 0x35, 0x76, 0x63, 0x6D, 0x63, 0x76, 0x64, 0x33, 0x4E, 0x7A, 0x4C, 0x7A, 0x49, 0x77, 0x4D, 0x44, 0x51, 0x76, 0x4D, 0x44, 0x45, 0x76, 0x62, 0x32, 0x46, 0x7A, 0x61, 0x58, 0x4D, 0x74, 0x4D, 0x6A, 0x41, 0x77, 0x4E, 0x44, 0x41, 0x78, 0x4C, 0x58, 0x64, 0x7A, 0x63, 0x79, 0x31, 0x33, 0x63, 0x33, 0x4E, 0x6C, 0x59, 0x33, 0x56, 0x79, 0x61, 0x58, 0x52, 0x35, 0x4C, 0x58, 0x56, 0x30, 0x61, 0x57, 0x78, 0x70, 0x64, 0x48, 0x6B, 0x74, 0x4D, 0x53, 0x34, 0x77, 0x4C, 0x6E, 0x68, 0x7A, 0x5A, 0x43, 0x49, 0x2B, 0x50, 0x46, 0x56, 0x7A, 0x5A, 0x58, 0x4A, 0x75, 0x59, 0x57, 0x31, 0x6C, 0x50, 0x6E, 0x56, 0x7A, 0x78, 0x6F, 0x35, 0x79, 0x50, 0x43, 0x39, 0x56, 0x63, 0x32, 0x56, 0x79, 0x62, 0x6D, 0x46, 0x74, 0x5A, 0x54, 0x34, 0x38, 0x55, 0x47, 0x46, 0x7A, 0x63, 0x33, 0x64, 0x76, 0x63, 0x6D, 0x51, 0x67, 0x56, 0x48, 0x6C, 0x77, 0x5A, 0x54, 0x30, 0x69, 0x61, 0x48, 0x52, 0x30, 0x63, 0x44, 0x6F, 0x76, 0x4C, 0x32, 0x52, 0x76, 0x59, 0x33, 0x4D, 0x75, 0x62, 0x32, 0x46, 0x7A, 0x61, 0x58, 0x4D, 0x74, 0x62, 0x33, 0x42, 0x6C, 0x62, 0x69, 0x35, 0x76, 0x63, 0x6D, 0x63, 0x76, 0x64, 0x33, 0x4E, 0x7A, 0x4C, 0x7A, 0x49, 0x77, 0x4D, 0x44, 0x51, 0x76, 0x4D, 0x44, 0x45, 0x76, 0x62, 0x32, 0x46, 0x7A, 0x61, 0x58, 0x4D, 0x74, 0x4D, 0x6A, 0x41, 0x77, 0x4E, 0x44, 0x41, 0x78, 0x4C, 0x58, 0x64, 0x7A, 0x63, 0x79, 0x31, 0x31, 0x63, 0x32, 0x56, 0x79, 0x62, 0x6D, 0x46, 0x74, 0x5A, 0x53, 0x31, 0x30, 0x62, 0x32, 0x74, 0x6C, 0x62, 0x69, 0x31, 0x77, 0x63, 0x6D, 0x39, 0x6D, 0x61, 0x57, 0x78, 0x6C, 0x4C, 0x54, 0x45, 0x75, 0x4D, 0x43, 0x4E, 0x51, 0x59, 0x58, 0x4E, 0x7A, 0x64, 0x32, 0x39, 0x79, 0x5A, 0x46, 0x52, 0x6C, 0x65, 0x48, 0x51, 0x69, 0x50, 0x6E, 0x42, 0x68, 0x63, 0x33, 0x50, 0x43, 0x76, 0x58, 0x64, 0x76, 0x63, 0x6D, 0x51, 0x38, 0x4C, 0x31, 0x42, 0x68, 0x63, 0x33, 0x4E, 0x33, 0x62, 0x33, 0x4A, 0x6B, 0x50, 0x6A, 0x77, 0x76, 0x56, 0x58, 0x4E, 0x6C, 0x63, 0x6D, 0x35, 0x68, 0x62, 0x57, 0x56, 0x55, 0x62, 0x32, 0x74, 0x6C, 0x62, 0x6A, 0x34, 0x3D, 0x0B }; + private static readonly string SerializedBootstrapContextSecurityTokenString = ""; + private static readonly byte[] SerializedBootstrapContextSecurityToken = new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x54, 0x06, 0x03, 0x00, 0x00, 0x00, 0x98, 0x01, 0x50, 0x46, 0x56, 0x7A, 0x5A, 0x58, 0x4A, 0x4F, 0x59, 0x57, 0x31, 0x6C, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x70, 0x64, 0x48, 0x6C, 0x55, 0x62, 0x32, 0x74, 0x6C, 0x62, 0x69, 0x42, 0x4A, 0x5A, 0x44, 0x30, 0x69, 0x64, 0x58, 0x56, 0x70, 0x5A, 0x43, 0x30, 0x35, 0x4D, 0x6A, 0x64, 0x6A, 0x4D, 0x47, 0x49, 0x35, 0x4F, 0x43, 0x31, 0x69, 0x59, 0x54, 0x45, 0x34, 0x4C, 0x54, 0x51, 0x35, 0x5A, 0x44, 0x49, 0x74, 0x59, 0x54, 0x59, 0x31, 0x4D, 0x79, 0x30, 0x7A, 0x4D, 0x44, 0x5A, 0x6B, 0x4E, 0x6A, 0x42, 0x6D, 0x4F, 0x44, 0x55, 0x33, 0x4E, 0x54, 0x45, 0x74, 0x4D, 0x79, 0x49, 0x67, 0x56, 0x58, 0x4E, 0x6C, 0x63, 0x6D, 0x35, 0x68, 0x62, 0x57, 0x55, 0x39, 0x49, 0x6E, 0x56, 0x7A, 0x78, 0x6F, 0x35, 0x79, 0x49, 0x69, 0x42, 0x51, 0x59, 0x58, 0x4E, 0x7A, 0x64, 0x32, 0x39, 0x79, 0x5A, 0x44, 0x30, 0x69, 0x63, 0x47, 0x46, 0x7A, 0x63, 0x38, 0x4B, 0x39, 0x64, 0x32, 0x39, 0x79, 0x5A, 0x43, 0x49, 0x76, 0x50, 0x67, 0x3D, 0x3D, 0x0B }; [Test] public void Ctor_StringToken_Works() @@ -184,12 +186,51 @@ public void Deserialize_SecurityTokenAndHandler_Works() } } - private class SimpleSecurityTokenHandler : UserNameSecurityTokenHandler + private static void Dump(byte[] data) { - public override bool RetainPassword + var sb = new StringBuilder(); + sb.Append("new byte[] { "); + bool first = true; + foreach(byte b in data) { - get { return true; } - set { base.RetainPassword = true; } + if (!first) sb.Append(", "); + else first = false; + sb.AppendFormat("0x{0:X2}", b); + } + sb.Append(" };"); + Console.WriteLine(sb.ToString()); + } + + private class SimpleSecurityTokenHandler : SecurityTokenHandler + { + public override string[] GetTokenTypeIdentifiers() + { + throw new NotImplementedException(); + } + + public override Type TokenType + { + get { return typeof(UserNameSecurityToken); } + } + + public override bool CanWriteToken + { + get + { + return true; + } + } + + public override void WriteToken(XmlWriter writer, SecurityToken token) + { + UserNameSecurityToken unst = token as UserNameSecurityToken; + if (unst == null) + throw new ArgumentException("Token must be of type UserNameSecurityToken", "token"); + writer.WriteStartElement("UserNameSecurityToken"); + writer.WriteAttributeString("Id", unst.Id); + writer.WriteAttributeString("Username", unst.UserName); + writer.WriteAttributeString("Password", unst.Password); + writer.WriteEndElement(); } } } From 4d7a441967fef5d794ccc824438cbaa47559e78f Mon Sep 17 00:00:00 2001 From: rjvdboon Date: Thu, 25 Sep 2014 22:09:21 +0200 Subject: [PATCH 236/543] Update unit tests for binary serialization --- .../BootstrapContextTest.cs | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs index cf044a8126f..74ec95ed4e8 100644 --- a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs +++ b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs @@ -55,7 +55,13 @@ public void Serialize_StringToken_Works() using (var s = new MemoryStream()) { binaryFormatter.Serialize(s, bootstrapContext); - Assert.AreEqual(SerializedBootstrapContextString, s.ToArray(), "#1"); + s.Position = 0; + BootstrapContext bootstrapContext2 = binaryFormatter.Deserialize(s) as BootstrapContext; + Assert.IsNotNull(bootstrapContext2, "#1"); + Assert.AreEqual(bootstrapContext.Token, bootstrapContext2.Token, "#2"); + Assert.AreEqual(bootstrapContext.TokenBytes, bootstrapContext2.TokenBytes, "#3"); + Assert.AreEqual(bootstrapContext.SecurityToken, bootstrapContext2.SecurityToken, "#4"); + Assert.AreEqual(bootstrapContext.SecurityTokenHandler, bootstrapContext2.SecurityTokenHandler, "#5"); } } @@ -103,7 +109,13 @@ public void Serialize_ByteArrayToken_Works() using (var s = new MemoryStream()) { binaryFormatter.Serialize(s, bootstrapContext); - Assert.AreEqual(SerializedBootstrapContextByteArray, s.ToArray(), "#1"); + s.Position = 0; + BootstrapContext bootstrapContext2 = binaryFormatter.Deserialize(s) as BootstrapContext; + Assert.IsNotNull(bootstrapContext2, "#1"); + Assert.AreEqual(bootstrapContext.Token, bootstrapContext2.Token, "#2"); + Assert.AreEqual(bootstrapContext.TokenBytes, bootstrapContext2.TokenBytes, "#3"); + Assert.AreEqual(bootstrapContext.SecurityToken, bootstrapContext2.SecurityToken, "#4"); + Assert.AreEqual(bootstrapContext.SecurityTokenHandler, bootstrapContext2.SecurityTokenHandler, "#5"); } } @@ -167,7 +179,14 @@ public void Serialize_SecurityTokenAndHandler_Works() using (var s = new MemoryStream()) { binaryFormatter.Serialize(s, bootstrapContext); - Assert.AreEqual(SerializedBootstrapContextSecurityToken, s.ToArray(), "#1"); + s.Position = 0; + BootstrapContext bootstrapContext2 = binaryFormatter.Deserialize(s) as BootstrapContext; + Assert.IsNotNull(bootstrapContext2, "#1"); + // Deserialize does not restore the SecurityToken, but restores into the Token. + Assert.AreEqual(SerializedBootstrapContextSecurityTokenString, bootstrapContext2.Token, "#2"); + Assert.AreEqual(bootstrapContext.TokenBytes, bootstrapContext2.TokenBytes, "#3"); + Assert.IsNull(bootstrapContext2.SecurityToken, "#4"); + Assert.IsNull(bootstrapContext2.SecurityTokenHandler, "#5"); } } @@ -186,6 +205,11 @@ public void Deserialize_SecurityTokenAndHandler_Works() } } + private static void DumpAsText(byte[] data) + { + Console.WriteLine("{0}", Encoding.ASCII.GetString(data)); + } + private static void Dump(byte[] data) { var sb = new StringBuilder(); From 6ee08cf772eb95c59ea81270523b210cb5948bc1 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Thu, 25 Sep 2014 15:02:38 -0400 Subject: [PATCH 237/543] [runtime] Implement lazy resolution of array interfaces. To resolve casting we make all relevant interfaces to use the generic variance casting code. This only affected ICollection`1 and IList`1, which are not terribly popular. To fix dispatch we augment vtable resolution to treat those interfaces as variant and use the already in place machinery. Memory reduction numbers for the corlib test suite: Initialized classes 8004 -> 7470 (7% reduction) Corlib mempool size: 2719832 -> 2678872 (1.5% reduction) Inflated classes 4500: 3.972 (12% reduction) Inflated signatures size: 166128 -> 139812 (16% reduction) Inflated methods size: 565152 -> 485664 (15$ reduction) --- mono/metadata/class-internals.h | 4 + mono/metadata/class.c | 156 +++++++++++++++++++++++++++++++- mono/metadata/object.c | 2 +- mono/mini/method-to-ir.c | 14 ++- 4 files changed, 166 insertions(+), 10 deletions(-) diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 32b5ef4561e..998f1d9f85e 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -1394,4 +1394,8 @@ mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_toke MonoClass * mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error) MONO_INTERNAL; +gboolean +mono_class_is_magical_array_interface (MonoClass *iface) MONO_INTERNAL; + + #endif /* __MONO_METADATA_CLASS_INTERBALS_H__ */ diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 240792536d3..7559faa3bf8 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -2755,6 +2755,28 @@ mono_class_interface_offset (MonoClass *klass, MonoClass *itf) { } } +static gboolean mono_array_class_implements_magic_interface (MonoClass *iface, MonoClass *array_class); + +static int +mono_class_array_get_magic_iface_offset (MonoClass *iface, MonoClass *array_class) +{ + MonoClass *gtd; + int i; + + if (!mono_array_class_implements_magic_interface (iface, array_class)) + return -1; + + gtd = mono_class_get_generic_type_definition (iface); + + for (i = 0; i < array_class->interface_offsets_count; i++) { + if (mono_class_get_generic_type_definition (array_class->interfaces_packed [i]) == gtd) { + return array_class->interface_offsets_packed [i]; + } + } + + return -1; +} + /* * mono_class_interface_offset_with_variance: * @@ -2771,7 +2793,13 @@ mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gbo *non_exact_match = FALSE; if (i >= 0) return i; - + + i = mono_class_array_get_magic_iface_offset (itf, klass); + if (i >= 0) { + *non_exact_match = TRUE; + return i; + } + if (!mono_class_has_variant_generic_params (itf)) return -1; @@ -2919,10 +2947,6 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume gboolean internal_enumerator; gboolean eclass_is_valuetype; - if (!mono_defaults.generic_ilist_class) { - *num = 0; - return NULL; - } internal_enumerator = FALSE; eclass_is_valuetype = FALSE; original_rank = eclass->rank; @@ -2941,6 +2965,10 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume *num = 0; return NULL; } + } else { + /* disable interface generiation for all arrays. */ + *num = 0; + return NULL; } /* @@ -7920,6 +7948,118 @@ mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate) return FALSE; } +gboolean +mono_class_is_magical_array_interface (MonoClass *iface) +{ + static MonoClass* generic_ilist_class = NULL; + static MonoClass* generic_icollection_class = NULL; + static MonoClass* generic_ienumerable_class = NULL; + static MonoClass* generic_ireadonlylist_class = NULL; + static MonoClass* generic_ireadonlycollection_class = NULL; + + if (!generic_ilist_class) { + generic_icollection_class = mono_class_from_name (mono_defaults.corlib, + "System.Collections.Generic", "ICollection`1"); + generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib, + "System.Collections.Generic", "IEnumerable`1"); + generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib, + "System.Collections.Generic", "IReadOnlyList`1"); + generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib, + "System.Collections.Generic", "IReadOnlyCollection`1"); + + mono_memory_barrier (); + generic_ilist_class = mono_class_from_name (mono_defaults.corlib, + "System.Collections.Generic", "IList`1"); + } + + iface = mono_class_get_generic_type_definition (iface); + return iface == generic_ilist_class || + iface == generic_icollection_class || + iface == generic_ienumerable_class || + iface == generic_ireadonlylist_class || + iface == generic_ireadonlycollection_class; +} + +static MonoClass* +lower_valuetype_class_for_array_cast (MonoClass *class) +{ + switch (class->byval_arg.type) { + case MONO_TYPE_I1: + case MONO_TYPE_U1: + return mono_defaults.byte_class; + case MONO_TYPE_I2: + case MONO_TYPE_U2: + return mono_defaults.int16_class; + case MONO_TYPE_I4: + case MONO_TYPE_U4: + return mono_defaults.int32_class; + case MONO_TYPE_I8: + case MONO_TYPE_U8: + return mono_defaults.int64_class; + default: + if (class->enumtype && mono_class_enum_basetype (class)) + return mono_class_from_mono_type (mono_class_enum_basetype (class)); + } + return class; +} + +static gboolean +mono_array_class_implements_magic_interface (MonoClass *iface, MonoClass *array_class) +{ + MonoClass *iface_arg0, *array_arg0; + + if (!array_class->rank) + return FALSE; + + if (!mono_class_is_magical_array_interface (iface)) + return FALSE; + + + iface_arg0 = mono_class_from_mono_type (iface->generic_class->context.class_inst->type_argv [0]); + array_arg0 = array_class->element_class; + /* Valuetypes are not compatible with sys.enum, sys.valuetype and sys.object, but mono_class_is_assignable_from will report so. */ + if (array_arg0->valuetype) { + if (iface_arg0 == mono_defaults.enum_class || iface_arg0 == mono_defaults.enum_class->parent || iface_arg0 == mono_defaults.object_class) + return FALSE; + } + + if (mono_class_is_assignable_from (iface_arg0, array_arg0)) + return TRUE; + + if (array_arg0->valuetype && iface_arg0->valuetype && lower_valuetype_class_for_array_cast (array_arg0) == lower_valuetype_class_for_array_cast (iface_arg0)) + return TRUE; + + return FALSE; +} + +static gboolean +mono_array_class_implements_magic_interface_slow (MonoClass *iface, MonoClass *array_class) +{ + MonoClass *iface_arg0, *array_arg0; + + if (!array_class->rank) + return FALSE; + + if (!mono_class_is_magical_array_interface (iface)) + return FALSE; + + iface_arg0 = mono_class_from_mono_type (iface->generic_class->context.class_inst->type_argv [0]); + array_arg0 = array_class->element_class; + /* Valuetypes are not compatible with sys.enum, sys.valuetype and sys.object, but mono_class_is_assignable_from will report so. */ + if (array_arg0->valuetype) { + if (iface_arg0 == mono_defaults.enum_class || iface_arg0 == mono_defaults.enum_class->parent || iface_arg0 == mono_defaults.object_class) + return FALSE; + } + + if (mono_class_is_assignable_from_slow (iface_arg0, array_arg0)) + return TRUE; + + if (array_arg0->valuetype && iface_arg0->valuetype && lower_valuetype_class_for_array_cast (array_arg0) == lower_valuetype_class_for_array_cast (iface_arg0)) + return TRUE; + + return FALSE; +} + /** * mono_class_is_assignable_from: * @klass: the class to be assigned to @@ -7993,6 +8133,9 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass) return TRUE; } } + + if (mono_array_class_implements_magic_interface (klass, oklass)) + return TRUE; return FALSE; } else if (klass->delegate) { if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE)) @@ -8124,6 +8267,9 @@ mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) return FALSE; } + if (mono_array_class_implements_magic_interface_slow (target, candidate)) + return TRUE; + for (i = 0; i < candidate->interface_count; ++i) { if (candidate->interfaces [i] == target) return TRUE; diff --git a/mono/metadata/object.c b/mono/metadata/object.c index a2aa759293b..759ec7b597d 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -5356,7 +5356,7 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass) } /*If the above check fails we are in the slow path of possibly raising an exception. So it's ok to it this way.*/ - if (mono_class_has_variant_generic_params (klass) && mono_class_is_assignable_from (klass, obj->vtable->klass)) + if (mono_class_is_assignable_from (klass, obj->vtable->klass)) return obj; } else { MonoClass *oklass = vt->klass; diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 4db81265757..f494c2378c6 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -4045,9 +4045,15 @@ mini_class_has_reference_variant_generic_argument (MonoCompile *cfg, MonoClass * return FALSE; } -// FIXME: This doesn't work yet (class libs tests fail?) +// FIXME: This doesn't work yet (class libs tests fail?) (mcs/tests/gtest-304.cs fails) #define is_complex_isinst(klass) (TRUE || (klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) +static gboolean +is_invariant_interface_that_required_variant_type_check (MonoClass *klass) +{ + return mono_class_is_magical_array_interface (klass); +} + static MonoInst* emit_castclass_with_cache (MonoCompile *cfg, MonoClass *klass, MonoInst **args, MonoBasicBlock **out_bblock) { @@ -9753,7 +9759,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b context_used = mini_class_check_context_used (cfg, klass); - if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { + if (!context_used && (mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || is_invariant_interface_that_required_variant_type_check (klass))) { MonoInst *args [3]; /* obj */ @@ -9816,7 +9822,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b context_used = mini_class_check_context_used (cfg, klass); - if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { + if (!context_used && (mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || is_invariant_interface_that_required_variant_type_check (klass))) { MonoMethod *mono_isinst = mono_marshal_get_isinst_with_cache (); MonoInst *args [3]; @@ -9888,7 +9894,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (generic_class_is_reference_type (cfg, klass)) { /* CASTCLASS FIXME kill this huge slice of duplicated code*/ - if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { + if (!context_used && (mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || is_invariant_interface_that_required_variant_type_check (klass))) { MonoInst *args [3]; /* obj */ From cab1c00168a773bd75ea3bee155dca12e88c9b78 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Thu, 25 Sep 2014 16:22:29 -0400 Subject: [PATCH 238/543] [runtime] Remove a bit chunk of what's dead code now. --- mono/metadata/class.c | 56 +++++++++---------------------------------- 1 file changed, 11 insertions(+), 45 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 7559faa3bf8..738356eca41 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -3379,6 +3379,7 @@ setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite) * vtables for compatible interfaces */ array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator); + g_assert (!(num_array_interfaces > 0 && !is_enumerator)); /* compute maximum number of slots and maximum interface id */ max_iid = 0; @@ -3479,51 +3480,16 @@ setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite) set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE); if (num_array_interfaces) { - if (is_enumerator) { - int ienumerator_idx = find_array_interface (class, "IEnumerator`1"); - int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]); - g_assert (ienumerator_offset >= 0); - for (i = 0; i < num_array_interfaces; ++i) { - ic = array_interfaces [i]; - if (strcmp (ic->name, "IEnumerator`1") == 0) - set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE); - else - g_assert_not_reached (); - /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/ - } - } else { - int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset; - int ilist_iface_idx = find_array_interface (class, "IList`1"); - MonoClass* ilist_class = class->interfaces [ilist_iface_idx]; - int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1"); - MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL; - int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1"); - int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1"); - int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1; - ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]); - icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]); - ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]); - ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1; - ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1; - g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0); - for (i = 0; i < num_array_interfaces; ++i) { - int offset; - ic = array_interfaces [i]; - if (ic->generic_class->container_class == mono_defaults.generic_ilist_class) - offset = ilist_offset; - else if (strcmp (ic->name, "ICollection`1") == 0) - offset = icollection_offset; - else if (strcmp (ic->name, "IEnumerable`1") == 0) - offset = ienumerable_offset; - else if (strcmp (ic->name, "IReadOnlyList`1") == 0) - offset = ireadonlylist_offset; - else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0) - offset = ireadonlycollection_offset; - else - g_assert_not_reached (); - set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE); - /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/ - } + int ienumerator_idx = find_array_interface (class, "IEnumerator`1"); + int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]); + g_assert (ienumerator_offset >= 0); + for (i = 0; i < num_array_interfaces; ++i) { + ic = array_interfaces [i]; + if (strcmp (ic->name, "IEnumerator`1") == 0) + set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE); + else + g_assert_not_reached (); + /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/ } } From 11049f9dd7eeaf8c8d471bf47cdb5c9556d1d80d Mon Sep 17 00:00:00 2001 From: "Robert J. van der Boon" Date: Fri, 26 Sep 2014 05:39:48 +0900 Subject: [PATCH 239/543] Added serialization of SecurityToken with Handler --- .../BootstrapContext.cs | 27 +++++++++++-------- .../BootstrapContextTest.cs | 6 +++-- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs index 4312b649271..6dc620b5bad 100644 --- a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs +++ b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs @@ -44,19 +44,19 @@ public class BootstrapContext : ISerializable public SecurityTokenHandler SecurityTokenHandler { get; private set; } /// Initializes a new instance of the class by using the specified string. - public BoostrapContext (string token) { + public BootstrapContext (string token) { if (token == null) throw new ArgumentNullException("token"); Token = token; } /// Initializes a new instance of the class by using the specified array. - public BoostrapContext (byte[] token) { + public BootstrapContext (byte[] token) { if (token == null) throw new ArgumentNullException("token"); TokenBytes = token; } /// Initializes a new instance of the class by using the specified security token and token handler. - public BoostrapContext (SecurityToken token, SecurityTokenHandler handler) { + public BootstrapContext (SecurityToken token, SecurityTokenHandler handler) { if (token == null) throw new ArgumentNullException("token"); if (handler == null) throw new ArgumentNullException("handler"); SecurityToken = token; @@ -64,24 +64,24 @@ public BoostrapContext (SecurityToken token, SecurityTokenHandler handler) { } /// Initializes a new instance of the class from a stream. - protected BootstrapContext(SerializationInfo info, SerializationContext context) { + protected BootstrapContext(SerializationInfo info, StreamingContext context) { if (info == null) throw new ArgumentNullException("info"); char type = info.GetChar("K"); switch (type) { case 'S': - Token = info.GetString("V"); + Token = info.GetString("T"); break; case 'B': - TokenBytes = (byte[])info.GetValue("V"); + TokenBytes = (byte[])info.GetValue("T", typeof(byte[])); break; case 'T': - Token = Convert.FromBase64String(info.GetString("V")); + Token = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(info.GetString("T"))); break; } } /// Populates the with data needed to serialize the current object. - public void GetObjectData(SerializationInfo info, SerializationContext context) { + public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) throw new ArgumentNullException("info"); if (Token != null) { info.AddValue("K", 'S'); @@ -91,11 +91,16 @@ public void GetObjectData(SerializationInfo info, SerializationContext context) info.AddValue("T", TokenBytes); } else if (SecurityToken != null && SecurityTokenHandler != null) { info.AddValue("K", 'T'); - // Serialize SecurityToken using SecurityTokenHandler - info.AddValue("T", Token); + using(var ms = new System.IO.MemoryStream()) + using(var streamWriter = new System.IO.StreamWriter(ms, new System.Text.UTF8Encoding(false))) + using(var writer = System.Xml.XmlWriter.Create(streamWriter, new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true })) { + SecurityTokenHandler.WriteToken(writer, SecurityToken); + writer.Flush(); + info.AddValue("T", Convert.ToBase64String(ms.ToArray())); + } } } } } -#endif \ No newline at end of file +#endif diff --git a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs index 74ec95ed4e8..a9f603f3b63 100644 --- a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs +++ b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs @@ -183,7 +183,9 @@ public void Serialize_SecurityTokenAndHandler_Works() BootstrapContext bootstrapContext2 = binaryFormatter.Deserialize(s) as BootstrapContext; Assert.IsNotNull(bootstrapContext2, "#1"); // Deserialize does not restore the SecurityToken, but restores into the Token. - Assert.AreEqual(SerializedBootstrapContextSecurityTokenString, bootstrapContext2.Token, "#2"); + Assert.IsNotNull(bootstrapContext2.Token, "#3"); + // We replace ' /' by '/' to accomodate the xml writer differences between mono and .net + Assert.AreEqual(SerializedBootstrapContextSecurityTokenString.Replace(" /","/"), bootstrapContext2.Token.Replace(" /","/"), "#2"); Assert.AreEqual(bootstrapContext.TokenBytes, bootstrapContext2.TokenBytes, "#3"); Assert.IsNull(bootstrapContext2.SecurityToken, "#4"); Assert.IsNull(bootstrapContext2.SecurityTokenHandler, "#5"); @@ -259,4 +261,4 @@ public override void WriteToken(XmlWriter writer, SecurityToken token) } } } -#endif \ No newline at end of file +#endif From 6c4bc5f9d7d8ab7d4baa7a3a09b9b68c921d2630 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 25 Sep 2014 16:55:12 -0400 Subject: [PATCH 240/543] [aot] Pass additional arguments to llc on x86. --- mono/mini/aot-compiler.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 2f51e54d000..ab59c11c365 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -702,6 +702,10 @@ arch_init (MonoAotCompile *acfg) acfg->llvm_label_prefix = ""; acfg->user_symbol_prefix = ""; +#if defined(TARGET_X86) + g_string_append (acfg->llc_args, " -march=x86 -mattr=sse4.1"); +#endif + #if defined(TARGET_AMD64) g_string_append (acfg->llc_args, " -march=x86-64 -mattr=sse4.1"); #endif From c5cf618a14711a2144b8a017ad0b61693253bd9c Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Fri, 26 Sep 2014 09:23:33 +0200 Subject: [PATCH 241/543] [mcs] Fix codegen for coalescing operator involving user operator conversion to result type --- mcs/errors/cs0429-5.cs | 26 ----------------- mcs/mcs/expression.cs | 3 ++ mcs/mcs/nullable.cs | 56 +++++++++++++++++++++++++++--------- mcs/tests/test-903.cs | 21 +++++++++++++- mcs/tests/ver-il-net_4_5.xml | 8 +++--- 5 files changed, 70 insertions(+), 44 deletions(-) delete mode 100644 mcs/errors/cs0429-5.cs diff --git a/mcs/errors/cs0429-5.cs b/mcs/errors/cs0429-5.cs deleted file mode 100644 index 1cc67a22817..00000000000 --- a/mcs/errors/cs0429-5.cs +++ /dev/null @@ -1,26 +0,0 @@ -// CS0429: Unreachable expression code detected -// Line: 24 -// Compiler options: -warnaserror - -using System; - -struct S -{ -} - -class C -{ - public static implicit operator S (C c) - { - return new S (); - } -} - -class Program -{ - static void Main () - { - C c = new C (); - Console.WriteLine (c ?? new S ()); - } -} diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index c784f62d1c1..975bf69ebf6 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -11134,6 +11134,9 @@ public Expression Source { get { return source; } + set { + source = value; + } } public override bool ContainsEmitWithAwait () diff --git a/mcs/mcs/nullable.cs b/mcs/mcs/nullable.cs index e857e365410..f3ed348c14f 100644 --- a/mcs/mcs/nullable.cs +++ b/mcs/mcs/nullable.cs @@ -1220,12 +1220,6 @@ Expression ConvertExpression (ResolveContext ec) return ReducedExpression.Create (right, this, false).Resolve (ec); left = Convert.ImplicitConversion (ec, unwrap ?? left, rtype, loc); - - if (TypeSpec.IsValueType (left.Type) && !left.Type.IsNullableType) { - Warning_UnreachableExpression (ec, right.Location); - return ReducedExpression.Create (left, this, false).Resolve (ec); - } - type = rtype; return this; } @@ -1285,16 +1279,52 @@ public override void Emit (EmitContext ec) return; } - left.Emit (ec); - ec.Emit (OpCodes.Dup); + // + // Null check is done on original expression not after expression is converted to + // result type. This is in most cases same but when user conversion is involved + // we can end up in situation when use operator does the null handling which is + // not what the operator is supposed to do + // + var op_expr = left as UserCast; + if (op_expr != null) { + op_expr.Source.Emit (ec); + LocalTemporary temp; + + // TODO: More load kinds can be special cased + if (!(op_expr.Source is VariableReference)) { + temp = new LocalTemporary (op_expr.Source.Type); + temp.Store (ec); + temp.Emit (ec); + op_expr.Source = temp; + } else { + temp = null; + } - // Only to make verifier happy - if (left.Type.IsGenericParameter) - ec.Emit (OpCodes.Box, left.Type); + var right_label = ec.DefineLabel (); + ec.Emit (OpCodes.Brfalse_S, right_label); + left.Emit (ec); + ec.Emit (OpCodes.Br, end_label); + ec.MarkLabel (right_label); - ec.Emit (OpCodes.Brtrue, end_label); + if (temp != null) + temp.Release (ec); + } else { + // + // Common case where expression is not modified before null check and + // we generate better/smaller code + // + left.Emit (ec); + ec.Emit (OpCodes.Dup); + + // Only to make verifier happy + if (left.Type.IsGenericParameter) + ec.Emit (OpCodes.Box, left.Type); + + ec.Emit (OpCodes.Brtrue, end_label); + + ec.Emit (OpCodes.Pop); + } - ec.Emit (OpCodes.Pop); right.Emit (ec); ec.MarkLabel (end_label); diff --git a/mcs/tests/test-903.cs b/mcs/tests/test-903.cs index 44513478a80..7dedb674daf 100644 --- a/mcs/tests/test-903.cs +++ b/mcs/tests/test-903.cs @@ -6,17 +6,36 @@ struct S class C { + public static int ConversionCalled; + public static implicit operator S (C c) { + ++ConversionCalled; return new S (); } } class Program { - static void Main () + static C field; + + static int Main () { C c = new C (); var x = c ?? new S (); + + if (C.ConversionCalled != 1) + return 1; + + c = null; + x = c ?? new S (); + if (C.ConversionCalled != 1) + return 2; + + x = field ?? new S (); + if (C.ConversionCalled != 1) + return 3; + + return 0; } } \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index e193e7b42b3..d8cd382501d 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -50768,19 +50768,19 @@ - 18 + 30 7 - - 15 - 7 + + 155 + From 007413298d5355ab6f41989b34f0520ca1cfa6d5 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 26 Sep 2014 10:31:51 +0100 Subject: [PATCH 242/543] Test Xml serialization of a property with attribute XmlText. The tested property has a default value that is not null. Covers 18908. --- .../XmlSerializerTestClasses.cs | 17 +++++++++++++ .../XmlSerializerTests.cs | 25 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs index b4ec87869e6..872e6cbdf71 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs @@ -1178,5 +1178,22 @@ public class ObjectWithNotSpecifiedNullableArrayItems [XmlArrayItem ("Element")] public List Elements; } + + [Serializable] + public sealed class ClassWithDefaultTextNotNull + { + [XmlText] + public string Value; + + public const string DefaultValue = "NotNull"; + + public ClassWithDefaultTextNotNull (string v) { + Value = v; + } + + public ClassWithDefaultTextNotNull () { + Value = DefaultValue; + } + } } diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs index 8f03b0c2223..ef6ba78867f 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs @@ -3495,6 +3495,31 @@ public void NotSpecifiedNullableArrayItems () } } } + + private static void TestClassWithDefaultTextNotNullAux (string value, string expected) + { + var obj = new ClassWithDefaultTextNotNull (value); + var ser = new XmlSerializer (typeof (ClassWithDefaultTextNotNull)); + + using (var mstream = new MemoryStream ()) + using (var writer = new XmlTextWriter (mstream, Encoding.ASCII)) { + ser.Serialize (writer, obj); + + mstream.Seek (0, SeekOrigin.Begin); + using (var reader = new XmlTextReader (mstream)) { + var result = (ClassWithDefaultTextNotNull) ser.Deserialize (reader); + Assert.AreEqual (expected, result.Value); + } + } + } + + [Test] + public void TestClassWithDefaultTextNotNull () + { + TestClassWithDefaultTextNotNullAux ("my_text", "my_text"); + TestClassWithDefaultTextNotNullAux ("", ClassWithDefaultTextNotNull.DefaultValue); + TestClassWithDefaultTextNotNullAux (null, ClassWithDefaultTextNotNull.DefaultValue); + } } // Test generated serialization code. From 916121f3d7ad235ec6f134b58b87ae1d1a5e750e Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 26 Sep 2014 10:35:57 +0100 Subject: [PATCH 243/543] Property with attribute XmlTest is now set from ReadString only. Before the change when the property default value was not null or empty the deserialized value would be the concatenation of the default value and the serialized value. The correct behavior is to use the serialized value only. Fixes 18908. --- .../SerializationCodeGenerator.cs | 8 +++----- .../XmlSerializationReaderInterpreter.cs | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs b/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs index baedf04c7ec..27848d10ea0 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs @@ -1955,14 +1955,12 @@ void GenerateReadMembers (XmlMapping xmlMap, ClassMap map, string ob, bool isVal { XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement) map.XmlTextCollector; XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) mem.ElementInfo [0]; + string str = GetStrTempVar (); + WriteLine ("string " + str + " = Reader.ReadString();"); if (info.TypeData.Type == typeof (string)) - GenerateSetMemberValue (mem, ob, "ReadString (" + GenerateGetMemberValue (mem, ob, isValueList) + ")", isValueList); + GenerateSetMemberValue (mem, ob, str, isValueList); else { - WriteLineInd ("{"); - string str = GetStrTempVar (); - WriteLine ("string " + str + " = Reader.ReadString();"); GenerateSetMemberValue (mem, ob, GenerateGetValueFromXmlString (str, info.TypeData, info.MappedType, info.IsNullable), isValueList); - WriteLineUni ("}"); } GenerateEndHook (); } diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs index 1853ad14976..5d9e4b24f34 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs @@ -505,7 +505,7 @@ void ReadMembers (ClassMap map, object ob, bool isValueList, bool readBySoapOrde XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement) map.XmlTextCollector; XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) mem.ElementInfo [0]; if (info.TypeData.Type == typeof (string)) - SetMemberValue (mem, ob, ReadString ((string) GetMemberValue (mem, ob, isValueList)), isValueList); + SetMemberValue (mem, ob, Reader.ReadString (), isValueList); else SetMemberValue (mem, ob, GetValueFromXmlString (Reader.ReadString(), info.TypeData, info.MappedType), isValueList); } From 96b46d1ad02df1386622116a211e8bacd60f3509 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Fri, 26 Sep 2014 14:31:01 +0200 Subject: [PATCH 244/543] [mcs] Add check for parameterless user constructor used as default parameter value --- mcs/errors/cs1736-2.cs | 14 ++++++++++++++ mcs/mcs/expression.cs | 6 +++--- mcs/mcs/parameter.cs | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 mcs/errors/cs1736-2.cs diff --git a/mcs/errors/cs1736-2.cs b/mcs/errors/cs1736-2.cs new file mode 100644 index 00000000000..b155aab79e0 --- /dev/null +++ b/mcs/errors/cs1736-2.cs @@ -0,0 +1,14 @@ +// CS1736: The expression being assigned to optional parameter `s' must be a constant or default value +// Line: 11 + +struct S +{ + public int i = 8; +} + +class X +{ + public void Foo (S s = new S ()) + { + } +} \ No newline at end of file diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 975bf69ebf6..e7bf61fab0b 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -7275,11 +7275,11 @@ public Arguments Arguments { } // - // Returns true for resolved `new S()' + // Returns true for resolved `new S()' when S does not declare parameterless constructor // - public bool IsDefaultStruct { + public bool IsGeneratedStructConstructor { get { - return arguments == null && type.IsStruct && GetType () == typeof (New); + return arguments == null && method == null && type.IsStruct && GetType () == typeof (New); } } diff --git a/mcs/mcs/parameter.cs b/mcs/mcs/parameter.cs index 1a30ae384c0..adac136fdc0 100644 --- a/mcs/mcs/parameter.cs +++ b/mcs/mcs/parameter.cs @@ -1418,7 +1418,7 @@ public void Resolve (ResolveContext rc, Parameter p) expr = Child; - if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) { + if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsGeneratedStructConstructor))) { if (!(expr is ErrorExpression)) { rc.Report.Error (1736, Location, "The expression being assigned to optional parameter `{0}' must be a constant or default value", From 0e37ed19be3cdd97aedb7d4a81b4dfa7cc7fa283 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Fri, 26 Sep 2014 14:12:22 -0400 Subject: [PATCH 245/543] Revert "[runtime] Remove a bit chunk of what's dead code now." This reverts commit cab1c00168a773bd75ea3bee155dca12e88c9b78. --- mono/metadata/class.c | 56 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 738356eca41..7559faa3bf8 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -3379,7 +3379,6 @@ setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite) * vtables for compatible interfaces */ array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator); - g_assert (!(num_array_interfaces > 0 && !is_enumerator)); /* compute maximum number of slots and maximum interface id */ max_iid = 0; @@ -3480,16 +3479,51 @@ setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite) set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE); if (num_array_interfaces) { - int ienumerator_idx = find_array_interface (class, "IEnumerator`1"); - int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]); - g_assert (ienumerator_offset >= 0); - for (i = 0; i < num_array_interfaces; ++i) { - ic = array_interfaces [i]; - if (strcmp (ic->name, "IEnumerator`1") == 0) - set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE); - else - g_assert_not_reached (); - /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/ + if (is_enumerator) { + int ienumerator_idx = find_array_interface (class, "IEnumerator`1"); + int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]); + g_assert (ienumerator_offset >= 0); + for (i = 0; i < num_array_interfaces; ++i) { + ic = array_interfaces [i]; + if (strcmp (ic->name, "IEnumerator`1") == 0) + set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE); + else + g_assert_not_reached (); + /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/ + } + } else { + int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset; + int ilist_iface_idx = find_array_interface (class, "IList`1"); + MonoClass* ilist_class = class->interfaces [ilist_iface_idx]; + int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1"); + MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL; + int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1"); + int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1"); + int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1; + ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]); + icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]); + ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]); + ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1; + ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1; + g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0); + for (i = 0; i < num_array_interfaces; ++i) { + int offset; + ic = array_interfaces [i]; + if (ic->generic_class->container_class == mono_defaults.generic_ilist_class) + offset = ilist_offset; + else if (strcmp (ic->name, "ICollection`1") == 0) + offset = icollection_offset; + else if (strcmp (ic->name, "IEnumerable`1") == 0) + offset = ienumerable_offset; + else if (strcmp (ic->name, "IReadOnlyList`1") == 0) + offset = ireadonlylist_offset; + else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0) + offset = ireadonlycollection_offset; + else + g_assert_not_reached (); + set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE); + /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/ + } } } From aa11aa6184a771d815d97c13096383c7b7352822 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Fri, 26 Sep 2014 14:12:32 -0400 Subject: [PATCH 246/543] Revert "[runtime] Implement lazy resolution of array interfaces." This reverts commit 6ee08cf772eb95c59ea81270523b210cb5948bc1. This broke corlib compilation in a very weird way. Reverting it for now as I have no idea on why things break. --- mono/metadata/class-internals.h | 4 - mono/metadata/class.c | 156 +------------------------------- mono/metadata/object.c | 2 +- mono/mini/method-to-ir.c | 14 +-- 4 files changed, 10 insertions(+), 166 deletions(-) diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 998f1d9f85e..32b5ef4561e 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -1394,8 +1394,4 @@ mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_toke MonoClass * mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error) MONO_INTERNAL; -gboolean -mono_class_is_magical_array_interface (MonoClass *iface) MONO_INTERNAL; - - #endif /* __MONO_METADATA_CLASS_INTERBALS_H__ */ diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 7559faa3bf8..240792536d3 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -2755,28 +2755,6 @@ mono_class_interface_offset (MonoClass *klass, MonoClass *itf) { } } -static gboolean mono_array_class_implements_magic_interface (MonoClass *iface, MonoClass *array_class); - -static int -mono_class_array_get_magic_iface_offset (MonoClass *iface, MonoClass *array_class) -{ - MonoClass *gtd; - int i; - - if (!mono_array_class_implements_magic_interface (iface, array_class)) - return -1; - - gtd = mono_class_get_generic_type_definition (iface); - - for (i = 0; i < array_class->interface_offsets_count; i++) { - if (mono_class_get_generic_type_definition (array_class->interfaces_packed [i]) == gtd) { - return array_class->interface_offsets_packed [i]; - } - } - - return -1; -} - /* * mono_class_interface_offset_with_variance: * @@ -2793,13 +2771,7 @@ mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gbo *non_exact_match = FALSE; if (i >= 0) return i; - - i = mono_class_array_get_magic_iface_offset (itf, klass); - if (i >= 0) { - *non_exact_match = TRUE; - return i; - } - + if (!mono_class_has_variant_generic_params (itf)) return -1; @@ -2947,6 +2919,10 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume gboolean internal_enumerator; gboolean eclass_is_valuetype; + if (!mono_defaults.generic_ilist_class) { + *num = 0; + return NULL; + } internal_enumerator = FALSE; eclass_is_valuetype = FALSE; original_rank = eclass->rank; @@ -2965,10 +2941,6 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume *num = 0; return NULL; } - } else { - /* disable interface generiation for all arrays. */ - *num = 0; - return NULL; } /* @@ -7948,118 +7920,6 @@ mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate) return FALSE; } -gboolean -mono_class_is_magical_array_interface (MonoClass *iface) -{ - static MonoClass* generic_ilist_class = NULL; - static MonoClass* generic_icollection_class = NULL; - static MonoClass* generic_ienumerable_class = NULL; - static MonoClass* generic_ireadonlylist_class = NULL; - static MonoClass* generic_ireadonlycollection_class = NULL; - - if (!generic_ilist_class) { - generic_icollection_class = mono_class_from_name (mono_defaults.corlib, - "System.Collections.Generic", "ICollection`1"); - generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib, - "System.Collections.Generic", "IEnumerable`1"); - generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib, - "System.Collections.Generic", "IReadOnlyList`1"); - generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib, - "System.Collections.Generic", "IReadOnlyCollection`1"); - - mono_memory_barrier (); - generic_ilist_class = mono_class_from_name (mono_defaults.corlib, - "System.Collections.Generic", "IList`1"); - } - - iface = mono_class_get_generic_type_definition (iface); - return iface == generic_ilist_class || - iface == generic_icollection_class || - iface == generic_ienumerable_class || - iface == generic_ireadonlylist_class || - iface == generic_ireadonlycollection_class; -} - -static MonoClass* -lower_valuetype_class_for_array_cast (MonoClass *class) -{ - switch (class->byval_arg.type) { - case MONO_TYPE_I1: - case MONO_TYPE_U1: - return mono_defaults.byte_class; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - return mono_defaults.int16_class; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - return mono_defaults.int32_class; - case MONO_TYPE_I8: - case MONO_TYPE_U8: - return mono_defaults.int64_class; - default: - if (class->enumtype && mono_class_enum_basetype (class)) - return mono_class_from_mono_type (mono_class_enum_basetype (class)); - } - return class; -} - -static gboolean -mono_array_class_implements_magic_interface (MonoClass *iface, MonoClass *array_class) -{ - MonoClass *iface_arg0, *array_arg0; - - if (!array_class->rank) - return FALSE; - - if (!mono_class_is_magical_array_interface (iface)) - return FALSE; - - - iface_arg0 = mono_class_from_mono_type (iface->generic_class->context.class_inst->type_argv [0]); - array_arg0 = array_class->element_class; - /* Valuetypes are not compatible with sys.enum, sys.valuetype and sys.object, but mono_class_is_assignable_from will report so. */ - if (array_arg0->valuetype) { - if (iface_arg0 == mono_defaults.enum_class || iface_arg0 == mono_defaults.enum_class->parent || iface_arg0 == mono_defaults.object_class) - return FALSE; - } - - if (mono_class_is_assignable_from (iface_arg0, array_arg0)) - return TRUE; - - if (array_arg0->valuetype && iface_arg0->valuetype && lower_valuetype_class_for_array_cast (array_arg0) == lower_valuetype_class_for_array_cast (iface_arg0)) - return TRUE; - - return FALSE; -} - -static gboolean -mono_array_class_implements_magic_interface_slow (MonoClass *iface, MonoClass *array_class) -{ - MonoClass *iface_arg0, *array_arg0; - - if (!array_class->rank) - return FALSE; - - if (!mono_class_is_magical_array_interface (iface)) - return FALSE; - - iface_arg0 = mono_class_from_mono_type (iface->generic_class->context.class_inst->type_argv [0]); - array_arg0 = array_class->element_class; - /* Valuetypes are not compatible with sys.enum, sys.valuetype and sys.object, but mono_class_is_assignable_from will report so. */ - if (array_arg0->valuetype) { - if (iface_arg0 == mono_defaults.enum_class || iface_arg0 == mono_defaults.enum_class->parent || iface_arg0 == mono_defaults.object_class) - return FALSE; - } - - if (mono_class_is_assignable_from_slow (iface_arg0, array_arg0)) - return TRUE; - - if (array_arg0->valuetype && iface_arg0->valuetype && lower_valuetype_class_for_array_cast (array_arg0) == lower_valuetype_class_for_array_cast (iface_arg0)) - return TRUE; - - return FALSE; -} - /** * mono_class_is_assignable_from: * @klass: the class to be assigned to @@ -8133,9 +7993,6 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass) return TRUE; } } - - if (mono_array_class_implements_magic_interface (klass, oklass)) - return TRUE; return FALSE; } else if (klass->delegate) { if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE)) @@ -8267,9 +8124,6 @@ mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) return FALSE; } - if (mono_array_class_implements_magic_interface_slow (target, candidate)) - return TRUE; - for (i = 0; i < candidate->interface_count; ++i) { if (candidate->interfaces [i] == target) return TRUE; diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 759ec7b597d..a2aa759293b 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -5356,7 +5356,7 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass) } /*If the above check fails we are in the slow path of possibly raising an exception. So it's ok to it this way.*/ - if (mono_class_is_assignable_from (klass, obj->vtable->klass)) + if (mono_class_has_variant_generic_params (klass) && mono_class_is_assignable_from (klass, obj->vtable->klass)) return obj; } else { MonoClass *oklass = vt->klass; diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index f494c2378c6..4db81265757 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -4045,15 +4045,9 @@ mini_class_has_reference_variant_generic_argument (MonoCompile *cfg, MonoClass * return FALSE; } -// FIXME: This doesn't work yet (class libs tests fail?) (mcs/tests/gtest-304.cs fails) +// FIXME: This doesn't work yet (class libs tests fail?) #define is_complex_isinst(klass) (TRUE || (klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) -static gboolean -is_invariant_interface_that_required_variant_type_check (MonoClass *klass) -{ - return mono_class_is_magical_array_interface (klass); -} - static MonoInst* emit_castclass_with_cache (MonoCompile *cfg, MonoClass *klass, MonoInst **args, MonoBasicBlock **out_bblock) { @@ -9759,7 +9753,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b context_used = mini_class_check_context_used (cfg, klass); - if (!context_used && (mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || is_invariant_interface_that_required_variant_type_check (klass))) { + if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { MonoInst *args [3]; /* obj */ @@ -9822,7 +9816,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b context_used = mini_class_check_context_used (cfg, klass); - if (!context_used && (mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || is_invariant_interface_that_required_variant_type_check (klass))) { + if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { MonoMethod *mono_isinst = mono_marshal_get_isinst_with_cache (); MonoInst *args [3]; @@ -9894,7 +9888,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (generic_class_is_reference_type (cfg, klass)) { /* CASTCLASS FIXME kill this huge slice of duplicated code*/ - if (!context_used && (mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || is_invariant_interface_that_required_variant_type_check (klass))) { + if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { MonoInst *args [3]; /* obj */ From 0567e7763ed9e5cb3a93cb83b50b27b5b4b5101b Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Fri, 26 Sep 2014 20:32:42 +0200 Subject: [PATCH 247/543] [mcs] Check for true/false user operators on unwrapped nullable type. Fixes #23199 --- mcs/mcs/ecore.cs | 6 +++++- mcs/tests/gtest-625.cs | 21 +++++++++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 18 ++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 mcs/tests/gtest-625.cs diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 7c2537c8bc7..d8c1f6e2cc1 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -1042,7 +1042,11 @@ protected static Expression GetOperatorFalse (ResolveContext ec, Expression e, L static Expression GetOperatorTrueOrFalse (ResolveContext ec, Expression e, bool is_true, Location loc) { var op = is_true ? Operator.OpType.True : Operator.OpType.False; - var methods = MemberCache.GetUserOperator (e.type, op, false); + var type = e.type; + if (type.IsNullableType) + type = Nullable.NullableInfo.GetUnderlyingType (type); + + var methods = MemberCache.GetUserOperator (type, op, false); if (methods == null) return null; diff --git a/mcs/tests/gtest-625.cs b/mcs/tests/gtest-625.cs new file mode 100644 index 00000000000..d733a809dc9 --- /dev/null +++ b/mcs/tests/gtest-625.cs @@ -0,0 +1,21 @@ +struct S +{ + public static bool operator true (S? S) + { + return true; + } + + public static bool operator false (S? S) + { + return true; + } +} + +class P +{ + static void Main () + { + if (new S? ()) { + } + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index d8cd382501d..317922c0e82 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -19460,6 +19460,24 @@ + + + + 10 + + + 10 + + + + + 23 + + + 7 + + + From 1641a095bba2be2bfbcb75524d3289c5fbc7a9b3 Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Fri, 26 Sep 2014 14:23:33 -0400 Subject: [PATCH 248/543] [Mono.Security] Clear Certificates after Import or Remove [part of PR #1004] PR: https://github.com/mono/mono/pull/1004 commit: https://github.com/rahvee/mono/commit/9fa2a1928a50114eb144202b939269f3f8d823f2 Modified to match Mono guidelines. --- .../Mono.Security.X509/X509Store.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs b/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs index b22f1b5ae25..d3671c0bf9f 100644 --- a/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs +++ b/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs @@ -97,10 +97,26 @@ public string Name { // methods public void Clear () + { + /* + * Both _certificates and _crls extend CollectionBase, whose Clear() method calls OnClear() and + * OnClearComplete(), which should be overridden in derivative classes. So we should not worry about + * other threads that might be holding references to _certificates or _crls. They should be smart enough + * to handle this gracefully. And if not, it's their own fault. + */ + ClearCertificates (); + ClearCrls (); + } + + void ClearCertificates() { if (_certificates != null) _certificates.Clear (); _certificates = null; + } + + void ClearCrls () + { if (_crls != null) _crls.Clear (); _crls = null; @@ -117,6 +133,7 @@ public void Import (X509Certificate certificate) fs.Write (data, 0, data.Length); fs.Close (); } + ClearCertificates (); // We have modified the store on disk. So forget the old state. } #if !NET_2_1 // Try to save privateKey if available.. @@ -141,6 +158,7 @@ public void Import (X509Crl crl) byte[] data = crl.RawData; fs.Write (data, 0, data.Length); } + ClearCrls (); // We have modified the store on disk. So forget the old state. } } @@ -149,6 +167,7 @@ public void Remove (X509Certificate certificate) string filename = Path.Combine (_storePath, GetUniqueName (certificate)); if (File.Exists (filename)) { File.Delete (filename); + ClearCertificates (); // We have modified the store on disk. So forget the old state. } } @@ -157,6 +176,7 @@ public void Remove (X509Crl crl) string filename = Path.Combine (_storePath, GetUniqueName (crl)); if (File.Exists (filename)) { File.Delete (filename); + ClearCrls (); // We have modified the store on disk. So forget the old state. } } From 1210628a04653b686e1fb2fe508dcc92bdf76291 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Thu, 24 Jul 2014 13:15:56 -0400 Subject: [PATCH 249/543] [threadpool] Add suspend pushing to a WSQ --- mono/metadata/mono-wsq.c | 13 +++++++++++++ mono/metadata/mono-wsq.h | 1 + 2 files changed, 14 insertions(+) diff --git a/mono/metadata/mono-wsq.c b/mono/metadata/mono-wsq.c index 7a9d2258d12..859fb69c55b 100644 --- a/mono/metadata/mono-wsq.c +++ b/mono/metadata/mono-wsq.c @@ -24,6 +24,7 @@ struct _MonoWSQ { volatile gint tail; MonoArray *queue; gint32 mask; + gint32 suspended; MonoSemType lock; }; @@ -61,6 +62,7 @@ mono_wsq_create () wsq = g_new0 (MonoWSQ, 1); wsq->mask = INITIAL_LENGTH - 1; + wsq->suspended = 0; MONO_GC_REGISTER_ROOT_SINGLE (wsq->queue); root = mono_get_root_domain (); wsq->queue = mono_array_new_cached (root, mono_defaults.object_class, INITIAL_LENGTH); @@ -72,6 +74,12 @@ mono_wsq_create () return wsq; } +gboolean +mono_wsq_suspend (MonoWSQ *wsq) +{ + return InterlockedCompareExchange (&wsq->suspended, 1, 0) == 0; +} + void mono_wsq_destroy (MonoWSQ *wsq) { @@ -112,6 +120,11 @@ mono_wsq_local_push (void *obj) return FALSE; } + if (wsq->suspended) { + WSQ_DEBUG ("local_push: wsq suspended\n"); + return FALSE; + } + tail = wsq->tail; if (tail < wsq->head + wsq->mask) { mono_array_setref (wsq->queue, tail & wsq->mask, (MonoObject *) obj); diff --git a/mono/metadata/mono-wsq.h b/mono/metadata/mono-wsq.h index 7208dadb6b9..ccb064d4f18 100644 --- a/mono/metadata/mono-wsq.h +++ b/mono/metadata/mono-wsq.h @@ -20,6 +20,7 @@ gboolean mono_wsq_local_push (void *obj) MONO_INTERNAL; gboolean mono_wsq_local_pop (void **ptr) MONO_INTERNAL; void mono_wsq_try_steal (MonoWSQ *wsq, void **ptr, guint32 ms_timeout) MONO_INTERNAL; gint mono_wsq_count (MonoWSQ *wsq) MONO_INTERNAL; +gboolean mono_wsq_suspend (MonoWSQ *wsq) MONO_INTERNAL; G_END_DECLS From c93f12021147713216080e815267d6f7c857c732 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 22 Jul 2014 12:16:45 -0400 Subject: [PATCH 250/543] [threadpool] Add heuristic to approach the optimal number of threads --- mono/metadata/threadpool.c | 153 ++++++++++++++++++++++++++++++------- 1 file changed, 125 insertions(+), 28 deletions(-) diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c index 39ade54daa1..651391115a3 100644 --- a/mono/metadata/threadpool.c +++ b/mono/metadata/threadpool.c @@ -41,6 +41,7 @@ #include #endif #include +#include #ifdef HAVE_SYS_SOCKET_H #include #endif @@ -132,6 +133,10 @@ typedef struct { volatile gint64 last_check; volatile gint64 time_sum; volatile gint n_sum; +#if DEBUG + volatile gint32 njobs; +#endif + volatile gint32 nexecuted; gint64 averages [2]; gboolean is_io; } ThreadPool; @@ -148,6 +153,7 @@ static void threadpool_init (ThreadPool *tp, int min_threads, int max_threads, v static void threadpool_start_idle_threads (ThreadPool *tp); static void threadpool_kill_idle_threads (ThreadPool *tp); static gboolean threadpool_start_thread (ThreadPool *tp); +static void threadpool_kill_thread (ThreadPool *tp); static void monitor_thread (gpointer data); static void socket_io_cleanup (SocketIOData *data); static MonoObject *get_io_event (MonoMList **list, gint event); @@ -656,6 +662,13 @@ mono_async_invoke (ThreadPool *tp, MonoAsyncResult *ares) mono_thread_set_execution_context (ares->original_context); ares->original_context = NULL; } + +#if DEBUG + InterlockedDecrement (&tp->njobs); +#endif + if (!tp->is_io) + InterlockedIncrement (&tp->nexecuted); + return exc; } @@ -757,21 +770,101 @@ signal_handler (int signo) } #endif +#define SAMPLES_PERIOD 500 +#define HISTORY_SIZE 10 + +typedef struct { + gint32 nexecuted; + gint32 nthreads; + gint8 nthreads_diff; +} SamplesHistory; + +static gint8 +monitor_heuristic (gint16 *current, gint16 *history_size, SamplesHistory *history, ThreadPool *tp) +{ + int i; + gint8 decision; + gint16 cur, max = 0; + + /* + * The following heuristic tries to approach the optimal number of threads to maximize jobs throughput. To + * achieve this, it simply stores the number of jobs executed (nexecuted), the number of Threads (nthreads) + * and the decision (nthreads_diff) for the past HISTORY_SIZE periods of time, each period being of + * duration SAMPLES_PERIOD ms. This history gives us an insight into what happened, and to see if we should + * increase or reduce the number of threads by comparing the last period (current) to the best one. + * + * The algorithm can be describe as following : + * - if we have a better throughput than the best period : we should either increase the number of threads + * in case we already have more threads, either reduce the number of threads if we have less threads; this + * is equivalent to move away from the number of threads of the best period, because we are currently better + * - if we have a worse throughput than the best period : we should either decrease the number of threads if + * we have more threads, either increase the number of threads if we have less threads; this is equivalent + * to get closer to the number of threads of the best period, because we are currently worse + */ + + *history_size = MIN (*history_size + 1, HISTORY_SIZE); + cur = *current = (*current + 1) % *history_size; + + history [cur].nthreads = tp->nthreads; + history [cur].nexecuted = InterlockedExchange (&tp->nexecuted, 0); + + if (tp->waiting) { + /* if we have waiting thread in the pool, then do not create a new one */ + history [cur].nthreads_diff = tp->waiting > 1 ? -1 : 0; + decision = 0; + } else if (tp->nthreads < tp->min_threads) { + history [cur].nthreads_diff = 1; + decision = 1; + } else if (*history_size <= 1) { + /* first iteration, let's add a thread by default */ + history [cur].nthreads_diff = 1; + decision = 2; + } else { + max = cur == 0 ? 1 : 0; + for (i = 0; i < *history_size; i++) { + if (i == cur) + continue; + if (history [i].nexecuted > history [max].nexecuted) + max = i; + } + + if (history [cur].nexecuted >= history [max].nexecuted) { + /* we improved the situation, let's continue ! */ + history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? 1 : -1; + decision = 3; + } else { + /* we made it worse, let's return to previous situation */ + history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? -1 : 1; + decision = 4; + } + } + +#if DEBUG + printf ("monitor_thread: decision: %1d, history [current]: {nexecuted: %5d, nthreads: %3d, waiting: %2d, nthreads_diff: %2d}, history [max]: {nexecuted: %5d, nthreads: %3d}\n", + decision, history [cur].nexecuted, history [cur].nthreads, tp->waiting, history [cur].nthreads_diff, history [max].nexecuted, history [max].nthreads); +#endif + + return history [cur].nthreads_diff; +} + static void monitor_thread (gpointer unused) { ThreadPool *pools [2]; MonoInternalThread *thread; - guint32 ms; - gboolean need_one; int i; + guint32 ms; + + gint16 history_size = 0, current = -1; + SamplesHistory *history = malloc (sizeof (SamplesHistory) * HISTORY_SIZE); + pools [0] = &async_tp; pools [1] = &async_io_tp; thread = mono_thread_internal_current (); ves_icall_System_Threading_Thread_SetName_internal (thread, mono_string_new (mono_domain_get (), "Threadpool monitor")); while (1) { - ms = 500; + ms = SAMPLES_PERIOD; i = 10; //number of spurious awakes we tolerate before doing a round of rebalancing. do { guint32 ts; @@ -794,23 +887,18 @@ monitor_thread (gpointer unused) for (i = 0; i < 2; i++) { ThreadPool *tp; tp = pools [i]; - if (tp->waiting > 0) - continue; - need_one = (mono_cq_count (tp->queue) > 0); - if (!need_one && !tp->is_io) { - mono_mutex_lock (&wsqs_lock); - for (i = 0; wsqs != NULL && i < wsqs->len; i++) { - MonoWSQ *wsq; - wsq = g_ptr_array_index (wsqs, i); - if (mono_wsq_count (wsq) != 0) { - need_one = TRUE; - break; - } - } - mono_mutex_unlock (&wsqs_lock); + + if (tp->is_io) { + if (!tp->waiting && mono_cq_count (tp->queue) > 0) + threadpool_start_thread (tp); + } else { + gint8 nthreads_diff = monitor_heuristic (¤t, &history_size, history, tp); + + if (nthreads_diff > 0) + threadpool_start_thread (tp); + else if (nthreads_diff < 0) + threadpool_kill_thread (tp); } - if (need_one) - threadpool_start_thread (tp); } } } @@ -1043,6 +1131,13 @@ pulse_on_new_job (ThreadPool *tp) MONO_SEM_POST (&tp->new_job); } +static void +threadpool_kill_thread (ThreadPool *tp) +{ + if (tp->destroy_thread == 0 && InterlockedCompareExchange (&tp->destroy_thread, 1, 0) == 0) + pulse_on_new_job (tp); +} + void icall_append_job (MonoObject *ar) { @@ -1058,7 +1153,6 @@ threadpool_append_job (ThreadPool *tp, MonoObject *ar) static void threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs) { - static int job_counter; MonoObject *ar; gint i; @@ -1082,10 +1176,6 @@ threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs) ar = jobs [i]; if (ar == NULL || mono_domain_is_unloading (ar->vtable->domain)) continue; /* Might happen when cleaning domain jobs */ - if (!tp->is_io && (InterlockedIncrement (&job_counter) % 10) == 0) { - MonoAsyncResult *o = (MonoAsyncResult *) ar; - o->add_time = mono_100ns_ticks (); - } threadpool_jobs_inc (ar); #ifndef DISABLE_PERFCOUNTERS mono_perfcounter_update_value (tp->pc_nitems, TRUE, 1); @@ -1096,6 +1186,10 @@ threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs) mono_cq_enqueue (tp->queue, ar); } +#if DEBUG + InterlockedAdd (&tp->njobs, njobs); +#endif + for (i = 0; tp->waiting > 0 && i < MIN(njobs, tp->max_threads); i++) pulse_on_new_job (tp); } @@ -1382,8 +1476,7 @@ process_idle_times (ThreadPool *tp, gint64 t) tp->ignore_times = 0; if (new_threads == -1) { - if (tp->destroy_thread == 0 && InterlockedCompareExchange (&tp->destroy_thread, 1, 0) == 0) - pulse_on_new_job (tp); + threadpool_kill_thread (tp); } } @@ -1541,8 +1634,12 @@ async_invoke_thread (gpointer data) ar = NULL; data = NULL; must_die = should_i_die (tp); - if (!must_die && (tp->is_io || !mono_wsq_local_pop (&data))) - dequeue_or_steal (tp, &data, wsq); + if (must_die) { + mono_wsq_suspend (wsq); + } else { + if (tp->is_io || !mono_wsq_local_pop (&data)) + dequeue_or_steal (tp, &data, wsq); + } n_naps = 0; while (!must_die && !data && n_naps < 4) { From 681a0061ad62ebcd8227a78ae9b628e690ca1fd5 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Mon, 28 Jul 2014 13:46:16 -0400 Subject: [PATCH 251/543] [threadpool] Remove process_idle_times so monitor_thread is the only function to change the number of threads --- mono/metadata/threadpool.c | 92 -------------------------------------- 1 file changed, 92 deletions(-) diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c index 651391115a3..f552e17f65c 100644 --- a/mono/metadata/threadpool.c +++ b/mono/metadata/threadpool.c @@ -63,13 +63,6 @@ #define THREAD_WANTS_A_BREAK(t) ((t->state & (ThreadState_StopRequested | \ ThreadState_SuspendRequested)) != 0) -#define SPIN_TRYLOCK(i) (InterlockedCompareExchange (&(i), 1, 0) == 0) -#define SPIN_LOCK(i) do { \ - if (SPIN_TRYLOCK (i)) \ - break; \ - } while (1) - -#define SPIN_UNLOCK(i) i = 0 #define SMALL_STACK (128 * (sizeof (gpointer) / 4) * 1024) /* DEBUG: prints tp data every 2s */ @@ -128,16 +121,10 @@ typedef struct { void *pc_nthreads; /* Performance counter for total number of active threads */ /**/ volatile gint destroy_thread; - volatile gint ignore_times; /* Used when there's a thread being created or destroyed */ - volatile gint sp_lock; /* spin lock used to protect ignore_times */ - volatile gint64 last_check; - volatile gint64 time_sum; - volatile gint n_sum; #if DEBUG volatile gint32 njobs; #endif volatile gint32 nexecuted; - gint64 averages [2]; gboolean is_io; } ThreadPool; @@ -1403,83 +1390,6 @@ dequeue_or_steal (ThreadPool *tp, gpointer *data, MonoWSQ *local_wsq) return (*data != NULL); } -static void -process_idle_times (ThreadPool *tp, gint64 t) -{ - gint64 ticks; - gint64 avg; - gboolean compute_avg; - gint new_threads; - gint64 per1; - - if (tp->ignore_times || t <= 0) - return; - - compute_avg = FALSE; - ticks = mono_100ns_ticks (); - t = ticks - t; - SPIN_LOCK (tp->sp_lock); - if (tp->ignore_times) { - SPIN_UNLOCK (tp->sp_lock); - return; - } - tp->time_sum += t; - tp->n_sum++; - if (tp->last_check == 0) - tp->last_check = ticks; - else if (tp->last_check > 0 && (ticks - tp->last_check) > 5000000) { - tp->ignore_times = 1; - compute_avg = TRUE; - } - SPIN_UNLOCK (tp->sp_lock); - - if (!compute_avg) - return; - - //printf ("Items: %d Time elapsed: %.3fs\n", tp->n_sum, (ticks - tp->last_check) / 10000.0); - tp->last_check = ticks; - new_threads = 0; - avg = tp->time_sum / tp->n_sum; - if (tp->averages [1] == 0) { - tp->averages [1] = avg; - } else { - per1 = ((100 * (ABS (avg - tp->averages [1]))) / tp->averages [1]); - if (per1 > 5) { - if (avg > tp->averages [1]) { - if (tp->averages [1] < tp->averages [0]) { - new_threads = -1; - } else { - new_threads = 1; - } - } else if (avg < tp->averages [1] && tp->averages [1] < tp->averages [0]) { - new_threads = 1; - } - } else { - int min, n; - min = tp->min_threads; - n = tp->nthreads; - if ((n - min) < min && tp->busy_threads == n) - new_threads = 1; - } - /* - if (new_threads != 0) { - printf ("n: %d per1: %lld avg=%lld avg1=%lld avg0=%lld\n", new_threads, per1, avg, tp->averages [1], tp->averages [0]); - } - */ - } - - tp->time_sum = 0; - tp->n_sum = 0; - - tp->averages [0] = tp->averages [1]; - tp->averages [1] = avg; - tp->ignore_times = 0; - - if (new_threads == -1) { - threadpool_kill_thread (tp); - } -} - static gboolean should_i_die (ThreadPool *tp) { @@ -1606,8 +1516,6 @@ async_invoke_thread (gpointer data) if (tp_item_begin_func) tp_item_begin_func (tp_item_user_data); - if (!is_io_task && ar->add_time > 0) - process_idle_times (tp, ar->add_time); exc = mono_async_invoke (tp, ar); if (tp_item_end_func) tp_item_end_func (tp_item_user_data); From 62edb78cd6656f7523917d6bd4a94172842184f3 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 22 Aug 2014 20:39:17 -0400 Subject: [PATCH 252/543] [threadpool] Put the monitor thread to sleep if there has been no tasks for the past 5 seconds (NON_BUSY_INTERATION * SAMPLES_PERIOD) This should improve a lot power consumption, because this avoir having a thread waking up every 500ms keeping the CPU awake. --- mono/metadata/threadpool.c | 50 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c index f552e17f65c..37c47896683 100644 --- a/mono/metadata/threadpool.c +++ b/mono/metadata/threadpool.c @@ -77,6 +77,12 @@ enum { KQUEUE_BACKEND }; +enum { + MONITOR_STATE_AWAKE, + MONITOR_STATE_FALLING_ASLEEP, + MONITOR_STATE_SLEEPING +}; + typedef struct { mono_mutex_t io_lock; /* access to sock_to_state */ int inited; // 0 -> not initialized , 1->initializing, 2->initialized, 3->cleaned up @@ -156,6 +162,10 @@ static GPtrArray *wsqs; mono_mutex_t wsqs_lock; static gboolean suspended; +static volatile gint32 monitor_njobs = 0; +static volatile gint32 monitor_state; +static MonoSemType monitor_sem; + /* Hooks */ static MonoThreadPoolFunc tp_start_func; static MonoThreadPoolFunc tp_finish_func; @@ -656,6 +666,9 @@ mono_async_invoke (ThreadPool *tp, MonoAsyncResult *ares) if (!tp->is_io) InterlockedIncrement (&tp->nexecuted); + if (InterlockedDecrement (&monitor_njobs) == 0) + monitor_state = MONITOR_STATE_FALLING_ASLEEP; + return exc; } @@ -759,6 +772,9 @@ signal_handler (int signo) #define SAMPLES_PERIOD 500 #define HISTORY_SIZE 10 +/* number of iteration without any jobs + in the queue before going to sleep */ +#define NUM_WAITING_ITERATIONS 10 typedef struct { gint32 nexecuted; @@ -842,6 +858,7 @@ monitor_thread (gpointer unused) int i; guint32 ms; + gint8 num_waiting_iterations = 0; gint16 history_size = 0, current = -1; SamplesHistory *history = malloc (sizeof (SamplesHistory) * HISTORY_SIZE); @@ -871,6 +888,25 @@ monitor_thread (gpointer unused) if (suspended) continue; + switch (monitor_state) { + case MONITOR_STATE_AWAKE: + num_waiting_iterations = 0; + break; + case MONITOR_STATE_FALLING_ASLEEP: + if (++num_waiting_iterations == NUM_WAITING_ITERATIONS) { + if (monitor_state == MONITOR_STATE_FALLING_ASLEEP && InterlockedCompareExchange (&monitor_state, MONITOR_STATE_SLEEPING, MONITOR_STATE_FALLING_ASLEEP) == MONITOR_STATE_FALLING_ASLEEP) { + MONO_SEM_WAIT (&monitor_sem); + + num_waiting_iterations = 0; + current = -1; + history_size = 0; + } + } + break; + case MONITOR_STATE_SLEEPING: + g_assert_not_reached (); + } + for (i = 0; i < 2; i++) { ThreadPool *tp; tp = pools [i]; @@ -953,6 +989,10 @@ mono_thread_pool_init (void) signal (SIGALRM, signal_handler); alarm (2); #endif + + MONO_SEM_INIT (&monitor_sem, 0); + monitor_state = MONITOR_STATE_AWAKE; + monitor_njobs = 0; } static MonoAsyncResult * @@ -1089,6 +1129,8 @@ mono_thread_pool_cleanup (void) mono_mutex_unlock (&wsqs_lock); MONO_SEM_DESTROY (&async_tp.new_job); } + + MONO_SEM_DESTROY (&monitor_sem); } static gboolean @@ -1159,6 +1201,14 @@ threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs) } } + InterlockedAdd (&monitor_njobs, njobs); + + if (monitor_state == MONITOR_STATE_SLEEPING && InterlockedCompareExchange (&monitor_state, MONITOR_STATE_AWAKE, MONITOR_STATE_SLEEPING) == MONITOR_STATE_SLEEPING) + MONO_SEM_POST (&monitor_sem); + + if (monitor_state == MONITOR_STATE_FALLING_ASLEEP) + InterlockedCompareExchange (&monitor_state, MONITOR_STATE_AWAKE, MONITOR_STATE_FALLING_ASLEEP); + for (i = 0; i < njobs; i++) { ar = jobs [i]; if (ar == NULL || mono_domain_is_unloading (ar->vtable->domain)) From c648f28f54f742c0ebee07b4739a463991b6be6d Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Fri, 26 Sep 2014 15:40:23 -0400 Subject: [PATCH 253/543] [corlib] Move iOS-specific code to a separate file for System.Environment --- mcs/class/corlib/System/Environment.cs | 43 +++++++------------------- 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/mcs/class/corlib/System/Environment.cs b/mcs/class/corlib/System/Environment.cs index f864785b9ef..21128defd9b 100644 --- a/mcs/class/corlib/System/Environment.cs +++ b/mcs/class/corlib/System/Environment.cs @@ -44,7 +44,7 @@ namespace System { [ComVisible (true)] - public static class Environment { + public static partial class Environment { /* * This is the version number of the corlib-runtime interface. When @@ -475,9 +475,6 @@ public static IDictionary GetEnvironmentVariables () } #endif - [MethodImplAttribute (MethodImplOptions.InternalCall)] - private extern static string GetWindowsFolderPath (int folder); - /// /// Returns the fully qualified path of the /// folder specified by the "folder" parameter @@ -486,6 +483,12 @@ public static string GetFolderPath (SpecialFolder folder) { return GetFolderPath (folder, SpecialFolderOption.None); } + +// for monotouch, not monotouch_runtime +#if !(MONOTOUCH && FULL_AOT_RUNTIME) + [MethodImplAttribute (MethodImplOptions.InternalCall)] + private extern static string GetWindowsFolderPath (int folder); + #if NET_4_0 public #endif @@ -577,38 +580,15 @@ internal static string UnixGetFolderPath (SpecialFolder folder, SpecialFolderOpt // personal == ~ case SpecialFolder.Personal: -#if MONOTOUCH - return Path.Combine (home, "Documents"); -#else return home; -#endif + // use FDO's CONFIG_HOME. This data will be synced across a network like the windows counterpart. case SpecialFolder.ApplicationData: -#if MONOTOUCH - { - string dir = Path.Combine (Path.Combine (home, "Documents"), ".config"); - if (option == SpecialFolderOption.Create){ - if (!Directory.Exists (dir)) - Directory.CreateDirectory (dir); - } - return dir; - } -#else return config; -#endif + //use FDO's DATA_HOME. This is *NOT* synced case SpecialFolder.LocalApplicationData: -#if MONOTOUCH - { - string dir = Path.Combine (home, "Documents"); - if (!Directory.Exists (dir)) - Directory.CreateDirectory (dir); - - return dir; - } -#else return data; -#endif case SpecialFolder.Desktop: case SpecialFolder.DesktopDirectory: @@ -705,8 +685,9 @@ internal static string UnixGetFolderPath (SpecialFolder folder, SpecialFolderOpt return "/usr/share"; default: throw new ArgumentException ("Invalid SpecialFolder"); - } - } + } + } +#endif [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)] From cca43a2d344fa827bfd9200c196626cd336d503e Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 26 Sep 2014 18:16:09 -0400 Subject: [PATCH 254/543] [sdb] Add an option to make debugger invokes virtual. Part of the fix for #23385. --- .../Mono.Debugger.Soft/Connection.cs | 13 +++++++------ .../Mono.Debugger.Soft/InvokeOptions.cs | 7 ++++++- .../Mono.Debugger.Soft/ObjectMirror.cs | 2 ++ mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs | 8 ++++++++ mcs/class/Mono.Debugger.Soft/Test/dtest.cs | 5 +++++ mono/mini/debugger-agent.c | 11 +++++++++-- 6 files changed, 37 insertions(+), 9 deletions(-) diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs index 14bf701f46f..a54315f175e 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs @@ -155,11 +155,12 @@ enum ValueTypeId { [Flags] enum InvokeFlags { - NONE = 0x0, - DISABLE_BREAKPOINTS = 0x1, - SINGLE_THREADED = 0x2, - OUT_THIS = 0x4, - OUT_ARGS = 0x8, + NONE = 0, + DISABLE_BREAKPOINTS = 1, + SINGLE_THREADED = 2, + OUT_THIS = 4, + OUT_ARGS = 8, + VIRTUAL = 16, } enum ElementType { @@ -416,7 +417,7 @@ public abstract class Connection * with newer runtimes, and vice versa. */ internal const int MAJOR_VERSION = 2; - internal const int MINOR_VERSION = 35; + internal const int MINOR_VERSION = 37; enum WPSuspendPolicy { NONE = 0, diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/InvokeOptions.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/InvokeOptions.cs index 5ca987ec694..99dc87fa805 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/InvokeOptions.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/InvokeOptions.cs @@ -22,6 +22,11 @@ public enum InvokeOptions { /* * Return the values of out arguments */ - ReturnOutArgs = 8 + ReturnOutArgs = 8, + /* + * Do a virtual invoke + * Since protocol version 2.37 + */ + Virtual = 16 } } diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs index d83e3a1a481..e65f62fc945 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs @@ -307,6 +307,8 @@ internal static IInvokeAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadM f |= InvokeFlags.OUT_THIS; if ((options & InvokeOptions.ReturnOutArgs) != 0) f |= InvokeFlags.OUT_ARGS; + if ((options & InvokeOptions.Virtual) != 0) + f |= InvokeFlags.VIRTUAL; InvokeAsyncResult r = new InvokeAsyncResult { AsyncState = state, AsyncWaitHandle = new ManualResetEvent (false), VM = vm, Thread = thread, Callback = callback }; thread.InvalidateFrames (); diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs index 3c9b2877c21..f75951b8bc6 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs @@ -22,6 +22,10 @@ public class TestsBase static string base_static_s = "C"; #pragma warning restore 0414 #pragma warning restore 0169 + + public virtual string virtual_method () { + return "V1"; + } } public enum AnEnum { @@ -1365,6 +1369,10 @@ public static void set_ip () { j = 5; set_ip_2 (); } + + public override string virtual_method () { + return "V2"; + } } class TypeLoadClass { diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs index 9a671202a82..df4fbcc6648 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs @@ -2137,6 +2137,11 @@ public void Invoke () { v = this_obj.InvokeMethod (e.Thread, m, null); AssertValue (42, v); + // virtual call + m = t.BaseType.GetMethod ("virtual_method"); + v = this_obj.InvokeMethod (e.Thread, m, null, InvokeOptions.Virtual); + AssertValue ("V2", v); + #if NET_4_5 // instance m = t.GetMethod ("invoke_pass_ref"); diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 58d66c88f48..63e39501fe1 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -289,7 +289,7 @@ typedef struct { #define HEADER_LENGTH 11 #define MAJOR_VERSION 2 -#define MINOR_VERSION 36 +#define MINOR_VERSION 37 typedef enum { CMD_SET_VM = 1, @@ -403,7 +403,8 @@ typedef enum { INVOKE_FLAG_DISABLE_BREAKPOINTS = 1, INVOKE_FLAG_SINGLE_THREADED = 2, INVOKE_FLAG_RETURN_OUT_THIS = 4, - INVOKE_FLAG_RETURN_OUT_ARGS = 8 + INVOKE_FLAG_RETURN_OUT_ARGS = 8, + INVOKE_FLAG_VIRTUAL = 16 } InvokeFlags; typedef enum { @@ -6565,6 +6566,12 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 return ERR_INVALID_ARGUMENT; } m = mono_object_get_virtual_method (this, m); + } else if (invoke->flags & INVOKE_FLAG_VIRTUAL) { + if (!this) { + DEBUG (1, fprintf (log_file, "[%p] Error: invoke with INVOKE_FLAG_VIRTUAL flag set without this argument.\n", (gpointer)GetCurrentThreadId ())); + return ERR_INVALID_ARGUMENT; + } + m = mono_object_get_virtual_method (this, m); } DEBUG (1, fprintf (log_file, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (m, TRUE), this ? this->vtable->klass->name : "")); From a32e2c7fe6ffabcb6b06e4ab28e3ea1a58f9c6a3 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 26 Sep 2014 19:48:13 -0400 Subject: [PATCH 255/543] [jit] Enable deadce on fp instructions on x86. Fixes #23392. --- mono/mini/local-propagation.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mono/mini/local-propagation.c b/mono/mini/local-propagation.c index 7bdb517bd2b..e564f7a4736 100644 --- a/mono/mini/local-propagation.c +++ b/mono/mini/local-propagation.c @@ -547,8 +547,7 @@ mono_local_deadce (MonoCompile *cfg) } } - /* Enabling this on x86 could screw up the fp stack */ - if (reg_is_softreg_no_fpstack (ins->dreg, spec [MONO_INST_DEST])) { + if (reg_is_softreg (ins->dreg, spec [MONO_INST_DEST])) { /* * Assignments to global vregs can only be eliminated if there is another * assignment to the same vreg later in the same bblock. From 13e0175fc8645bd1cb8d1413a3f84a29d6d57a18 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sat, 27 Sep 2014 20:10:18 +1000 Subject: [PATCH 256/543] Add basic implement of ManagementObjectSearcher This change is released under the MIT license. --- .../System.Management/ManagementObjectSearcher.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mcs/class/System.Management/System.Management/ManagementObjectSearcher.cs b/mcs/class/System.Management/System.Management/ManagementObjectSearcher.cs index 90ed57e3dce..f79d9662bcd 100644 --- a/mcs/class/System.Management/System.Management/ManagementObjectSearcher.cs +++ b/mcs/class/System.Management/System.Management/ManagementObjectSearcher.cs @@ -26,28 +26,28 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // - using System.ComponentModel; namespace System.Management { - [MonoTODO ("System.Management is not implemented")] [ToolboxItem (false)] public class ManagementObjectSearcher : Component { + ObjectQuery mQueryObject; + public ManagementObjectSearcher () { - throw new NotImplementedException (); + mQueryObject = new ObjectQuery (); } public ManagementObjectSearcher (ObjectQuery query) { - throw new NotImplementedException (); + mQueryObject = (ObjectQuery)query.Clone (); } public ManagementObjectSearcher (string queryString) { - throw new NotImplementedException (); + mQueryObject = new ObjectQuery (queryString); } public ManagementObjectSearcher (ManagementScope scope, ObjectQuery query) @@ -81,10 +81,10 @@ public EnumerationOptions Options { public ObjectQuery Query { get { - throw new NotImplementedException (); + return mQueryObject; } set { - throw new NotImplementedException (); + mQueryObject = value; } } From bb12899b3a211b459214278db9e140ddccc14c8f Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Sat, 27 Sep 2014 16:40:57 +0200 Subject: [PATCH 257/543] [corlib] Timespan ticks formatting rewrite. Fixes #23376 --- mcs/class/corlib/System/TimeSpan.cs | 97 +++++++++++++------- mcs/class/corlib/Test/System/TimeSpanTest.cs | 12 +++ 2 files changed, 78 insertions(+), 31 deletions(-) diff --git a/mcs/class/corlib/System/TimeSpan.cs b/mcs/class/corlib/System/TimeSpan.cs index 7762dfc9177..f6937ef3ca2 100644 --- a/mcs/class/corlib/System/TimeSpan.cs +++ b/mcs/class/corlib/System/TimeSpan.cs @@ -614,41 +614,76 @@ string ToStringCustom (string format) element = parser.GetNextElement (); switch (element.Type) { - case FormatElementType.Days: - value = Math.Abs (Days); - break; - case FormatElementType.Hours: - value = Math.Abs (Hours); - break; - case FormatElementType.Minutes: - value = Math.Abs (Minutes); - break; - case FormatElementType.Seconds: - value = Math.Abs (Seconds); - break; - case FormatElementType.Ticks: - case FormatElementType.TicksUppercase: - value = Math.Abs (Milliseconds); - if (value == 0) { - if (element.Type == FormatElementType.Ticks) - break; - - continue; - } + case FormatElementType.Days: + value = Math.Abs (Days); + break; + case FormatElementType.Hours: + value = Math.Abs (Hours); + break; + case FormatElementType.Minutes: + value = Math.Abs (Minutes); + break; + case FormatElementType.Seconds: + value = Math.Abs (Seconds); + break; + case FormatElementType.Ticks: + case FormatElementType.TicksUppercase: + // + // TODO: Unify with datetime ticks formatting + // + value = (int)(_ticks % TicksPerSecond); + if (value == 0) { + if (element.Type == FormatElementType.Ticks) + break; - int threshold = (int)Math.Pow (10, element.IntValue); - while (value >= threshold) - value /= 10; - sb.Append (value.ToString ()); continue; - case FormatElementType.EscapedChar: - sb.Append (element.CharValue); + } + + int total_length = element.IntValue; + const int max_length = 7; + int digits = max_length; + for (var dv = (int)Math.Pow (10, max_length - 1); dv > value; dv /= 10, --digits) + ; + + // + // Skip only leading zeros in F format + // + if (element.Type == FormatElementType.TicksUppercase && max_length - digits >= total_length) continue; - case FormatElementType.Literal: - sb.Append (element.StringValue); + + // + // Add leading zeros + // + int leading = 0; + for (; leading < total_length && leading < max_length - digits; ++leading) { + sb.Append ("0"); + } + + if (total_length == leading) continue; - default: - throw new FormatException ("The format is not recognized."); + + // + // Remove trailing zeros + // + if (element.Type == FormatElementType.TicksUppercase) { + while (value % 10 == 0) + value /= 10; + } + + var max_value = (int)Math.Pow (10, total_length - leading); + while (value >= max_value) + value /= 10; + + sb.Append (value.ToString (CultureInfo.InvariantCulture)); + continue; + case FormatElementType.EscapedChar: + sb.Append (element.CharValue); + continue; + case FormatElementType.Literal: + sb.Append (element.StringValue); + continue; + default: + throw new FormatException ("The format is not recognized."); } sb.Append (value.ToString ("D" + element.IntValue.ToString ())); diff --git a/mcs/class/corlib/Test/System/TimeSpanTest.cs b/mcs/class/corlib/Test/System/TimeSpanTest.cs index 101cad48a92..2d9e0984996 100644 --- a/mcs/class/corlib/Test/System/TimeSpanTest.cs +++ b/mcs/class/corlib/Test/System/TimeSpanTest.cs @@ -1430,6 +1430,18 @@ public void ToStringCustomFormats () ts = new TimeSpan (123456789); Assert.AreEqual ("12.3", ts.ToString ("s\\.f"), "#F0"); Assert.AreEqual ("12.3", ts.ToString ("s\\.F"), "#F1"); + Assert.AreEqual ("12.3456789", ts.ToString ("s\\.fffffff"), "#F2"); + Assert.AreEqual ("12.345678", ts.ToString ("s\\.ffffff"), "#F3"); + + ts = new TimeSpan (1234); + Assert.AreEqual ("0.000123", ts.ToString ("s\\.ffffff"), "#G0"); + Assert.AreEqual ("0.0001", ts.ToString ("s\\.ffff"), "#G1"); + Assert.AreEqual ("0.", ts.ToString ("s\\.F"), "#G2"); + Assert.AreEqual ("0.", ts.ToString ("s\\.FFF"), "#G3"); + + ts = TimeSpan.FromSeconds (0.05); + Assert.AreEqual (".0", ts.ToString ("\\.f"), "#H0"); + Assert.AreEqual (".", ts.ToString ("\\.F"), "#H1"); } [Test] From d90ab2a6970c4065ebcf8ea7cc3e968386639017 Mon Sep 17 00:00:00 2001 From: rjvdboon Date: Sat, 27 Sep 2014 21:27:44 +0200 Subject: [PATCH 258/543] Adhere to mono coding guidelines. --- .../BootstrapContext.cs | 85 ++--- .../BootstrapContextTest.cs | 297 +++++++++--------- 2 files changed, 191 insertions(+), 191 deletions(-) diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs index 6dc620b5bad..2eb55937d6e 100644 --- a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs +++ b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs @@ -27,80 +27,93 @@ // #if NET_4_5 using System; +using System.IO; using System.Runtime.Serialization; +using System.Text; +using System.Xml; -namespace System.IdentityModel.Tokens -{ +namespace System.IdentityModel.Tokens { [Serializable] - public class BootstrapContext : ISerializable - { + public class BootstrapContext : ISerializable { /// Gets the string that was used to initialize the context. public string Token { get; private set; } /// Gets the array that was used to initialize the context. - public byte[] TokenBytes { get; private set; } + public byte [] TokenBytes { get; private set; } /// Gets the security token that was used to initialize the context. public SecurityToken SecurityToken { get; private set; } /// Gets the token handler that was used to initialize the context. public SecurityTokenHandler SecurityTokenHandler { get; private set; } /// Initializes a new instance of the class by using the specified string. - public BootstrapContext (string token) { - if (token == null) throw new ArgumentNullException("token"); + public BootstrapContext (string token) + { + if (token == null) + throw new ArgumentNullException ("token"); Token = token; } /// Initializes a new instance of the class by using the specified array. - public BootstrapContext (byte[] token) { - if (token == null) throw new ArgumentNullException("token"); + public BootstrapContext (byte [] token) + { + if (token == null) + throw new ArgumentNullException ("token"); TokenBytes = token; } /// Initializes a new instance of the class by using the specified security token and token handler. - public BootstrapContext (SecurityToken token, SecurityTokenHandler handler) { - if (token == null) throw new ArgumentNullException("token"); - if (handler == null) throw new ArgumentNullException("handler"); + public BootstrapContext (SecurityToken token, SecurityTokenHandler handler) + { + if (token == null) + throw new ArgumentNullException ("token"); + if (handler == null) + throw new ArgumentNullException ("handler"); SecurityToken = token; SecurityTokenHandler = handler; } - + /// Initializes a new instance of the class from a stream. - protected BootstrapContext(SerializationInfo info, StreamingContext context) { - if (info == null) throw new ArgumentNullException("info"); - char type = info.GetChar("K"); + protected BootstrapContext (SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException ("info"); + char type = info.GetChar ("K"); switch (type) { case 'S': - Token = info.GetString("T"); + Token = info.GetString ("T"); break; case 'B': - TokenBytes = (byte[])info.GetValue("T", typeof(byte[])); + TokenBytes = (byte [])info.GetValue ("T", typeof (byte [])); break; case 'T': - Token = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(info.GetString("T"))); + Token = Encoding.UTF8.GetString (Convert.FromBase64String (info.GetString ("T"))); break; } } - + /// Populates the with data needed to serialize the current object. - public void GetObjectData(SerializationInfo info, StreamingContext context) { - if (info == null) throw new ArgumentNullException("info"); + public void GetObjectData (SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException ("info"); if (Token != null) { - info.AddValue("K", 'S'); - info.AddValue("T", Token); - } else if (TokenBytes != null) { - info.AddValue("K", 'B'); - info.AddValue("T", TokenBytes); - } else if (SecurityToken != null && SecurityTokenHandler != null) { - info.AddValue("K", 'T'); - using(var ms = new System.IO.MemoryStream()) - using(var streamWriter = new System.IO.StreamWriter(ms, new System.Text.UTF8Encoding(false))) - using(var writer = System.Xml.XmlWriter.Create(streamWriter, new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true })) { - SecurityTokenHandler.WriteToken(writer, SecurityToken); - writer.Flush(); - info.AddValue("T", Convert.ToBase64String(ms.ToArray())); + info.AddValue ("K", 'S'); + info.AddValue ("T", Token); + } + else if (TokenBytes != null) { + info.AddValue ("K", 'B'); + info.AddValue ("T", TokenBytes); + } + else if (SecurityToken != null && SecurityTokenHandler != null) { + info.AddValue ("K", 'T'); + using (var ms = new MemoryStream ()) + using (var streamWriter = new StreamWriter (ms, new UTF8Encoding (false))) + using (var writer = XmlWriter.Create (streamWriter, new XmlWriterSettings { OmitXmlDeclaration = true })) { + SecurityTokenHandler.WriteToken (writer, SecurityToken); + writer.Flush (); + info.AddValue ("T", Convert.ToBase64String (ms.ToArray ())); } } } - } } #endif diff --git a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs index a9f603f3b63..1d5090748cd 100644 --- a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs +++ b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs @@ -12,251 +12,238 @@ using System.Xml; using NUnit.Framework; -namespace MonoTests.System.IdentityModel.Tokens.net_4_5 -{ +namespace MonoTests.System.IdentityModel.Tokens.net_4_5 { [TestFixture] - public class BootstrapContextTest - { + public class BootstrapContextTest { // The following byte arrays are the serialized bytes as emitted on Microsoft .Net 4.5. - private static readonly byte[] SerializedBootstrapContextByteArray = new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x07, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x42, 0x09, 0x03, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x0B }; - private static readonly byte[] SerializedBootstrapContextString = new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x53, 0x06, 0x03, 0x00, 0x00, 0x00, 0x05, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x0B }; - + private static readonly byte [] SerializedBootstrapContextByteArray = new byte [] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x07, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x42, 0x09, 0x03, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x0B }; + private static readonly byte [] SerializedBootstrapContextString = new byte [] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x53, 0x06, 0x03, 0x00, 0x00, 0x00, 0x05, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x0B }; + // Put in some non-ascii/latin1 characters to test the encoding scheme // \u018E == Latin capital letter Reversed E private const string user = "us\u018Er"; // \u00BD == Vulgar Fraction one half private const string password = "pass\u00BDword"; - private static readonly string SerializedBootstrapContextSecurityTokenString = ""; - private static readonly byte[] SerializedBootstrapContextSecurityToken = new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x54, 0x06, 0x03, 0x00, 0x00, 0x00, 0x98, 0x01, 0x50, 0x46, 0x56, 0x7A, 0x5A, 0x58, 0x4A, 0x4F, 0x59, 0x57, 0x31, 0x6C, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x70, 0x64, 0x48, 0x6C, 0x55, 0x62, 0x32, 0x74, 0x6C, 0x62, 0x69, 0x42, 0x4A, 0x5A, 0x44, 0x30, 0x69, 0x64, 0x58, 0x56, 0x70, 0x5A, 0x43, 0x30, 0x35, 0x4D, 0x6A, 0x64, 0x6A, 0x4D, 0x47, 0x49, 0x35, 0x4F, 0x43, 0x31, 0x69, 0x59, 0x54, 0x45, 0x34, 0x4C, 0x54, 0x51, 0x35, 0x5A, 0x44, 0x49, 0x74, 0x59, 0x54, 0x59, 0x31, 0x4D, 0x79, 0x30, 0x7A, 0x4D, 0x44, 0x5A, 0x6B, 0x4E, 0x6A, 0x42, 0x6D, 0x4F, 0x44, 0x55, 0x33, 0x4E, 0x54, 0x45, 0x74, 0x4D, 0x79, 0x49, 0x67, 0x56, 0x58, 0x4E, 0x6C, 0x63, 0x6D, 0x35, 0x68, 0x62, 0x57, 0x55, 0x39, 0x49, 0x6E, 0x56, 0x7A, 0x78, 0x6F, 0x35, 0x79, 0x49, 0x69, 0x42, 0x51, 0x59, 0x58, 0x4E, 0x7A, 0x64, 0x32, 0x39, 0x79, 0x5A, 0x44, 0x30, 0x69, 0x63, 0x47, 0x46, 0x7A, 0x63, 0x38, 0x4B, 0x39, 0x64, 0x32, 0x39, 0x79, 0x5A, 0x43, 0x49, 0x76, 0x50, 0x67, 0x3D, 0x3D, 0x0B }; + private static readonly string SerializedBootstrapContextSecurityTokenString = ""; + private static readonly byte [] SerializedBootstrapContextSecurityToken = new byte [] { 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x57, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x34, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x30, 0x2C, 0x20, 0x43, 0x75, 0x6C, 0x74, 0x75, 0x72, 0x65, 0x3D, 0x6E, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6C, 0x2C, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x3D, 0x62, 0x37, 0x37, 0x61, 0x35, 0x63, 0x35, 0x36, 0x31, 0x39, 0x33, 0x34, 0x65, 0x30, 0x38, 0x39, 0x05, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x2E, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x73, 0x2E, 0x42, 0x6F, 0x6F, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, 0x02, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x01, 0x54, 0x00, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x54, 0x06, 0x03, 0x00, 0x00, 0x00, 0x98, 0x01, 0x50, 0x46, 0x56, 0x7A, 0x5A, 0x58, 0x4A, 0x4F, 0x59, 0x57, 0x31, 0x6C, 0x55, 0x32, 0x56, 0x6A, 0x64, 0x58, 0x4A, 0x70, 0x64, 0x48, 0x6C, 0x55, 0x62, 0x32, 0x74, 0x6C, 0x62, 0x69, 0x42, 0x4A, 0x5A, 0x44, 0x30, 0x69, 0x64, 0x58, 0x56, 0x70, 0x5A, 0x43, 0x30, 0x35, 0x4D, 0x6A, 0x64, 0x6A, 0x4D, 0x47, 0x49, 0x35, 0x4F, 0x43, 0x31, 0x69, 0x59, 0x54, 0x45, 0x34, 0x4C, 0x54, 0x51, 0x35, 0x5A, 0x44, 0x49, 0x74, 0x59, 0x54, 0x59, 0x31, 0x4D, 0x79, 0x30, 0x7A, 0x4D, 0x44, 0x5A, 0x6B, 0x4E, 0x6A, 0x42, 0x6D, 0x4F, 0x44, 0x55, 0x33, 0x4E, 0x54, 0x45, 0x74, 0x4D, 0x79, 0x49, 0x67, 0x56, 0x58, 0x4E, 0x6C, 0x63, 0x6D, 0x35, 0x68, 0x62, 0x57, 0x55, 0x39, 0x49, 0x6E, 0x56, 0x7A, 0x78, 0x6F, 0x35, 0x79, 0x49, 0x69, 0x42, 0x51, 0x59, 0x58, 0x4E, 0x7A, 0x64, 0x32, 0x39, 0x79, 0x5A, 0x44, 0x30, 0x69, 0x63, 0x47, 0x46, 0x7A, 0x63, 0x38, 0x4B, 0x39, 0x64, 0x32, 0x39, 0x79, 0x5A, 0x43, 0x49, 0x76, 0x50, 0x67, 0x3D, 0x3D, 0x0B }; [Test] - public void Ctor_StringToken_Works() + public void Ctor_StringToken_Works () { - BootstrapContext bootstrapContext = new BootstrapContext("token"); + BootstrapContext bootstrapContext = new BootstrapContext ("token"); - Assert.AreEqual("token", bootstrapContext.Token, "#1"); - Assert.IsNull(bootstrapContext.TokenBytes, "#2"); - Assert.IsNull(bootstrapContext.SecurityToken, "#3"); - Assert.IsNull(bootstrapContext.SecurityTokenHandler, "#4"); + Assert.AreEqual ("token", bootstrapContext.Token, "#1"); + Assert.IsNull (bootstrapContext.TokenBytes, "#2"); + Assert.IsNull (bootstrapContext.SecurityToken, "#3"); + Assert.IsNull (bootstrapContext.SecurityTokenHandler, "#4"); } [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void Ctor_StringToken_NullToken_Throws() + [ExpectedException (typeof (ArgumentNullException))] + public void Ctor_StringToken_NullToken_Throws () { - BootstrapContext bootstrapContext = new BootstrapContext((string)null); - Assert.Fail("Should have thrown"); + BootstrapContext bootstrapContext = new BootstrapContext ((string)null); + Assert.Fail ("Should have thrown"); } [Test] - public void Serialize_StringToken_Works() + public void Serialize_StringToken_Works () { - BootstrapContext bootstrapContext = new BootstrapContext("token"); - BinaryFormatter binaryFormatter = new BinaryFormatter(); - using (var s = new MemoryStream()) - { - binaryFormatter.Serialize(s, bootstrapContext); + BootstrapContext bootstrapContext = new BootstrapContext ("token"); + BinaryFormatter binaryFormatter = new BinaryFormatter (); + using (var s = new MemoryStream ()) { + binaryFormatter.Serialize (s, bootstrapContext); s.Position = 0; - BootstrapContext bootstrapContext2 = binaryFormatter.Deserialize(s) as BootstrapContext; - Assert.IsNotNull(bootstrapContext2, "#1"); - Assert.AreEqual(bootstrapContext.Token, bootstrapContext2.Token, "#2"); - Assert.AreEqual(bootstrapContext.TokenBytes, bootstrapContext2.TokenBytes, "#3"); - Assert.AreEqual(bootstrapContext.SecurityToken, bootstrapContext2.SecurityToken, "#4"); - Assert.AreEqual(bootstrapContext.SecurityTokenHandler, bootstrapContext2.SecurityTokenHandler, "#5"); + BootstrapContext bootstrapContext2 = binaryFormatter.Deserialize (s) as BootstrapContext; + Assert.IsNotNull (bootstrapContext2, "#1"); + Assert.AreEqual (bootstrapContext.Token, bootstrapContext2.Token, "#2"); + Assert.AreEqual (bootstrapContext.TokenBytes, bootstrapContext2.TokenBytes, "#3"); + Assert.AreEqual (bootstrapContext.SecurityToken, bootstrapContext2.SecurityToken, "#4"); + Assert.AreEqual (bootstrapContext.SecurityTokenHandler, bootstrapContext2.SecurityTokenHandler, "#5"); } } [Test] - public void Deserialize_StringToken_Works() - { - BinaryFormatter binaryFormatter = new BinaryFormatter(); - using (var s = new MemoryStream(SerializedBootstrapContextString)) - { - BootstrapContext bootstrapContext = binaryFormatter.Deserialize(s) as BootstrapContext; - Assert.IsNotNull(bootstrapContext, "#1"); - Assert.AreEqual("token", bootstrapContext.Token, "#2"); - Assert.IsNull(bootstrapContext.TokenBytes, "#3"); - Assert.IsNull(bootstrapContext.SecurityToken, "#4"); - Assert.IsNull(bootstrapContext.SecurityTokenHandler, "#5"); + public void Deserialize_StringToken_Works () + { + BinaryFormatter binaryFormatter = new BinaryFormatter (); + using (var s = new MemoryStream (SerializedBootstrapContextString)) { + BootstrapContext bootstrapContext = binaryFormatter.Deserialize (s) as BootstrapContext; + Assert.IsNotNull (bootstrapContext, "#1"); + Assert.AreEqual ("token", bootstrapContext.Token, "#2"); + Assert.IsNull (bootstrapContext.TokenBytes, "#3"); + Assert.IsNull (bootstrapContext.SecurityToken, "#4"); + Assert.IsNull (bootstrapContext.SecurityTokenHandler, "#5"); } } [Test] - public void Ctor_ByteArrayToken_Works() + public void Ctor_ByteArrayToken_Works () { - BootstrapContext bootstrapContext = new BootstrapContext(new byte[]{0x01}); + BootstrapContext bootstrapContext = new BootstrapContext (new byte [] { 0x01 }); - Assert.IsNotNull(bootstrapContext.TokenBytes, "#1"); - Assert.AreEqual(1, bootstrapContext.TokenBytes.Length, "#2"); - Assert.AreEqual(1, bootstrapContext.TokenBytes[0], "#3"); - Assert.IsNull(bootstrapContext.Token, "#4"); - Assert.IsNull(bootstrapContext.SecurityToken, "#5"); - Assert.IsNull(bootstrapContext.SecurityTokenHandler, "#6"); + Assert.IsNotNull (bootstrapContext.TokenBytes, "#1"); + Assert.AreEqual (1, bootstrapContext.TokenBytes.Length, "#2"); + Assert.AreEqual (1, bootstrapContext.TokenBytes [0], "#3"); + Assert.IsNull (bootstrapContext.Token, "#4"); + Assert.IsNull (bootstrapContext.SecurityToken, "#5"); + Assert.IsNull (bootstrapContext.SecurityTokenHandler, "#6"); } [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void Ctor_ByteArrayToken_NullToken_Throws() + [ExpectedException (typeof (ArgumentNullException))] + public void Ctor_ByteArrayToken_NullToken_Throws () { - BootstrapContext bootstrapContext = new BootstrapContext((byte[])null); - Assert.Fail("Should have thrown"); + BootstrapContext bootstrapContext = new BootstrapContext ((byte [])null); + Assert.Fail ("Should have thrown"); } [Test] - public void Serialize_ByteArrayToken_Works() + public void Serialize_ByteArrayToken_Works () { - BootstrapContext bootstrapContext = new BootstrapContext(new byte[]{0x1}); - BinaryFormatter binaryFormatter = new BinaryFormatter(); - using (var s = new MemoryStream()) - { - binaryFormatter.Serialize(s, bootstrapContext); + BootstrapContext bootstrapContext = new BootstrapContext (new byte [] { 0x1 }); + BinaryFormatter binaryFormatter = new BinaryFormatter (); + using (var s = new MemoryStream ()) { + binaryFormatter.Serialize (s, bootstrapContext); s.Position = 0; - BootstrapContext bootstrapContext2 = binaryFormatter.Deserialize(s) as BootstrapContext; - Assert.IsNotNull(bootstrapContext2, "#1"); - Assert.AreEqual(bootstrapContext.Token, bootstrapContext2.Token, "#2"); - Assert.AreEqual(bootstrapContext.TokenBytes, bootstrapContext2.TokenBytes, "#3"); - Assert.AreEqual(bootstrapContext.SecurityToken, bootstrapContext2.SecurityToken, "#4"); - Assert.AreEqual(bootstrapContext.SecurityTokenHandler, bootstrapContext2.SecurityTokenHandler, "#5"); + BootstrapContext bootstrapContext2 = binaryFormatter.Deserialize (s) as BootstrapContext; + Assert.IsNotNull (bootstrapContext2, "#1"); + Assert.AreEqual (bootstrapContext.Token, bootstrapContext2.Token, "#2"); + Assert.AreEqual (bootstrapContext.TokenBytes, bootstrapContext2.TokenBytes, "#3"); + Assert.AreEqual (bootstrapContext.SecurityToken, bootstrapContext2.SecurityToken, "#4"); + Assert.AreEqual (bootstrapContext.SecurityTokenHandler, bootstrapContext2.SecurityTokenHandler, "#5"); } } [Test] - public void Deserialize_ByteArrayToken_Works() - { - BinaryFormatter binaryFormatter = new BinaryFormatter(); - using (var s = new MemoryStream(SerializedBootstrapContextByteArray)) - { - BootstrapContext bootstrapContext = binaryFormatter.Deserialize(s) as BootstrapContext; - Assert.IsNotNull(bootstrapContext, "#1"); - Assert.IsNotNull(bootstrapContext.TokenBytes, "#2"); - Assert.AreEqual(1, bootstrapContext.TokenBytes.Length, "#3"); - Assert.AreEqual(1, bootstrapContext.TokenBytes[0], "#4"); - Assert.IsNull(bootstrapContext.Token, "#5"); - Assert.IsNull(bootstrapContext.SecurityToken, "#6"); - Assert.IsNull(bootstrapContext.SecurityTokenHandler, "#7"); + public void Deserialize_ByteArrayToken_Works () + { + BinaryFormatter binaryFormatter = new BinaryFormatter (); + using (var s = new MemoryStream (SerializedBootstrapContextByteArray)) { + BootstrapContext bootstrapContext = binaryFormatter.Deserialize (s) as BootstrapContext; + Assert.IsNotNull (bootstrapContext, "#1"); + Assert.IsNotNull (bootstrapContext.TokenBytes, "#2"); + Assert.AreEqual (1, bootstrapContext.TokenBytes.Length, "#3"); + Assert.AreEqual (1, bootstrapContext.TokenBytes [0], "#4"); + Assert.IsNull (bootstrapContext.Token, "#5"); + Assert.IsNull (bootstrapContext.SecurityToken, "#6"); + Assert.IsNull (bootstrapContext.SecurityTokenHandler, "#7"); } } [Test] - public void Ctor_SecurityToken_Works() + public void Ctor_SecurityToken_Works () { - var securityToken = new UserNameSecurityToken(user, password); - var securityTokenHandler = new SimpleSecurityTokenHandler(); - BootstrapContext bootstrapContext = new BootstrapContext(securityToken, securityTokenHandler); + var securityToken = new UserNameSecurityToken (user, password); + var securityTokenHandler = new SimpleSecurityTokenHandler (); + BootstrapContext bootstrapContext = new BootstrapContext (securityToken, securityTokenHandler); - Assert.IsNotNull(bootstrapContext.SecurityToken, "#1"); - Assert.AreEqual(user, securityToken.UserName, "#2"); - Assert.AreEqual(password, securityToken.Password, "#3"); - Assert.AreEqual(securityTokenHandler, bootstrapContext.SecurityTokenHandler, "#4"); + Assert.IsNotNull (bootstrapContext.SecurityToken, "#1"); + Assert.AreEqual (user, securityToken.UserName, "#2"); + Assert.AreEqual (password, securityToken.Password, "#3"); + Assert.AreEqual (securityTokenHandler, bootstrapContext.SecurityTokenHandler, "#4"); - Assert.IsNull(bootstrapContext.Token, "#5"); - Assert.IsNull(bootstrapContext.TokenBytes, "#6"); + Assert.IsNull (bootstrapContext.Token, "#5"); + Assert.IsNull (bootstrapContext.TokenBytes, "#6"); } [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void Ctor_SecurityToken_NullToken_Throws() + [ExpectedException (typeof (ArgumentNullException))] + public void Ctor_SecurityToken_NullToken_Throws () { - BootstrapContext bootstrapContext = new BootstrapContext(null, new SimpleSecurityTokenHandler()); - Assert.Fail("Should have thrown"); + BootstrapContext bootstrapContext = new BootstrapContext (null, new SimpleSecurityTokenHandler ()); + Assert.Fail ("Should have thrown"); } [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void Ctor_SecurityToken_NullHandler_Throws() + [ExpectedException (typeof (ArgumentNullException))] + public void Ctor_SecurityToken_NullHandler_Throws () { - BootstrapContext bootstrapContext = new BootstrapContext(new UserNameSecurityToken("user", "password"), null); - Assert.Fail("Should have thrown"); + BootstrapContext bootstrapContext = new BootstrapContext (new UserNameSecurityToken ("user", "password"), null); + Assert.Fail ("Should have thrown"); } [Test] - public void Serialize_SecurityTokenAndHandler_Works() + public void Serialize_SecurityTokenAndHandler_Works () { - var securityToken = new UserNameSecurityToken(user, password, "uuid-927c0b98-ba18-49d2-a653-306d60f85751-3"); - var securityTokenHandler = new SimpleSecurityTokenHandler(); - BootstrapContext bootstrapContext = new BootstrapContext(securityToken, securityTokenHandler); + var securityToken = new UserNameSecurityToken (user, password, "uuid-927c0b98-ba18-49d2-a653-306d60f85751-3"); + var securityTokenHandler = new SimpleSecurityTokenHandler (); + BootstrapContext bootstrapContext = new BootstrapContext (securityToken, securityTokenHandler); - BinaryFormatter binaryFormatter = new BinaryFormatter(); - using (var s = new MemoryStream()) - { - binaryFormatter.Serialize(s, bootstrapContext); + BinaryFormatter binaryFormatter = new BinaryFormatter (); + using (var s = new MemoryStream ()) { + binaryFormatter.Serialize (s, bootstrapContext); s.Position = 0; - BootstrapContext bootstrapContext2 = binaryFormatter.Deserialize(s) as BootstrapContext; - Assert.IsNotNull(bootstrapContext2, "#1"); + BootstrapContext bootstrapContext2 = binaryFormatter.Deserialize (s) as BootstrapContext; + Assert.IsNotNull (bootstrapContext2, "#1"); // Deserialize does not restore the SecurityToken, but restores into the Token. - Assert.IsNotNull(bootstrapContext2.Token, "#3"); + Assert.IsNotNull (bootstrapContext2.Token, "#3"); // We replace ' /' by '/' to accomodate the xml writer differences between mono and .net - Assert.AreEqual(SerializedBootstrapContextSecurityTokenString.Replace(" /","/"), bootstrapContext2.Token.Replace(" /","/"), "#2"); - Assert.AreEqual(bootstrapContext.TokenBytes, bootstrapContext2.TokenBytes, "#3"); - Assert.IsNull(bootstrapContext2.SecurityToken, "#4"); - Assert.IsNull(bootstrapContext2.SecurityTokenHandler, "#5"); + Assert.AreEqual (SerializedBootstrapContextSecurityTokenString.Replace (" /", "/"), bootstrapContext2.Token.Replace (" /", "/"), "#2"); + Assert.AreEqual (bootstrapContext.TokenBytes, bootstrapContext2.TokenBytes, "#3"); + Assert.IsNull (bootstrapContext2.SecurityToken, "#4"); + Assert.IsNull (bootstrapContext2.SecurityTokenHandler, "#5"); } } [Test] - public void Deserialize_SecurityTokenAndHandler_Works() - { - BinaryFormatter binaryFormatter = new BinaryFormatter(); - using (var s = new MemoryStream(SerializedBootstrapContextSecurityToken)) - { - BootstrapContext bootstrapContext = binaryFormatter.Deserialize(s) as BootstrapContext; - Assert.IsNotNull(bootstrapContext, "#1"); - Assert.AreEqual(SerializedBootstrapContextSecurityTokenString, bootstrapContext.Token, "#2"); - Assert.IsNull(bootstrapContext.SecurityToken, "#3"); - Assert.IsNull(bootstrapContext.SecurityTokenHandler, "#4"); - Assert.IsNull(bootstrapContext.TokenBytes, "#5"); + public void Deserialize_SecurityTokenAndHandler_Works () + { + BinaryFormatter binaryFormatter = new BinaryFormatter (); + using (var s = new MemoryStream (SerializedBootstrapContextSecurityToken)) { + BootstrapContext bootstrapContext = binaryFormatter.Deserialize (s) as BootstrapContext; + Assert.IsNotNull (bootstrapContext, "#1"); + Assert.AreEqual (SerializedBootstrapContextSecurityTokenString, bootstrapContext.Token, "#2"); + Assert.IsNull (bootstrapContext.SecurityToken, "#3"); + Assert.IsNull (bootstrapContext.SecurityTokenHandler, "#4"); + Assert.IsNull (bootstrapContext.TokenBytes, "#5"); } } - private static void DumpAsText(byte[] data) + private static void DumpAsText (byte [] data) { - Console.WriteLine("{0}", Encoding.ASCII.GetString(data)); + Console.WriteLine ("{0}", Encoding.ASCII.GetString (data)); } - private static void Dump(byte[] data) + private static void Dump (byte [] data) { - var sb = new StringBuilder(); - sb.Append("new byte[] { "); + var sb = new StringBuilder (); + sb.Append ("new byte[] { "); bool first = true; - foreach(byte b in data) - { - if (!first) sb.Append(", "); - else first = false; - sb.AppendFormat("0x{0:X2}", b); + foreach (byte b in data) { + if (!first) + sb.Append (", "); + else + first = false; + sb.AppendFormat ("0x{0:X2}", b); } - sb.Append(" };"); - Console.WriteLine(sb.ToString()); + sb.Append (" };"); + Console.WriteLine (sb.ToString ()); } - private class SimpleSecurityTokenHandler : SecurityTokenHandler - { - public override string[] GetTokenTypeIdentifiers() + private class SimpleSecurityTokenHandler : SecurityTokenHandler { + public override string [] GetTokenTypeIdentifiers () { - throw new NotImplementedException(); + throw new NotImplementedException (); } - public override Type TokenType - { - get { return typeof(UserNameSecurityToken); } + public override Type TokenType { + get { return typeof (UserNameSecurityToken); } } - public override bool CanWriteToken - { - get - { - return true; - } + public override bool CanWriteToken { + get { return true; } } - public override void WriteToken(XmlWriter writer, SecurityToken token) + public override void WriteToken (XmlWriter writer, SecurityToken token) { UserNameSecurityToken unst = token as UserNameSecurityToken; if (unst == null) - throw new ArgumentException("Token must be of type UserNameSecurityToken", "token"); - writer.WriteStartElement("UserNameSecurityToken"); - writer.WriteAttributeString("Id", unst.Id); - writer.WriteAttributeString("Username", unst.UserName); - writer.WriteAttributeString("Password", unst.Password); - writer.WriteEndElement(); + throw new ArgumentException ("Token must be of type UserNameSecurityToken", "token"); + writer.WriteStartElement ("UserNameSecurityToken"); + writer.WriteAttributeString ("Id", unst.Id); + writer.WriteAttributeString ("Username", unst.UserName); + writer.WriteAttributeString ("Password", unst.Password); + writer.WriteEndElement (); } } } From 2f9fb9e88834ea6d8a44171a2c7dd6f6c8c9033a Mon Sep 17 00:00:00 2001 From: rjvdboon Date: Sat, 27 Sep 2014 21:32:46 +0200 Subject: [PATCH 259/543] more coding style changes --- .../System.IdentityModel.Tokens/BootstrapContext.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs index 2eb55937d6e..5e9f589c294 100644 --- a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs +++ b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs @@ -98,12 +98,10 @@ public void GetObjectData (SerializationInfo info, StreamingContext context) if (Token != null) { info.AddValue ("K", 'S'); info.AddValue ("T", Token); - } - else if (TokenBytes != null) { + } else if (TokenBytes != null) { info.AddValue ("K", 'B'); info.AddValue ("T", TokenBytes); - } - else if (SecurityToken != null && SecurityTokenHandler != null) { + } else if (SecurityToken != null && SecurityTokenHandler != null) { info.AddValue ("K", 'T'); using (var ms = new MemoryStream ()) using (var streamWriter = new StreamWriter (ms, new UTF8Encoding (false))) From 657b6caad681f693547d70804fdec6f717668a8d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 28 Sep 2014 01:49:33 -0400 Subject: [PATCH 260/543] [runtime] Implement and enable the new interrupt code on amd64. --- mono/metadata/threads-types.h | 4 ++-- mono/metadata/threads.c | 5 ++++- mono/mini/exceptions-amd64.c | 9 ++++++++- mono/mini/mini.h | 2 +- mono/utils/mono-threads.c | 2 +- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/mono/metadata/threads-types.h b/mono/metadata/threads-types.h index 6aeca4acf5e..969f5ba2d9b 100644 --- a/mono/metadata/threads-types.h +++ b/mono/metadata/threads-types.h @@ -18,6 +18,7 @@ #include #include "mono/utils/mono-compiler.h" #include "mono/utils/mono-membar.h" +#include "mono/utils/mono-threads.h" /* This is a copy of System.Threading.ThreadState */ typedef enum { @@ -40,8 +41,6 @@ typedef enum { ThreadApartmentState_Unknown = 0x00000002 } MonoThreadApartmentState; -typedef void (*MonoThreadNotifyPendingExcFunc) (void); - #define SPECIAL_STATIC_NONE 0 #define SPECIAL_STATIC_THREAD 1 #define SPECIAL_STATIC_CONTEXT 2 @@ -54,6 +53,7 @@ typedef LPTHREAD_START_ROUTINE WapiThreadStart; typedef struct _MonoInternalThread MonoInternalThread; typedef void (*MonoThreadCleanupFunc) (MonoInternalThread* thread); +typedef void (*MonoThreadNotifyPendingExcFunc) (MonoThreadInfo *info); MonoInternalThread* mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, guint32 stack_size) MONO_INTERNAL; diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index b5583952036..a090b70cffa 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -4197,7 +4197,7 @@ mono_thread_request_interruption (gboolean running_managed) if (mono_thread_notify_pending_exc_fn && !running_managed) /* The JIT will notify the thread about the interruption */ /* This shouldn't take any locks */ - mono_thread_notify_pending_exc_fn (); + mono_thread_notify_pending_exc_fn (NULL); /* this will awake the thread if it is in WaitForSingleObject or similar */ @@ -4658,6 +4658,9 @@ suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt) InterlockedIncrement (&thread_interruption_requested); if (interrupt) interrupt_handle = mono_thread_info_prepare_interrupt (thread->handle); + if (mono_thread_notify_pending_exc_fn && !running_managed) + /* The JIT will notify the thread about the interruption */ + mono_thread_notify_pending_exc_fn (info); mono_thread_info_finish_suspend_and_resume (info); if (interrupt) mono_thread_info_finish_interrupt (interrupt_handle); diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index f6cd5155e0f..a0865b7e2b6 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -1021,10 +1021,17 @@ static gpointer throw_pending_exception; * exception. */ void -mono_arch_notify_pending_exc (void) +mono_arch_notify_pending_exc (MonoThreadInfo *info) { MonoLMF *lmf = mono_get_lmf (); + if (!info) { + lmf = mono_get_lmf (); + } else { + g_assert (info->suspend_state.valid); + lmf = info->suspend_state.unwind_data [MONO_UNWIND_DATA_LMF]; + } + if (!lmf) /* Not yet started */ return; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index a0cadfb6bb6..c176f7c0829 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2465,7 +2465,7 @@ void mono_arch_emit_imt_argument (MonoCompile *cfg, MonoCallInst MonoMethod* mono_arch_find_imt_method (mgreg_t *regs, guint8 *code) MONO_INTERNAL; MonoVTable* mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code) MONO_INTERNAL; gpointer mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp) MONO_INTERNAL; -void mono_arch_notify_pending_exc (void) MONO_INTERNAL; +void mono_arch_notify_pending_exc (MonoThreadInfo *info) MONO_INTERNAL; guint8* mono_arch_get_call_target (guint8 *code) MONO_INTERNAL; guint32 mono_arch_get_plt_info_offset (guint8 *plt_entry, mgreg_t *regs, guint8 *code) MONO_INTERNAL; GSList *mono_arch_get_trampolines (gboolean aot) MONO_INTERNAL; diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index ce0e5be87ef..008c3c86b5b 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -734,7 +734,7 @@ mono_thread_info_new_interrupt_enabled (void) #if defined(HOST_WIN32) return !disable_new_interrupt; #endif -#if defined (__i386__) +#if defined (__i386__) || defined(__x86_64__) return !disable_new_interrupt; #endif #if defined(__arm__) && !defined(__APPLE__) From a5439f96461a2a2a3e88933760bd90d74c6b30b0 Mon Sep 17 00:00:00 2001 From: Marius Ungureanu Date: Sun, 28 Sep 2014 23:48:58 +0300 Subject: [PATCH 261/543] [CorCompare] Add sealed methods parsing. --- mcs/tools/corcompare/mono-api-info.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mcs/tools/corcompare/mono-api-info.cs b/mcs/tools/corcompare/mono-api-info.cs index 2dc4bcebb3d..8a42507826b 100644 --- a/mcs/tools/corcompare/mono-api-info.cs +++ b/mcs/tools/corcompare/mono-api-info.cs @@ -907,6 +907,8 @@ protected override void AddExtraData (XmlNode p, MemberReference memberDefenitio AddAttribute (p, "abstract", "true"); if (mbase.IsVirtual) AddAttribute (p, "virtual", "true"); + if (mbase.IsFinal && mbase.IsVirtual && mbase.IsReuseSlot) + AddAttribute (p, "sealed", "true"); if (mbase.IsStatic) AddAttribute (p, "static", "true"); From 63f50e9a1a2b94de2477c508da238dce6ea804f5 Mon Sep 17 00:00:00 2001 From: Marius Ungureanu Date: Sun, 28 Sep 2014 23:50:39 +0300 Subject: [PATCH 262/543] [CorCompare] Add pointer as a class type. --- mcs/tools/corcompare/mono-api-info.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mcs/tools/corcompare/mono-api-info.cs b/mcs/tools/corcompare/mono-api-info.cs index 8a42507826b..a689210b12b 100644 --- a/mcs/tools/corcompare/mono-api-info.cs +++ b/mcs/tools/corcompare/mono-api-info.cs @@ -545,6 +545,9 @@ static string GetClassType (TypeDefinition t) if (TypeHelper.IsDelegate(t)) return "delegate"; + if (t.IsPointer) + return "pointer"; + return "class"; } From 5d3a42dc0f75473ad3be7c8f6ae61a76e278fdf0 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 28 Sep 2014 19:44:10 -0400 Subject: [PATCH 263/543] [runtime] Disallow generic classes with explicit layout. Fixes #23438. --- mono/metadata/class.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 240792536d3..baa9565e8c9 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -1642,6 +1642,10 @@ mono_class_setup_fields (MonoClass *class) mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name)); break; } + if (class->generic_container) { + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout.")); + break; + } } } From 9ac8be28af3acaa4f920f6bf327a3c3362504dd2 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 28 Sep 2014 19:56:53 -0400 Subject: [PATCH 264/543] [bcl] Add AppDomain.FirstChangeException event, not implemented yet. --- mcs/class/corlib/System/AppDomain.cs | 4 ++ .../System/FirstChanceExceptionEventArgs.cs | 44 +++++++++++++++++++ mcs/class/corlib/corlib.dll.sources | 1 + 3 files changed, 49 insertions(+) create mode 100644 mcs/class/corlib/System/FirstChanceExceptionEventArgs.cs diff --git a/mcs/class/corlib/System/AppDomain.cs b/mcs/class/corlib/System/AppDomain.cs index 5ebd4db216e..07b6fd45590 100644 --- a/mcs/class/corlib/System/AppDomain.cs +++ b/mcs/class/corlib/System/AppDomain.cs @@ -1405,6 +1405,10 @@ internal void ProcessMessageInDomain (byte[] arrRequest, CADMethodCallMessage ca [method: SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)] public event UnhandledExceptionEventHandler UnhandledException; +#if NET_4_5 + public event EventHandler FirstChanceException; +#endif + #if NET_4_0 [MonoTODO] public bool IsHomogenous { diff --git a/mcs/class/corlib/System/FirstChanceExceptionEventArgs.cs b/mcs/class/corlib/System/FirstChanceExceptionEventArgs.cs new file mode 100644 index 00000000000..d39fbdc715e --- /dev/null +++ b/mcs/class/corlib/System/FirstChanceExceptionEventArgs.cs @@ -0,0 +1,44 @@ +// +// System.FirstChangeExceptionEventArgs.cs +// +// Copyright 2014 Xamarin Inc (http://www.xamarin.com). +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if NET_4_5 +using System; + +public class FirstChanceExceptionEventArgs : EventArgs +{ + Exception exception; + + public FirstChanceExceptionEventArgs (Exception exception) { + this.exception = exception; + } + + public Exception Exception { + get { + return exception; + } + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/corlib.dll.sources b/mcs/class/corlib/corlib.dll.sources index 2626ca0fa3e..b1516b8bb14 100644 --- a/mcs/class/corlib/corlib.dll.sources +++ b/mcs/class/corlib/corlib.dll.sources @@ -160,6 +160,7 @@ System/EventHandler.cs System/Exception.cs System/ExecutionEngineException.cs System/FieldAccessException.cs +System/FirstChanceExceptionEventArgs.cs System/FlagsAttribute.cs System/FormatException.cs System/Funcs.cs From b533e2abac2f907203e778640c8f4209e8cca491 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 28 Sep 2014 19:57:52 -0400 Subject: [PATCH 265/543] Fix a warning. --- mcs/class/corlib/System.Text/UTF8Encoding.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/mcs/class/corlib/System.Text/UTF8Encoding.cs b/mcs/class/corlib/System.Text/UTF8Encoding.cs index 1ea7a9ea86a..b3a93f14274 100644 --- a/mcs/class/corlib/System.Text/UTF8Encoding.cs +++ b/mcs/class/corlib/System.Text/UTF8Encoding.cs @@ -831,7 +831,6 @@ public override int GetChars (byte[] bytes, int byteIndex, int byteCount, uint leftOverBits = 0; uint leftOverCount = 0; DecoderFallbackBuffer buf = null; - byte [] bufferArg = null; return InternalGetChars (bytes, byteIndex, byteCount, chars, charIndex, ref leftOverBits, ref leftOverCount, DecoderFallback, ref buf, true); } From 75eb6a9caf2decab65b705f5a5952a73ba0416b4 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 29 Sep 2014 01:06:50 -0400 Subject: [PATCH 266/543] Revert "[jit] Enable deadce on fp instructions on x86. Fixes #23392." This reverts commit a32e2c7fe6ffabcb6b06e4ab28e3ea1a58f9c6a3. Revert this as it breaks the build. --- mono/mini/local-propagation.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mono/mini/local-propagation.c b/mono/mini/local-propagation.c index e564f7a4736..7bdb517bd2b 100644 --- a/mono/mini/local-propagation.c +++ b/mono/mini/local-propagation.c @@ -547,7 +547,8 @@ mono_local_deadce (MonoCompile *cfg) } } - if (reg_is_softreg (ins->dreg, spec [MONO_INST_DEST])) { + /* Enabling this on x86 could screw up the fp stack */ + if (reg_is_softreg_no_fpstack (ins->dreg, spec [MONO_INST_DEST])) { /* * Assignments to global vregs can only be eliminated if there is another * assignment to the same vreg later in the same bblock. From 84f9d58737c00d8563ef1ad1020680360d6aab87 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 29 Sep 2014 11:39:52 +0200 Subject: [PATCH 267/543] [mcs] Handle crash in binary operators when enum is used and nullable type is undefined --- mcs/mcs/expression.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index e7bf61fab0b..6699377f8df 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -4601,7 +4601,15 @@ Expression ResolveEnumOperators (ResolveContext rc, bool lenum, bool renum, Type return expr; } - enum_type = rc.Module.PredefinedTypes.Nullable.TypeSpec.MakeGenericType (rc.Module, new[] { enum_type }); + var nullable = rc.Module.PredefinedTypes.Nullable; + + // + // Don't try nullable version when nullable type is undefined + // + if (!nullable.IsDefined) + return null; + + enum_type = nullable.TypeSpec.MakeGenericType (rc.Module, new[] { enum_type }); } expr = ResolveOperatorPredefined (rc, rc.Module.GetPredefinedEnumAritmeticOperators (enum_type, true), false); From 22a218578a986811325b7e24a5c98001ad52f386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Mon, 29 Sep 2014 14:11:06 +0200 Subject: [PATCH 268/543] Updated links in CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c56d15a99a0..a04886ff4b0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ When contributing to the Mono project, please follow the [Mono Coding Guidelines][1]. We have been using a coding style for many years, please make your patches conform to these guidelines. -[1] http://www.mono-project.com/Coding_Guidelines +[1] http://www.mono-project.com/community/contributing/coding-guidelines/ Etiquette ========= @@ -68,7 +68,7 @@ status of your pull request. If it succeeded and we like the changes, a maintainer will likely merge it. Otherwise, you can amend your pull request to fix build breakage and Jenkins will test it again. -[2] http://monojenkins.cloudapp.net +[2] http://jenkins.mono-project.com/ # Inactivity From 5d762ffe93f8ede40a347c751c33d588729ed7eb Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 29 Sep 2014 15:13:05 +0200 Subject: [PATCH 269/543] [mcs] null operator on unconstrained generic values --- mcs/errors/cs0023-25.cs | 10 +++++++ mcs/mcs/codegen.cs | 17 ++++++------ mcs/mcs/ecore.cs | 2 ++ mcs/tests/test-null-operator-010.cs | 41 +++++++++++++++++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 24 +++++++++++++++++ 5 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 mcs/errors/cs0023-25.cs create mode 100644 mcs/tests/test-null-operator-010.cs diff --git a/mcs/errors/cs0023-25.cs b/mcs/errors/cs0023-25.cs new file mode 100644 index 00000000000..d6f5c5bbe1a --- /dev/null +++ b/mcs/errors/cs0023-25.cs @@ -0,0 +1,10 @@ +// CS0023: The `?' operator cannot be applied to operand of type `T' +// Line: 8 + +class C +{ + static void Foo (T t) where T : struct + { + var r = t?.ToString (); + } +} \ No newline at end of file diff --git a/mcs/mcs/codegen.cs b/mcs/mcs/codegen.cs index 7ab8f746f53..fba8f0bca29 100644 --- a/mcs/mcs/codegen.cs +++ b/mcs/mcs/codegen.cs @@ -1066,7 +1066,7 @@ public void EmitPredefined (EmitContext ec, MethodSpec method, Arguments Argumen var ie = new InstanceEmitter (instance_copy, IsAddressCall (instance_copy, call_op, method.DeclaringType)); if (Arguments == null) { - ie.EmitLoad (ec); + ie.EmitLoad (ec, true); } } else if (!InstanceExpressionOnStack) { var ie = new InstanceEmitter (InstanceExpression, IsAddressCall (InstanceExpression, call_op, method.DeclaringType)); @@ -1228,7 +1228,7 @@ public void Emit (EmitContext ec, bool conditionalAccess) instance_address = instance as LocalTemporary; if (instance_address == null) { - EmitLoad (ec); + EmitLoad (ec, false); ec.Emit (OpCodes.Dup); ec.EmitLoadFromPtr (instance.Type); @@ -1236,11 +1236,8 @@ public void Emit (EmitContext ec, bool conditionalAccess) } else { instance.Emit (ec); } - - if (instance.Type.Kind == MemberKind.TypeParameter) - ec.Emit (OpCodes.Box, instance.Type); } else { - EmitLoad (ec); + EmitLoad (ec, !conditionalAccess); if (conditionalAccess) { conditional_access_dup = !IsInexpensiveLoad (); @@ -1250,6 +1247,9 @@ public void Emit (EmitContext ec, bool conditionalAccess) } if (conditionalAccess) { + if (instance.Type.Kind == MemberKind.TypeParameter) + ec.Emit (OpCodes.Box, instance.Type); + ec.Emit (OpCodes.Brtrue_S, NullOperatorLabel); if (conditional_access_dup) @@ -1282,7 +1282,7 @@ public void Emit (EmitContext ec, bool conditionalAccess) } } - public void EmitLoad (EmitContext ec) + public void EmitLoad (EmitContext ec, bool boxInstance) { var instance_type = instance.Type; @@ -1313,8 +1313,9 @@ public void EmitLoad (EmitContext ec) instance.Emit (ec); // Only to make verifier happy - if (RequiresBoxing ()) + if (boxInstance && RequiresBoxing ()) { ec.Emit (OpCodes.Box, instance_type); + } } public TypeSpec GetStackType (EmitContext ec) diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index d8c1f6e2cc1..3143908b63a 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -457,6 +457,8 @@ protected static bool IsNullPropagatingValid (TypeSpec type) return false; case MemberKind.InternalCompilerType: return type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + case MemberKind.TypeParameter: + return !((TypeParameterSpec) type).IsValueType; default: return true; } diff --git a/mcs/tests/test-null-operator-010.cs b/mcs/tests/test-null-operator-010.cs new file mode 100644 index 00000000000..2d724034329 --- /dev/null +++ b/mcs/tests/test-null-operator-010.cs @@ -0,0 +1,41 @@ +using System; + +class Test +{ + static void Main () + { + Test_1 (""); + Test_1 (null); + + Test_2 (null); + Test_2 ("z"); + Test_2 (0); + Test_2 ((long?) -8); + + Test_3 (new int[1]); + Test_3 (new int[] { 5 }); + } + + static void Test_1 (T x) where T : class + { + x?.Call (); + } + + static void Test_2 (T x) + { + x?.Call (); + } + + static void Test_3 (T[] x) + { + x[0]?.Call (); + } +} + +static class Ext +{ + public static void Call (this T t) + { + Console.WriteLine (typeof (T)); + } +} diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 317922c0e82..4cd47f3ebe1 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -67710,6 +67710,30 @@ + + + + 79 + + + 22 + + + 21 + + + 28 + + + 7 + + + + + 17 + + + From f1ca57ebb381092c9e4bd5df0e19b2089acc2ca8 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 29 Sep 2014 16:44:12 +0200 Subject: [PATCH 270/543] [mcs] Don't consider loads from captured local cheap --- mcs/mcs/codegen.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mcs/mcs/codegen.cs b/mcs/mcs/codegen.cs index fba8f0bca29..53cc740a350 100644 --- a/mcs/mcs/codegen.cs +++ b/mcs/mcs/codegen.cs @@ -1343,6 +1343,9 @@ bool RequiresBoxing () return false; } + // + // Returns true for cheap race-free load, where we can avoid using dup + // bool IsInexpensiveLoad () { if (instance is Constant) @@ -1352,8 +1355,10 @@ bool IsInexpensiveLoad () return false; var vr = instance as VariableReference; - if (vr != null) - return !vr.IsRef; + if (vr != null) { + // Load from captured local would be racy without dup + return !vr.IsRef && !vr.IsHoisted; + } if (instance is LocalTemporary) return true; From 7968a8df1674a6e2aa8990faaca3c426efc2e279 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 29 Sep 2014 13:01:41 -0400 Subject: [PATCH 271/543] [x86] Reenable the no pushes code again. --- mono/mini/mini-x86.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/mini/mini-x86.h b/mono/mini/mini-x86.h index 05b977c547a..5ab5acc96c1 100644 --- a/mono/mini/mini-x86.h +++ b/mono/mini/mini-x86.h @@ -74,7 +74,7 @@ struct sigcontext { #endif /* HAVE_WORKING_SIGALTSTACK */ #endif /* !HOST_WIN32 */ -/* #define MONO_X86_NO_PUSHES 1 */ +#define MONO_X86_NO_PUSHES 1 #define MONO_ARCH_SUPPORT_TASKLETS 1 From 67297b2710d0fcacb760500927a5a345c0d9b262 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 29 Sep 2014 13:37:03 -0400 Subject: [PATCH 272/543] Fix a warning. --- mono/mini/mini.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 551cde41403..f015d6e75b8 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -4934,7 +4934,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl gboolean run_cctors = (flags & JIT_FLAG_RUN_CCTORS) ? 1 : 0; gboolean compile_aot = (flags & JIT_FLAG_AOT) ? 1 : 0; gboolean full_aot = (flags & JIT_FLAG_FULL_AOT) ? 1 : 0; +#ifdef ENABLE_LLVM gboolean llvm = (flags & JIT_FLAG_LLVM) ? 1 : 0; +#endif InterlockedIncrement (&mono_jit_stats.methods_compiled); if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION) From 2a4230fe3bc7b1de30f2e2b8c49671b8ac128626 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 29 Sep 2014 19:49:40 +0200 Subject: [PATCH 273/543] [facades] Add ComInterfaceType type forwarder --- .../Facades/System.Runtime.InteropServices/TypeForwarders.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/mcs/class/Facades/System.Runtime.InteropServices/TypeForwarders.cs b/mcs/class/Facades/System.Runtime.InteropServices/TypeForwarders.cs index 060d9292265..3fb4b16a435 100644 --- a/mcs/class/Facades/System.Runtime.InteropServices/TypeForwarders.cs +++ b/mcs/class/Facades/System.Runtime.InteropServices/TypeForwarders.cs @@ -40,6 +40,7 @@ [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.COMException))] [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.ComMemberType))] [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.ComSourceInterfacesAttribute))] +[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.ComInterfaceType))] [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.ComTypes.IStream))] [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.ComTypes.STATSTG))] [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.CriticalHandle))] From 06ba93fd0e217d098afb98bc694fe86d491fc7bd Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Sat, 13 Sep 2014 09:13:07 +0200 Subject: [PATCH 274/543] [sgen] Remove SGen fixed heap configuration. It's not well-tested, not widely used, we can surpass its speed with upcoming improvements and we won't put those into the fixed configuration because it's too much of a diversion. --- man/mono.1 | 12 +- mono/metadata/Makefile.am | 2 - mono/metadata/sgen-gc.c | 6 +- mono/metadata/sgen-marksweep-fixed-par.c | 25 --- mono/metadata/sgen-marksweep-fixed.c | 24 --- mono/metadata/sgen-marksweep.c | 213 +---------------------- 6 files changed, 9 insertions(+), 273 deletions(-) delete mode 100644 mono/metadata/sgen-marksweep-fixed-par.c delete mode 100644 mono/metadata/sgen-marksweep-fixed.c diff --git a/man/mono.1 b/man/mono.1 index 3d4bd54e989..f423e8855f3 100644 --- a/man/mono.1 +++ b/man/mono.1 @@ -1078,16 +1078,8 @@ program but will obviously use more memory. The default nursery size \fBmajor=\fIcollector\fR Specifies which major collector to use. Options are `marksweep' for the Mark&Sweep collector, `marksweep-conc' for concurrent Mark&Sweep, -`marksweep-par' for parallel Mark&Sweep, `marksweep-fixed' for -Mark&Sweep with a fixed heap, and `marksweep-fixed-par' for parallel -Mark&Sweep with a fixed heap. The Mark&Sweep collector is the default. -.TP -\fBmajor-heap-size=\fIsize\fR -Sets the size of the major heap (not including the large object space) -for the fixed-heap Mark&Sweep collector (i.e. `marksweep-fixed' and -`marksweep-fixed-par'). The size is in bytes, with optional suffixes -`k', `m' and `g' to specify kilo-, mega- and gigabytes, respectively. -The default is 512 megabytes. +and `marksweep-par' for parallel Mark&Sweep. The non-concurrent, +non-parallel Mark&Sweep collector is the default. .TP \fBsoft-heap-limit=\fIsize\fR Once the heap size gets larger than this size, ignore what the default diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index bfa08c4d39c..51a275283ba 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -222,9 +222,7 @@ sgen_sources = \ sgen-gc.c \ sgen-internal.c \ sgen-marksweep.c \ - sgen-marksweep-fixed.c \ sgen-marksweep-par.c \ - sgen-marksweep-fixed-par.c \ sgen-los.c \ sgen-protocol.c \ sgen-bridge.c \ diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 545d14f23bc..e752a49d456 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -4693,12 +4693,8 @@ mono_gc_base_init (void) if (!major_collector_opt || !strcmp (major_collector_opt, "marksweep")) { use_marksweep_major: sgen_marksweep_init (&major_collector); - } else if (!major_collector_opt || !strcmp (major_collector_opt, "marksweep-fixed")) { - sgen_marksweep_fixed_init (&major_collector); } else if (!major_collector_opt || !strcmp (major_collector_opt, "marksweep-par")) { sgen_marksweep_par_init (&major_collector); - } else if (!major_collector_opt || !strcmp (major_collector_opt, "marksweep-fixed-par")) { - sgen_marksweep_fixed_par_init (&major_collector); } else if (!major_collector_opt || !strcmp (major_collector_opt, "marksweep-conc")) { sgen_marksweep_conc_init (&major_collector); } else { @@ -4894,7 +4890,7 @@ mono_gc_base_init (void) fprintf (stderr, " max-heap-size=N (where N is an integer, possibly with a k, m or a g suffix)\n"); fprintf (stderr, " soft-heap-limit=n (where N is an integer, possibly with a k, m or a g suffix)\n"); fprintf (stderr, " nursery-size=N (where N is an integer, possibly with a k, m or a g suffix)\n"); - fprintf (stderr, " major=COLLECTOR (where COLLECTOR is `marksweep', `marksweep-conc', `marksweep-par', 'marksweep-fixed' or 'marksweep-fixed-par')\n"); + fprintf (stderr, " major=COLLECTOR (where COLLECTOR is `marksweep', `marksweep-conc', `marksweep-par')\n"); fprintf (stderr, " minor=COLLECTOR (where COLLECTOR is `simple' or `split')\n"); fprintf (stderr, " wbarrier=WBARRIER (where WBARRIER is `remset' or `cardtable')\n"); fprintf (stderr, " stack-mark=MARK-METHOD (where MARK-METHOD is 'precise' or 'conservative')\n"); diff --git a/mono/metadata/sgen-marksweep-fixed-par.c b/mono/metadata/sgen-marksweep-fixed-par.c deleted file mode 100644 index 7c03e5b1728..00000000000 --- a/mono/metadata/sgen-marksweep-fixed-par.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "config.h" - -#ifdef HAVE_SGEN_GC - -#ifndef DISABLE_SGEN_MAJOR_MARKSWEEP_FIXED_PAR - -#define SGEN_PARALLEL_MARK -#define FIXED_HEAP - -#include "sgen-marksweep.c" - -#else - -#include "metadata/sgen-gc.h" - -void -sgen_marksweep_fixed_par_init (SgenMajorCollector *collector) -{ - fprintf (stderr, "Error: Mono was configured using --enable-minimal=sgen_marksweep_fixed_par.\n"); - exit (1); -} - -#endif - -#endif diff --git a/mono/metadata/sgen-marksweep-fixed.c b/mono/metadata/sgen-marksweep-fixed.c deleted file mode 100644 index 3d08895bce7..00000000000 --- a/mono/metadata/sgen-marksweep-fixed.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "config.h" - -#ifdef HAVE_SGEN_GC - -#ifndef DISABLE_SGEN_MAJOR_MARKSWEEP_FIXED - -#define FIXED_HEAP - -#include "sgen-marksweep.c" - -#else - -#include "metadata/sgen-gc.h" - -void -sgen_marksweep_fixed_init (SgenMajorCollector *collector) -{ - fprintf (stderr, "Error: Mono was configured using --enable-minimal=sgen_marksweep_fixed.\n"); - exit (1); -} - -#endif - -#endif diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index d3093385805..38b61d8a274 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -41,7 +41,7 @@ #include "metadata/sgen-layout-stats.h" #include "metadata/gc-internal.h" -#if !defined(SGEN_PARALLEL_MARK) && !defined(FIXED_HEAP) +#if !defined(SGEN_PARALLEL_MARK) #define SGEN_HAVE_CONCURRENT_MARK #endif @@ -50,10 +50,6 @@ #define MAJOR_SECTION_SIZE MS_BLOCK_SIZE #define CARDS_PER_BLOCK (MS_BLOCK_SIZE / CARD_SIZE_IN_BYTES) -#ifdef FIXED_HEAP -#define MS_DEFAULT_HEAP_NUM_BLOCKS (32 * 1024) /* 512 MB */ -#endif - /* * Don't allocate single blocks, but alloc a contingent of this many * blocks in one swoop. This must be a power of two. @@ -65,11 +61,7 @@ * of a block is the MSBlockHeader, then opional padding, then come * the objects, so this must be >= sizeof (MSBlockHeader). */ -#ifdef FIXED_HEAP -#define MS_BLOCK_SKIP 0 -#else #define MS_BLOCK_SKIP 16 -#endif #define MS_BLOCK_FREE (MS_BLOCK_SIZE - MS_BLOCK_SKIP) @@ -89,10 +81,6 @@ struct _MSBlockInfo { unsigned int has_pinned : 1; /* means cannot evacuate */ unsigned int is_to_space : 1; unsigned int swept : 1; -#ifdef FIXED_HEAP - unsigned int used : 1; - unsigned int zeroed : 1; -#endif MSBlockInfo *next; char *block; void **free_list; @@ -104,31 +92,15 @@ struct _MSBlockInfo { mword mark_words [MS_NUM_MARK_WORDS]; }; -#ifdef FIXED_HEAP -static mword ms_heap_num_blocks = MS_DEFAULT_HEAP_NUM_BLOCKS; - -static char *ms_heap_start; -static char *ms_heap_end; - -#define MS_PTR_IN_SMALL_MAJOR_HEAP(p) ((char*)(p) >= ms_heap_start && (char*)(p) < ms_heap_end) - -/* array of all all block infos in the system */ -static MSBlockInfo *block_infos; -#endif - #define MS_BLOCK_OBJ(b,i) ((b)->block + MS_BLOCK_SKIP + (b)->obj_size * (i)) #define MS_BLOCK_OBJ_FOR_SIZE(b,i,obj_size) ((b)->block + MS_BLOCK_SKIP + (obj_size) * (i)) #define MS_BLOCK_DATA_FOR_OBJ(o) ((char*)((mword)(o) & ~(mword)(MS_BLOCK_SIZE - 1))) -#ifdef FIXED_HEAP -#define MS_BLOCK_FOR_OBJ(o) (&block_infos [(mword)((char*)(o) - ms_heap_start) >> MS_BLOCK_SIZE_SHIFT]) -#else typedef struct { MSBlockInfo *info; } MSBlockHeader; #define MS_BLOCK_FOR_OBJ(o) (((MSBlockHeader*)MS_BLOCK_DATA_FOR_OBJ ((o)))->info) -#endif /* object index will always be small */ #define MS_BLOCK_OBJ_INDEX(o,b) ((int)(((char*)(o) - ((b)->block + MS_BLOCK_SKIP)) / (b)->obj_size)) @@ -205,14 +177,9 @@ static gboolean concurrent_mark; /* all allocated blocks in the system */ static MSBlockInfo *all_blocks; -#ifdef FIXED_HEAP -/* non-allocated block free-list */ -static MSBlockInfo *empty_blocks = NULL; -#else /* non-allocated block free-list */ static void *empty_blocks = NULL; static size_t num_empty_blocks = 0; -#endif #define FOREACH_BLOCK(bl) for ((bl) = all_blocks; (bl); (bl) = (bl)->next) { #define END_FOREACH_BLOCK } @@ -279,40 +246,6 @@ ms_find_block_obj_size_index (size_t size) fast_block_obj_size_indexes [((s)+7)>>3] : \ ms_find_block_obj_size_index ((s))) -#ifdef FIXED_HEAP -static void* -major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits) -{ - char *nursery_start; - mword major_heap_size = ms_heap_num_blocks * MS_BLOCK_SIZE; - mword alloc_size = nursery_size + major_heap_size; - mword i; - - g_assert (ms_heap_num_blocks > 0); - g_assert (nursery_size % MS_BLOCK_SIZE == 0); - if (nursery_align) - g_assert (nursery_align % MS_BLOCK_SIZE == 0); - - nursery_start = sgen_alloc_os_memory_aligned (alloc_size, nursery_align ? nursery_align : MS_BLOCK_SIZE, SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE, "heap"); - ms_heap_start = nursery_start + nursery_size; - ms_heap_end = ms_heap_start + major_heap_size; - - block_infos = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo) * ms_heap_num_blocks, INTERNAL_MEM_MS_BLOCK_INFO, TRUE); - - for (i = 0; i < ms_heap_num_blocks; ++i) { - block_infos [i].block = ms_heap_start + i * MS_BLOCK_SIZE; - if (i < ms_heap_num_blocks - 1) - block_infos [i].next_free = &block_infos [i + 1]; - else - block_infos [i].next_free = NULL; - block_infos [i].zeroed = TRUE; - } - - empty_blocks = &block_infos [0]; - - return nursery_start; -} -#else static void* major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits) { @@ -324,7 +257,6 @@ major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits) return start; } -#endif static void update_heap_boundaries_for_block (MSBlockInfo *block) @@ -332,36 +264,6 @@ update_heap_boundaries_for_block (MSBlockInfo *block) sgen_update_heap_boundaries ((mword)block->block, (mword)block->block + MS_BLOCK_SIZE); } -#ifdef FIXED_HEAP -static MSBlockInfo* -ms_get_empty_block (void) -{ - MSBlockInfo *block; - - g_assert (empty_blocks); - - do { - block = empty_blocks; - } while (SGEN_CAS_PTR ((gpointer*)&empty_blocks, block->next_free, block) != block); - - block->used = TRUE; - - if (!block->zeroed) - memset (block->block, 0, MS_BLOCK_SIZE); - - return block; -} - -static void -ms_free_block (MSBlockInfo *block) -{ - block->next_free = empty_blocks; - empty_blocks = block; - block->used = FALSE; - block->zeroed = FALSE; - sgen_memgov_release_space (MS_BLOCK_SIZE, SPACE_MAJOR); -} -#else static void* ms_get_empty_block (void) { @@ -440,7 +342,6 @@ ms_free_block (void *block) SGEN_ATOMIC_ADD_P (num_empty_blocks, 1); } -#endif //#define MARKSWEEP_CONSISTENCY_CHECK @@ -459,11 +360,6 @@ check_block_free_list (MSBlockInfo *block, int size, gboolean pinned) if (block->swept) g_assert (block->free_list); -#ifdef FIXED_HEAP - /* the block must not be in the empty_blocks list */ - for (b = empty_blocks; b; b = b->next_free) - g_assert (b != block); -#endif /* the block must be in the all_blocks list */ for (b = all_blocks; b; b = b->next) { if (b == block) @@ -476,13 +372,11 @@ check_block_free_list (MSBlockInfo *block, int size, gboolean pinned) static void check_empty_blocks (void) { -#ifndef FIXED_HEAP void *p; size_t i = 0; for (p = empty_blocks; p; p = *(void**)p) ++i; g_assert (i == num_empty_blocks); -#endif } static void @@ -497,10 +391,8 @@ consistency_check (void) int num_free = 0; void **free; -#ifndef FIXED_HEAP /* check block header */ g_assert (((MSBlockHeader*)block->block)->info == block); -#endif /* count number of free slots */ for (i = 0; i < count; ++i) { @@ -543,9 +435,7 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) #ifdef SGEN_PARALLEL_MARK MSBlockInfo *next; #endif -#ifndef FIXED_HEAP MSBlockHeader *header; -#endif MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references); char *obj_start; int i; @@ -553,11 +443,7 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) if (!sgen_memgov_try_alloc_space (MS_BLOCK_SIZE, SPACE_MAJOR)) return FALSE; -#ifdef FIXED_HEAP - info = ms_get_empty_block (); -#else info = sgen_alloc_internal (INTERNAL_MEM_MS_BLOCK_INFO); -#endif SGEN_ASSERT (9, count >= 2, "block with %d objects, it must hold at least 2", count); @@ -574,12 +460,10 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) */ info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD); info->swept = 1; -#ifndef FIXED_HEAP info->block = ms_get_empty_block (); header = (MSBlockHeader*) info->block; header->info = info; -#endif #ifdef SGEN_HAVE_CONCURRENT_MARK info->cardtable_mod_union = NULL; #endif @@ -859,24 +743,16 @@ major_is_object_live (char *obj) { MSBlockInfo *block; int word, bit; -#ifndef FIXED_HEAP mword objsize; -#endif if (sgen_ptr_in_nursery (obj)) return FALSE; -#ifdef FIXED_HEAP - /* LOS */ - if (!MS_PTR_IN_SMALL_MAJOR_HEAP (obj)) - return FALSE; -#else objsize = SGEN_ALIGN_UP (sgen_safe_object_get_size ((MonoObject*)obj)); /* LOS */ if (objsize > SGEN_MAX_SMALL_OBJ_SIZE) return FALSE; -#endif /* now we know it's in a major block */ block = MS_BLOCK_FOR_OBJ (obj); @@ -1224,9 +1100,6 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) HEAVY_STAT (++stat_slots_allocated_in_vain); } } else { -#ifdef FIXED_HEAP - if (MS_PTR_IN_SMALL_MAJOR_HEAP (obj)) -#else mword vtable_word = *(mword*)obj; vt = (MonoVTable*)(vtable_word & ~SGEN_VTABLE_BITS_MASK); @@ -1237,9 +1110,7 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) } objsize = SGEN_ALIGN_UP (sgen_par_object_get_size (vt, (MonoObject*)obj)); - if (objsize <= SGEN_MAX_SMALL_OBJ_SIZE) -#endif - { + if (objsize <= SGEN_MAX_SMALL_OBJ_SIZE) { int size_index; block = MS_BLOCK_FOR_OBJ (obj); @@ -1249,18 +1120,6 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) if (block->is_to_space) return; -#ifdef FIXED_HEAP - { - mword vtable_word = *(mword*)obj; - vt = (MonoVTable*)(vtable_word & ~SGEN_VTABLE_BITS_MASK); - - if (vtable_word & SGEN_FORWARDED_BIT) { - *ptr = (void*)vt; - return; - } - } -#endif - HEAVY_STAT (++stat_major_objects_evacuated); goto do_copy_object; } @@ -1269,10 +1128,7 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) } else { LOSObject *bigobj = sgen_los_header_for_object (obj); mword size_word = bigobj->size; -#ifdef FIXED_HEAP - mword vtable_word = *(mword*)obj; - vt = (MonoVTable*)(vtable_word & ~SGEN_VTABLE_BITS_MASK); -#endif + if (size_word & 1) return; binary_protocol_pin (obj, vt, sgen_safe_object_get_size ((MonoObject*)obj)); @@ -1293,16 +1149,11 @@ major_copy_or_mark_object_concurrent (void **ptr, void *obj, SgenGrayQueue *queu g_assert (!SGEN_OBJECT_IS_FORWARDED (obj)); if (!sgen_ptr_in_nursery (obj)) { -#ifdef FIXED_HEAP - if (MS_PTR_IN_SMALL_MAJOR_HEAP (obj)) -#else mword objsize; objsize = SGEN_ALIGN_UP (sgen_safe_object_get_size ((MonoObject*)obj)); - if (objsize <= SGEN_MAX_SMALL_OBJ_SIZE) -#endif - { + if (objsize <= SGEN_MAX_SMALL_OBJ_SIZE) { MSBlockInfo *block = MS_BLOCK_FOR_OBJ (obj); MS_MARK_OBJECT_AND_ENQUEUE (obj, block, queue); } else { @@ -1390,9 +1241,6 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) } } else { char *forwarded; -#ifdef FIXED_HEAP - if (MS_PTR_IN_SMALL_MAJOR_HEAP (obj)) -#else mword objsize; /* @@ -1410,9 +1258,7 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) objsize = SGEN_ALIGN_UP (sgen_safe_object_get_size ((MonoObject*)obj)); - if (objsize <= SGEN_MAX_SMALL_OBJ_SIZE) -#endif - { + if (objsize <= SGEN_MAX_SMALL_OBJ_SIZE) { int size_index; gboolean evacuate; @@ -1420,20 +1266,6 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) size_index = block->obj_size_index; evacuate = evacuate_block_obj_sizes [size_index]; -#ifdef FIXED_HEAP - /* - * We could also check for !block->has_pinned - * here, but it would only make an uncommon case - * faster, namely objects that are in blocks - * whose slot sizes are evacuated but which have - * pinned objects. - */ - if (evacuate && (forwarded = SGEN_OBJECT_IS_FORWARDED (obj))) { - *ptr = forwarded; - return; - } -#endif - if (evacuate && !block->has_pinned) { g_assert (!SGEN_OBJECT_IS_PINNED (obj)); if (block->is_to_space) @@ -1713,13 +1545,8 @@ ms_sweep (void) *iter = block->next; binary_protocol_empty (MS_BLOCK_OBJ (block, 0), (char*)MS_BLOCK_OBJ (block, count) - (char*)MS_BLOCK_OBJ (block, 0)); -#ifdef FIXED_HEAP - ms_free_block (block); -#else ms_free_block (block->block); - sgen_free_internal (block, INTERNAL_MEM_MS_BLOCK_INFO); -#endif --num_major_sections; } @@ -1891,7 +1718,7 @@ major_finish_major_collection (void) { } -#if !defined(FIXED_HEAP) && SIZEOF_VOID_P != 8 +#if SIZEOF_VOID_P != 8 static int compare_pointers (const void *va, const void *vb) { char *a = *(char**)va, *b = *(char**)vb; @@ -1906,7 +1733,6 @@ compare_pointers (const void *va, const void *vb) { static void major_have_computer_minor_collection_allowance (void) { -#ifndef FIXED_HEAP size_t section_reserve = sgen_get_minor_collection_allowance () / MS_BLOCK_SIZE; g_assert (have_swept); @@ -2056,7 +1882,6 @@ major_have_computer_minor_collection_allowance (void) ++stat_major_blocks_freed_individual; #endif } -#endif } static void @@ -2117,17 +1942,6 @@ get_num_major_sections (void) static gboolean major_handle_gc_param (const char *opt) { -#ifdef FIXED_HEAP - if (g_str_has_prefix (opt, "major-heap-size=")) { - const char *arg = strchr (opt, '=') + 1; - size_t size; - if (!mono_gc_parse_environment_string_extract_number (arg, &size)) - return FALSE; - ms_heap_num_blocks = (size + MS_BLOCK_SIZE - 1) / MS_BLOCK_SIZE; - g_assert (ms_heap_num_blocks > 0); - return TRUE; - } else -#endif if (g_str_has_prefix (opt, "evacuation-threshold=")) { const char *arg = strchr (opt, '=') + 1; int percentage = atoi (arg); @@ -2153,9 +1967,6 @@ major_print_gc_param_usage (void) { fprintf (stderr, "" -#ifdef FIXED_HEAP - " major-heap-size=N (where N is an integer, possibly with a k, m or a g suffix)\n" -#endif " evacuation-threshold=P (where P is a percentage, an integer in 0-100)\n" " (no-)lazy-sweep\n" ); @@ -2501,28 +2312,16 @@ static void sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurrent) #else // SGEN_HAVE_CONCURRENT_MARK #ifdef SGEN_PARALLEL_MARK -#ifdef FIXED_HEAP -void -sgen_marksweep_fixed_par_init (SgenMajorCollector *collector) -#else // FIXED_HEAP void sgen_marksweep_par_init (SgenMajorCollector *collector) -#endif // FIXED_HEAP #else // SGEN_PARALLEL_MARK -#ifdef FIXED_HEAP -void -sgen_marksweep_fixed_init (SgenMajorCollector *collector) -#else // FIXED_HEAP #error unknown configuration -#endif // FIXED_HEAP #endif // SGEN_PARALLEL_MARK #endif // SGEN_HAVE_CONCURRENT_MARK { int i; -#ifndef FIXED_HEAP sgen_register_fixed_internal_mem_type (INTERNAL_MEM_MS_BLOCK_INFO, sizeof (MSBlockInfo)); -#endif num_block_obj_sizes = ms_calculate_block_obj_sizes (MS_BLOCK_OBJ_SIZE_FACTOR, NULL); block_obj_sizes = sgen_alloc_internal_dynamic (sizeof (int) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE); From 8a005b8290ca0a489252f57e61c4a282a61b3998 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Sat, 13 Sep 2014 09:47:06 +0200 Subject: [PATCH 275/543] [sgen] Remove parallel collector. This was almost completely untested and performance was erratic. --- man/mono.1 | 9 +- mono/metadata/Makefile.am | 1 - mono/metadata/sgen-gc.c | 127 ++-------- mono/metadata/sgen-gc.h | 6 - mono/metadata/sgen-marksweep-par.c | 24 -- mono/metadata/sgen-marksweep.c | 333 +------------------------ mono/metadata/sgen-minor-copy-object.h | 83 ------ mono/metadata/sgen-minor-scan-object.h | 57 ----- mono/metadata/sgen-simple-nursery.c | 8 - mono/metadata/sgen-split-nursery.c | 93 ------- mono/metadata/sgen-workers.c | 10 +- mono/tests/Makefile.am | 3 - 12 files changed, 28 insertions(+), 726 deletions(-) delete mode 100644 mono/metadata/sgen-marksweep-par.c diff --git a/man/mono.1 b/man/mono.1 index f423e8855f3..d058031ed16 100644 --- a/man/mono.1 +++ b/man/mono.1 @@ -1075,11 +1075,10 @@ first generation (of two). A larger nursery will usually speed up the program but will obviously use more memory. The default nursery size 4 MB. .TP -\fBmajor=\fIcollector\fR -Specifies which major collector to use. Options are `marksweep' for -the Mark&Sweep collector, `marksweep-conc' for concurrent Mark&Sweep, -and `marksweep-par' for parallel Mark&Sweep. The non-concurrent, -non-parallel Mark&Sweep collector is the default. +\fBmajor=\fIcollector\fR Specifies which major collector to use. +Options are `marksweep' for the Mark&Sweep collector, and +`marksweep-conc' for concurrent Mark&Sweep. The non-concurrent +Mark&Sweep collector is the default. .TP \fBsoft-heap-limit=\fIsize\fR Once the heap size gets larger than this size, ignore what the default diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index 51a275283ba..7a744e03bdf 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -222,7 +222,6 @@ sgen_sources = \ sgen-gc.c \ sgen-internal.c \ sgen-marksweep.c \ - sgen-marksweep-par.c \ sgen-los.c \ sgen-protocol.c \ sgen-bridge.c \ diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index e752a49d456..3d191e7537b 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -285,7 +285,6 @@ static gboolean do_scan_starts_check = FALSE; * GC.Collect(). */ static gboolean allow_synchronous_major = TRUE; -static gboolean nursery_collection_is_parallel = FALSE; static gboolean disable_minor_collections = FALSE; static gboolean disable_major_collections = FALSE; gboolean do_pin_stats = FALSE; @@ -603,8 +602,7 @@ gray_queue_redirect (SgenGrayQueue *queue) } if (wake) { - g_assert (concurrent_collection_in_progress || - (current_collection_generation == GENERATION_OLD && major_collector.is_parallel)); + g_assert (concurrent_collection_in_progress); if (sgen_workers_have_started ()) { sgen_workers_wake_up_all (); } else { @@ -1082,19 +1080,12 @@ sgen_pin_object (void *object, GrayQueue *queue) { g_assert (!concurrent_collection_in_progress); - if (sgen_collection_is_parallel ()) { - LOCK_PIN_QUEUE; - /*object arrives pinned*/ - sgen_pin_stage_ptr (object); - ++objects_pinned ; - UNLOCK_PIN_QUEUE; - } else { - SGEN_PIN_OBJECT (object); - sgen_pin_stage_ptr (object); - ++objects_pinned; - if (G_UNLIKELY (do_pin_stats)) - sgen_pin_stats_register_object (object, safe_object_get_size (object)); - } + SGEN_PIN_OBJECT (object); + sgen_pin_stage_ptr (object); + ++objects_pinned; + if (G_UNLIKELY (do_pin_stats)) + sgen_pin_stats_register_object (object, safe_object_get_size (object)); + GRAY_OBJECT_ENQUEUE (queue, object); binary_protocol_pin (object, (gpointer)LOAD_VTABLE (object), safe_object_get_size (object)); @@ -1905,9 +1896,6 @@ sgen_register_moved_object (void *obj, void *destination) { g_assert (mono_profiler_events & MONO_PROFILE_GC_MOVES); - /* FIXME: handle this for parallel collector */ - g_assert (!sgen_collection_is_parallel ()); - if (moved_objects_idx == MOVED_OBJECTS_NUM) { mono_profiler_gc_moves (moved_objects, moved_objects_idx); moved_objects_idx = 0; @@ -1998,19 +1986,6 @@ sgen_set_pinned_from_failed_allocation (mword objsize) bytes_pinned_from_failed_allocation += objsize; } -gboolean -sgen_collection_is_parallel (void) -{ - switch (current_collection_generation) { - case GENERATION_NURSERY: - return nursery_collection_is_parallel; - case GENERATION_OLD: - return major_collector.is_parallel; - default: - g_error ("Invalid current generation %d", current_collection_generation); - } -} - gboolean sgen_collection_is_concurrent (void) { @@ -2198,7 +2173,7 @@ check_nursery_is_clean (void) static void init_gray_queue (void) { - if (sgen_collection_is_parallel () || sgen_collection_is_concurrent ()) { + if (sgen_collection_is_concurrent ()) { sgen_workers_init_distribute_gray_queue (); sgen_gray_object_queue_init_with_alloc_prepare (&gray_queue, NULL, gray_queue_redirect, sgen_workers_get_distribute_section_gray_queue ()); @@ -2249,11 +2224,8 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) #endif current_collection_generation = GENERATION_NURSERY; - if (sgen_collection_is_parallel ()) - current_object_ops = sgen_minor_collector.parallel_ops; - else - current_object_ops = sgen_minor_collector.serial_ops; - + current_object_ops = sgen_minor_collector.serial_ops; + reset_pinned_from_failed_allocation (); check_scan_starts (); @@ -2340,12 +2312,10 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) MONO_GC_CHECKPOINT_4 (GENERATION_NURSERY); - if (!sgen_collection_is_parallel ()) { - ctx.scan_func = current_object_ops.scan_object; - ctx.copy_func = NULL; - ctx.queue = &gray_queue; - sgen_drain_gray_stack (-1, ctx); - } + ctx.scan_func = current_object_ops.scan_object; + ctx.copy_func = NULL; + ctx.queue = &gray_queue; + sgen_drain_gray_stack (-1, ctx); if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS) report_registered_roots (); @@ -2390,10 +2360,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) MONO_GC_CHECKPOINT_7 (GENERATION_NURSERY); - g_assert (!sgen_collection_is_parallel () && !sgen_collection_is_concurrent ()); - - if (sgen_collection_is_parallel () || sgen_collection_is_concurrent ()) - g_assert (sgen_gray_object_queue_is_empty (&gray_queue)); + g_assert (!sgen_collection_is_concurrent ()); /* Scan the list of objects ready for finalization. If */ sfejd_fin_ready = sgen_alloc_internal_dynamic (sizeof (ScanFinalizerEntriesJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE); @@ -2696,11 +2663,6 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, gboolean finish_up_con main_gc_thread = mono_native_thread_self (); #endif - if (!concurrent_collection_in_progress && major_collector.is_parallel) { - sgen_workers_start_all_workers (); - sgen_workers_start_marking (); - } - if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS) report_registered_roots (); TV_GETTIME (atv); @@ -2829,7 +2791,7 @@ wait_for_workers_to_finish (void) static void join_workers (void) { - if (concurrent_collection_in_progress || major_collector.is_parallel) { + if (concurrent_collection_in_progress) { gray_queue_redirect (&gray_queue); sgen_workers_join (); } @@ -2850,7 +2812,7 @@ major_finish_collection (const char *reason, size_t old_next_pin_slot, gboolean TV_GETTIME (btv); - if (concurrent_collection_in_progress || major_collector.is_parallel) + if (concurrent_collection_in_progress) join_workers (); if (concurrent_collection_in_progress) { @@ -4573,7 +4535,6 @@ mono_gc_base_init (void) char *minor_collector_opt = NULL; size_t max_heap = 0; size_t soft_limit = 0; - int num_workers; int result; int dummy; gboolean debug_print_allowance = FALSE; @@ -4693,8 +4654,6 @@ mono_gc_base_init (void) if (!major_collector_opt || !strcmp (major_collector_opt, "marksweep")) { use_marksweep_major: sgen_marksweep_init (&major_collector); - } else if (!major_collector_opt || !strcmp (major_collector_opt, "marksweep-par")) { - sgen_marksweep_par_init (&major_collector); } else if (!major_collector_opt || !strcmp (major_collector_opt, "marksweep-conc")) { sgen_marksweep_conc_init (&major_collector); } else { @@ -4702,16 +4661,6 @@ mono_gc_base_init (void) goto use_marksweep_major; } - if (have_split_nursery && major_collector.is_parallel) { - sgen_env_var_error (MONO_GC_PARAMS_NAME, "Disabling split minor collector.", "`minor=split` is not supported with the parallel collector yet."); - have_split_nursery = FALSE; - } - - num_workers = mono_cpu_count (); - g_assert (num_workers > 0); - if (num_workers > 16) - num_workers = 16; - ///* Keep this the default for now */ /* Precise marking is broken on all supported targets. Disable until fixed. */ conservative_stack_mark = TRUE; @@ -4753,26 +4702,6 @@ mono_gc_base_init (void) } continue; } - if (g_str_has_prefix (opt, "workers=")) { - long val; - char *endptr; - if (!major_collector.is_parallel) { - sgen_env_var_error (MONO_GC_PARAMS_NAME, "Ignoring.", "The `workers` option can only be used for parallel collectors."); - continue; - } - opt = strchr (opt, '=') + 1; - val = strtol (opt, &endptr, 10); - if (!*opt || *endptr) { - sgen_env_var_error (MONO_GC_PARAMS_NAME, "Ignoring.", "Cannot parse the `workers` option value."); - continue; - } - if (val <= 0 || val > 16) { - sgen_env_var_error (MONO_GC_PARAMS_NAME, "Using default value.", "The number of `workers` must be in the range 1 to 16."); - continue; - } - num_workers = (int)val; - continue; - } if (g_str_has_prefix (opt, "stack-mark=")) { opt = strchr (opt, '=') + 1; if (!strcmp (opt, "precise")) { @@ -4863,10 +4792,6 @@ mono_gc_base_init (void) } if (!strcmp (opt, "cementing")) { - if (major_collector.is_parallel) { - sgen_env_var_error (MONO_GC_PARAMS_NAME, "Ignoring.", "`cementing` is not supported for the parallel major collector."); - continue; - } cement_enabled = TRUE; continue; } @@ -4911,12 +4836,8 @@ mono_gc_base_init (void) g_strfreev (opts); } - if (major_collector.is_parallel) { - cement_enabled = FALSE; - sgen_workers_init (num_workers); - } else if (major_collector.is_concurrent) { + if (major_collector.is_concurrent) sgen_workers_init (1); - } if (major_collector_opt) g_free (major_collector_opt); @@ -5071,18 +4992,6 @@ mono_gc_base_init (void) g_strfreev (opts); } - if (major_collector.is_parallel) { - if (heap_dump_file) { - sgen_env_var_error (MONO_GC_DEBUG_NAME, "Disabling.", "Cannot do `heap-dump` with the parallel collector."); - fclose (heap_dump_file); - heap_dump_file = NULL; - } - if (do_pin_stats) { - sgen_env_var_error (MONO_GC_DEBUG_NAME, "Disabling.", "`print-pinning` is not supported with the parallel collector."); - do_pin_stats = FALSE; - } - } - if (major_collector.post_param_init) major_collector.post_param_init (&major_collector); diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 41a7151ba29..cc5daa551ba 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -537,7 +537,6 @@ void sgen_sort_addresses (void **array, size_t size) MONO_INTERNAL; void sgen_add_to_global_remset (gpointer ptr, gpointer obj) MONO_INTERNAL; int sgen_get_current_collection_generation (void) MONO_INTERNAL; -gboolean sgen_collection_is_parallel (void) MONO_INTERNAL; gboolean sgen_collection_is_concurrent (void) MONO_INTERNAL; gboolean sgen_concurrent_collection_in_progress (void) MONO_INTERNAL; @@ -634,10 +633,8 @@ typedef struct { gboolean is_split; char* (*alloc_for_promotion) (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references); - char* (*par_alloc_for_promotion) (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references); SgenObjectOperations serial_ops; - SgenObjectOperations parallel_ops; void (*prepare_to_space) (char *to_space_bitmap, size_t space_bitmap_size); void (*clear_fragments) (void); @@ -671,7 +668,6 @@ typedef enum { typedef struct _SgenMajorCollector SgenMajorCollector; struct _SgenMajorCollector { size_t section_size; - gboolean is_parallel; gboolean is_concurrent; gboolean supports_cardtable; gboolean sweeps_lazily; @@ -697,7 +693,6 @@ struct _SgenMajorCollector { SgenObjectOperations major_concurrent_ops; void* (*alloc_object) (MonoVTable *vtable, size_t size, gboolean has_references); - void* (*par_alloc_object) (MonoVTable *vtable, size_t size, gboolean has_references); void (*free_pinned_object) (char *obj, size_t size); void (*iterate_objects) (IterateObjectsFlags flags, IterateObjectCallbackFunc callback, void *data); void (*free_non_pinned_object) (char *obj, size_t size); @@ -1000,7 +995,6 @@ void sgen_nursery_alloc_prepare_for_minor (void) MONO_INTERNAL; void sgen_nursery_alloc_prepare_for_major (void) MONO_INTERNAL; char* sgen_alloc_for_promotion (char *obj, size_t objsize, gboolean has_references) MONO_INTERNAL; -char* sgen_par_alloc_for_promotion (char *obj, size_t objsize, gboolean has_references) MONO_INTERNAL; /* TLS Data */ diff --git a/mono/metadata/sgen-marksweep-par.c b/mono/metadata/sgen-marksweep-par.c deleted file mode 100644 index 5bc7805c870..00000000000 --- a/mono/metadata/sgen-marksweep-par.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "config.h" - -#ifdef HAVE_SGEN_GC - -#ifndef DISABLE_SGEN_MAJOR_MARKSWEEP_PAR - -#define SGEN_PARALLEL_MARK - -#include "sgen-marksweep.c" - -#else - -#include "metadata/sgen-gc.h" - -void -sgen_marksweep_par_init (SgenMajorCollector *collector) -{ - fprintf (stderr, "Error: Mono was configured using --enable-minimal=sgen_marksweep_par.\n"); - exit (1); -} - -#endif /* DISABLE_SGEN_MAJOR_MARKSWEEP_PAR */ - -#endif diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index 38b61d8a274..740cfab973f 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -41,9 +41,7 @@ #include "metadata/sgen-layout-stats.h" #include "metadata/gc-internal.h" -#if !defined(SGEN_PARALLEL_MARK) #define SGEN_HAVE_CONCURRENT_MARK -#endif #define MS_BLOCK_SIZE (16*1024) #define MS_BLOCK_SIZE_SHIFT 14 @@ -154,12 +152,6 @@ static int fast_block_obj_size_indexes [MS_NUM_FAST_BLOCK_OBJ_SIZE_INDEXES]; #define MS_BLOCK_TYPE_MAX 4 -#ifdef SGEN_PARALLEL_MARK -static LOCK_DECLARE (ms_block_list_mutex); -#define LOCK_MS_BLOCK_LIST mono_mutex_lock (&ms_block_list_mutex) -#define UNLOCK_MS_BLOCK_LIST mono_mutex_unlock (&ms_block_list_mutex) -#endif - static gboolean *evacuate_block_obj_sizes; static float evacuation_threshold = 0.666f; #ifdef SGEN_HAVE_CONCURRENT_MARK @@ -188,14 +180,6 @@ static size_t num_major_sections = 0; /* one free block list for each block object size */ static MSBlockInfo **free_block_lists [MS_BLOCK_TYPE_MAX]; -#ifdef SGEN_PARALLEL_MARK -#ifdef HAVE_KW_THREAD -static __thread MSBlockInfo ***workers_free_block_lists; -#else -static MonoNativeTlsKey workers_free_block_lists_key; -#endif -#endif - static long long stat_major_blocks_alloced = 0; static long long stat_major_blocks_freed = 0; static long long stat_major_blocks_lazy_swept = 0; @@ -231,15 +215,6 @@ ms_find_block_obj_size_index (size_t size) #define FREE_BLOCKS_FROM(lists,p,r) (lists [((p) ? MS_BLOCK_FLAG_PINNED : 0) | ((r) ? MS_BLOCK_FLAG_REFS : 0)]) #define FREE_BLOCKS(p,r) (FREE_BLOCKS_FROM (free_block_lists, (p), (r))) -#ifdef SGEN_PARALLEL_MARK -#ifdef HAVE_KW_THREAD -#define FREE_BLOCKS_LOCAL(p,r) (FREE_BLOCKS_FROM (workers_free_block_lists, (p), (r))) -#else -#define FREE_BLOCKS_LOCAL(p,r) (FREE_BLOCKS_FROM (((MSBlockInfo***)(mono_native_tls_get_value (workers_free_block_lists_key))), (p), (r))) -#endif -#else -//#define FREE_BLOCKS_LOCAL(p,r) (FREE_BLOCKS_FROM (free_block_lists, (p), (r))) -#endif #define MS_BLOCK_OBJ_SIZE_INDEX(s) \ (((s)+7)>>3 < MS_NUM_FAST_BLOCK_OBJ_SIZE_INDEXES ? \ @@ -432,9 +407,6 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) int size = block_obj_sizes [size_index]; int count = MS_BLOCK_FREE / size; MSBlockInfo *info; -#ifdef SGEN_PARALLEL_MARK - MSBlockInfo *next; -#endif MSBlockHeader *header; MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references); char *obj_start; @@ -482,21 +454,11 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) /* the last one */ *(void**)obj_start = NULL; -#ifdef SGEN_PARALLEL_MARK - do { - next = info->next_free = free_blocks [size_index]; - } while (SGEN_CAS_PTR ((void**)&free_blocks [size_index], info, next) != next); - - do { - next = info->next = all_blocks; - } while (SGEN_CAS_PTR ((void**)&all_blocks, info, next) != next); -#else info->next_free = free_blocks [size_index]; free_blocks [size_index] = info; info->next = all_blocks; all_blocks = info; -#endif ++num_major_sections; return TRUE; @@ -540,86 +502,6 @@ unlink_slot_from_free_list_uncontested (MSBlockInfo **free_blocks, int size_inde return obj; } -#ifdef SGEN_PARALLEL_MARK -static gboolean -try_remove_block_from_free_list (MSBlockInfo *block, MSBlockInfo **free_blocks, int size_index) -{ - /* - * No more free slots in the block, so try to free the block. - * Don't try again if we don't succeed - another thread will - * already have done it. - */ - MSBlockInfo *next_block = block->next_free; - if (SGEN_CAS_PTR ((void**)&free_blocks [size_index], next_block, block) == block) { - /* - void *old = SGEN_CAS_PTR ((void**)&block->next_free, NULL, next_block); - g_assert (old == next_block); - */ - block->next_free = NULL; - return TRUE; - } - return FALSE; -} - -static void* -alloc_obj_par (MonoVTable *vtable, int size, gboolean pinned, gboolean has_references) -{ - int size_index = MS_BLOCK_OBJ_SIZE_INDEX (size); - MSBlockInfo **free_blocks_local = FREE_BLOCKS_LOCAL (pinned, has_references); - MSBlockInfo *block; - void *obj; - -#ifdef SGEN_HAVE_CONCURRENT_MARK - if (concurrent_mark) - g_assert_not_reached (); -#endif - - SGEN_ASSERT (9, current_collection_generation == GENERATION_OLD, "old gen parallel allocator called from a %d collection", current_collection_generation); - - if (free_blocks_local [size_index]) { - get_slot: - obj = unlink_slot_from_free_list_uncontested (free_blocks_local, size_index); - } else { - MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references); - - get_block: - block = free_blocks [size_index]; - if (block) { - if (!try_remove_block_from_free_list (block, free_blocks, size_index)) - goto get_block; - - g_assert (block->next_free == NULL); - g_assert (block->free_list); - block->next_free = free_blocks_local [size_index]; - free_blocks_local [size_index] = block; - - goto get_slot; - } else { - gboolean success; - - LOCK_MS_BLOCK_LIST; - success = ms_alloc_block (size_index, pinned, has_references); - UNLOCK_MS_BLOCK_LIST; - - if (G_UNLIKELY (!success)) - return NULL; - - goto get_block; - } - } - - *(MonoVTable**)obj = vtable; - - return obj; -} - -static void* -major_par_alloc_object (MonoVTable *vtable, size_t size, gboolean has_references) -{ - return alloc_obj_par (vtable, size, FALSE, has_references); -} -#endif - static void* alloc_obj (MonoVTable *vtable, size_t size, gboolean pinned, gboolean has_references) { @@ -627,11 +509,6 @@ alloc_obj (MonoVTable *vtable, size_t size, gboolean pinned, gboolean has_refere MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references); void *obj; -#ifdef SGEN_PARALLEL_MARK - SGEN_ASSERT (9, current_collection_generation == GENERATION_OLD, "old gen parallel allocator called from a %d collection", current_collection_generation); - -#endif - if (!free_blocks [size_index]) { if (G_UNLIKELY (!ms_alloc_block (size_index, pinned, has_references))) return NULL; @@ -1003,145 +880,6 @@ pin_major_object (char *obj, SgenGrayQueue *queue) #include "sgen-major-copy-object.h" -#ifdef SGEN_PARALLEL_MARK -static void -major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) -{ - mword objsize; - MSBlockInfo *block; - MonoVTable *vt; - - HEAVY_STAT (++stat_copy_object_called_major); - - SGEN_ASSERT (9, obj, "null object from pointer %p", ptr); - SGEN_ASSERT (9, current_collection_generation == GENERATION_OLD, "old gen parallel allocator called from a %d collection", current_collection_generation); - - if (sgen_ptr_in_nursery (obj)) { - int word, bit; - gboolean has_references; - void *destination; - mword vtable_word = *(mword*)obj; - vt = (MonoVTable*)(vtable_word & ~SGEN_VTABLE_BITS_MASK); - - if (vtable_word & SGEN_FORWARDED_BIT) { - *ptr = (void*)vt; - return; - } - - if (vtable_word & SGEN_PINNED_BIT) - return; - - /* An object in the nursery To Space has already been copied and grayed. Nothing to do. */ - if (sgen_nursery_is_to_space (obj)) - return; - - HEAVY_STAT (++stat_objects_copied_major); - - do_copy_object: - objsize = SGEN_ALIGN_UP (sgen_par_object_get_size (vt, (MonoObject*)obj)); - has_references = SGEN_VTABLE_HAS_REFERENCES (vt); - - destination = sgen_minor_collector.par_alloc_for_promotion (vt, obj, objsize, has_references); - if (G_UNLIKELY (!destination)) { - if (!sgen_ptr_in_nursery (obj)) { - int size_index; - block = MS_BLOCK_FOR_OBJ (obj); - size_index = block->obj_size_index; - evacuate_block_obj_sizes [size_index] = FALSE; - } - - sgen_parallel_pin_or_update (ptr, obj, vt, queue); - sgen_set_pinned_from_failed_allocation (objsize); - return; - } - - if (SGEN_CAS_PTR (obj, (void*)((mword)destination | SGEN_FORWARDED_BIT), vt) == vt) { - gboolean was_marked; - - par_copy_object_no_checks (destination, vt, obj, objsize, has_references ? queue : NULL); - obj = destination; - *ptr = obj; - - /* - * FIXME: If we make major_alloc_object() give - * us the block info, too, we won't have to - * re-fetch it here. - * - * FIXME (2): We should rework this to avoid all those nursery checks. - */ - /* - * For the split nursery allocator the object - * might still be in the nursery despite - * having being promoted, in which case we - * can't mark it. - */ - if (!sgen_ptr_in_nursery (obj)) { - block = MS_BLOCK_FOR_OBJ (obj); - MS_CALC_MARK_BIT (word, bit, obj); - SGEN_ASSERT (9, !MS_MARK_BIT (block, word, bit), "object %p already marked", obj); - MS_PAR_SET_MARK_BIT (was_marked, block, word, bit); - binary_protocol_mark (obj, vt, sgen_safe_object_get_size ((MonoObject*)obj)); - } - } else { - /* - * FIXME: We have allocated destination, but - * we cannot use it. Give it back to the - * allocator. - */ - *(void**)destination = NULL; - - vtable_word = *(mword*)obj; - g_assert (vtable_word & SGEN_FORWARDED_BIT); - - obj = (void*)(vtable_word & ~SGEN_VTABLE_BITS_MASK); - - *ptr = obj; - - HEAVY_STAT (++stat_slots_allocated_in_vain); - } - } else { - mword vtable_word = *(mword*)obj; - vt = (MonoVTable*)(vtable_word & ~SGEN_VTABLE_BITS_MASK); - - /* see comment in the non-parallel version below */ - if (vtable_word & SGEN_FORWARDED_BIT) { - *ptr = (void*)vt; - return; - } - objsize = SGEN_ALIGN_UP (sgen_par_object_get_size (vt, (MonoObject*)obj)); - - if (objsize <= SGEN_MAX_SMALL_OBJ_SIZE) { - int size_index; - - block = MS_BLOCK_FOR_OBJ (obj); - size_index = block->obj_size_index; - - if (!block->has_pinned && evacuate_block_obj_sizes [size_index]) { - if (block->is_to_space) - return; - - HEAVY_STAT (++stat_major_objects_evacuated); - goto do_copy_object; - } - - MS_PAR_MARK_OBJECT_AND_ENQUEUE (obj, block, queue); - } else { - LOSObject *bigobj = sgen_los_header_for_object (obj); - mword size_word = bigobj->size; - - if (size_word & 1) - return; - binary_protocol_pin (obj, vt, sgen_safe_object_get_size ((MonoObject*)obj)); - if (SGEN_CAS_PTR ((void*)&bigobj->size, (void*)(size_word | 1), (void*)size_word) == (void*)size_word) { - if (SGEN_VTABLE_HAS_REFERENCES (vt)) - GRAY_OBJECT_ENQUEUE (queue, obj); - } else { - g_assert (sgen_los_object_is_pinned (obj)); - } - } - } -} -#else #ifdef SGEN_HAVE_CONCURRENT_MARK static void major_copy_or_mark_object_concurrent (void **ptr, void *obj, SgenGrayQueue *queue) @@ -1293,7 +1031,6 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) } } } -#endif static void major_copy_or_mark_object_canonical (void **ptr, SgenGrayQueue *queue) @@ -2256,49 +1993,6 @@ alloc_free_block_lists (MSBlockInfo ***lists) lists [i] = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo*) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE); } -#ifdef SGEN_PARALLEL_MARK -static void* -major_alloc_worker_data (void) -{ - /* FIXME: free this when the workers come down */ - MSBlockInfo ***lists = malloc (sizeof (MSBlockInfo**) * MS_BLOCK_TYPE_MAX); - alloc_free_block_lists (lists); - return lists; -} - -static void -major_init_worker_thread (void *data) -{ - MSBlockInfo ***lists = data; - int i; - - g_assert (lists && lists != free_block_lists); - for (i = 0; i < MS_BLOCK_TYPE_MAX; ++i) { - int j; - for (j = 0; j < num_block_obj_sizes; ++j) - g_assert (!lists [i][j]); - } - -#ifdef HAVE_KW_THREAD - workers_free_block_lists = data; -#else - mono_native_tls_set_value (workers_free_block_lists_key, data); -#endif -} - -static void -major_reset_worker_data (void *data) -{ - MSBlockInfo ***lists = data; - int i; - for (i = 0; i < MS_BLOCK_TYPE_MAX; ++i) { - int j; - for (j = 0; j < num_block_obj_sizes; ++j) - lists [i][j] = NULL; - } -} -#endif - #undef pthread_create static void @@ -2311,12 +2005,7 @@ post_param_init (SgenMajorCollector *collector) static void sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurrent) #else // SGEN_HAVE_CONCURRENT_MARK -#ifdef SGEN_PARALLEL_MARK -void -sgen_marksweep_par_init (SgenMajorCollector *collector) -#else // SGEN_PARALLEL_MARK #error unknown configuration -#endif // SGEN_PARALLEL_MARK #endif // SGEN_HAVE_CONCURRENT_MARK { int i; @@ -2347,10 +2036,6 @@ sgen_marksweep_par_init (SgenMajorCollector *collector) for (i = 0; i < MS_NUM_FAST_BLOCK_OBJ_SIZE_INDEXES * 8; ++i) g_assert (MS_BLOCK_OBJ_SIZE_INDEX (i) == ms_find_block_obj_size_index (i)); -#ifdef SGEN_PARALLEL_MARK - LOCK_INIT (ms_block_list_mutex); -#endif - mono_counters_register ("# major blocks allocated", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_alloced); mono_counters_register ("# major blocks freed", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_freed); mono_counters_register ("# major blocks lazy swept", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_lazy_swept); @@ -2362,21 +2047,8 @@ sgen_marksweep_par_init (SgenMajorCollector *collector) mono_counters_register ("# major blocks allocated less ideally", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_alloced_less_ideal); #endif -#ifdef SGEN_PARALLEL_MARK -#ifndef HAVE_KW_THREAD - mono_native_tls_alloc (&workers_free_block_lists_key, NULL); -#endif -#endif - collector->section_size = MAJOR_SECTION_SIZE; -#ifdef SGEN_PARALLEL_MARK - collector->is_parallel = TRUE; - collector->alloc_worker_data = major_alloc_worker_data; - collector->init_worker_thread = major_init_worker_thread; - collector->reset_worker_data = major_reset_worker_data; -#else - collector->is_parallel = FALSE; -#endif + #ifdef SGEN_HAVE_CONCURRENT_MARK concurrent_mark = is_concurrent; if (is_concurrent) { @@ -2399,9 +2071,6 @@ sgen_marksweep_par_init (SgenMajorCollector *collector) collector->alloc_degraded = major_alloc_degraded; collector->alloc_object = major_alloc_object; -#ifdef SGEN_PARALLEL_MARK - collector->par_alloc_object = major_par_alloc_object; -#endif collector->free_pinned_object = free_pinned_object; collector->iterate_objects = major_iterate_objects; collector->free_non_pinned_object = major_free_non_pinned_object; diff --git a/mono/metadata/sgen-minor-copy-object.h b/mono/metadata/sgen-minor-copy-object.h index 187988e7def..c18e49f16dd 100644 --- a/mono/metadata/sgen-minor-copy-object.h +++ b/mono/metadata/sgen-minor-copy-object.h @@ -21,7 +21,6 @@ #define collector_pin_object(obj, queue) sgen_pin_object (obj, queue); #define COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION alloc_for_promotion -#define COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION par_alloc_for_promotion extern long long stat_nursery_copy_object_failed_to_space; /* from sgen-gc.c */ @@ -211,88 +210,6 @@ SERIAL_COPY_OBJECT_FROM_OBJ (void **obj_slot, SgenGrayQueue *queue) #endif } -static void -PARALLEL_COPY_OBJECT (void **obj_slot, SgenGrayQueue *queue) -{ - char *obj = *obj_slot; - mword vtable_word, objsize; - MonoVTable *vt; - void *destination; - gboolean has_references; - - SGEN_ASSERT (9, current_collection_generation == GENERATION_NURSERY, "calling minor-par-copy from a %d generation collection", current_collection_generation); - - HEAVY_STAT (++stat_copy_object_called_nursery); - - if (!sgen_ptr_in_nursery (obj)) { - HEAVY_STAT (++stat_nursery_copy_object_failed_from_space); - return; - } - - vtable_word = *(mword*)obj; - vt = (MonoVTable*)(vtable_word & ~SGEN_VTABLE_BITS_MASK); - - /* - * Before we can copy the object we must make sure that we are - * allowed to, i.e. that the object not pinned, not already - * forwarded and not in the nursery To Space. - */ - - if (vtable_word & SGEN_FORWARDED_BIT) { - HEAVY_STAT (++stat_nursery_copy_object_failed_forwarded); - *obj_slot = vt; - return; - } - if (vtable_word & SGEN_PINNED_BIT) { - HEAVY_STAT (++stat_nursery_copy_object_failed_pinned); - return; - } - - if (sgen_nursery_is_to_space (obj)) { - HEAVY_STAT (++stat_nursery_copy_object_failed_to_space); - return; - } - - HEAVY_STAT (++stat_objects_copied_nursery); - - objsize = SGEN_ALIGN_UP (sgen_par_object_get_size (vt, (MonoObject*)obj)); - has_references = SGEN_VTABLE_HAS_REFERENCES (vt); - - destination = COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION (vt, obj, objsize, has_references); - - if (G_UNLIKELY (!destination)) { - sgen_parallel_pin_or_update (obj_slot, obj, vt, queue); - return; - } - - *(MonoVTable**)destination = vt; - - if (SGEN_CAS_PTR ((void*)obj, (void*)((mword)destination | SGEN_FORWARDED_BIT), vt) == vt) { - par_copy_object_no_checks (destination, vt, obj, objsize, has_references ? queue : NULL); - obj = destination; - *obj_slot = obj; - } else { - /* FIXME: unify with code in major_copy_or_mark_object() */ - - /* FIXME: Give destination back to the allocator. */ - /*The major collector only needs the first word zeroed and nursery requires all bits to be. */ - if (!sgen_ptr_in_nursery (destination)) - *(void**)destination = NULL; - else - memset (destination, 0, objsize); - - vtable_word = *(mword*)obj; - g_assert (vtable_word & SGEN_FORWARDED_BIT); - - obj = (void*)(vtable_word & ~SGEN_VTABLE_BITS_MASK); - - *obj_slot = obj; - - HEAVY_STAT (++stat_slots_allocated_in_vain); - } -} - #define FILL_MINOR_COLLECTOR_COPY_OBJECT(collector) do { \ (collector)->serial_ops.copy_or_mark_object = SERIAL_COPY_OBJECT; \ - (collector)->parallel_ops.copy_or_mark_object = PARALLEL_COPY_OBJECT; \ } while (0) diff --git a/mono/metadata/sgen-minor-scan-object.h b/mono/metadata/sgen-minor-scan-object.h index 7a34dfd4ac3..10f752a73b2 100644 --- a/mono/metadata/sgen-minor-scan-object.h +++ b/mono/metadata/sgen-minor-scan-object.h @@ -24,70 +24,15 @@ extern long long stat_scan_object_called_nursery; #if defined(SGEN_SIMPLE_NURSERY) #define SERIAL_SCAN_OBJECT simple_nursery_serial_scan_object #define SERIAL_SCAN_VTYPE simple_nursery_serial_scan_vtype -#define PARALLEL_SCAN_OBJECT simple_nursery_parallel_scan_object -#define PARALLEL_SCAN_VTYPE simple_nursery_parallel_scan_vtype #elif defined (SGEN_SPLIT_NURSERY) #define SERIAL_SCAN_OBJECT split_nursery_serial_scan_object #define SERIAL_SCAN_VTYPE split_nursery_serial_scan_vtype -#define PARALLEL_SCAN_OBJECT split_nursery_parallel_scan_object -#define PARALLEL_SCAN_VTYPE split_nursery_parallel_scan_vtype #else #error "Please define GC_CONF_NAME" #endif -#undef HANDLE_PTR -#define HANDLE_PTR(ptr,obj) do { \ - void *__old = *(ptr); \ - void *__copy; \ - SGEN_OBJECT_LAYOUT_STATISTICS_MARK_BITMAP ((obj), (ptr)); \ - if (__old) { \ - PARALLEL_COPY_OBJECT ((ptr), queue); \ - __copy = *(ptr); \ - SGEN_COND_LOG (9, __old != __copy, "Overwrote field at %p with %p (was: %p)", (ptr), *(ptr), __old); \ - if (G_UNLIKELY (sgen_ptr_in_nursery (__copy) && !sgen_ptr_in_nursery ((ptr)))) \ - sgen_add_to_global_remset ((ptr), __copy); \ - } \ - } while (0) - -/* - * Scan the object pointed to by @start for references to - * other objects between @from_start and @from_end and copy - * them to the gray_objects area. - */ -static void -PARALLEL_SCAN_OBJECT (char *start, SgenGrayQueue *queue) -{ - SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP; - -#define SCAN_OBJECT_PROTOCOL -#include "sgen-scan-object.h" - - SGEN_OBJECT_LAYOUT_STATISTICS_COMMIT_BITMAP; - HEAVY_STAT (++stat_scan_object_called_nursery); -} - -/* - * scan_vtype: - * - * Scan the valuetype pointed to by START, described by DESC for references to - * other objects between @from_start and @from_end and copy them to the gray_objects area. - * Returns a pointer to the end of the object. - */ -static void -PARALLEL_SCAN_VTYPE (char *start, mword desc, SgenGrayQueue *queue BINARY_PROTOCOL_ARG (size_t size)) -{ - SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP; - - /* The descriptors include info about the MonoObject header as well */ - start -= sizeof (MonoObject); - -#define SCAN_OBJECT_NOVTABLE -#define SCAN_OBJECT_PROTOCOL -#include "sgen-scan-object.h" -} - #undef HANDLE_PTR /* Global remsets are handled in SERIAL_COPY_OBJECT_FROM_OBJ */ #define HANDLE_PTR(ptr,obj) do { \ @@ -125,8 +70,6 @@ SERIAL_SCAN_VTYPE (char *start, mword desc, SgenGrayQueue *queue BINARY_PROTOCOL } #define FILL_MINOR_COLLECTOR_SCAN_OBJECT(collector) do { \ - (collector)->parallel_ops.scan_object = PARALLEL_SCAN_OBJECT; \ - (collector)->parallel_ops.scan_vtype = PARALLEL_SCAN_VTYPE; \ (collector)->serial_ops.scan_object = SERIAL_SCAN_OBJECT; \ (collector)->serial_ops.scan_vtype = SERIAL_SCAN_VTYPE; \ } while (0) diff --git a/mono/metadata/sgen-simple-nursery.c b/mono/metadata/sgen-simple-nursery.c index f2f7066c301..2cfb9d3211c 100644 --- a/mono/metadata/sgen-simple-nursery.c +++ b/mono/metadata/sgen-simple-nursery.c @@ -35,12 +35,6 @@ alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has return major_collector.alloc_object (vtable, objsize, has_references); } -static inline char* -par_alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references) -{ - return major_collector.par_alloc_object (vtable, objsize, has_references); -} - static SgenFragment* build_fragments_get_exclude_head (void) { @@ -79,7 +73,6 @@ init_nursery (SgenFragmentAllocator *allocator, char *start, char *end) #define SGEN_SIMPLE_NURSERY #define SERIAL_COPY_OBJECT simple_nursery_serial_copy_object -#define PARALLEL_COPY_OBJECT simple_nursery_parallel_copy_object #define SERIAL_COPY_OBJECT_FROM_OBJ simple_nursery_serial_copy_object_from_obj #include "sgen-minor-copy-object.h" @@ -91,7 +84,6 @@ sgen_simple_nursery_init (SgenMinorCollector *collector) collector->is_split = FALSE; collector->alloc_for_promotion = alloc_for_promotion; - collector->par_alloc_for_promotion = par_alloc_for_promotion; collector->prepare_to_space = prepare_to_space; collector->clear_fragments = clear_fragments; diff --git a/mono/metadata/sgen-split-nursery.c b/mono/metadata/sgen-split-nursery.c index 1f62d14b703..87cc412c672 100644 --- a/mono/metadata/sgen-split-nursery.c +++ b/mono/metadata/sgen-split-nursery.c @@ -145,8 +145,6 @@ static AgeAllocationBuffer age_alloc_buffers [MAX_AGE]; /* The collector allocs from here. */ static SgenFragmentAllocator collector_allocator; -static LOCK_DECLARE (par_alloc_buffer_refill_mutex); - static inline int get_object_age (char *object) { @@ -292,82 +290,6 @@ alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has return p; } -static char* -par_alloc_for_promotion_slow_path (int age, size_t objsize) -{ - char *p; - size_t allocated_size; - size_t aligned_objsize = (size_t)align_up (objsize, SGEN_TO_SPACE_GRANULE_BITS); - - mono_mutex_lock (&par_alloc_buffer_refill_mutex); - -restart: - p = age_alloc_buffers [age].next; - if (G_LIKELY (p + objsize <= age_alloc_buffers [age].end)) { - if (SGEN_CAS_PTR ((void*)&age_alloc_buffers [age].next, p + objsize, p) != p) - goto restart; - } else { - /* Reclaim remaining space - if we OOMd the nursery nothing to see here. */ - char *end = age_alloc_buffers [age].end; - if (end) { - do { - p = age_alloc_buffers [age].next; - } while (SGEN_CAS_PTR ((void*)&age_alloc_buffers [age].next, end, p) != p); - sgen_clear_range (p, end); - } - - /* By setting end to NULL we make sure no other thread can advance while we're updating.*/ - age_alloc_buffers [age].end = NULL; - STORE_STORE_FENCE; - - p = sgen_fragment_allocator_par_range_alloc ( - &collector_allocator, - MAX (aligned_objsize, AGE_ALLOC_BUFFER_DESIRED_SIZE), - MAX (aligned_objsize, AGE_ALLOC_BUFFER_MIN_SIZE), - &allocated_size); - if (p) { - set_age_in_range (p, p + allocated_size, age); - age_alloc_buffers [age].next = p + objsize; - STORE_STORE_FENCE; /* Next must arrive before the new value for next. */ - age_alloc_buffers [age].end = p + allocated_size; - } - } - - mono_mutex_unlock (&par_alloc_buffer_refill_mutex); - return p; -} - -static inline char* -par_alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references) -{ - char *p; - int age; - - age = get_object_age (obj); - if (age >= promote_age) - return major_collector.par_alloc_object (vtable, objsize, has_references); - -restart: - p = age_alloc_buffers [age].next; - - LOAD_LOAD_FENCE; /* The read of ->next must happen before ->end */ - - if (G_LIKELY (p + objsize <= age_alloc_buffers [age].end)) { - if (SGEN_CAS_PTR ((void*)&age_alloc_buffers [age].next, p + objsize, p) != p) - goto restart; - } else { - p = par_alloc_for_promotion_slow_path (age, objsize); - - /* Have we failed to promote to the nursery, lets just evacuate it to old gen. */ - if (!p) - return major_collector.par_alloc_object (vtable, objsize, has_references); - } - - *(MonoVTable**)p = vtable; - - return p; -} - static char* minor_alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references) { @@ -380,18 +302,6 @@ minor_alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboole return alloc_for_promotion (vtable, obj, objsize, has_references); } -static char* -minor_par_alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references) -{ - /* - We only need to check for a non-nursery object if we're doing a major collection. - */ - if (!sgen_ptr_in_nursery (obj)) - return major_collector.par_alloc_object (vtable, objsize, has_references); - - return par_alloc_for_promotion (vtable, obj, objsize, has_references); -} - static SgenFragment* build_fragments_get_exclude_head (void) { @@ -522,7 +432,6 @@ print_gc_param_usage (void) #define SGEN_SPLIT_NURSERY #define SERIAL_COPY_OBJECT split_nursery_serial_copy_object -#define PARALLEL_COPY_OBJECT split_nursery_parallel_copy_object #define SERIAL_COPY_OBJECT_FROM_OBJ split_nursery_serial_copy_object_from_obj #include "sgen-minor-copy-object.h" @@ -534,7 +443,6 @@ sgen_split_nursery_init (SgenMinorCollector *collector) collector->is_split = TRUE; collector->alloc_for_promotion = minor_alloc_for_promotion; - collector->par_alloc_for_promotion = minor_par_alloc_for_promotion; collector->prepare_to_space = prepare_to_space; collector->clear_fragments = clear_fragments; @@ -547,7 +455,6 @@ sgen_split_nursery_init (SgenMinorCollector *collector) FILL_MINOR_COLLECTOR_COPY_OBJECT (collector); FILL_MINOR_COLLECTOR_SCAN_OBJECT (collector); - LOCK_INIT (par_alloc_buffer_refill_mutex); } diff --git a/mono/metadata/sgen-workers.c b/mono/metadata/sgen-workers.c index b3eebb02d9c..94ca31c9e6f 100644 --- a/mono/metadata/sgen-workers.c +++ b/mono/metadata/sgen-workers.c @@ -140,7 +140,7 @@ workers_wait (void) static gboolean collection_needs_workers (void) { - return sgen_collection_is_parallel () || sgen_collection_is_concurrent (); + return sgen_collection_is_concurrent (); } void @@ -301,7 +301,7 @@ workers_get_work (WorkerData *data) * distribute gray queue. */ major = sgen_get_major_collector (); - if (major->is_concurrent || major->is_parallel) { + if (major->is_concurrent) { GrayQueueSection *section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue); if (section) { sgen_gray_object_enqueue_section (&data->private_gray_queue, section); @@ -441,7 +441,7 @@ sgen_workers_init_distribute_gray_queue (void) if (!collection_needs_workers ()) return; - init_distribute_gray_queue (sgen_get_major_collector ()->is_concurrent || sgen_get_major_collector ()->is_parallel); + init_distribute_gray_queue (sgen_get_major_collector ()->is_concurrent); } void @@ -449,7 +449,7 @@ sgen_workers_init (int num_workers) { int i; - if (!sgen_get_major_collector ()->is_parallel && !sgen_get_major_collector ()->is_concurrent) + if (!sgen_get_major_collector ()->is_concurrent) return; //g_print ("initing %d workers\n", num_workers); @@ -462,7 +462,7 @@ sgen_workers_init (int num_workers) MONO_SEM_INIT (&workers_waiting_sem, 0); MONO_SEM_INIT (&workers_done_sem, 0); - init_distribute_gray_queue (sgen_get_major_collector ()->is_concurrent || sgen_get_major_collector ()->is_parallel); + init_distribute_gray_queue (sgen_get_major_collector ()->is_concurrent); if (sgen_get_major_collector ()->alloc_worker_data) workers_gc_thread_major_collector_data = sgen_get_major_collector ()->alloc_worker_data (); diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 58392b04acd..6268cadb4f0 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -936,13 +936,11 @@ SGEN_TESTS = \ SGEN_CONFIGURATIONS = \ "|plain" \ - "major=marksweep-par|ms-par" \ "major=marksweep-conc|ms-conc" \ "major=marksweep-conc,minor=split|ms-conc-split" \ "minor=split|ms-split" \ "minor=split,alloc-ratio=95|ms-split-95" \ "|plain-clear-at-gc|clear-at-gc" \ - "major=marksweep-par|ms-par-clear-at-gc|clear-at-gc" \ "major=marksweep-conc|ms-conc-clear-at-gc|clear-at-gc" \ "minor=split|ms-split-clear-at-gc|clear-at-gc" @@ -1321,7 +1319,6 @@ OOM_TESTS = \ test-oom: $(OOM_TESTS) @for fn in $+ ; do \ echo "Testing $$fn ..."; \ - MONO_GC_PARAMS=max-heap-size=16m,major=marksweep-par MONO_ENV_OPTIONS="--gc=sgen" $(RUNTIME) $$fn > $$fn.stdout || exit 1; \ MONO_GC_PARAMS=max-heap-size=16m MONO_ENV_OPTIONS="--gc=sgen" $(RUNTIME) $$fn > $$fn.stdout || exit 1; \ MONO_GC_PARAMS=max-heap-size=16m $(RUNTIME) $$fn > $$fn.stdout || exit 1; \ done From 050ee93a674e130aa2e52670c8d7e4a7c971337f Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 20 Aug 2014 13:45:50 -0700 Subject: [PATCH 276/543] [sgen] Implement get_and_reset_num_major_objects_marked() for non-conc, too. This is used for profiling and debugging. There's no reason to only have it for concurrent. --- mono/metadata/sgen-marksweep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index 740cfab973f..04b99ac11a1 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -1044,6 +1044,7 @@ major_copy_or_mark_object_concurrent_canonical (void **ptr, SgenGrayQueue *queue { major_copy_or_mark_object_concurrent (ptr, *ptr, queue); } +#endif static long long major_get_and_reset_num_major_objects_marked (void) @@ -1056,7 +1057,6 @@ major_get_and_reset_num_major_objects_marked (void) return 0; #endif } -#endif #include "sgen-major-scan-object.h" @@ -2054,13 +2054,13 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr if (is_concurrent) { collector->is_concurrent = TRUE; collector->want_synchronous_collection = &want_evacuation; - collector->get_and_reset_num_major_objects_marked = major_get_and_reset_num_major_objects_marked; } else #endif { collector->is_concurrent = FALSE; collector->want_synchronous_collection = NULL; } + collector->get_and_reset_num_major_objects_marked = major_get_and_reset_num_major_objects_marked; collector->supports_cardtable = TRUE; collector->have_swept = &have_swept; From d07b7650c7747f1940e29e1a3342431eed8afea1 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 20 Aug 2014 15:17:21 -0700 Subject: [PATCH 277/543] [sgen] Abstract block info->block via macro. If we want to experiment with putting the block info into the block this makes it easy. --- mono/metadata/sgen-marksweep.c | 38 ++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index 04b99ac11a1..d51769d7955 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -90,8 +90,10 @@ struct _MSBlockInfo { mword mark_words [MS_NUM_MARK_WORDS]; }; -#define MS_BLOCK_OBJ(b,i) ((b)->block + MS_BLOCK_SKIP + (b)->obj_size * (i)) -#define MS_BLOCK_OBJ_FOR_SIZE(b,i,obj_size) ((b)->block + MS_BLOCK_SKIP + (obj_size) * (i)) +#define MS_BLOCK_FOR_BLOCK_INFO(b) ((b)->block) + +#define MS_BLOCK_OBJ(b,i) (MS_BLOCK_FOR_BLOCK_INFO(b) + MS_BLOCK_SKIP + (b)->obj_size * (i)) +#define MS_BLOCK_OBJ_FOR_SIZE(b,i,obj_size) (MS_BLOCK_FOR_BLOCK_INFO(b) + MS_BLOCK_SKIP + (obj_size) * (i)) #define MS_BLOCK_DATA_FOR_OBJ(o) ((char*)((mword)(o) & ~(mword)(MS_BLOCK_SIZE - 1))) typedef struct { @@ -101,7 +103,7 @@ typedef struct { #define MS_BLOCK_FOR_OBJ(o) (((MSBlockHeader*)MS_BLOCK_DATA_FOR_OBJ ((o)))->info) /* object index will always be small */ -#define MS_BLOCK_OBJ_INDEX(o,b) ((int)(((char*)(o) - ((b)->block + MS_BLOCK_SKIP)) / (b)->obj_size)) +#define MS_BLOCK_OBJ_INDEX(o,b) ((int)(((char*)(o) - (MS_BLOCK_FOR_BLOCK_INFO(b) + MS_BLOCK_SKIP)) / (b)->obj_size)) //casting to int is fine since blocks are 32k #define MS_CALC_MARK_BIT(w,b,o) do { \ @@ -133,7 +135,7 @@ typedef struct { } \ } while (1) -#define MS_OBJ_ALLOCED(o,b) (*(void**)(o) && (*(char**)(o) < (b)->block || *(char**)(o) >= (b)->block + MS_BLOCK_SIZE)) +#define MS_OBJ_ALLOCED(o,b) (*(void**)(o) && (*(char**)(o) < MS_BLOCK_FOR_BLOCK_INFO (b) || *(char**)(o) >= MS_BLOCK_FOR_BLOCK_INFO (b) + MS_BLOCK_SIZE)) #define MS_BLOCK_OBJ_SIZE_FACTOR (sqrt (2.0)) @@ -236,7 +238,7 @@ major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits) static void update_heap_boundaries_for_block (MSBlockInfo *block) { - sgen_update_heap_boundaries ((mword)block->block, (mword)block->block + MS_BLOCK_SIZE); + sgen_update_heap_boundaries ((mword)MS_BLOCK_FOR_BLOCK_INFO (block), (mword)MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE); } static void* @@ -443,7 +445,7 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) update_heap_boundaries_for_block (info); /* build free list */ - obj_start = info->block + MS_BLOCK_SKIP; + obj_start = MS_BLOCK_FOR_BLOCK_INFO (info) + MS_BLOCK_SKIP; info->free_list = (void**)obj_start; /* we're skipping the last one - it must be nulled */ for (i = 0; i < count - 1; ++i) { @@ -470,7 +472,7 @@ obj_is_from_pinned_alloc (char *ptr) MSBlockInfo *block; FOREACH_BLOCK (block) { - if (ptr >= block->block && ptr <= block->block + MS_BLOCK_SIZE) + if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) return block->pinned; } END_FOREACH_BLOCK; return FALSE; @@ -644,7 +646,7 @@ major_ptr_is_in_non_pinned_space (char *ptr, char **start) MSBlockInfo *block; FOREACH_BLOCK (block) { - if (ptr >= block->block && ptr <= block->block + MS_BLOCK_SIZE) { + if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) { int count = MS_BLOCK_FREE / block->obj_size; int i; @@ -705,7 +707,7 @@ major_is_valid_object (char *object) int idx; char *obj; - if ((block->block > object) || ((block->block + MS_BLOCK_SIZE) <= object)) + if ((MS_BLOCK_FOR_BLOCK_INFO (block) > object) || ((MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) <= object)) continue; idx = MS_BLOCK_OBJ_INDEX (object, block); @@ -732,11 +734,11 @@ major_describe_pointer (char *ptr) int w, b; gboolean marked; - if ((block->block > ptr) || ((block->block + MS_BLOCK_SIZE) <= ptr)) + if ((MS_BLOCK_FOR_BLOCK_INFO (block) > ptr) || ((MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) <= ptr)) continue; SGEN_LOG (0, "major-ptr (block %p sz %d pin %d ref %d)\n", - block->block, block->obj_size, block->pinned, block->has_references); + MS_BLOCK_FOR_BLOCK_INFO (block), block->obj_size, block->pinned, block->has_references); idx = MS_BLOCK_OBJ_INDEX (ptr, block); obj = (char*)MS_BLOCK_OBJ (block, idx); @@ -814,7 +816,7 @@ major_dump_heap (FILE *heap_dump_file) start = i; } else { if (start >= 0) { - sgen_dump_occupied (MS_BLOCK_OBJ (block, start), MS_BLOCK_OBJ (block, i), block->block); + sgen_dump_occupied (MS_BLOCK_OBJ (block, start), MS_BLOCK_OBJ (block, i), MS_BLOCK_FOR_BLOCK_INFO (block)); start = -1; } } @@ -1627,7 +1629,7 @@ major_find_pin_queue_start_ends (SgenGrayQueue *queue) MSBlockInfo *block; FOREACH_BLOCK (block) { - block->pin_queue_start = sgen_find_optimized_pin_queue_area (block->block + MS_BLOCK_SKIP, block->block + MS_BLOCK_SIZE, + block->pin_queue_start = sgen_find_optimized_pin_queue_area (MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SKIP, MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE, &block->pin_queue_num_entries); } END_FOREACH_BLOCK; } @@ -1716,7 +1718,7 @@ major_iterate_live_block_ranges (sgen_cardtable_block_callback callback) FOREACH_BLOCK (block) { if (block->has_references) - callback ((mword)block->block, MS_BLOCK_SIZE); + callback ((mword)MS_BLOCK_FOR_BLOCK_INFO (block), MS_BLOCK_SIZE); } END_FOREACH_BLOCK; } @@ -1797,7 +1799,7 @@ major_scan_card_table (gboolean mod_union, SgenGrayQueue *queue) continue; block_obj_size = block->obj_size; - block_start = block->block; + block_start = MS_BLOCK_FOR_BLOCK_INFO (block); if (block_obj_size >= CARD_SIZE_IN_BYTES) { guint8 *cards; @@ -1944,7 +1946,7 @@ major_count_cards (long long *num_total_cards, long long *num_marked_cards) long long marked_cards = 0; FOREACH_BLOCK (block) { - guint8 *cards = sgen_card_table_get_card_scan_address ((mword) block->block); + guint8 *cards = sgen_card_table_get_card_scan_address ((mword) MS_BLOCK_FOR_BLOCK_INFO (block)); int i; if (!block->has_references) @@ -1971,7 +1973,7 @@ update_cardtable_mod_union (void) size_t num_cards; block->cardtable_mod_union = sgen_card_table_update_mod_union (block->cardtable_mod_union, - block->block, MS_BLOCK_SIZE, &num_cards); + MS_BLOCK_FOR_BLOCK_INFO (block), MS_BLOCK_SIZE, &num_cards); SGEN_ASSERT (0, num_cards == CARDS_PER_BLOCK, "Number of cards calculation is wrong"); } END_FOREACH_BLOCK; @@ -1981,7 +1983,7 @@ static guint8* major_get_cardtable_mod_union_for_object (char *obj) { MSBlockInfo *block = MS_BLOCK_FOR_OBJ (obj); - return &block->cardtable_mod_union [(obj - (char*)sgen_card_table_align_pointer (block->block)) >> CARD_BITS]; + return &block->cardtable_mod_union [(obj - (char*)sgen_card_table_align_pointer (MS_BLOCK_FOR_BLOCK_INFO (block))) >> CARD_BITS]; } #endif From c2022b34b7820821406d4e46df7868db89144f2c Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Fri, 22 Aug 2014 11:30:34 -0700 Subject: [PATCH 278/543] [sgen] Remove obsolete check in #ifdef. That macro doesn't exist anymore. --- mono/metadata/sgen-gc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index cc5daa551ba..1a092271608 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -351,7 +351,7 @@ typedef struct { static inline MONO_ALWAYS_INLINE void GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj) { -#if defined(SGEN_GRAY_OBJECT_ENQUEUE) || SGEN_MAX_DEBUG_LEVEL >= 9 +#if SGEN_MAX_DEBUG_LEVEL >= 9 sgen_gray_object_enqueue (queue, obj); #else if (G_UNLIKELY (!queue->first || queue->cursor == GRAY_LAST_CURSOR_POSITION (queue->first))) { @@ -372,7 +372,7 @@ GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj) static inline MONO_ALWAYS_INLINE void GRAY_OBJECT_DEQUEUE (SgenGrayQueue *queue, char** obj) { -#if defined(SGEN_GRAY_OBJECT_ENQUEUE) || SGEN_MAX_DEBUG_LEVEL >= 9 +#if SGEN_MAX_DEBUG_LEVEL >= 9 *obj = sgen_gray_object_enqueue (queue); #else if (!queue->first) { From 003488cc2a75981f8d9e1a5a46f8ad2adbdc4a38 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Fri, 22 Aug 2014 11:36:28 -0700 Subject: [PATCH 279/543] [sgen] GrayQueueEntry struct instead of just char*. This makes it easier to later enqueue the GC descriptor with the object. --- mono/metadata/sgen-gc.h | 14 +++++++++---- mono/metadata/sgen-gray.c | 38 ++++++++++++++++++++---------------- mono/metadata/sgen-gray.h | 24 +++++++++++++++++------ mono/metadata/sgen-workers.c | 12 ++++++------ mono/metadata/sgen-workers.h | 2 +- 5 files changed, 56 insertions(+), 34 deletions(-) diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 1a092271608..6603072da7f 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -357,9 +357,11 @@ GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj) if (G_UNLIKELY (!queue->first || queue->cursor == GRAY_LAST_CURSOR_POSITION (queue->first))) { sgen_gray_object_enqueue (queue, obj); } else { + GrayQueueEntry entry = { obj }; + HEAVY_STAT (gc_stats.gray_queue_enqueue_fast_path ++); - *++queue->cursor = obj; + *++queue->cursor = entry; #ifdef SGEN_HEAVY_BINARY_PROTOCOL binary_protocol_gray_enqueue (queue, queue->cursor, obj); #endif @@ -372,8 +374,10 @@ GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj) static inline MONO_ALWAYS_INLINE void GRAY_OBJECT_DEQUEUE (SgenGrayQueue *queue, char** obj) { + GrayQueueEntry entry; #if SGEN_MAX_DEBUG_LEVEL >= 9 - *obj = sgen_gray_object_enqueue (queue); + entry = sgen_gray_object_enqueue (queue); + *obj = entry.obj; #else if (!queue->first) { HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++); @@ -383,11 +387,13 @@ GRAY_OBJECT_DEQUEUE (SgenGrayQueue *queue, char** obj) binary_protocol_gray_dequeue (queue, queue->cursor, *obj); #endif } else if (G_UNLIKELY (queue->cursor == GRAY_FIRST_CURSOR_POSITION (queue->first))) { - *obj = sgen_gray_object_dequeue (queue); + entry = sgen_gray_object_dequeue (queue); + *obj = entry.obj; } else { HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++); - *obj = *queue->cursor--; + entry = *queue->cursor--; + *obj = entry.obj; #ifdef SGEN_HEAVY_BINARY_PROTOCOL binary_protocol_gray_dequeue (queue, queue->cursor + 1, *obj); #endif diff --git a/mono/metadata/sgen-gray.c b/mono/metadata/sgen-gray.c index 2393cbabb14..2031a729cf4 100644 --- a/mono/metadata/sgen-gray.c +++ b/mono/metadata/sgen-gray.c @@ -69,7 +69,7 @@ sgen_gray_object_alloc_queue_section (SgenGrayQueue *queue) /* Link it with the others */ section->next = queue->first; queue->first = section; - queue->cursor = (char**)section->objects - 1; + queue->cursor = section->entries - 1; } void @@ -90,6 +90,8 @@ sgen_gray_object_free_queue_section (GrayQueueSection *section) void sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj) { + GrayQueueEntry entry = { obj }; + HEAVY_STAT (gc_stats.gray_queue_enqueue_slow_path ++); SGEN_ASSERT (9, obj, "enqueueing a null object"); @@ -110,33 +112,35 @@ sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj) } STATE_ASSERT (queue->first, GRAY_QUEUE_SECTION_STATE_ENQUEUED); SGEN_ASSERT (9, queue->cursor <= GRAY_LAST_CURSOR_POSITION (queue->first), "gray queue %p overflow, first %p, cursor %p", queue, queue->first, queue->cursor); - *++queue->cursor = obj; + *++queue->cursor = entry; #ifdef SGEN_HEAVY_BINARY_PROTOCOL binary_protocol_gray_enqueue (queue, queue->cursor, obj); #endif } -char* +GrayQueueEntry sgen_gray_object_dequeue (SgenGrayQueue *queue) { - char *obj; + GrayQueueEntry entry; HEAVY_STAT (gc_stats.gray_queue_dequeue_slow_path ++); - if (sgen_gray_object_queue_is_empty (queue)) - return NULL; + if (sgen_gray_object_queue_is_empty (queue)) { + entry.obj = NULL; + return entry; + } STATE_ASSERT (queue->first, GRAY_QUEUE_SECTION_STATE_ENQUEUED); - SGEN_ASSERT (9, queue->cursor >= (char**)queue->first->objects, "gray queue %p underflow, first %p, cursor %d", queue, queue->first, queue->cursor); + SGEN_ASSERT (9, queue->cursor >= GRAY_FIRST_CURSOR_POSITION (queue->first), "gray queue %p underflow, first %p, cursor %d", queue, queue->first, queue->cursor); - obj = *queue->cursor--; + entry = *queue->cursor--; #ifdef SGEN_HEAVY_BINARY_PROTOCOL binary_protocol_gray_dequeue (queue, queue->cursor + 1, obj); #endif - if (G_UNLIKELY (queue->cursor == (char**)queue->first->objects - 1)) { + if (G_UNLIKELY (queue->cursor < GRAY_FIRST_CURSOR_POSITION (queue->first))) { GrayQueueSection *section = queue->first; queue->first = section->next; section->next = queue->free_list; @@ -144,10 +148,10 @@ sgen_gray_object_dequeue (SgenGrayQueue *queue) STATE_TRANSITION (section, GRAY_QUEUE_SECTION_STATE_ENQUEUED, GRAY_QUEUE_SECTION_STATE_FREE_LIST); queue->free_list = section; - queue->cursor = queue->first ? (char**)queue->first->objects + queue->first->size - 1 : NULL; + queue->cursor = queue->first ? queue->first->entries + queue->first->size - 1 : NULL; } - return obj; + return entry; } GrayQueueSection* @@ -162,9 +166,9 @@ sgen_gray_object_dequeue_section (SgenGrayQueue *queue) queue->first = section->next; section->next = NULL; - section->size = queue->cursor - (char**)section->objects + 1; + section->size = queue->cursor - section->entries + 1; - queue->cursor = queue->first ? (char**)queue->first->objects + queue->first->size - 1 : NULL; + queue->cursor = queue->first ? queue->first->entries + queue->first->size - 1 : NULL; STATE_TRANSITION (section, GRAY_QUEUE_SECTION_STATE_ENQUEUED, GRAY_QUEUE_SECTION_STATE_FLOATING); @@ -177,16 +181,16 @@ sgen_gray_object_enqueue_section (SgenGrayQueue *queue, GrayQueueSection *sectio STATE_TRANSITION (section, GRAY_QUEUE_SECTION_STATE_FLOATING, GRAY_QUEUE_SECTION_STATE_ENQUEUED); if (queue->first) - queue->first->size = queue->cursor - (char**)queue->first->objects + 1; + queue->first->size = queue->cursor - queue->first->entries + 1; section->next = queue->first; queue->first = section; - queue->cursor = (char**)queue->first->objects + queue->first->size - 1; + queue->cursor = queue->first->entries + queue->first->size - 1; #ifdef SGEN_CHECK_GRAY_OBJECT_ENQUEUE if (queue->enqueue_check_func) { int i; for (i = 0; i < section->size; ++i) - queue->enqueue_check_func (section->objects [i]); + queue->enqueue_check_func (section->entries [i].obj); } #endif } @@ -338,7 +342,7 @@ sgen_section_gray_queue_enqueue (SgenSectionGrayQueue *queue, GrayQueueSection * if (queue->enqueue_check_func) { int i; for (i = 0; i < section->size; ++i) - queue->enqueue_check_func (section->objects [i]); + queue->enqueue_check_func (section->entries [i].obj); } #endif diff --git a/mono/metadata/sgen-gray.h b/mono/metadata/sgen-gray.h index 2dfea35a146..5ad7ab1381c 100644 --- a/mono/metadata/sgen-gray.h +++ b/mono/metadata/sgen-gray.h @@ -48,7 +48,14 @@ * array and another 1 for the actual value in the array. */ -#define SGEN_GRAY_QUEUE_SECTION_SIZE (128 - 3) +/* SGEN_GRAY_QUEUE_HEADER_SIZE is number of machine words */ +#ifdef SGEN_CHECK_GRAY_OBJECT_SECTIONS +#define SGEN_GRAY_QUEUE_HEADER_SIZE 4 +#else +#define SGEN_GRAY_QUEUE_HEADER_SIZE 2 +#endif + +#define SGEN_GRAY_QUEUE_SECTION_SIZE (128 - SGEN_GRAY_QUEUE_HEADER_SIZE) #ifdef SGEN_CHECK_GRAY_OBJECT_SECTIONS typedef enum { @@ -59,6 +66,11 @@ typedef enum { } GrayQueueSectionState; #endif +typedef struct _GrayQueueEntry GrayQueueEntry; +struct _GrayQueueEntry { + char *obj; +}; + /* * This is a stack now instead of a queue, so the most recently added items are removed * first, improving cache locality, and keeping the stack size manageable. @@ -75,7 +87,7 @@ struct _GrayQueueSection { #endif int size; GrayQueueSection *next; - char *objects [SGEN_GRAY_QUEUE_SECTION_SIZE]; + GrayQueueEntry entries [SGEN_GRAY_QUEUE_SECTION_SIZE]; }; typedef struct _SgenGrayQueue SgenGrayQueue; @@ -84,7 +96,7 @@ typedef void (*GrayQueueAllocPrepareFunc) (SgenGrayQueue*); typedef void (*GrayQueueEnqueueCheckFunc) (char*); struct _SgenGrayQueue { - char **cursor; + GrayQueueEntry *cursor; GrayQueueSection *first; GrayQueueSection *free_list; GrayQueueAllocPrepareFunc alloc_prepare_func; @@ -105,11 +117,11 @@ struct _SgenSectionGrayQueue { #endif }; -#define GRAY_LAST_CURSOR_POSITION(s) ((char**)(s)->objects + SGEN_GRAY_QUEUE_SECTION_SIZE - 1) -#define GRAY_FIRST_CURSOR_POSITION(s) ((char**)(s)->objects) +#define GRAY_LAST_CURSOR_POSITION(s) ((s)->entries + SGEN_GRAY_QUEUE_SECTION_SIZE - 1) +#define GRAY_FIRST_CURSOR_POSITION(s) ((s)->entries) void sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj) MONO_INTERNAL; -char* sgen_gray_object_dequeue (SgenGrayQueue *queue) MONO_INTERNAL; +GrayQueueEntry sgen_gray_object_dequeue (SgenGrayQueue *queue) MONO_INTERNAL; GrayQueueSection* sgen_gray_object_dequeue_section (SgenGrayQueue *queue) MONO_INTERNAL; void sgen_gray_object_enqueue_section (SgenGrayQueue *queue, GrayQueueSection *section) MONO_INTERNAL; void sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func) MONO_INTERNAL; diff --git a/mono/metadata/sgen-workers.c b/mono/metadata/sgen-workers.c index 94ca31c9e6f..2d48745762b 100644 --- a/mono/metadata/sgen-workers.c +++ b/mono/metadata/sgen-workers.c @@ -243,9 +243,9 @@ workers_steal (WorkerData *data, WorkerData *victim_data, gboolean lock) n -= m; sgen_gray_object_alloc_queue_section (queue); - memcpy (queue->first->objects, + memcpy (queue->first->entries, victim_data->stealable_stack + victim_data->stealable_stack_fill - num + n, - sizeof (char*) * m); + sizeof (GrayQueueEntry) * m); queue->first->size = m; /* @@ -253,10 +253,10 @@ workers_steal (WorkerData *data, WorkerData *victim_data, gboolean lock) * Doing so trigger "assert not reached" in sgen-scan-object.h : we use the queue->cursor * to compute the size of the first section during section allocation (via alloc_prepare_func * -> workers_gray_queue_share_redirect -> sgen_gray_object_dequeue_section) which will be then - * set to 0, because queue->cursor is still pointing to queue->first->objects [-1], thus + * set to 0, because queue->cursor is still pointing to queue->first->entries [-1], thus * losing objects in the gray queue. */ - queue->cursor = (char**)queue->first->objects + queue->first->size - 1; + queue->cursor = queue->first->entries + queue->first->size - 1; } victim_data->stealable_stack_fill -= num; @@ -338,8 +338,8 @@ workers_gray_queue_share_redirect (SgenGrayQueue *queue) int num = MIN (section->size, STEALABLE_STACK_SIZE - data->stealable_stack_fill); memcpy (data->stealable_stack + data->stealable_stack_fill, - section->objects + section->size - num, - sizeof (char*) * num); + section->entries + section->size - num, + sizeof (GrayQueueEntry) * num); section->size -= num; data->stealable_stack_fill += num; diff --git a/mono/metadata/sgen-workers.h b/mono/metadata/sgen-workers.h index 9070623673f..d13c4609674 100644 --- a/mono/metadata/sgen-workers.h +++ b/mono/metadata/sgen-workers.h @@ -34,7 +34,7 @@ struct _WorkerData { mono_mutex_t stealable_stack_mutex; volatile int stealable_stack_fill; - char *stealable_stack [STEALABLE_STACK_SIZE]; + GrayQueueEntry stealable_stack [STEALABLE_STACK_SIZE]; }; typedef void (*JobFunc) (WorkerData *worker_data, void *job_data); From 96e37d79b39da628d3b99c362b84b861cdf387b8 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Fri, 22 Aug 2014 14:04:33 -0700 Subject: [PATCH 280/543] [sgen] Pass descriptor, not vtable, to OBJ_COMPLEX_ARR_FOREACH_PTR. Later on, when we enqueue objects with their GC descriptors, we won't load the vtable before scanning (because we'll already have the descriptor), so the scanning macros shouldn't take them as arguments. --- mono/metadata/sgen-descriptor.h | 7 ++++--- mono/metadata/sgen-scan-object.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mono/metadata/sgen-descriptor.h b/mono/metadata/sgen-descriptor.h index 366c7667778..1910f98a117 100644 --- a/mono/metadata/sgen-descriptor.h +++ b/mono/metadata/sgen-descriptor.h @@ -258,15 +258,16 @@ sgen_gc_descr_has_references (mword desc) } while (0) /* this one is untested */ -#define OBJ_COMPLEX_ARR_FOREACH_PTR(vt,obj) do { \ +#define OBJ_COMPLEX_ARR_FOREACH_PTR(desc,obj) do { \ /* there are pointers */ \ - gsize *mbitmap_data = sgen_get_complex_descriptor ((vt)->desc); \ + GCVTable *vt = (GCVTable*)SGEN_LOAD_VTABLE (obj); \ + gsize *mbitmap_data = sgen_get_complex_descriptor ((desc)); \ gsize mbwords = (*mbitmap_data++) - 1; \ gsize el_size = mono_array_element_size (vt->klass); \ char *e_start = (char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector); \ char *e_end = e_start + el_size * mono_array_length_fast ((MonoArray*)(obj)); \ if (0) \ - g_print ("found %d at %p (0x%zx): %s.%s\n", mbwords, (obj), (vt)->desc, vt->klass->name_space, vt->klass->name); \ + g_print ("found %d at %p (0x%zx): %s.%s\n", mbwords, (obj), (desc), (vt)->klass->name_space, (vt)->klass->name); \ while (e_start < e_end) { \ void **_objptr = (void**)e_start; \ gsize *bitmap_data = mbitmap_data; \ diff --git a/mono/metadata/sgen-scan-object.h b/mono/metadata/sgen-scan-object.h index 7cbe57a6c83..d33560cdb00 100644 --- a/mono/metadata/sgen-scan-object.h +++ b/mono/metadata/sgen-scan-object.h @@ -97,7 +97,7 @@ #ifndef SCAN_OBJECT_NOVTABLE case DESC_TYPE_COMPLEX_ARR: /* this is an array of complex structs */ -#define SCAN OBJ_COMPLEX_ARR_FOREACH_PTR (vt, start) +#define SCAN OBJ_COMPLEX_ARR_FOREACH_PTR (desc, start) #ifndef SCAN_OBJECT_NOSCAN SCAN; #endif From 72c15bb6f222184aeeda3c5d4093d698905d29e1 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Fri, 22 Aug 2014 14:06:45 -0700 Subject: [PATCH 281/543] [sgen] Enqueue objects with their descriptors. At the point where we enqueue objects we have already fetched their descriptors, and when we later scan them (after dequeuing) we need the descriptor again, so we avoid cache misses by enqueuing them together. --- mono/metadata/sgen-cardtable.c | 4 +-- mono/metadata/sgen-copy-object.h | 2 +- mono/metadata/sgen-debug.c | 21 ++++++++++++--- mono/metadata/sgen-gc.c | 26 ++++++++++++------- mono/metadata/sgen-gc.h | 36 +++++++++++++++++++++----- mono/metadata/sgen-gray.c | 4 +-- mono/metadata/sgen-gray.h | 3 ++- mono/metadata/sgen-major-scan-object.h | 2 +- mono/metadata/sgen-marksweep.c | 30 +++++++++++---------- mono/metadata/sgen-minor-scan-object.h | 2 +- mono/metadata/sgen-new-bridge.c | 2 ++ mono/metadata/sgen-nursery-allocator.c | 2 +- mono/metadata/sgen-old-bridge.c | 2 ++ mono/metadata/sgen-scan-object.h | 14 +++------- mono/metadata/sgen-tarjan-bridge.c | 2 ++ 15 files changed, 99 insertions(+), 53 deletions(-) diff --git a/mono/metadata/sgen-cardtable.c b/mono/metadata/sgen-cardtable.c index 472244b6312..7ee7e07bee3 100644 --- a/mono/metadata/sgen-cardtable.c +++ b/mono/metadata/sgen-cardtable.c @@ -687,9 +687,9 @@ sgen_cardtable_scan_object (char *obj, mword block_obj_size, guint8 *cards, gboo HEAVY_STAT (++bloby_objects); if (cards) { if (sgen_card_table_is_range_marked (cards, (mword)obj, block_obj_size)) - sgen_get_current_object_ops ()->scan_object (obj, queue); + sgen_get_current_object_ops ()->scan_object (obj, sgen_obj_get_descriptor (obj), queue); } else if (sgen_card_table_region_begin_scanning ((mword)obj, block_obj_size)) { - sgen_get_current_object_ops ()->scan_object (obj, queue); + sgen_get_current_object_ops ()->scan_object (obj, sgen_obj_get_descriptor (obj), queue); } binary_protocol_card_scan (obj, sgen_safe_object_get_size ((MonoObject*)obj)); diff --git a/mono/metadata/sgen-copy-object.h b/mono/metadata/sgen-copy-object.h index adad2514d08..21331c18f06 100644 --- a/mono/metadata/sgen-copy-object.h +++ b/mono/metadata/sgen-copy-object.h @@ -64,7 +64,7 @@ par_copy_object_no_checks (char *destination, MonoVTable *vt, void *obj, mword o obj = destination; if (queue) { SGEN_LOG (9, "Enqueuing gray object %p (%s)", obj, sgen_safe_name (obj)); - GRAY_OBJECT_ENQUEUE (queue, obj); + GRAY_OBJECT_ENQUEUE (queue, obj, sgen_vtable_get_descriptor (vt)); } } diff --git a/mono/metadata/sgen-debug.c b/mono/metadata/sgen-debug.c index 1387676c758..113078c1839 100644 --- a/mono/metadata/sgen-debug.c +++ b/mono/metadata/sgen-debug.c @@ -174,7 +174,8 @@ static gboolean missing_remsets; static void check_consistency_callback (char *start, size_t size, void *dummy) { - GCVTable *vt = (GCVTable*)LOAD_VTABLE (start); + MonoVTable *vt = (MonoVTable*)LOAD_VTABLE (start); + mword desc = sgen_vtable_get_descriptor (vt); SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, vt->klass->name); #include "sgen-scan-object.h" @@ -230,7 +231,8 @@ static void check_mod_union_callback (char *start, size_t size, void *dummy) { gboolean in_los = (gboolean) (size_t) dummy; - GCVTable *vt = (GCVTable*)LOAD_VTABLE (start); + MonoVTable *vt = (MonoVTable*)LOAD_VTABLE (start); + mword desc = sgen_vtable_get_descriptor (vt); guint8 *cards; SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, vt->klass->name); @@ -269,6 +271,8 @@ sgen_check_mod_union_consistency (void) static void check_major_refs_callback (char *start, size_t size, void *dummy) { + mword desc = sgen_obj_get_descriptor (start); + #include "sgen-scan-object.h" } @@ -296,9 +300,13 @@ sgen_check_major_refs (void) void check_object (char *start) { + mword desc; + if (!start) return; + desc = sgen_obj_get_descriptor (start); + #include "sgen-scan-object.h" } @@ -425,6 +433,7 @@ static void verify_object_pointers_callback (char *start, size_t size, void *data) { gboolean allow_missing_pinned = (gboolean) (size_t) data; + mword desc = sgen_obj_get_descriptor (start); #include "sgen-scan-object.h" } @@ -548,6 +557,7 @@ static void check_marked_callback (char *start, size_t size, void *dummy) { gboolean is_los = (gboolean) (size_t) dummy; + mword desc; if (is_los) { if (!sgen_los_object_is_pinned (start)) @@ -557,6 +567,8 @@ check_marked_callback (char *start, size_t size, void *dummy) return; } + desc = sgen_obj_get_descriptor (start); + #include "sgen-scan-object.h" } @@ -608,6 +620,7 @@ scan_object_for_specific_ref (char *start, MonoObject *key) start = forwarded; if (scan_object_for_specific_ref_precise) { + mword desc = sgen_obj_get_descriptor (start); #include "sgen-scan-object.h" } else { mword *words = (mword*)start; @@ -896,7 +909,9 @@ check_reference_for_xdomain (gpointer *ptr, char *obj, MonoDomain *domain) static void scan_object_for_xdomain_refs (char *start, mword size, void *data) { - MonoDomain *domain = ((MonoObject*)start)->vtable->domain; + MonoVTable *vt = (MonoVTable*)SGEN_LOAD_VTABLE (start); + MonoDomain *domain = vt->domain; + mword desc = sgen_vtable_get_descriptor (vt); #include "sgen-scan-object.h" } diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 3d191e7537b..b6da9896e71 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -866,27 +866,28 @@ gboolean sgen_drain_gray_stack (int max_objs, ScanCopyContext ctx) { char *obj; + mword desc; ScanObjectFunc scan_func = ctx.scan_func; GrayQueue *queue = ctx.queue; if (max_objs == -1) { for (;;) { - GRAY_OBJECT_DEQUEUE (queue, &obj); + GRAY_OBJECT_DEQUEUE (queue, &obj, &desc); if (!obj) return TRUE; SGEN_LOG (9, "Precise gray object scan %p (%s)", obj, safe_name (obj)); - scan_func (obj, queue); + scan_func (obj, desc, queue); } } else { int i; do { for (i = 0; i != max_objs; ++i) { - GRAY_OBJECT_DEQUEUE (queue, &obj); + GRAY_OBJECT_DEQUEUE (queue, &obj, &desc); if (!obj) return TRUE; SGEN_LOG (9, "Precise gray object scan %p (%s)", obj, safe_name (obj)); - scan_func (obj, queue); + scan_func (obj, desc, queue); } } while (max_objs < 0); return FALSE; @@ -923,6 +924,7 @@ pin_objects_from_nursery_pin_queue (ScanCopyContext ctx) while (start < end) { void *obj_to_pin = NULL; size_t obj_to_pin_size = 0; + mword desc; addr = *start; @@ -1017,8 +1019,9 @@ pin_objects_from_nursery_pin_queue (ScanCopyContext ctx) /* * Finally - pin the object! */ + desc = sgen_obj_get_descriptor_safe (obj_to_pin); if (scan_func) { - scan_func (obj_to_pin, queue); + scan_func (obj_to_pin, desc, queue); } else { SGEN_LOG (4, "Pinned object %p, vtable %p (%s), count %d\n", obj_to_pin, *(void**)obj_to_pin, safe_name (obj_to_pin), count); @@ -1037,7 +1040,7 @@ pin_objects_from_nursery_pin_queue (ScanCopyContext ctx) #endif pin_object (obj_to_pin); - GRAY_OBJECT_ENQUEUE (queue, obj_to_pin); + GRAY_OBJECT_ENQUEUE (queue, obj_to_pin, desc); if (G_UNLIKELY (do_pin_stats)) sgen_pin_stats_register_object (obj_to_pin, obj_to_pin_size); definitely_pinned [count] = obj_to_pin; @@ -1086,7 +1089,7 @@ sgen_pin_object (void *object, GrayQueue *queue) if (G_UNLIKELY (do_pin_stats)) sgen_pin_stats_register_object (object, safe_object_get_size (object)); - GRAY_OBJECT_ENQUEUE (queue, object); + GRAY_OBJECT_ENQUEUE (queue, object, sgen_obj_get_descriptor (object)); binary_protocol_pin (object, (gpointer)LOAD_VTABLE (object), safe_object_get_size (object)); #ifdef ENABLE_DTRACE @@ -1261,7 +1264,8 @@ unpin_objects_from_queue (SgenGrayQueue *queue) { for (;;) { char *addr; - GRAY_OBJECT_DEQUEUE (queue, &addr); + mword desc; + GRAY_OBJECT_DEQUEUE (queue, &addr, &desc); if (!addr) break; g_assert (SGEN_OBJECT_IS_PINNED (addr)); @@ -2460,7 +2464,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) static void scan_nursery_objects_callback (char *obj, size_t size, ScanCopyContext *ctx) { - ctx->scan_func (obj, ctx->queue); + ctx->scan_func (obj, sgen_obj_get_descriptor (obj), ctx->queue); } static void @@ -2604,7 +2608,7 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, gboolean finish_up_con } sgen_los_pin_object (bigobj->data); if (SGEN_OBJECT_HAS_REFERENCES (bigobj->data)) - GRAY_OBJECT_ENQUEUE (WORKERS_DISTRIBUTE_GRAY_QUEUE, bigobj->data); + GRAY_OBJECT_ENQUEUE (WORKERS_DISTRIBUTE_GRAY_QUEUE, bigobj->data, sgen_obj_get_descriptor (bigobj->data)); if (G_UNLIKELY (do_pin_stats)) sgen_pin_stats_register_object ((char*) bigobj->data, safe_object_get_size ((MonoObject*) bigobj->data)); SGEN_LOG (6, "Marked large object %p (%s) size: %lu from roots", bigobj->data, safe_name (bigobj->data), (unsigned long)sgen_los_object_size (bigobj)); @@ -4260,6 +4264,8 @@ typedef struct { static void collect_references (HeapWalkInfo *hwi, char *start, size_t size) { + mword desc = sgen_obj_get_descriptor (start); + #include "sgen-scan-object.h" } diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 6603072da7f..56aeecfd508 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -349,15 +349,15 @@ typedef struct { #define SGEN_LOAD_VTABLE(addr) ((*(mword*)(addr)) & ~SGEN_VTABLE_BITS_MASK) static inline MONO_ALWAYS_INLINE void -GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj) +GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj, mword desc) { #if SGEN_MAX_DEBUG_LEVEL >= 9 - sgen_gray_object_enqueue (queue, obj); + sgen_gray_object_enqueue (queue, obj, desc); #else if (G_UNLIKELY (!queue->first || queue->cursor == GRAY_LAST_CURSOR_POSITION (queue->first))) { - sgen_gray_object_enqueue (queue, obj); + sgen_gray_object_enqueue (queue, obj, desc); } else { - GrayQueueEntry entry = { obj }; + GrayQueueEntry entry = { obj, desc }; HEAVY_STAT (gc_stats.gray_queue_enqueue_fast_path ++); @@ -372,12 +372,13 @@ GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj) } static inline MONO_ALWAYS_INLINE void -GRAY_OBJECT_DEQUEUE (SgenGrayQueue *queue, char** obj) +GRAY_OBJECT_DEQUEUE (SgenGrayQueue *queue, char** obj, mword *desc) { GrayQueueEntry entry; #if SGEN_MAX_DEBUG_LEVEL >= 9 entry = sgen_gray_object_enqueue (queue); *obj = entry.obj; + *desc = entry.desc; #else if (!queue->first) { HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++); @@ -389,11 +390,13 @@ GRAY_OBJECT_DEQUEUE (SgenGrayQueue *queue, char** obj) } else if (G_UNLIKELY (queue->cursor == GRAY_FIRST_CURSOR_POSITION (queue->first))) { entry = sgen_gray_object_dequeue (queue); *obj = entry.obj; + *desc = entry.desc; } else { HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++); entry = *queue->cursor--; *obj = entry.obj; + *desc = entry.desc; #ifdef SGEN_HEAVY_BINARY_PROTOCOL binary_protocol_gray_dequeue (queue, queue->cursor + 1, *obj); #endif @@ -506,7 +509,7 @@ struct _ObjectList { }; typedef void (*CopyOrMarkObjectFunc) (void**, SgenGrayQueue*); -typedef void (*ScanObjectFunc) (char*, SgenGrayQueue*); +typedef void (*ScanObjectFunc) (char *obj, mword desc, SgenGrayQueue*); typedef void (*ScanVTypeFunc) (char*, mword desc, SgenGrayQueue* BINARY_PROTOCOL_ARG (size_t size)); typedef struct @@ -792,6 +795,27 @@ slow_object_get_size (MonoVTable *vtable, MonoObject* o) } } +static inline mword +sgen_vtable_get_descriptor (MonoVTable *vtable) +{ + return (mword)vtable->gc_descr; +} + +static inline mword +sgen_obj_get_descriptor (char *obj) +{ + MonoVTable *vtable = ((MonoObject*)obj)->vtable; + SGEN_ASSERT (0, !(((mword)vtable) & SGEN_VTABLE_BITS_MASK), "Object can't be tagged"); + return sgen_vtable_get_descriptor (vtable); +} + +static inline mword +sgen_obj_get_descriptor_safe (char *obj) +{ + MonoVTable *vtable = (MonoVTable*)SGEN_LOAD_VTABLE (obj); + return sgen_vtable_get_descriptor (vtable); +} + /* * This function can be called on an object whose first word, the * vtable field, is not intact. This is necessary for the parallel diff --git a/mono/metadata/sgen-gray.c b/mono/metadata/sgen-gray.c index 2031a729cf4..7bc9bddc1cd 100644 --- a/mono/metadata/sgen-gray.c +++ b/mono/metadata/sgen-gray.c @@ -88,9 +88,9 @@ sgen_gray_object_free_queue_section (GrayQueueSection *section) */ void -sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj) +sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj, mword desc) { - GrayQueueEntry entry = { obj }; + GrayQueueEntry entry = { obj, desc }; HEAVY_STAT (gc_stats.gray_queue_enqueue_slow_path ++); diff --git a/mono/metadata/sgen-gray.h b/mono/metadata/sgen-gray.h index 5ad7ab1381c..09f9d5839e5 100644 --- a/mono/metadata/sgen-gray.h +++ b/mono/metadata/sgen-gray.h @@ -69,6 +69,7 @@ typedef enum { typedef struct _GrayQueueEntry GrayQueueEntry; struct _GrayQueueEntry { char *obj; + mword desc; }; /* @@ -120,7 +121,7 @@ struct _SgenSectionGrayQueue { #define GRAY_LAST_CURSOR_POSITION(s) ((s)->entries + SGEN_GRAY_QUEUE_SECTION_SIZE - 1) #define GRAY_FIRST_CURSOR_POSITION(s) ((s)->entries) -void sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj) MONO_INTERNAL; +void sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj, mword desc) MONO_INTERNAL; GrayQueueEntry sgen_gray_object_dequeue (SgenGrayQueue *queue) MONO_INTERNAL; GrayQueueSection* sgen_gray_object_dequeue_section (SgenGrayQueue *queue) MONO_INTERNAL; void sgen_gray_object_enqueue_section (SgenGrayQueue *queue, GrayQueueSection *section) MONO_INTERNAL; diff --git a/mono/metadata/sgen-major-scan-object.h b/mono/metadata/sgen-major-scan-object.h index a4674a2139d..668a9cd6411 100644 --- a/mono/metadata/sgen-major-scan-object.h +++ b/mono/metadata/sgen-major-scan-object.h @@ -56,7 +56,7 @@ extern long long stat_scan_object_called_major; } while (0) static void -CONCURRENT_NAME (major_scan_object) (char *start, SgenGrayQueue *queue) +CONCURRENT_NAME (major_scan_object) (char *start, mword desc, SgenGrayQueue *queue) { SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP; diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index d51769d7955..cdb978776af 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -828,30 +828,30 @@ major_dump_heap (FILE *heap_dump_file) #define LOAD_VTABLE SGEN_LOAD_VTABLE -#define MS_MARK_OBJECT_AND_ENQUEUE_CHECKED(obj,block,queue) do { \ +#define MS_MARK_OBJECT_AND_ENQUEUE_CHECKED(obj,desc,block,queue) do { \ int __word, __bit; \ MS_CALC_MARK_BIT (__word, __bit, (obj)); \ if (!MS_MARK_BIT ((block), __word, __bit) && MS_OBJ_ALLOCED ((obj), (block))) { \ MS_SET_MARK_BIT ((block), __word, __bit); \ if ((block)->has_references) \ - GRAY_OBJECT_ENQUEUE ((queue), (obj)); \ + GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \ binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((MonoObject*)(obj))); \ INC_NUM_MAJOR_OBJECTS_MARKED (); \ } \ } while (0) -#define MS_MARK_OBJECT_AND_ENQUEUE(obj,block,queue) do { \ +#define MS_MARK_OBJECT_AND_ENQUEUE(obj,desc,block,queue) do { \ int __word, __bit; \ MS_CALC_MARK_BIT (__word, __bit, (obj)); \ SGEN_ASSERT (9, MS_OBJ_ALLOCED ((obj), (block)), "object %p not allocated", obj); \ if (!MS_MARK_BIT ((block), __word, __bit)) { \ MS_SET_MARK_BIT ((block), __word, __bit); \ if ((block)->has_references) \ - GRAY_OBJECT_ENQUEUE ((queue), (obj)); \ + GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \ binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((MonoObject*)(obj))); \ INC_NUM_MAJOR_OBJECTS_MARKED (); \ } \ } while (0) -#define MS_PAR_MARK_OBJECT_AND_ENQUEUE(obj,block,queue) do { \ +#define MS_PAR_MARK_OBJECT_AND_ENQUEUE(obj,desc,block,queue) do { \ int __word, __bit; \ gboolean __was_marked; \ SGEN_ASSERT (9, MS_OBJ_ALLOCED ((obj), (block)), "object %p not allocated", obj); \ @@ -859,7 +859,7 @@ major_dump_heap (FILE *heap_dump_file) MS_PAR_SET_MARK_BIT (__was_marked, (block), __word, __bit); \ if (!__was_marked) { \ if ((block)->has_references) \ - GRAY_OBJECT_ENQUEUE ((queue), (obj)); \ + GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \ binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((MonoObject*)(obj))); \ INC_NUM_MAJOR_OBJECTS_MARKED (); \ } \ @@ -877,7 +877,7 @@ pin_major_object (char *obj, SgenGrayQueue *queue) block = MS_BLOCK_FOR_OBJ (obj); block->has_pinned = TRUE; - MS_MARK_OBJECT_AND_ENQUEUE (obj, block, queue); + MS_MARK_OBJECT_AND_ENQUEUE (obj, sgen_obj_get_descriptor (obj), block, queue); } #include "sgen-major-copy-object.h" @@ -895,7 +895,7 @@ major_copy_or_mark_object_concurrent (void **ptr, void *obj, SgenGrayQueue *queu if (objsize <= SGEN_MAX_SMALL_OBJ_SIZE) { MSBlockInfo *block = MS_BLOCK_FOR_OBJ (obj); - MS_MARK_OBJECT_AND_ENQUEUE (obj, block, queue); + MS_MARK_OBJECT_AND_ENQUEUE (obj, sgen_obj_get_descriptor (obj), block, queue); } else { if (sgen_los_object_is_pinned (obj)) return; @@ -909,7 +909,7 @@ major_copy_or_mark_object_concurrent (void **ptr, void *obj, SgenGrayQueue *queu sgen_los_pin_object (obj); if (SGEN_OBJECT_HAS_REFERENCES (obj)) - GRAY_OBJECT_ENQUEUE (queue, obj); + GRAY_OBJECT_ENQUEUE (queue, obj, sgen_obj_get_descriptor (obj)); INC_NUM_MAJOR_OBJECTS_MARKED (); } } @@ -953,7 +953,7 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) block = MS_BLOCK_FOR_OBJ (obj); size_index = block->obj_size_index; evacuate_block_obj_sizes [size_index] = FALSE; - MS_MARK_OBJECT_AND_ENQUEUE (obj, block, queue); + MS_MARK_OBJECT_AND_ENQUEUE (obj, sgen_obj_get_descriptor (obj), block, queue); } return; } @@ -1013,7 +1013,7 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) HEAVY_STAT (++stat_major_objects_evacuated); goto do_copy_object; } else { - MS_MARK_OBJECT_AND_ENQUEUE (obj, block, queue); + MS_MARK_OBJECT_AND_ENQUEUE (obj, sgen_obj_get_descriptor (obj), block, queue); } } else { if (sgen_los_object_is_pinned (obj)) @@ -1029,7 +1029,7 @@ major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue) sgen_los_pin_object (obj); if (SGEN_OBJECT_HAS_REFERENCES (obj)) - GRAY_OBJECT_ENQUEUE (queue, obj); + GRAY_OBJECT_ENQUEUE (queue, obj, sgen_obj_get_descriptor (obj)); } } } @@ -1081,10 +1081,12 @@ mark_pinned_objects_in_block (MSBlockInfo *block, SgenGrayQueue *queue) for (i = 0; i < block->pin_queue_num_entries; ++i) { int index = MS_BLOCK_OBJ_INDEX (block->pin_queue_start [i], block); + char *obj; SGEN_ASSERT (9, index >= 0 && index < MS_BLOCK_FREE / block->obj_size, "invalid object %p index %d max-index %d", block->pin_queue_start [i], index, MS_BLOCK_FREE / block->obj_size); if (index == last_index) continue; - MS_MARK_OBJECT_AND_ENQUEUE_CHECKED (MS_BLOCK_OBJ (block, index), block, queue); + obj = MS_BLOCK_OBJ (block, index); + MS_MARK_OBJECT_AND_ENQUEUE_CHECKED (obj, sgen_obj_get_descriptor (obj), block, queue); last_index = index; } } @@ -1927,7 +1929,7 @@ major_scan_card_table (gboolean mod_union, SgenGrayQueue *queue) } HEAVY_STAT (++scanned_objects); - scan_func (obj, queue); + scan_func (obj, sgen_obj_get_descriptor (obj), queue); next_small: obj += block_obj_size; } diff --git a/mono/metadata/sgen-minor-scan-object.h b/mono/metadata/sgen-minor-scan-object.h index 10f752a73b2..dc91e17f6f4 100644 --- a/mono/metadata/sgen-minor-scan-object.h +++ b/mono/metadata/sgen-minor-scan-object.h @@ -45,7 +45,7 @@ extern long long stat_scan_object_called_nursery; } while (0) static void -SERIAL_SCAN_OBJECT (char *start, SgenGrayQueue *queue) +SERIAL_SCAN_OBJECT (char *start, mword desc, SgenGrayQueue *queue) { SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP; diff --git a/mono/metadata/sgen-new-bridge.c b/mono/metadata/sgen-new-bridge.c index d07203db4d1..51b00e96695 100644 --- a/mono/metadata/sgen-new-bridge.c +++ b/mono/metadata/sgen-new-bridge.c @@ -652,6 +652,7 @@ dfs1 (HashEntry *obj_entry) if (obj_entry) { /* obj_entry needs to be expanded */ src = dyn_array_ptr_pop (&dfs_stack); + if (src) g_assert (!src->v.dfs1.forwarded_to); @@ -664,6 +665,7 @@ dfs1 (HashEntry *obj_entry) if (!obj_entry->v.dfs1.is_visited) { int num_links = 0; + mword desc = sgen_obj_get_descriptor (start); obj_entry->v.dfs1.is_visited = 1; diff --git a/mono/metadata/sgen-nursery-allocator.c b/mono/metadata/sgen-nursery-allocator.c index 3d422e6b7b8..6fc63e54961 100644 --- a/mono/metadata/sgen-nursery-allocator.c +++ b/mono/metadata/sgen-nursery-allocator.c @@ -782,7 +782,7 @@ sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_ if (addr0 < addr1) { if (unpin_queue) - GRAY_OBJECT_ENQUEUE (unpin_queue, addr0); + GRAY_OBJECT_ENQUEUE (unpin_queue, addr0, sgen_obj_get_descriptor_safe (addr0)); else SGEN_UNPIN_OBJECT (addr0); sgen_set_nursery_scan_start (addr0); diff --git a/mono/metadata/sgen-old-bridge.c b/mono/metadata/sgen-old-bridge.c index 42a588164df..4e2ba7b84d7 100644 --- a/mono/metadata/sgen-old-bridge.c +++ b/mono/metadata/sgen-old-bridge.c @@ -521,10 +521,12 @@ dfs1 (HashEntry *obj_entry) obj_entry = dyn_array_ptr_pop (&dfs_stack); if (obj_entry) { + mword desc; src = dyn_array_ptr_pop (&dfs_stack); obj = obj_entry->obj; start = (char*)obj; + desc = sgen_obj_get_descriptor (start); if (src) { //g_print ("link %s -> %s\n", sgen_safe_name (src->obj), sgen_safe_name (obj)); diff --git a/mono/metadata/sgen-scan-object.h b/mono/metadata/sgen-scan-object.h index d33560cdb00..78db6674cb4 100644 --- a/mono/metadata/sgen-scan-object.h +++ b/mono/metadata/sgen-scan-object.h @@ -23,7 +23,8 @@ * object must be given in the variable "char* start". Afterwards, * "start" will point to the start of the next object, if the scanned * object contained references. If not, the value of "start" should - * be considered undefined after executing this code. + * be considered undefined after executing this code. The object's + * GC descriptor must be in the variable "mword desc". * * Modifiers (automatically undefined): * @@ -40,17 +41,8 @@ { #ifndef SCAN_OBJECT_NOVTABLE - GCVTable *vt; - mword desc; - - vt = (GCVTable*)SGEN_LOAD_VTABLE (start); - //type = vt->desc & 0x7; - - /* gcc should be smart enough to remove the bounds check, but it isn't:( */ - desc = vt->desc; - #if defined(SGEN_HEAVY_BINARY_PROTOCOL) && defined(SCAN_OBJECT_PROTOCOL) - binary_protocol_scan_begin (start, vt, sgen_safe_object_get_size ((MonoObject*)start)); + binary_protocol_scan_begin (start, SGEN_LOAD_VTABLE (start), sgen_safe_object_get_size ((MonoObject*)start)); #endif #else #if defined(SGEN_HEAVY_BINARY_PROTOCOL) && defined(SCAN_OBJECT_PROTOCOL) diff --git a/mono/metadata/sgen-tarjan-bridge.c b/mono/metadata/sgen-tarjan-bridge.c index 59013f70124..5c6525e9ec7 100644 --- a/mono/metadata/sgen-tarjan-bridge.c +++ b/mono/metadata/sgen-tarjan-bridge.c @@ -661,6 +661,7 @@ push_all (ScanData *data) { MonoObject *obj = data->obj; char *start = (char*)obj; + mword desc = sgen_obj_get_descriptor (start); #if DUMP_GRAPH printf ("**scanning %p %s\n", obj, safe_name_bridge (obj)); @@ -712,6 +713,7 @@ compute_low (ScanData *data) { MonoObject *obj = data->obj; char *start = (char*)obj; + mword desc = sgen_obj_get_descriptor (start); #include "sgen-scan-object.h" } From 78408ae100cf457186dc49b8d590f1529fe7f531 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Fri, 22 Aug 2014 14:14:50 -0700 Subject: [PATCH 282/543] [sgen] Free gray queue sections after GC, not at start of next. We trim the free list of the gray queue to a maximum number of sections, but we did it at each collection start, so the extraneous sections were kept around between collections. --- mono/metadata/sgen-gc.c | 2 ++ mono/metadata/sgen-gray.c | 30 +++++++++++++++++------------- mono/metadata/sgen-gray.h | 1 + 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index b6da9896e71..2b73b701c32 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -1736,6 +1736,8 @@ finish_gray_stack (int generation, GrayQueue *queue) } g_assert (sgen_gray_object_queue_is_empty (queue)); + + sgen_gray_object_queue_trim_free_list (queue); } void diff --git a/mono/metadata/sgen-gray.c b/mono/metadata/sgen-gray.c index 7bc9bddc1cd..9201f98cd86 100644 --- a/mono/metadata/sgen-gray.c +++ b/mono/metadata/sgen-gray.c @@ -196,21 +196,10 @@ sgen_gray_object_enqueue_section (SgenGrayQueue *queue, GrayQueueSection *sectio } void -sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func) +sgen_gray_object_queue_trim_free_list (SgenGrayQueue *queue) { GrayQueueSection *section, *next; - int i; - - g_assert (sgen_gray_object_queue_is_empty (queue)); - - queue->alloc_prepare_func = NULL; - queue->alloc_prepare_data = NULL; -#ifdef SGEN_CHECK_GRAY_OBJECT_ENQUEUE - queue->enqueue_check_func = enqueue_check_func; -#endif - - /* Free the extra sections allocated during the last collection */ - i = 0; + int i = 0; for (section = queue->free_list; section && i < GRAY_QUEUE_LENGTH_LIMIT - 1; section = section->next) { STATE_ASSERT (section, GRAY_QUEUE_SECTION_STATE_FREE_LIST); i ++; @@ -225,6 +214,21 @@ sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enq } } +void +sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func) +{ + g_assert (sgen_gray_object_queue_is_empty (queue)); + + queue->alloc_prepare_func = NULL; + queue->alloc_prepare_data = NULL; +#ifdef SGEN_CHECK_GRAY_OBJECT_ENQUEUE + queue->enqueue_check_func = enqueue_check_func; +#endif + + /* Free the extra sections allocated during the last collection */ + sgen_gray_object_queue_trim_free_list (queue); +} + static void invalid_prepare_func (SgenGrayQueue *queue) { diff --git a/mono/metadata/sgen-gray.h b/mono/metadata/sgen-gray.h index 09f9d5839e5..1ea9fad5465 100644 --- a/mono/metadata/sgen-gray.h +++ b/mono/metadata/sgen-gray.h @@ -125,6 +125,7 @@ void sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj, mword desc) MONO GrayQueueEntry sgen_gray_object_dequeue (SgenGrayQueue *queue) MONO_INTERNAL; GrayQueueSection* sgen_gray_object_dequeue_section (SgenGrayQueue *queue) MONO_INTERNAL; void sgen_gray_object_enqueue_section (SgenGrayQueue *queue, GrayQueueSection *section) MONO_INTERNAL; +void sgen_gray_object_queue_trim_free_list (SgenGrayQueue *queue) MONO_INTERNAL; void sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func) MONO_INTERNAL; void sgen_gray_object_queue_init_invalid (SgenGrayQueue *queue) MONO_INTERNAL; void sgen_gray_object_queue_init_with_alloc_prepare (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func, From 533b11a0f6059f5b5d29b9d2559989e83320b723 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Fri, 22 Aug 2014 14:58:24 -0700 Subject: [PATCH 283/543] [sgen] Simplify sgen_drain_gray_stack(). This seems to have accumulated code duplication by accident. --- mono/metadata/sgen-gc.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 2b73b701c32..572c788c707 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -861,37 +861,29 @@ sgen_add_to_global_remset (gpointer ptr, gpointer obj) * Scan objects in the gray stack until the stack is empty. This should be called * frequently after each object is copied, to achieve better locality and cache * usage. + * + * max_objs is the maximum number of objects to scan, or -1 to scan until the stack is + * empty. */ gboolean sgen_drain_gray_stack (int max_objs, ScanCopyContext ctx) { - char *obj; - mword desc; ScanObjectFunc scan_func = ctx.scan_func; GrayQueue *queue = ctx.queue; - if (max_objs == -1) { - for (;;) { + do { + int i; + for (i = 0; i != max_objs; ++i) { + char *obj; + mword desc; GRAY_OBJECT_DEQUEUE (queue, &obj, &desc); if (!obj) return TRUE; SGEN_LOG (9, "Precise gray object scan %p (%s)", obj, safe_name (obj)); scan_func (obj, desc, queue); } - } else { - int i; - - do { - for (i = 0; i != max_objs; ++i) { - GRAY_OBJECT_DEQUEUE (queue, &obj, &desc); - if (!obj) - return TRUE; - SGEN_LOG (9, "Precise gray object scan %p (%s)", obj, safe_name (obj)); - scan_func (obj, desc, queue); - } - } while (max_objs < 0); - return FALSE; - } + } while (max_objs < 0); + return FALSE; } /* From 53b798f915720da0f09e0d4d731b33e0a299eea6 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 27 Aug 2014 14:33:56 -0700 Subject: [PATCH 284/543] [sgen] Added some comments. --- mono/metadata/sgen-gc.c | 1 + mono/metadata/sgen-major-scan-object.h | 11 +++++++++++ mono/metadata/sgen-scan-object.h | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 572c788c707..8a1518586c1 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -2310,6 +2310,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) MONO_GC_CHECKPOINT_4 (GENERATION_NURSERY); + /* FIXME: why is this here? */ ctx.scan_func = current_object_ops.scan_object; ctx.copy_func = NULL; ctx.queue = &gray_queue; diff --git a/mono/metadata/sgen-major-scan-object.h b/mono/metadata/sgen-major-scan-object.h index 668a9cd6411..dafc1d7ea4d 100644 --- a/mono/metadata/sgen-major-scan-object.h +++ b/mono/metadata/sgen-major-scan-object.h @@ -37,6 +37,17 @@ extern long long stat_scan_object_called_major; #define CONCURRENT_NAME(x) x #endif +/* + * FIXME: We use the same scanning function in the concurrent collector whether we scan + * during the starting/finishing collection pause (with the world stopped) or from the + * concurrent worker thread. + * + * As long as the world is stopped, we should just follow pointers into the nursery and + * evict if possible. In that case we also don't need the ALWAYS_ADD_TO_GLOBAL_REMSET case, + * which only seems to make sense for when the world is stopped, in which case we only need + * it because we don't follow into the nursery. + */ + #undef HANDLE_PTR #define HANDLE_PTR(ptr,obj) do { \ void *__old = *(ptr); \ diff --git a/mono/metadata/sgen-scan-object.h b/mono/metadata/sgen-scan-object.h index 78db6674cb4..ad569dda359 100644 --- a/mono/metadata/sgen-scan-object.h +++ b/mono/metadata/sgen-scan-object.h @@ -26,6 +26,10 @@ * be considered undefined after executing this code. The object's * GC descriptor must be in the variable "mword desc". * + * The macro `HANDLE_PTR` will be invoked for every reference encountered while scanning the + * object. It is called with two parameters: The pointer to the reference (not the + * reference itself!) as well as the pointer to the scanned object. + * * Modifiers (automatically undefined): * * SCAN_OBJECT_NOSCAN - if defined, don't actually scan the object, From aa8cabc373c02ef81edf286d1f53619cfe581e12 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 27 Aug 2014 14:35:51 -0700 Subject: [PATCH 285/543] [sgen] do-while loop instead of 1-unrolled while loop in bitmap scan. --- mono/metadata/sgen-descriptor.h | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/mono/metadata/sgen-descriptor.h b/mono/metadata/sgen-descriptor.h index 1910f98a117..7e94eb64023 100644 --- a/mono/metadata/sgen-descriptor.h +++ b/mono/metadata/sgen-descriptor.h @@ -183,20 +183,13 @@ sgen_gc_descr_has_references (mword desc) void **_objptr = (void**)(obj); \ gsize _bmap = (desc) >> 16; \ _objptr += OBJECT_HEADER_WORDS; \ - { \ + do { \ int _index = GNUC_BUILTIN_CTZ (_bmap); \ _objptr += _index; \ _bmap >>= (_index + 1); \ HANDLE_PTR (_objptr, (obj)); \ _objptr ++; \ - } \ - while (_bmap) { \ - int _index = GNUC_BUILTIN_CTZ (_bmap); \ - _objptr += _index; \ - _bmap >>= (_index + 1); \ - HANDLE_PTR (_objptr, (obj)); \ - _objptr ++; \ - } \ + } while (_bmap); \ } while (0) #else #define OBJ_BITMAP_FOREACH_PTR(desc,obj) do { \ From 0f7be7ca38d1cc7dcdc0f1b7318c45394f4a20af Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 27 Aug 2014 14:37:03 -0700 Subject: [PATCH 286/543] [sgen] Heavy statistics counters for scanned object descriptors. --- mono/metadata/sgen-descriptor.c | 28 ++++++++++++++++++++++++++ mono/metadata/sgen-descriptor.h | 20 +++++++++++------- mono/metadata/sgen-gc.c | 1 + mono/metadata/sgen-major-scan-object.h | 4 ++++ mono/metadata/sgen-minor-scan-object.h | 4 ++++ 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/mono/metadata/sgen-descriptor.c b/mono/metadata/sgen-descriptor.c index c578a91cfb2..6da8f7290d9 100644 --- a/mono/metadata/sgen-descriptor.c +++ b/mono/metadata/sgen-descriptor.c @@ -43,6 +43,7 @@ #define _XOPEN_SOURCE #endif +#include "utils/mono-counters.h" #include "metadata/sgen-gc.h" #define MAX_USER_DESCRIPTORS 16 @@ -58,6 +59,9 @@ static MonoGCRootMarkFunc user_descriptors [MAX_USER_DESCRIPTORS]; static int user_descriptors_next = 0; static void *all_ref_root_descrs [32]; +#ifdef HEAVY_STATISTICS +static long long stat_scanned_count_per_descriptor [DESC_TYPE_MAX]; +#endif static int alloc_complex_descriptor (gsize *bitmap, int numbits) @@ -348,4 +352,28 @@ sgen_get_user_descriptor_func (mword desc) return user_descriptors [desc >> ROOT_DESC_TYPE_SHIFT]; } +#ifdef HEAVY_STATISTICS +void +sgen_descriptor_count_scanned_object (mword desc) +{ + int type = desc & 7; + SGEN_ASSERT (0, type, "Descriptor type can't be zero"); + ++stat_scanned_count_per_descriptor [type - 1]; +} +#endif + +void +sgen_init_descriptors (void) +{ +#ifdef HEAVY_STATISTICS + mono_counters_register ("# scanned RUN_LENGTH", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_scanned_count_per_descriptor [DESC_TYPE_RUN_LENGTH - 1]); + mono_counters_register ("# scanned SMALL_BITMAP", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_scanned_count_per_descriptor [DESC_TYPE_SMALL_BITMAP - 1]); + mono_counters_register ("# scanned COMPLEX", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_scanned_count_per_descriptor [DESC_TYPE_COMPLEX - 1]); + mono_counters_register ("# scanned VECTOR", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_scanned_count_per_descriptor [DESC_TYPE_VECTOR - 1]); + mono_counters_register ("# scanned LARGE_BITMAP", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_scanned_count_per_descriptor [DESC_TYPE_LARGE_BITMAP - 1]); + mono_counters_register ("# scanned COMPLEX_ARR", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_scanned_count_per_descriptor [DESC_TYPE_COMPLEX_ARR - 1]); + mono_counters_register ("# scanned COMPLEX_PTRFREE", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_scanned_count_per_descriptor [DESC_TYPE_COMPLEX_PTRFREE - 1]); +#endif +} + #endif diff --git a/mono/metadata/sgen-descriptor.h b/mono/metadata/sgen-descriptor.h index 7e94eb64023..53f47236405 100644 --- a/mono/metadata/sgen-descriptor.h +++ b/mono/metadata/sgen-descriptor.h @@ -82,13 +82,14 @@ enum { * copy_object_no_checks(), without having to fetch the * object's class. */ - DESC_TYPE_RUN_LENGTH = 1, /* 16 bits aligned byte size | 1-3 (offset, numptr) bytes tuples */ - DESC_TYPE_SMALL_BITMAP, /* 16 bits aligned byte size | 16-48 bit bitmap */ - DESC_TYPE_COMPLEX, /* index for bitmap into complex_descriptors */ - DESC_TYPE_VECTOR, /* 10 bits element size | 1 bit kind | 2 bits desc | element desc */ - DESC_TYPE_LARGE_BITMAP, /* | 29-61 bitmap bits */ - DESC_TYPE_COMPLEX_ARR, /* index for bitmap into complex_descriptors */ - DESC_TYPE_COMPLEX_PTRFREE, /*Nothing, used to encode large ptr objects. */ + DESC_TYPE_RUN_LENGTH = 1, /* 16 bits aligned byte size | 1-3 (offset, numptr) bytes tuples */ + DESC_TYPE_SMALL_BITMAP = 2, /* 16 bits aligned byte size | 16-48 bit bitmap */ + DESC_TYPE_COMPLEX = 3, /* index for bitmap into complex_descriptors */ + DESC_TYPE_VECTOR = 4, /* 10 bits element size | 1 bit kind | 2 bits desc | element desc */ + DESC_TYPE_LARGE_BITMAP = 5, /* | 29-61 bitmap bits */ + DESC_TYPE_COMPLEX_ARR = 6, /* index for bitmap into complex_descriptors */ + DESC_TYPE_COMPLEX_PTRFREE = 7, /*Nothing, used to encode large ptr objects. */ + DESC_TYPE_MAX = 7, /* values for array kind */ DESC_TYPE_V_SZARRAY = 0, /*vector with no bounds data */ DESC_TYPE_V_ARRAY = 1, /* array with bounds data */ @@ -117,6 +118,11 @@ gsize* sgen_get_complex_descriptor (mword desc) MONO_INTERNAL; void* sgen_get_complex_descriptor_bitmap (mword desc) MONO_INTERNAL; MonoGCRootMarkFunc sgen_get_user_descriptor_func (mword desc) MONO_INTERNAL; +void sgen_init_descriptors (void) MONO_INTERNAL; + +#ifdef HEAVY_STATISTICS +void sgen_descriptor_count_scanned_object (mword desc) MONO_INTERNAL; +#endif static inline gboolean sgen_gc_descr_has_references (mword desc) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 8a1518586c1..29eaa6d6ab3 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -4605,6 +4605,7 @@ mono_gc_base_init (void) sgen_init_fin_weak_hash (); sgen_init_stw (); sgen_init_hash_table (); + sgen_init_descriptors (); sgen_register_fixed_internal_mem_type (INTERNAL_MEM_SECTION, SGEN_SIZEOF_GC_MEM_SECTION); sgen_register_fixed_internal_mem_type (INTERNAL_MEM_FINALIZE_READY_ENTRY, sizeof (FinalizeReadyEntry)); diff --git a/mono/metadata/sgen-major-scan-object.h b/mono/metadata/sgen-major-scan-object.h index dafc1d7ea4d..6f2c0089e8b 100644 --- a/mono/metadata/sgen-major-scan-object.h +++ b/mono/metadata/sgen-major-scan-object.h @@ -71,6 +71,10 @@ CONCURRENT_NAME (major_scan_object) (char *start, mword desc, SgenGrayQueue *que { SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP; +#ifdef HEAVY_STATISTICS + sgen_descriptor_count_scanned_object (desc); +#endif + #define SCAN_OBJECT_PROTOCOL #include "sgen-scan-object.h" diff --git a/mono/metadata/sgen-minor-scan-object.h b/mono/metadata/sgen-minor-scan-object.h index dc91e17f6f4..3cff269a7da 100644 --- a/mono/metadata/sgen-minor-scan-object.h +++ b/mono/metadata/sgen-minor-scan-object.h @@ -49,6 +49,10 @@ SERIAL_SCAN_OBJECT (char *start, mword desc, SgenGrayQueue *queue) { SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP; +#ifdef HEAVY_STATISTICS + sgen_descriptor_count_scanned_object (desc); +#endif + #define SCAN_OBJECT_PROTOCOL #include "sgen-scan-object.h" From aa82365b6b81330d4bad665e16c4889b5f9e5540 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 27 Aug 2014 14:37:24 -0700 Subject: [PATCH 287/543] [sgen] Scoping fix in a macro. --- mono/metadata/sgen-major-scan-object.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/sgen-major-scan-object.h b/mono/metadata/sgen-major-scan-object.h index 6f2c0089e8b..14b11317096 100644 --- a/mono/metadata/sgen-major-scan-object.h +++ b/mono/metadata/sgen-major-scan-object.h @@ -51,9 +51,9 @@ extern long long stat_scan_object_called_major; #undef HANDLE_PTR #define HANDLE_PTR(ptr,obj) do { \ void *__old = *(ptr); \ - void *__copy; \ SGEN_OBJECT_LAYOUT_STATISTICS_MARK_BITMAP ((obj), (ptr)); \ if (__old && FOLLOW_OBJECT (__old)) { \ + void *__copy; \ PREFETCH_DYNAMIC_HEAP (__old); \ CONCURRENT_NAME (major_copy_or_mark_object) ((ptr), __old, queue); \ __copy = *(ptr); \ From 62df12c0e4653ef985c5d4ea07fa28f143ce6d7f Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Thu, 28 Aug 2014 16:32:06 -0700 Subject: [PATCH 288/543] [sgen] Move HEAVY_STAT macro to sgen-conf.h. That's where we define HEAVY_STATISTICS, too. --- mono/metadata/sgen-conf.h | 6 ++++++ mono/metadata/sgen-gc.h | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mono/metadata/sgen-conf.h b/mono/metadata/sgen-conf.h index 009d0f66ee2..babee94026e 100644 --- a/mono/metadata/sgen-conf.h +++ b/mono/metadata/sgen-conf.h @@ -41,6 +41,12 @@ typedef guint64 mword; */ // #define HEAVY_STATISTICS +#ifdef HEAVY_STATISTICS +#define HEAVY_STAT(x) x +#else +#define HEAVY_STAT(x) +#endif + /* * Define this to allow the user to change the nursery size by * specifying its value in the MONO_GC_PARAMS environmental diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 56aeecfd508..eb156d183c6 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -190,14 +190,10 @@ extern LOCK_DECLARE (sgen_interruption_mutex); #endif #ifdef HEAVY_STATISTICS -#define HEAVY_STAT(x) x - extern long long stat_objects_alloced_degraded; extern long long stat_bytes_alloced_degraded; extern long long stat_copy_object_called_major; extern long long stat_objects_copied_major; -#else -#define HEAVY_STAT(x) #endif #define SGEN_ASSERT(level, a, ...) do { \ From 18ee4f22a3486613312bbccb72d27d45c70d3290 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Thu, 28 Aug 2014 16:33:00 -0700 Subject: [PATCH 289/543] [sgen] Move GRAY_OBJECT_ENQUEUE/DEQUEUE to sgen-gray.h. --- mono/metadata/sgen-gc.h | 56 --------------------------------------- mono/metadata/sgen-gray.h | 54 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 56 deletions(-) diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index eb156d183c6..3832f54e119 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -344,62 +344,6 @@ typedef struct { */ #define SGEN_LOAD_VTABLE(addr) ((*(mword*)(addr)) & ~SGEN_VTABLE_BITS_MASK) -static inline MONO_ALWAYS_INLINE void -GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj, mword desc) -{ -#if SGEN_MAX_DEBUG_LEVEL >= 9 - sgen_gray_object_enqueue (queue, obj, desc); -#else - if (G_UNLIKELY (!queue->first || queue->cursor == GRAY_LAST_CURSOR_POSITION (queue->first))) { - sgen_gray_object_enqueue (queue, obj, desc); - } else { - GrayQueueEntry entry = { obj, desc }; - - HEAVY_STAT (gc_stats.gray_queue_enqueue_fast_path ++); - - *++queue->cursor = entry; -#ifdef SGEN_HEAVY_BINARY_PROTOCOL - binary_protocol_gray_enqueue (queue, queue->cursor, obj); -#endif - } - - PREFETCH (obj); -#endif -} - -static inline MONO_ALWAYS_INLINE void -GRAY_OBJECT_DEQUEUE (SgenGrayQueue *queue, char** obj, mword *desc) -{ - GrayQueueEntry entry; -#if SGEN_MAX_DEBUG_LEVEL >= 9 - entry = sgen_gray_object_enqueue (queue); - *obj = entry.obj; - *desc = entry.desc; -#else - if (!queue->first) { - HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++); - - *obj = NULL; -#ifdef SGEN_HEAVY_BINARY_PROTOCOL - binary_protocol_gray_dequeue (queue, queue->cursor, *obj); -#endif - } else if (G_UNLIKELY (queue->cursor == GRAY_FIRST_CURSOR_POSITION (queue->first))) { - entry = sgen_gray_object_dequeue (queue); - *obj = entry.obj; - *desc = entry.desc; - } else { - HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++); - - entry = *queue->cursor--; - *obj = entry.obj; - *desc = entry.desc; -#ifdef SGEN_HEAVY_BINARY_PROTOCOL - binary_protocol_gray_dequeue (queue, queue->cursor + 1, *obj); -#endif - } -#endif -} - /* List of what each bit on of the vtable gc bits means. */ diff --git a/mono/metadata/sgen-gray.h b/mono/metadata/sgen-gray.h index 1ea9fad5465..b277765d374 100644 --- a/mono/metadata/sgen-gray.h +++ b/mono/metadata/sgen-gray.h @@ -147,4 +147,58 @@ sgen_gray_object_queue_is_empty (SgenGrayQueue *queue) return queue->first == NULL; } +static inline MONO_ALWAYS_INLINE void +GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj, mword desc) +{ +#if SGEN_MAX_DEBUG_LEVEL >= 9 + sgen_gray_object_enqueue (queue, obj, desc); +#else + if (G_UNLIKELY (!queue->first || queue->cursor == GRAY_LAST_CURSOR_POSITION (queue->first))) { + sgen_gray_object_enqueue (queue, obj, desc); + } else { + GrayQueueEntry entry = { obj, desc }; + + HEAVY_STAT (gc_stats.gray_queue_enqueue_fast_path ++); + + *++queue->cursor = entry; +#ifdef SGEN_HEAVY_BINARY_PROTOCOL + binary_protocol_gray_enqueue (queue, queue->cursor, obj); +#endif + } +#endif +} + +static inline MONO_ALWAYS_INLINE void +GRAY_OBJECT_DEQUEUE (SgenGrayQueue *queue, char** obj, mword *desc) +{ + GrayQueueEntry entry; +#if SGEN_MAX_DEBUG_LEVEL >= 9 + entry = sgen_gray_object_enqueue (queue); + *obj = entry.obj; + *desc = entry.desc; +#else + if (!queue->first) { + HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++); + + *obj = NULL; +#ifdef SGEN_HEAVY_BINARY_PROTOCOL + binary_protocol_gray_dequeue (queue, queue->cursor, *obj); +#endif + } else if (G_UNLIKELY (queue->cursor == GRAY_FIRST_CURSOR_POSITION (queue->first))) { + entry = sgen_gray_object_dequeue (queue); + *obj = entry.obj; + *desc = entry.desc; + } else { + HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++); + + entry = *queue->cursor--; + *obj = entry.obj; + *desc = entry.desc; +#ifdef SGEN_HEAVY_BINARY_PROTOCOL + binary_protocol_gray_dequeue (queue, queue->cursor + 1, *obj); +#endif + } +#endif +} + #endif From 8e714a70a1982555085e33b5a5aa430c022bdcfa Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Tue, 2 Sep 2014 12:38:48 -0700 Subject: [PATCH 290/543] [sgen] Keep allocated blocks in array instead of linked list. We were spending a lot of time in major_iterate_live_block_ranges() on the lcscbench benchmark, mainly from following the linked block list. This change makes it much faster. --- mono/metadata/sgen-marksweep.c | 44 +++++++++++------------------- mono/metadata/sgen-pointer-queue.c | 34 +++++++++++++++++++++++ mono/metadata/sgen-pointer-queue.h | 2 ++ 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index cdb978776af..194ad2fb0bd 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -40,6 +40,7 @@ #include "metadata/sgen-memory-governor.h" #include "metadata/sgen-layout-stats.h" #include "metadata/gc-internal.h" +#include "metadata/sgen-pointer-queue.h" #define SGEN_HAVE_CONCURRENT_MARK @@ -79,7 +80,6 @@ struct _MSBlockInfo { unsigned int has_pinned : 1; /* means cannot evacuate */ unsigned int is_to_space : 1; unsigned int swept : 1; - MSBlockInfo *next; char *block; void **free_list; MSBlockInfo *next_free; @@ -169,14 +169,15 @@ static gboolean concurrent_mark; #endif /* all allocated blocks in the system */ -static MSBlockInfo *all_blocks; +static SgenPointerQueue allocated_blocks; /* non-allocated block free-list */ static void *empty_blocks = NULL; static size_t num_empty_blocks = 0; -#define FOREACH_BLOCK(bl) for ((bl) = all_blocks; (bl); (bl) = (bl)->next) { -#define END_FOREACH_BLOCK } +#define FOREACH_BLOCK(bl) { size_t __index; for (__index = 0; __index < allocated_blocks.next_slot; ++__index) { (bl) = allocated_blocks.data [__index]; +#define END_FOREACH_BLOCK } } +#define DELETE_BLOCK_IN_FOREACH() (allocated_blocks.data [__index] = NULL) static size_t num_major_sections = 0; /* one free block list for each block object size */ @@ -337,12 +338,8 @@ check_block_free_list (MSBlockInfo *block, int size, gboolean pinned) if (block->swept) g_assert (block->free_list); - /* the block must be in the all_blocks list */ - for (b = all_blocks; b; b = b->next) { - if (b == block) - break; - } - g_assert (b == block); + /* the block must be in the allocated_blocks array */ + g_assert (sgen_pointer_queue_find (&allocated_blocks, block) != (size_t)-1); } } @@ -459,8 +456,7 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) info->next_free = free_blocks [size_index]; free_blocks [size_index] = info; - info->next = all_blocks; - all_blocks = info; + sgen_pointer_queue_add (&allocated_blocks, info); ++num_major_sections; return TRUE; @@ -1193,7 +1189,7 @@ static void ms_sweep (void) { int i; - MSBlockInfo **iter; + MSBlockInfo *block; /* statistics for evacuation */ int *slots_available = alloca (sizeof (int) * num_block_obj_sizes); @@ -1217,9 +1213,7 @@ ms_sweep (void) } /* traverse all blocks, free and zero unmarked objects */ - iter = &all_blocks; - while (*iter) { - MSBlockInfo *block = *iter; + FOREACH_BLOCK (block) { int count; gboolean have_live = FALSE; gboolean has_pinned; @@ -1264,8 +1258,6 @@ ms_sweep (void) slots_available [obj_size_index] += count; } - iter = &block->next; - /* * If there are free slots in the block, add * the block to the corresponding free list. @@ -1283,7 +1275,7 @@ ms_sweep (void) * Blocks without live objects are removed from the * block list and freed. */ - *iter = block->next; + DELETE_BLOCK_IN_FOREACH (); binary_protocol_empty (MS_BLOCK_OBJ (block, 0), (char*)MS_BLOCK_OBJ (block, count) - (char*)MS_BLOCK_OBJ (block, 0)); ms_free_block (block->block); @@ -1291,7 +1283,8 @@ ms_sweep (void) --num_major_sections; } - } + } END_FOREACH_BLOCK; + sgen_pointer_queue_remove_nulls (&allocated_blocks); for (i = 0; i < num_block_obj_sizes; ++i) { float usage = (float)slots_used [i] / (float)slots_available [i]; @@ -1437,18 +1430,13 @@ major_start_major_collection (void) // Sweep all unswept blocks if (lazy_sweep) { - MSBlockInfo **iter; + MSBlockInfo *block; MONO_GC_SWEEP_BEGIN (GENERATION_OLD, TRUE); - iter = &all_blocks; - while (*iter) { - MSBlockInfo *block = *iter; - + FOREACH_BLOCK (block) { sweep_block (block, TRUE); - - iter = &block->next; - } + } END_FOREACH_BLOCK; MONO_GC_SWEEP_END (GENERATION_OLD, TRUE); } diff --git a/mono/metadata/sgen-pointer-queue.c b/mono/metadata/sgen-pointer-queue.c index fe491605d52..3fc1a42f8d1 100644 --- a/mono/metadata/sgen-pointer-queue.c +++ b/mono/metadata/sgen-pointer-queue.c @@ -64,6 +64,27 @@ sgen_pointer_queue_search (SgenPointerQueue *queue, void *addr) return first; } +/* + * Removes all NULL pointers from the queue. + */ +void +sgen_pointer_queue_remove_nulls (SgenPointerQueue *queue) +{ + void **start, **cur, **end; + start = cur = queue->data; + end = queue->data + queue->next_slot; + while (cur < end) { + if (*cur) + *start++ = *cur++; + else + ++cur; + } + queue->next_slot = start - queue->data; +} + +/* + * Sorts the pointers in the queue, then removes duplicates. + */ void sgen_pointer_queue_sort_uniq (SgenPointerQueue *queue) { @@ -85,4 +106,17 @@ sgen_pointer_queue_sort_uniq (SgenPointerQueue *queue) SGEN_LOG (5, "Pointer queue reduced to size: %lu", queue->next_slot); } +/* + * Does a linear search through the pointer queue to find `ptr`. Returns the index if + * found, otherwise (size_t)-1. + */ +size_t +sgen_pointer_queue_find (SgenPointerQueue *queue, void *ptr) +{ + for (size_t i = 0; i < queue->next_slot; ++i) + if (queue->data [i] == ptr) + return i; + return (size_t)-1; +} + #endif diff --git a/mono/metadata/sgen-pointer-queue.h b/mono/metadata/sgen-pointer-queue.h index 031870f1285..d972f3cc92e 100644 --- a/mono/metadata/sgen-pointer-queue.h +++ b/mono/metadata/sgen-pointer-queue.h @@ -28,7 +28,9 @@ typedef struct { void sgen_pointer_queue_add (SgenPointerQueue *queue, void *ptr) MONO_INTERNAL; void sgen_pointer_queue_clear (SgenPointerQueue *queue) MONO_INTERNAL; +void sgen_pointer_queue_remove_nulls (SgenPointerQueue *queue) MONO_INTERNAL; void sgen_pointer_queue_sort_uniq (SgenPointerQueue *queue) MONO_INTERNAL; size_t sgen_pointer_queue_search (SgenPointerQueue *queue, void *addr) MONO_INTERNAL; +size_t sgen_pointer_queue_find (SgenPointerQueue *queue, void *ptr) MONO_INTERNAL; #endif From 0cfc7008a0699d2be81dfa1a277cb0ad1e87156d Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Fri, 5 Sep 2014 20:50:47 +0200 Subject: [PATCH 291/543] [sgen] Don't unroll run-length scanning loop. --- mono/metadata/sgen-descriptor.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/mono/metadata/sgen-descriptor.h b/mono/metadata/sgen-descriptor.h index 53f47236405..c06354dd958 100644 --- a/mono/metadata/sgen-descriptor.h +++ b/mono/metadata/sgen-descriptor.h @@ -174,8 +174,6 @@ sgen_gc_descr_has_references (mword desc) void **_objptr = (void**)(obj); \ _objptr += ((desc) >> 16) & 0xff; \ _objptr_end = _objptr + (((desc) >> 24) & 0xff); \ - HANDLE_PTR (_objptr, (obj)); \ - _objptr ++; \ while (_objptr < _objptr_end) { \ HANDLE_PTR (_objptr, (obj)); \ _objptr++; \ From 70980c0cde736ec3be0367c7688162400773df8b Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Sun, 7 Sep 2014 14:16:40 +0200 Subject: [PATCH 292/543] [sgen] Move SGen statistics out of gc-internal.h. This introduced a dependency from sgen-conf.h to a lot of compilation units in metadata, leading to long build times when experimenting with SGen. --- mono/metadata/gc-internal.h | 9 --------- mono/metadata/gc.c | 8 -------- mono/metadata/sgen-gc.c | 1 + mono/metadata/sgen-gray.c | 29 +++++++++++++++++++++++++---- mono/metadata/sgen-gray.h | 17 ++++++++++++++--- 5 files changed, 40 insertions(+), 24 deletions(-) diff --git a/mono/metadata/gc-internal.h b/mono/metadata/gc-internal.h index f5e9ba95dc0..8e8c35f8360 100644 --- a/mono/metadata/gc-internal.h +++ b/mono/metadata/gc-internal.h @@ -13,7 +13,6 @@ #include #include #include -#include #include typedef struct { @@ -22,14 +21,6 @@ typedef struct { long long minor_gc_time; long long major_gc_time; long long major_gc_time_concurrent; -#ifdef HEAVY_STATISTICS - unsigned long long gray_queue_section_alloc; - unsigned long long gray_queue_section_free; - unsigned long long gray_queue_enqueue_fast_path; - unsigned long long gray_queue_dequeue_fast_path; - unsigned long long gray_queue_enqueue_slow_path; - unsigned long long gray_queue_dequeue_slow_path; -#endif } GCStats; #define mono_domain_finalizers_lock(domain) mono_mutex_lock (&(domain)->finalizable_objects_hash_lock); diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 95073555641..a0472955071 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -1155,14 +1155,6 @@ mono_gc_init (void) mono_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time); mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time); mono_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent); -#ifdef HEAVY_STATISTICS - mono_counters_register ("Gray Queue alloc section", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_section_alloc); - mono_counters_register ("Gray Queue free section", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_section_free); - mono_counters_register ("Gray Queue enqueue fast path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_enqueue_fast_path); - mono_counters_register ("Gray Queue dequeue fast path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_dequeue_fast_path); - mono_counters_register ("Gray Queue enqueue slow path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_enqueue_slow_path); - mono_counters_register ("Gray Queue dequeue slow path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_dequeue_slow_path); -#endif mono_gc_base_init (); diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 29eaa6d6ab3..01d92284afe 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -4606,6 +4606,7 @@ mono_gc_base_init (void) sgen_init_stw (); sgen_init_hash_table (); sgen_init_descriptors (); + sgen_init_gray_queues (); sgen_register_fixed_internal_mem_type (INTERNAL_MEM_SECTION, SGEN_SIZEOF_GC_MEM_SECTION); sgen_register_fixed_internal_mem_type (INTERNAL_MEM_FINALIZE_READY_ENTRY, sizeof (FinalizeReadyEntry)); diff --git a/mono/metadata/sgen-gray.c b/mono/metadata/sgen-gray.c index 9201f98cd86..247608751fe 100644 --- a/mono/metadata/sgen-gray.c +++ b/mono/metadata/sgen-gray.c @@ -25,6 +25,15 @@ #include "utils/mono-counters.h" #include "sgen-protocol.h" +#ifdef HEAVY_STATISTICS +unsigned long long stat_gray_queue_section_alloc; +unsigned long long stat_gray_queue_section_free; +unsigned long long stat_gray_queue_enqueue_fast_path; +unsigned long long stat_gray_queue_dequeue_fast_path; +unsigned long long stat_gray_queue_enqueue_slow_path; +unsigned long long stat_gray_queue_dequeue_slow_path; +#endif + #define GRAY_QUEUE_LENGTH_LIMIT 64 #ifdef SGEN_CHECK_GRAY_OBJECT_SECTIONS @@ -46,7 +55,7 @@ sgen_gray_object_alloc_queue_section (SgenGrayQueue *queue) { GrayQueueSection *section; - HEAVY_STAT (gc_stats.gray_queue_section_alloc ++); + HEAVY_STAT (stat_gray_queue_section_alloc ++); if (queue->alloc_prepare_func) queue->alloc_prepare_func (queue); @@ -75,7 +84,7 @@ sgen_gray_object_alloc_queue_section (SgenGrayQueue *queue) void sgen_gray_object_free_queue_section (GrayQueueSection *section) { - HEAVY_STAT (gc_stats.gray_queue_section_free ++); + HEAVY_STAT (stat_gray_queue_section_free ++); STATE_TRANSITION (section, GRAY_QUEUE_SECTION_STATE_FLOATING, GRAY_QUEUE_SECTION_STATE_FREED); sgen_free_internal (section, INTERNAL_MEM_GRAY_QUEUE); @@ -92,7 +101,7 @@ sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj, mword desc) { GrayQueueEntry entry = { obj, desc }; - HEAVY_STAT (gc_stats.gray_queue_enqueue_slow_path ++); + HEAVY_STAT (stat_gray_queue_enqueue_slow_path ++); SGEN_ASSERT (9, obj, "enqueueing a null object"); //sgen_check_objref (obj); @@ -124,7 +133,7 @@ sgen_gray_object_dequeue (SgenGrayQueue *queue) { GrayQueueEntry entry; - HEAVY_STAT (gc_stats.gray_queue_dequeue_slow_path ++); + HEAVY_STAT (stat_gray_queue_dequeue_slow_path ++); if (sgen_gray_object_queue_is_empty (queue)) { entry.obj = NULL; @@ -353,4 +362,16 @@ sgen_section_gray_queue_enqueue (SgenSectionGrayQueue *queue, GrayQueueSection * unlock_section_queue (queue); } +void +sgen_init_gray_queues (void) +{ +#ifdef HEAVY_STATISTICS + mono_counters_register ("Gray Queue alloc section", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_gray_queue_section_alloc); + mono_counters_register ("Gray Queue free section", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_gray_queue_section_free); + mono_counters_register ("Gray Queue enqueue fast path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_gray_queue_enqueue_fast_path); + mono_counters_register ("Gray Queue dequeue fast path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_gray_queue_dequeue_fast_path); + mono_counters_register ("Gray Queue enqueue slow path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_gray_queue_enqueue_slow_path); + mono_counters_register ("Gray Queue dequeue slow path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_gray_queue_dequeue_slow_path); +#endif +} #endif diff --git a/mono/metadata/sgen-gray.h b/mono/metadata/sgen-gray.h index b277765d374..c0ccd616bd7 100644 --- a/mono/metadata/sgen-gray.h +++ b/mono/metadata/sgen-gray.h @@ -121,6 +121,17 @@ struct _SgenSectionGrayQueue { #define GRAY_LAST_CURSOR_POSITION(s) ((s)->entries + SGEN_GRAY_QUEUE_SECTION_SIZE - 1) #define GRAY_FIRST_CURSOR_POSITION(s) ((s)->entries) +#ifdef HEAVY_STATISTICS +extern unsigned long long stat_gray_queue_section_alloc; +extern unsigned long long stat_gray_queue_section_free; +extern unsigned long long stat_gray_queue_enqueue_fast_path; +extern unsigned long long stat_gray_queue_dequeue_fast_path; +extern unsigned long long stat_gray_queue_enqueue_slow_path; +extern unsigned long long stat_gray_queue_dequeue_slow_path; +#endif + +void sgen_init_gray_queues (void) MONO_INTERNAL; + void sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj, mword desc) MONO_INTERNAL; GrayQueueEntry sgen_gray_object_dequeue (SgenGrayQueue *queue) MONO_INTERNAL; GrayQueueSection* sgen_gray_object_dequeue_section (SgenGrayQueue *queue) MONO_INTERNAL; @@ -158,7 +169,7 @@ GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj, mword desc) } else { GrayQueueEntry entry = { obj, desc }; - HEAVY_STAT (gc_stats.gray_queue_enqueue_fast_path ++); + HEAVY_STAT (stat_gray_queue_enqueue_fast_path ++); *++queue->cursor = entry; #ifdef SGEN_HEAVY_BINARY_PROTOCOL @@ -178,7 +189,7 @@ GRAY_OBJECT_DEQUEUE (SgenGrayQueue *queue, char** obj, mword *desc) *desc = entry.desc; #else if (!queue->first) { - HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++); + HEAVY_STAT (stat_gray_queue_dequeue_fast_path ++); *obj = NULL; #ifdef SGEN_HEAVY_BINARY_PROTOCOL @@ -189,7 +200,7 @@ GRAY_OBJECT_DEQUEUE (SgenGrayQueue *queue, char** obj, mword *desc) *obj = entry.obj; *desc = entry.desc; } else { - HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++); + HEAVY_STAT (stat_gray_queue_dequeue_fast_path ++); entry = *queue->cursor--; *obj = entry.obj; From ac83118056d32239ab267958ef0e1c35c9afb668 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Tue, 16 Sep 2014 10:01:34 +0200 Subject: [PATCH 293/543] [sgen] Shift, don't divide, just to make sure. --- mono/metadata/sgen-gc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 3832f54e119..c979c312615 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -548,7 +548,7 @@ static inline gboolean sgen_nursery_is_to_space (char *object) { size_t idx = (object - sgen_nursery_start) >> SGEN_TO_SPACE_GRANULE_BITS; - size_t byte = idx / 8; + size_t byte = idx >> 3; size_t bit = idx & 0x7; SGEN_ASSERT (4, sgen_ptr_in_nursery (object), "object %p is not in nursery [%p - %p]", object, sgen_get_nursery_start (), sgen_get_nursery_end ()); From e8efdfa3604172748c42f5859fb153ff0673b1ea Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Tue, 2 Sep 2014 13:09:29 -0700 Subject: [PATCH 294/543] [sgen] Macro abstractions for pointer tagging. --- mono/metadata/Makefile.am | 3 ++- mono/metadata/sgen-gc.c | 8 +++---- mono/metadata/sgen-gc.h | 30 +++++++++++++++++-------- mono/metadata/sgen-tagged-pointer.h | 34 +++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 mono/metadata/sgen-tagged-pointer.h diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index 7a744e03bdf..d27404acb0f 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -268,7 +268,8 @@ sgen_sources = \ sgen-layout-stats.c \ sgen-layout-stats.h \ sgen-qsort.c \ - sgen-qsort.h + sgen-qsort.h \ + sgen-tagged-pointer.h libmonoruntime_la_SOURCES = $(common_sources) $(gc_dependent_sources) $(null_gc_sources) $(boehm_sources) libmonoruntime_la_CFLAGS = $(BOEHM_DEFINES) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 01d92284afe..2b1c8740c68 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -1101,7 +1101,7 @@ sgen_parallel_pin_or_update (void **ptr, void *obj, MonoVTable *vt, SgenGrayQueu gboolean major_pinned = FALSE; if (sgen_ptr_in_nursery (obj)) { - if (SGEN_CAS_PTR (obj, (void*)((mword)vt | SGEN_PINNED_BIT), vt) == vt) { + if (SGEN_CAS_PTR (obj, SGEN_POINTER_TAG_PINNED (vt), vt) == vt) { sgen_pin_object (obj, queue); break; } @@ -1112,13 +1112,13 @@ sgen_parallel_pin_or_update (void **ptr, void *obj, MonoVTable *vt, SgenGrayQueu vtable_word = *(mword*)obj; /*someone else forwarded it, update the pointer and bail out*/ - if (vtable_word & SGEN_FORWARDED_BIT) { - *ptr = (void*)(vtable_word & ~SGEN_VTABLE_BITS_MASK); + if (SGEN_POINTER_IS_TAGGED_FORWARDED (vtable_word)) { + *ptr = SGEN_POINTER_UNTAG_VTABLE (vtable_word); break; } /*someone pinned it, nothing to do.*/ - if (vtable_word & SGEN_PINNED_BIT || major_pinned) + if (SGEN_POINTER_IS_TAGGED_PINNED (vtable_word) || major_pinned) break; } } diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index c979c312615..076d03bc9d7 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -319,30 +319,42 @@ typedef struct { * The values are already shifted. * The forwarding address is stored in the sync block. */ -#define SGEN_FORWARDED_BIT 1 -#define SGEN_PINNED_BIT 2 + #define SGEN_VTABLE_BITS_MASK 0x3 +#include "sgen-tagged-pointer.h" + +#define SGEN_POINTER_IS_TAGGED_FORWARDED(p) SGEN_POINTER_IS_TAGGED_1((p)) +#define SGEN_POINTER_TAG_FORWARDED(p) SGEN_POINTER_TAG_1((p)) + +#define SGEN_POINTER_IS_TAGGED_PINNED(p) SGEN_POINTER_IS_TAGGED_2((p)) +#define SGEN_POINTER_TAG_PINNED(p) SGEN_POINTER_TAG_2((p)) + +#define SGEN_POINTER_UNTAG_VTABLE(p) SGEN_POINTER_UNTAG_12((p)) + /* returns NULL if not forwarded, or the forwarded address */ -#define SGEN_OBJECT_IS_FORWARDED(obj) (((mword*)(obj))[0] & SGEN_FORWARDED_BIT ? (void*)(((mword*)(obj))[0] & ~SGEN_VTABLE_BITS_MASK) : NULL) -#define SGEN_OBJECT_IS_PINNED(obj) (((mword*)(obj))[0] & SGEN_PINNED_BIT) +#define SGEN_VTABLE_IS_FORWARDED(vtable) (SGEN_POINTER_IS_TAGGED_FORWARDED ((vtable)) ? SGEN_POINTER_UNTAG_VTABLE ((vtable)) : NULL) +#define SGEN_OBJECT_IS_FORWARDED(obj) (SGEN_VTABLE_IS_FORWARDED (((mword*)(obj))[0])) + +#define SGEN_VTABLE_IS_PINNED(vtable) SGEN_POINTER_IS_TAGGED_PINNED ((vtable)) +#define SGEN_OBJECT_IS_PINNED(obj) (SGEN_VTABLE_IS_PINNED (((mword*)(obj))[0])) /* set the forwarded address fw_addr for object obj */ #define SGEN_FORWARD_OBJECT(obj,fw_addr) do { \ - ((mword*)(obj))[0] = (mword)(fw_addr) | SGEN_FORWARDED_BIT; \ + *(void**)(obj) = SGEN_POINTER_TAG_FORWARDED ((fw_addr)); \ } while (0) #define SGEN_PIN_OBJECT(obj) do { \ - ((mword*)(obj))[0] |= SGEN_PINNED_BIT; \ + *(void**)(obj) = SGEN_POINTER_TAG_PINNED (*(void**)(obj)); \ } while (0) #define SGEN_UNPIN_OBJECT(obj) do { \ - ((mword*)(obj))[0] &= ~SGEN_PINNED_BIT; \ + *(void**)(obj) = SGEN_POINTER_UNTAG_2 (*(void**)(obj)); \ } while (0) /* * Since we set bits in the vtable, use the macro to load it from the pointer to * an object that is potentially pinned. */ -#define SGEN_LOAD_VTABLE(addr) ((*(mword*)(addr)) & ~SGEN_VTABLE_BITS_MASK) +#define SGEN_LOAD_VTABLE(addr) SGEN_POINTER_UNTAG_12 (*(void**)(addr)) /* List of what each bit on of the vtable gc bits means. @@ -745,7 +757,7 @@ static inline mword sgen_obj_get_descriptor (char *obj) { MonoVTable *vtable = ((MonoObject*)obj)->vtable; - SGEN_ASSERT (0, !(((mword)vtable) & SGEN_VTABLE_BITS_MASK), "Object can't be tagged"); + SGEN_ASSERT (0, !SGEN_POINTER_IS_TAGGED_1_OR_2 (vtable), "Object can't be tagged"); return sgen_vtable_get_descriptor (vtable); } diff --git a/mono/metadata/sgen-tagged-pointer.h b/mono/metadata/sgen-tagged-pointer.h new file mode 100644 index 00000000000..fc065f7f96b --- /dev/null +++ b/mono/metadata/sgen-tagged-pointer.h @@ -0,0 +1,34 @@ +/* + * sgen-tagged-pointer.h: Macros for tagging and untagging pointers. + * + * Copyright (C) 2014 Xamarin Inc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License 2.0 as published by the Free Software Foundation; + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License 2.0 along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MONO_SGEN_TAGGED_POINTER_H__ +#define __MONO_SGEN_TAGGED_POINTER_H__ + +#define SGEN_POINTER_IS_TAGGED_1(p) ((mword)(p) & 1) +#define SGEN_POINTER_TAG_1(p) ((void*)((mword)(p) | 1)) +#define SGEN_POINTER_UNTAG_1(p) ((void*)((mword)(p) & ~1)) + +#define SGEN_POINTER_IS_TAGGED_2(p) ((mword)(p) & 2) +#define SGEN_POINTER_TAG_2(p) ((void*)((mword)(p) | 2)) +#define SGEN_POINTER_UNTAG_2(p) ((void*)((mword)(p) & ~2)) + +#define SGEN_POINTER_IS_TAGGED_1_OR_2(p) ((mword)(p) & 3) +#define SGEN_POINTER_UNTAG_12(p) ((void*)((mword)(p) & ~3)) + +#endif From a12c4b8099dfaade0524a16a0ba43bd8f52dafd3 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Tue, 2 Sep 2014 13:29:56 -0700 Subject: [PATCH 295/543] [sgen] Tag block pointers with whether the blocks contain references. --- mono/metadata/sgen-marksweep.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index 194ad2fb0bd..89806871343 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -168,6 +168,12 @@ static gboolean have_swept; static gboolean concurrent_mark; #endif +#define BLOCK_IS_TAGGED_HAS_REFERENCES(bl) SGEN_POINTER_IS_TAGGED_1 ((bl)) +#define BLOCK_TAG_HAS_REFERENCES(bl) SGEN_POINTER_TAG_1 ((bl)) +#define BLOCK_UNTAG_HAS_REFERENCES(bl) SGEN_POINTER_UNTAG_1 ((bl)) + +#define BLOCK_TAG(bl) ((bl)->has_references ? BLOCK_TAG_HAS_REFERENCES ((bl)) : (bl)) + /* all allocated blocks in the system */ static SgenPointerQueue allocated_blocks; @@ -175,7 +181,8 @@ static SgenPointerQueue allocated_blocks; static void *empty_blocks = NULL; static size_t num_empty_blocks = 0; -#define FOREACH_BLOCK(bl) { size_t __index; for (__index = 0; __index < allocated_blocks.next_slot; ++__index) { (bl) = allocated_blocks.data [__index]; +#define FOREACH_BLOCK(bl) { size_t __index; for (__index = 0; __index < allocated_blocks.next_slot; ++__index) { (bl) = BLOCK_UNTAG_HAS_REFERENCES (allocated_blocks.data [__index]); +#define FOREACH_BLOCK_HAS_REFERENCES(bl,hr) { size_t __index; for (__index = 0; __index < allocated_blocks.next_slot; ++__index) { (bl) = allocated_blocks.data [__index]; (hr) = BLOCK_IS_TAGGED_HAS_REFERENCES ((bl)); (bl) = BLOCK_UNTAG_HAS_REFERENCES ((bl)); #define END_FOREACH_BLOCK } } #define DELETE_BLOCK_IN_FOREACH() (allocated_blocks.data [__index] = NULL) @@ -339,7 +346,7 @@ check_block_free_list (MSBlockInfo *block, int size, gboolean pinned) g_assert (block->free_list); /* the block must be in the allocated_blocks array */ - g_assert (sgen_pointer_queue_find (&allocated_blocks, block) != (size_t)-1); + g_assert (sgen_pointer_queue_find (&allocated_blocks, BLOCK_TAG (block)) != (size_t)-1); } } @@ -456,7 +463,7 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) info->next_free = free_blocks [size_index]; free_blocks [size_index] = info; - sgen_pointer_queue_add (&allocated_blocks, info); + sgen_pointer_queue_add (&allocated_blocks, BLOCK_TAG (info)); ++num_major_sections; return TRUE; @@ -1705,9 +1712,10 @@ static void major_iterate_live_block_ranges (sgen_cardtable_block_callback callback) { MSBlockInfo *block; + gboolean has_references; - FOREACH_BLOCK (block) { - if (block->has_references) + FOREACH_BLOCK_HAS_REFERENCES (block, has_references) { + if (has_references) callback ((mword)MS_BLOCK_FOR_BLOCK_INFO (block), MS_BLOCK_SIZE); } END_FOREACH_BLOCK; } @@ -1772,6 +1780,7 @@ static void major_scan_card_table (gboolean mod_union, SgenGrayQueue *queue) { MSBlockInfo *block; + gboolean has_references; ScanObjectFunc scan_func = sgen_get_current_object_ops ()->scan_object; #ifdef SGEN_HAVE_CONCURRENT_MARK @@ -1781,11 +1790,11 @@ major_scan_card_table (gboolean mod_union, SgenGrayQueue *queue) g_assert (!mod_union); #endif - FOREACH_BLOCK (block) { + FOREACH_BLOCK_HAS_REFERENCES (block, has_references) { int block_obj_size; char *block_start; - if (!block->has_references) + if (!has_references) continue; block_obj_size = block->obj_size; @@ -1932,14 +1941,15 @@ static void major_count_cards (long long *num_total_cards, long long *num_marked_cards) { MSBlockInfo *block; + gboolean has_references; long long total_cards = 0; long long marked_cards = 0; - FOREACH_BLOCK (block) { + FOREACH_BLOCK_HAS_REFERENCES (block, has_references) { guint8 *cards = sgen_card_table_get_card_scan_address ((mword) MS_BLOCK_FOR_BLOCK_INFO (block)); int i; - if (!block->has_references) + if (!has_references) continue; total_cards += CARDS_PER_BLOCK; From c70c3c429aec4deff5b52c7e18cc89ecc265e928 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Tue, 2 Sep 2014 18:57:25 -0700 Subject: [PATCH 296/543] [sgen] Don't use callback for pinning cemented objects. --- mono/metadata/sgen-gc.c | 11 ++--------- mono/metadata/sgen-pinning.c | 5 +++-- mono/metadata/sgen-pinning.h | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 2b1c8740c68..6516957a3a0 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -2180,13 +2180,6 @@ init_gray_queue (void) } } -static void -pin_stage_object_callback (char *obj, size_t size, void *data) -{ - sgen_pin_stage_ptr (obj); - /* FIXME: do pin stats if enabled */ -} - /* * Collect objects in the nursery. Returns whether to trigger a major * collection. @@ -2271,7 +2264,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) mono_profiler_gc_event (MONO_GC_EVENT_MARK_START, 0); pin_from_roots (sgen_get_nursery_start (), nursery_next, WORKERS_DISTRIBUTE_GRAY_QUEUE); /* pin cemented objects */ - sgen_cement_iterate (pin_stage_object_callback, NULL); + sgen_pin_cemented_objects (); /* identify pinned objects */ sgen_optimize_pin_queue (); sgen_pinning_setup_section (nursery_section); @@ -2547,7 +2540,7 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, gboolean finish_up_con * * FIXME: We could evict now! */ - sgen_cement_iterate (pin_stage_object_callback, NULL); + sgen_pin_cemented_objects (); } if (!concurrent_collection_in_progress) diff --git a/mono/metadata/sgen-pinning.c b/mono/metadata/sgen-pinning.c index d91692d42e9..71a8dbefebe 100644 --- a/mono/metadata/sgen-pinning.c +++ b/mono/metadata/sgen-pinning.c @@ -266,7 +266,7 @@ sgen_cement_lookup_or_register (char *obj) } void -sgen_cement_iterate (IterateObjectCallbackFunc callback, void *callback_data) +sgen_pin_cemented_objects (void) { int i; for (i = 0; i < SGEN_CEMENT_HASH_SIZE; ++i) { @@ -275,7 +275,8 @@ sgen_cement_iterate (IterateObjectCallbackFunc callback, void *callback_data) SGEN_ASSERT (5, cement_hash [i].count >= SGEN_CEMENT_THRESHOLD, "Cementing hash inconsistent"); - callback (cement_hash [i].obj, 0, callback_data); + sgen_pin_stage_ptr (cement_hash [i].obj); + /* FIXME: do pin stats if enabled */ } } diff --git a/mono/metadata/sgen-pinning.h b/mono/metadata/sgen-pinning.h index 46db46536cd..19840beb646 100644 --- a/mono/metadata/sgen-pinning.h +++ b/mono/metadata/sgen-pinning.h @@ -53,7 +53,7 @@ void sgen_cement_concurrent_start (void) MONO_INTERNAL; void sgen_cement_concurrent_finish (void) MONO_INTERNAL; gboolean sgen_cement_lookup (char *obj) MONO_INTERNAL; gboolean sgen_cement_lookup_or_register (char *obj) MONO_INTERNAL; -void sgen_cement_iterate (IterateObjectCallbackFunc callback, void *callback_data) MONO_INTERNAL; +void sgen_pin_cemented_objects (void) MONO_INTERNAL; void sgen_cement_clear_below_threshold (void) MONO_INTERNAL; #endif From 1fbdf06d04d99c27e866884e3cf18a4391b7cbdb Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 29 Sep 2014 14:30:09 -0400 Subject: [PATCH 297/543] [runtime] Enable the new interrupt code on ios. --- mono/utils/mono-threads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index 008c3c86b5b..d5b2239e93e 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -737,7 +737,7 @@ mono_thread_info_new_interrupt_enabled (void) #if defined (__i386__) || defined(__x86_64__) return !disable_new_interrupt; #endif -#if defined(__arm__) && !defined(__APPLE__) +#if defined(__arm__) return !disable_new_interrupt; #endif return FALSE; From ada4b4b06fb4e0c4d1566c265cd21a97159a4fe9 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Mon, 29 Sep 2014 16:00:45 -0400 Subject: [PATCH 298/543] [sgen] Remove useless internal allocation --- mono/metadata/sgen-gc.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 6516957a3a0..9ac29632957 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -2054,19 +2054,13 @@ job_scan_thread_data (WorkerData *worker_data, void *job_data_untyped) sgen_free_internal_dynamic (job_data, sizeof (ScanThreadDataJobData), INTERNAL_MEM_WORKER_JOB_DATA); } -typedef struct -{ - FinalizeReadyEntry *list; -} ScanFinalizerEntriesJobData; - static void job_scan_finalizer_entries (WorkerData *worker_data, void *job_data_untyped) { - ScanFinalizerEntriesJobData *job_data = job_data_untyped; + FinalizeReadyEntry *list = job_data_untyped; ScanCopyContext ctx = { NULL, current_object_ops.copy_or_mark_object, sgen_workers_get_job_gray_queue (worker_data) }; - scan_finalizer_entries (job_data->list, ctx); - sgen_free_internal_dynamic (job_data, sizeof (ScanFinalizerEntriesJobData), INTERNAL_MEM_WORKER_JOB_DATA); + scan_finalizer_entries (list, ctx); } static void @@ -2192,7 +2186,6 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) char *nursery_next; FinishRememberedSetScanJobData *frssjd; ScanFromRegisteredRootsJobData *scrrjd_normal, *scrrjd_wbarrier; - ScanFinalizerEntriesJobData *sfejd_fin_ready, *sfejd_critical_fin; ScanThreadDataJobData *stdjd; mword fragment_total; ScanCopyContext ctx; @@ -2355,13 +2348,8 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) g_assert (!sgen_collection_is_concurrent ()); /* Scan the list of objects ready for finalization. If */ - sfejd_fin_ready = sgen_alloc_internal_dynamic (sizeof (ScanFinalizerEntriesJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE); - sfejd_fin_ready->list = fin_ready_list; - sgen_workers_enqueue_job (job_scan_finalizer_entries, sfejd_fin_ready); - - sfejd_critical_fin = sgen_alloc_internal_dynamic (sizeof (ScanFinalizerEntriesJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE); - sfejd_critical_fin->list = critical_fin_list; - sgen_workers_enqueue_job (job_scan_finalizer_entries, sfejd_critical_fin); + sgen_workers_enqueue_job (job_scan_finalizer_entries, fin_ready_list); + sgen_workers_enqueue_job (job_scan_finalizer_entries, critical_fin_list); MONO_GC_CHECKPOINT_8 (GENERATION_NURSERY); @@ -2477,7 +2465,6 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, gboolean finish_up_con GCRootReport root_report = { 0 }; ScanFromRegisteredRootsJobData *scrrjd_normal, *scrrjd_wbarrier; ScanThreadDataJobData *stdjd; - ScanFinalizerEntriesJobData *sfejd_fin_ready, *sfejd_critical_fin; ScanCopyContext ctx; if (concurrent_collection_in_progress) { @@ -2696,13 +2683,8 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, gboolean finish_up_con report_finalizer_roots (); /* scan the list of objects ready for finalization */ - sfejd_fin_ready = sgen_alloc_internal_dynamic (sizeof (ScanFinalizerEntriesJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE); - sfejd_fin_ready->list = fin_ready_list; - sgen_workers_enqueue_job (job_scan_finalizer_entries, sfejd_fin_ready); - - sfejd_critical_fin = sgen_alloc_internal_dynamic (sizeof (ScanFinalizerEntriesJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE); - sfejd_critical_fin->list = critical_fin_list; - sgen_workers_enqueue_job (job_scan_finalizer_entries, sfejd_critical_fin); + sgen_workers_enqueue_job (job_scan_finalizer_entries, fin_ready_list); + sgen_workers_enqueue_job (job_scan_finalizer_entries, critical_fin_list); if (scan_mod_union) { g_assert (finish_up_concurrent_mark); From 4e3ca74fcb7463bc32af7ac0c46b6f4706340532 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Mon, 29 Sep 2014 13:52:00 -0700 Subject: [PATCH 299/543] Fix build on pre-C99 compilers. --- mono/metadata/sgen-pointer-queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mono/metadata/sgen-pointer-queue.c b/mono/metadata/sgen-pointer-queue.c index 3fc1a42f8d1..f99c5bc5ced 100644 --- a/mono/metadata/sgen-pointer-queue.c +++ b/mono/metadata/sgen-pointer-queue.c @@ -113,7 +113,8 @@ sgen_pointer_queue_sort_uniq (SgenPointerQueue *queue) size_t sgen_pointer_queue_find (SgenPointerQueue *queue, void *ptr) { - for (size_t i = 0; i < queue->next_slot; ++i) + size_t i; + for (i = 0; i < queue->next_slot; ++i) if (queue->data [i] == ptr) return i; return (size_t)-1; From dbd022aba4db6a9fae3dbe5167bec679ba69630b Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Mon, 29 Sep 2014 17:34:38 -0400 Subject: [PATCH 300/543] Enable build on RHEL and CentOS --- mono-core.spec.in | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/mono-core.spec.in b/mono-core.spec.in index 0b7337d05d5..90d0b581219 100644 --- a/mono-core.spec.in +++ b/mono-core.spec.in @@ -4,6 +4,9 @@ %ifnarch %ix86 x86_64 %define llvm no +%endif + +%ifnarch %ix86 x86_64 s390x %define sgen no %endif @@ -16,10 +19,14 @@ Version: @VERSION@ Release: 0 Source0: mono-%{version}.tar.bz2 BuildRequires: bison +%if 0%{?suse_version} BuildRequires: fdupes +BuildRequires: xorg-x11-libX11-devel +%else +BuildRequires: libX11-devel +%endif BuildRequires: gcc-c++ BuildRequires: pkgconfig -BuildRequires: xorg-x11-libX11-devel BuildRequires: zlib-devel %ifnarch ia64 BuildRequires: valgrind-devel @@ -48,7 +55,9 @@ Conflicts: banshee < 1.0 Conflicts: f-spot < 0.4 Conflicts: helix-banshee < 1.0 Conflicts: mono-addins < 0.3.1 +%if 0%{?suse_version} Recommends: libgdiplus0 >= 2.6 +%endif %if %llvm == yes Recommends: libmono-llvm0 = %{version}-%{release} %endif @@ -92,6 +101,7 @@ export CFLAGS=" $RPM_OPT_FLAGS -fno-strict-aliasing" export PATH=/opt/novell/llvm-mono/bin:$PATH %endif %configure \ + --target=%{_host} \ --with-sgen=%{sgen} \ %if %llvm == yes --enable-loadedllvm \ @@ -104,6 +114,7 @@ export PATH=/opt/novell/llvm-mono/bin:$PATH --with-moonlight=no #make # We are not -jN safe! %{?jobs:-j%jobs} # We are now ! +make get-monolite-latest make %{?_smp_mflags} %install @@ -130,7 +141,9 @@ rm -f %buildroot%_prefix/lib/mono/2.0/cilc.exe* ln -s . %buildroot%_prefix%_prefix RPM_BUILD_ROOT=%buildroot%_prefix /usr/lib/rpm/brp-compress rm %buildroot%_prefix%_prefix +%if 0%{?suse_version} %fdupes %buildroot%_prefix +%endif %find_lang mcs %clean From c9044d71bb96440ddc7d998eddd48f02182d6ce2 Mon Sep 17 00:00:00 2001 From: Alexander Bekrenev Date: Tue, 30 Sep 2014 10:46:14 +0400 Subject: [PATCH 301/543] MembershipUser::UpdateUser method fix --- mcs/class/System.Web/System.Web.Security/MembershipUser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.Web/System.Web.Security/MembershipUser.cs b/mcs/class/System.Web/System.Web.Security/MembershipUser.cs index b2bae459a52..13a7319cbae 100644 --- a/mcs/class/System.Web/System.Web.Security/MembershipUser.cs +++ b/mcs/class/System.Web/System.Web.Security/MembershipUser.cs @@ -94,7 +94,7 @@ void UpdateSelf (MembershipUser fromUser) internal void UpdateUser () { - MembershipUser newUser = Provider.GetUser (name, false); + MembershipUser newUser = Provider.GetUser (UserName, false); UpdateSelf (newUser); } From 01ffcd4145742dd09798a62c5661d1ff5ee37651 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Tue, 30 Sep 2014 09:47:24 +0200 Subject: [PATCH 302/543] [mcs] struct initializers are still experimental --- mcs/errors/cs0573-2.cs | 7 +++++++ mcs/errors/cs0573.cs | 7 +++++++ mcs/errors/cs1644-46.cs | 8 -------- mcs/errors/cs1736-2.cs | 4 +++- mcs/mcs/class.cs | 7 +++++-- mcs/tests/gtest-autoproperty-09.cs | 1 + mcs/tests/gtest-autoproperty-10.cs | 1 + mcs/tests/test-906.cs | 1 + mcs/tests/test-primary-ctor-01.cs | 1 + mcs/tests/test-primary-ctor-07.cs | 2 ++ 10 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 mcs/errors/cs0573-2.cs create mode 100644 mcs/errors/cs0573.cs delete mode 100644 mcs/errors/cs1644-46.cs diff --git a/mcs/errors/cs0573-2.cs b/mcs/errors/cs0573-2.cs new file mode 100644 index 00000000000..443bed39123 --- /dev/null +++ b/mcs/errors/cs0573-2.cs @@ -0,0 +1,7 @@ +// CS0573: 'S': Structs cannot have instance property or field initializers +// Line: 6 + +struct S +{ + public int Prop { get; set; } = 3; +} diff --git a/mcs/errors/cs0573.cs b/mcs/errors/cs0573.cs new file mode 100644 index 00000000000..fd8de1ebc6e --- /dev/null +++ b/mcs/errors/cs0573.cs @@ -0,0 +1,7 @@ +// CS0573: 'S': Structs cannot have instance property or field initializers +// Line: 6 + +struct S +{ + int v = 0; +} diff --git a/mcs/errors/cs1644-46.cs b/mcs/errors/cs1644-46.cs deleted file mode 100644 index a62e6d1f2d3..00000000000 --- a/mcs/errors/cs1644-46.cs +++ /dev/null @@ -1,8 +0,0 @@ -// CS1644: Feature `struct instance member initializer' cannot be used because it is not part of the C# 5.0 language specification -// Line: 12 -// Compiler options: -langversion:5 - -struct S -{ - int i = 0; -} \ No newline at end of file diff --git a/mcs/errors/cs1736-2.cs b/mcs/errors/cs1736-2.cs index b155aab79e0..c9c9e849a24 100644 --- a/mcs/errors/cs1736-2.cs +++ b/mcs/errors/cs1736-2.cs @@ -3,7 +3,9 @@ struct S { - public int i = 8; + public S () + { + } } class X diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs index 37b93b7141a..37e1667db6f 100644 --- a/mcs/mcs/class.cs +++ b/mcs/mcs/class.cs @@ -976,8 +976,11 @@ public void RegisterFieldForInitialization (MemberCore field, FieldInitializer e initialized_static_fields.Add (expression); } else { - if (Kind == MemberKind.Struct && Compiler.Settings.Version < LanguageVersion.V_6) { - Report.FeatureIsNotAvailable (Compiler, expression.Location, "struct instance member initializer"); + if (Kind == MemberKind.Struct) { + if (Compiler.Settings.Version != LanguageVersion.Experimental) { + Report.Error (573, expression.Location, "'{0}': Structs cannot have instance property or field initializers", + GetSignatureForError ()); + } } if (initialized_fields == null) diff --git a/mcs/tests/gtest-autoproperty-09.cs b/mcs/tests/gtest-autoproperty-09.cs index b6109d943c3..42c12e9add6 100644 --- a/mcs/tests/gtest-autoproperty-09.cs +++ b/mcs/tests/gtest-autoproperty-09.cs @@ -1,3 +1,4 @@ +// Compiler options: -langversion:experimental using System; struct S diff --git a/mcs/tests/gtest-autoproperty-10.cs b/mcs/tests/gtest-autoproperty-10.cs index a7308568468..036d9c3a43a 100644 --- a/mcs/tests/gtest-autoproperty-10.cs +++ b/mcs/tests/gtest-autoproperty-10.cs @@ -1,3 +1,4 @@ +// Compiler options: -langversion:experimental struct S { public decimal P { get; } = -3; diff --git a/mcs/tests/test-906.cs b/mcs/tests/test-906.cs index 2af641f84c2..9a34e438773 100644 --- a/mcs/tests/test-906.cs +++ b/mcs/tests/test-906.cs @@ -1,3 +1,4 @@ +// Compiler options: -langversion:experimental using System; struct S1 diff --git a/mcs/tests/test-primary-ctor-01.cs b/mcs/tests/test-primary-ctor-01.cs index f2b2239fd4d..5b2eeaed8d5 100644 --- a/mcs/tests/test-primary-ctor-01.cs +++ b/mcs/tests/test-primary-ctor-01.cs @@ -1,3 +1,4 @@ +// Compiler options: -langversion:experimental class Simple(int arg) { int Property { get; } = arg; diff --git a/mcs/tests/test-primary-ctor-07.cs b/mcs/tests/test-primary-ctor-07.cs index 2e2fc7adbbe..79a1c2991e7 100644 --- a/mcs/tests/test-primary-ctor-07.cs +++ b/mcs/tests/test-primary-ctor-07.cs @@ -1,3 +1,5 @@ +// Compiler options: -langversion:experimental + using System; struct S (int x) From 999e88dcd5d8dbadf7f53258a8e7381ab8ccf5eb Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Tue, 30 Sep 2014 11:12:24 +0200 Subject: [PATCH 303/543] [mcs] Correctly identify constant switch section when value match is not section start. Fixes #23475 --- mcs/mcs/statement.cs | 12 +++++++++++- mcs/tests/test-907.cs | 22 ++++++++++++++++++++++ mcs/tests/ver-il-net_4_5.xml | 10 ++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 mcs/tests/test-907.cs diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs index e46dca447eb..00d61eba2b7 100644 --- a/mcs/mcs/statement.cs +++ b/mcs/mcs/statement.cs @@ -5044,7 +5044,17 @@ public SwitchLabel FindLabel (Constant value) } } - return sl; + if (sl == null || sl.SectionStart) + return sl; + + // + // Always return section start, it simplifies handling of switch labels + // + for (int idx = case_labels.IndexOf (sl); ; --idx) { + var cs = case_labels [idx]; + if (cs.SectionStart) + return cs; + } } protected override bool DoFlowAnalysis (FlowAnalysisContext fc) diff --git a/mcs/tests/test-907.cs b/mcs/tests/test-907.cs new file mode 100644 index 00000000000..0a832c91123 --- /dev/null +++ b/mcs/tests/test-907.cs @@ -0,0 +1,22 @@ +public enum Foo { One, Two }; + +class MainClass +{ + public static int Main () + { + const Foo foo = Foo.Two; + int obj; + + switch (foo) { + case Foo.One: + case Foo.Two: + obj = 2; + break; + } + + if (obj != 2) + return 1; + + return 0; + } +} diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 4cd47f3ebe1..5ec386000e2 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -50865,6 +50865,16 @@ + + + + 37 + + + 7 + + + From 497481742ad95f3b2f21a169f4a38401ee5bb2d6 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Tue, 30 Sep 2014 13:02:32 +0200 Subject: [PATCH 304/543] [mcs] Undo bool loads normalization from byte arrays --- mcs/mcs/codegen.cs | 13 ++---- mcs/tests/test-898.cs | 79 ------------------------------------ mcs/tests/ver-il-net_4_5.xml | 24 ++--------- 3 files changed, 7 insertions(+), 109 deletions(-) delete mode 100644 mcs/tests/test-898.cs diff --git a/mcs/mcs/codegen.cs b/mcs/mcs/codegen.cs index 53cc740a350..6dfe7b6ce6b 100644 --- a/mcs/mcs/codegen.cs +++ b/mcs/mcs/codegen.cs @@ -549,13 +549,10 @@ public void EmitArrayLoad (ArrayContainer ac) switch (type.BuiltinType) { case BuiltinTypeSpec.Type.Bool: // - // Workaround MSIL limitation. Load bool element as single bit, - // bool array can actually store any byte value + // bool array can actually store any byte value in underlying byte slot + // and C# spec does not specify any normalization rule, except the result + // is undefined // - ig.Emit (OpCodes.Ldelem_U1); - ig.Emit (OpCodes.Ldc_I4_0); - ig.Emit (OpCodes.Cgt_Un); - break; case BuiltinTypeSpec.Type.Byte: ig.Emit (OpCodes.Ldelem_U1); break; @@ -771,12 +768,8 @@ public void EmitLoadFromPtr (TypeSpec type) ig.Emit (OpCodes.Ldind_U1); break; case BuiltinTypeSpec.Type.SByte: - ig.Emit (OpCodes.Ldind_I1); - break; case BuiltinTypeSpec.Type.Bool: ig.Emit (OpCodes.Ldind_I1); - ig.Emit (OpCodes.Ldc_I4_0); - ig.Emit (OpCodes.Cgt_Un); break; case BuiltinTypeSpec.Type.ULong: case BuiltinTypeSpec.Type.Long: diff --git a/mcs/tests/test-898.cs b/mcs/tests/test-898.cs deleted file mode 100644 index 5b6940372fb..00000000000 --- a/mcs/tests/test-898.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Compiler options: -unsafe - -using System; - -class BoolArrayWithByteValues -{ - - static int Foo (ref bool b) - { - bool b2 = true; - bool r; - r = b == true; - if (!r) - return 10; - - r = b == b2; - if (!r) - return 11; - - return 0; - } - - static unsafe bool Ptr () - { - bool rv; - - var arr = new byte [256]; - for (int i = 0; i < arr.Length; i++) - arr [i] = (byte) i; - fixed (byte* bptr = arr) { - rv = true; - for (int i = 0; i < arr.Length; i++) { - bool* boptr = (bool*)(bptr + i); - if (arr[i] > 0 && !*boptr) - rv = false; - System.Console.WriteLine ("#{0} = {1}", i, *boptr); - } - } - - return rv; - } - - static int Main() - { - var a = new bool[1]; - Buffer.SetByte (a, 0, 5); - - var b = true; - bool r; - r = a [0]; - if (!r) - return 1; - - r = a [0] == true; - if (!r) - return 2; - - r = a [0] == b; - if (!r) - return 3; - - r = a [0] != false; - if (!r) - return 4; - - r = a [0] != b; - if (r) - return 5; - - var res = Foo (ref a [0]); - if (res != 0) - return res; - - if (!Ptr ()) - return 6; - - return 0; - } -} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 5ec386000e2..ca08bdcbbb1 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -32277,7 +32277,7 @@ - 355 + 352 7 @@ -46953,7 +46953,7 @@ - 149 + 146 7 @@ -50683,22 +50683,6 @@ - - - - 58 - - - 191 - - - 7 - - - 167 - - - @@ -60106,7 +60090,7 @@ - 338 + 335 @@ -60226,7 +60210,7 @@ - 235 + 232 13 From 7ece665d16714db0979bde5df254231c5be24f10 Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Tue, 30 Sep 2014 13:20:19 +0100 Subject: [PATCH 305/543] Refresh HashAlgorithmTest to match changed NullStream behaviour in 8b9c60075f7b97fe88c3c588968977ff9bcf8c28 --- .../Test/System.Security.Cryptography/HashAlgorithmTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs index 9feea2b3385..54a7c42238f 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs @@ -138,7 +138,7 @@ public void Clear2 () } [Test] - [ExpectedException (typeof (NullReferenceException))] + [ExpectedException (typeof (ArgumentNullException))] public void NullStream () { Stream s = null; From a49bd2664faf629f01f71b313ba73180b7b8902d Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Tue, 30 Sep 2014 13:21:16 +0100 Subject: [PATCH 306/543] Add new cert-sync command to scripts/.gitignore --- scripts/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/.gitignore b/scripts/.gitignore index 09042162780..ff0b717d53a 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -3,6 +3,7 @@ /al1 /al2 /caspol +/cert-sync /cert2spc /certmgr /cccheck From d171cdf5e281973c06f2751f4e33098f1a624a95 Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Tue, 30 Sep 2014 14:51:13 +0100 Subject: [PATCH 307/543] Finish test changes started in 7ece665d16714db0979bde5df254231c5be24f10 --- .../RSACryptoServiceProviderTest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs index 6cf1637d085..1be7986a438 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs @@ -251,8 +251,7 @@ public void SignDataByteArrayNull () } [Test] - //[ExpectedException (typeof (ArgumentNullException))] - [ExpectedException (typeof (NullReferenceException))] + [ExpectedException (typeof (ArgumentNullException))] public void SignDataStreamNull () { rsa = new RSACryptoServiceProvider (minKeySize); From fc7c8e976562012fee04d1bd2422461bc24b5e19 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 30 Sep 2014 22:12:53 -0400 Subject: [PATCH 308/543] [jit] Make each CASTCLASS_CACHE patch unique by generating a unique identifier from the method index and an per-method counter. Fixes #23478. --- mono/mini/aot-compiler.c | 2 ++ mono/mini/aot-runtime.c | 4 ++- mono/mini/generics.cs | 31 +++++++++++++++++++ mono/mini/method-to-ir.c | 65 +++++++++++++++++++--------------------- mono/mini/mini.c | 5 +++- mono/mini/mini.h | 4 ++- 6 files changed, 74 insertions(+), 37 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index ab59c11c365..70e11b7730f 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -5007,7 +5007,9 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR: case MONO_PATCH_INFO_JIT_TLS_ID: case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR: + break; case MONO_PATCH_INFO_CASTCLASS_CACHE: + encode_value (patch_info->data.index, p, &p); break; case MONO_PATCH_INFO_METHOD_REL: encode_value ((gint)patch_info->data.offset, p, &p); diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 81d58e784a6..ca2f6552f71 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -3285,9 +3285,11 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin case MONO_PATCH_INFO_MONITOR_ENTER: case MONO_PATCH_INFO_MONITOR_EXIT: case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR: - case MONO_PATCH_INFO_CASTCLASS_CACHE: case MONO_PATCH_INFO_JIT_TLS_ID: break; + case MONO_PATCH_INFO_CASTCLASS_CACHE: + ji->data.index = decode_value (p, &p); + break; case MONO_PATCH_INFO_RGCTX_FETCH: { gboolean res; MonoJumpInfoRgctxEntry *entry; diff --git a/mono/mini/generics.cs b/mono/mini/generics.cs index cdf7b36ef68..f350710c76e 100644 --- a/mono/mini/generics.cs +++ b/mono/mini/generics.cs @@ -913,6 +913,7 @@ public Type getInstance() { } } + [Category ("GSHAREDVT")] static int test_0_synchronized_gshared () { var c = new SyncClass (); if (c.getInstance () != typeof (string)) @@ -1088,6 +1089,36 @@ public static int test_0_delegate_callvirt_fullaot () { var s = f2 (f); return s == "A" ? 0 : 1; } + + public interface ICovariant + { + } + + // Deleting the `out` modifier from this line stop the problem + public interface IExtCovariant : ICovariant + { + } + + public class Sample : ICovariant + { + } + + public interface IMyInterface + { + } + + public static int test_0_variant_cast_cache () { + object covariant = new Sample(); + + var foo = (ICovariant)(covariant); + + try { + var extCovariant = (IExtCovariant)covariant; + return 1; + } catch { + return 0; + } + } } #if !MOBILE diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 4db81265757..c97c935fe9d 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -4063,6 +4063,33 @@ emit_castclass_with_cache (MonoCompile *cfg, MonoClass *klass, MonoInst **args, return res; } +static MonoInst* +emit_castclass_with_cache_nonshared (MonoCompile *cfg, MonoInst *obj, MonoClass *klass, MonoBasicBlock **out_bblock) +{ + MonoInst *args [3]; + int idx; + + /* obj */ + args [0] = obj; + + /* klass */ + EMIT_NEW_CLASSCONST (cfg, args [1], klass); + + /* inline cache*/ + if (cfg->compile_aot) { + /* Each CASTCLASS_CACHE patch needs a unique index which identifies the call site */ + cfg->castclass_cache_index ++; + idx = (cfg->method_index << 16) | cfg->castclass_cache_index; + EMIT_NEW_AOTCONST (cfg, args [2], MONO_PATCH_INFO_CASTCLASS_CACHE, GINT_TO_POINTER (idx)); + } else { + EMIT_NEW_PCONST (cfg, args [2], mono_domain_alloc0 (cfg->domain, sizeof (gpointer))); + } + + /*The wrapper doesn't inline well so the bloat of inlining doesn't pay off.*/ + + return emit_castclass_with_cache (cfg, klass, args, out_bblock); +} + /* * Returns NULL and set the cfg exception on error. */ @@ -9754,23 +9781,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b context_used = mini_class_check_context_used (cfg, klass); if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { - MonoInst *args [3]; - - /* obj */ - args [0] = *sp; - - /* klass */ - EMIT_NEW_CLASSCONST (cfg, args [1], klass); - - /* inline cache*/ - if (cfg->compile_aot) - EMIT_NEW_AOTCONST (cfg, args [2], MONO_PATCH_INFO_CASTCLASS_CACHE, NULL); - else - EMIT_NEW_PCONST (cfg, args [2], mono_domain_alloc0 (cfg->domain, sizeof (gpointer))); - - /*The wrapper doesn't inline well so the bloat of inlining doesn't pay off.*/ - - *sp++ = emit_castclass_with_cache (cfg, klass, args, &bblock); + *sp = emit_castclass_with_cache_nonshared (cfg, sp [0], klass, &bblock); + sp ++; ip += 5; inline_costs += 2; } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) { @@ -9889,23 +9901,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (generic_class_is_reference_type (cfg, klass)) { /* CASTCLASS FIXME kill this huge slice of duplicated code*/ if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { - MonoInst *args [3]; - - /* obj */ - args [0] = *sp; - - /* klass */ - EMIT_NEW_CLASSCONST (cfg, args [1], klass); - - /* inline cache*/ - /*FIXME AOT support*/ - if (cfg->compile_aot) - EMIT_NEW_AOTCONST (cfg, args [2], MONO_PATCH_INFO_CASTCLASS_CACHE, NULL); - else - EMIT_NEW_PCONST (cfg, args [2], mono_domain_alloc0 (cfg->domain, sizeof (gpointer))); - - /* The wrapper doesn't inline well so the bloat of inlining doesn't pay off. */ - *sp++ = emit_castclass_with_cache (cfg, klass, args, &bblock); + *sp = emit_castclass_with_cache_nonshared (cfg, sp [0], klass, &bblock); + sp ++; ip += 5; inline_costs += 2; } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) { diff --git a/mono/mini/mini.c b/mono/mini/mini.c index f015d6e75b8..827176f6cbc 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -3239,9 +3239,10 @@ mono_patch_info_hash (gconstpointer data) case MONO_PATCH_INFO_JIT_TLS_ID: case MONO_PATCH_INFO_MONITOR_ENTER: case MONO_PATCH_INFO_MONITOR_EXIT: - case MONO_PATCH_INFO_CASTCLASS_CACHE: case MONO_PATCH_INFO_GOT_OFFSET: return (ji->type << 8); + case MONO_PATCH_INFO_CASTCLASS_CACHE: + return (ji->type << 8) | (ji->data.index); case MONO_PATCH_INFO_SWITCH: return (ji->type << 8) | ji->data.table->table_size; case MONO_PATCH_INFO_GSHAREDVT_METHOD: @@ -3306,6 +3307,8 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb) return ji1->data.gsharedvt_method->method == ji2->data.gsharedvt_method->method; case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: return ji1->data.del_tramp->klass == ji2->data.del_tramp->klass && ji1->data.del_tramp->method == ji2->data.del_tramp->method && ji1->data.del_tramp->virtual == ji2->data.del_tramp->virtual; + case MONO_PATCH_INFO_CASTCLASS_CACHE: + return ji1->data.index == ji2->data.index; default: if (ji1->data.target != ji2->data.target) return 0; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index c176f7c0829..f989bc27416 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -123,7 +123,7 @@ #endif /* Version number of the AOT file format */ -#define MONO_AOT_FILE_VERSION 102 +#define MONO_AOT_FILE_VERSION 103 //TODO: This is x86/amd64 specific. #define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6)) @@ -1237,6 +1237,7 @@ struct MonoJumpInfo { #else int offset; #endif + int index; MonoBasicBlock *bb; MonoInst *inst; MonoMethod *method; @@ -1613,6 +1614,7 @@ typedef struct { /* Symbol used to refer to this method in generated assembly */ char *asm_symbol; char *llvm_method_name; + int castclass_cache_index; MonoJitExceptionInfo *llvm_ex_info; guint32 llvm_ex_info_len; From 9aaf79b05500981cf09298750b3b8bb22e1d3c57 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 1 Oct 2014 14:27:18 -0400 Subject: [PATCH 309/543] Fix some warnings by not including utils/mono-threads.h into threads-types.h. --- mono/metadata/threads-types.h | 4 ++-- mono/mini/mini.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mono/metadata/threads-types.h b/mono/metadata/threads-types.h index 969f5ba2d9b..860bb5b67e9 100644 --- a/mono/metadata/threads-types.h +++ b/mono/metadata/threads-types.h @@ -18,7 +18,6 @@ #include #include "mono/utils/mono-compiler.h" #include "mono/utils/mono-membar.h" -#include "mono/utils/mono-threads.h" /* This is a copy of System.Threading.ThreadState */ typedef enum { @@ -53,7 +52,8 @@ typedef LPTHREAD_START_ROUTINE WapiThreadStart; typedef struct _MonoInternalThread MonoInternalThread; typedef void (*MonoThreadCleanupFunc) (MonoInternalThread* thread); -typedef void (*MonoThreadNotifyPendingExcFunc) (MonoThreadInfo *info); +/* INFO has type MonoThreadInfo* */ +typedef void (*MonoThreadNotifyPendingExcFunc) (gpointer info); MonoInternalThread* mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, guint32 stack_size) MONO_INTERNAL; diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 827176f6cbc..25bf6614ca4 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -7441,7 +7441,7 @@ mini_init (const char *filename, const char *runtime_version) printf ("MONO_DISABLE_PENDING_EXCEPTIONS env var set.\n"); } else { check_for_pending_exc = FALSE; - mono_threads_install_notify_pending_exc (mono_arch_notify_pending_exc); + mono_threads_install_notify_pending_exc ((MonoThreadNotifyPendingExcFunc)mono_arch_notify_pending_exc); } #endif From 52834175e1f88c9819f4c58a7fa47f70dcf74355 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 1 Oct 2014 15:02:25 -0400 Subject: [PATCH 310/543] [runtime] Add a missing call to mono_thread_notify_pending_exc_fn () to the thread abort code. --- mono/metadata/threads.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index a090b70cffa..de4917ce08d 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -4597,6 +4597,10 @@ abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception, */ gpointer interrupt_handle; + if (mono_thread_notify_pending_exc_fn) + /* The JIT will notify the thread about the interruption */ + mono_thread_notify_pending_exc_fn (info); + interrupt_handle = mono_thread_info_prepare_interrupt (thread->handle); mono_thread_info_finish_suspend_and_resume (info); mono_thread_info_finish_interrupt (interrupt_handle); From 0ac61b03fcd9baf75739d3c567b36647bde08025 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Wed, 1 Oct 2014 15:10:37 -0400 Subject: [PATCH 311/543] [corlib] Fix UnicodeEncoding GetMaxByteCount and GetMaxCharCount to return the same values as .net. --- .../corlib/System.Text/UnicodeEncoding.cs | 4 +- .../Test/System.Text/UnicodeEncodingTest.cs | 38 +++++++++++-------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/mcs/class/corlib/System.Text/UnicodeEncoding.cs b/mcs/class/corlib/System.Text/UnicodeEncoding.cs index edb57e69ca2..48077a2452b 100644 --- a/mcs/class/corlib/System.Text/UnicodeEncoding.cs +++ b/mcs/class/corlib/System.Text/UnicodeEncoding.cs @@ -345,7 +345,7 @@ public override int GetMaxByteCount (int charCount) if (charCount < 0) { throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_NonNegative")); } - return charCount * 2; + return charCount * 2 + 2; } // Get the maximum number of characters needed to decode a @@ -356,7 +356,7 @@ public override int GetMaxCharCount (int byteCount) throw new ArgumentOutOfRangeException ("byteCount", _("ArgRange_NonNegative")); } - return byteCount / 2; + return (byteCount + 1) / 2 + 1; } // Get a Unicode-specific decoder that is attached to this instance. diff --git a/mcs/class/corlib/Test/System.Text/UnicodeEncodingTest.cs b/mcs/class/corlib/Test/System.Text/UnicodeEncodingTest.cs index 9938bcef1ae..e780524afe1 100644 --- a/mcs/class/corlib/Test/System.Text/UnicodeEncodingTest.cs +++ b/mcs/class/corlib/Test/System.Text/UnicodeEncodingTest.cs @@ -164,34 +164,18 @@ public void TestPreamble3() } [Test] -#if NET_2_0 - [Category ("NotWorking")] -#endif public void TestMaxCharCount() { UnicodeEncoding UnicodeEnc = new UnicodeEncoding (); -#if NET_2_0 - // where is this extra 1 coming from? Assert.AreEqual (26, UnicodeEnc.GetMaxCharCount(50), "UTF #1"); Assert.AreEqual (27, UnicodeEnc.GetMaxCharCount(51), "UTF #2"); -#else - Assert.AreEqual (25, UnicodeEnc.GetMaxCharCount(50), "UTF #1"); -#endif } [Test] -#if NET_2_0 - [Category ("NotWorking")] -#endif public void TestMaxByteCount() { UnicodeEncoding UnicodeEnc = new UnicodeEncoding (); -#if NET_2_0 - // is this extra 2 BOM? Assert.AreEqual (102, UnicodeEnc.GetMaxByteCount(50), "UTF #1"); -#else - Assert.AreEqual (100, UnicodeEnc.GetMaxByteCount(50), "UTF #1"); -#endif } [Test] @@ -257,5 +241,27 @@ public void GetString_Odd_Count_ff () Assert.AreEqual (2, s.Length, "Length"); Assert.AreEqual (65533, (int) s [1], "1"); } + + [Test] + public void GetMaxByteCountIncludesBOM () + { + Assert.AreEqual (2, Encoding.Unicode.GetMaxByteCount (0), "#1"); + Assert.AreEqual (4, Encoding.Unicode.GetMaxByteCount (1), "#2"); + Assert.AreEqual (6, Encoding.Unicode.GetMaxByteCount (2), "#3"); + Assert.AreEqual (10, Encoding.Unicode.GetMaxByteCount (4), "#4"); + Assert.AreEqual (20, Encoding.Unicode.GetMaxByteCount (9), "#5"); + Assert.AreEqual (22, Encoding.Unicode.GetMaxByteCount (10), "#6"); + } + + [Test] + public void GetMaxCharCountRoundsCorrectly () + { + Assert.AreEqual (1, Encoding.Unicode.GetMaxCharCount (0), "#1"); + Assert.AreEqual (2, Encoding.Unicode.GetMaxCharCount (1), "#2"); + Assert.AreEqual (2, Encoding.Unicode.GetMaxCharCount (2), "#3"); + Assert.AreEqual (3, Encoding.Unicode.GetMaxCharCount (4), "#4"); + Assert.AreEqual (6, Encoding.Unicode.GetMaxCharCount (9), "#5"); + Assert.AreEqual (6, Encoding.Unicode.GetMaxCharCount (10), "#6"); + } } } From d659d7540d35c0574ddbfbf4cacee384fe0a2ba2 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 1 Oct 2014 16:36:16 -0400 Subject: [PATCH 312/543] [x86] Remove the now unused push based parameter passing code. --- mono/mini/exceptions-x86.c | 23 ---- mono/mini/mini-x86.c | 253 +++++++------------------------------ mono/mini/mini-x86.h | 3 - 3 files changed, 44 insertions(+), 235 deletions(-) diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index 841b4580a6b..615b3f2371f 100755 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -808,29 +808,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, /* Adjust IP */ new_ctx->eip --; - -#ifndef MONO_X86_NO_PUSHES - /* Pop arguments off the stack */ - if (ji->has_arch_eh_info) { - int stack_size; - - stack_size = mono_jit_info_get_arch_eh_info (ji)->stack_size; - - if (stack_size) { -#ifdef ENABLE_LLVM - MonoJitInfo *caller_ji; - - caller_ji = mini_jit_info_table_find (domain, (char*)new_ctx->eip, NULL); - /* LLVM doesn't push the arguments */ - if (caller_ji && !caller_ji->from_llvm) - new_ctx->esp += stack_size; -#else - new_ctx->esp += stack_size; -#endif - } - } -#endif - return TRUE; } else if (*lmf) { diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index c7931e328ff..5f589b258b8 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -1217,10 +1217,6 @@ mono_arch_create_vars (MonoCompile *cfg) cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG); } -#ifdef MONO_X86_NO_PUSHES - cfg->arch.no_pushes = TRUE; -#endif - if (cfg->method->save_lmf) { cfg->create_lmf_var = TRUE; cfg->lmf_ir = TRUE; @@ -1279,17 +1275,9 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) if (cfg->compile_aot) { sig_reg = mono_alloc_ireg (cfg); MONO_EMIT_NEW_SIGNATURECONST (cfg, sig_reg, tmp_sig); - if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, cinfo->sig_cookie.offset, sig_reg); - } else { - MONO_EMIT_NEW_UNALU (cfg, OP_X86_PUSH, -1, sig_reg); - } + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, cinfo->sig_cookie.offset, sig_reg); } else { - if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, X86_ESP, cinfo->sig_cookie.offset, tmp_sig); - } else { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_X86_PUSH_IMM, -1, -1, tmp_sig); - } + MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, X86_ESP, cinfo->sig_cookie.offset, tmp_sig); } } @@ -1415,7 +1403,7 @@ emit_gc_param_slot_def (MonoCompile *cfg, int sp_offset, MonoType *t) MonoInst *def; /* Needs checking if the feature will be enabled again */ - g_assert (!cfg->arch.no_pushes); + g_assert_not_reached (); /* On x86, the offsets are from the sp value before the start of the call sequence */ if (t == NULL) @@ -1444,19 +1432,6 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG)) sentinelpos = sig->sentinelpos + (sig->hasthis ? 1 : 0); - if (cinfo->need_stack_align && !cfg->arch.no_pushes) { - MONO_INST_NEW (cfg, arg, OP_SUB_IMM); - arg->dreg = X86_ESP; - arg->sreg1 = X86_ESP; - arg->inst_imm = cinfo->stack_align_amount; - MONO_ADD_INS (cfg->cbb, arg); - for (i = 0; i < cinfo->stack_align_amount; i += sizeof (mgreg_t)) { - sp_offset += 4; - - emit_gc_param_slot_def (cfg, sp_offset, NULL); - } - } - if (sig_ret && MONO_TYPE_ISSTRUCT (sig_ret)) { if (cinfo->ret.storage == ArgValuetypeInReg) { /* @@ -1475,7 +1450,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) /* Handle the case where there are no implicit arguments */ if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == sentinelpos)) { emit_sig_cookie (cfg, call, cinfo); - sp_offset = (cfg->arch.no_pushes) ? cinfo->sig_cookie.offset : (sp_offset + 4); + sp_offset = cinfo->sig_cookie.offset; emit_gc_param_slot_def (cfg, sp_offset, NULL); } @@ -1487,23 +1462,15 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) if (cinfo->vtype_retaddr && cinfo->vret_arg_index == 1 && i == 0) { MonoInst *vtarg; + /* Push the vret arg before the first argument */ - if (cfg->arch.no_pushes) { - MONO_INST_NEW (cfg, vtarg, OP_STORE_MEMBASE_REG); - vtarg->type = STACK_MP; - vtarg->inst_destbasereg = X86_ESP; - vtarg->sreg1 = call->vret_var->dreg; - vtarg->inst_offset = cinfo->ret.offset; - MONO_ADD_INS (cfg->cbb, vtarg); - sp_offset = cinfo->ret.offset; - } else { - MONO_INST_NEW (cfg, vtarg, OP_X86_PUSH); - vtarg->type = STACK_MP; - vtarg->sreg1 = call->vret_var->dreg; - MONO_ADD_INS (cfg->cbb, vtarg); - sp_offset += 4; - } - emit_gc_param_slot_def (cfg, sp_offset, NULL); + MONO_INST_NEW (cfg, vtarg, OP_STORE_MEMBASE_REG); + vtarg->type = STACK_MP; + vtarg->inst_destbasereg = X86_ESP; + vtarg->sreg1 = call->vret_var->dreg; + vtarg->inst_offset = cinfo->ret.offset; + MONO_ADD_INS (cfg->cbb, vtarg); + emit_gc_param_slot_def (cfg, cinfo->ret.offset, NULL); } if (i >= sig->hasthis) @@ -1555,8 +1522,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) MONO_ADD_INS (cfg->cbb, arg); if (ainfo->storage != ArgValuetypeInReg) { - sp_offset = (cfg->arch.no_pushes) ? ainfo->offset : (sp_offset + size); - emit_gc_param_slot_def (cfg, sp_offset, orig_type); + emit_gc_param_slot_def (cfg, ainfo->offset, orig_type); } } } else { @@ -1564,47 +1530,21 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) case ArgOnStack: if (!t->byref) { if (t->type == MONO_TYPE_R4) { - if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg); - } else { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 4); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, X86_ESP, 0, in->dreg); - } + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg); argsize = 4; } else if (t->type == MONO_TYPE_R8) { - if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg); - } else { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 8); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, X86_ESP, 0, in->dreg); - } + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg); argsize = 8; } else if (t->type == MONO_TYPE_I8 || t->type == MONO_TYPE_U8) { - if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset + 4, in->dreg + 2); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg + 1); - } else { - MONO_EMIT_NEW_UNALU (cfg, OP_X86_PUSH, -1, in->dreg + 2); - MONO_EMIT_NEW_UNALU (cfg, OP_X86_PUSH, -1, in->dreg + 1); - sp_offset += 4; - } + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset + 4, in->dreg + 2); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg + 1); argsize = 4; } else { - if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg); - } else { - arg->opcode = OP_X86_PUSH; - MONO_ADD_INS (cfg->cbb, arg); - } + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg); argsize = 4; } } else { - if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg); - } else { - arg->opcode = OP_X86_PUSH; - MONO_ADD_INS (cfg->cbb, arg); - } + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg); argsize = 4; } break; @@ -1618,8 +1558,6 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) g_assert_not_reached (); } - sp_offset = (cfg->arch.no_pushes) ? ainfo->offset : (sp_offset + argsize); - if (cfg->compute_gc_maps) { if (argsize == 4) { /* FIXME: The == STACK_OBJ check might be fragile ? */ @@ -1627,20 +1565,16 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) /* this */ if (call->need_unbox_trampoline) /* The unbox trampoline transforms this into a managed pointer */ - emit_gc_param_slot_def (cfg, sp_offset, &mono_defaults.int_class->this_arg); + emit_gc_param_slot_def (cfg, ainfo->offset, &mono_defaults.int_class->this_arg); else - emit_gc_param_slot_def (cfg, sp_offset, &mono_defaults.object_class->byval_arg); + emit_gc_param_slot_def (cfg, ainfo->offset, &mono_defaults.object_class->byval_arg); } else { - emit_gc_param_slot_def (cfg, sp_offset, orig_type); + emit_gc_param_slot_def (cfg, ainfo->offset, orig_type); } } else { /* i8/r8 */ - for (j = 0; j < argsize; j += 4) { - if (cfg->arch.no_pushes) - emit_gc_param_slot_def (cfg, sp_offset + j, NULL); - else - emit_gc_param_slot_def (cfg, sp_offset - j, NULL); - } + for (j = 0; j < argsize; j += 4) + emit_gc_param_slot_def (cfg, ainfo->offset + j, NULL); } } } @@ -1648,8 +1582,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (i == sentinelpos)) { /* Emit the signature cookie just before the implicit arguments */ emit_sig_cookie (cfg, call, cinfo); - sp_offset = (cfg->arch.no_pushes) ? cinfo->sig_cookie.offset : (sp_offset + 4); - emit_gc_param_slot_def (cfg, sp_offset, NULL); + emit_gc_param_slot_def (cfg, cinfo->sig_cookie.offset, NULL); } } @@ -1669,29 +1602,13 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) mono_call_inst_add_outarg_reg (cfg, call, vtarg->dreg, cinfo->ret.reg, FALSE); } else if (cinfo->vtype_retaddr && cinfo->vret_arg_index == 0) { - if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, cinfo->ret.offset, call->vret_var->dreg); - sp_offset = cinfo->ret.offset; - } else { - MonoInst *vtarg; - MONO_INST_NEW (cfg, vtarg, OP_X86_PUSH); - vtarg->type = STACK_MP; - vtarg->sreg1 = call->vret_var->dreg; - MONO_ADD_INS (cfg->cbb, vtarg); - sp_offset += 4; - } - emit_gc_param_slot_def (cfg, sp_offset, NULL); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, cinfo->ret.offset, call->vret_var->dreg); + emit_gc_param_slot_def (cfg, cinfo->ret.offset, NULL); } - - /* if the function returns a struct on stack, the called method already does a ret $0x4 */ - if (!cfg->arch.no_pushes) - cinfo->stack_usage -= cinfo->callee_stack_pop; } call->stack_usage = cinfo->stack_usage; call->stack_align_amount = cinfo->stack_align_amount; - if (!cfg->arch.no_pushes) - cfg->arch.param_area_size = MAX (cfg->arch.param_area_size, sp_offset); } void @@ -1699,7 +1616,6 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) { MonoCallInst *call = (MonoCallInst*)ins->inst_p0; ArgInfo *ainfo = ins->inst_p1; - MonoInst *arg; int size = ins->backend.size; if (ainfo->storage == ArgValuetypeInReg) { @@ -1723,42 +1639,16 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) else { if (cfg->gsharedvt && mini_is_gsharedvt_klass (cfg, ins->klass)) { /* Pass by addr */ - if (cfg->arch.no_pushes) { - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, src->dreg); - } else { - MONO_INST_NEW (cfg, arg, OP_X86_PUSH); - arg->sreg1 = src->dreg; - MONO_ADD_INS (cfg->cbb, arg); - } + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, src->dreg); } else if (size <= 4) { - if (cfg->arch.no_pushes) { - int dreg = mono_alloc_ireg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, 0); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, dreg); - } else { - MONO_INST_NEW (cfg, arg, OP_X86_PUSH_MEMBASE); - arg->sreg1 = src->dreg; - MONO_ADD_INS (cfg->cbb, arg); - } + int dreg = mono_alloc_ireg (cfg); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, 0); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, dreg); } else if (size <= 20) { - if (cfg->arch.no_pushes) { - mini_emit_memcpy (cfg, X86_ESP, ainfo->offset, src->dreg, 0, size, 4); - } else { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, ALIGN_TO (size, 4)); - mini_emit_memcpy (cfg, X86_ESP, 0, src->dreg, 0, size, 4); - } + mini_emit_memcpy (cfg, X86_ESP, ainfo->offset, src->dreg, 0, size, 4); } else { - if (cfg->arch.no_pushes) { - // FIXME: Code growth - mini_emit_memcpy (cfg, X86_ESP, ainfo->offset, src->dreg, 0, size, 4); - } else { - MONO_INST_NEW (cfg, arg, OP_X86_PUSH_OBJ); - arg->inst_basereg = src->dreg; - arg->inst_offset = 0; - arg->inst_imm = size; - - MONO_ADD_INS (cfg->cbb, arg); - } + // FIXME: Code growth + mini_emit_memcpy (cfg, X86_ESP, ainfo->offset, src->dreg, 0, size, 4); } } } @@ -2301,7 +2191,7 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree) x86_push_reg (code, X86_EDI); x86_mov_reg_imm (code, X86_ECX, (0x1000 >> 2)); x86_alu_reg_reg (code, X86_XOR, X86_EAX, X86_EAX); - if (cfg->param_area && cfg->arch.no_pushes) + if (cfg->param_area) x86_lea_membase (code, X86_EDI, X86_ESP, 12 + ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); else x86_lea_membase (code, X86_EDI, X86_ESP, 12); @@ -2351,7 +2241,7 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree) x86_mov_reg_reg (code, X86_ECX, sreg, 4); x86_alu_reg_reg (code, X86_XOR, X86_EAX, X86_EAX); - if (cfg->param_area && cfg->arch.no_pushes) + if (cfg->param_area) x86_lea_membase (code, X86_EDI, X86_ESP, offset + ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); else x86_lea_membase (code, X86_EDI, X86_ESP, offset); @@ -3396,65 +3286,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } ins->flags |= MONO_INST_GC_CALLSITE; ins->backend.pc_offset = code - cfg->native_code; - if (call->stack_usage && !CALLCONV_IS_STDCALL (call->signature) && !cfg->arch.no_pushes) { - /* a pop is one byte, while an add reg, imm is 3. So if there are 4 or 8 - * bytes to pop, we want to use pops. GCC does this (note it won't happen - * for P4 or i686 because gcc will avoid using pop push at all. But we aren't - * smart enough to do that optimization yet - * - * It turns out that on my P4, doing two pops for 8 bytes on the stack makes - * mcs botstrap slow down. However, doing 1 pop for 4 bytes creates a small, - * (most likely from locality benefits). People with other processors should - * check on theirs to see what happens. - */ - if (call->stack_usage == 4) { - /* we want to use registers that won't get used soon, so use - * ecx, as eax will get allocated first. edx is used by long calls, - * so we can't use that. - */ - - x86_pop_reg (code, X86_ECX); - } else { - x86_alu_reg_imm (code, X86_ADD, X86_ESP, call->stack_usage); - } - } else if (cinfo->callee_stack_pop && cfg->arch.no_pushes) { + if (cinfo->callee_stack_pop) { /* Have to compensate for the stack space popped by the callee */ x86_alu_reg_imm (code, X86_SUB, X86_ESP, cinfo->callee_stack_pop); } code = emit_move_return_value (cfg, ins, code); break; } - case OP_X86_PUSH: - g_assert (!cfg->arch.no_pushes); - x86_push_reg (code, ins->sreg1); - break; - case OP_X86_PUSH_IMM: - g_assert (!cfg->arch.no_pushes); - x86_push_imm (code, ins->inst_imm); - break; - case OP_X86_PUSH_MEMBASE: - g_assert (!cfg->arch.no_pushes); - x86_push_membase (code, ins->inst_basereg, ins->inst_offset); - break; - case OP_X86_PUSH_OBJ: - g_assert (!cfg->arch.no_pushes); - x86_alu_reg_imm (code, X86_SUB, X86_ESP, ins->inst_imm); - x86_push_reg (code, X86_EDI); - x86_push_reg (code, X86_ESI); - x86_push_reg (code, X86_ECX); - if (ins->inst_offset) - x86_lea_membase (code, X86_ESI, ins->inst_basereg, ins->inst_offset); - else - x86_mov_reg_reg (code, X86_ESI, ins->inst_basereg, 4); - x86_lea_membase (code, X86_EDI, X86_ESP, 12); - x86_mov_reg_imm (code, X86_ECX, (ins->inst_imm >> 2)); - x86_cld (code); - x86_prefix (code, X86_REP_PREFIX); - x86_movsd (code); - x86_pop_reg (code, X86_ECX); - x86_pop_reg (code, X86_ESI); - x86_pop_reg (code, X86_EDI); - break; case OP_X86_LEA: x86_lea_memindex (code, ins->dreg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->backend.shift_amount); break; @@ -3470,8 +3308,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_alu_reg_imm (code, X86_AND, ins->sreg1, ~(MONO_ARCH_LOCALLOC_ALIGNMENT - 1)); code = mono_emit_stack_alloc (cfg, code, ins); x86_mov_reg_reg (code, ins->dreg, X86_ESP, 4); - if (cfg->param_area && cfg->arch.no_pushes) - x86_alu_reg_imm (code, X86_ADD, ins->dreg, ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); + if (cfg->param_area) + x86_alu_reg_imm (code, X86_ADD, ins->dreg, ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); break; case OP_LOCALLOC_IMM: { guint32 size = ins->inst_imm; @@ -3488,8 +3326,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) x86_alu_reg_imm (code, X86_SUB, X86_ESP, size); x86_mov_reg_reg (code, ins->dreg, X86_ESP, 4); } - if (cfg->param_area && cfg->arch.no_pushes) - x86_alu_reg_imm (code, X86_ADD, ins->dreg, ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); + if (cfg->param_area) + x86_alu_reg_imm (code, X86_ADD, ins->dreg, ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); break; } case OP_THROW: { @@ -3520,9 +3358,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_START_HANDLER: { MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region); x86_mov_membase_reg (code, spvar->inst_basereg, spvar->inst_offset, X86_ESP, 4); - if (cfg->param_area && cfg->arch.no_pushes) { + if (cfg->param_area) x86_alu_reg_imm (code, X86_SUB, X86_ESP, ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); - } break; } case OP_ENDFINALLY: { @@ -5347,10 +5184,8 @@ mono_arch_emit_prolog (MonoCompile *cfg) cfg->frame_reg = X86_ESP; } - if (cfg->arch.no_pushes) { - cfg->stack_offset += cfg->param_area; - cfg->stack_offset = ALIGN_TO (cfg->stack_offset, MONO_ARCH_FRAME_ALIGNMENT); - } + cfg->stack_offset += cfg->param_area; + cfg->stack_offset = ALIGN_TO (cfg->stack_offset, MONO_ARCH_FRAME_ALIGNMENT); alloc_size = cfg->stack_offset; pos = 0; diff --git a/mono/mini/mini-x86.h b/mono/mini/mini-x86.h index 5ab5acc96c1..bce110f1035 100644 --- a/mono/mini/mini-x86.h +++ b/mono/mini/mini-x86.h @@ -74,8 +74,6 @@ struct sigcontext { #endif /* HAVE_WORKING_SIGALTSTACK */ #endif /* !HOST_WIN32 */ -#define MONO_X86_NO_PUSHES 1 - #define MONO_ARCH_SUPPORT_TASKLETS 1 #ifndef DISABLE_SIMD @@ -169,7 +167,6 @@ struct MonoLMF { typedef struct { gboolean need_stack_frame_inited; gboolean need_stack_frame; - gboolean no_pushes; int sp_fp_offset, param_area_size; } MonoCompileArch; From c856758e54c2d92ccc858e409caf5617dc7ba1b3 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 1 Oct 2014 16:42:47 -0400 Subject: [PATCH 313/543] [jit] Remove the unused MONO_DISABLE_PENDING_EXCEPTIONS env var, the functionality it disable is not experimental anymore. --- mono/mini/mini.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 25bf6614ca4..859c91c72f9 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -7436,13 +7436,8 @@ mini_init (const char *filename, const char *runtime_version) mono_threads_install_cleanup (mini_thread_cleanup); #ifdef MONO_ARCH_HAVE_NOTIFY_PENDING_EXC - // This is experimental code so provide an env var to switch it off - if (g_getenv ("MONO_DISABLE_PENDING_EXCEPTIONS")) { - printf ("MONO_DISABLE_PENDING_EXCEPTIONS env var set.\n"); - } else { - check_for_pending_exc = FALSE; - mono_threads_install_notify_pending_exc ((MonoThreadNotifyPendingExcFunc)mono_arch_notify_pending_exc); - } + check_for_pending_exc = FALSE; + mono_threads_install_notify_pending_exc ((MonoThreadNotifyPendingExcFunc)mono_arch_notify_pending_exc); #endif #define JIT_TRAMPOLINES_WORK From b86bd886d6d96b7830e9aa7e9423ef4e8f40ab85 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 1 Oct 2014 14:51:20 -0700 Subject: [PATCH 314/543] [sgen] Fix concurrent mark with split nursery. --- mono/metadata/sgen-gc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 9ac29632957..def25a77cdd 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -2440,7 +2440,11 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) static void scan_nursery_objects_callback (char *obj, size_t size, ScanCopyContext *ctx) { - ctx->scan_func (obj, sgen_obj_get_descriptor (obj), ctx->queue); + /* + * This is called on all objects in the nursery, including pinned ones, so we need + * to use sgen_obj_get_descriptor_safe(), which masks out the vtable tag bits. + */ + ctx->scan_func (obj, sgen_obj_get_descriptor_safe (obj), ctx->queue); } static void From aa73f76a347496efa05893771eaf58c83bea5dba Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 1 Oct 2014 22:49:18 -0400 Subject: [PATCH 315/543] [jit] Define NOMAP32BIT on winx64. --- mono/mini/mini-amd64.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index 2a017149f1f..f909b4f401a 100755 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -336,6 +336,10 @@ typedef struct { */ #define MONO_ARCH_NOMAP32BIT +#elif defined(HOST_WIN32) + +#define MONO_ARCH_NOMAP32BIT 1 + #endif /* __FreeBSD__ */ #ifdef HOST_WIN32 From 88297792e79873af45528b625371bb61d2a9a657 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 5 Sep 2014 15:31:28 +0300 Subject: [PATCH 316/543] TimeZoneInfo is now always present in corlib. Prior to net_4_0 TimeZoneInfo is a private class. --- .../System.Core/System/TimeZoneInfo.AdjustmentRule.cs | 7 +++++-- .../System.Core/System/TimeZoneInfo.Serialization.cs | 7 +++++-- .../System.Core/System/TimeZoneInfo.TransitionTime.cs | 7 +++++-- mcs/class/System.Core/System/TimeZoneInfo.cs | 7 +++++-- mcs/class/corlib/System/InvalidTimeZoneException.cs | 9 ++++----- mcs/class/corlib/System/TimeZoneNotFoundException.cs | 8 ++++---- 6 files changed, 28 insertions(+), 17 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.AdjustmentRule.cs b/mcs/class/System.Core/System/TimeZoneInfo.AdjustmentRule.cs index 637d0c400df..37f21464dcf 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.AdjustmentRule.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.AdjustmentRule.cs @@ -24,13 +24,16 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE)) +#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE) using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { - public sealed partial class TimeZoneInfo { +#if NET_4_0 || !INSIDE_CORLIB + public +#endif + sealed partial class TimeZoneInfo { [SerializableAttribute] #if MOBILE [TypeForwardedFrom (Consts.AssemblySystem_Core)] diff --git a/mcs/class/System.Core/System/TimeZoneInfo.Serialization.cs b/mcs/class/System.Core/System/TimeZoneInfo.Serialization.cs index 22aa38c5fa6..3a7da39ec7f 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.Serialization.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.Serialization.cs @@ -24,7 +24,7 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE)) +#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE) using System.Collections.Generic; using System.Globalization; @@ -33,7 +33,10 @@ namespace System { - public partial class TimeZoneInfo +#if NET_4_0 || !INSIDE_CORLIB + public +#endif + partial class TimeZoneInfo { public static TimeZoneInfo FromSerializedString (string source) { diff --git a/mcs/class/System.Core/System/TimeZoneInfo.TransitionTime.cs b/mcs/class/System.Core/System/TimeZoneInfo.TransitionTime.cs index d57df150f05..719bb9d51f3 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.TransitionTime.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.TransitionTime.cs @@ -24,14 +24,17 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE)) +#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE) using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { - public sealed partial class TimeZoneInfo +#if NET_4_0 || !INSIDE_CORLIB + public +#endif + sealed partial class TimeZoneInfo { [SerializableAttribute] #if MOBILE diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index aead18c764f..8a85fd73079 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -35,7 +35,7 @@ [assembly:TypeForwardedTo (typeof(TimeZoneInfo))] -#elif (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE)) +#elif INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE) using System.Collections.Generic; using System.Collections.ObjectModel; @@ -57,7 +57,10 @@ namespace System [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] #endif [SerializableAttribute] - public sealed partial class TimeZoneInfo : IEquatable, ISerializable, IDeserializationCallback +#if NET_4_0 || !INSIDE_CORLIB + public +#endif + sealed partial class TimeZoneInfo : IEquatable, ISerializable, IDeserializationCallback { TimeSpan baseUtcOffset; public TimeSpan BaseUtcOffset { diff --git a/mcs/class/corlib/System/InvalidTimeZoneException.cs b/mcs/class/corlib/System/InvalidTimeZoneException.cs index 7096e56cd33..7beb2d4982c 100644 --- a/mcs/class/corlib/System/InvalidTimeZoneException.cs +++ b/mcs/class/corlib/System/InvalidTimeZoneException.cs @@ -24,8 +24,6 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#if NET_4_0 - using System.Runtime.CompilerServices; namespace System @@ -36,7 +34,10 @@ namespace System #elif NET_4_0 [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] #endif - public class InvalidTimeZoneException : Exception +#if NET_4_0 + public +#endif + class InvalidTimeZoneException : Exception { public InvalidTimeZoneException () : base () {} @@ -51,5 +52,3 @@ protected InvalidTimeZoneException (Runtime.Serialization.SerializationInfo info {} } } - -#endif diff --git a/mcs/class/corlib/System/TimeZoneNotFoundException.cs b/mcs/class/corlib/System/TimeZoneNotFoundException.cs index 79b094ddde0..643b82104b3 100644 --- a/mcs/class/corlib/System/TimeZoneNotFoundException.cs +++ b/mcs/class/corlib/System/TimeZoneNotFoundException.cs @@ -24,7 +24,6 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#if NET_4_0 using System.Runtime.CompilerServices; @@ -36,7 +35,10 @@ namespace System #elif NET_4_0 [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] #endif - public class TimeZoneNotFoundException : Exception +#if NET_4_0 + public +#endif + class TimeZoneNotFoundException : Exception { public TimeZoneNotFoundException () : base () {} @@ -51,5 +53,3 @@ protected TimeZoneNotFoundException (Runtime.Serialization.SerializationInfo inf {} } } - -#endif From 9be262f8cc2dce118c077895a57b4e119462db42 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Sat, 6 Sep 2014 10:20:32 +0300 Subject: [PATCH 317/543] CurrentSystemTimeZone.GetUtcOffset now supports multiple DST periods. DateTime.Now was returning wrong values when system TimeZone had more than one daylight saving time. Fixes 22648. --- mcs/class/System.Core/System/TimeZoneInfo.cs | 8 -------- mcs/class/corlib/System/TimeZone.cs | 5 +---- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index 8a85fd73079..2b297d48ca0 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -778,14 +778,6 @@ public bool IsDaylightSavingTime (DateTime dateTime) if (!SupportsDaylightSavingTime) return false; - //FIXME: do not rely on DateTime implementation ! - if ((dateTime.Kind == DateTimeKind.Local || dateTime.Kind == DateTimeKind.Unspecified) && this == TimeZoneInfo.Local) - return dateTime.IsDaylightSavingTime (); - - //FIXME: do not rely on DateTime implementation ! - if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Utc) - return IsDaylightSavingTime (DateTime.SpecifyKind (dateTime.ToUniversalTime (), DateTimeKind.Utc)); - AdjustmentRule rule = GetApplicableRule (dateTime.Date); if (rule == null) return false; diff --git a/mcs/class/corlib/System/TimeZone.cs b/mcs/class/corlib/System/TimeZone.cs index cea224133e4..104cd9be0be 100644 --- a/mcs/class/corlib/System/TimeZone.cs +++ b/mcs/class/corlib/System/TimeZone.cs @@ -366,10 +366,7 @@ public override TimeSpan GetUtcOffset (DateTime time) if (time.Kind == DateTimeKind.Utc) return TimeSpan.Zero; - if (IsDaylightSavingTime (time) && !IsAmbiguousTime (time)) - return utcOffsetWithDLS; - - return utcOffsetWithOutDLS; + return TimeZoneInfo.Local.GetUtcOffset (time); } private bool IsAmbiguousTime (DateTime time) From 709d2c58ad0901febeaa0cf830cf23d0531963ad Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 1 Oct 2014 17:38:00 +0100 Subject: [PATCH 318/543] Removed unused CurrentSystemTimeZone fields and methods. --- mcs/class/corlib/System/TimeZone.cs | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/mcs/class/corlib/System/TimeZone.cs b/mcs/class/corlib/System/TimeZone.cs index 104cd9be0be..edbf6a4bb27 100644 --- a/mcs/class/corlib/System/TimeZone.cs +++ b/mcs/class/corlib/System/TimeZone.cs @@ -252,17 +252,6 @@ internal class CurrentSystemTimeZone : TimeZone, IDeserializationCallback { // A yearwise cache of DaylightTime. private Dictionary m_CachedDaylightChanges = new Dictionary (1); - // the offset when daylightsaving is not on (in ticks) - private long m_ticksOffset; - - // the offset when daylightsaving is not on. - [NonSerialized] - private TimeSpan utcOffsetWithOutDLS; - - // the offset when daylightsaving is on. - [NonSerialized] - private TimeSpan utcOffsetWithDLS; - internal enum TimeZoneData { DaylightSavingStartIdx, @@ -315,8 +304,6 @@ internal CurrentSystemTimeZone (long lnow) m_standardName = Locale.GetText (names[(int)TimeZoneNames.StandardNameIdx]); m_daylightName = Locale.GetText (names[(int)TimeZoneNames.DaylightNameIdx]); - m_ticksOffset = data[(int)TimeZoneData.UtcOffsetIdx]; - DaylightTime dlt = GetDaylightTimeFromData (data); m_CachedDaylightChanges.Add (now.Year, dlt); OnDeserialization (dlt); @@ -369,16 +356,6 @@ public override TimeSpan GetUtcOffset (DateTime time) return TimeZoneInfo.Local.GetUtcOffset (time); } - private bool IsAmbiguousTime (DateTime time) - { - if (time.Kind == DateTimeKind.Utc) - return false; - - DaylightTime changes = GetDaylightChanges (time.Year); - - return time < changes.End && time >= changes.End - changes.Delta; - } - void IDeserializationCallback.OnDeserialization (object sender) { OnDeserialization (null); @@ -397,8 +374,6 @@ private void OnDeserialization (DaylightTime dlt) } else this_year = dlt.Start.Year; - utcOffsetWithOutDLS = new TimeSpan (m_ticksOffset); - utcOffsetWithDLS = new TimeSpan (m_ticksOffset + dlt.Delta.Ticks); this_year_dlt = dlt; } From 16dbea555d4f9b2cd92fbf49d061afecc0fd9caa Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Thu, 2 Oct 2014 13:44:35 -0400 Subject: [PATCH 319/543] Revert "Missing Args checks." This reverts commit 8b9c60075f7b97fe88c3c588968977ff9bcf8c28. --- .../Mono.Security/Mono.Security.Cryptography/CryptoTools.cs | 4 ---- .../corlib/System.Security.Cryptography/HashAlgorithm.cs | 2 -- 2 files changed, 6 deletions(-) diff --git a/mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoTools.cs b/mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoTools.cs index 054038731ae..d57ce5ae55c 100644 --- a/mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoTools.cs +++ b/mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoTools.cs @@ -88,10 +88,6 @@ public BlockProcessor (ICryptoTransform transform) // block size (which isn't their real internal block size) public BlockProcessor (ICryptoTransform transform, int blockSize) { - if (transform == null) - throw new ArgumentNullException ("transform"); - if (blockSize <= 0) - throw new ArgumentOutOfRangeException ("blockSize"); this.transform = transform; this.blockSize = blockSize; block = new byte [blockSize]; diff --git a/mcs/class/corlib/System.Security.Cryptography/HashAlgorithm.cs b/mcs/class/corlib/System.Security.Cryptography/HashAlgorithm.cs index 150cac95bef..07074f8aef3 100644 --- a/mcs/class/corlib/System.Security.Cryptography/HashAlgorithm.cs +++ b/mcs/class/corlib/System.Security.Cryptography/HashAlgorithm.cs @@ -98,8 +98,6 @@ public byte[] ComputeHash (Stream inputStream) // don't read stream unless object is ready to use if (disposed) throw new ObjectDisposedException ("HashAlgorithm"); - if (inputStream == null) - throw new ArgumentNullException ("InputStream"); byte[] buffer = new byte [4096]; int len = inputStream.Read (buffer, 0, 4096); From d525ff73e1f8b434b52d585b7dca12eba1b5c73c Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Thu, 2 Oct 2014 13:44:58 -0400 Subject: [PATCH 320/543] Revert "Refresh HashAlgorithmTest to match changed NullStream behaviour in 8b9c60075f7b97fe88c3c588968977ff9bcf8c28" This reverts commit 7ece665d16714db0979bde5df254231c5be24f10. --- .../Test/System.Security.Cryptography/HashAlgorithmTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs index 54a7c42238f..9feea2b3385 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs @@ -138,7 +138,7 @@ public void Clear2 () } [Test] - [ExpectedException (typeof (ArgumentNullException))] + [ExpectedException (typeof (NullReferenceException))] public void NullStream () { Stream s = null; From 3e3fe21e7f9e2a1c7cf3a0f286b44e00a72fc5e8 Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Thu, 2 Oct 2014 13:45:11 -0400 Subject: [PATCH 321/543] Revert "Finish test changes started in 7ece665d16714db0979bde5df254231c5be24f10" This reverts commit d171cdf5e281973c06f2751f4e33098f1a624a95. --- .../RSACryptoServiceProviderTest.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs index 1be7986a438..6cf1637d085 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs @@ -251,7 +251,8 @@ public void SignDataByteArrayNull () } [Test] - [ExpectedException (typeof (ArgumentNullException))] + //[ExpectedException (typeof (ArgumentNullException))] + [ExpectedException (typeof (NullReferenceException))] public void SignDataStreamNull () { rsa = new RSACryptoServiceProvider (minKeySize); From da3b7dd2714fae2ea23a2fa559bb99d9dae97d03 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 14:23:15 -0400 Subject: [PATCH 322/543] [amd64] Define MONO_ARCH_NOMAP32BIT on all non-linux platforms instead of defining it once for each platform. --- mono/mini/mini-amd64.h | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index f909b4f401a..f3ac1f9cdbb 100755 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -276,11 +276,11 @@ typedef struct { #endif /* !HOST_WIN32 && !__native_client__ */ -#if defined (__APPLE__) - -#define MONO_ARCH_NOMAP32BIT +#if !defined(__linux__) +#define MONO_ARCH_NOMAP32BIT 1 +#endif -#elif defined (__NetBSD__) +#if defined (__NetBSD__) #define REG_RAX 14 #define REG_RCX 3 @@ -300,16 +300,6 @@ typedef struct { #define REG_R15 11 #define REG_RIP 21 -#define MONO_ARCH_NOMAP32BIT - -#elif defined (__OpenBSD__) - -#define MONO_ARCH_NOMAP32BIT - -#elif defined (__DragonFly__) - -#define MONO_ARCH_NOMAP32BIT - #elif defined (__FreeBSD__) || defined(__FreeBSD_kernel__) #define REG_RAX 7 @@ -330,16 +320,6 @@ typedef struct { #define REG_R15 15 #define REG_RIP 20 -/* - * FreeBSD does not have MAP_32BIT, so code allocated by the code manager might not have a - * 32 bit address. - */ -#define MONO_ARCH_NOMAP32BIT - -#elif defined(HOST_WIN32) - -#define MONO_ARCH_NOMAP32BIT 1 - #endif /* __FreeBSD__ */ #ifdef HOST_WIN32 From 1e709688bb2dd61aa6a040456d689742bf755ed8 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 14:32:11 -0400 Subject: [PATCH 323/543] [jit] Remove unused defines. --- mono/mini/mini-amd64.h | 44 ------------------------------------------ mono/mini/mini-arm.h | 1 - mono/mini/mini-mips.h | 1 - mono/mini/mini-ppc.h | 1 - mono/mini/mini-s390x.h | 1 - mono/mini/mini-x86.h | 1 - 6 files changed, 49 deletions(-) diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index f3ac1f9cdbb..e62821e3328 100755 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -280,48 +280,6 @@ typedef struct { #define MONO_ARCH_NOMAP32BIT 1 #endif -#if defined (__NetBSD__) - -#define REG_RAX 14 -#define REG_RCX 3 -#define REG_RDX 2 -#define REG_RBX 13 -#define REG_RSP 24 -#define REG_RBP 12 -#define REG_RSI 1 -#define REG_RDI 0 -#define REG_R8 4 -#define REG_R9 5 -#define REG_R10 6 -#define REG_R11 7 -#define REG_R12 8 -#define REG_R13 9 -#define REG_R14 10 -#define REG_R15 11 -#define REG_RIP 21 - -#elif defined (__FreeBSD__) || defined(__FreeBSD_kernel__) - -#define REG_RAX 7 -#define REG_RCX 4 -#define REG_RDX 3 -#define REG_RBX 8 -#define REG_RSP 23 -#define REG_RBP 9 -#define REG_RSI 2 -#define REG_RDI 1 -#define REG_R8 5 -#define REG_R9 6 -#define REG_R10 10 -#define REG_R11 11 -#define REG_R12 12 -#define REG_R13 13 -#define REG_R14 14 -#define REG_R15 15 -#define REG_RIP 20 - -#endif /* __FreeBSD__ */ - #ifdef HOST_WIN32 #define MONO_AMD64_ARG_REG1 AMD64_RCX #define MONO_AMD64_ARG_REG2 AMD64_RDX @@ -339,7 +297,6 @@ typedef struct { #define MONO_ARCH_EMULATE_FREM 1 #define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1 -#define MONO_ARCH_ENABLE_REGALLOC_IN_EH_BLOCKS 1 #define MONO_ARCH_ENABLE_MONO_LMF_VAR 1 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1 @@ -360,7 +317,6 @@ typedef struct { #define MONO_ARCH_ENABLE_GLOBAL_RA 1 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1 #define MONO_ARCH_HAVE_LIVERANGE_OPS 1 -#define MONO_ARCH_HAVE_XP_UNWIND 1 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1 #define MONO_ARCH_MONITOR_OBJECT_REG MONO_AMD64_ARG_REG1 #define MONO_ARCH_HAVE_GET_TRAMPOLINES 1 diff --git a/mono/mini/mini-arm.h b/mono/mini/mini-arm.h index 7c3fd9ad041..75a8ad9d526 100644 --- a/mono/mini/mini-arm.h +++ b/mono/mini/mini-arm.h @@ -256,7 +256,6 @@ typedef struct MonoCompileArch { #define MONO_ARCH_NEED_DIV_CHECK 1 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE -#define MONO_ARCH_HAVE_XP_UNWIND 1 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1 #define ARM_NUM_REG_ARGS (ARM_LAST_ARG_REG-ARM_FIRST_ARG_REG+1) diff --git a/mono/mini/mini-mips.h b/mono/mini/mini-mips.h index c94f7c898f3..044410ba7a8 100644 --- a/mono/mini/mini-mips.h +++ b/mono/mini/mini-mips.h @@ -268,7 +268,6 @@ typedef struct MonoCompileArch { #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1 -#define MONO_ARCH_HAVE_XP_UNWIND 1 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1 #define MONO_ARCH_GSHARED_SUPPORTED 1 diff --git a/mono/mini/mini-ppc.h b/mono/mini/mini-ppc.h index c3025a712e0..2fc2ba81c96 100644 --- a/mono/mini/mini-ppc.h +++ b/mono/mini/mini-ppc.h @@ -182,7 +182,6 @@ typedef struct MonoCompileArch { #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1 -#define MONO_ARCH_HAVE_XP_UNWIND 1 #define MONO_ARCH_GSHARED_SUPPORTED 1 diff --git a/mono/mini/mini-s390x.h b/mono/mini/mini-s390x.h index 50b74c51fd9..f60e1445de2 100644 --- a/mono/mini/mini-s390x.h +++ b/mono/mini/mini-s390x.h @@ -54,7 +54,6 @@ typedef struct #define MONO_ARCH_VTABLE_REG MONO_ARCH_IMT_REG #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG #define MONO_ARCH_THIS_AS_FIRST_ARG 1 -#define MONO_ARCH_HAVE_XP_UNWIND 1 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1 diff --git a/mono/mini/mini-x86.h b/mono/mini/mini-x86.h index bce110f1035..ed50bddb9cb 100644 --- a/mono/mini/mini-x86.h +++ b/mono/mini/mini-x86.h @@ -217,7 +217,6 @@ typedef struct { #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1 #define MONO_ARCH_HAVE_LIVERANGE_OPS 1 -#define MONO_ARCH_HAVE_XP_UNWIND 1 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1 #if defined(__linux__) || defined (__APPLE__) #define MONO_ARCH_MONITOR_OBJECT_REG X86_EAX From 1317d99cae74df6e6ebe0be6807443c8b4738717 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 15:49:00 -0400 Subject: [PATCH 324/543] [sgen] Reorganize sgen-archdep.h to remove unused defines. --- mono/metadata/sgen-archdep.h | 72 +++++------------------------------ mono/metadata/sgen-os-posix.c | 17 ++++++++- 2 files changed, 25 insertions(+), 64 deletions(-) diff --git a/mono/metadata/sgen-archdep.h b/mono/metadata/sgen-archdep.h index b86ec318c7c..420dc96e47d 100644 --- a/mono/metadata/sgen-archdep.h +++ b/mono/metadata/sgen-archdep.h @@ -21,7 +21,14 @@ #ifndef __MONO_SGENARCHDEP_H__ #define __MONO_SGENARCHDEP_H__ -#include +#include + +/* + * Define either USE_MONO_CTX, or + * ARCH_SIGCTX_SP/ARCH_SIGCTX_IP/ARCH_STORE_REGS/ARCH_COPY_SIGCTX_REGS. + * Define ARCH_NUM_REGS to be the number of general registers in MonoContext, or the + * number of registers stored by ARCH_STORE_REGS. + */ #if defined(MONO_CROSS_COMPILE) @@ -35,35 +42,23 @@ #elif defined(TARGET_X86) -#include - #define REDZONE_SIZE 0 #define ARCH_NUM_REGS 8 -#ifdef MONO_ARCH_HAS_MONO_CONTEXT -#define USE_MONO_CTX -#else +#ifndef MONO_ARCH_HAS_MONO_CONTEXT #error 0 #endif -/*FIXME, move this to mono-sigcontext as this is generaly useful.*/ -#define ARCH_SIGCTX_SP(ctx) (UCONTEXT_REG_ESP ((ctx))) -#define ARCH_SIGCTX_IP(ctx) (UCONTEXT_REG_EIP ((ctx))) +#define USE_MONO_CTX #elif defined(TARGET_AMD64) -#include - #define REDZONE_SIZE 128 #define ARCH_NUM_REGS 16 #define USE_MONO_CTX -/*FIXME, move this to mono-sigcontext as this is generaly useful.*/ -#define ARCH_SIGCTX_SP(ctx) (UCONTEXT_REG_RSP (ctx)) -#define ARCH_SIGCTX_IP(ctx) (UCONTEXT_REG_RIP (ctx)) - #elif defined(TARGET_POWERPC) #define REDZONE_SIZE 224 @@ -99,39 +94,9 @@ /* We dont store ip, sp */ #define ARCH_NUM_REGS 14 -#define ARCH_STORE_REGS(ptr) \ - __asm__ __volatile__( \ - "push {lr}\n" \ - "mov lr, %0\n" \ - "stmia lr!, {r0-r12}\n" \ - "pop {lr}\n" \ - : \ - : "r" (ptr) \ - ) - -#define ARCH_SIGCTX_SP(ctx) (UCONTEXT_REG_SP((ctx))) -#define ARCH_SIGCTX_IP(ctx) (UCONTEXT_REG_PC((ctx))) -#define ARCH_COPY_SIGCTX_REGS(a,ctx) do { \ - ((a)[0]) = (gpointer) (UCONTEXT_REG_R0((ctx))); \ - ((a)[1]) = (gpointer) (UCONTEXT_REG_R1((ctx))); \ - ((a)[2]) = (gpointer) (UCONTEXT_REG_R2((ctx))); \ - ((a)[3]) = (gpointer) (UCONTEXT_REG_R3((ctx))); \ - ((a)[4]) = (gpointer) (UCONTEXT_REG_R4((ctx))); \ - ((a)[5]) = (gpointer) (UCONTEXT_REG_R5((ctx))); \ - ((a)[6]) = (gpointer) (UCONTEXT_REG_R6((ctx))); \ - ((a)[7]) = (gpointer) (UCONTEXT_REG_R7((ctx))); \ - ((a)[8]) = (gpointer) (UCONTEXT_REG_R8((ctx))); \ - ((a)[9]) = (gpointer) (UCONTEXT_REG_R9((ctx))); \ - ((a)[10]) = (gpointer) (UCONTEXT_REG_R10((ctx))); \ - ((a)[11]) = (gpointer) (UCONTEXT_REG_R11((ctx))); \ - ((a)[12]) = (gpointer) (UCONTEXT_REG_R12((ctx))); \ - ((a)[13]) = (gpointer) (UCONTEXT_REG_LR((ctx))); \ - } while (0) #elif defined(TARGET_ARM64) -#include - #ifdef __linux__ #define REDZONE_SIZE 0 #elif defined(__APPLE__) @@ -142,12 +107,6 @@ #define USE_MONO_CTX #define ARCH_NUM_REGS 31 -#define ARCH_STORE_REGS(ptr) do { g_assert_not_reached (); } while (0) - -#define ARCH_SIGCTX_SP(ctx) UCONTEXT_REG_SP (ctx) -#define ARCH_SIGCTX_IP(ctx) UCONTEXT_REG_PC (ctx) -#define ARCH_COPY_SIGCTX_REGS(a,ctx) do { g_assert_not_reached (); } while (0) - #elif defined(__mips__) #define REDZONE_SIZE 0 @@ -155,23 +114,12 @@ #define USE_MONO_CTX #define ARCH_NUM_REGS 32 -/* - * These casts are necessary since glibc always makes the - * gregs 64-bit values in userland. - */ -#define ARCH_SIGCTX_SP(ctx) ((gsize) UCONTEXT_GREGS((ctx))[29]) -#define ARCH_SIGCTX_IP(ctx) ((gsize) UCONTEXT_REG_PC((ctx))) - #elif defined(__s390x__) #define REDZONE_SIZE 0 -#include - #define USE_MONO_CTX #define ARCH_NUM_REGS 16 -#define ARCH_SIGCTX_SP(ctx) ((UCONTEXT_GREGS((ctx))) [15]) -#define ARCH_SIGCTX_IP(ctx) ((ucontext_t *) (ctx))->uc_mcontext.psw.addr #elif defined(__sparc__) diff --git a/mono/metadata/sgen-os-posix.c b/mono/metadata/sgen-os-posix.c index 909b8382c81..9918d16adc5 100644 --- a/mono/metadata/sgen-os-posix.c +++ b/mono/metadata/sgen-os-posix.c @@ -56,17 +56,30 @@ suspend_thread (SgenThreadInfo *info, void *context) #ifndef USE_MONO_CTX gpointer regs [ARCH_NUM_REGS]; #endif + MonoContext ctx; gpointer stack_start; info->stopped_domain = mono_domain_get (); - info->stopped_ip = context ? (gpointer) ARCH_SIGCTX_IP (context) : NULL; info->signal = 0; stop_count = sgen_global_stop_count; /* duplicate signal */ if (0 && info->stop_count == stop_count) return; +#ifdef USE_MONO_CTX + if (context) { + mono_sigctx_to_monoctx (context, &ctx); + info->stopped_ip = MONO_CONTEXT_GET_IP (&ctx); + stack_start = MONO_CONTEXT_GET_SP (&ctx) - REDZONE_SIZE; + } else { + info->stopped_ip = NULL; + stack_start = NULL; + } +#else + info->stopped_ip = context ? (gpointer) ARCH_SIGCTX_IP (context) : NULL; stack_start = context ? (char*) ARCH_SIGCTX_SP (context) - REDZONE_SIZE : NULL; +#endif + /* If stack_start is not within the limits, then don't set it in info and we will be restarted. */ if (stack_start >= info->stack_start_limit && info->stack_start <= info->stack_end) { @@ -74,7 +87,7 @@ suspend_thread (SgenThreadInfo *info, void *context) #ifdef USE_MONO_CTX if (context) { - mono_sigctx_to_monoctx (context, &info->ctx); + memcpy (&info->ctx, &ctx, sizeof (MonoContext)); } else { memset (&info->ctx, 0, sizeof (MonoContext)); } From 4437ecea91bab3fe68ba1c30521acf75052662cd Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 16:06:01 -0400 Subject: [PATCH 325/543] Fix the arm build. --- mono/utils/mono-context.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mono/utils/mono-context.h b/mono/utils/mono-context.h index 619e574e424..3b01b49f066 100755 --- a/mono/utils/mono-context.h +++ b/mono/utils/mono-context.h @@ -240,6 +240,8 @@ extern void mono_context_get_current (void *); #elif (defined(__arm__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM)) /* defined(__x86_64__) */ +#include + typedef struct { mgreg_t pc; mgreg_t regs [16]; From e7778f3fd587dc0a232c3c00193ee08910450a9d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 16:06:24 -0400 Subject: [PATCH 326/543] Fix a warning. --- mono/metadata/gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index a0472955071..4e025385b76 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -1224,7 +1224,7 @@ mono_gc_cleanup (void) ret = WaitForSingleObjectEx (gc_thread->handle, INFINITE, TRUE); g_assert (ret == WAIT_OBJECT_0); - mono_thread_join ((gpointer)gc_thread->tid); + mono_thread_join (MONO_UINT_TO_NATIVE_THREAD_ID (gc_thread->tid)); } } gc_thread = NULL; From 4c6a463678f3f0bfa599caeb66de72c7217fa95d Mon Sep 17 00:00:00 2001 From: Chris Hamons Date: Thu, 2 Oct 2014 15:34:48 -0500 Subject: [PATCH 327/543] [mono-api-html] Add filter for new namespaces/types - Reviewed by Sebastien --- mcs/tools/corcompare/mono-api-html/ApiDiff.cs | 11 ++++++++++- mcs/tools/corcompare/mono-api-html/ClassComparer.cs | 6 +++++- .../corcompare/mono-api-html/NamespaceComparer.cs | 7 ++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/mcs/tools/corcompare/mono-api-html/ApiDiff.cs b/mcs/tools/corcompare/mono-api-html/ApiDiff.cs index 6a7f39d90f3..b79dd7b886a 100644 --- a/mcs/tools/corcompare/mono-api-html/ApiDiff.cs +++ b/mcs/tools/corcompare/mono-api-html/ApiDiff.cs @@ -64,6 +64,11 @@ public static List IgnoreAdded { get { return ignoreAdded; } } + static List ignoreNew = new List (); + public static List IgnoreNew { + get { return ignoreNew; } + } + static List ignoreRemoved = new List (); public static List IgnoreRemoved { get { return ignoreRemoved; } @@ -83,11 +88,12 @@ public static int Main (string[] args) var options = new OptionSet { { "h|help", "Show this help", v => showHelp = true }, { "d|diff=", "HTML diff file out output (omit for stdout)", v => diff = v }, - { "i|ignore=", "Ignore both added and removed members whose description matches a given C# regular expression (see below).", + { "i|ignore=", "Ignore new, added, and removed members whose description matches a given C# regular expression (see below).", v => { var r = new Regex (v); State.IgnoreAdded.Add (r); State.IgnoreRemoved.Add (r); + State.IgnoreNew.Add (r); } }, { "a|ignore-added=", "Ignore added members whose description matches a given C# regular expression (see below).", @@ -96,6 +102,9 @@ public static int Main (string[] args) { "r|ignore-removed=", "Ignore removed members whose description matches a given C# regular expression (see below).", v => State.IgnoreRemoved.Add (new Regex (v)) }, + { "n|ignore-new=", "Ignore new namespaces and types whose description matches a given C# regular expression (see below).", + v => State.IgnoreNew.Add (new Regex (v)) + }, { "x|lax", "Ignore duplicate XML entries", v => State.Lax = true } }; diff --git a/mcs/tools/corcompare/mono-api-html/ClassComparer.cs b/mcs/tools/corcompare/mono-api-html/ClassComparer.cs index bdf22fea489..d96613c3e8a 100644 --- a/mcs/tools/corcompare/mono-api-html/ClassComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/ClassComparer.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Xml.Linq; namespace Xamarin.ApiDiff { @@ -68,7 +69,10 @@ public void Compare (XElement source, XElement target) public override void Added (XElement target) { - Output.WriteLine ("

New Type {0}.{1}

", State.Namespace, target.Attribute ("name").Value); + string name = target.Attribute ("name").Value; + if (State.IgnoreNew.Any (re => re.IsMatch (name))) + return; + Output.WriteLine ("

New Type {0}.{1}

", State.Namespace, name); Output.WriteLine ("
");
 			State.Indent = 0;
 			AddedInner (target);
diff --git a/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs b/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs
index 7239385870e..427df66e6eb 100644
--- a/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs
+++ b/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs
@@ -26,6 +26,7 @@
 
 using System;
 using System.IO;
+using System.Linq;
 using System.Xml.Linq;
 
 namespace Xamarin.ApiDiff {
@@ -55,7 +56,11 @@ public override void SetContext (XElement current)
 
 		public override void Added (XElement target)
 		{
-			Output.WriteLine ("

New Namespace {0}

", target.Attribute ("name").Value); + string name = target.Attribute ("name").Value; + if (State.IgnoreNew.Any (re => re.IsMatch (name))) + return; + + Output.WriteLine ("

New Namespace {0}

", name); Output.WriteLine (); // list all new types foreach (var addedType in target.Element ("classes").Elements ("class")) From c1fe551f9cb6365f742f7444e8df5f31111a11f6 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 18:41:42 -0400 Subject: [PATCH 328/543] [arm] Increase the length of the tls_get opcode. --- mono/mini/cpu-arm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/mini/cpu-arm.md b/mono/mini/cpu-arm.md index 431936113c3..6fd40d92c3a 100644 --- a/mono/mini/cpu-arm.md +++ b/mono/mini/cpu-arm.md @@ -211,7 +211,7 @@ sbb_imm: dest:i src1:i len:12 br_reg: src1:i len:8 bigmul: len:8 dest:l src1:i src2:i bigmul_un: len:8 dest:l src1:i src2:i -tls_get: len:8 dest:i clob:c +tls_get: len:20 dest:i clob:c # 32 bit opcodes int_add: dest:i src1:i src2:i len:4 From f862057fb1de1b83edc63b2a104270175e7dfd13 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 19:04:27 -0400 Subject: [PATCH 329/543] [amd64] Simplify mono_arch_install_handler_block_guard (). --- mono/mini/mini-amd64.c | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index faa8cafd322..9317394473a 100755 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -8174,49 +8174,15 @@ mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val) } } -/*MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD*/ gpointer mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, MonoContext *ctx, gpointer new_value) { - int offset; gpointer *sp, old_value; char *bp; - const unsigned char *handler; - - /*Decode the first instruction to figure out where did we store the spvar*/ - /*Our jit MUST generate the following: - mov %rsp, ?(%rbp) - - Which is encoded as: REX.W 0x89 mod_rm - mod_rm (rsp, rbp, imm) which can be: (imm will never be zero) - mod (reg + imm8): 01 reg(rsp): 100 rm(rbp): 101 -> 01100101 (0x65) - mod (reg + imm32): 10 reg(rsp): 100 rm(rbp): 101 -> 10100101 (0xA5) - - FIXME can we generate frameless methods on this case? - - */ - handler = clause->handler_start; - - /*REX.W*/ - if (*handler != 0x48) - return NULL; - ++handler; - - /*mov r, r/m */ - if (*handler != 0x89) - return NULL; - ++handler; - - if (*handler == 0x65) - offset = *(signed char*)(handler + 1); - else if (*handler == 0xA5) - offset = *(int*)(handler + 1); - else - return NULL; /*Load the spvar*/ bp = MONO_CONTEXT_GET_BP (ctx); - sp = *(gpointer*)(bp + offset); + sp = *(gpointer*)(bp + clause->exvar_offset); old_value = *sp; if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size)) From 9523b73148d711b2d1c036202823407b2454e3f7 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 20:35:42 -0400 Subject: [PATCH 330/543] [arm] Implement handler block guards. --- mono/mini/mini-arm.c | 20 +++++++++++ mono/mini/mini-arm.h | 1 + mono/mini/tramp-arm.c | 78 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index b644d7dca7a..9491a442d1a 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -6929,6 +6929,26 @@ mono_arch_get_trampolines (gboolean aot) return mono_arm_get_exception_trampolines (aot); } +gpointer +mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, MonoContext *ctx, gpointer new_value) +{ + gpointer *lr_loc; + char *old_value; + char *bp; + + /*Load the spvar*/ + bp = MONO_CONTEXT_GET_BP (ctx); + lr_loc = (gpointer*)(bp + clause->exvar_offset); + + old_value = *lr_loc; + if ((char*)old_value < (char*)ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size)) + return old_value; + + *lr_loc = new_value; + + return old_value; +} + #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) /* * mono_arch_set_breakpoint: diff --git a/mono/mini/mini-arm.h b/mono/mini/mini-arm.h index 75a8ad9d526..0e7061c35d5 100644 --- a/mono/mini/mini-arm.h +++ b/mono/mini/mini-arm.h @@ -283,6 +283,7 @@ typedef struct MonoCompileArch { #define MONO_ARCH_GC_MAPS_SUPPORTED 1 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1 +#define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1 #define MONO_ARCH_GSHAREDVT_SUPPORTED 1 #define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE 1 diff --git a/mono/mini/tramp-arm.c b/mono/mini/tramp-arm.c index bb500a7c0f5..f9e651093b4 100644 --- a/mono/mini/tramp-arm.c +++ b/mono/mini/tramp-arm.c @@ -505,17 +505,21 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty tramp = mono_get_trampoline_code (tramp_type); - mono_domain_lock (domain); + if (domain) { + mono_domain_lock (domain); #ifdef USE_JUMP_TABLES - code = buf = mono_domain_code_reserve_align (domain, size, 4); + code = buf = mono_domain_code_reserve_align (domain, size, 4); #else - code = buf = mono_domain_code_reserve_align (domain, size, 4); - if ((short_branch = branch_for_target_reachable (code + 4, tramp))) { - size = 12; - mono_domain_code_commit (domain, code, SPEC_TRAMP_SIZE, size); + code = buf = mono_domain_code_reserve_align (domain, size, 4); + if ((short_branch = branch_for_target_reachable (code + 4, tramp))) { + size = 12; + mono_domain_code_commit (domain, code, SPEC_TRAMP_SIZE, size); } #endif - mono_domain_unlock (domain); + mono_domain_unlock (domain); + } else { + code = buf = mono_global_codeman_reserve (size); + } #ifdef USE_JUMP_TABLES /* For jumptables case we always generate the same code for trampolines, @@ -894,6 +898,59 @@ mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean a return buf; } +static gpointer +handler_block_trampoline_helper (gpointer *ptr) +{ + MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); + return jit_tls->handler_block_return_address; +} + +gpointer +mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot) +{ + guint8 *tramp; + guint8 *code, *buf; + int tramp_size = 64; + MonoJumpInfo *ji = NULL; + GSList *unwind_ops = NULL; + + g_assert (!aot); + + code = buf = mono_global_codeman_reserve (tramp_size); + + tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD, NULL, NULL); + + /* + This trampoline restore the call chain of the handler block then jumps into the code that deals with it. + */ + + /* + * We are in a method frame after the call emitted by OP_CALL_HANDLER. + */ + /* Obtain jit_tls->handler_block_return_address */ + ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0); + ARM_B (code, 0); + *(gpointer*)code = handler_block_trampoline_helper; + code += 4; + + /* Set it as the return address so the trampoline will return to it */ + ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_R0); + + /* Call the trampoline */ + ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0); + code = emit_bx (code, ARMREG_R0); + *(gpointer*)code = tramp; + code += 4; + + mono_arch_flush_icache (buf, code - buf); + g_assert (code - buf <= tramp_size); + + if (info) + *info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops); + + return buf; +} + #else guchar* @@ -944,6 +1001,13 @@ mono_arch_get_nullified_class_init_trampoline (MonoTrampInfo **info) g_assert_not_reached (); return NULL; } + +gpointer +mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot) +{ + g_assert_not_reached (); + return NULL; +} #endif /* DISABLE_JIT */ From 7a430acd7765fec9a4402355c0400edc2b0ac038 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 20:40:38 -0400 Subject: [PATCH 331/543] [jit] Get rid of unused MONO_ARCH_THIS_AS_FIRST_ARG define. --- mono/mini/mini-amd64.h | 1 - mono/mini/mini-arm.h | 1 - mono/mini/mini-ia64.h | 1 - mono/mini/mini-mips.h | 2 -- mono/mini/mini-ppc.h | 1 - mono/mini/mini-s390x.h | 1 - mono/mini/mini-sparc.h | 2 -- mono/mini/mini-trampolines.c | 4 ---- mono/mini/mini-x86.h | 1 - 9 files changed, 14 deletions(-) diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index e62821e3328..ebd2638727b 100755 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -336,7 +336,6 @@ typedef struct { #define MONO_ARCH_HAVE_LLVM_IMT_TRAMPOLINE 1 #define MONO_ARCH_LLVM_SUPPORTED 1 -#define MONO_ARCH_THIS_AS_FIRST_ARG 1 #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1 #define MONO_ARCH_HAVE_CARD_TABLE_WBARRIER 1 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1 diff --git a/mono/mini/mini-arm.h b/mono/mini/mini-arm.h index 0e7061c35d5..f22514b61ef 100644 --- a/mono/mini/mini-arm.h +++ b/mono/mini/mini-arm.h @@ -266,7 +266,6 @@ typedef struct MonoCompileArch { #define MONO_ARCH_AOT_SUPPORTED 1 #define MONO_ARCH_LLVM_SUPPORTED 1 -#define MONO_ARCH_THIS_AS_FIRST_ARG 1 #define MONO_ARCH_GSHARED_SUPPORTED 1 #define MONO_ARCH_DYN_CALL_SUPPORTED 1 diff --git a/mono/mini/mini-ia64.h b/mono/mini/mini-ia64.h index d419bc26c72..15bb596d414 100644 --- a/mono/mini/mini-ia64.h +++ b/mono/mini/mini-ia64.h @@ -115,6 +115,5 @@ unw_dyn_region_info_t* mono_ia64_create_unwind_region (Ia64CodegenState *code); #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1 #define MONO_ARCH_HAVE_SAVE_UNWIND_INFO 1 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1 -#define MONO_ARCH_THIS_AS_FIRST_ARG 1 #endif /* __MONO_MINI_IA64_H__ */ diff --git a/mono/mini/mini-mips.h b/mono/mini/mini-mips.h index 044410ba7a8..d8d769130c4 100644 --- a/mono/mini/mini-mips.h +++ b/mono/mini/mini-mips.h @@ -279,8 +279,6 @@ typedef struct MonoCompileArch { #define MONO_ARCH_NEED_DIV_CHECK 1 #define MONO_ARCH_NO_IOV_CHECK 1 -#define MONO_ARCH_THIS_AS_FIRST_ARG 1 - #define MIPS_NUM_REG_ARGS (MIPS_LAST_ARG_REG-MIPS_FIRST_ARG_REG+1) #define MIPS_NUM_REG_FPARGS (MIPS_LAST_FPARG_REG-MIPS_FIRST_FPARG_REG+1) diff --git a/mono/mini/mini-ppc.h b/mono/mini/mini-ppc.h index 2fc2ba81c96..4b39b7ac223 100644 --- a/mono/mini/mini-ppc.h +++ b/mono/mini/mini-ppc.h @@ -191,7 +191,6 @@ typedef struct MonoCompileArch { #if !defined(MONO_CROSS_COMPILE) && !defined(TARGET_PS3) #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1 #endif -#define MONO_ARCH_THIS_AS_FIRST_ARG 1 #define MONO_ARCH_HAVE_OP_TAIL_CALL 1 #define PPC_NUM_REG_ARGS (PPC_LAST_ARG_REG-PPC_FIRST_ARG_REG+1) diff --git a/mono/mini/mini-s390x.h b/mono/mini/mini-s390x.h index f60e1445de2..b40425c6478 100644 --- a/mono/mini/mini-s390x.h +++ b/mono/mini/mini-s390x.h @@ -53,7 +53,6 @@ typedef struct #define MONO_ARCH_IMT_REG s390_r9 #define MONO_ARCH_VTABLE_REG MONO_ARCH_IMT_REG #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG -#define MONO_ARCH_THIS_AS_FIRST_ARG 1 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1 diff --git a/mono/mini/mini-sparc.h b/mono/mini/mini-sparc.h index 4b947784558..ab8e452b70e 100644 --- a/mono/mini/mini-sparc.h +++ b/mono/mini/mini-sparc.h @@ -112,8 +112,6 @@ void mono_arch_tls_init (void); #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS #endif -#define MONO_ARCH_THIS_AS_FIRST_ARG 1 - #ifndef __GNUC__ /* assume Sun compiler if not GCC */ static void * __builtin_return_address(int depth) diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index 4434564ee79..d8f1e4298e9 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -728,10 +728,6 @@ mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp) * We use one vtable trampoline per vtable slot index, so we need only the vtable, * the other two can be computed from the vtable + the slot index. */ -#ifndef MONO_ARCH_THIS_AS_FIRST_ARG - /* All architectures should support this */ - g_assert_not_reached (); -#endif /* * Obtain the vtable from the 'this' arg. diff --git a/mono/mini/mini-x86.h b/mono/mini/mini-x86.h index ed50bddb9cb..f6ddc930427 100644 --- a/mono/mini/mini-x86.h +++ b/mono/mini/mini-x86.h @@ -245,7 +245,6 @@ typedef struct { #define MONO_ARCH_GSHARED_SUPPORTED 1 #define MONO_ARCH_HAVE_LLVM_IMT_TRAMPOLINE 1 #define MONO_ARCH_LLVM_SUPPORTED 1 -#define MONO_ARCH_THIS_AS_FIRST_ARG 1 #if defined(MONO_ARCH_USE_SIGACTION) || defined(TARGET_WIN32) #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1 From af33ad4eaac6b2cdd95f120021c2ef3055e09137 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 21:29:51 -0400 Subject: [PATCH 332/543] [jit] Implement 5dbf97e66057f8626c53fcea30f1988d6627e5a2 for calls made from NEWOBJ too. Fixes #23557. --- mono/mini/method-to-ir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index c97c935fe9d..973f37bd735 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -9738,7 +9738,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b addr = emit_get_rgctx_gsharedvt_call (cfg, context_used, fsig, cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE); mono_emit_calli (cfg, fsig, sp, addr, NULL, vtable_arg); } else if (context_used && - ((!mono_method_is_generic_sharable (cmethod, TRUE) || + ((!mono_method_is_generic_sharable_full (cmethod, TRUE, FALSE, FALSE) || !mono_class_generic_sharing_enabled (cmethod->klass)) || cfg->gsharedvt)) { MonoInst *cmethod_addr; From 6e27f984ab97136f16f5d945ba28ad207ed95c4c Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 2 Oct 2014 23:29:53 -0400 Subject: [PATCH 333/543] [bcl] Use random ports for the HttpListener tests. --- .../Test/System.Net/HttpListenerTest.cs | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/mcs/class/System/Test/System.Net/HttpListenerTest.cs b/mcs/class/System/Test/System.Net/HttpListenerTest.cs index 05ff63ce8ea..7f3011e2b9d 100644 --- a/mcs/class/System/Test/System.Net/HttpListenerTest.cs +++ b/mcs/class/System/Test/System.Net/HttpListenerTest.cs @@ -36,6 +36,14 @@ namespace MonoTests.System.Net { [TestFixture] public class HttpListenerTest { + + int port; + + [SetUp] + public void SetUp () { + port = new Random ().Next (7777, 8000); + } + [Test] public void DefaultProperties () { @@ -152,10 +160,12 @@ public void DefaultHttpsPort () [Test] public void TwoListeners_SameAddress () { + if (!CanOpenPort (port)) + Assert.Ignore ("port"); HttpListener listener1 = new HttpListener (); - listener1.Prefixes.Add ("http://127.0.0.1:7777/"); + listener1.Prefixes.Add ("http://127.0.0.1:" + port + "/"); HttpListener listener2 = new HttpListener (); - listener2.Prefixes.Add ("http://127.0.0.1:7777/hola/"); + listener2.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/"); listener1.Start (); listener2.Start (); } @@ -164,10 +174,12 @@ public void TwoListeners_SameAddress () [ExpectedException (typeof (HttpListenerException))] public void TwoListeners_SameURL () { + if (!CanOpenPort (port)) + Assert.Ignore ("port"); HttpListener listener1 = new HttpListener (); - listener1.Prefixes.Add ("http://127.0.0.1:7777/hola/"); + listener1.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/"); HttpListener listener2 = new HttpListener (); - listener2.Prefixes.Add ("http://127.0.0.1:7777/hola/"); + listener2.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/"); listener1.Start (); listener2.Start (); } @@ -176,8 +188,10 @@ public void TwoListeners_SameURL () [ExpectedException (typeof (HttpListenerException))] public void MultipleSlashes () { + if (!CanOpenPort (port)) + Assert.Ignore ("port"); HttpListener listener = new HttpListener (); - listener.Prefixes.Add ("http://localhost:7777/hola////"); + listener.Prefixes.Add ("http://localhost:" + port + "/hola////"); // this one throws on Start(), not when adding it. listener.Start (); } @@ -186,8 +200,10 @@ public void MultipleSlashes () [ExpectedException (typeof (HttpListenerException))] public void PercentSign () { + if (!CanOpenPort (port)) + Assert.Ignore ("port"); HttpListener listener = new HttpListener (); - listener.Prefixes.Add ("http://localhost:7777/hola%3E/"); + listener.Prefixes.Add ("http://localhost:" + port + "/hola%3E/"); // this one throws on Start(), not when adding it. listener.Start (); } @@ -202,8 +218,10 @@ public void CloseBeforeStart () [Test] public void CloseTwice () { + if (!CanOpenPort (port)) + Assert.Ignore ("port"); HttpListener listener = new HttpListener (); - listener.Prefixes.Add ("http://localhost:7777/hola/"); + listener.Prefixes.Add ("http://localhost:" + port + "/hola/"); listener.Start (); listener.Close (); listener.Close (); @@ -212,8 +230,10 @@ public void CloseTwice () [Test] public void StartStopStart () { + if (!CanOpenPort (port)) + Assert.Ignore ("port"); HttpListener listener = new HttpListener (); - listener.Prefixes.Add ("http://localhost:7777/hola/"); + listener.Prefixes.Add ("http://localhost:" + port + "/hola/"); listener.Start (); listener.Stop (); listener.Start (); @@ -223,8 +243,10 @@ public void StartStopStart () [Test] public void StartStopDispose () { + if (!CanOpenPort (port)) + Assert.Ignore ("port"); using (HttpListener listener = new HttpListener ()){ - listener.Prefixes.Add ("http://localhost:7777/hola/"); + listener.Prefixes.Add ("http://localhost:" + port + "/hola/"); listener.Start (); listener.Stop (); } @@ -240,8 +262,10 @@ public void AbortBeforeStart () [Test] public void AbortTwice () { + if (!CanOpenPort (port)) + Assert.Ignore ("port"); HttpListener listener = new HttpListener (); - listener.Prefixes.Add ("http://localhost:7777/hola/"); + listener.Prefixes.Add ("http://localhost:" + port + "/hola/"); listener.Start (); listener.Abort (); listener.Abort (); From b0cff959e47c3d9955e6675364bf71404cd74bac Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Thu, 2 Oct 2014 21:04:13 -0700 Subject: [PATCH 334/543] [runtime] Fix allocation size calculation for strings in 64-bit builds. Depending on alignment and packing, part of the string might be inside the MonoString struct boundaries. This e.g. shows up on 64-bit builds of mono where we were allocating 4 extra bytes per string. --- mono/metadata/boehm-gc.c | 2 +- mono/metadata/object.c | 4 ++-- mono/metadata/sgen-alloc.c | 10 +++++----- mono/metadata/sgen-gc.h | 4 ++-- mono/metadata/string-icalls.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index 3320820f877..a3f8296459a 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -753,7 +753,7 @@ create_allocator (int atype, int tls_key) bytes_var = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg); if (atype == ATYPE_STRING) { /* a string alloator method takes the args: (vtable, len) */ - /* bytes = (sizeof (MonoString) + ((len + 1) * 2)); */ + /* bytes = (offsetof (MonoString, chars) + ((len + 1) * 2)); */ mono_mb_emit_ldarg (mb, 1); mono_mb_emit_icon (mb, 1); mono_mb_emit_byte (mb, MONO_CEE_ADD); diff --git a/mono/metadata/object.c b/mono/metadata/object.c index a2aa759293b..b9abf073f05 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -5041,10 +5041,10 @@ mono_string_new_size (MonoDomain *domain, gint32 len) size_t size; /* check for overflow */ - if (len < 0 || len > ((SIZE_MAX - sizeof (MonoString) - 2) / 2)) + if (len < 0 || len > ((SIZE_MAX - offsetof (MonoString, chars) - 2) / 2)) mono_gc_out_of_memory (-1); - size = (sizeof (MonoString) + ((len + 1) * 2)); + size = (offsetof (MonoString, chars) + ((len + 1) * 2)); g_assert (size > 0); vtable = mono_class_vtable (domain, mono_defaults.string_class); diff --git a/mono/metadata/sgen-alloc.c b/mono/metadata/sgen-alloc.c index d9a52e9b195..5d343adbe18 100644 --- a/mono/metadata/sgen-alloc.c +++ b/mono/metadata/sgen-alloc.c @@ -887,7 +887,7 @@ create_allocator (int atype) /* * a string allocator method takes the args: (vtable, len) * - * bytes = sizeof (MonoString) + ((len + 1) * 2) + * bytes = offsetof (MonoString, chars) + ((len + 1) * 2) * * condition: * @@ -895,11 +895,11 @@ create_allocator (int atype) * * therefore: * - * sizeof (MonoString) + ((len + 1) * 2) <= INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - * len <= (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - sizeof (MonoString)) / 2 - 1 + * offsetof (MonoString, chars) + ((len + 1) * 2) <= INT32_MAX - (SGEN_ALLOC_ALIGN - 1) + * len <= (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - offsetof (MonoString, chars)) / 2 - 1 */ mono_mb_emit_ldarg (mb, 1); - mono_mb_emit_icon (mb, (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - sizeof (MonoString)) / 2 - 1); + mono_mb_emit_icon (mb, (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - MONO_STRUCT_OFFSET (MonoString, chars)) / 2 - 1); pos = mono_mb_emit_short_branch (mb, MONO_CEE_BLE_UN_S); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); @@ -911,7 +911,7 @@ create_allocator (int atype) mono_mb_emit_icon (mb, 1); mono_mb_emit_byte (mb, MONO_CEE_SHL); //WE manually fold the above + 2 here - mono_mb_emit_icon (mb, sizeof (MonoString) + 2); + mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoString, chars) + 2); mono_mb_emit_byte (mb, CEE_ADD); mono_mb_emit_stloc (mb, size_var); } else { diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 076d03bc9d7..9f21b3e76f0 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -731,7 +731,7 @@ slow_object_get_size (MonoVTable *vtable, MonoObject* o) * mono_array_length_fast not using the object's vtable. */ if (klass == mono_defaults.string_class) { - return sizeof (MonoString) + 2 * mono_string_length_fast ((MonoString*) o) + 2; + return offsetof (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2; } else if (klass->rank) { MonoArray *array = (MonoArray*)o; size_t size = sizeof (MonoArray) + klass->sizes.element_size * mono_array_length_fast (array); @@ -782,7 +782,7 @@ sgen_par_object_get_size (MonoVTable *vtable, MonoObject* o) if (type == DESC_TYPE_RUN_LENGTH || type == DESC_TYPE_SMALL_BITMAP) { mword size = descr & 0xfff8; if (size == 0) /* This is used to encode a string */ - return sizeof (MonoString) + 2 * mono_string_length_fast ((MonoString*) o) + 2; + return offsetof (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2; return size; } else if (type == DESC_TYPE_VECTOR) { int element_size = ((descr) >> VECTOR_ELSIZE_SHIFT) & MAX_ELEMENT_SIZE; diff --git a/mono/metadata/string-icalls.c b/mono/metadata/string-icalls.c index 0927141e792..388d866141f 100644 --- a/mono/metadata/string-icalls.c +++ b/mono/metadata/string-icalls.c @@ -65,5 +65,5 @@ ves_icall_System_String_GetLOSLimit (void) { int limit = mono_gc_get_los_limit (); - return (limit - 2 - sizeof (MonoString)) / 2; + return (limit - 2 - offsetof (MonoString, chars)) / 2; } From 8ab9a76c7ec0c1a5db1cb3d7869c72bd6af478ef Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 2 Oct 2014 14:02:38 +0100 Subject: [PATCH 335/543] Updated TimeZoneInfoTest.DSTTransisions to correct .NET behavior. --- mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs b/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs index f6ea66e98c6..65f99d62703 100644 --- a/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs +++ b/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs @@ -232,7 +232,7 @@ public void DSTTransisions () DateTime afterDST = new DateTime (2007, 10, 28, 2, 0, 0, DateTimeKind.Unspecified); Assert.IsFalse (london.IsDaylightSavingTime (beforeDST), "Just before DST"); Assert.IsTrue (london.IsDaylightSavingTime (startDST), "the first seconds of DST"); - Assert.IsTrue (london.IsDaylightSavingTime (endDST), "The last seconds of DST"); + Assert.IsFalse (london.IsDaylightSavingTime (endDST), "The last seconds of DST"); Assert.IsFalse (london.IsDaylightSavingTime (afterDST), "Just after DST"); } From 411d4aa0bb64e6da220a7dc9964be075577508f3 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 2 Oct 2014 18:28:11 +0100 Subject: [PATCH 336/543] Test TimeZoneInfo.GetUtcOffset with multiple DST and DateTimeKind. --- .../Test/System/TimeZoneInfoTest.cs | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs b/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs index 65f99d62703..c3972e747c1 100644 --- a/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs +++ b/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs @@ -804,6 +804,143 @@ public void Serialization_Deserialization () Assert.IsTrue (london.Equals (deserialized)); } } + + [TestFixture] + public class MultipleDaylightSavingTimeTests { + private TimeZoneInfo cairo; + private DateTime dst1Start; + private DateTime dst1End; + private DateTime dst2Start; + private DateTime dst2End; + + private TimeSpan baseUtcOffset; + private TimeSpan dstUtcOffset; + private TimeSpan dstOffset; + + [SetUp] + public void CreateTimeZones () + { + /* + From 1/1/2014 12:00:00 AM to 6/30/2014 12:00:00 AM + Delta: 01:00:00 + Begins at 12:00 AM on 16 May + Ends at 1:00 AM on 29 June + From 7/1/2014 12:00:00 AM to 12/31/2014 12:00:00 AM + Delta: 01:00:00 + Begins at 12:00 AM on 29 July + Ends at 12:00 AM on 26 September + */ + dst1Start = new DateTime (2014, 5, 16); + dst1End = new DateTime (2014, 6, 29); + dst2Start = new DateTime (2014, 7, 29); + dst2End = new DateTime (2014, 9, 26); + + baseUtcOffset = new TimeSpan (2, 0, 0); + dstUtcOffset = new TimeSpan (3, 0, 0); + dstOffset = dstUtcOffset - baseUtcOffset; + + var rule1 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule ( + new DateTime (2014, 1, 1), new DateTime (2014, 6, 30), dstOffset, + CreateFixedDateRule (dst1Start), CreateFixedDateRule (dst1End)); + + var rule2 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule ( + new DateTime (2014, 7, 1), new DateTime (2014, 12, 31), dstOffset, + CreateFixedDateRule (dst2Start), CreateFixedDateRule (dst2End)); + + cairo = TimeZoneInfo.CreateCustomTimeZone ("Africa/Cairo", baseUtcOffset, "Africa/Cairo", "EET", "EEST", + new [] {rule1, rule2}); + } + + private static TimeZoneInfo.TransitionTime CreateFixedDateRule (DateTime dateTime) + { + var time = new DateTime (dateTime.Ticks - dateTime.Date.Ticks); + return TimeZoneInfo.TransitionTime.CreateFixedDateRule (time, dateTime.Month, dateTime.Day); + } + + [Test] + public void GetUtcOffset_FromUTC () + { + var d = dst1Start.Add (-baseUtcOffset); + d = DateTime.SpecifyKind (d, DateTimeKind.Utc); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + + d = dst1End.Add (-baseUtcOffset-dstOffset); + d = DateTime.SpecifyKind (d, DateTimeKind.Utc); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + + d = dst2Start.Add (-baseUtcOffset); + d = DateTime.SpecifyKind (d, DateTimeKind.Utc); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + + d = dst2End.Add (-baseUtcOffset-dstOffset); + d = DateTime.SpecifyKind (d, DateTimeKind.Utc); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + } + + [Test] + public void GetUtcOffset_FromLocal () + { + var d = dst1Start.Add (-baseUtcOffset); + d = DateTime.SpecifyKind (d, DateTimeKind.Utc); + d = d.ToLocalTime (); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + + d = dst1End.Add (-baseUtcOffset-dstOffset); + d = DateTime.SpecifyKind (d, DateTimeKind.Utc); + d = d.ToLocalTime (); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + + d = dst2Start.Add (-baseUtcOffset); + d = DateTime.SpecifyKind (d, DateTimeKind.Utc); + d = d.ToLocalTime (); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + + d = dst2End.Add (-baseUtcOffset-dstOffset); + d = DateTime.SpecifyKind (d, DateTimeKind.Utc); + d = d.ToLocalTime (); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + } + + [Test] + public void GetUtcOffset_FromUnspecified () + { + var d = dst1Start.Add (dstOffset); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + + d = dst1End.Add (-dstOffset); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + + d = dst2Start.Add (dstOffset); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + + d = dst2End.Add (-dstOffset); + Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1)))); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d)); + Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1)))); + } + } } } #endif From b863d3c58d5528cf4e0e031eca87d3628679c9e2 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 2 Oct 2014 18:34:41 +0100 Subject: [PATCH 337/543] Simplified TimeZone.ToLocalTime. Old code was producing invalid DST dates. --- mcs/class/corlib/System/TimeZone.cs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/mcs/class/corlib/System/TimeZone.cs b/mcs/class/corlib/System/TimeZone.cs index edbf6a4bb27..f4e01b03be3 100644 --- a/mcs/class/corlib/System/TimeZone.cs +++ b/mcs/class/corlib/System/TimeZone.cs @@ -144,22 +144,7 @@ public virtual DateTime ToLocalTime (DateTime time) return DateTime.SpecifyKind (DateTime.MinValue, DateTimeKind.Local); } - DateTime local = DateTime.SpecifyKind (time.Add (utcOffset), DateTimeKind.Local); - DaylightTime dlt = GetDaylightChanges (time.Year); - if (dlt.Delta.Ticks == 0) - return DateTime.SpecifyKind (local, DateTimeKind.Local); - - // FIXME: check all of the combination of - // - basis: local-based or UTC-based - // - hemisphere: Northern or Southern - // - offset: positive or negative - - // PST should work fine here. - if (local < dlt.End && dlt.End.Subtract (dlt.Delta) <= local) - return DateTime.SpecifyKind (local, DateTimeKind.Local); - - TimeSpan localOffset = GetUtcOffset (local); - return DateTime.SpecifyKind (time.Add (localOffset), DateTimeKind.Local); + return DateTime.SpecifyKind (time.Add (utcOffset), DateTimeKind.Local); } public virtual DateTime ToUniversalTime (DateTime time) From d6848d1ef616c336760c0d668b48ec7a0caf9024 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 2 Oct 2014 18:43:49 +0100 Subject: [PATCH 338/543] ConvertTimeToUtc no longer relies in DateTime.ToUniversalTime. --- mcs/class/System.Core/System/TimeZoneInfo.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index 2b297d48ca0..5d94a1aeed6 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -335,8 +335,7 @@ public static DateTime ConvertTimeToUtc (DateTime dateTime) if (dateTime.Kind == DateTimeKind.Utc) return dateTime; - //FIXME: do not rely on DateTime implementation ! - return DateTime.SpecifyKind (dateTime.ToUniversalTime (), DateTimeKind.Utc); + return ConvertTimeToUtc (dateTime, TimeZoneInfo.Local); } public static DateTime ConvertTimeToUtc (DateTime dateTime, TimeZoneInfo sourceTimeZone) @@ -359,9 +358,6 @@ public static DateTime ConvertTimeToUtc (DateTime dateTime, TimeZoneInfo sourceT if (dateTime.Kind == DateTimeKind.Utc) return dateTime; - if (dateTime.Kind == DateTimeKind.Local) - return ConvertTimeToUtc (dateTime); - if (sourceTimeZone.IsAmbiguousTime (dateTime) || !sourceTimeZone.IsDaylightSavingTime (dateTime)) return DateTime.SpecifyKind (dateTime - sourceTimeZone.BaseUtcOffset, DateTimeKind.Utc); else { From 306ac05ea1453b66019ded46d27b32ca1930cef7 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 2 Oct 2014 18:46:17 +0100 Subject: [PATCH 339/543] Removed repeated logic from TimeZoneInfo.ConvertTimeToUtc. --- mcs/class/System.Core/System/TimeZoneInfo.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index 5d94a1aeed6..21bba67030a 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -352,9 +352,6 @@ public static DateTime ConvertTimeToUtc (DateTime dateTime, TimeZoneInfo sourceT if (sourceTimeZone.IsInvalidTime (dateTime)) throw new ArgumentException ("dateTime parameter is an invalid time"); - if (dateTime.Kind == DateTimeKind.Utc && sourceTimeZone == TimeZoneInfo.Utc) - return dateTime; - if (dateTime.Kind == DateTimeKind.Utc) return dateTime; From 09fc592499976aee92f797e93d381b28a70d94b4 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 3 Oct 2014 10:26:46 +0200 Subject: [PATCH 340/543] Created helper method TimeZoneInfo.IsInDST. --- mcs/class/System.Core/System/TimeZoneInfo.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index 21bba67030a..1fd88fab283 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -748,6 +748,16 @@ public bool IsAmbiguousTime (DateTimeOffset dateTimeOffset) throw new NotImplementedException (); } + private bool IsInDST (AdjustmentRule rule, DateTime dateTime) + { + // Check whether we're in the dateTime year's DST period + if (IsInDSTForYear (rule, dateTime, dateTime.Year)) + return true; + + // We might be in the dateTime previous year's DST period + return IsInDSTForYear (rule, dateTime, dateTime.Year - 1); + } + bool IsInDSTForYear (AdjustmentRule rule, DateTime dateTime, int year) { DateTime DST_start = TransitionPoint (rule.DaylightTransitionStart, year); From 374e1b13e084b4d544abc87543be8f296a047de2 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 2 Oct 2014 18:47:27 +0100 Subject: [PATCH 341/543] TimeZoneInfo.GetUtcOffset now handles all DateTimeKinds. Removed GetUtcOffset cohesion with TimeZoneInfo.IsDaylightSavingTime. --- mcs/class/System.Core/System/TimeZoneInfo.cs | 42 +++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index 1fd88fab283..6bc047d415a 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -680,12 +680,44 @@ public static ReadOnlyCollection GetSystemTimeZones () public TimeSpan GetUtcOffset (DateTime dateTime) { - if (IsDaylightSavingTime (dateTime)) { - AdjustmentRule rule = GetApplicableRule (dateTime); - if (rule != null) - return BaseUtcOffset + rule.DaylightDelta; + TimeZoneInfo tz = this; + if (dateTime.Kind == DateTimeKind.Utc) + tz = TimeZoneInfo.Utc; + + if (dateTime.Kind == DateTimeKind.Local) + tz = TimeZoneInfo.Local; + + var utcDateTimeTicks = dateTime.Ticks - tz.BaseUtcOffset.Ticks; + if (utcDateTimeTicks < 0 || utcDateTimeTicks > DateTime.MaxValue.Ticks) + return BaseUtcOffset; + + var utcDateTime = new DateTime (utcDateTimeTicks, DateTimeKind.Utc); + + var tzRule = tz.GetApplicableRule (utcDateTime); + DateTime dst = DateTime.MinValue; + if (tzRule != null) { + var dstTicks = utcDateTime.Ticks - tzRule.DaylightDelta.Ticks; + if (dstTicks < 0 || dstTicks > DateTime.MaxValue.Ticks) + return BaseUtcOffset; + + dst = new DateTime (dstTicks, DateTimeKind.Utc); } - + + if (dateTime.Kind == DateTimeKind.Unspecified) + { + if (tzRule != null && IsInDST (tzRule, utcDateTime) && IsInDST (tzRule, dst)) + return BaseUtcOffset + tzRule.DaylightDelta; + + return BaseUtcOffset; + } + + if (tzRule != null && tz.IsInDST (tzRule, dst)) + utcDateTime -= tzRule.DaylightDelta; + + var rule = GetApplicableRule (utcDateTime); + if (rule != null && IsInDST (rule, utcDateTime)) + return BaseUtcOffset + rule.DaylightDelta; + return BaseUtcOffset; } From 1a92f4e90b435f2a954325c7310e219c33ff68f1 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 3 Oct 2014 10:28:21 +0200 Subject: [PATCH 342/543] TimeZoneInfo.IsDaylightSavingTime now uses GetUtcOffset. --- mcs/class/System.Core/System/TimeZoneInfo.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index 6bc047d415a..0ea9bc4ac62 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -812,17 +812,8 @@ public bool IsDaylightSavingTime (DateTime dateTime) if (!SupportsDaylightSavingTime) return false; - - AdjustmentRule rule = GetApplicableRule (dateTime.Date); - if (rule == null) - return false; - - // Check whether we're in the dateTime year's DST period - if (IsInDSTForYear (rule, dateTime, dateTime.Year)) - return true; - // We might be in the dateTime previous year's DST period - return IsInDSTForYear (rule, dateTime, dateTime.Year - 1); + return GetUtcOffset (dateTime) != BaseUtcOffset; } public bool IsDaylightSavingTime (DateTimeOffset dateTimeOffset) From 97c6bc06ea7e003884270c36df069ce4dff64403 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Sat, 4 Oct 2014 16:46:47 +0100 Subject: [PATCH 343/543] Refactored TimeZoneInfo.GetUtcOffset. Added GetUtcOffset auxiliar methods with bool out parameter that is true when the given DateTime is a DST. --- mcs/class/System.Core/System/TimeZoneInfo.cs | 92 ++++++++++++++------ 1 file changed, 65 insertions(+), 27 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index 0ea9bc4ac62..845ead62096 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -680,6 +680,19 @@ public static ReadOnlyCollection GetSystemTimeZones () public TimeSpan GetUtcOffset (DateTime dateTime) { + bool isDST; + return GetUtcOffset (dateTime, out isDST); + } + + public TimeSpan GetUtcOffset (DateTimeOffset dateTimeOffset) + { + throw new NotImplementedException (); + } + + private TimeSpan GetUtcOffset (DateTime dateTime, out bool isDST) + { + isDST = false; + TimeZoneInfo tz = this; if (dateTime.Kind == DateTimeKind.Utc) tz = TimeZoneInfo.Utc; @@ -687,43 +700,65 @@ public TimeSpan GetUtcOffset (DateTime dateTime) if (dateTime.Kind == DateTimeKind.Local) tz = TimeZoneInfo.Local; - var utcDateTimeTicks = dateTime.Ticks - tz.BaseUtcOffset.Ticks; - if (utcDateTimeTicks < 0 || utcDateTimeTicks > DateTime.MaxValue.Ticks) + bool isTzDst; + var tzOffset = GetUtcOffset (dateTime, tz, out isTzDst); + + if (tz == this) { + isDST = isTzDst; + return tzOffset; + } + + var utcTicks = dateTime.Ticks - tzOffset.Ticks; + if (utcTicks < 0 || utcTicks > DateTime.MaxValue.Ticks) return BaseUtcOffset; - var utcDateTime = new DateTime (utcDateTimeTicks, DateTimeKind.Utc); + var utcDateTime = new DateTime (utcTicks, DateTimeKind.Utc); - var tzRule = tz.GetApplicableRule (utcDateTime); - DateTime dst = DateTime.MinValue; - if (tzRule != null) { - var dstTicks = utcDateTime.Ticks - tzRule.DaylightDelta.Ticks; - if (dstTicks < 0 || dstTicks > DateTime.MaxValue.Ticks) - return BaseUtcOffset; + return GetUtcOffset (utcDateTime, this, out isDST); + } - dst = new DateTime (dstTicks, DateTimeKind.Utc); - } + private static TimeSpan GetUtcOffset (DateTime dateTime, TimeZoneInfo tz, out bool isDST) + { + if (dateTime.Kind == DateTimeKind.Local && tz != TimeZoneInfo.Local) + throw new Exception (); - if (dateTime.Kind == DateTimeKind.Unspecified) - { - if (tzRule != null && IsInDST (tzRule, utcDateTime) && IsInDST (tzRule, dst)) - return BaseUtcOffset + tzRule.DaylightDelta; + isDST = false; - return BaseUtcOffset; + if (tz == TimeZoneInfo.Utc) + return TimeSpan.Zero; + + if (dateTime.Kind == DateTimeKind.Utc) { + var utcRule = tz.GetApplicableRule (dateTime); + if (utcRule != null && tz.IsInDST (utcRule, dateTime)) { + isDST = true; + return tz.BaseUtcOffset + utcRule.DaylightDelta; + } + + return tz.BaseUtcOffset; } - if (tzRule != null && tz.IsInDST (tzRule, dst)) - utcDateTime -= tzRule.DaylightDelta; + var stdTicks = dateTime.Ticks - tz.BaseUtcOffset.Ticks; + if (stdTicks < 0 || stdTicks > DateTime.MaxValue.Ticks) + return tz.BaseUtcOffset; - var rule = GetApplicableRule (utcDateTime); - if (rule != null && IsInDST (rule, utcDateTime)) - return BaseUtcOffset + rule.DaylightDelta; + var stdUtcDateTime = new DateTime (stdTicks, DateTimeKind.Utc); + var tzRule = tz.GetApplicableRule (stdUtcDateTime); - return BaseUtcOffset; - } + DateTime dstUtcDateTime = DateTime.MinValue; + if (tzRule != null) { + var dstTicks = stdUtcDateTime.Ticks - tzRule.DaylightDelta.Ticks; + if (dstTicks < 0 || dstTicks > DateTime.MaxValue.Ticks) + return tz.BaseUtcOffset; - public TimeSpan GetUtcOffset (DateTimeOffset dateTimeOffset) - { - throw new NotImplementedException (); + dstUtcDateTime = new DateTime (dstTicks, DateTimeKind.Utc); + } + + if (tzRule != null && tz.IsInDST (tzRule, stdUtcDateTime) && tz.IsInDST (tzRule, dstUtcDateTime)) { + isDST = true; + return tz.BaseUtcOffset + tzRule.DaylightDelta; + } + + return tz.BaseUtcOffset; } public bool HasSameRules (TimeZoneInfo other) @@ -813,7 +848,10 @@ public bool IsDaylightSavingTime (DateTime dateTime) if (!SupportsDaylightSavingTime) return false; - return GetUtcOffset (dateTime) != BaseUtcOffset; + bool isDst; + GetUtcOffset (dateTime, out isDst); + + return isDst; } public bool IsDaylightSavingTime (DateTimeOffset dateTimeOffset) From 2a73a83d8919141e16a19ce22ecf9805117b7cba Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Sat, 4 Oct 2014 17:32:03 +0100 Subject: [PATCH 344/543] Use TZ transitions when AdjustementRules are ignored. Fixes 23170. In some cases the timezone transitions provided by iOS are not convertible to AdjustmentRules because of changes on the base offset. Now we store the transitions so they can be used instead of an incomplete list of AdjustmentRules. --- mcs/class/System.Core/System/TimeZoneInfo.cs | 58 +++++++++++++++++++- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index 845ead62096..54178376bdd 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -103,6 +103,11 @@ public static TimeZoneInfo Local { } } + /* + TimeZone transitions are stored when there is a change on the base offset. + */ + private List> transitions; + static TimeZoneInfo CreateLocal () { #if MONODROID @@ -727,6 +732,10 @@ private static TimeSpan GetUtcOffset (DateTime dateTime, TimeZoneInfo tz, out bo if (tz == TimeZoneInfo.Utc) return TimeSpan.Zero; + TimeSpan offset; + if (tz.TryGetTransitionOffset(dateTime, out offset, out isDST)) + return offset; + if (dateTime.Kind == DateTimeKind.Utc) { var utcRule = tz.GetApplicableRule (dateTime); if (utcRule != null && tz.IsInDST (utcRule, dateTime)) { @@ -1028,6 +1037,40 @@ private AdjustmentRule GetApplicableRule (DateTime dateTime) return null; } + private bool TryGetTransitionOffset (DateTime dateTime, out TimeSpan offset,out bool isDst) + { + offset = BaseUtcOffset; + isDst = false; + + if (transitions == null) + return false; + + //Transitions are always in standard time + DateTime date = dateTime; + + if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Local) + date = date.ToUniversalTime () + BaseUtcOffset; + + if (dateTime.Kind == DateTimeKind.Utc && this != TimeZoneInfo.Utc) + date = date + BaseUtcOffset; + + for (var i = transitions.Count - 1; i >= 0; i--) { + var pair = transitions [i]; + DateTime ttime = pair.Key; + TimeType ttype = pair.Value; + + if (ttime > date) + continue; + + offset = new TimeSpan (0, 0, ttype.Offset); + isDst = ttype.IsDst; + + return true; + } + + return false; + } + private static DateTime TransitionPoint (TransitionTime transition, int year) { if (transition.IsFixedDateRule) @@ -1118,6 +1161,7 @@ private static TimeZoneInfo ParseTZBuffer (string id, byte [] buffer, int length bool dst_observed = false; DateTime dst_start = DateTime.MinValue; List adjustmentRules = new List (); + bool storeTransition = false; for (int i = 0; i < transitions.Count; i++) { var pair = transitions [i]; @@ -1128,6 +1172,8 @@ private static TimeZoneInfo ParseTZBuffer (string id, byte [] buffer, int length standardDisplayName = ttype.Name; daylightDisplayName = null; baseUtcOffset = new TimeSpan (0, 0, ttype.Offset); + if (adjustmentRules.Count > 0) // We ignore AdjustmentRules but store transitions. + storeTransition = true; adjustmentRules = new List (); dst_observed = false; } @@ -1169,16 +1215,22 @@ private static TimeZoneInfo ParseTZBuffer (string id, byte [] buffer, int length } } - if (adjustmentRules.Count == 0) { + TimeZoneInfo tz; + if (adjustmentRules.Count == 0 && !storeTransition) { TimeType t = (TimeType)time_types [0]; if (standardDisplayName == null) { standardDisplayName = t.Name; baseUtcOffset = new TimeSpan (0, 0, t.Offset); } - return CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName); + tz = CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName); } else { - return CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName, daylightDisplayName, ValidateRules (adjustmentRules).ToArray ()); + tz = CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName, daylightDisplayName, ValidateRules (adjustmentRules).ToArray ()); } + + if (storeTransition) + tz.transitions = transitions; + + return tz; } static Dictionary ParseAbbreviations (byte [] buffer, int index, int count) From 9e573872f0480ce7cf6468fc70e436d7bac56f61 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 5 Oct 2014 00:04:44 -0400 Subject: [PATCH 345/543] [arm] Increase size of tls_get opcode to 24. --- mono/mini/cpu-arm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/mini/cpu-arm.md b/mono/mini/cpu-arm.md index 6fd40d92c3a..b31b368ec78 100644 --- a/mono/mini/cpu-arm.md +++ b/mono/mini/cpu-arm.md @@ -211,7 +211,7 @@ sbb_imm: dest:i src1:i len:12 br_reg: src1:i len:8 bigmul: len:8 dest:l src1:i src2:i bigmul_un: len:8 dest:l src1:i src2:i -tls_get: len:20 dest:i clob:c +tls_get: len:24 dest:i clob:c # 32 bit opcodes int_add: dest:i src1:i src2:i len:4 From f39cc88e58d01d22ec5e220e04560eedc110b3b3 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Sun, 5 Oct 2014 14:36:05 -0400 Subject: [PATCH 346/543] [corlib] Notify parent task when child task uses NotOnFaulted. Fixes #23594 --- .../corlib/System.Threading.Tasks/Task.cs | 5 +++- .../TaskContinuation.cs | 2 +- .../Test/System.Threading.Tasks/TaskTest.cs | 28 +++++++++++++++---- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/mcs/class/corlib/System.Threading.Tasks/Task.cs b/mcs/class/corlib/System.Threading.Tasks/Task.cs index 1f8165a0d48..4f4abd33e9c 100644 --- a/mcs/class/corlib/System.Threading.Tasks/Task.cs +++ b/mcs/class/corlib/System.Threading.Tasks/Task.cs @@ -635,7 +635,7 @@ void ProcessChildExceptions (bool isParent = false) #region Cancel and Wait related method - internal void CancelReal () + internal void CancelReal (bool notifyParent = false) { Status = TaskStatus.Canceled; @@ -643,6 +643,9 @@ internal void CancelReal () wait_handle.Set (); ProcessCompleteDelegates (); + + if (notifyParent && parent != null && NotifyParentOnFinish ()) + parent = null; } void HandleGenericException (Exception e) diff --git a/mcs/class/corlib/System.Threading.Tasks/TaskContinuation.cs b/mcs/class/corlib/System.Threading.Tasks/TaskContinuation.cs index 2a0547850bd..8ede25eebe4 100644 --- a/mcs/class/corlib/System.Threading.Tasks/TaskContinuation.cs +++ b/mcs/class/corlib/System.Threading.Tasks/TaskContinuation.cs @@ -94,7 +94,7 @@ bool ContinuationStatusCheck (TaskContinuationOptions kind) public void Execute () { if (!ContinuationStatusCheck (continuationOptions)) { - task.CancelReal (); + task.CancelReal (notifyParent : true); task.Dispose (); return; } diff --git a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs index 63eb8a2aff1..1c391f6b08a 100644 --- a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs +++ b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs @@ -616,18 +616,18 @@ public void ContinueWithWithStart () public void ContinueWithChildren () { ParallelTestHelper.Repeat (delegate { - bool result = false; + bool result = false; - var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent)); + var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent)); var mre = new ManualResetEvent (false); - t.ContinueWith (l => { + t.ContinueWith (l => { result = true; mre.Set (); }); Assert.IsTrue (mre.WaitOne (1000), "#1"); - Assert.IsTrue (result, "#2"); + Assert.IsTrue (result, "#2"); }, 2); } @@ -1094,7 +1094,7 @@ public void InlineNotTrashingParentRelationship () var t = new Task (() => { new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously (); Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent); - }); + }); t.RunSynchronously (); Assert.IsTrue (r1); @@ -1932,6 +1932,24 @@ public void LazyCancelationTest () } } + [Test] + public void ChildTaskWithUnscheduledContinuationAttachedToParent () + { + Task inner = null; + var child = Task.Factory.StartNew (() => { + inner = Task.Run (() => { + throw new ApplicationException (); + }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously); + }); + + int counter = 0; + var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously); + Assert.IsTrue (t.Wait (5000), "#1"); + Assert.AreEqual (1, counter, "#2"); + Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3"); + Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4"); + } + [Test] [Category("NotWorking")] public void TaskContinuationChainLeak() From 58105a4dc67f272deb07b1ec1e8885d0743e515a Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Sun, 5 Oct 2014 15:44:55 -0400 Subject: [PATCH 347/543] [system.xml] Add missing 4.0 property --- mcs/class/System.XML/System.Xml/XmlTextReader2.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mcs/class/System.XML/System.Xml/XmlTextReader2.cs b/mcs/class/System.XML/System.Xml/XmlTextReader2.cs index 2110bb62f17..52a7a9e6878 100644 --- a/mcs/class/System.XML/System.Xml/XmlTextReader2.cs +++ b/mcs/class/System.XML/System.Xml/XmlTextReader2.cs @@ -254,6 +254,11 @@ public override ReadState ReadState { get { return entity != null ? ReadState.Interactive : source.ReadState; } } +#if NET_4_0 + [MonoTODO] + public DtdProcessing DtdProcessing { get; set; } +#endif + #if !NET_4_5 public override XmlReaderSettings Settings { get { return base.Settings; } From 153d104c077aab61c5046ddfd1a63f87612978e9 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Sun, 5 Oct 2014 17:58:02 -0400 Subject: [PATCH 348/543] [system.xml] Make XmlSerializer work even when XmlTextReader has explicitly set its resolver --- mcs/class/System.XML/System.Xml/XmlTextReader.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mcs/class/System.XML/System.Xml/XmlTextReader.cs b/mcs/class/System.XML/System.Xml/XmlTextReader.cs index 63745fe3039..7dc686ba352 100644 --- a/mcs/class/System.XML/System.Xml/XmlTextReader.cs +++ b/mcs/class/System.XML/System.Xml/XmlTextReader.cs @@ -164,11 +164,6 @@ internal XmlTextReader (string url, TextReader fragment, XmlNodeType fragType, X InitializeContext (url, context, fragment, fragType); } - Uri ResolveUri (string url) - { - return resolver == null ? null : resolver.ResolveUri (null, url); - } - Stream GetStreamFromUrl (string url, out string absoluteUriString) { #if NET_2_1 @@ -177,9 +172,13 @@ Stream GetStreamFromUrl (string url, out string absoluteUriString) if (url.Length == 0) throw new ArgumentException ("url"); #endif - Uri uri = ResolveUri (url); + // + // This needs to work even if resolver is explicitly set to null + // + var res = resolver ?? new XmlUrlResolver (); + var uri = res.ResolveUri (null, url); absoluteUriString = uri != null ? uri.ToString () : String.Empty; - return resolver == null ? null : resolver.GetEntity (uri, null, typeof (Stream)) as Stream; + return res.GetEntity (uri, null, typeof (Stream)) as Stream; } #endregion From d8ae2993ef317a9b609b3910fb6a3a62a98b43a1 Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Sun, 5 Oct 2014 22:16:27 -0700 Subject: [PATCH 349/543] [runtime] Implement nursery canaries. Use the new MONO_GC_DEBUG option "nursery-canaries" to suffix each nursery object with a canary (guard) word, which is checked on each minor collection. Can be used to detect/debug heap corruption issues. Adding canaries to LOS is also easy if wanted - not sure about major heap. --- man/mono.1 | 5 +++ mono/metadata/sgen-alloc.c | 25 +++++++++----- mono/metadata/sgen-gc.c | 43 +++++++++++++++++++++--- mono/metadata/sgen-gc.h | 45 ++++++++++++++++++++++++++ mono/metadata/sgen-nursery-allocator.c | 5 +-- 5 files changed, 109 insertions(+), 14 deletions(-) diff --git a/man/mono.1 b/man/mono.1 index d058031ed16..784c078d381 100644 --- a/man/mono.1 +++ b/man/mono.1 @@ -1257,6 +1257,11 @@ work, Mono needs to be compiled with the BINARY_PROTOCOL define on sgen-gc.c. You can then use this command to explore the output .nf sgen-grep-binprot 0x1234 0x5678 < file +.TP +\fBnursery-canaries\fR +If set, objects allocated in the nursery are suffixed with a canary (guard) +word, which is checked on each minor collection. Can be used to detect/debug +heap corruption issues. .fi .ne .RE diff --git a/mono/metadata/sgen-alloc.c b/mono/metadata/sgen-alloc.c index 5d343adbe18..3b0c3a3ec33 100644 --- a/mono/metadata/sgen-alloc.c +++ b/mono/metadata/sgen-alloc.c @@ -189,9 +189,12 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size) void **p; char *new_next; TLAB_ACCESS_INIT; + size_t real_size = size; + + CANARIFY_SIZE(size); HEAVY_STAT (++stat_objects_alloced); - if (size <= SGEN_MAX_SMALL_OBJ_SIZE) + if (real_size <= SGEN_MAX_SMALL_OBJ_SIZE) HEAVY_STAT (stat_bytes_alloced += size); else HEAVY_STAT (stat_bytes_alloced_los += size); @@ -207,7 +210,7 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size) if (collect_before_allocs) { if (((current_alloc % collect_before_allocs) == 0) && nursery_section) { sgen_perform_collection (0, GENERATION_NURSERY, "collect-before-alloc-triggered", TRUE); - if (!degraded_mode && sgen_can_alloc_size (size) && size <= SGEN_MAX_SMALL_OBJ_SIZE) { + if (!degraded_mode && sgen_can_alloc_size (size) && real_size <= SGEN_MAX_SMALL_OBJ_SIZE) { // FIXME: g_assert_not_reached (); } @@ -229,8 +232,8 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size) * specially by the world-stopping code. */ - if (size > SGEN_MAX_SMALL_OBJ_SIZE) { - p = sgen_los_alloc_large_inner (vtable, size); + if (real_size > SGEN_MAX_SMALL_OBJ_SIZE) { + p = sgen_los_alloc_large_inner (vtable, ALIGN_UP (real_size)); } else { /* tlab_next and tlab_temp_end are TLS vars so accessing them might be expensive */ @@ -247,6 +250,7 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size) * visible before the vtable store. */ + CANARIFY_ALLOC(p,real_size); SGEN_LOG (6, "Allocated object %p, vtable: %p (%s), size: %zd", p, vtable, vtable->klass->name, size); binary_protocol_alloc (p , vtable, size); if (G_UNLIKELY (MONO_GC_NURSERY_OBJ_ALLOC_ENABLED ())) @@ -290,7 +294,7 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size) do { p = sgen_nursery_alloc (size); if (!p) { - sgen_ensure_free_space (size); + sgen_ensure_free_space (real_size); if (degraded_mode) return alloc_degraded (vtable, size, FALSE); else @@ -347,13 +351,14 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size) TLAB_TEMP_END = MIN (TLAB_REAL_END, TLAB_NEXT + SGEN_SCAN_START_SIZE); SGEN_LOG (5, "Expanding local alloc: %p-%p", TLAB_NEXT, TLAB_TEMP_END); } + CANARIFY_ALLOC(p,real_size); } if (G_LIKELY (p)) { SGEN_LOG (6, "Allocated object %p, vtable: %p (%s), size: %zd", p, vtable, vtable->klass->name, size); binary_protocol_alloc (p, vtable, size); if (G_UNLIKELY (MONO_GC_MAJOR_OBJ_ALLOC_LARGE_ENABLED ()|| MONO_GC_NURSERY_OBJ_ALLOC_ENABLED ())) { - if (size > SGEN_MAX_SMALL_OBJ_SIZE) + if (real_size > SGEN_MAX_SMALL_OBJ_SIZE) MONO_GC_MAJOR_OBJ_ALLOC_LARGE ((mword)p, size, vtable->klass->name_space, vtable->klass->name); else MONO_GC_NURSERY_OBJ_ALLOC ((mword)p, size, vtable->klass->name_space, vtable->klass->name); @@ -370,12 +375,15 @@ mono_gc_try_alloc_obj_nolock (MonoVTable *vtable, size_t size) void **p; char *new_next; TLAB_ACCESS_INIT; + size_t real_size = size; + + CANARIFY_SIZE(size); size = ALIGN_UP (size); - SGEN_ASSERT (9, size >= sizeof (MonoObject), "Object too small"); + SGEN_ASSERT (9, real_size >= sizeof (MonoObject), "Object too small"); g_assert (vtable->gc_descr); - if (size > SGEN_MAX_SMALL_OBJ_SIZE) + if (real_size > SGEN_MAX_SMALL_OBJ_SIZE) return NULL; if (G_UNLIKELY (size > tlab_size)) { @@ -440,6 +448,7 @@ mono_gc_try_alloc_obj_nolock (MonoVTable *vtable, size_t size) HEAVY_STAT (++stat_objects_alloced); HEAVY_STAT (stat_bytes_alloced += size); + CANARIFY_ALLOC(p,real_size); SGEN_LOG (6, "Allocated object %p, vtable: %p (%s), size: %zd", p, vtable, vtable->klass->name, size); binary_protocol_alloc (p, vtable, size); if (G_UNLIKELY (MONO_GC_NURSERY_OBJ_ALLOC_ENABLED ())) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index def25a77cdd..ddbef83fe24 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -290,6 +290,7 @@ static gboolean disable_major_collections = FALSE; gboolean do_pin_stats = FALSE; static gboolean do_verify_nursery = FALSE; static gboolean do_dump_nursery_content = FALSE; +static gboolean enable_nursery_canaries = FALSE; #ifdef HEAVY_STATISTICS long long stat_objects_alloced_degraded = 0; @@ -392,6 +393,12 @@ safe_name (void* obj) return vt->klass->name; } +gboolean +nursery_canaries_enabled (void) +{ + return enable_nursery_canaries; +} + #define safe_object_get_size sgen_safe_object_get_size const char* @@ -631,10 +638,14 @@ sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc obj = start; } - size = ALIGN_UP (safe_object_get_size ((MonoObject*)obj)); - - if ((MonoVTable*)SGEN_LOAD_VTABLE (obj) != array_fill_vtable) + if ((MonoVTable*)SGEN_LOAD_VTABLE (obj) != array_fill_vtable) { + CHECK_CANARY_FOR_OBJECT (obj); + size = ALIGN_UP (safe_object_get_size ((MonoObject*)obj)); callback (obj, size, data); + CANARIFY_SIZE (size); + } else { + size = ALIGN_UP (safe_object_get_size ((MonoObject*)obj)); + } start += size; } @@ -693,8 +704,10 @@ clear_domain_process_object (char *obj, MonoDomain *domain) static void clear_domain_process_minor_object_callback (char *obj, size_t size, MonoDomain *domain) { - if (clear_domain_process_object (obj, domain)) + if (clear_domain_process_object (obj, domain)) { + CANARIFY_SIZE (size); memset (obj, 0, size); + } } static void @@ -986,6 +999,10 @@ pin_objects_from_nursery_pin_queue (ScanCopyContext ctx) } /* Skip to the next object */ + if (((MonoObject*)search_start)->synchronisation != GINT_TO_POINTER (-1)) { + CHECK_CANARY_FOR_OBJECT (search_start); + obj_size = obj_size + CANARY_SIZE; + } search_start = (void*)((char*)search_start + obj_size); } while (search_start <= addr); @@ -1007,6 +1024,8 @@ pin_objects_from_nursery_pin_queue (ScanCopyContext ctx) */ if (((MonoObject*)obj_to_pin)->synchronisation == GINT_TO_POINTER (-1)) goto next_pin_queue_entry; + else + pinning_front = (char*)pinning_front + CANARY_SIZE; /* * Finally - pin the object! @@ -2096,6 +2115,9 @@ verify_nursery (void) if (!do_verify_nursery) return; + + if (nursery_canaries_enabled ()) + SGEN_LOG (1, "Checking nursery canaries..."); /*This cleans up unused fragments */ sgen_nursery_allocator_prepare_for_pinning (); @@ -2124,6 +2146,10 @@ verify_nursery (void) SGEN_LOG (1, "HOLE [%p %p %d]", hole_start, cur, (int)(cur - hole_start)); SGEN_LOG (1, "OBJ [%p %p %d %d %s %d]", cur, cur + size, (int)size, (int)ss, sgen_safe_name ((MonoObject*)cur), (gpointer)LOAD_VTABLE (cur) == sgen_get_array_fill_vtable ()); } + if (nursery_canaries_enabled () && (MonoVTable*)SGEN_LOAD_VTABLE (cur) != array_fill_vtable) { + CHECK_CANARY_FOR_OBJECT (cur); + CANARIFY_SIZE (size); + } cur += size; hole_start = cur; } @@ -4936,6 +4962,10 @@ mono_gc_base_init (void) *colon = '\0'; } binary_protocol_init (filename, (long long)limit); + } else if (!strcmp (opt, "nursery-canaries")) { + do_verify_nursery = TRUE; + sgen_set_use_managed_allocator (FALSE); + enable_nursery_canaries = TRUE; } else if (!sgen_bridge_handle_gc_debug (opt)) { sgen_env_var_error (MONO_GC_DEBUG_NAME, "Ignoring.", "Unknown option `%s`.", opt); @@ -4965,6 +4995,7 @@ mono_gc_base_init (void) fprintf (stderr, " print-pinning\n"); fprintf (stderr, " heap-dump=\n"); fprintf (stderr, " binary-protocol=[:]\n"); + fprintf (stderr, " nursery-canaries\n"); sgen_bridge_print_gc_debug_usage (); fprintf (stderr, "\n"); @@ -5345,4 +5376,8 @@ mono_gc_register_finalizer_callbacks (MonoGCFinalizerCallbacks *callbacks) fin_callbacks = *callbacks; } + + + + #endif /* HAVE_SGEN_GC */ diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 9f21b3e76f0..6eaea3e0a7d 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -811,6 +811,22 @@ sgen_safe_object_get_size (MonoObject *obj) return sgen_par_object_get_size ((MonoVTable*)SGEN_LOAD_VTABLE (obj), obj); } +/* + * This variant guarantees to return the exact size of the object + * before alignment. Needed for canary support. + */ +static inline guint +sgen_safe_object_get_size_unaligned (MonoObject *obj) +{ + char *forwarded; + + if ((forwarded = SGEN_OBJECT_IS_FORWARDED (obj))) { + obj = (MonoObject*)forwarded; + } + + return slow_object_get_size ((MonoVTable*)SGEN_LOAD_VTABLE (obj), obj); +} + const char* sgen_safe_name (void* obj) MONO_INTERNAL; gboolean sgen_object_is_live (void *obj) MONO_INTERNAL; @@ -1144,6 +1160,35 @@ void sgen_env_var_error (const char *env_var, const char *fallback, const char * void sgen_qsort (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*)) MONO_INTERNAL; gint64 sgen_timestamp (void) MONO_INTERNAL; +/* + * Canary (guard word) support + * Notes: + * - CANARY_SIZE must be multiple of word size in bytes + * - Canary space is not included on checks against SGEN_MAX_SMALL_OBJ_SIZE + */ + +gboolean nursery_canaries_enabled (void) MONO_INTERNAL; + +#define CANARY_SIZE 8 +#define CANARY_STRING "koupepia" + +#define CANARIFY_SIZE(size) size = size + CANARY_SIZE + +#define CANARIFY_ALLOC(addr,size) if (nursery_canaries_enabled ()) { \ + memcpy ((char*) (addr) + (size), CANARY_STRING, CANARY_SIZE); \ + } + +#define CANARY_VALID(addr) (strncmp ((char*) (addr), CANARY_STRING, CANARY_SIZE) == 0) + +#define CHECK_CANARY_FOR_OBJECT(addr) if (nursery_canaries_enabled ()) { \ + char* canary_ptr = (char*) (addr) + sgen_safe_object_get_size_unaligned ((MonoObject *) (addr)); \ + if (!CANARY_VALID(canary_ptr)) { \ + char canary_copy[CANARY_SIZE +1]; \ + strncpy (canary_copy, canary_ptr, 8); \ + canary_copy[CANARY_SIZE] = 0; \ + g_error ("CORRUPT CANARY:\naddr->%p\ntype->%s\nexcepted->'%s'\nfound->'%s'\n", (char*) addr, ((MonoObject*)addr)->vtable->klass->name, CANARY_STRING, canary_copy); \ + } } + #endif /* HAVE_SGEN_GC */ #endif /* __MONO_SGENGC_H__ */ diff --git a/mono/metadata/sgen-nursery-allocator.c b/mono/metadata/sgen-nursery-allocator.c index 6fc63e54961..01d1bd1a796 100644 --- a/mono/metadata/sgen-nursery-allocator.c +++ b/mono/metadata/sgen-nursery-allocator.c @@ -785,9 +785,10 @@ sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_ GRAY_OBJECT_ENQUEUE (unpin_queue, addr0, sgen_obj_get_descriptor_safe (addr0)); else SGEN_UNPIN_OBJECT (addr0); + size = SGEN_ALIGN_UP (sgen_safe_object_get_size ((MonoObject*)addr0)); + CANARIFY_SIZE (size); sgen_set_nursery_scan_start (addr0); frag_end = addr0; - size = SGEN_ALIGN_UP (sgen_safe_object_get_size ((MonoObject*)addr0)); ++i; } else { frag_end = addr1; @@ -871,7 +872,7 @@ sgen_can_alloc_size (size_t size) void* sgen_nursery_alloc (size_t size) { - SGEN_ASSERT (1, size >= sizeof (MonoObject) && size <= SGEN_MAX_SMALL_OBJ_SIZE, "Invalid nursery object size"); + SGEN_ASSERT (1, size >= sizeof (MonoObject) && size <= (SGEN_MAX_SMALL_OBJ_SIZE + CANARY_SIZE), "Invalid nursery object size"); SGEN_LOG (4, "Searching nursery for size: %zd", size); size = SGEN_ALIGN_UP (size); From 84110040aac8c8999a9c510e418ec8cec1234a81 Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Sun, 5 Oct 2014 22:21:15 -0700 Subject: [PATCH 350/543] [runtime] Convert String.InternalSetLength to an icall. Needed for canary support. The change does not have a negative impact on StringBuilder performance; under variable-string-length microbenchmarks it seems to perform ~15-20% faster than the managed implementation. --- mcs/class/corlib/System/String.cs | 20 ++------------------ mono/metadata/boehm-gc.c | 12 ++++++++++++ mono/metadata/gc-internal.h | 2 ++ mono/metadata/icall-def.h | 1 + mono/metadata/sgen-gc.c | 19 +++++++++++++++++++ mono/metadata/string-icalls.c | 7 +++++++ mono/metadata/string-icalls.h | 3 +++ 7 files changed, 46 insertions(+), 18 deletions(-) diff --git a/mcs/class/corlib/System/String.cs b/mcs/class/corlib/System/String.cs index 2a408933eac..65e460647ca 100644 --- a/mcs/class/corlib/System/String.cs +++ b/mcs/class/corlib/System/String.cs @@ -2688,24 +2688,8 @@ internal unsafe void InternalSetChar (int idx, char val) } } - internal unsafe void InternalSetLength (int newLength) - { - if (newLength > length) - throw new ArgumentOutOfRangeException ("newLength", "newLength as to be <= length"); - - // zero terminate, we can pass string objects directly via pinvoke - // we also zero the rest of the string, since the new GC needs to be - // able to handle the changing size (it will skip the 0 bytes). - fixed (char * pStr = &start_char) { - char *p = pStr + newLength; - char *end = pStr + length; - while (p < end) { - p [0] = '\0'; - p++; - } - } - length = newLength; - } + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern void InternalSetLength (int newLength); [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)] // When modifying it, GetCaseInsensitiveHashCode() should be modified as well. diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index a3f8296459a..090f2f7a1dc 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -1291,6 +1291,18 @@ mono_gc_get_los_limit (void) return G_MAXINT; } +void +mono_gc_set_string_length (MonoString *str, gint32 new_length) +{ + mono_unichar2 *new_end = str->chars + new_length; + + /* zero the discarded string. This null-delimits the string and allows + * the space to be reclaimed by SGen. */ + + memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2)); + str->length = new_length; +} + gboolean mono_gc_user_markers_supported (void) { diff --git a/mono/metadata/gc-internal.h b/mono/metadata/gc-internal.h index 8e8c35f8360..7b8836363f8 100644 --- a/mono/metadata/gc-internal.h +++ b/mono/metadata/gc-internal.h @@ -329,6 +329,8 @@ void mono_gc_set_skip_thread (gboolean skip) MONO_INTERNAL; */ gboolean mono_gc_is_disabled (void) MONO_INTERNAL; +void mono_gc_set_string_length (MonoString *str, gint32 new_length) MONO_INTERNAL; + #if defined(__MACH__) void mono_gc_register_mach_exception_thread (pthread_t thread) MONO_INTERNAL; pthread_t mono_gc_get_mach_exception_thread (void) MONO_INTERNAL; diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 103eb3c4230..257b8332f5f 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -797,6 +797,7 @@ ICALL(STRING_8a, "GetLOSLimit", ves_icall_System_String_GetLOSLimit) ICALL(STRING_9, "InternalAllocateStr", ves_icall_System_String_InternalAllocateStr) ICALL(STRING_10, "InternalIntern", ves_icall_System_String_InternalIntern) ICALL(STRING_11, "InternalIsInterned", ves_icall_System_String_InternalIsInterned) +ICALL(STRING_12, "InternalSetLength", ves_icall_System_String_InternalSetLength) ICALL_TYPE(TENC, "System.Text.Encoding", TENC_1) ICALL(TENC_1, "InternalCodePage", ves_icall_System_Text_Encoding_InternalCodePage) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index ddbef83fe24..f24fabeac0a 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -4360,6 +4360,25 @@ mono_gc_get_los_limit (void) return MAX_SMALL_OBJ_SIZE; } +void +mono_gc_set_string_length (MonoString *str, gint32 new_length) +{ + mono_unichar2 *new_end = str->chars + new_length; + + /* zero the discarded string. This null-delimits the string and allows + * the space to be reclaimed by SGen. */ + + if (nursery_canaries_enabled () && sgen_ptr_in_nursery (str)) { + CHECK_CANARY_FOR_OBJECT (str); + memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2) + CANARY_SIZE); + memcpy (new_end + 1 , CANARY_STRING, CANARY_SIZE); + } else { + memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2)); + } + + str->length = new_length; +} + gboolean mono_gc_user_markers_supported (void) { diff --git a/mono/metadata/string-icalls.c b/mono/metadata/string-icalls.c index 388d866141f..22b1fbbbdb4 100644 --- a/mono/metadata/string-icalls.c +++ b/mono/metadata/string-icalls.c @@ -67,3 +67,10 @@ ves_icall_System_String_GetLOSLimit (void) return (limit - 2 - offsetof (MonoString, chars)) / 2; } + +void +ves_icall_System_String_InternalSetLength (MonoString *str, gint32 new_length) +{ + mono_gc_set_string_length (str, new_length); +} + diff --git a/mono/metadata/string-icalls.h b/mono/metadata/string-icalls.h index a0b831a1e20..33bcf80378b 100644 --- a/mono/metadata/string-icalls.h +++ b/mono/metadata/string-icalls.h @@ -30,4 +30,7 @@ ves_icall_System_String_InternalIsInterned (MonoString *str) MONO_INTERNAL; int ves_icall_System_String_GetLOSLimit (void) MONO_INTERNAL; +void +ves_icall_System_String_InternalSetLength (MonoString *str, gint32 new_length) MONO_INTERNAL; + #endif /* _MONO_CLI_STRING_ICALLS_H_ */ From d29a341e73dd575892c04c3033ec4e51670345f5 Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Sun, 5 Oct 2014 23:08:48 -0700 Subject: [PATCH 351/543] [runtime] Fix canary oops --- mono/metadata/sgen-gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index f24fabeac0a..d29c6c5b1f3 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -1024,7 +1024,7 @@ pin_objects_from_nursery_pin_queue (ScanCopyContext ctx) */ if (((MonoObject*)obj_to_pin)->synchronisation == GINT_TO_POINTER (-1)) goto next_pin_queue_entry; - else + else if (nursery_canaries_enabled ()) pinning_front = (char*)pinning_front + CANARY_SIZE; /* From 27d26c36cc3f4f8c9558de81854a5020ec94bd62 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 6 Oct 2014 15:32:45 +0100 Subject: [PATCH 352/543] Added bash script to test DateTime.Now. The test changes TZ environment variable and compares DateTime.Now with system date. The test checks all the timezones installed in /usr/share/zoneinfo/. --- mcs/class/corlib/DateTime.Now_Test.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100755 mcs/class/corlib/DateTime.Now_Test.sh diff --git a/mcs/class/corlib/DateTime.Now_Test.sh b/mcs/class/corlib/DateTime.Now_Test.sh new file mode 100755 index 00000000000..27b9c2014d2 --- /dev/null +++ b/mcs/class/corlib/DateTime.Now_Test.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +export MONO_PATH=${MONO_PATH:-$SCRIPT_PATH/../lib/net_4_5/} + +TZ_FAILS=0 +TZ_COUNT=0 +FORMAT="%a %b %d %T %Y" + +for tz in $(cd /usr/share/zoneinfo/; find * -type f -print); do + TZ_COUNT=$(expr $TZ_COUNT + 1) + SYS_DATETIME=$(date -ju -f "$FORMAT" "$(TZ=$tz date "+$FORMAT")" "+%s") + CS_DATETIME=$(TZ=$tz csharp -e '(int)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;') + DIFF=$(expr $SYS_DATETIME - $CS_DATETIME) + if [ "$DIFF" -gt "5" ] || [ "$DIFF" -lt "-5" ]; then + TZ_FAILS=$(expr $TZ_FAILS + 1) + echo "" + echo "DateTime.Now failed with timezone: $tz" + echo " System: $(date -ju -f "%s" "$SYS_DATETIME" "+%Y-%m-%d %T")" + echo " DateTime.Now: $(date -ju -f "%s" "$CS_DATETIME" "+%Y-%m-%d %T")" + fi + echo ".\c" +done +echo "" +echo "DateTime.Now failed with $TZ_FAILS of $TZ_COUNT timezones." From b97e3209b3e0d641b25b10c222e5c1d1ed024c72 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 6 Oct 2014 10:54:09 -0400 Subject: [PATCH 353/543] [runtime] Silence a warning that has not helped us fix anything. --- mono/utils/mono-threads.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index d5b2239e93e..9aa70ac20b0 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -144,7 +144,7 @@ register_thread (MonoThreadInfo *info, gpointer baseptr) if (threads_callbacks.thread_register) { if (threads_callbacks.thread_register (info, baseptr) == NULL) { - g_warning ("thread registation failed\n"); + // g_warning ("thread registation failed\n"); g_free (info); return NULL; } @@ -605,7 +605,7 @@ mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_ke for (;;) { const char *suspend_error = "Unknown error"; if (!(info = mono_thread_info_suspend_sync (id, interrupt_kernel, &suspend_error))) { - g_warning ("failed to suspend thread %p due to %s, hopefully it is dead", (gpointer)id, suspend_error); + // g_warning ("failed to suspend thread %p due to %s, hopefully it is dead", (gpointer)id, suspend_error); mono_thread_info_suspend_unlock (); return NULL; } @@ -614,7 +614,7 @@ mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_ke break; if (!mono_thread_info_core_resume (info)) { - g_warning ("failed to resume thread %p, hopefully it is dead", (gpointer)id); + // g_warning ("failed to resume thread %p, hopefully it is dead", (gpointer)id); mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1); mono_thread_info_suspend_unlock (); return NULL; From 457c87c69ff6968556cb958e546cea108eab6355 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 6 Oct 2014 15:57:13 +0100 Subject: [PATCH 354/543] TimeZoneInfo.CreateLocal now handles environment variable TZ. --- mcs/class/System.Core/System/TimeZoneInfo.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index 54178376bdd..15ee8615aea 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -117,6 +117,17 @@ static TimeZoneInfo CreateLocal () return BuildFromStream ("Local", stream); } #elif LIBC + var tz = Environment.GetEnvironmentVariable ("TZ"); + if (tz != null) { + if (tz == String.Empty) + return Utc; + try { + return FindSystemTimeZoneByFileName (tz, Path.Combine (TimeZoneDirectory, tz)); + } catch { + return Utc; + } + } + try { return FindSystemTimeZoneByFileName ("Local", "/etc/localtime"); } catch { From 5a22dacd4ec0b61f58bb9358596ebcf87a65446d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 6 Oct 2014 14:56:21 -0400 Subject: [PATCH 355/543] [bcl] Remove some verbose test output. --- mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs index 1c391f6b08a..4e358cadd94 100644 --- a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs +++ b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs @@ -905,7 +905,7 @@ public void UnobservedExceptionOnFinalizerThreadTest () }; var inner = new ApplicationException (); Thread t = new Thread (delegate () { - Task.Factory.StartNew (() => { Console.WriteLine ("HIT!"); throw inner; }); + Task.Factory.StartNew (() => { throw inner; }); }); t.Start (); t.Join (); From 7ecf25c7a19bca07f87d2c243ec26e35a46b0464 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Mon, 6 Oct 2014 12:11:57 -0700 Subject: [PATCH 356/543] [sgen] Fix pointer access. Thanks to @martinpotter for finding the bug. --- mono/metadata/sgen-pointer-queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/sgen-pointer-queue.c b/mono/metadata/sgen-pointer-queue.c index fe491605d52..c645bdd8798 100644 --- a/mono/metadata/sgen-pointer-queue.c +++ b/mono/metadata/sgen-pointer-queue.c @@ -77,7 +77,7 @@ sgen_pointer_queue_sort_uniq (SgenPointerQueue *queue) end = queue->data + queue->next_slot; while (cur < end) { *start = *cur++; - while (*start == *cur && cur < end) + while (cur < end && *start == *cur) cur++; start++; }; From f533903590e91c38b6c3f49968634d58fe1c2849 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 6 Oct 2014 16:13:54 -0400 Subject: [PATCH 357/543] Kill timed-out tests when using the managed test runner. --- mono/tests/test-runner.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/mono/tests/test-runner.cs b/mono/tests/test-runner.cs index ce0d65e7418..24caf07cc13 100644 --- a/mono/tests/test-runner.cs +++ b/mono/tests/test-runner.cs @@ -301,6 +301,7 @@ public static int Main (String[] args) { lock (monitor) { foreach (Process p in processes) { Console.WriteLine (process_data [p].test); + p.Kill (); } } return 1; From 14d49cce103796228e6869130846f17157872e08 Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Mon, 6 Oct 2014 17:02:23 -0700 Subject: [PATCH 358/543] [runtime] Fix another lost canary change --- mono/metadata/sgen-gc.c | 5 ++--- mono/metadata/sgen-gc.h | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index d29c6c5b1f3..f1f55e73da8 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -1001,7 +1001,8 @@ pin_objects_from_nursery_pin_queue (ScanCopyContext ctx) /* Skip to the next object */ if (((MonoObject*)search_start)->synchronisation != GINT_TO_POINTER (-1)) { CHECK_CANARY_FOR_OBJECT (search_start); - obj_size = obj_size + CANARY_SIZE; + CANARIFY_SIZE (obj_size); + CANARIFY_SIZE (obj_to_pin_size); } search_start = (void*)((char*)search_start + obj_size); } while (search_start <= addr); @@ -1024,8 +1025,6 @@ pin_objects_from_nursery_pin_queue (ScanCopyContext ctx) */ if (((MonoObject*)obj_to_pin)->synchronisation == GINT_TO_POINTER (-1)) goto next_pin_queue_entry; - else if (nursery_canaries_enabled ()) - pinning_front = (char*)pinning_front + CANARY_SIZE; /* * Finally - pin the object! diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 6eaea3e0a7d..12121dc723f 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -1172,7 +1172,9 @@ gboolean nursery_canaries_enabled (void) MONO_INTERNAL; #define CANARY_SIZE 8 #define CANARY_STRING "koupepia" -#define CANARIFY_SIZE(size) size = size + CANARY_SIZE +#define CANARIFY_SIZE(size) if (nursery_canaries_enabled ()) { \ + size = size + CANARY_SIZE; \ + } #define CANARIFY_ALLOC(addr,size) if (nursery_canaries_enabled ()) { \ memcpy ((char*) (addr) + (size), CANARY_STRING, CANARY_SIZE); \ From aea4abc755d4406558f8544516378d98e92b1a37 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 09:56:48 +0100 Subject: [PATCH 359/543] Call SetupRequestAsync only after ContentType changes. Fixes 19529. --- mcs/class/System/System.Net/WebClient.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/mcs/class/System/System.Net/WebClient.cs b/mcs/class/System/System.Net/WebClient.cs index ded7767114a..3248b9d62f5 100644 --- a/mcs/class/System/System.Net/WebClient.cs +++ b/mcs/class/System/System.Net/WebClient.cs @@ -1972,20 +1972,17 @@ public async Task UploadFileTaskAsync (Uri address, string method, strin if (fileName == null) throw new ArgumentNullException ("fileName"); - WebRequest request = null; try { SetBusy (); cts = new CancellationTokenSource (); - request = await SetupRequestAsync (address, method, true).ConfigureAwait (false); - var result = await UploadFileTaskAsyncCore (request, method, fileName, cts.Token).ConfigureAwait (false); + + var result = await UploadFileTaskAsyncCore (address, method, fileName, cts.Token).ConfigureAwait (false); OnUploadFileCompleted (new UploadFileCompletedEventArgs (result, null, false, null)); return result; } catch (WebException ex) { OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, ex, false, null)); throw; } catch (OperationCanceledException) { - if (request != null) - request.Abort (); OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, null, true, null)); throw; } catch (Exception ex) { @@ -1994,8 +1991,7 @@ public async Task UploadFileTaskAsync (Uri address, string method, strin } } - async Task UploadFileTaskAsyncCore (WebRequest request, string method, - string fileName, CancellationToken token) + async Task UploadFileTaskAsyncCore (Uri address, string method, string fileName, CancellationToken token) { token.ThrowIfCancellationRequested (); @@ -2018,9 +2014,15 @@ async Task UploadFileTaskAsyncCore (WebRequest request, string method, Stream reqStream = null; Stream fStream = null; WebResponse response = null; + WebRequest request = null; fileName = Path.GetFullPath (fileName); + try { + request = await SetupRequestAsync (address, method, true).ConfigureAwait (false); + } catch (OperationCanceledException) { + } + try { fStream = File.OpenRead (fileName); token.ThrowIfCancellationRequested (); From a1e558f6c6a24c2cdc21a2a6104dd719e28ecce8 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 23 Sep 2014 09:59:07 +0100 Subject: [PATCH 360/543] Reset stream position before doing CopyToAsync. CopyToAsync begins copying at the current position. --- mcs/class/System/System.Net/WebClient.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mcs/class/System/System.Net/WebClient.cs b/mcs/class/System/System.Net/WebClient.cs index 3248b9d62f5..38415f05c5f 100644 --- a/mcs/class/System/System.Net/WebClient.cs +++ b/mcs/class/System/System.Net/WebClient.cs @@ -2044,7 +2044,9 @@ async Task UploadFileTaskAsyncCore (Uri address, string method, string f Path.GetFileName (fileName), fileCType); byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders); ms.Write (partHeadersBytes, 0, partHeadersBytes.Length); - await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false); + var msLength = (int)ms.Position; + ms.Seek (0, SeekOrigin.Begin); + await ms.CopyToAsync (reqStream, msLength, token).ConfigureAwait (false); } } int nread; @@ -2086,7 +2088,9 @@ async Task UploadFileTaskAsyncCore (Uri address, string method, string f ms.WriteByte ((byte) '-'); ms.WriteByte ((byte) '\r'); ms.WriteByte ((byte) '\n'); - await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false); + var msLength = (int)ms.Position; + ms.Seek (0, SeekOrigin.Begin); + await ms.CopyToAsync (reqStream, msLength, token).ConfigureAwait (false); } } reqStream.Close (); From fa2c2870e56fa25ee1142ebdba9910a07504eda8 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 7 Oct 2014 14:03:29 +0100 Subject: [PATCH 361/543] Added missing files to projects csproj files. --- .../Microsoft.Build.Engine/Microsoft.Build.Engine-net_4_5.csproj | 1 + mcs/class/System.Data/System.Data-net_4_5.csproj | 1 + mcs/class/corlib/corlib-net_4_5.csproj | 1 + 3 files changed, 3 insertions(+) diff --git a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.Engine-net_4_5.csproj b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.Engine-net_4_5.csproj index df6603cfa85..2c42dc4da76 100644 --- a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.Engine-net_4_5.csproj +++ b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.Engine-net_4_5.csproj @@ -112,6 +112,7 @@ + diff --git a/mcs/class/System.Data/System.Data-net_4_5.csproj b/mcs/class/System.Data/System.Data-net_4_5.csproj index 95dead37499..eb65112a417 100644 --- a/mcs/class/System.Data/System.Data-net_4_5.csproj +++ b/mcs/class/System.Data/System.Data-net_4_5.csproj @@ -206,6 +206,7 @@ + diff --git a/mcs/class/corlib/corlib-net_4_5.csproj b/mcs/class/corlib/corlib-net_4_5.csproj index d80870fca6f..bf5bf190955 100644 --- a/mcs/class/corlib/corlib-net_4_5.csproj +++ b/mcs/class/corlib/corlib-net_4_5.csproj @@ -1587,6 +1587,7 @@ + From 4cda578c6ad946e3450448c039e79b32609b2b8f Mon Sep 17 00:00:00 2001 From: Vladimir Kargov Date: Tue, 7 Oct 2014 19:30:31 +0400 Subject: [PATCH 362/543] [runtime] Take correct domain information from StackFrameInfo for each stack frame. --- mono/mini/mini-exceptions.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 5993ddddb63..db4a1ce4b0c 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -2227,8 +2227,8 @@ print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer d if (frame->ji) method = jinfo_get_method (frame->ji); - if (method) { - gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ()); + if (method && frame->domain) { + gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain); g_string_append_printf (p, " %s\n", location); g_free (location); } else From aab88e769c048bb091c6f1ad564d260d1205fd03 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 7 Oct 2014 17:34:44 +0200 Subject: [PATCH 363/543] [MWF] Pass graphics when calculating button text and image This fixes a problem with calculating the text width of a button which caused the text to get truncated under certain circumstances instead of being wrapped. This fixes Xamarin-23168. Change-Id: Iac0d8a2720a99cf5433e05d5123a04c4b019e493 --- .../System.Windows.Forms/Button.cs | 2 +- .../System.Windows.Forms/Theme.cs | 2 +- .../System.Windows.Forms/ThemeWin32Classic.cs | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Button.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Button.cs index dc640e836cd..e04f3997168 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Button.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Button.cs @@ -175,7 +175,7 @@ internal override void Draw (PaintEventArgs pevent) Rectangle text_rectangle; Rectangle image_rectangle; - ThemeEngine.Current.CalculateButtonTextAndImageLayout (this, out text_rectangle, out image_rectangle); + ThemeEngine.Current.CalculateButtonTextAndImageLayout (pevent.Graphics, this, out text_rectangle, out image_rectangle); // Draw our button if (this.FlatStyle == FlatStyle.Standard) diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Theme.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Theme.cs index 18ee3dd8117..b8cc63b7e81 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Theme.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Theme.cs @@ -698,7 +698,7 @@ public virtual Image Images(string mimetype, string extension, int size) { #region Button public abstract Size CalculateButtonAutoSize (Button button); - public abstract void CalculateButtonTextAndImageLayout (ButtonBase b, out Rectangle textRectangle, out Rectangle imageRectangle); + public abstract void CalculateButtonTextAndImageLayout (Graphics g, ButtonBase b, out Rectangle textRectangle, out Rectangle imageRectangle); public abstract void DrawButton (Graphics g, Button b, Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle); public abstract void DrawFlatButton (Graphics g, ButtonBase b, Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle); public abstract void DrawPopupButton (Graphics g, Button b, Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle); diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs index 522dec40ec6..a9ed1ebec31 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs @@ -364,12 +364,14 @@ public override Size CalculateButtonAutoSize (Button button) return ret_size; } - public override void CalculateButtonTextAndImageLayout (ButtonBase button, out Rectangle textRectangle, out Rectangle imageRectangle) + public override void CalculateButtonTextAndImageLayout (Graphics g, ButtonBase button, out Rectangle textRectangle, out Rectangle imageRectangle) { Image image = button.Image; string text = button.Text; Rectangle content_rect = button.PaddingClientRectangle; - Size text_size = TextRenderer.MeasureTextInternal (text, button.Font, content_rect.Size, button.TextFormatFlags, button.UseCompatibleTextRendering); + if (button.TextImageRelation != TextImageRelation.Overlay) + content_rect.Inflate(-4, -4); + Size text_size = TextRenderer.MeasureTextInternal (g, text, button.Font, content_rect.Size, button.TextFormatFlags, button.UseCompatibleTextRendering); Size image_size = image == null ? Size.Empty : image.Size; textRectangle = Rectangle.Empty; @@ -438,19 +440,15 @@ public override void CalculateButtonTextAndImageLayout (ButtonBase button, out R imageRectangle = new Rectangle (image_x, image_y, image_width, image_height); break; case TextImageRelation.ImageAboveText: - content_rect.Inflate (-4, -4); LayoutTextAboveOrBelowImage (content_rect, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); break; case TextImageRelation.TextAboveImage: - content_rect.Inflate (-4, -4); LayoutTextAboveOrBelowImage (content_rect, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); break; case TextImageRelation.ImageBeforeText: - content_rect.Inflate (-4, -4); LayoutTextBeforeOrAfterImage (content_rect, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); break; case TextImageRelation.TextBeforeImage: - content_rect.Inflate (-4, -4); LayoutTextBeforeOrAfterImage (content_rect, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); break; } From 7cfd463841a4875af614ce104e030ac91aa4f185 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 7 Oct 2014 13:03:28 -0400 Subject: [PATCH 364/543] [runtime] Factor out some duplicate code from the MonoJitInfo creation code. --- mono/metadata/domain-internals.h | 15 +++++++ mono/metadata/domain.c | 35 ++++++++++++++++ mono/mini/aot-runtime.c | 69 ++++++++++++++------------------ mono/mini/mini.c | 50 +++++++---------------- 4 files changed, 94 insertions(+), 75 deletions(-) diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index 24989f49afd..68257c7ef13 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -188,6 +188,14 @@ typedef struct { gboolean cas_method_permitonly:1; } MonoMethodCasInfo; +typedef enum { + JIT_INFO_NONE = 0, + JIT_INFO_HAS_CAS_INFO = (1 << 0), + JIT_INFO_HAS_GENERIC_JIT_INFO = (1 << 1), + JIT_INFO_HAS_TRY_BLOCK_HOLES = (1 << 2), + JIT_INFO_HAS_ARCH_EH_INFO = (1 << 3) +} MonoJitInfoFlags; + struct _MonoJitInfo { /* NOTE: These first two elements (method and next_jit_code_hash) must be in the same order and at the @@ -456,6 +464,13 @@ mono_cleanup (void) MONO_INTERNAL; void mono_close_exe_image (void) MONO_INTERNAL; +int +mono_jit_info_size (MonoJitInfoFlags flags, int num_clauses, int num_holes) MONO_INTERNAL; + +void +mono_jit_info_init (MonoJitInfo *ji, MonoMethod *method, guint8 *code, int code_size, + MonoJitInfoFlags flags, int num_clauses, int num_holes) MONO_INTERNAL; + void mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji) MONO_INTERNAL; diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index 013e73b6910..c624b6a78d5 100755 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -890,6 +890,41 @@ mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func) jit_info_find_in_aot_func = func; } +int +mono_jit_info_size (MonoJitInfoFlags flags, int num_clauses, int num_holes) +{ + int size = MONO_SIZEOF_JIT_INFO; + + size += num_clauses * sizeof (MonoJitExceptionInfo); + if (flags & JIT_INFO_HAS_CAS_INFO) + size += sizeof (MonoMethodCasInfo); + if (flags & JIT_INFO_HAS_GENERIC_JIT_INFO) + size += sizeof (MonoGenericJitInfo); + if (flags & JIT_INFO_HAS_TRY_BLOCK_HOLES) + size += sizeof (MonoTryBlockHoleTableJitInfo) + num_holes * sizeof (MonoTryBlockHoleJitInfo); + if (flags & JIT_INFO_HAS_ARCH_EH_INFO) + size += sizeof (MonoArchEHJitInfo); + return size; +} + +void +mono_jit_info_init (MonoJitInfo *ji, MonoMethod *method, guint8 *code, int code_size, + MonoJitInfoFlags flags, int num_clauses, int num_holes) +{ + ji->d.method = method; + ji->code_start = code; + ji->code_size = code_size; + ji->num_clauses = num_clauses; + if (flags & JIT_INFO_HAS_CAS_INFO) + ji->has_cas_info = 1; + if (flags & JIT_INFO_HAS_GENERIC_JIT_INFO) + ji->has_generic_jit_info = 1; + if (flags & JIT_INFO_HAS_TRY_BLOCK_HOLES) + ji->has_try_block_holes = 1; + if (flags & JIT_INFO_HAS_ARCH_EH_INFO) + ji->has_arch_eh_info = 1; +} + gpointer mono_jit_info_get_code_start (MonoJitInfo* ji) { diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index ca2f6552f71..e9b5f42668a 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -2344,7 +2344,8 @@ static MonoJitInfo* decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, MonoMethod *method, guint8 *code, MonoJitExceptionInfo *clauses, int num_clauses, - int extra_size, GSList **nesting, + MonoJitInfoFlags flags, + GSList **nesting, int *this_reg, int *this_offset) { guint8 *p; @@ -2455,20 +2456,17 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, * allocate a new JI. */ jinfo = - mono_domain_alloc0_lock_free (domain, MONO_SIZEOF_JIT_INFO + (sizeof (MonoJitExceptionInfo) * (ei_len + nested_len)) + extra_size); + mono_domain_alloc0_lock_free (domain, mono_jit_info_size (flags, ei_len + nested_len, 0)); + mono_jit_info_init (jinfo, method, code, code_len, flags, ei_len + nested_len, 0); - jinfo->code_size = code_len; jinfo->unwind_info = mono_cache_unwind_info (info.unw_info, info.unw_info_len); - jinfo->d.method = method; - jinfo->code_start = code; - jinfo->domain_neutral = 0; /* This signals that unwind_info points to a normal cached unwind info */ jinfo->from_aot = 0; - jinfo->num_clauses = ei_len + nested_len; + jinfo->from_llvm = 1; for (i = 0; i < ei_len; ++i) { /* - * orig_jinfo contains the original IL exception info saved by the AOT + * clauses contains the original IL exception info saved by the AOT * compiler, we have to combine that with the information produced by LLVM */ /* The type_info entries contain IL clause indexes */ @@ -2544,7 +2542,8 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, { int i, buf_len, num_clauses, len; MonoJitInfo *jinfo; - guint unwind_info, flags; + MonoJitInfoFlags flags = JIT_INFO_NONE; + guint unwind_info, eflags; gboolean has_generic_jit_info, has_dwarf_unwind_info, has_clauses, has_seq_points, has_try_block_holes, has_arch_eh_jit_info; gboolean from_llvm, has_gc_map; guint8 *p; @@ -2556,15 +2555,15 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, async = mono_thread_info_is_async_context (); p = ex_info; - flags = decode_value (p, &p); - has_generic_jit_info = (flags & 1) != 0; - has_dwarf_unwind_info = (flags & 2) != 0; - has_clauses = (flags & 4) != 0; - has_seq_points = (flags & 8) != 0; - from_llvm = (flags & 16) != 0; - has_try_block_holes = (flags & 32) != 0; - has_gc_map = (flags & 64) != 0; - has_arch_eh_jit_info = (flags & 128) != 0; + eflags = decode_value (p, &p); + has_generic_jit_info = (eflags & 1) != 0; + has_dwarf_unwind_info = (eflags & 2) != 0; + has_clauses = (eflags & 4) != 0; + has_seq_points = (eflags & 8) != 0; + from_llvm = (eflags & 16) != 0; + has_try_block_holes = (eflags & 32) != 0; + has_gc_map = (eflags & 64) != 0; + has_arch_eh_jit_info = (eflags & 128) != 0; if (has_dwarf_unwind_info) { unwind_info = decode_value (p, &p); @@ -2572,13 +2571,16 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, } else { unwind_info = decode_value (p, &p); } - if (has_generic_jit_info) + if (has_generic_jit_info) { + flags |= JIT_INFO_HAS_GENERIC_JIT_INFO; generic_info_size = sizeof (MonoGenericJitInfo); - else + } else { generic_info_size = 0; + } if (has_try_block_holes) { num_holes = decode_value (p, &p); + flags |= JIT_INFO_HAS_TRY_BLOCK_HOLES; try_holes_info_size = sizeof (MonoTryBlockHoleTableJitInfo) + num_holes * sizeof (MonoTryBlockHoleJitInfo); } else { num_holes = try_holes_info_size = 0; @@ -2588,10 +2590,12 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, num_clauses = decode_value (p, &p); else num_clauses = 0; - if (has_arch_eh_jit_info) + if (has_arch_eh_jit_info) { + flags |= JIT_INFO_HAS_ARCH_EH_INFO; arch_eh_jit_info_size = sizeof (MonoArchEHJitInfo); - else + } else { arch_eh_jit_info_size = 0; + } if (from_llvm) { MonoJitExceptionInfo *clauses; @@ -2624,17 +2628,16 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, } } - jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, clauses, num_clauses, generic_info_size + try_holes_info_size + arch_eh_jit_info_size, nesting, &this_reg, &this_offset); - jinfo->from_llvm = 1; + jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, clauses, num_clauses, flags, nesting, &this_reg, &this_offset); g_free (clauses); for (i = 0; i < num_clauses; ++i) g_slist_free (nesting [i]); g_free (nesting); } else { - len = MONO_SIZEOF_JIT_INFO + (sizeof (MonoJitExceptionInfo) * num_clauses) + generic_info_size + try_holes_info_size + arch_eh_jit_info_size; + len = mono_jit_info_size (flags, num_clauses, num_holes); jinfo = alloc0_jit_info_data (domain, len, async); - jinfo->num_clauses = num_clauses; + mono_jit_info_init (jinfo, method, code, code_len, flags, num_clauses, num_holes); for (i = 0; i < jinfo->num_clauses; ++i) { MonoJitExceptionInfo *ei = &jinfo->clauses [i]; @@ -2661,25 +2664,11 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, ei->handler_start = code + decode_value (p, &p); } - jinfo->code_size = code_len; jinfo->unwind_info = unwind_info; - jinfo->d.method = method; - jinfo->code_start = code; jinfo->domain_neutral = 0; jinfo->from_aot = 1; } - /* - * Set all the 'has' flags, the mono_jit_info_get () functions depends on this to - * compute the addresses of data blocks. - */ - if (has_generic_jit_info) - jinfo->has_generic_jit_info = 1; - if (has_arch_eh_jit_info) - jinfo->has_arch_eh_info = 1; - if (has_try_block_holes) - jinfo->has_try_block_holes = 1; - if (has_try_block_holes) { MonoTryBlockHoleTableJitInfo *table; diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 859c91c72f9..b5e13dc592b 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -4329,18 +4329,15 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) GSList *tmp; MonoMethodHeader *header; MonoJitInfo *jinfo; - int num_clauses; - int generic_info_size, arch_eh_info_size = 0; - int holes_size = 0, num_holes = 0, cas_size = 0; + MonoJitInfoFlags flags = JIT_INFO_NONE; + int num_clauses, num_holes = 0; guint32 stack_size = 0; g_assert (method_to_compile == cfg->method); header = cfg->header; if (cfg->generic_sharing_context) - generic_info_size = sizeof (MonoGenericJitInfo); - else - generic_info_size = 0; + flags |= JIT_INFO_HAS_GENERIC_JIT_INFO; if (cfg->arch_eh_jit_info) { MonoJitArgumentInfo *arg_info; @@ -4354,11 +4351,11 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) stack_size = mono_arch_get_argument_info (cfg->generic_sharing_context, sig, sig->param_count, arg_info); if (stack_size) - arch_eh_info_size = sizeof (MonoArchEHJitInfo); + flags |= JIT_INFO_HAS_ARCH_EH_INFO; } - if (cfg->has_unwind_info_for_epilog && !arch_eh_info_size) - arch_eh_info_size = sizeof (MonoArchEHJitInfo); + if (cfg->has_unwind_info_for_epilog && !(flags & JIT_INFO_HAS_ARCH_EH_INFO)) + flags |= JIT_INFO_HAS_ARCH_EH_INFO; if (cfg->try_block_holes) { for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) { @@ -4373,34 +4370,25 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) ++num_holes; } if (num_holes) - holes_size = sizeof (MonoTryBlockHoleTableJitInfo) + num_holes * sizeof (MonoTryBlockHoleJitInfo); + flags |= JIT_INFO_HAS_TRY_BLOCK_HOLES; if (G_UNLIKELY (cfg->verbose_level >= 4)) printf ("Number of try block holes %d\n", num_holes); } - if (mono_security_method_has_declsec (cfg->method_to_register)) { - cas_size = sizeof (MonoMethodCasInfo); - } + if (mono_security_method_has_declsec (cfg->method_to_register)) + flags |= JIT_INFO_HAS_ARCH_EH_INFO; if (COMPILE_LLVM (cfg)) num_clauses = cfg->llvm_ex_info_len; else num_clauses = header->num_clauses; - if (cfg->method->dynamic) { - jinfo = g_malloc0 (MONO_SIZEOF_JIT_INFO + (num_clauses * sizeof (MonoJitExceptionInfo)) + - generic_info_size + holes_size + arch_eh_info_size + cas_size); - } else { - jinfo = mono_domain_alloc0 (cfg->domain, MONO_SIZEOF_JIT_INFO + - (num_clauses * sizeof (MonoJitExceptionInfo)) + - generic_info_size + holes_size + arch_eh_info_size + cas_size); - } - - jinfo->d.method = cfg->method_to_register; - jinfo->code_start = cfg->native_code; - jinfo->code_size = cfg->code_len; + if (cfg->method->dynamic) + jinfo = g_malloc0 (mono_jit_info_size (flags, num_clauses, num_holes)); + else + jinfo = mono_domain_alloc0 (cfg->domain, mono_jit_info_size (flags, num_clauses, num_holes)); + mono_jit_info_init (jinfo, cfg->method_to_register, cfg->native_code, cfg->code_len, flags, num_clauses, num_holes); jinfo->domain_neutral = (cfg->opt & MONO_OPT_SHARED) != 0; - jinfo->num_clauses = num_clauses; if (COMPILE_LLVM (cfg)) jinfo->from_llvm = TRUE; @@ -4410,8 +4398,6 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) MonoGenericJitInfo *gi; GSList *loclist = NULL; - jinfo->has_generic_jit_info = 1; - gi = mono_jit_info_get_generic_jit_info (jinfo); g_assert (gi); @@ -4485,7 +4471,6 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) MonoTryBlockHoleTableJitInfo *table; int i; - jinfo->has_try_block_holes = 1; table = mono_jit_info_get_try_block_hole_table_info (jinfo); table->num_holes = (guint16)num_holes; i = 0; @@ -4514,19 +4499,14 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) g_assert (i == num_holes); } - if (arch_eh_info_size) { + if (jinfo->has_arch_eh_info) { MonoArchEHJitInfo *info; - jinfo->has_arch_eh_info = 1; info = mono_jit_info_get_arch_eh_info (jinfo); info->stack_size = stack_size; } - if (cas_size) { - jinfo->has_cas_info = 1; - } - if (COMPILE_LLVM (cfg)) { if (num_clauses) memcpy (&jinfo->clauses [0], &cfg->llvm_ex_info [0], num_clauses * sizeof (MonoJitExceptionInfo)); From 10c2cc4d3f5ddc32a3999a42c92bbf78a12aa86d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 7 Oct 2014 13:26:12 -0400 Subject: [PATCH 365/543] [runtime] Move the MonoJit/MonoJitInfoTable code to a separate file from domain.c. --- mono/metadata/Makefile.am | 1 + mono/metadata/domain-internals.h | 6 + mono/metadata/domain.c | 907 +---------------------------- mono/metadata/jit-info.c | 946 +++++++++++++++++++++++++++++++ 4 files changed, 956 insertions(+), 904 deletions(-) create mode 100644 mono/metadata/jit-info.c diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index d27404acb0f..335484ae676 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -124,6 +124,7 @@ common_sources = \ icall.c \ icall-def.h \ image.c \ + jit-info.c \ loader.c \ locales.c \ locales.h \ diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index 68257c7ef13..065e0458fa2 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -471,6 +471,12 @@ void mono_jit_info_init (MonoJitInfo *ji, MonoMethod *method, guint8 *code, int code_size, MonoJitInfoFlags flags, int num_clauses, int num_holes) MONO_INTERNAL; +MonoJitInfoTable * +mono_jit_info_table_new (MonoDomain *domain) MONO_INTERNAL; + +void +mono_jit_info_table_free (MonoJitInfoTable *table) MONO_INTERNAL; + void mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji) MONO_INTERNAL; diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index c624b6a78d5..e30c0345c0a 100755 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -116,8 +116,6 @@ typedef struct { static const MonoRuntimeInfo *current_runtime = NULL; -static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL; - /* This is the list of runtime versions supported by this JIT. */ static const MonoRuntimeInfo supported_runtimes[] = { @@ -170,905 +168,6 @@ mono_domain_get_tls_offset (void) return offset; } -#define JIT_INFO_TABLE_FILL_RATIO_NOM 3 -#define JIT_INFO_TABLE_FILL_RATIO_DENOM 4 -#define JIT_INFO_TABLE_FILLED_NUM_ELEMENTS (MONO_JIT_INFO_TABLE_CHUNK_SIZE * JIT_INFO_TABLE_FILL_RATIO_NOM / JIT_INFO_TABLE_FILL_RATIO_DENOM) - -#define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2) -#define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6) - -#define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL) -#define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->d.method == JIT_INFO_TOMBSTONE_MARKER) - -#define JIT_INFO_TABLE_HAZARD_INDEX 0 -#define JIT_INFO_HAZARD_INDEX 1 - -static int -jit_info_table_num_elements (MonoJitInfoTable *table) -{ - int i; - int num_elements = 0; - - for (i = 0; i < table->num_chunks; ++i) { - MonoJitInfoTableChunk *chunk = table->chunks [i]; - int chunk_num_elements = chunk->num_elements; - int j; - - for (j = 0; j < chunk_num_elements; ++j) { - if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) - ++num_elements; - } - } - - return num_elements; -} - -static MonoJitInfoTableChunk* -jit_info_table_new_chunk (void) -{ - MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1); - chunk->refcount = 1; - - return chunk; -} - -static MonoJitInfoTable * -jit_info_table_new (MonoDomain *domain) -{ - MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*)); - - table->domain = domain; - table->num_chunks = 1; - table->chunks [0] = jit_info_table_new_chunk (); - - return table; -} - -static void -jit_info_table_free (MonoJitInfoTable *table) -{ - int i; - int num_chunks = table->num_chunks; - MonoDomain *domain = table->domain; - - mono_domain_lock (domain); - - table->domain->num_jit_info_tables--; - if (table->domain->num_jit_info_tables <= 1) { - GSList *list; - - for (list = table->domain->jit_info_free_queue; list; list = list->next) - g_free (list->data); - - g_slist_free (table->domain->jit_info_free_queue); - table->domain->jit_info_free_queue = NULL; - } - - /* At this point we assume that there are no other threads - still accessing the table, so we don't have to worry about - hazardous pointers. */ - - for (i = 0; i < num_chunks; ++i) { - MonoJitInfoTableChunk *chunk = table->chunks [i]; - int num_elements; - int j; - - if (--chunk->refcount > 0) - continue; - - num_elements = chunk->num_elements; - for (j = 0; j < num_elements; ++j) { - MonoJitInfo *ji = chunk->data [j]; - - if (IS_JIT_INFO_TOMBSTONE (ji)) - g_free (ji); - } - - g_free (chunk); - } - - mono_domain_unlock (domain); - - g_free (table); -} - -/* The jit_info_table is sorted in ascending order by the end - * addresses of the compiled methods. The reason why we have to do - * this is that once we introduce tombstones, it becomes possible for - * code ranges to overlap, and if we sort by code start and insert at - * the back of the table, we cannot guarantee that we won't overlook - * an entry. - * - * There are actually two possible ways to do the sorting and - * inserting which work with our lock-free mechanism: - * - * 1. Sort by start address and insert at the front. When looking for - * an entry, find the last one with a start address lower than the one - * you're looking for, then work your way to the front of the table. - * - * 2. Sort by end address and insert at the back. When looking for an - * entry, find the first one with an end address higher than the one - * you're looking for, then work your way to the end of the table. - * - * We chose the latter out of convenience. - */ -static int -jit_info_table_index (MonoJitInfoTable *table, gint8 *addr) -{ - int left = 0, right = table->num_chunks; - - g_assert (left < right); - - do { - int pos = (left + right) / 2; - MonoJitInfoTableChunk *chunk = table->chunks [pos]; - - if (addr < chunk->last_code_end) - right = pos; - else - left = pos + 1; - } while (left < right); - g_assert (left == right); - - if (left >= table->num_chunks) - return table->num_chunks - 1; - return left; -} - -static int -jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr) -{ - int left = 0, right = chunk->num_elements; - - while (left < right) { - int pos = (left + right) / 2; - MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX); - gint8 *code_end = (gint8*)ji->code_start + ji->code_size; - - if (addr < code_end) - right = pos; - else - left = pos + 1; - } - g_assert (left == right); - - return left; -} - -static MonoJitInfo* -jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint8 *addr) -{ - MonoJitInfo *ji; - int chunk_pos, pos; - - chunk_pos = jit_info_table_index (table, (gint8*)addr); - g_assert (chunk_pos < table->num_chunks); - - pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr); - - /* We now have a position that's very close to that of the - first element whose end address is higher than the one - we're looking for. If we don't have the exact position, - then we have a position below that one, so we'll just - search upward until we find our element. */ - do { - MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos]; - - while (pos < chunk->num_elements) { - ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX); - - ++pos; - - if (IS_JIT_INFO_TOMBSTONE (ji)) { - mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX); - continue; - } - if ((gint8*)addr >= (gint8*)ji->code_start - && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) { - mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX); - return ji; - } - - /* If we find a non-tombstone element which is already - beyond what we're looking for, we have to end the - search. */ - if ((gint8*)addr < (gint8*)ji->code_start) - goto not_found; - } - - ++chunk_pos; - pos = 0; - } while (chunk_pos < table->num_chunks); - - not_found: - if (hp) - mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX); - return NULL; -} - -/* - * mono_jit_info_table_find_internal: - * - * If TRY_AOT is FALSE, avoid loading information for missing methods from AOT images, which is currently not async safe. - * In this case, only those AOT methods will be found whose jit info is already loaded. - * ASYNC SAFETY: When called in an async context (mono_thread_info_is_async_context ()), this is async safe. - * In this case, the returned MonoJitInfo might not have metadata information, in particular, - * mono_jit_info_get_method () could fail. - */ -MonoJitInfo* -mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot) -{ - MonoJitInfoTable *table; - MonoJitInfo *ji, *module_ji; - MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); - - ++mono_stats.jit_info_table_lookup_count; - - /* First we have to get the domain's jit_info_table. This is - complicated by the fact that a writer might substitute a - new table and free the old one. What the writer guarantees - us is that it looks at the hazard pointers after it has - changed the jit_info_table pointer. So, if we guard the - table by a hazard pointer and make sure that the pointer is - still there after we've made it hazardous, we don't have to - worry about the writer freeing the table. */ - table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX); - - ji = jit_info_table_find (table, hp, (gint8*)addr); - if (hp) - mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); - if (ji) - return ji; - - /* Maybe its an AOT module */ - if (try_aot && mono_root_domain && mono_root_domain->aot_modules) { - table = get_hazardous_pointer ((gpointer volatile*)&mono_root_domain->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX); - module_ji = jit_info_table_find (table, hp, (gint8*)addr); - if (module_ji) - ji = jit_info_find_in_aot_func (domain, module_ji->d.image, addr); - if (hp) - mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); - } - - return ji; -} - -MonoJitInfo* -mono_jit_info_table_find (MonoDomain *domain, char *addr) -{ - return mono_jit_info_table_find_internal (domain, addr, TRUE); -} - -static G_GNUC_UNUSED void -jit_info_table_check (MonoJitInfoTable *table) -{ - int i; - - for (i = 0; i < table->num_chunks; ++i) { - MonoJitInfoTableChunk *chunk = table->chunks [i]; - int j; - - g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */); - if (chunk->refcount > 10) - printf("warning: chunk refcount is %d\n", chunk->refcount); - g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE); - - for (j = 0; j < chunk->num_elements; ++j) { - MonoJitInfo *this = chunk->data [j]; - MonoJitInfo *next; - - g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end); - - if (j < chunk->num_elements - 1) - next = chunk->data [j + 1]; - else if (i < table->num_chunks - 1) { - int k; - - for (k = i + 1; k < table->num_chunks; ++k) - if (table->chunks [k]->num_elements > 0) - break; - - if (k >= table->num_chunks) - return; - - g_assert (table->chunks [k]->num_elements > 0); - next = table->chunks [k]->data [0]; - } else - return; - - g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size); - } - } -} - -static MonoJitInfoTable* -jit_info_table_realloc (MonoJitInfoTable *old) -{ - int i; - int num_elements = jit_info_table_num_elements (old); - int required_size; - int num_chunks; - int new_chunk, new_element; - MonoJitInfoTable *new; - - /* number of needed places for elements needed */ - required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM); - num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE; - if (num_chunks == 0) { - g_assert (num_elements == 0); - return jit_info_table_new (old->domain); - } - g_assert (num_chunks > 0); - - new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks); - new->domain = old->domain; - new->num_chunks = num_chunks; - - for (i = 0; i < num_chunks; ++i) - new->chunks [i] = jit_info_table_new_chunk (); - - new_chunk = 0; - new_element = 0; - for (i = 0; i < old->num_chunks; ++i) { - MonoJitInfoTableChunk *chunk = old->chunks [i]; - int chunk_num_elements = chunk->num_elements; - int j; - - for (j = 0; j < chunk_num_elements; ++j) { - if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) { - g_assert (new_chunk < num_chunks); - new->chunks [new_chunk]->data [new_element] = chunk->data [j]; - if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) { - new->chunks [new_chunk]->num_elements = new_element; - ++new_chunk; - new_element = 0; - } - } - } - } - - if (new_chunk < num_chunks) { - g_assert (new_chunk == num_chunks - 1); - new->chunks [new_chunk]->num_elements = new_element; - g_assert (new->chunks [new_chunk]->num_elements > 0); - } - - for (i = 0; i < num_chunks; ++i) { - MonoJitInfoTableChunk *chunk = new->chunks [i]; - MonoJitInfo *ji = chunk->data [chunk->num_elements - 1]; - - new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size; - } - - return new; -} - -static void -jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p) -{ - MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk (); - MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk (); - - g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE); - - new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2; - new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements; - - memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements); - memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements); - - new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start - + new1->data [new1->num_elements - 1]->code_size; - new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start - + new2->data [new2->num_elements - 1]->code_size; - - *new1p = new1; - *new2p = new2; -} - -static MonoJitInfoTable* -jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk) -{ - MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE - + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1)); - int i, j; - - new_table->domain = table->domain; - new_table->num_chunks = table->num_chunks + 1; - - j = 0; - for (i = 0; i < table->num_chunks; ++i) { - if (table->chunks [i] == chunk) { - jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]); - j += 2; - } else { - new_table->chunks [j] = table->chunks [i]; - ++new_table->chunks [j]->refcount; - ++j; - } - } - - g_assert (j == new_table->num_chunks); - - return new_table; -} - -static MonoJitInfoTableChunk* -jit_info_table_purify_chunk (MonoJitInfoTableChunk *old) -{ - MonoJitInfoTableChunk *new = jit_info_table_new_chunk (); - int i, j; - - j = 0; - for (i = 0; i < old->num_elements; ++i) { - if (!IS_JIT_INFO_TOMBSTONE (old->data [i])) - new->data [j++] = old->data [i]; - } - - new->num_elements = j; - if (new->num_elements > 0) - new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size; - else - new->last_code_end = old->last_code_end; - - return new; -} - -static MonoJitInfoTable* -jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk) -{ - MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE - + sizeof (MonoJitInfoTableChunk*) * table->num_chunks); - int i, j; - - new_table->domain = table->domain; - new_table->num_chunks = table->num_chunks; - - j = 0; - for (i = 0; i < table->num_chunks; ++i) { - if (table->chunks [i] == chunk) - new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]); - else { - new_table->chunks [j] = table->chunks [i]; - ++new_table->chunks [j]->refcount; - ++j; - } - } - - g_assert (j == new_table->num_chunks); - - return new_table; -} - -/* As we add an element to the table the case can arise that the chunk - * to which we need to add is already full. In that case we have to - * allocate a new table and do something about that chunk. We have - * several strategies: - * - * If the number of elements in the table is below the low watermark - * or above the high watermark, we reallocate the whole table. - * Otherwise we only concern ourselves with the overflowing chunk: - * - * If there are no tombstones in the chunk then we split the chunk in - * two, each half full. - * - * If the chunk does contain tombstones, we just make a new copy of - * the chunk without the tombstones, which will have room for at least - * the one element we have to add. - */ -static MonoJitInfoTable* -jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk) -{ - int num_elements = jit_info_table_num_elements (table); - int i; - - if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE) - || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) { - //printf ("reallocing table\n"); - return jit_info_table_realloc (table); - } - - /* count the number of non-tombstone elements in the chunk */ - num_elements = 0; - for (i = 0; i < chunk->num_elements; ++i) { - if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i])) - ++num_elements; - } - - if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) { - //printf ("splitting chunk\n"); - return jit_info_table_copy_and_split_chunk (table, chunk); - } - - //printf ("purifying chunk\n"); - return jit_info_table_copy_and_purify_chunk (table, chunk); -} - -/* We add elements to the table by first making space for them by - * shifting the elements at the back to the right, one at a time. - * This results in duplicate entries during the process, but during - * all the time the table is in a sorted state. Also, when an element - * is replaced by another one, the element that replaces it has an end - * address that is equal to or lower than that of the replaced - * element. That property is necessary to guarantee that when - * searching for an element we end up at a position not higher than - * the one we're looking for (i.e. we either find the element directly - * or we end up to the left of it). - */ -static void -jit_info_table_add (MonoDomain *domain, MonoJitInfoTable *volatile *table_ptr, MonoJitInfo *ji) -{ - MonoJitInfoTable *table; - MonoJitInfoTableChunk *chunk; - int chunk_pos, pos; - int num_elements; - int i; - - table = *table_ptr; - - restart: - chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size); - g_assert (chunk_pos < table->num_chunks); - chunk = table->chunks [chunk_pos]; - - if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) { - MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk); - - /* Debugging code, should be removed. */ - //jit_info_table_check (new_table); - - *table_ptr = new_table; - mono_memory_barrier (); - domain->num_jit_info_tables++; - mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free, TRUE, FALSE); - table = new_table; - - goto restart; - } - - /* Debugging code, should be removed. */ - //jit_info_table_check (table); - - num_elements = chunk->num_elements; - - pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size); - - /* First we need to size up the chunk by one, by copying the - last item, or inserting the first one, if the table is - empty. */ - if (num_elements > 0) - chunk->data [num_elements] = chunk->data [num_elements - 1]; - else - chunk->data [0] = ji; - mono_memory_write_barrier (); - chunk->num_elements = ++num_elements; - - /* Shift the elements up one by one. */ - for (i = num_elements - 2; i >= pos; --i) { - mono_memory_write_barrier (); - chunk->data [i + 1] = chunk->data [i]; - } - - /* Now we have room and can insert the new item. */ - mono_memory_write_barrier (); - chunk->data [pos] = ji; - - /* Set the high code end address chunk entry. */ - chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start - + chunk->data [chunk->num_elements - 1]->code_size; - - /* Debugging code, should be removed. */ - //jit_info_table_check (table); -} - -void -mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji) -{ - g_assert (ji->d.method != NULL); - - mono_domain_lock (domain); - - ++mono_stats.jit_info_table_insert_count; - - jit_info_table_add (domain, &domain->jit_info_table, ji); - - mono_domain_unlock (domain); -} - -static MonoJitInfo* -mono_jit_info_make_tombstone (MonoJitInfo *ji) -{ - MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1); - - tombstone->code_start = ji->code_start; - tombstone->code_size = ji->code_size; - tombstone->d.method = JIT_INFO_TOMBSTONE_MARKER; - - return tombstone; -} - -/* - * LOCKING: domain lock - */ -static void -mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji) -{ - if (domain->num_jit_info_tables <= 1) { - /* Can it actually happen that we only have one table - but ji is still hazardous? */ - mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE); - } else { - domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji); - } -} - -static void -jit_info_table_remove (MonoJitInfoTable *table, MonoJitInfo *ji) -{ - MonoJitInfoTableChunk *chunk; - gpointer start = ji->code_start; - int chunk_pos, pos; - - chunk_pos = jit_info_table_index (table, start); - g_assert (chunk_pos < table->num_chunks); - - pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start); - - do { - chunk = table->chunks [chunk_pos]; - - while (pos < chunk->num_elements) { - if (chunk->data [pos] == ji) - goto found; - - g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos])); - g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size - <= (guint8*)ji->code_start + ji->code_size); - - ++pos; - } - - ++chunk_pos; - pos = 0; - } while (chunk_pos < table->num_chunks); - - found: - g_assert (chunk->data [pos] == ji); - - chunk->data [pos] = mono_jit_info_make_tombstone (ji); - - /* Debugging code, should be removed. */ - //jit_info_table_check (table); -} - -void -mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji) -{ - MonoJitInfoTable *table; - - mono_domain_lock (domain); - table = domain->jit_info_table; - - ++mono_stats.jit_info_table_remove_count; - - jit_info_table_remove (table, ji); - - mono_jit_info_free_or_queue (domain, ji); - - mono_domain_unlock (domain); -} - -void -mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end) -{ - MonoJitInfo *ji; - - g_assert (mono_root_domain); - mono_domain_lock (mono_root_domain); - - /* - * We reuse MonoJitInfoTable to store AOT module info, - * this gives us async-safe lookup. - */ - if (!mono_root_domain->aot_modules) { - mono_root_domain->num_jit_info_tables ++; - mono_root_domain->aot_modules = jit_info_table_new (mono_root_domain); - } - - ji = g_new0 (MonoJitInfo, 1); - ji->d.image = image; - ji->code_start = start; - ji->code_size = (guint8*)end - (guint8*)start; - jit_info_table_add (mono_root_domain, &mono_root_domain->aot_modules, ji); - - mono_domain_unlock (mono_root_domain); -} - -void -mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func) -{ - jit_info_find_in_aot_func = func; -} - -int -mono_jit_info_size (MonoJitInfoFlags flags, int num_clauses, int num_holes) -{ - int size = MONO_SIZEOF_JIT_INFO; - - size += num_clauses * sizeof (MonoJitExceptionInfo); - if (flags & JIT_INFO_HAS_CAS_INFO) - size += sizeof (MonoMethodCasInfo); - if (flags & JIT_INFO_HAS_GENERIC_JIT_INFO) - size += sizeof (MonoGenericJitInfo); - if (flags & JIT_INFO_HAS_TRY_BLOCK_HOLES) - size += sizeof (MonoTryBlockHoleTableJitInfo) + num_holes * sizeof (MonoTryBlockHoleJitInfo); - if (flags & JIT_INFO_HAS_ARCH_EH_INFO) - size += sizeof (MonoArchEHJitInfo); - return size; -} - -void -mono_jit_info_init (MonoJitInfo *ji, MonoMethod *method, guint8 *code, int code_size, - MonoJitInfoFlags flags, int num_clauses, int num_holes) -{ - ji->d.method = method; - ji->code_start = code; - ji->code_size = code_size; - ji->num_clauses = num_clauses; - if (flags & JIT_INFO_HAS_CAS_INFO) - ji->has_cas_info = 1; - if (flags & JIT_INFO_HAS_GENERIC_JIT_INFO) - ji->has_generic_jit_info = 1; - if (flags & JIT_INFO_HAS_TRY_BLOCK_HOLES) - ji->has_try_block_holes = 1; - if (flags & JIT_INFO_HAS_ARCH_EH_INFO) - ji->has_arch_eh_info = 1; -} - -gpointer -mono_jit_info_get_code_start (MonoJitInfo* ji) -{ - return ji->code_start; -} - -int -mono_jit_info_get_code_size (MonoJitInfo* ji) -{ - return ji->code_size; -} - -MonoMethod* -mono_jit_info_get_method (MonoJitInfo* ji) -{ - g_assert (!ji->async); - return ji->d.method; -} - -static gpointer -jit_info_key_extract (gpointer value) -{ - MonoJitInfo *info = (MonoJitInfo*)value; - - return info->d.method; -} - -static gpointer* -jit_info_next_value (gpointer value) -{ - MonoJitInfo *info = (MonoJitInfo*)value; - - return (gpointer*)&info->next_jit_code_hash; -} - -void -mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash) -{ - mono_internal_hash_table_init (jit_code_hash, - mono_aligned_addr_hash, - jit_info_key_extract, - jit_info_next_value); -} - -MonoGenericJitInfo* -mono_jit_info_get_generic_jit_info (MonoJitInfo *ji) -{ - if (ji->has_generic_jit_info) - return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses]; - else - return NULL; -} - -/* - * mono_jit_info_get_generic_sharing_context: - * @ji: a jit info - * - * Returns the jit info's generic sharing context, or NULL if it - * doesn't have one. - */ -MonoGenericSharingContext* -mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji) -{ - MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji); - - if (gi) - return gi->generic_sharing_context; - else - return NULL; -} - -/* - * mono_jit_info_set_generic_sharing_context: - * @ji: a jit info - * @gsctx: a generic sharing context - * - * Sets the jit info's generic sharing context. The jit info must - * have memory allocated for the context. - */ -void -mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx) -{ - MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji); - - g_assert (gi); - - gi->generic_sharing_context = gsctx; -} - -MonoTryBlockHoleTableJitInfo* -mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji) -{ - if (ji->has_try_block_holes) { - char *ptr = (char*)&ji->clauses [ji->num_clauses]; - if (ji->has_generic_jit_info) - ptr += sizeof (MonoGenericJitInfo); - return (MonoTryBlockHoleTableJitInfo*)ptr; - } else { - return NULL; - } -} - -static int -try_block_hole_table_size (MonoJitInfo *ji) -{ - MonoTryBlockHoleTableJitInfo *table; - - table = mono_jit_info_get_try_block_hole_table_info (ji); - g_assert (table); - return sizeof (MonoTryBlockHoleTableJitInfo) + table->num_holes * sizeof (MonoTryBlockHoleJitInfo); -} - -MonoArchEHJitInfo* -mono_jit_info_get_arch_eh_info (MonoJitInfo *ji) -{ - if (ji->has_arch_eh_info) { - char *ptr = (char*)&ji->clauses [ji->num_clauses]; - if (ji->has_generic_jit_info) - ptr += sizeof (MonoGenericJitInfo); - if (ji->has_try_block_holes) - ptr += try_block_hole_table_size (ji); - return (MonoArchEHJitInfo*)ptr; - } else { - return NULL; - } -} - -MonoMethodCasInfo* -mono_jit_info_get_cas_info (MonoJitInfo *ji) -{ - if (ji->has_cas_info) { - char *ptr = (char*)&ji->clauses [ji->num_clauses]; - if (ji->has_generic_jit_info) - ptr += sizeof (MonoGenericJitInfo); - if (ji->has_try_block_holes) - ptr += try_block_hole_table_size (ji); - if (ji->has_arch_eh_info) - ptr += sizeof (MonoArchEHJitInfo); - return (MonoMethodCasInfo*)ptr; - } else { - return NULL; - } -} - #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1)) #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1))) @@ -1341,7 +440,7 @@ mono_domain_create (void) mono_jit_code_hash_init (&domain->jit_code_hash); domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC); domain->num_jit_info_tables = 1; - domain->jit_info_table = jit_info_table_new (domain); + domain->jit_info_table = mono_jit_info_table_new (domain); domain->jit_info_free_queue = NULL; domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL); domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL); @@ -2133,9 +1232,9 @@ mono_domain_free (MonoDomain *domain, gboolean force) */ mono_thread_hazardous_try_free_all (); if (domain->aot_modules) - jit_info_table_free (domain->aot_modules); + mono_jit_info_table_free (domain->aot_modules); g_assert (domain->num_jit_info_tables == 1); - jit_info_table_free (domain->jit_info_table); + mono_jit_info_table_free (domain->jit_info_table); domain->jit_info_table = NULL; g_assert (!domain->jit_info_free_queue); diff --git a/mono/metadata/jit-info.c b/mono/metadata/jit-info.c new file mode 100644 index 00000000000..cc0b76622fb --- /dev/null +++ b/mono/metadata/jit-info.c @@ -0,0 +1,946 @@ +/* + * jit-info.c: MonoJitInfo functionality + * + * Author: + * Dietmar Maurer (dietmar@ximian.com) + * Patrik Torstensson + * + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) + * Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com) + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL; + +#define JIT_INFO_TABLE_FILL_RATIO_NOM 3 +#define JIT_INFO_TABLE_FILL_RATIO_DENOM 4 +#define JIT_INFO_TABLE_FILLED_NUM_ELEMENTS (MONO_JIT_INFO_TABLE_CHUNK_SIZE * JIT_INFO_TABLE_FILL_RATIO_NOM / JIT_INFO_TABLE_FILL_RATIO_DENOM) + +#define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2) +#define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6) + +#define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL) +#define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->d.method == JIT_INFO_TOMBSTONE_MARKER) + +#define JIT_INFO_TABLE_HAZARD_INDEX 0 +#define JIT_INFO_HAZARD_INDEX 1 + +static int +jit_info_table_num_elements (MonoJitInfoTable *table) +{ + int i; + int num_elements = 0; + + for (i = 0; i < table->num_chunks; ++i) { + MonoJitInfoTableChunk *chunk = table->chunks [i]; + int chunk_num_elements = chunk->num_elements; + int j; + + for (j = 0; j < chunk_num_elements; ++j) { + if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) + ++num_elements; + } + } + + return num_elements; +} + +static MonoJitInfoTableChunk* +jit_info_table_new_chunk (void) +{ + MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1); + chunk->refcount = 1; + + return chunk; +} + +MonoJitInfoTable * +mono_jit_info_table_new (MonoDomain *domain) +{ + MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*)); + + table->domain = domain; + table->num_chunks = 1; + table->chunks [0] = jit_info_table_new_chunk (); + + return table; +} + +void +mono_jit_info_table_free (MonoJitInfoTable *table) +{ + int i; + int num_chunks = table->num_chunks; + MonoDomain *domain = table->domain; + + mono_domain_lock (domain); + + table->domain->num_jit_info_tables--; + if (table->domain->num_jit_info_tables <= 1) { + GSList *list; + + for (list = table->domain->jit_info_free_queue; list; list = list->next) + g_free (list->data); + + g_slist_free (table->domain->jit_info_free_queue); + table->domain->jit_info_free_queue = NULL; + } + + /* At this point we assume that there are no other threads + still accessing the table, so we don't have to worry about + hazardous pointers. */ + + for (i = 0; i < num_chunks; ++i) { + MonoJitInfoTableChunk *chunk = table->chunks [i]; + int num_elements; + int j; + + if (--chunk->refcount > 0) + continue; + + num_elements = chunk->num_elements; + for (j = 0; j < num_elements; ++j) { + MonoJitInfo *ji = chunk->data [j]; + + if (IS_JIT_INFO_TOMBSTONE (ji)) + g_free (ji); + } + + g_free (chunk); + } + + mono_domain_unlock (domain); + + g_free (table); +} + +/* The jit_info_table is sorted in ascending order by the end + * addresses of the compiled methods. The reason why we have to do + * this is that once we introduce tombstones, it becomes possible for + * code ranges to overlap, and if we sort by code start and insert at + * the back of the table, we cannot guarantee that we won't overlook + * an entry. + * + * There are actually two possible ways to do the sorting and + * inserting which work with our lock-free mechanism: + * + * 1. Sort by start address and insert at the front. When looking for + * an entry, find the last one with a start address lower than the one + * you're looking for, then work your way to the front of the table. + * + * 2. Sort by end address and insert at the back. When looking for an + * entry, find the first one with an end address higher than the one + * you're looking for, then work your way to the end of the table. + * + * We chose the latter out of convenience. + */ +static int +jit_info_table_index (MonoJitInfoTable *table, gint8 *addr) +{ + int left = 0, right = table->num_chunks; + + g_assert (left < right); + + do { + int pos = (left + right) / 2; + MonoJitInfoTableChunk *chunk = table->chunks [pos]; + + if (addr < chunk->last_code_end) + right = pos; + else + left = pos + 1; + } while (left < right); + g_assert (left == right); + + if (left >= table->num_chunks) + return table->num_chunks - 1; + return left; +} + +static int +jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr) +{ + int left = 0, right = chunk->num_elements; + + while (left < right) { + int pos = (left + right) / 2; + MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX); + gint8 *code_end = (gint8*)ji->code_start + ji->code_size; + + if (addr < code_end) + right = pos; + else + left = pos + 1; + } + g_assert (left == right); + + return left; +} + +static MonoJitInfo* +jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint8 *addr) +{ + MonoJitInfo *ji; + int chunk_pos, pos; + + chunk_pos = jit_info_table_index (table, (gint8*)addr); + g_assert (chunk_pos < table->num_chunks); + + pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr); + + /* We now have a position that's very close to that of the + first element whose end address is higher than the one + we're looking for. If we don't have the exact position, + then we have a position below that one, so we'll just + search upward until we find our element. */ + do { + MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos]; + + while (pos < chunk->num_elements) { + ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX); + + ++pos; + + if (IS_JIT_INFO_TOMBSTONE (ji)) { + mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX); + continue; + } + if ((gint8*)addr >= (gint8*)ji->code_start + && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) { + mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX); + return ji; + } + + /* If we find a non-tombstone element which is already + beyond what we're looking for, we have to end the + search. */ + if ((gint8*)addr < (gint8*)ji->code_start) + goto not_found; + } + + ++chunk_pos; + pos = 0; + } while (chunk_pos < table->num_chunks); + + not_found: + if (hp) + mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX); + return NULL; +} + +/* + * mono_jit_info_table_find_internal: + * + * If TRY_AOT is FALSE, avoid loading information for missing methods from AOT images, which is currently not async safe. + * In this case, only those AOT methods will be found whose jit info is already loaded. + * ASYNC SAFETY: When called in an async context (mono_thread_info_is_async_context ()), this is async safe. + * In this case, the returned MonoJitInfo might not have metadata information, in particular, + * mono_jit_info_get_method () could fail. + */ +MonoJitInfo* +mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot) +{ + MonoJitInfoTable *table; + MonoJitInfo *ji, *module_ji; + MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); + + ++mono_stats.jit_info_table_lookup_count; + + /* First we have to get the domain's jit_info_table. This is + complicated by the fact that a writer might substitute a + new table and free the old one. What the writer guarantees + us is that it looks at the hazard pointers after it has + changed the jit_info_table pointer. So, if we guard the + table by a hazard pointer and make sure that the pointer is + still there after we've made it hazardous, we don't have to + worry about the writer freeing the table. */ + table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX); + + ji = jit_info_table_find (table, hp, (gint8*)addr); + if (hp) + mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); + if (ji) + return ji; + + /* Maybe its an AOT module */ + if (try_aot && mono_get_root_domain () && mono_get_root_domain ()->aot_modules) { + table = get_hazardous_pointer ((gpointer volatile*)&mono_get_root_domain ()->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX); + module_ji = jit_info_table_find (table, hp, (gint8*)addr); + if (module_ji) + ji = jit_info_find_in_aot_func (domain, module_ji->d.image, addr); + if (hp) + mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); + } + + return ji; +} + +MonoJitInfo* +mono_jit_info_table_find (MonoDomain *domain, char *addr) +{ + return mono_jit_info_table_find_internal (domain, addr, TRUE); +} + +static G_GNUC_UNUSED void +jit_info_table_check (MonoJitInfoTable *table) +{ + int i; + + for (i = 0; i < table->num_chunks; ++i) { + MonoJitInfoTableChunk *chunk = table->chunks [i]; + int j; + + g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */); + if (chunk->refcount > 10) + printf("warning: chunk refcount is %d\n", chunk->refcount); + g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE); + + for (j = 0; j < chunk->num_elements; ++j) { + MonoJitInfo *this = chunk->data [j]; + MonoJitInfo *next; + + g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end); + + if (j < chunk->num_elements - 1) + next = chunk->data [j + 1]; + else if (i < table->num_chunks - 1) { + int k; + + for (k = i + 1; k < table->num_chunks; ++k) + if (table->chunks [k]->num_elements > 0) + break; + + if (k >= table->num_chunks) + return; + + g_assert (table->chunks [k]->num_elements > 0); + next = table->chunks [k]->data [0]; + } else + return; + + g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size); + } + } +} + +static MonoJitInfoTable* +jit_info_table_realloc (MonoJitInfoTable *old) +{ + int i; + int num_elements = jit_info_table_num_elements (old); + int required_size; + int num_chunks; + int new_chunk, new_element; + MonoJitInfoTable *new; + + /* number of needed places for elements needed */ + required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM); + num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE; + if (num_chunks == 0) { + g_assert (num_elements == 0); + return mono_jit_info_table_new (old->domain); + } + g_assert (num_chunks > 0); + + new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks); + new->domain = old->domain; + new->num_chunks = num_chunks; + + for (i = 0; i < num_chunks; ++i) + new->chunks [i] = jit_info_table_new_chunk (); + + new_chunk = 0; + new_element = 0; + for (i = 0; i < old->num_chunks; ++i) { + MonoJitInfoTableChunk *chunk = old->chunks [i]; + int chunk_num_elements = chunk->num_elements; + int j; + + for (j = 0; j < chunk_num_elements; ++j) { + if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) { + g_assert (new_chunk < num_chunks); + new->chunks [new_chunk]->data [new_element] = chunk->data [j]; + if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) { + new->chunks [new_chunk]->num_elements = new_element; + ++new_chunk; + new_element = 0; + } + } + } + } + + if (new_chunk < num_chunks) { + g_assert (new_chunk == num_chunks - 1); + new->chunks [new_chunk]->num_elements = new_element; + g_assert (new->chunks [new_chunk]->num_elements > 0); + } + + for (i = 0; i < num_chunks; ++i) { + MonoJitInfoTableChunk *chunk = new->chunks [i]; + MonoJitInfo *ji = chunk->data [chunk->num_elements - 1]; + + new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size; + } + + return new; +} + +static void +jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p) +{ + MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk (); + MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk (); + + g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE); + + new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2; + new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements; + + memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements); + memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements); + + new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start + + new1->data [new1->num_elements - 1]->code_size; + new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start + + new2->data [new2->num_elements - 1]->code_size; + + *new1p = new1; + *new2p = new2; +} + +static MonoJitInfoTable* +jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk) +{ + MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1)); + int i, j; + + new_table->domain = table->domain; + new_table->num_chunks = table->num_chunks + 1; + + j = 0; + for (i = 0; i < table->num_chunks; ++i) { + if (table->chunks [i] == chunk) { + jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]); + j += 2; + } else { + new_table->chunks [j] = table->chunks [i]; + ++new_table->chunks [j]->refcount; + ++j; + } + } + + g_assert (j == new_table->num_chunks); + + return new_table; +} + +static MonoJitInfoTableChunk* +jit_info_table_purify_chunk (MonoJitInfoTableChunk *old) +{ + MonoJitInfoTableChunk *new = jit_info_table_new_chunk (); + int i, j; + + j = 0; + for (i = 0; i < old->num_elements; ++i) { + if (!IS_JIT_INFO_TOMBSTONE (old->data [i])) + new->data [j++] = old->data [i]; + } + + new->num_elements = j; + if (new->num_elements > 0) + new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size; + else + new->last_code_end = old->last_code_end; + + return new; +} + +static MonoJitInfoTable* +jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk) +{ + MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + + sizeof (MonoJitInfoTableChunk*) * table->num_chunks); + int i, j; + + new_table->domain = table->domain; + new_table->num_chunks = table->num_chunks; + + j = 0; + for (i = 0; i < table->num_chunks; ++i) { + if (table->chunks [i] == chunk) + new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]); + else { + new_table->chunks [j] = table->chunks [i]; + ++new_table->chunks [j]->refcount; + ++j; + } + } + + g_assert (j == new_table->num_chunks); + + return new_table; +} + +/* As we add an element to the table the case can arise that the chunk + * to which we need to add is already full. In that case we have to + * allocate a new table and do something about that chunk. We have + * several strategies: + * + * If the number of elements in the table is below the low watermark + * or above the high watermark, we reallocate the whole table. + * Otherwise we only concern ourselves with the overflowing chunk: + * + * If there are no tombstones in the chunk then we split the chunk in + * two, each half full. + * + * If the chunk does contain tombstones, we just make a new copy of + * the chunk without the tombstones, which will have room for at least + * the one element we have to add. + */ +static MonoJitInfoTable* +jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk) +{ + int num_elements = jit_info_table_num_elements (table); + int i; + + if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE) + || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) { + //printf ("reallocing table\n"); + return jit_info_table_realloc (table); + } + + /* count the number of non-tombstone elements in the chunk */ + num_elements = 0; + for (i = 0; i < chunk->num_elements; ++i) { + if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i])) + ++num_elements; + } + + if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) { + //printf ("splitting chunk\n"); + return jit_info_table_copy_and_split_chunk (table, chunk); + } + + //printf ("purifying chunk\n"); + return jit_info_table_copy_and_purify_chunk (table, chunk); +} + +/* We add elements to the table by first making space for them by + * shifting the elements at the back to the right, one at a time. + * This results in duplicate entries during the process, but during + * all the time the table is in a sorted state. Also, when an element + * is replaced by another one, the element that replaces it has an end + * address that is equal to or lower than that of the replaced + * element. That property is necessary to guarantee that when + * searching for an element we end up at a position not higher than + * the one we're looking for (i.e. we either find the element directly + * or we end up to the left of it). + */ +static void +jit_info_table_add (MonoDomain *domain, MonoJitInfoTable *volatile *table_ptr, MonoJitInfo *ji) +{ + MonoJitInfoTable *table; + MonoJitInfoTableChunk *chunk; + int chunk_pos, pos; + int num_elements; + int i; + + table = *table_ptr; + + restart: + chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size); + g_assert (chunk_pos < table->num_chunks); + chunk = table->chunks [chunk_pos]; + + if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) { + MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk); + + /* Debugging code, should be removed. */ + //jit_info_table_check (new_table); + + *table_ptr = new_table; + mono_memory_barrier (); + domain->num_jit_info_tables++; + mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)mono_jit_info_table_free, TRUE, FALSE); + table = new_table; + + goto restart; + } + + /* Debugging code, should be removed. */ + //jit_info_table_check (table); + + num_elements = chunk->num_elements; + + pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size); + + /* First we need to size up the chunk by one, by copying the + last item, or inserting the first one, if the table is + empty. */ + if (num_elements > 0) + chunk->data [num_elements] = chunk->data [num_elements - 1]; + else + chunk->data [0] = ji; + mono_memory_write_barrier (); + chunk->num_elements = ++num_elements; + + /* Shift the elements up one by one. */ + for (i = num_elements - 2; i >= pos; --i) { + mono_memory_write_barrier (); + chunk->data [i + 1] = chunk->data [i]; + } + + /* Now we have room and can insert the new item. */ + mono_memory_write_barrier (); + chunk->data [pos] = ji; + + /* Set the high code end address chunk entry. */ + chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start + + chunk->data [chunk->num_elements - 1]->code_size; + + /* Debugging code, should be removed. */ + //jit_info_table_check (table); +} + +void +mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji) +{ + g_assert (ji->d.method != NULL); + + mono_domain_lock (domain); + + ++mono_stats.jit_info_table_insert_count; + + jit_info_table_add (domain, &domain->jit_info_table, ji); + + mono_domain_unlock (domain); +} + +static MonoJitInfo* +mono_jit_info_make_tombstone (MonoJitInfo *ji) +{ + MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1); + + tombstone->code_start = ji->code_start; + tombstone->code_size = ji->code_size; + tombstone->d.method = JIT_INFO_TOMBSTONE_MARKER; + + return tombstone; +} + +/* + * LOCKING: domain lock + */ +static void +mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji) +{ + if (domain->num_jit_info_tables <= 1) { + /* Can it actually happen that we only have one table + but ji is still hazardous? */ + mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE); + } else { + domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji); + } +} + +static void +jit_info_table_remove (MonoJitInfoTable *table, MonoJitInfo *ji) +{ + MonoJitInfoTableChunk *chunk; + gpointer start = ji->code_start; + int chunk_pos, pos; + + chunk_pos = jit_info_table_index (table, start); + g_assert (chunk_pos < table->num_chunks); + + pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start); + + do { + chunk = table->chunks [chunk_pos]; + + while (pos < chunk->num_elements) { + if (chunk->data [pos] == ji) + goto found; + + g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos])); + g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size + <= (guint8*)ji->code_start + ji->code_size); + + ++pos; + } + + ++chunk_pos; + pos = 0; + } while (chunk_pos < table->num_chunks); + + found: + g_assert (chunk->data [pos] == ji); + + chunk->data [pos] = mono_jit_info_make_tombstone (ji); + + /* Debugging code, should be removed. */ + //jit_info_table_check (table); +} + +void +mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji) +{ + MonoJitInfoTable *table; + + mono_domain_lock (domain); + table = domain->jit_info_table; + + ++mono_stats.jit_info_table_remove_count; + + jit_info_table_remove (table, ji); + + mono_jit_info_free_or_queue (domain, ji); + + mono_domain_unlock (domain); +} + +void +mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end) +{ + MonoJitInfo *ji; + MonoDomain *domain = mono_get_root_domain (); + + g_assert (domain); + mono_domain_lock (domain); + + /* + * We reuse MonoJitInfoTable to store AOT module info, + * this gives us async-safe lookup. + */ + if (!domain->aot_modules) { + domain->num_jit_info_tables ++; + domain->aot_modules = mono_jit_info_table_new (domain); + } + + ji = g_new0 (MonoJitInfo, 1); + ji->d.image = image; + ji->code_start = start; + ji->code_size = (guint8*)end - (guint8*)start; + jit_info_table_add (domain, &domain->aot_modules, ji); + + mono_domain_unlock (domain); +} + +void +mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func) +{ + jit_info_find_in_aot_func = func; +} + +int +mono_jit_info_size (MonoJitInfoFlags flags, int num_clauses, int num_holes) +{ + int size = MONO_SIZEOF_JIT_INFO; + + size += num_clauses * sizeof (MonoJitExceptionInfo); + if (flags & JIT_INFO_HAS_CAS_INFO) + size += sizeof (MonoMethodCasInfo); + if (flags & JIT_INFO_HAS_GENERIC_JIT_INFO) + size += sizeof (MonoGenericJitInfo); + if (flags & JIT_INFO_HAS_TRY_BLOCK_HOLES) + size += sizeof (MonoTryBlockHoleTableJitInfo) + num_holes * sizeof (MonoTryBlockHoleJitInfo); + if (flags & JIT_INFO_HAS_ARCH_EH_INFO) + size += sizeof (MonoArchEHJitInfo); + return size; +} + +void +mono_jit_info_init (MonoJitInfo *ji, MonoMethod *method, guint8 *code, int code_size, + MonoJitInfoFlags flags, int num_clauses, int num_holes) +{ + ji->d.method = method; + ji->code_start = code; + ji->code_size = code_size; + ji->num_clauses = num_clauses; + if (flags & JIT_INFO_HAS_CAS_INFO) + ji->has_cas_info = 1; + if (flags & JIT_INFO_HAS_GENERIC_JIT_INFO) + ji->has_generic_jit_info = 1; + if (flags & JIT_INFO_HAS_TRY_BLOCK_HOLES) + ji->has_try_block_holes = 1; + if (flags & JIT_INFO_HAS_ARCH_EH_INFO) + ji->has_arch_eh_info = 1; +} + +gpointer +mono_jit_info_get_code_start (MonoJitInfo* ji) +{ + return ji->code_start; +} + +int +mono_jit_info_get_code_size (MonoJitInfo* ji) +{ + return ji->code_size; +} + +MonoMethod* +mono_jit_info_get_method (MonoJitInfo* ji) +{ + g_assert (!ji->async); + return ji->d.method; +} + +static gpointer +jit_info_key_extract (gpointer value) +{ + MonoJitInfo *info = (MonoJitInfo*)value; + + return info->d.method; +} + +static gpointer* +jit_info_next_value (gpointer value) +{ + MonoJitInfo *info = (MonoJitInfo*)value; + + return (gpointer*)&info->next_jit_code_hash; +} + +void +mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash) +{ + mono_internal_hash_table_init (jit_code_hash, + mono_aligned_addr_hash, + jit_info_key_extract, + jit_info_next_value); +} + +MonoGenericJitInfo* +mono_jit_info_get_generic_jit_info (MonoJitInfo *ji) +{ + if (ji->has_generic_jit_info) + return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses]; + else + return NULL; +} + +/* + * mono_jit_info_get_generic_sharing_context: + * @ji: a jit info + * + * Returns the jit info's generic sharing context, or NULL if it + * doesn't have one. + */ +MonoGenericSharingContext* +mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji) +{ + MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji); + + if (gi) + return gi->generic_sharing_context; + else + return NULL; +} + +/* + * mono_jit_info_set_generic_sharing_context: + * @ji: a jit info + * @gsctx: a generic sharing context + * + * Sets the jit info's generic sharing context. The jit info must + * have memory allocated for the context. + */ +void +mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx) +{ + MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji); + + g_assert (gi); + + gi->generic_sharing_context = gsctx; +} + +MonoTryBlockHoleTableJitInfo* +mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji) +{ + if (ji->has_try_block_holes) { + char *ptr = (char*)&ji->clauses [ji->num_clauses]; + if (ji->has_generic_jit_info) + ptr += sizeof (MonoGenericJitInfo); + return (MonoTryBlockHoleTableJitInfo*)ptr; + } else { + return NULL; + } +} + +static int +try_block_hole_table_size (MonoJitInfo *ji) +{ + MonoTryBlockHoleTableJitInfo *table; + + table = mono_jit_info_get_try_block_hole_table_info (ji); + g_assert (table); + return sizeof (MonoTryBlockHoleTableJitInfo) + table->num_holes * sizeof (MonoTryBlockHoleJitInfo); +} + +MonoArchEHJitInfo* +mono_jit_info_get_arch_eh_info (MonoJitInfo *ji) +{ + if (ji->has_arch_eh_info) { + char *ptr = (char*)&ji->clauses [ji->num_clauses]; + if (ji->has_generic_jit_info) + ptr += sizeof (MonoGenericJitInfo); + if (ji->has_try_block_holes) + ptr += try_block_hole_table_size (ji); + return (MonoArchEHJitInfo*)ptr; + } else { + return NULL; + } +} + +MonoMethodCasInfo* +mono_jit_info_get_cas_info (MonoJitInfo *ji) +{ + if (ji->has_cas_info) { + char *ptr = (char*)&ji->clauses [ji->num_clauses]; + if (ji->has_generic_jit_info) + ptr += sizeof (MonoGenericJitInfo); + if (ji->has_try_block_holes) + ptr += try_block_hole_table_size (ji); + if (ji->has_arch_eh_info) + ptr += sizeof (MonoArchEHJitInfo); + return (MonoMethodCasInfo*)ptr; + } else { + return NULL; + } +} From 6abce1e8d80a9dfdc11f8b2fb6d1d1eab7d9b768 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 7 Oct 2014 18:45:50 +0100 Subject: [PATCH 366/543] Test HttpQSCollection.ToString url encoding. Covers #22557. --- mcs/class/System.Web/Test/System.Web/HttpUtilityTest.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mcs/class/System.Web/Test/System.Web/HttpUtilityTest.cs b/mcs/class/System.Web/Test/System.Web/HttpUtilityTest.cs index 4c7228dd6a2..5ead2173893 100644 --- a/mcs/class/System.Web/Test/System.Web/HttpUtilityTest.cs +++ b/mcs/class/System.Web/Test/System.Web/HttpUtilityTest.cs @@ -861,6 +861,15 @@ static void ParseQueryString_Helper (NameValueCollection nvc, string msg, string @" ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ", }; + [Test] + public void ToStringEncoding () + { + var queryStringNameValues = HttpUtility.ParseQueryString(string.Empty); + queryStringNameValues.Add("ReturnUrl", @"http://localhost/login/authenticate?ReturnUrl=http://localhost/secured_area&__provider__=google"); + + var expected = "ReturnUrl=http%3a%2f%2flocalhost%2flogin%2fauthenticate%3fReturnUrl%3dhttp%3a%2f%2flocalhost%2fsecured_area%26__provider__%3dgoogle"; + Assert.AreEqual (expected, queryStringNameValues.ToString()); + } } } From 843fe0b3c6af817b2a831d21c97e0dfeae38a634 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 7 Oct 2014 18:50:45 +0100 Subject: [PATCH 367/543] HttpQSCollection.ToString now url encodes values. Fixes 22557. --- mcs/class/System.Web/System.Web/HttpUtility.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.Web/System.Web/HttpUtility.cs b/mcs/class/System.Web/System.Web/HttpUtility.cs index bb821a573cf..71892767469 100644 --- a/mcs/class/System.Web/System.Web/HttpUtility.cs +++ b/mcs/class/System.Web/System.Web/HttpUtility.cs @@ -56,7 +56,7 @@ public override string ToString () StringBuilder sb = new StringBuilder (); string [] keys = AllKeys; for (int i = 0; i < count; i++) { - sb.AppendFormat ("{0}={1}&", keys [i], this [keys [i]]); + sb.AppendFormat ("{0}={1}&", keys [i], UrlEncode (this [keys [i]])); } if (sb.Length > 0) sb.Length--; From 8b90653ff3048951167da9e6c7cc074a90815c5b Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 7 Oct 2014 13:51:10 -0400 Subject: [PATCH 368/543] [System.Core/Android] Fix standalone unit tests. Commit 5564dad1 broke the self-test (for testing on the developer machine, not an Android target). Fixup the comment so that appropriate data is grabbed and used for testing, and improve AndroidTimeZones.GetDefaultTimeZoneName() so that the default timezone ID can be specified via the __XA_OVERRIDE_TIMEZONE_ID__ environment variable for testing. Finally, demonstrate TimeZoneInfo.GetUtcOffset(DateTime) use so that I can get better insight into the timezone data stored within the database: $ __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe --offset=1969-01-01 Using DateTime Offset: 1/1/1969 12:00:00 AM DB type: System.AndroidTzData name=Africa/Abidjan Africa/Abidjan From Offset: 00:00:00 name=Africa/Accra Africa/Accra From Offset: 00:00:00 name=Africa/Addis_Ababa Africa/Addis_Ababa From Offset: 03:00:00 ... --- .../System/TimeZoneInfo.Android.cs | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.Android.cs b/mcs/class/System.Core/System/TimeZoneInfo.Android.cs index 63502e555fa..bd35e657343 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.Android.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.Android.cs @@ -553,7 +553,10 @@ static string GetDefaultTimeZoneName () { IntPtr value = IntPtr.Zero; int n = 0; - string defaultTimeZone; + string defaultTimeZone = Environment.GetEnvironmentVariable ("__XA_OVERRIDE_TIMEZONE_ID__"); + + if (!string.IsNullOrEmpty (defaultTimeZone)) + return defaultTimeZone; // Used by the tests if (Environment.GetEnvironmentVariable ("__XA_USE_JAVA_DEFAULT_TIMEZONE_ID__") == null) @@ -576,16 +579,20 @@ static string GetDefaultTimeZoneName () #if SELF_TEST /* * Compile: - * mcs /out:tzi.exe /unsafe "/d:INSIDE_CORLIB;MONODROID;NET_4_0;LIBC;SELF_TEST" System/TimeZone*.cs ../../build/common/Consts.cs ../Mono.Options/Mono.Options/Options.cs + * mcs /debug+ /out:tzi.exe /unsafe "/d:INSIDE_CORLIB;MONODROID;NET_4_0;LIBC;SELF_TEST" ../corlib/System/AndroidPlatform.cs System/TimeZone*.cs ../../build/common/Consts.cs ../Mono.Options/Mono.Options/Options.cs * Prep: * mkdir -p usr/share/zoneinfo + * mkdir -p misc/zoneinfo/zoneinfo * android_root=`adb shell echo '$ANDROID_ROOT' | tr -d "\r"` + * android_data=`adb shell echo '$ANDROID_DATA' | tr -d "\r"` * adb pull $android_root/usr/share/zoneinfo usr/share/zoneinfo + * adb pull $android_data/misc/zoneinfo/tzdata misc/zoneinfo * Run: - * ANDROID_ROOT=`pwd` mono tzi.exe + * __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe --offset=1969-01-01 */ static void Main (string[] args) { + DateTime? offset = null; Func c = () => GetDefaultTimeZoneDB (); Mono.Options.OptionSet p = null; p = new Mono.Options.OptionSet () { @@ -595,6 +602,10 @@ static void Main (string[] args) { "Z=", "Create ZoneInfoDB from {DIR}.", v => { c = () => new ZoneInfoDB (v); } }, + { "offset=", "Show timezone info offset for DateTime {OFFSET}.", v => { + offset = DateTime.Parse (v); + Console.WriteLine ("Using DateTime Offset: {0}", offset); + } }, { "help", "Show this message and exit", v => { p.WriteOptionDescriptions (Console.Out); Environment.Exit (0); @@ -607,8 +618,12 @@ static void Main (string[] args) Console.Write ("name={0,-40}", id); try { TimeZoneInfo zone = _GetTimeZone (id); - if (zone != null) - Console.Write (" {0}", zone); + if (zone != null) { + Console.Write (" {0,-40}", zone); + if (offset.HasValue) { + Console.Write ("From Offset: {0}", zone.GetUtcOffset (offset.Value)); + } + } else { Console.Write (" ERROR:null"); } From ac2d851398d740e670c5f9073164546f18152848 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 7 Oct 2014 15:43:08 -0400 Subject: [PATCH 369/543] [jit] Reduce code duplication in the inlining code. --- mono/mini/method-to-ir.c | 62 ++++++++++++++++++++++------------------ mono/mini/mini.c | 2 +- mono/mini/mini.h | 5 +++- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 973f37bd735..fd0ec8b1e72 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -4689,6 +4689,8 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method) int i; #endif + if (cfg->disable_inline) + return FALSE; if (cfg->generic_sharing_context) return FALSE; @@ -4793,6 +4795,9 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method) } #endif + if (g_list_find (cfg->dont_inline, method)) + return FALSE; + return TRUE; } @@ -6003,9 +6008,14 @@ emit_init_local (MonoCompile *cfg, int local, MonoType *type, gboolean init) } } +/* + * inline_method: + * + * Return the cost of inlining CMETHOD. + */ static int inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp, - guchar *ip, guint real_offset, GList *dont_inline, gboolean inline_always) + guchar *ip, guint real_offset, gboolean inline_always, MonoBasicBlock **out_cbb) { MonoInst *ins, *rvar = NULL; MonoMethodHeader *cheader; @@ -6022,7 +6032,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, guint32 prev_cil_offset_to_bb_len; MonoMethod *prev_current_method; MonoGenericContext *prev_generic_context; - gboolean ret_var_set, prev_ret_var_set, virtual = FALSE; + gboolean ret_var_set, prev_ret_var_set, prev_disable_inline, virtual = FALSE; g_assert (cfg->exception_type == MONO_EXCEPTION_NONE); @@ -6098,11 +6108,12 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, prev_current_method = cfg->current_method; prev_generic_context = cfg->generic_context; prev_ret_var_set = cfg->ret_var_set; + prev_disable_inline = cfg->disable_inline; if (*ip == CEE_CALLVIRT && !(cmethod->flags & METHOD_ATTRIBUTE_STATIC)) virtual = TRUE; - costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, rvar, dont_inline, sp, real_offset, virtual); + costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, rvar, sp, real_offset, virtual); ret_var_set = cfg->ret_var_set; @@ -6118,6 +6129,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, cfg->current_method = prev_current_method; cfg->generic_context = prev_generic_context; cfg->ret_var_set = prev_ret_var_set; + cfg->disable_inline = prev_disable_inline; cfg->inline_depth --; if ((costs >= 0 && costs < 60) || inline_always) { @@ -6172,6 +6184,8 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, cfg->cbb = ebblock; } + *out_cbb = cfg->cbb; + if (rvar) { /* * If the inlined method contains only a throw, then the ret var is not @@ -6854,7 +6868,7 @@ create_magic_tls_access (MonoCompile *cfg, MonoClassField *tls_field, MonoInst * */ int mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, - MonoInst *return_var, GList *dont_inline, MonoInst **inline_args, + MonoInst *return_var, MonoInst **inline_args, guint inline_offset, gboolean is_virtual_call) { MonoError error; @@ -6884,13 +6898,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b gboolean dont_verify, dont_verify_stloc, readonly = FALSE; int context_used; gboolean init_locals, seq_points, skip_dead_blocks; - gboolean disable_inline, sym_seq_points = FALSE; + gboolean sym_seq_points = FALSE; MonoInst *cached_tls_addr = NULL; MonoDebugMethodInfo *minfo; MonoBitSet *seq_point_locs = NULL; MonoBitSet *seq_point_set_locs = NULL; - disable_inline = is_jit_optimizer_disabled (method); + cfg->disable_inline = is_jit_optimizer_disabled (method); /* serialization and xdomain stuff may need access to private fields and methods */ dont_verify = method->klass->image->assembly->corlib_internal? TRUE: FALSE; @@ -7019,7 +7033,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b param_types [n + sig->hasthis] = sig->params [n]; cfg->arg_types = param_types; - dont_inline = g_list_prepend (dont_inline, method); + cfg->dont_inline = g_list_prepend (cfg->dont_inline, method); if (cfg->method == method) { if (cfg->prof_options & MONO_PROFILE_INS_COVERAGE) @@ -8374,8 +8388,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b /* Inlining */ if (cmethod && (cfg->opt & MONO_OPT_INLINE) && (!virtual || !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) || MONO_METHOD_IS_FINAL (cmethod)) && - !disable_inline && mono_method_check_inlining (cfg, cmethod) && - !g_list_find (dont_inline, cmethod)) { + mono_method_check_inlining (cfg, cmethod)) { int costs; gboolean always = FALSE; @@ -8387,10 +8400,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b always = TRUE; } - costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, dont_inline, always); + costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, always, &bblock); if (costs) { cfg->real_offset += 5; - bblock = cfg->cbb; if (!MONO_TYPE_IS_VOID (fsig->ret)) { /* *sp is already set by inline_method */ @@ -9715,14 +9727,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b CHECK_CFG_EXCEPTION; } else if ((cfg->opt & MONO_OPT_INLINE) && cmethod && !context_used && !vtable_arg && - !disable_inline && mono_method_check_inlining (cfg, cmethod) && - !mono_class_is_subclass_of (cmethod->klass, mono_defaults.exception_class, FALSE) && - !g_list_find (dont_inline, cmethod)) { + mono_method_check_inlining (cfg, cmethod) && + !mono_class_is_subclass_of (cmethod->klass, mono_defaults.exception_class, FALSE)) { int costs; - if ((costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, dont_inline, FALSE))) { + if ((costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, FALSE, &bblock))) { cfg->real_offset += 5; - bblock = cfg->cbb; inline_costs += costs - 5; } else { @@ -9795,14 +9805,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b save_cast_details (cfg, klass, sp [0]->dreg, TRUE, &bblock); costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), - iargs, ip, cfg->real_offset, dont_inline, TRUE); + iargs, ip, cfg->real_offset, TRUE, &bblock); reset_cast_details (cfg); CHECK_CFG_EXCEPTION; g_assert (costs > 0); ip += 5; cfg->real_offset += 5; - bblock = cfg->cbb; *sp++ = iargs [0]; @@ -9856,13 +9865,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b iargs [0] = sp [0]; costs = inline_method (cfg, mono_isinst, mono_method_signature (mono_isinst), - iargs, ip, cfg->real_offset, dont_inline, TRUE); + iargs, ip, cfg->real_offset, TRUE, &bblock); CHECK_CFG_EXCEPTION; g_assert (costs > 0); ip += 5; cfg->real_offset += 5; - bblock = cfg->cbb; *sp++= iargs [0]; @@ -9914,13 +9922,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b iargs [0] = sp [0]; costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), - iargs, ip, cfg->real_offset, dont_inline, TRUE); + iargs, ip, cfg->real_offset, TRUE, &bblock); CHECK_CFG_EXCEPTION; g_assert (costs > 0); ip += 5; cfg->real_offset += 5; - bblock = cfg->cbb; *sp++ = iargs [0]; inline_costs += costs; @@ -10202,12 +10209,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (cfg->opt & MONO_OPT_INLINE || cfg->compile_aot) { costs = inline_method (cfg, stfld_wrapper, mono_method_signature (stfld_wrapper), - iargs, ip, cfg->real_offset, dont_inline, TRUE); + iargs, ip, cfg->real_offset, TRUE, &bblock); CHECK_CFG_EXCEPTION; g_assert (costs > 0); cfg->real_offset += 5; - bblock = cfg->cbb; inline_costs += costs; } else { @@ -10266,9 +10272,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b EMIT_NEW_ICONST (cfg, iargs [3], klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset); if (cfg->opt & MONO_OPT_INLINE || cfg->compile_aot) { costs = inline_method (cfg, wrapper, mono_method_signature (wrapper), - iargs, ip, cfg->real_offset, dont_inline, TRUE); + iargs, ip, cfg->real_offset, TRUE, &bblock); CHECK_CFG_EXCEPTION; - bblock = cfg->cbb; g_assert (costs > 0); cfg->real_offset += 5; @@ -12346,7 +12351,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } g_slist_free (class_inits); - dont_inline = g_list_remove (dont_inline, method); + cfg->dont_inline = g_list_remove (cfg->dont_inline, method); if (inline_costs < 0) { char *mname; @@ -12356,6 +12361,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b mono_cfg_set_exception (cfg, MONO_EXCEPTION_INVALID_PROGRAM); cfg->exception_message = g_strdup_printf ("Method %s is too complex.", mname); g_free (mname); + inline_costs = -1; cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header); mono_basic_block_free (original_bb); return -1; @@ -12386,7 +12392,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b cleanup: g_slist_free (class_inits); mono_basic_block_free (original_bb); - dont_inline = g_list_remove (dont_inline, method); + cfg->dont_inline = g_list_remove (cfg->dont_inline, method); cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header); return -1; } diff --git a/mono/mini/mini.c b/mono/mini/mini.c index b5e13dc592b..3224aad4aa3 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -5266,7 +5266,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl /* SSAPRE is not supported on linear IR */ cfg->opt &= ~MONO_OPT_SSAPRE; - i = mono_method_to_ir (cfg, method_to_compile, NULL, NULL, NULL, NULL, NULL, 0, FALSE); + i = mono_method_to_ir (cfg, method_to_compile, NULL, NULL, NULL, NULL, 0, FALSE); if (i < 0) { if (try_generic_shared && cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) { diff --git a/mono/mini/mini.h b/mono/mini/mini.h index f989bc27416..dcc6da1d311 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -1524,6 +1524,7 @@ typedef struct { guint has_atomic_cas_i4 : 1; guint check_pinvoke_callconv : 1; guint has_unwind_info_for_epilog : 1; + guint disable_inline : 1; gpointer debug_info; guint32 lmf_offset; guint16 *intvars; @@ -1540,6 +1541,8 @@ typedef struct { guint32 encoded_unwind_ops_len; GSList* unwind_ops; + GList* dont_inline; + /* Fields used by the local reg allocator */ void* reginfo; int reginfo_len; @@ -2295,7 +2298,7 @@ void mono_tramp_info_register (MonoTrampInfo *info) MONO_INTERNAL; int mini_exception_id_by_name (const char *name) MONO_INTERNAL; int mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, - MonoInst *return_var, GList *dont_inline, MonoInst **inline_args, + MonoInst *return_var, MonoInst **inline_args, guint inline_offset, gboolean is_virtual_call) MONO_INTERNAL; MonoInst *mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) MONO_INTERNAL; From 478f99f39832e29748d6e641608a38df41658d11 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 7 Oct 2014 18:14:04 -0400 Subject: [PATCH 370/543] [threaddpool] Fix deadlock in thread pool with monitor thread Because the monitor thread was not marked as background thread, remove_and_abort_threads (threads.c:2807) would mark it as needed to be waited to shutdown the runtime, and wait_for_tids (threads.c:2652) would then wait indefinitely for it to finish. The issue was that the monitor was waiting on the semaphore monitor_sem, and thus would never exit. Thread 7 (Thread 0x1c13 of process 99776): #0 0x00007fff86590a56 in ?? () from /usr/lib/system/libsystem_kernel.dylib #1 0x00000001003cc03a in mono_sem_wait (sem=0x1004f7f50, alertable=0) at mono-semaphore.c:103 #2 0x00000001002cef41 in monitor_thread (unused=0x0) at threadpool.c:898 #3 0x00000001002cb78f in start_wrapper_internal (data=0x10500abf0) at threads.c:657 #4 0x00000001002cb4a1 in start_wrapper (data=0x10500abf0) at threads.c:704 #5 0x00000001003d61d4 in inner_start_thread (arg=0x7fff5fbfe500) at mono-threads-posix.c:84 #6 0x00007fff8e7c9899 in _pthread_body () from /usr/lib/system/libsystem_pthread.dylib #7 0x00007fff8e7c972a in _pthread_start () from /usr/lib/system/libsystem_pthread.dylib #8 0x00007fff8e7cdfc9 in thread_start () from /usr/lib/system/libsystem_pthread.dylib #9 0x0000000000000000 in ?? () Thread 1 (Thread 0x1503 of process 99776): #0 0x00007fff86594716 in ?? () from /usr/lib/system/libsystem_kernel.dylib #1 0x00007fff8e7cbc3b in _pthread_cond_wait () from /usr/lib/system/libsystem_pthread.dylib #2 0x000000010039cfaa in _wapi_handle_timedwait_signal_handle (handle=0xa55, timeout=0x0, alertable=1, poll=0) at handles.c:1595 #3 0x000000010039d03d in _wapi_handle_wait_signal_handle (handle=0xa55, alertable=1) at handles.c:1540 #4 0x00000001003b7ba3 in WaitForSingleObjectEx (handle=0xa55, timeout=4294967295, alertable=1) at wait.c:194 #5 0x00000001003b865d in WaitForMultipleObjectsEx (numobjects=1, handles=0x7fff5fbff1f8, waitall=1, timeout=4294967295, alertable=1) at wait.c:516 #6 0x00000001002c75df in wait_for_tids (wait=0x7fff5fbff1f8, timeout=4294967295) at threads.c:2658 #7 0x00000001002c70e5 in mono_thread_manage () at threads.c:2951 #8 0x00000001000d551b in mono_main (argc=6, argv=0x7fff5fbff9e8) at driver.c:2021 #9 0x0000000100001bd1 in mono_main_with_options (argc=6, argv=0x7fff5fbff9e8) at ./main.c:91 #10 0x00000001000017d3 in main (argc=6, argv=0x7fff5fbff9e8) at ./main.c:122 --- mono/metadata/threadpool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c index 37c47896683..ab8e7cfeeaf 100644 --- a/mono/metadata/threadpool.c +++ b/mono/metadata/threadpool.c @@ -1190,7 +1190,8 @@ threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs) if (tp->pool_status == 0 && InterlockedCompareExchange (&tp->pool_status, 1, 0) == 0) { if (!tp->is_io) { - mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK); + MonoInternalThread* mt = mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK); + ves_icall_System_Threading_Thread_SetState (mt, ThreadState_Background); threadpool_start_thread (tp); } /* Create on demand up to min_threads to avoid startup penalty for apps that don't use From fbea92153684c2db093a44830818d226fdb17862 Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Tue, 7 Oct 2014 16:18:25 -0700 Subject: [PATCH 371/543] [tests] Add tests for Bug #23058 and polymorphism/known types in DataContractJsonSerializer. --- .../DataContractJsonSerializerTest.cs | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs b/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs index 68d9fb6a083..8a11d70baf1 100644 --- a/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs +++ b/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs @@ -1191,6 +1191,15 @@ private object Deserialize (string xml, Type type, params Type [] knownTypes) return ser.ReadObject (xr); } + public T Deserialize(string json) + { + var bytes = Encoding.Unicode.GetBytes (json); + using (MemoryStream stream = new MemoryStream (bytes)) { + var serializer = new DataContractJsonSerializer (typeof(T)); + return (T)serializer.ReadObject (stream); + } + } + [Test] public void IsStartObject () { @@ -1819,6 +1828,50 @@ public void TestNonCollectionGetOnlyProperty () serializer.WriteObject (stream, o); } + // properly deserialize object with a polymorphic property (known derived type) + [Test] + public void Bug23058() + { + string serializedObj = @"{""PolymorphicProperty"":{""__type"":""KnownDerivedType:#MonoTests.System.Runtime.Serialization.Json"",""BaseTypeProperty"":""Base"",""DerivedProperty"":""Derived 1""},""Name"":""Parent2""}"; + ParentType deserializedObj = Deserialize (serializedObj); + + Assert.AreEqual (deserializedObj.PolymorphicProperty.GetType ().FullName, "MonoTests.System.Runtime.Serialization.Json.KnownDerivedType"); + Assert.AreEqual (deserializedObj.PolymorphicProperty.BaseTypeProperty, "Base"); + Assert.AreEqual ((deserializedObj.PolymorphicProperty as KnownDerivedType).DerivedProperty, "Derived 1"); + Assert.AreEqual (deserializedObj.Name, "Parent2"); + } + + // properly deserialize object with a polymorphic property (base type with __type hint) + [Test] + public void DeserializeBaseTypePropHint() + { + string serializedObj = @"{""PolymorphicProperty"":{""__type"":""BaseType:#MonoTests.System.Runtime.Serialization.Json"",""BaseTypeProperty"":""Base""},""Name"":""Parent2""}"; + ParentType deserializedObj = Deserialize (serializedObj); + + Assert.AreEqual (deserializedObj.PolymorphicProperty.GetType ().FullName, "MonoTests.System.Runtime.Serialization.Json.BaseType"); + Assert.AreEqual (deserializedObj.PolymorphicProperty.BaseTypeProperty, "Base"); + } + + // properly deserialize object with a polymorphic property (base type with __type hint) + [Test] + public void DeserializeBaseTypePropNoHint() + { + string serializedObj = @"{""PolymorphicProperty"":{""BaseTypeProperty"":""Base""},""Name"":""Parent2""}"; + ParentType deserializedObj = Deserialize (serializedObj); + + Assert.AreEqual (deserializedObj.PolymorphicProperty.GetType ().FullName, "MonoTests.System.Runtime.Serialization.Json.BaseType"); + Assert.AreEqual (deserializedObj.PolymorphicProperty.BaseTypeProperty, "Base"); + } + + // properly fail deserializing object with a polymorphic property (unknown derived type) + [ExpectedException (typeof (SerializationException))] + [Test] + public void FailDeserializingUnknownTypeProp() + { + string serializedObj = @"{""PolymorphicProperty"":{""__type"":""UnknownDerivedType:#MonoTests.System.Runtime.Serialization.Json"",""BaseTypeProperty"":""Base"",""DerivedProperty"":""Derived 1""},""Name"":""Parent2""}"; + ParentType deserializedObj = Deserialize (serializedObj); + } + #endregion } @@ -2037,6 +2090,42 @@ void OnDeserialized (StreamingContext c) public long CodedServerTimeUTC { get; set; } public DateTime ServerTimeUTC { get; set; } } + + #region polymorphism test helper classes + + [DataContract] + [KnownType (typeof (KnownDerivedType))] + public class ParentType + { + [DataMember] + public string Name { get; set; } + + [DataMember] + public BaseType PolymorphicProperty { get; set; } + } + + [DataContract] + public class BaseType + { + [DataMember] + public string BaseTypeProperty { get; set; } + } + + [DataContract] + public class KnownDerivedType : BaseType + { + [DataMemberAttribute] + public string DerivedProperty { get; set; } + } + + [DataContract] + public class UnknownDerivedType : BaseType + { + [DataMember] + public string DerivedProperty { get; set; } + } + + #endregion } [DataContract] From 71e152accc727089faffa6b4fd6bf58cb62636cf Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Tue, 7 Oct 2014 16:23:37 -0700 Subject: [PATCH 372/543] [bcl] Implement KnownTypes for DataContractJsonSerializer. Fixes #23058 and polymorphism support. Also discarded old __type hint behavior in JsonSerializationReader that potentially allowed any loaded type to be instantiated. --- .../DataContractJsonSerializer.cs | 14 +++++-- .../JsonSerializationReader.cs | 40 +++++++++++-------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs index 295161932b5..8bb11605edf 100644 --- a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs +++ b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs @@ -84,7 +84,17 @@ public DataContractJsonSerializer (Type type, XmlDictionaryString rootName, IEnu throw new ArgumentOutOfRangeException ("maxItemsInObjectGraph"); this.type = type; - known_types = new ReadOnlyCollection (knownTypes != null ? knownTypes.ToArray () : Type.EmptyTypes); + + var knownTypesFromAttributes = new List (); + + foreach (var attr in type.GetCustomAttributes (typeof(KnownTypeAttribute))) + knownTypesFromAttributes.Add ((attr as KnownTypeAttribute).Type); + + if (knownTypes != null) + knownTypesFromAttributes.AddRange (knownTypes); + + known_types = new ReadOnlyCollection (knownTypesFromAttributes); + root = rootName; max_items = maxItemsInObjectGraph; ignore_extension = ignoreExtensionDataObject; @@ -134,8 +144,6 @@ public IDataContractSurrogate DataContractSurrogate { public bool IgnoreExtensionDataObject { get { return ignore_extension; } } - - [MonoTODO] public ReadOnlyCollection KnownTypes { get { return known_types; } } diff --git a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs index 55d03402ad2..9af14a6cfd5 100644 --- a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs +++ b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs @@ -182,8 +182,18 @@ public object ReadObject (Type type, object instance) if (ct != null) { return DeserializeGenericCollection (type, ct, instance); } else { - TypeMap map = GetTypeMap (type); - return map.Deserialize (this, instance); + string typeHint = reader.GetAttribute ("__type"); + if (typeHint != null) { + // this might be a derived & known type. We allow it when it's both. + Type exactType = GetRuntimeType (typeHint, type); + if (exactType == null) + throw SerializationError (String.Format ("Cannot load type '{0}'", typeHint)); + TypeMap map = GetTypeMap (exactType); + return map.Deserialize (this, instance); + } else { // no type hint + TypeMap map = GetTypeMap (type); + return map.Deserialize (this, instance); + } } } else @@ -198,24 +208,22 @@ object ReadValueType (Type type, bool nullable) } - Type GetRuntimeType (string name) + Type GetRuntimeType (string name, Type baseType) { - name = ToRuntimeTypeName (name); + string properName = ToRuntimeTypeName (name); + + if (baseType != null && baseType.FullName.Equals (properName)) + return baseType; + if (serializer.KnownTypes != null) foreach (Type t in serializer.KnownTypes) - if (t.FullName == name) + if (t.FullName.Equals (properName)) return t; - var ret = root_type.Assembly.GetType (name, false) ?? Type.GetType (name, false); - if (ret != null) - return ret; - // We probably have to iterate all the existing - // assemblies that are loaded in current domain. - foreach (var ass in AppDomain.CurrentDomain.GetAssemblies ()) { - ret = ass.GetType (name, false); - if (ret != null) - return ret; - } + if (baseType != null) + foreach (var attr in baseType.GetCustomAttributes (typeof(KnownTypeAttribute))) + if ((attr as KnownTypeAttribute).Type.FullName.Equals (properName)) + return (attr as KnownTypeAttribute).Type; return null; } @@ -230,7 +238,7 @@ object ReadInstanceDrivenObject () case "object": string runtimeType = reader.GetAttribute ("__type"); if (runtimeType != null) { - Type t = GetRuntimeType (runtimeType); + Type t = GetRuntimeType (runtimeType, null); if (t == null) throw SerializationError (String.Format ("Cannot load type '{0}'", runtimeType)); return ReadObject (t); From c01afa20e8f89ecbea71a4a8bbd18ac60eb1ef2c Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 7 Oct 2014 20:20:58 -0400 Subject: [PATCH 373/543] [jit] Clean up the jit failure handling code a bit, move the the bulk of the eror handling macros into functions, unify the cleanup code at the end of mono_method_to_ir (). --- mono/metadata/class-internals.h | 4 +- mono/mini/method-to-ir.c | 153 +++++++++++++++++++------------- mono/mini/mini.c | 1 + mono/mini/mini.h | 4 +- 4 files changed, 97 insertions(+), 65 deletions(-) diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 32b5ef4561e..2bf904143f1 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -208,8 +208,8 @@ enum { MONO_EXCEPTION_GENERIC_SHARING_FAILED = 11, MONO_EXCEPTION_BAD_IMAGE = 12, MONO_EXCEPTION_OBJECT_SUPPLIED = 13, /*The exception object is already created.*/ - MONO_EXCEPTION_OUT_OF_MEMORY = 14 - /* add other exception type */ + MONO_EXCEPTION_OUT_OF_MEMORY = 14, + MONO_EXCEPTION_INLINE_FAILED = 15 }; /* This struct collects the info needed for the runtime use of a class, diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index fd0ec8b1e72..0890a6df82a 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -71,49 +71,35 @@ #define BRANCH_COST 10 #define INLINE_LENGTH_LIMIT 20 + +/* These have 'cfg' as an implicit argument */ #define INLINE_FAILURE(msg) do { \ - if ((cfg->method != method) && (method->wrapper_type == MONO_WRAPPER_NONE)) { \ - if (cfg->verbose_level >= 2) \ - printf ("inline failed: %s\n", msg); \ - goto inline_failure; \ + if ((cfg->method != cfg->current_method) && (cfg->current_method->wrapper_type == MONO_WRAPPER_NONE)) { \ + inline_failure (cfg, msg); \ + goto exception_exit; \ } \ } while (0) #define CHECK_CFG_EXCEPTION do {\ - if (cfg->exception_type != MONO_EXCEPTION_NONE)\ - goto exception_exit;\ + if (cfg->exception_type != MONO_EXCEPTION_NONE) \ + goto exception_exit; \ } while (0) -#define METHOD_ACCESS_FAILURE do { \ - char *method_fname = mono_method_full_name (method, TRUE); \ - char *cil_method_fname = mono_method_full_name (cil_method, TRUE); \ - mono_cfg_set_exception (cfg, MONO_EXCEPTION_METHOD_ACCESS); \ - cfg->exception_message = g_strdup_printf ("Method `%s' is inaccessible from method `%s'\n", cil_method_fname, method_fname); \ - g_free (method_fname); \ - g_free (cil_method_fname); \ - goto exception_exit; \ +#define METHOD_ACCESS_FAILURE(method, cmethod) do { \ + method_access_failure ((cfg), (method), (cmethod)); \ + goto exception_exit; \ } while (0) -#define FIELD_ACCESS_FAILURE do { \ - char *method_fname = mono_method_full_name (method, TRUE); \ - char *field_fname = mono_field_full_name (field); \ - mono_cfg_set_exception (cfg, MONO_EXCEPTION_FIELD_ACCESS); \ - cfg->exception_message = g_strdup_printf ("Field `%s' is inaccessible from method `%s'\n", field_fname, method_fname); \ - g_free (method_fname); \ - g_free (field_fname); \ +#define FIELD_ACCESS_FAILURE(method, field) do { \ + field_access_failure ((cfg), (method), (field)); \ goto exception_exit; \ } while (0) #define GENERIC_SHARING_FAILURE(opcode) do { \ - if (cfg->generic_sharing_context) { \ - if (cfg->verbose_level > 2) \ - printf ("sharing failed for method %s.%s.%s/%d opcode %s line %d\n", method->klass->name_space, method->klass->name, method->name, method->signature->param_count, mono_opcode_name ((opcode)), __LINE__); \ - mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED); \ + if (cfg->gshared) { \ + gshared_failure (cfg, opcode, __FILE__, __LINE__); \ goto exception_exit; \ } \ } while (0) #define GSHAREDVT_FAILURE(opcode) do { \ if (cfg->gsharedvt) { \ - cfg->exception_message = g_strdup_printf ("gsharedvt failed for method %s.%s.%s/%d opcode %s %s:%d", method->klass->name_space, method->klass->name, method->name, method->signature->param_count, mono_opcode_name ((opcode)), __FILE__, __LINE__); \ - if (cfg->verbose_level >= 2) \ - printf ("%s\n", cfg->exception_message); \ - mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED); \ + gsharedvt_failure (cfg, opcode, __FILE__, __LINE__); \ goto exception_exit; \ } \ } while (0) @@ -126,6 +112,16 @@ printf ("AOT disabled: %s:%d\n", __FILE__, __LINE__); \ (cfg)->disable_aot = TRUE; \ } while (0) +#define LOAD_ERROR do { \ + break_on_unverified (); \ + mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD); \ + goto exception_exit; \ + } while (0) + +#define TYPE_LOAD_ERROR(klass) do { \ + cfg->exception_ptr = klass; \ + LOAD_ERROR; \ + } while (0) /* Determine whenever 'ins' represents a load of the 'this' argument */ #define MONO_CHECK_THIS(ins) (mono_method_signature (cfg->method)->hasthis && ((ins)->opcode == OP_MOVE) && ((ins)->sreg1 == cfg->args [0]->dreg)) @@ -367,6 +363,60 @@ mono_create_helper_signatures (void) helper_sig_monitor_enter_exit_trampoline_llvm = mono_create_icall_signature ("void object"); } +static MONO_NEVER_INLINE void +break_on_unverified (void) +{ + if (mini_get_debug_options ()->break_on_unverified) + G_BREAKPOINT (); +} + +static MONO_NEVER_INLINE void +method_access_failure (MonoCompile *cfg, MonoMethod *method, MonoMethod *cil_method) +{ + char *method_fname = mono_method_full_name (method, TRUE); + char *cil_method_fname = mono_method_full_name (cil_method, TRUE); + mono_cfg_set_exception (cfg, MONO_EXCEPTION_METHOD_ACCESS); + cfg->exception_message = g_strdup_printf ("Method `%s' is inaccessible from method `%s'\n", cil_method_fname, method_fname); + g_free (method_fname); + g_free (cil_method_fname); +} + +static MONO_NEVER_INLINE void +field_access_failure (MonoCompile *cfg, MonoMethod *method, MonoClassField *field) +{ + char *method_fname = mono_method_full_name (method, TRUE); + char *field_fname = mono_field_full_name (field); + mono_cfg_set_exception (cfg, MONO_EXCEPTION_FIELD_ACCESS); + cfg->exception_message = g_strdup_printf ("Field `%s' is inaccessible from method `%s'\n", field_fname, method_fname); + g_free (method_fname); + g_free (field_fname); +} + +static MONO_NEVER_INLINE void +inline_failure (MonoCompile *cfg, const char *msg) +{ + if (cfg->verbose_level >= 2) + printf ("inline failed: %s\n", msg); + mono_cfg_set_exception (cfg, MONO_EXCEPTION_INLINE_FAILED); +} + +static MONO_NEVER_INLINE void +gshared_failure (MonoCompile *cfg, int opcode, const char *file, int line) +{ + if (cfg->verbose_level > 2) \ + printf ("sharing failed for method %s.%s.%s/%d opcode %s line %d\n", cfg->current_method->klass->name_space, cfg->current_method->klass->name, cfg->current_method->name, cfg->current_method->signature->param_count, mono_opcode_name ((opcode)), __LINE__); + mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED); +} + +static MONO_NEVER_INLINE void +gsharedvt_failure (MonoCompile *cfg, int opcode, const char *file, int line) +{ + cfg->exception_message = g_strdup_printf ("gsharedvt failed for method %s.%s.%s/%d opcode %s %s:%d", cfg->current_method->klass->name_space, cfg->current_method->klass->name, cfg->current_method->name, cfg->current_method->signature->param_count, mono_opcode_name ((opcode)), file, line); + if (cfg->verbose_level >= 2) + printf ("%s\n", cfg->exception_message); + mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED); +} + /* * When using gsharedvt, some instatiations might be verifiable, and some might be not. i.e. * foo (int i) { ldarg.0; box T; } @@ -378,16 +428,10 @@ mono_create_helper_signatures (void) mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED); \ goto exception_exit; \ } \ - if (mini_get_debug_options ()->break_on_unverified) \ - G_BREAKPOINT (); \ - else \ - goto unverified; \ + break_on_unverified (); \ + goto unverified; \ } while (0) -#define LOAD_ERROR do { if (mini_get_debug_options ()->break_on_unverified) G_BREAKPOINT (); else goto load_error; } while (0) - -#define TYPE_LOAD_ERROR(klass) do { if (mini_get_debug_options ()->break_on_unverified) G_BREAKPOINT (); else { cfg->exception_ptr = klass; goto load_error; } } while (0) - #define GET_BBLOCK(cfg,tblock,ip) do { \ (tblock) = cfg->cil_offset_to_bb [(ip) - cfg->cil_start]; \ if (!(tblock)) { \ @@ -6242,7 +6286,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, #define CHECK_LOCAL(num) if ((unsigned)(num) >= (unsigned)header->num_locals) UNVERIFIED #define CHECK_OPSIZE(size) if (ip + size > end) UNVERIFIED #define CHECK_UNVERIFIABLE(cfg) if (cfg->unverifiable) UNVERIFIED -#define CHECK_TYPELOAD(klass) if (!(klass) || (klass)->exception_type) {cfg->exception_ptr = klass; LOAD_ERROR;} +#define CHECK_TYPELOAD(klass) if (!(klass) || (klass)->exception_type) TYPE_LOAD_ERROR ((klass)) /* offset from br.s -> br like opcodes */ #define BIG_BRANCH_OFFSET 13 @@ -6664,7 +6708,7 @@ emit_optimized_ldloca_ir (MonoCompile *cfg, unsigned char *ip, unsigned char *en emit_init_local (cfg, local, type, TRUE); return ip + 6; } -load_error: + exception_exit: return NULL; } @@ -7961,7 +8005,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } if (!mono_method_can_access_method (method_definition, target_method) && !mono_method_can_access_method (method, cil_method)) - METHOD_ACCESS_FAILURE; + METHOD_ACCESS_FAILURE (method, cil_method); } if (mono_security_core_clr_enabled ()) @@ -10148,7 +10192,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (!field) LOAD_ERROR; if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_field (method, field)) - FIELD_ACCESS_FAILURE; + FIELD_ACCESS_FAILURE (method, field); mono_class_init (klass); if (is_instance && *ip != CEE_LDFLDA && is_magic_tls_access (field)) @@ -11761,7 +11805,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b cil_method = cmethod; if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod)) - METHOD_ACCESS_FAILURE; + METHOD_ACCESS_FAILURE (method, cil_method); if (mono_security_cas_enabled ()) { if (check_linkdemand (cfg, method, cmethod)) @@ -11985,7 +12029,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b * stack overflows which is different behavior than the * non-inlined case, thus disable inlining in this case. */ - goto inline_failure; + INLINE_FAILURE("localloc"); MONO_INST_NEW (cfg, ins, OP_LOCALLOC); ins->dreg = alloc_preg (cfg); @@ -12350,9 +12394,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } } - g_slist_free (class_inits); - cfg->dont_inline = g_list_remove (cfg->dont_inline, method); - if (inline_costs < 0) { char *mname; @@ -12361,30 +12402,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b mono_cfg_set_exception (cfg, MONO_EXCEPTION_INVALID_PROGRAM); cfg->exception_message = g_strdup_printf ("Method %s is too complex.", mname); g_free (mname); - inline_costs = -1; - cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header); - mono_basic_block_free (original_bb); - return -1; } if ((cfg->verbose_level > 2) && (cfg->method == method)) mono_print_code (cfg, "AFTER METHOD-TO-IR"); - cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header); - mono_basic_block_free (original_bb); - return inline_costs; + goto cleanup; exception_exit: g_assert (cfg->exception_type != MONO_EXCEPTION_NONE); goto cleanup; - inline_failure: - goto cleanup; - - load_error: - mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD); - goto cleanup; - unverified: set_exception_type_from_invalid_il (cfg, method, ip); goto cleanup; @@ -12394,7 +12422,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b mono_basic_block_free (original_bb); cfg->dont_inline = g_list_remove (cfg->dont_inline, method); cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header); - return -1; + if (cfg->exception_type) + return -1; + else + return inline_costs; } static int diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 3224aad4aa3..6b4d8bfddad 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -5033,6 +5033,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl if (cfg->generic_sharing_context) { method_to_register = method_to_compile; + cfg->gshared = TRUE; } else { g_assert (method == method_to_compile); method_to_register = method; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index dcc6da1d311..d507b960ef6 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -1426,8 +1426,6 @@ typedef struct { MonoGenericSharingContext gsctx; MonoGenericContext *gsctx_context; - gboolean gsharedvt; - MonoGSharedVtMethodInfo *gsharedvt_info; /* Points to the gsharedvt locals area at runtime */ @@ -1525,6 +1523,8 @@ typedef struct { guint check_pinvoke_callconv : 1; guint has_unwind_info_for_epilog : 1; guint disable_inline : 1; + guint gshared : 1; + guint gsharedvt : 1; gpointer debug_info; guint32 lmf_offset; guint16 *intvars; From f51b9a4bb2d65e7b6102df9ebee39e3cd1463ca0 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 7 Oct 2014 20:44:28 -0400 Subject: [PATCH 374/543] [jit] Extract the ctor calling code from the NEWOBJ implementation into a separate function. --- mono/mini/method-to-ir.c | 167 +++++++++++++++++++++------------------ 1 file changed, 88 insertions(+), 79 deletions(-) diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 0890a6df82a..6f757ff8e97 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -6905,6 +6905,90 @@ create_magic_tls_access (MonoCompile *cfg, MonoClassField *tls_field, MonoInst * return addr; } +/* + * handle_ctor_call: + * + * Handle calls made to ctors from NEWOBJ opcodes. + * + * REF_BBLOCK will point to the current bblock after the call. + */ +static void +handle_ctor_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, int context_used, + MonoInst **sp, guint8 *ip, MonoBasicBlock **ref_bblock, int *inline_costs) +{ + MonoInst *vtable_arg = NULL, *callvirt_this_arg = NULL, *ins; + MonoBasicBlock *bblock = *ref_bblock; + + if (cmethod->klass->valuetype && mono_class_generic_sharing_enabled (cmethod->klass) && + mono_method_is_generic_sharable (cmethod, TRUE)) { + if (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst) { + mono_class_vtable (cfg->domain, cmethod->klass); + CHECK_TYPELOAD (cmethod->klass); + + vtable_arg = emit_get_rgctx_method (cfg, context_used, + cmethod, MONO_RGCTX_INFO_METHOD_RGCTX); + } else { + if (context_used) { + vtable_arg = emit_get_rgctx_klass (cfg, context_used, + cmethod->klass, MONO_RGCTX_INFO_VTABLE); + } else { + MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass); + + CHECK_TYPELOAD (cmethod->klass); + EMIT_NEW_VTABLECONST (cfg, vtable_arg, vtable); + } + } + } + + /* Avoid virtual calls to ctors if possible */ + if (mono_class_is_marshalbyref (cmethod->klass)) + callvirt_this_arg = sp [0]; + + if (cmethod && (cfg->opt & MONO_OPT_INTRINS) && (ins = mini_emit_inst_for_ctor (cfg, cmethod, fsig, sp))) { + g_assert (MONO_TYPE_IS_VOID (fsig->ret)); + CHECK_CFG_EXCEPTION; + } else if ((cfg->opt & MONO_OPT_INLINE) && cmethod && !context_used && !vtable_arg && + mono_method_check_inlining (cfg, cmethod) && + !mono_class_is_subclass_of (cmethod->klass, mono_defaults.exception_class, FALSE)) { + int costs; + + if ((costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, FALSE, &bblock))) { + cfg->real_offset += 5; + + *inline_costs += costs - 5; + *ref_bblock = bblock; + } else { + INLINE_FAILURE ("inline failure"); + // FIXME-VT: Clean this up + if (cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig)) + GSHAREDVT_FAILURE(*ip); + mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, callvirt_this_arg, NULL, NULL); + } + } else if (cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig)) { + MonoInst *addr; + + addr = emit_get_rgctx_gsharedvt_call (cfg, context_used, fsig, cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE); + mono_emit_calli (cfg, fsig, sp, addr, NULL, vtable_arg); + } else if (context_used && + ((!mono_method_is_generic_sharable_full (cmethod, TRUE, FALSE, FALSE) || + !mono_class_generic_sharing_enabled (cmethod->klass)) || cfg->gsharedvt)) { + MonoInst *cmethod_addr; + + /* Generic calls made out of gsharedvt methods cannot be patched, so use an indirect call */ + + cmethod_addr = emit_get_rgctx_method (cfg, context_used, + cmethod, MONO_RGCTX_INFO_GENERIC_METHOD_CODE); + + mono_emit_calli (cfg, fsig, sp, cmethod_addr, NULL, vtable_arg); + } else { + INLINE_FAILURE ("ctor call"); + ins = mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, + callvirt_this_arg, NULL, vtable_arg); + } + exception_exit: + return; +} + /* * mono_method_to_ir: * @@ -9612,27 +9696,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } */ - if (cmethod->klass->valuetype && mono_class_generic_sharing_enabled (cmethod->klass) && - mono_method_is_generic_sharable (cmethod, TRUE)) { - if (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst) { - mono_class_vtable (cfg->domain, cmethod->klass); - CHECK_TYPELOAD (cmethod->klass); - - vtable_arg = emit_get_rgctx_method (cfg, context_used, - cmethod, MONO_RGCTX_INFO_METHOD_RGCTX); - } else { - if (context_used) { - vtable_arg = emit_get_rgctx_klass (cfg, context_used, - cmethod->klass, MONO_RGCTX_INFO_VTABLE); - } else { - MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass); - - CHECK_TYPELOAD (cmethod->klass); - EMIT_NEW_VTABLECONST (cfg, vtable_arg, vtable); - } - } - } - n = fsig->param_count; CHECK_STACK (n); @@ -9646,8 +9709,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b ((n < 2) || (!fsig->params [1]->byref && fsig->params [1]->type == MONO_TYPE_STRING))) { MonoInst *iargs [3]; - g_assert (!vtable_arg); - sp -= n; EMIT_NEW_ICONST (cfg, iargs [0], cmethod->klass->type_token); @@ -9688,8 +9749,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b iargs [0] = NULL; if (mini_class_is_system_array (cmethod->klass)) { - g_assert (!vtable_arg); - *sp = emit_get_rgctx_method (cfg, context_used, cmethod, MONO_RGCTX_INFO_METHOD); @@ -9712,8 +9771,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b /* now call the string ctor */ alloc = mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, NULL, NULL, NULL); } else { - MonoInst* callvirt_this_arg = NULL; - if (cmethod->klass->valuetype) { iargs [0] = mono_compile_create_var (cfg, &cmethod->klass->byval_arg, OP_LOCAL); emit_init_rvar (cfg, iargs [0]->dreg, &cmethod->klass->byval_arg); @@ -9757,56 +9814,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MONO_EMIT_NEW_UNALU (cfg, OP_NOT_NULL, -1, alloc->dreg); /* Now call the actual ctor */ - /* Avoid virtual calls to ctors if possible */ - if (mono_class_is_marshalbyref (cmethod->klass)) - callvirt_this_arg = sp [0]; - - - if (cmethod && (cfg->opt & MONO_OPT_INTRINS) && (ins = mini_emit_inst_for_ctor (cfg, cmethod, fsig, sp))) { - if (!MONO_TYPE_IS_VOID (fsig->ret)) { - type_to_eval_stack_type ((cfg), fsig->ret, ins); - *sp = ins; - sp++; - } - - CHECK_CFG_EXCEPTION; - } else if ((cfg->opt & MONO_OPT_INLINE) && cmethod && !context_used && !vtable_arg && - mono_method_check_inlining (cfg, cmethod) && - !mono_class_is_subclass_of (cmethod->klass, mono_defaults.exception_class, FALSE)) { - int costs; - - if ((costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, FALSE, &bblock))) { - cfg->real_offset += 5; - - inline_costs += costs - 5; - } else { - INLINE_FAILURE ("inline failure"); - // FIXME-VT: Clean this up - if (cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig)) - GSHAREDVT_FAILURE(*ip); - mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, callvirt_this_arg, NULL, NULL); - } - } else if (cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig)) { - MonoInst *addr; - - addr = emit_get_rgctx_gsharedvt_call (cfg, context_used, fsig, cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE); - mono_emit_calli (cfg, fsig, sp, addr, NULL, vtable_arg); - } else if (context_used && - ((!mono_method_is_generic_sharable_full (cmethod, TRUE, FALSE, FALSE) || - !mono_class_generic_sharing_enabled (cmethod->klass)) || cfg->gsharedvt)) { - MonoInst *cmethod_addr; - - /* Generic calls made out of gsharedvt methods cannot be patched, so use an indirect call */ - - cmethod_addr = emit_get_rgctx_method (cfg, context_used, - cmethod, MONO_RGCTX_INFO_GENERIC_METHOD_CODE); - - mono_emit_calli (cfg, fsig, sp, cmethod_addr, NULL, vtable_arg); - } else { - INLINE_FAILURE ("ctor call"); - ins = mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, - callvirt_this_arg, NULL, vtable_arg); - } + handle_ctor_call (cfg, cmethod, fsig, context_used, sp, ip, &bblock, &inline_costs); + CHECK_CFG_EXCEPTION; } if (alloc == NULL) { @@ -9814,9 +9823,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b EMIT_NEW_TEMPLOAD (cfg, ins, iargs [0]->inst_c0); type_to_eval_stack_type (cfg, &ins->klass->byval_arg, ins); *sp++= ins; - } - else + } else { *sp++ = alloc; + } ip += 5; inline_costs += 5; From 7e034defbc8f1b3f9583ce9d6ea5afd718025689 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 8 Oct 2014 10:41:14 +0100 Subject: [PATCH 375/543] Test that BlockingCollection.Add blocks when there is no more space. --- .../BlockingCollectionTests.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs b/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs index b33a5b4385f..995dfdc1a91 100644 --- a/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs +++ b/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs @@ -247,6 +247,19 @@ public void TakeAnyCancellable () Assert.AreEqual (-10, t.Result, "#5"); Assert.AreEqual ("canceled", res, "#6"); } + + [Test, ExpectedException (typeof(OperationCanceledException))] + public void BoundedAddLimit () + { + const int elNumber = 5; + + var c = new BlockingCollection (elNumber); + var token = new CancellationTokenSource (100); + + for (var i = 0; i < elNumber + 1; i++) { + c.Add (1, token.Token); + } + } } } #endif From 00c918e0a95d9cd5f2efd004ef184794f5a7ddb4 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 8 Oct 2014 11:51:59 +0100 Subject: [PATCH 376/543] BlockingCollection.Add was adding one more item than it should. --- .../BlockingCollection.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs b/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs index 893cd8e3a46..951935846fb 100644 --- a/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs +++ b/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs @@ -124,8 +124,12 @@ public bool TryAdd (T item, int millisecondsTimeout, CancellationToken cancellat int cachedRemoveId = removeId; int itemsIn = cachedAddId - cachedRemoveId; + // Check our transaction id against completed stored one + if (isComplete.Value && cachedAddId >= completeId) + ThrowCompleteException (); + // If needed, we check and wait that the collection isn't full - if (upperBound != -1 && itemsIn > upperBound) { + if (upperBound != -1 && itemsIn >= upperBound) { if (millisecondsTimeout == 0) return false; @@ -144,10 +148,6 @@ public bool TryAdd (T item, int millisecondsTimeout, CancellationToken cancellat continue; } - // Check our transaction id against completed stored one - if (isComplete.Value && cachedAddId >= completeId) - ThrowCompleteException (); - // Validate the steps we have been doing until now if (Interlocked.CompareExchange (ref addId, cachedAddId + 1, cachedAddId) != cachedAddId) continue; From 0e13745ec23511afa333ad61adbfededfa2fe9bc Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 8 Oct 2014 11:58:26 +0100 Subject: [PATCH 377/543] Test BlockCollection.AddAny. Covers #22775. --- .../BlockingCollectionTests.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs b/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs index 995dfdc1a91..bf41aeee21a 100644 --- a/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs +++ b/mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs @@ -260,6 +260,27 @@ public void BoundedAddLimit () c.Add (1, token.Token); } } + + [Test] + public void AddAnyCancellable () + { + const int elNumber = 5; + const int colNumber = 5; + + var cols = new BlockingCollection [colNumber]; + for (var i = 0; i < colNumber; i++) { + cols[i] = new BlockingCollection (elNumber); + } + + var token = new CancellationTokenSource (100); + for (var i = 0; i < colNumber * elNumber; i++) { + BlockingCollection .AddToAny (cols, 1, token.Token); + } + + foreach (var col in cols) { + Assert.AreEqual (elNumber, col.Count); + } + } } } #endif From 7724a608a53415dba5c7a25aab7800b8d54745c3 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 8 Oct 2014 12:16:36 +0100 Subject: [PATCH 378/543] Improved BlockingCollection.AddAny. Fixes #22775. AddAny no longer consumes OperationCanceledException. AddAny no longer blocks while adding an item to the first collection when its full. --- .../BlockingCollection.cs | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs b/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs index 951935846fb..7d942b8d7d5 100644 --- a/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs +++ b/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs @@ -292,29 +292,40 @@ static bool IsThereANullElement (BlockingCollection[] collections) public static int AddToAny (BlockingCollection[] collections, T item) { CheckArray (collections); - int index = 0; - foreach (var coll in collections) { - try { - coll.Add (item); - return index; - } catch {} - index++; + WaitHandle[] wait_table = null; + while (true) { + for (int i = 0; i < collections.Length; ++i) { + if (collections [i].TryAdd (item)) + return i; + } + if (wait_table == null) { + wait_table = new WaitHandle [collections.Length]; + for (int i = 0; i < collections.Length; ++i) + wait_table [i] = collections [i].mreAdd.WaitHandle; + } + WaitHandle.WaitAny (wait_table); } - return -1; } public static int AddToAny (BlockingCollection[] collections, T item, CancellationToken cancellationToken) { CheckArray (collections); - int index = 0; - foreach (var coll in collections) { - try { - coll.Add (item, cancellationToken); - return index; - } catch {} - index++; + WaitHandle[] wait_table = null; + while (true) { + for (int i = 0; i < collections.Length; ++i) { + if (collections [i].TryAdd (item)) + return i; + } + cancellationToken.ThrowIfCancellationRequested (); + if (wait_table == null) { + wait_table = new WaitHandle [collections.Length + 1]; + for (int i = 0; i < collections.Length; ++i) + wait_table [i] = collections [i].mreAdd.WaitHandle; + wait_table [collections.Length] = cancellationToken.WaitHandle; + } + WaitHandle.WaitAny (wait_table); + cancellationToken.ThrowIfCancellationRequested (); } - return -1; } public static int TryAddToAny (BlockingCollection[] collections, T item) From 54844b08ef4299e66a64d02a71c07c25a8963dd8 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 8 Oct 2014 12:59:42 +0100 Subject: [PATCH 379/543] Refactored AddToAny and TakeFromAny to reuse code. --- .../BlockingCollection.cs | 31 ++----------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs b/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs index 7d942b8d7d5..395bc68e96d 100644 --- a/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs +++ b/mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs @@ -291,20 +291,7 @@ static bool IsThereANullElement (BlockingCollection[] collections) public static int AddToAny (BlockingCollection[] collections, T item) { - CheckArray (collections); - WaitHandle[] wait_table = null; - while (true) { - for (int i = 0; i < collections.Length; ++i) { - if (collections [i].TryAdd (item)) - return i; - } - if (wait_table == null) { - wait_table = new WaitHandle [collections.Length]; - for (int i = 0; i < collections.Length; ++i) - wait_table [i] = collections [i].mreAdd.WaitHandle; - } - WaitHandle.WaitAny (wait_table); - } + return AddToAny (collections, item, CancellationToken.None); } public static int AddToAny (BlockingCollection[] collections, T item, CancellationToken cancellationToken) @@ -379,21 +366,7 @@ public static int TryAddToAny (BlockingCollection[] collections, T item, int public static int TakeFromAny (BlockingCollection[] collections, out T item) { - item = default (T); - CheckArray (collections); - WaitHandle[] wait_table = null; - while (true) { - for (int i = 0; i < collections.Length; ++i) { - if (collections [i].TryTake (out item)) - return i; - } - if (wait_table == null) { - wait_table = new WaitHandle [collections.Length]; - for (int i = 0; i < collections.Length; ++i) - wait_table [i] = collections [i].mreRemove.WaitHandle; - } - WaitHandle.WaitAny (wait_table); - } + return TakeFromAny (collections, out item, CancellationToken.None); } public static int TakeFromAny (BlockingCollection[] collections, out T item, CancellationToken cancellationToken) From 98ce3f76b2a0d8c02da05f5733a721797959ff11 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 8 Oct 2014 13:52:55 -0400 Subject: [PATCH 380/543] [threaddpool] Fix deadlock in thread pool with monitor thread (2nd attempt) Because the monitor thread was not marked as background thread, remove_and_abort_threads (threads.c:2807) would mark it as needed to be waited to shutdown the runtime, and wait_for_tids (threads.c:2652) would then wait indefinitely for it to finish. The issue was that the monitor was waiting on the semaphore monitor_sem, and thus would never exit. Thread 7 (Thread 0x1c13 of process 99776): #0 0x00007fff86590a56 in ?? () from /usr/lib/system/libsystem_kernel.dylib #1 0x00000001003cc03a in mono_sem_wait (sem=0x1004f7f50, alertable=0) at mono-semaphore.c:103 #2 0x00000001002cef41 in monitor_thread (unused=0x0) at threadpool.c:898 #3 0x00000001002cb78f in start_wrapper_internal (data=0x10500abf0) at threads.c:657 #4 0x00000001002cb4a1 in start_wrapper (data=0x10500abf0) at threads.c:704 #5 0x00000001003d61d4 in inner_start_thread (arg=0x7fff5fbfe500) at mono-threads-posix.c:84 #6 0x00007fff8e7c9899 in _pthread_body () from /usr/lib/system/libsystem_pthread.dylib #7 0x00007fff8e7c972a in _pthread_start () from /usr/lib/system/libsystem_pthread.dylib #8 0x00007fff8e7cdfc9 in thread_start () from /usr/lib/system/libsystem_pthread.dylib #9 0x0000000000000000 in ?? () Thread 1 (Thread 0x1503 of process 99776): #0 0x00007fff86594716 in ?? () from /usr/lib/system/libsystem_kernel.dylib #1 0x00007fff8e7cbc3b in _pthread_cond_wait () from /usr/lib/system/libsystem_pthread.dylib #2 0x000000010039cfaa in _wapi_handle_timedwait_signal_handle (handle=0xa55, timeout=0x0, alertable=1, poll=0) at handles.c:1595 #3 0x000000010039d03d in _wapi_handle_wait_signal_handle (handle=0xa55, alertable=1) at handles.c:1540 #4 0x00000001003b7ba3 in WaitForSingleObjectEx (handle=0xa55, timeout=4294967295, alertable=1) at wait.c:194 #5 0x00000001003b865d in WaitForMultipleObjectsEx (numobjects=1, handles=0x7fff5fbff1f8, waitall=1, timeout=4294967295, alertable=1) at wait.c:516 #6 0x00000001002c75df in wait_for_tids (wait=0x7fff5fbff1f8, timeout=4294967295) at threads.c:2658 #7 0x00000001002c70e5 in mono_thread_manage () at threads.c:2951 #8 0x00000001000d551b in mono_main (argc=6, argv=0x7fff5fbff9e8) at driver.c:2021 #9 0x0000000100001bd1 in mono_main_with_options (argc=6, argv=0x7fff5fbff9e8) at ./main.c:91 #10 0x00000001000017d3 in main (argc=6, argv=0x7fff5fbff9e8) at ./main.c:122 Thanks @akoeplinger for the help debugging --- mono/metadata/threadpool.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c index ab8e7cfeeaf..02acb073a85 100644 --- a/mono/metadata/threadpool.c +++ b/mono/metadata/threadpool.c @@ -165,6 +165,7 @@ static gboolean suspended; static volatile gint32 monitor_njobs = 0; static volatile gint32 monitor_state; static MonoSemType monitor_sem; +static MonoInternalThread *monitor_internal_thread; /* Hooks */ static MonoThreadPoolFunc tp_start_func; @@ -1190,8 +1191,8 @@ threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs) if (tp->pool_status == 0 && InterlockedCompareExchange (&tp->pool_status, 1, 0) == 0) { if (!tp->is_io) { - MonoInternalThread* mt = mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK); - ves_icall_System_Threading_Thread_SetState (mt, ThreadState_Background); + monitor_internal_thread = mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK); + monitor_internal_thread->flags |= MONO_THREAD_FLAG_DONT_MANAGE; threadpool_start_thread (tp); } /* Create on demand up to min_threads to avoid startup penalty for apps that don't use From c33600f57d9b95b047b65b9522da984d97d2eeab Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 8 Oct 2014 15:12:26 -0400 Subject: [PATCH 381/543] [bcl] Free strings allocated using Marshal.SecureStringToBSTR () using Marshal.ZeroFreeBSTR (). --- mcs/class/System/System.Diagnostics/Process.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mcs/class/System/System.Diagnostics/Process.cs b/mcs/class/System/System.Diagnostics/Process.cs index 795ebaaa80f..ef042e905cf 100644 --- a/mcs/class/System/System.Diagnostics/Process.cs +++ b/mcs/class/System/System.Diagnostics/Process.cs @@ -940,7 +940,7 @@ private static bool Start_shell (ProcessStartInfo startInfo, Process process) ref proc_info); } finally { if (proc_info.Password != IntPtr.Zero) - Marshal.FreeBSTR (proc_info.Password); + Marshal.ZeroFreeBSTR (proc_info.Password); proc_info.Password = IntPtr.Zero; } if (!ret) { @@ -1080,7 +1080,7 @@ private static bool Start_noshell (ProcessStartInfo startInfo, ref proc_info); } finally { if (proc_info.Password != IntPtr.Zero) - Marshal.FreeBSTR (proc_info.Password); + Marshal.ZeroFreeBSTR (proc_info.Password); proc_info.Password = IntPtr.Zero; } if (!ret) { From 17edd267ab7d8bf9204b688a9f538df79127d1dd Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 8 Oct 2014 16:12:01 -0400 Subject: [PATCH 382/543] [bcl] Use List instead of ArrayList () in a few places. --- .../System/System.Diagnostics/LocalFileEventLog.cs | 7 +++---- mcs/class/System/System.Diagnostics/Process.cs | 12 ++++++------ mcs/class/System/System.Diagnostics/Win32EventLog.cs | 7 +++---- mcs/class/System/System.IO/DefaultWatcher.cs | 7 ++++--- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/mcs/class/System/System.Diagnostics/LocalFileEventLog.cs b/mcs/class/System/System.Diagnostics/LocalFileEventLog.cs index e5a34ff1a41..c013223d081 100644 --- a/mcs/class/System/System.Diagnostics/LocalFileEventLog.cs +++ b/mcs/class/System/System.Diagnostics/LocalFileEventLog.cs @@ -29,7 +29,7 @@ // using System; -using System.Collections; +using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; @@ -227,7 +227,7 @@ protected override EventLogEntry GetEntry (int index) DateFormat, CultureInfo.InvariantCulture); DateTime timeWritten = File.GetLastWriteTime (file); int stringNums = int.Parse (tr.ReadLine ().Substring (20)); - ArrayList replacementTemp = new ArrayList (); + var replacementTemp = new List (); StringBuilder sb = new StringBuilder (); while (replacementTemp.Count < stringNums) { char c = (char) tr.Read (); @@ -238,8 +238,7 @@ protected override EventLogEntry GetEntry (int index) sb.Append (c); } } - string [] replacementStrings = new string [replacementTemp.Count]; - replacementTemp.CopyTo (replacementStrings, 0); + string [] replacementStrings = replacementTemp.ToArray (); string message = FormatMessage (source, instanceID, replacementStrings); int eventID = EventLog.GetEventID (instanceID); diff --git a/mcs/class/System/System.Diagnostics/Process.cs b/mcs/class/System/System.Diagnostics/Process.cs index ef042e905cf..0cf197af1dc 100644 --- a/mcs/class/System/System.Diagnostics/Process.cs +++ b/mcs/class/System/System.Diagnostics/Process.cs @@ -39,7 +39,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.Permissions; -using System.Collections; +using System.Collections.Generic; using System.Security; using System.Threading; @@ -832,13 +832,13 @@ public static Process GetProcessById(int processId, string machineName) { [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static int[] GetProcesses_internal(); - public static Process[] GetProcesses() + public static Process[] GetProcesses () { int [] pids = GetProcesses_internal (); if (pids == null) return new Process [0]; - ArrayList proclist = new ArrayList (pids.Length); + var proclist = new List (pids.Length); for (int i = 0; i < pids.Length; i++) { try { proclist.Add (GetProcessById (pids [i])); @@ -851,7 +851,7 @@ public static Process[] GetProcesses() } } - return ((Process []) proclist.ToArray (typeof (Process))); + return proclist.ToArray (); } [MonoTODO ("There is no support for retrieving process information from a remote machine")] @@ -871,7 +871,7 @@ public static Process[] GetProcessesByName(string processName) if (pids == null) return new Process [0]; - ArrayList proclist = new ArrayList (pids.Length); + var proclist = new List (pids.Length); for (int i = 0; i < pids.Length; i++) { try { Process p = GetProcessById (pids [i]); @@ -886,7 +886,7 @@ public static Process[] GetProcessesByName(string processName) } } - return ((Process []) proclist.ToArray (typeof (Process))); + return proclist.ToArray (); } [MonoTODO] diff --git a/mcs/class/System/System.Diagnostics/Win32EventLog.cs b/mcs/class/System/System.Diagnostics/Win32EventLog.cs index 40fe3a36b15..4002c3b7cdc 100644 --- a/mcs/class/System/System.Diagnostics/Win32EventLog.cs +++ b/mcs/class/System/System.Diagnostics/Win32EventLog.cs @@ -28,7 +28,7 @@ // using System; -using System.Collections; +using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; @@ -177,12 +177,11 @@ public override void DeleteEventSource (string source, string machineName) string [] sources = (string []) logKey.GetValue ("Sources"); if (sources != null) { - ArrayList temp = new ArrayList (); + var temp = new List (); for (int i = 0; i < sources.Length; i++) if (sources [i] != source) temp.Add (sources [i]); - string [] newSources = new string [temp.Count]; - temp.CopyTo (newSources, 0); + string [] newSources = temp.ToArray (); logKey.SetValue ("Sources", newSources); } } diff --git a/mcs/class/System/System.IO/DefaultWatcher.cs b/mcs/class/System/System.IO/DefaultWatcher.cs index 8988a6b9703..d2d8b28d86c 100644 --- a/mcs/class/System/System.IO/DefaultWatcher.cs +++ b/mcs/class/System/System.IO/DefaultWatcher.cs @@ -30,6 +30,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.IO; using System.Threading; @@ -240,12 +241,12 @@ void DoFiles (DefaultWatcherData data, string directory, bool dispatch) return; /* Removed files */ - ArrayList removed = null; + List removed = null; foreach (string filename in data.Files.Keys) { FileData fd = (FileData) data.Files [filename]; if (fd.NotExists) { if (removed == null) - removed = new ArrayList (); + removed = new List (); removed.Add (filename); DispatchEvents (data.FSW, FileAction.Removed, filename); @@ -269,7 +270,7 @@ void DoFiles (DefaultWatcherData data, string directory, bool dispatch) } catch { /* Deleted */ if (removed == null) - removed = new ArrayList (); + removed = new List (); removed.Add (filename); DispatchEvents (data.FSW, FileAction.Removed, filename); From e92af122487b75438610c5154efc9202adf0f949 Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Wed, 8 Oct 2014 22:04:34 -0700 Subject: [PATCH 383/543] Fix oops in DataContractJsonSerializer fix --- .../DataContractJsonSerializer.cs | 2 +- .../JsonSerializationReader.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs index 8bb11605edf..8ae0ce57356 100644 --- a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs +++ b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs @@ -87,7 +87,7 @@ public DataContractJsonSerializer (Type type, XmlDictionaryString rootName, IEnu var knownTypesFromAttributes = new List (); - foreach (var attr in type.GetCustomAttributes (typeof(KnownTypeAttribute))) + foreach (var attr in type.GetCustomAttributes (typeof (KnownTypeAttribute), false)) knownTypesFromAttributes.Add ((attr as KnownTypeAttribute).Type); if (knownTypes != null) diff --git a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs index 9af14a6cfd5..d0f84d0f93a 100644 --- a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs +++ b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs @@ -221,7 +221,7 @@ Type GetRuntimeType (string name, Type baseType) return t; if (baseType != null) - foreach (var attr in baseType.GetCustomAttributes (typeof(KnownTypeAttribute))) + foreach (var attr in baseType.GetCustomAttributes (typeof (KnownTypeAttribute), false)) if ((attr as KnownTypeAttribute).Type.FullName.Equals (properName)) return (attr as KnownTypeAttribute).Type; From 43fd14b9d8486b2b50a15a7101846f7b7e1dc806 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 9 Oct 2014 12:56:04 -0400 Subject: [PATCH 384/543] [runtime] Use the functionality in mono-proclib.c to enumerate processes, remove duplicate code from the io-layer. --- mono/io-layer/processes.c | 134 -------------------------------------- mono/io-layer/processes.h | 1 - mono/metadata/process.c | 26 +++++++- mono/utils/mono-proclib.c | 4 ++ 4 files changed, 27 insertions(+), 138 deletions(-) diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index c65bf23813c..31b4be5f34f 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -1343,140 +1343,6 @@ static gboolean process_enum (gpointer handle, gpointer user_data) } #endif /* UNUSED_CODE */ -#if defined(PLATFORM_MACOSX) || defined(__OpenBSD__) - -gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed) -{ - guint32 count, fit, i, j; - gint32 err; - gboolean done; - size_t proclength, size; -#if defined(__OpenBSD__) - struct kinfo_proc *result; - int name[6]; - name[0] = CTL_KERN; - name[1] = KERN_PROC; - name[2] = KERN_PROC_ALL; - name[3] = 0; - name[4] = sizeof(struct kinfo_proc); - name[5] = 0; -#else - struct kinfo_proc *result; - static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; -#endif - - mono_once (&process_current_once, process_set_current); - - result = NULL; - done = FALSE; - - do { - proclength = 0; -#if defined(__OpenBSD__) - size = (sizeof(name) / sizeof(*name)); -#else - size = (sizeof(name) / sizeof(*name)) - 1; -#endif - err = sysctl ((int *)name, size, NULL, &proclength, NULL, 0); - - if (err == 0) { - result = malloc (proclength); - - if (result == NULL) - return FALSE; - -#if defined(__OpenBSD__) - name[5] = (int)(proclength / sizeof(struct kinfo_proc)); -#endif - - err = sysctl ((int *) name, size, result, &proclength, NULL, 0); - - if (err == 0) - done = TRUE; - else { - free (result); - result = NULL; - } - } - } while (err == 0 && !done); - - if (err != 0) { - if (result != NULL) { - free (result); - result = NULL; - } - return(FALSE); - } - - count = proclength / sizeof(struct kinfo_proc); - - fit = len / sizeof(guint32); - for (i = 0, j = 0; j< fit && i < count; i++) { -#if defined(__OpenBSD__) - pids [j++] = result [i].p_pid; -#else - if (result[i].kp_proc.p_pid > 0) /* Pid 0 not supported */ - pids [j++] = result [i].kp_proc.p_pid; -#endif - } - free (result); - result = NULL; - *needed = j * sizeof(guint32); - - return(TRUE); -} -#elif defined(__HAIKU__) - -gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed) -{ - guint32 fit, i = 0; - int32 cookie = 0; - team_info teamInfo; - - mono_once (&process_current_once, process_set_current); - - fit = len / sizeof (guint32); - while (get_next_team_info (&cookie, &teamInfo) == B_OK && i < fit) { - pids [i++] = teamInfo.team; - } - *needed = i * sizeof (guint32); - - return TRUE; -} -#else -gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed) -{ - guint32 fit, i; - DIR *dir; - struct dirent *entry; - - mono_once (&process_current_once, process_set_current); - - dir = opendir ("/proc"); - if (dir == NULL) { - return(FALSE); - } - - i = 0; - fit = len / sizeof (guint32); - while(i < fit && (entry = readdir (dir)) != NULL) { - pid_t pid; - char *endptr; - - if (!isdigit (entry->d_name[0])) - continue; - - pid = (pid_t) strtol (entry->d_name, &endptr, 10); - if (*endptr == '\0') - pids [i++] = (guint32) pid; - } - closedir (dir); - *needed = i * sizeof(guint32); - - return(TRUE); -} -#endif - static gboolean process_open_compare (gpointer handle, gpointer user_data) { pid_t wanted_pid; diff --git a/mono/io-layer/processes.h b/mono/io-layer/processes.h index 8e4c0aa558b..5ab1fe03589 100644 --- a/mono/io-layer/processes.h +++ b/mono/io-layer/processes.h @@ -189,7 +189,6 @@ extern gboolean CreateProcessWithLogonW (const gunichar2 *username, extern gpointer GetCurrentProcess (void); extern guint32 GetProcessId (gpointer handle); extern guint32 GetCurrentProcessId (void); -extern gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed); extern gboolean CloseProcess (gpointer handle); extern gpointer OpenProcess (guint32 access, gboolean inherit, guint32 pid); extern gboolean GetExitCodeProcess (gpointer process, guint32 *code); diff --git a/mono/metadata/process.c b/mono/metadata/process.c index c9e0f8bf63b..20a4d820f92 100644 --- a/mono/metadata/process.c +++ b/mono/metadata/process.c @@ -891,14 +891,33 @@ MonoString *ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE pr /* Returns an array of pids */ MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void) { +#if !defined(HOST_WIN32) + MonoArray *procs; + gpointer *pidarray; + int i, count; + + MONO_ARCH_SAVE_REGS; + + pidarray = mono_process_list (&count); + if (!pidarray) + mono_raise_exception (mono_get_exception_not_supported ("This system does not support EnumProcesses")); + procs = mono_array_new (mono_domain_get (), mono_get_int32_class (), count); + if (sizeof (guint32) == sizeof (gpointer)) { + memcpy (mono_array_addr (procs, guint32, 0), pidarray, count); + } else { + for (i = 0; i < count; ++i) + *(mono_array_addr (procs, guint32, i)) = GPOINTER_TO_UINT (pidarray [i]); + } + g_free (pidarray); + + return procs; +#else MonoArray *procs; gboolean ret; DWORD needed; - guint32 count; + int count; guint32 *pids; - MONO_ARCH_SAVE_REGS; - count = 512; do { pids = g_new0 (guint32, count); @@ -926,6 +945,7 @@ MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void) pids = NULL; return procs; +#endif } MonoBoolean ves_icall_System_Diagnostics_Process_GetWorkingSet_internal (HANDLE process, guint32 *min, guint32 *max) diff --git a/mono/utils/mono-proclib.c b/mono/utils/mono-proclib.c index 3f032f9d22c..1303b5b4d44 100644 --- a/mono/utils/mono-proclib.c +++ b/mono/utils/mono-proclib.c @@ -105,6 +105,10 @@ mono_process_list (int *size) if (size) *size = res; return buf; +#elif defined(__HAIKU__) + /* FIXME: Add back the code from 9185fcc305e43428d0f40f3ee37c8a405d41c9ae */ + g_assert_not_reached (); + return NULL; #else const char *name; void **buf = NULL; From 4109ab0ee4928cc15732440d783708701314f176 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 9 Oct 2014 13:04:41 -0400 Subject: [PATCH 385/543] [runtime] Use the functionality in mono-proclib.c to get the current pid, remove duplicate code from the io-layer. --- mono/io-layer/processes.c | 7 ------- mono/io-layer/processes.h | 1 - mono/metadata/process.c | 5 +++-- mono/metadata/sgen-gc.c | 6 +----- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index 31b4be5f34f..cd787835132 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -1261,13 +1261,6 @@ guint32 GetProcessId (gpointer handle) return (process_handle->id); } -guint32 GetCurrentProcessId (void) -{ - mono_once (&process_current_once, process_set_current); - - return (GetProcessId (current_process)); -} - /* Returns the process id as a convenience to the functions that call this */ static pid_t signal_process_if_gone (gpointer handle) { diff --git a/mono/io-layer/processes.h b/mono/io-layer/processes.h index 5ab1fe03589..99a62faeb1d 100644 --- a/mono/io-layer/processes.h +++ b/mono/io-layer/processes.h @@ -188,7 +188,6 @@ extern gboolean CreateProcessWithLogonW (const gunichar2 *username, extern gpointer GetCurrentProcess (void); extern guint32 GetProcessId (gpointer handle); -extern guint32 GetCurrentProcessId (void); extern gboolean CloseProcess (gpointer handle); extern gpointer OpenProcess (guint32 access, gboolean inherit, guint32 pid); extern gboolean GetExitCodeProcess (gpointer process, guint32 *code); diff --git a/mono/metadata/process.c b/mono/metadata/process.c index 20a4d820f92..f0f53ebe8f9 100644 --- a/mono/metadata/process.c +++ b/mono/metadata/process.c @@ -60,11 +60,12 @@ HANDLE ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid) return(handle); } -guint32 ves_icall_System_Diagnostics_Process_GetPid_internal (void) +guint32 +ves_icall_System_Diagnostics_Process_GetPid_internal (void) { MONO_ARCH_SAVE_REGS; - return(GetCurrentProcessId ()); + return mono_process_current_pid (); } void ves_icall_System_Diagnostics_Process_Process_free_internal (MonoObject *this, diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index f1f55e73da8..1364cc0a9e0 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -4889,11 +4889,7 @@ mono_gc_base_init (void) if (opt [0] == ':') opt++; if (opt [0]) { -#ifdef HOST_WIN32 - char *rf = g_strdup_printf ("%s.%d", opt, GetCurrentProcessId ()); -#else - char *rf = g_strdup_printf ("%s.%d", opt, getpid ()); -#endif + char *rf = g_strdup_printf ("%s.%d", opt, mono_process_current_pid ()); gc_debug_file = fopen (rf, "wb"); if (!gc_debug_file) gc_debug_file = stderr; From 92d86659ca5a71b91c631cb69fb5c6ceccd68c7c Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 9 Oct 2014 14:04:20 -0400 Subject: [PATCH 386/543] [runtime] Remove pre WinXP SP2 windows support code. --- configure.ac | 2 +- mono/metadata/process.c | 83 +---------------------------------------- winconfig.h | 8 +--- 3 files changed, 3 insertions(+), 90 deletions(-) diff --git a/configure.ac b/configure.ac index c6c36c9eefb..38b678c9d80 100644 --- a/configure.ac +++ b/configure.ac @@ -115,7 +115,7 @@ case "$host" in AC_DEFINE(MINGW_CROSS_COMPILE,1,[Cross-compiling using MinGW]) fi HOST_CC="gcc" - # Windows 2000 is required that includes Internet Explorer 5.01 + # Windows XP SP2 is required CPPFLAGS="$CPPFLAGS -DWINVER=0x0502 -D_WIN32_WINNT=0x0502 -D_WIN32_IE=0x0501 -D_UNICODE -DUNICODE -DWIN32_THREADS -DFD_SETSIZE=1024" LDFLAGS="$LDFLAGS -lmswsock -lws2_32 -lole32 -loleaut32 -lpsapi -lversion -ladvapi32 -lwinmm -lkernel32" libmono_cflags="-mms-bitfields -mwindows" diff --git a/mono/metadata/process.c b/mono/metadata/process.c index f0f53ebe8f9..d7cc110aec6 100644 --- a/mono/metadata/process.c +++ b/mono/metadata/process.c @@ -23,18 +23,7 @@ #include #include #include -#ifndef HAVE_GETPROCESSID -#if defined(_MSC_VER) || defined(HAVE_WINTERNL_H) -#include -#ifndef NT_SUCCESS -#define NT_SUCCESS(status) ((NTSTATUS) (status) >= 0) -#endif /* !NT_SUCCESS */ -#else /* ! (defined(_MSC_VER) || defined(HAVE_WINTERNL_H)) */ -#include -#include -#endif /* (defined(_MSC_VER) || defined(HAVE_WINTERNL_H)) */ -#endif /* !HAVE_GETPROCESSID */ -/* FIXME: fix this code to not depend so much on the inetrnals */ +/* FIXME: fix this code to not depend so much on the internals */ #include #define LOGDEBUG(...) @@ -526,76 +515,6 @@ complete_path (const gunichar2 *appname, gchar **completed) return TRUE; } -#ifndef HAVE_GETPROCESSID -/* Run-time GetProcessId detection for Windows */ -#ifdef TARGET_WIN32 -#define HAVE_GETPROCESSID - -typedef DWORD (WINAPI *GETPROCESSID_PROC) (HANDLE); -typedef DWORD (WINAPI *NTQUERYINFORMATIONPROCESS_PROC) (HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); -typedef DWORD (WINAPI *RTLNTSTATUSTODOSERROR_PROC) (NTSTATUS); - -static DWORD WINAPI GetProcessId_detect (HANDLE process); - -static GETPROCESSID_PROC GetProcessId = &GetProcessId_detect; -static NTQUERYINFORMATIONPROCESS_PROC NtQueryInformationProcess_proc = NULL; -static RTLNTSTATUSTODOSERROR_PROC RtlNtStatusToDosError_proc = NULL; - -static DWORD WINAPI GetProcessId_ntdll (HANDLE process) -{ - PROCESS_BASIC_INFORMATION pi; - NTSTATUS status; - - status = NtQueryInformationProcess_proc (process, ProcessBasicInformation, &pi, sizeof (pi), NULL); - if (NT_SUCCESS (status)) { - return pi.UniqueProcessId; - } else { - SetLastError (RtlNtStatusToDosError_proc (status)); - return 0; - } -} - -static DWORD WINAPI GetProcessId_stub (HANDLE process) -{ - SetLastError (ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - -static DWORD WINAPI GetProcessId_detect (HANDLE process) -{ - HMODULE module_handle; - GETPROCESSID_PROC GetProcessId_kernel; - - /* Windows XP SP1 and above have GetProcessId API */ - module_handle = GetModuleHandle (L"kernel32.dll"); - if (module_handle != NULL) { - GetProcessId_kernel = (GETPROCESSID_PROC) GetProcAddress (module_handle, "GetProcessId"); - if (GetProcessId_kernel != NULL) { - GetProcessId = GetProcessId_kernel; - return GetProcessId (process); - } - } - - /* Windows 2000 and above have deprecated NtQueryInformationProcess API */ - module_handle = GetModuleHandle (L"ntdll.dll"); - if (module_handle != NULL) { - NtQueryInformationProcess_proc = (NTQUERYINFORMATIONPROCESS_PROC) GetProcAddress (module_handle, "NtQueryInformationProcess"); - if (NtQueryInformationProcess_proc != NULL) { - RtlNtStatusToDosError_proc = (RTLNTSTATUSTODOSERROR_PROC) GetProcAddress (module_handle, "RtlNtStatusToDosError"); - if (RtlNtStatusToDosError_proc != NULL) { - GetProcessId = &GetProcessId_ntdll; - return GetProcessId (process); - } - } - } - - /* Fall back to ERROR_CALL_NOT_IMPLEMENTED */ - GetProcessId = &GetProcessId_stub; - return GetProcessId (process); -} -#endif /* HOST_WIN32 */ -#endif /* !HAVE_GETPROCESSID */ - MonoBoolean ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_info) { SHELLEXECUTEINFO shellex = {0}; diff --git a/winconfig.h b/winconfig.h index 0c690d3a35c..b6d74e1cb41 100644 --- a/winconfig.h +++ b/winconfig.h @@ -13,11 +13,7 @@ #endif #if _WIN32_WINNT < 0x0502 -/* Required for Vectored Exception Handling. - Interlocked* functions are also not available in XP SP1 and below -*/ -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0502 +#error "Mono requires WinXP SP2 or later" #endif /* _WIN32_WINNT < 0x0502 */ /* @@ -198,9 +194,7 @@ /* #undef HAVE_GETPRIORITY */ /* Define to 1 if you have the `GetProcessId' function. */ -#if (_WIN32_WINNT >= 0x0502) #define HAVE_GETPROCESSID 1 -#endif /* Define to 1 if you have the `getpwnam_r' function. */ /* #undef HAVE_GETPWNAM_R */ From eea8080dadaf8af162281b4137d59862deafe6c1 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 9 Oct 2014 15:19:56 -0400 Subject: [PATCH 387/543] [runtime] Use WinXP SP2 as the minimum version on the msvc builds too. --- msvc/genmdesc.vcxproj | 4 ++-- msvc/libgc.vcxproj | 8 ++++---- msvc/profiler-logging.vcxproj | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/msvc/genmdesc.vcxproj b/msvc/genmdesc.vcxproj index d3c7511cd49..d33fd7a454d 100644 --- a/msvc/genmdesc.vcxproj +++ b/msvc/genmdesc.vcxproj @@ -131,7 +131,7 @@ Disabled ..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories) - _DEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) + _DEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -218,7 +218,7 @@ MinSpace OnlyExplicitInline ..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories) - NDEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) + NDEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) true MultiThreadedDLL true diff --git a/msvc/libgc.vcxproj b/msvc/libgc.vcxproj index 08bcfa0ba8c..db5bfab6d46 100644 --- a/msvc/libgc.vcxproj +++ b/msvc/libgc.vcxproj @@ -75,7 +75,7 @@ Disabled ..\libgc\include;%(AdditionalIncludeDirectories) - _DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) + _DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -95,7 +95,7 @@ MinSpace ..\libgc\include;%(AdditionalIncludeDirectories) - NDEBUG;__i386__;TARGET_X86;i386;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) + NDEBUG;__i386__;TARGET_X86;i386;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -115,7 +115,7 @@ Disabled ..\libgc\include;%(AdditionalIncludeDirectories) - _DEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024 + _DEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024 true EnableFastChecks MultiThreadedDebugDLL @@ -138,7 +138,7 @@ MinSpace ..\libgc\include;%(AdditionalIncludeDirectories) - NDEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) + NDEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) MultiThreadedDLL true diff --git a/msvc/profiler-logging.vcxproj b/msvc/profiler-logging.vcxproj index 2d28de55104..b4576542797 100644 --- a/msvc/profiler-logging.vcxproj +++ b/msvc/profiler-logging.vcxproj @@ -118,7 +118,7 @@ Disabled ..\libgc\include;..\;..\mono\;..\mono\jit;..\mono\eglib\src;..\..\mono\eglib\src;%(AdditionalIncludeDirectories) - TARGET_X86;_DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;GC_NOT_DLL;HAVE_CONFIG_H;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) + TARGET_X86;_DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;GC_NOT_DLL;HAVE_CONFIG_H;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -140,7 +140,7 @@ Disabled ..\libgc\include;..\;..\mono\;..\mono\jit;..\mono\eglib\src;..\..\mono\eglib\src;%(AdditionalIncludeDirectories) - TARGET_X86;_DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;GC_NOT_DLL;HAVE_CONFIG_H;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) + TARGET_X86;_DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;GC_NOT_DLL;HAVE_CONFIG_H;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL From a487812e61f6a59d497d9bfdf6f17564b8637cc2 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 9 Oct 2014 15:50:56 -0400 Subject: [PATCH 388/543] runtime] Really use WinXP SP2 as the minimum version on the msvc builds too. Update project files with newly added/removed sources. --- msvc/libmonoruntime.vcxproj | 6 ++---- msvc/mono.props | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/msvc/libmonoruntime.vcxproj b/msvc/libmonoruntime.vcxproj index 3635bdae2d5..c65a603ff9f 100644 --- a/msvc/libmonoruntime.vcxproj +++ b/msvc/libmonoruntime.vcxproj @@ -57,6 +57,7 @@ + @@ -98,9 +99,6 @@ - - - @@ -466,4 +464,4 @@ - \ No newline at end of file + diff --git a/msvc/mono.props b/msvc/mono.props index 46b4dde2c8f..ffec2840f23 100644 --- a/msvc/mono.props +++ b/msvc/mono.props @@ -9,11 +9,11 @@ - __default_codegen__;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;GC_NOT_DLL;WIN32_THREADS;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;_UNICODE;UNICODE;WIN32_THREADS;FD_SETSIZE=1024;$(PreprocessorDefinitions);_WINSOCKAPI_ + __default_codegen__;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;GC_NOT_DLL;WIN32_THREADS;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;_UNICODE;UNICODE;WIN32_THREADS;FD_SETSIZE=1024;$(PreprocessorDefinitions);_WINSOCKAPI_ 4273;4005 Mswsock.lib;ws2_32.lib;ole32.lib;oleaut32.lib;psapi.lib;version.lib;advapi32.lib;winmm.lib;kernel32.lib;$(AdditionalDependencies) - \ No newline at end of file + From e1af46ef452c6e087594e97219f34701c9ee0688 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 9 Oct 2014 16:21:56 -0400 Subject: [PATCH 389/543] [runtime] More win32 build fixes. --- msvc/genmdesc.vcxproj | 3 ++- msvc/libtest.vcxproj | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/msvc/genmdesc.vcxproj b/msvc/genmdesc.vcxproj index d33fd7a454d..34efcacfd5c 100644 --- a/msvc/genmdesc.vcxproj +++ b/msvc/genmdesc.vcxproj @@ -18,6 +18,7 @@ x64 + {B7098DFA-31E6-4006-8A15-1C9A4E925149} genmdesc @@ -338,4 +339,4 @@ - \ No newline at end of file + diff --git a/msvc/libtest.vcxproj b/msvc/libtest.vcxproj index 0fa69f3a15d..8e35a6e7659 100644 --- a/msvc/libtest.vcxproj +++ b/msvc/libtest.vcxproj @@ -18,6 +18,7 @@ x64 + {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4} libtest @@ -199,4 +200,4 @@ - \ No newline at end of file + From 02be6a4f28cae261f46b3de619629fbefbdec353 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 9 Oct 2014 16:48:51 -0400 Subject: [PATCH 390/543] [runtime] Use explicit initialization in the io-layer process code instead of pthread_once (). Get rid of the WAPI_PROCESS_HANDLE_OFFSET code which was only used in shared mode. --- mono/io-layer/handles.c | 1 + mono/io-layer/process-private.h | 1 + mono/io-layer/processes.c | 120 ++++---------------------------- 3 files changed, 16 insertions(+), 106 deletions(-) diff --git a/mono/io-layer/handles.c b/mono/io-layer/handles.c index 8cd74e9ff36..6644f568d59 100644 --- a/mono/io-layer/handles.c +++ b/mono/io-layer/handles.c @@ -266,6 +266,7 @@ wapi_init (void) _wapi_global_signal_cond = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle)).signal_cond; _wapi_global_signal_mutex = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle)).signal_mutex; + wapi_processes_init (); /* Using g_atexit here instead of an explicit function call in * a cleanup routine lets us cope when a third-party library diff --git a/mono/io-layer/process-private.h b/mono/io-layer/process-private.h index c3e6988732d..75223c5b5e1 100644 --- a/mono/io-layer/process-private.h +++ b/mono/io-layer/process-private.h @@ -21,6 +21,7 @@ #define _WAPI_PROCESS_UNHANDLED (1 << (8*sizeof(pid_t)-1)) #define _WAPI_PROCESS_UNHANDLED_PID_MASK (-1 & ~_WAPI_PROCESS_UNHANDLED) +void wapi_processes_init (void); extern gpointer _wapi_process_duplicate (void); extern void wapi_processes_cleanup (void); diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index cd787835132..710d8c2fb5f 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -142,20 +142,9 @@ static volatile gint32 mono_processes_cleaning_up = 0; static mono_mutex_t mono_processes_mutex; static void mono_processes_cleanup (void); -static mono_once_t process_current_once=MONO_ONCE_INIT; -static gpointer current_process=NULL; +static gpointer current_process; static char *cli_launcher; -static mono_once_t process_ops_once=MONO_ONCE_INIT; - -static void process_ops_init (void) -{ - _wapi_handle_register_capabilities (WAPI_HANDLE_PROCESS, - WAPI_HANDLE_CAP_WAIT | - WAPI_HANDLE_CAP_SPECIAL_WAIT); -} - - /* Check if a pid is valid - i.e. if a process exists with this pid. */ static gboolean is_pid_valid (pid_t pid) { @@ -571,7 +560,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, struct MonoProcess *mono_process; gboolean fork_failed = FALSE; - mono_once (&process_ops_once, process_ops_init); mono_once (&process_sig_chld_once, process_add_sigchld_handler); /* appname and cmdline specify the executable and its args: @@ -945,18 +933,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, env_count++; } } - /* pass process handle info to the child, so it doesn't have - * to do an expensive search over the whole list - */ - if (env_strings != NULL) { - struct _WapiHandleUnshared *handle_data; - struct _WapiHandle_shared_ref *ref; - - handle_data = &_WAPI_PRIVATE_HANDLES(GPOINTER_TO_UINT(handle)); - ref = &handle_data->u.shared; - - env_strings[env_count] = g_strdup_printf ("_WAPI_PROCESS_HANDLE_OFFSET=%d", ref->offset); - } /* Create a pipe to make sure the child doesn't exit before * we can add the process to the linked list of mono_processes */ @@ -1152,65 +1128,16 @@ extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime); #define g_unsetenv(a) unsetenv(a) #endif -static void process_set_current (void) +void +wapi_processes_init (void) { pid_t pid = _wapi_getpid (); - const char *handle_env; struct _WapiHandle_process process_handle = {0}; - - mono_once (&process_ops_once, process_ops_init); - - handle_env = g_getenv ("_WAPI_PROCESS_HANDLE_OFFSET"); - g_unsetenv ("_WAPI_PROCESS_HANDLE_OFFSET"); - - if (handle_env != NULL) { - struct _WapiHandle_process *process_handlep; - gchar *procname = NULL; - gboolean ok; - - current_process = _wapi_handle_new_from_offset (WAPI_HANDLE_PROCESS, atoi (handle_env), TRUE); - - DEBUG ("%s: Found my process handle: %p (offset %d 0x%x)", - __func__, current_process, atoi (handle_env), - atoi (handle_env)); - - ok = _wapi_lookup_handle (current_process, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handlep); - if (ok) { - /* This test will probably break on linuxthreads, but - * that should be ancient history on all distros we - * care about by now - */ - if (process_handlep->id == pid) { - procname = process_handlep->proc_name; - if (!strcmp (procname, "mono")) { - /* Set a better process name */ - DEBUG ("%s: Setting better process name", __func__); - - process_set_name (process_handlep); - } else { - DEBUG ("%s: Leaving process name: %s", __func__, procname); - } - - return; - } - - /* Wrong pid, so drop this handle and fall through to - * create a new one - */ - _wapi_handle_unref (current_process); - } - } - - /* We get here if the handle wasn't specified in the - * environment, or if the process ID was wrong, or if the - * handle lookup failed (eg if the parent process forked and - * quit immediately, and deleted the shared data before the - * child got a chance to attach it.) - */ - - DEBUG ("%s: Need to create my own process handle", __func__); + _wapi_handle_register_capabilities (WAPI_HANDLE_PROCESS, + WAPI_HANDLE_CAP_WAIT | + WAPI_HANDLE_CAP_SPECIAL_WAIT); + process_handle.id = pid; process_set_defaults (&process_handle); @@ -1218,27 +1145,22 @@ static void process_set_current (void) current_process = _wapi_handle_new (WAPI_HANDLE_PROCESS, &process_handle); - if (current_process == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error creating process handle", __func__); - return; - } + g_assert (current_process); } -gpointer _wapi_process_duplicate () +gpointer +_wapi_process_duplicate (void) { - mono_once (&process_current_once, process_set_current); - _wapi_handle_ref (current_process); - return(current_process); + return current_process; } /* Returns a pseudo handle that doesn't need to be closed afterwards */ -gpointer GetCurrentProcess (void) +gpointer +GetCurrentProcess (void) { - mono_once (&process_current_once, process_set_current); - - return(_WAPI_PROCESS_CURRENT); + return _WAPI_PROCESS_CURRENT; } guint32 GetProcessId (gpointer handle) @@ -1381,8 +1303,6 @@ gpointer OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_ /* Find the process handle that corresponds to pid */ gpointer handle = NULL; - mono_once (&process_current_once, process_set_current); - DEBUG ("%s: looking for process %d", __func__, pid); handle = _wapi_search_handle (WAPI_HANDLE_PROCESS, @@ -1413,8 +1333,6 @@ gboolean GetExitCodeProcess (gpointer process, guint32 *code) gboolean ok; guint32 pid = -1; - mono_once (&process_current_once, process_set_current); - if(code==NULL) { return(FALSE); } @@ -1465,8 +1383,6 @@ gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time, gboolean ok; gboolean ku_times_set = FALSE; - mono_once (&process_current_once, process_set_current); - if(create_time==NULL || exit_time==NULL || kernel_time==NULL || user_time==NULL) { /* Not sure if w32 allows NULLs here or not */ @@ -2175,8 +2091,6 @@ static guint32 get_module_name (gpointer process, gpointer module, int i; gchar *proc_name = NULL; - mono_once (&process_current_once, process_set_current); - DEBUG ("%s: Getting module base name, process handle %p module %p", __func__, process, module); @@ -2320,8 +2234,6 @@ gboolean GetModuleInformation (gpointer process, gpointer module, gboolean ret = FALSE; gchar *proc_name = NULL; - mono_once (&process_current_once, process_set_current); - DEBUG ("%s: Getting module info, process handle %p module %p", __func__, process, module); @@ -2393,8 +2305,6 @@ gboolean GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max) struct _WapiHandle_process *process_handle; gboolean ok; - mono_once (&process_current_once, process_set_current); - if(min==NULL || max==NULL) { /* Not sure if w32 allows NULLs here or not */ return(FALSE); @@ -2425,8 +2335,6 @@ gboolean SetProcessWorkingSetSize (gpointer process, size_t min, size_t max) struct _WapiHandle_process *process_handle; gboolean ok; - mono_once (&process_current_once, process_set_current); - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { /* This is a pseudo handle, so just fail for now */ From 5f2f74f5ded32eeb78527922a7ea3d23da0ad8c7 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 9 Oct 2014 21:46:01 -0400 Subject: [PATCH 391/543] [runtime] Rewrite io-layer process code to reduce duplication and make it conform to the mono coding conventions. --- mono/io-layer/process-private.h | 9 + mono/io-layer/processes.c | 598 +++++++++++++++----------------- 2 files changed, 286 insertions(+), 321 deletions(-) diff --git a/mono/io-layer/process-private.h b/mono/io-layer/process-private.h index 75223c5b5e1..a70f6586c12 100644 --- a/mono/io-layer/process-private.h +++ b/mono/io-layer/process-private.h @@ -16,10 +16,17 @@ /* There doesn't seem to be a defined symbol for this */ #define _WAPI_PROCESS_CURRENT (gpointer)0xFFFFFFFF +/* + * Handles > _WAPI_PROCESS_UNHANDLED are pseudo handles which represent processes + * not started by the runtime. + */ /* This marks a system process that we don't have a handle on */ /* FIXME: Cope with PIDs > sizeof guint */ #define _WAPI_PROCESS_UNHANDLED (1 << (8*sizeof(pid_t)-1)) #define _WAPI_PROCESS_UNHANDLED_PID_MASK (-1 & ~_WAPI_PROCESS_UNHANDLED) +#define WAPI_IS_PSEUDO_PROCESS_HANDLE(handle) ((GPOINTER_TO_UINT(handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) +#define WAPI_PID_TO_HANDLE(pid) GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + (pid)) +#define WAPI_HANDLE_TO_PID(handle) (GPOINTER_TO_UINT ((handle)) - _WAPI_PROCESS_UNHANDLED) void wapi_processes_init (void); extern gpointer _wapi_process_duplicate (void); @@ -71,4 +78,6 @@ struct _WapiHandle_process struct MonoProcess *mono_process; }; +typedef struct _WapiHandle_process WapiHandle_process; + #endif /* _WAPI_PROCESS_PRIVATE_H_ */ diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index 710d8c2fb5f..6e19ab98317 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -86,7 +86,7 @@ * arm-apple-darwin9. We'll manually define the symbol on Apple as it does * in fact exist on all implementations (so far) */ -gchar ***_NSGetEnviron(void); +char ***_NSGetEnviron(void); #define environ (*_NSGetEnviron()) #else extern char **environ; @@ -145,8 +145,22 @@ static void mono_processes_cleanup (void); static gpointer current_process; static char *cli_launcher; +static WapiHandle_process * +lookup_process_handle (gpointer handle) +{ + WapiHandle_process *process_data; + gboolean ret; + + ret = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS, + (gpointer *)&process_data); + if (!ret) + return NULL; + return process_data; +} + /* Check if a pid is valid - i.e. if a process exists with this pid. */ -static gboolean is_pid_valid (pid_t pid) +static gboolean +is_pid_valid (pid_t pid) { gboolean result = FALSE; @@ -158,7 +172,7 @@ static gboolean is_pid_valid (pid_t pid) if (get_team_info ((team_id)pid, &teamInfo) == B_OK) result = TRUE; #else - gchar *dir = g_strdup_printf ("/proc/%d", pid); + char *dir = g_strdup_printf ("/proc/%d", pid); if (!access (dir, F_OK)) result = TRUE; g_free (dir); @@ -167,7 +181,8 @@ static gboolean is_pid_valid (pid_t pid) return result; } -static void process_set_defaults (struct _WapiHandle_process *process_handle) +static void +process_set_defaults (WapiHandle_process *process_handle) { /* These seem to be the defaults on w2k */ process_handle->min_working_set = 204800; @@ -268,7 +283,7 @@ static const gunichar2 *utf16_quote = utf16_quote_bytes; void print_utf16 (gunichar2 *str) { - gchar *res; + char *res; res = g_utf16_to_utf8 (str, -1, NULL, NULL, NULL); g_print ("%s\n", res); @@ -277,7 +292,8 @@ print_utf16 (gunichar2 *str) #endif /* Implemented as just a wrapper around CreateProcess () */ -gboolean ShellExecuteEx (WapiShellExecuteInfo *sei) +gboolean +ShellExecuteEx (WapiShellExecuteInfo *sei) { gboolean ret; WapiProcessInformation process_info; @@ -288,13 +304,12 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei) * that */ SetLastError (ERROR_INVALID_PARAMETER); - return (FALSE); + return FALSE; } - if (sei->lpFile == NULL) { + if (sei->lpFile == NULL) /* w2k returns TRUE for this, for some reason. */ - return (TRUE); - } + return TRUE; /* Put both executable and parameters into the second argument * to CreateProcess (), so it searches $PATH. The conversion @@ -302,9 +317,9 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei) * g_strdup_printf () equivalent for gunichar2 :-( */ args = utf16_concat (utf16_quote, sei->lpFile, utf16_quote, sei->lpParameters == NULL ? NULL : utf16_space, sei->lpParameters, NULL); - if (args == NULL){ + if (args == NULL) { SetLastError (ERROR_INVALID_DATA); - return (FALSE); + return FALSE; } ret = CreateProcess (NULL, args, NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT, NULL, @@ -335,7 +350,7 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei) handler = g_find_program_in_path ("kfmclient"); if (handler == NULL){ handler_utf16 = (gunichar2 *) -1; - return (FALSE); + return FALSE; } else { /* kfmclient needs exec argument */ char *old = handler; @@ -359,7 +374,7 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei) sei->lpFile, utf16_quote, sei->lpParameters == NULL ? NULL : utf16_space, sei->lpParameters, NULL); - if (args == NULL){ + if (args == NULL) { SetLastError (ERROR_INVALID_DATA); return FALSE; } @@ -367,7 +382,7 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei) CREATE_UNICODE_ENVIRONMENT, NULL, sei->lpDirectory, NULL, &process_info); g_free (args); - if (!ret){ + if (!ret) { if (GetLastError () != ERROR_OUTOFMEMORY) SetLastError (ERROR_INVALID_DATA); return FALSE; @@ -377,17 +392,16 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei) process_info.hProcess = NULL; } - if (sei->fMask & SEE_MASK_NOCLOSEPROCESS) { + if (sei->fMask & SEE_MASK_NOCLOSEPROCESS) sei->hProcess = process_info.hProcess; - } else { + else CloseHandle (process_info.hProcess); - } - return (ret); + return ret; } static gboolean -is_managed_binary (const gchar *filename) +is_managed_binary (const char *filename) { int original_errno = errno; #if defined(HAVE_LARGE_FILE_SUPPORT) && defined(O_LARGEFILE) @@ -494,17 +508,18 @@ is_managed_binary (const gchar *filename) return managed; } -gboolean CreateProcessWithLogonW (const gunichar2 *username, - const gunichar2 *domain, - const gunichar2 *password, - const guint32 logonFlags, - const gunichar2 *appname, - const gunichar2 *cmdline, - guint32 create_flags, - gpointer env, - const gunichar2 *cwd, - WapiStartupInfo *startup, - WapiProcessInformation *process_info) +gboolean +CreateProcessWithLogonW (const gunichar2 *username, + const gunichar2 *domain, + const gunichar2 *password, + const guint32 logonFlags, + const gunichar2 *appname, + const gunichar2 *cmdline, + guint32 create_flags, + gpointer env, + const gunichar2 *cwd, + WapiStartupInfo *startup, + WapiProcessInformation *process_info) { /* FIXME: use user information */ return CreateProcess (appname, cmdline, NULL, NULL, FALSE, create_flags, env, cwd, startup, process_info); @@ -524,17 +539,15 @@ is_executable (const char *prog) } static void -switchDirectorySeparators(gchar *path) +switch_dir_separators (char *path) { size_t i, pathLength = strlen(path); /* Turn all the slashes round the right way, except for \' */ /* There are probably other characters that need to be excluded as well. */ - for (i = 0; i < pathLength; i++) - { - if (path[i] == '\\' && i < pathLength - 1 && path[i+1] != '\'' ) { + for (i = 0; i < pathLength; i++) { + if (path[i] == '\\' && i < pathLength - 1 && path[i+1] != '\'' ) path[i] = '/'; - } } } @@ -546,11 +559,12 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, WapiStartupInfo *startup, WapiProcessInformation *process_info) { - gchar *cmd=NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL, *dir = NULL, **env_strings = NULL, **argv = NULL; + char *cmd = NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL; + char *dir = NULL, **env_strings = NULL, **argv = NULL; guint32 i, env_count = 0; gboolean ret = FALSE; gpointer handle; - struct _WapiHandle_process process_handle = {0}, *process_handle_data; + WapiHandle_process process_handle = {0}, *process_handle_data; GError *gerr = NULL; int in_fd, out_fd, err_fd; pid_t pid; @@ -598,7 +612,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, goto free_strings; } - switchDirectorySeparators(cmd); + switch_dir_separators(cmd); } if (cmdline != NULL) { @@ -621,13 +635,13 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, } /* Turn all the slashes round the right way */ - switchDirectorySeparators(dir); + switch_dir_separators(dir); } /* We can't put off locating the executable any longer :-( */ if (cmd != NULL) { - gchar *unquoted; + char *unquoted; if (g_ascii_isalpha (cmd[0]) && (cmd[1] == ':')) { /* Strip off the drive letter. I can't * believe that CP/M holdover is still @@ -672,7 +686,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, args_after_prog = args; } else { - gchar *token = NULL; + char *token = NULL; char quote; /* Dig out the first token from args, taking quotation @@ -735,7 +749,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, /* Turn all the slashes round the right way. Only for * the prg. name */ - switchDirectorySeparators(token); + switch_dir_separators(token); if (g_ascii_isalpha (token[0]) && (token[1] == ':')) { /* Strip off the drive letter. I can't @@ -758,7 +772,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, SetLastError (ERROR_FILE_NOT_FOUND); goto free_strings; } - } else { char *curdir = g_get_current_dir (); @@ -834,7 +847,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, } if (args_after_prog != NULL && *args_after_prog) { - gchar *qprog; + char *qprog; qprog = g_shell_quote (prog); full_prog = g_strconcat (qprog, " ", args_after_prog, NULL); @@ -883,7 +896,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, * environment variables in the new process. Otherwise the * new process inherits the same environment. */ - if (new_environ != NULL) { + if (new_environ) { gunichar2 *new_environp; /* Count the number of strings */ @@ -898,7 +911,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, /* +2: one for the process handle value, and the last * one is NULL */ - env_strings = g_new0 (gchar *, env_count + 2); + env_strings = g_new0 (char *, env_count + 2); /* Copy each environ string into 'strings' turning it * into utf8 (or the requested encoding) at the same @@ -914,14 +927,13 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, } } } else { - for (i = 0; environ[i] != NULL; i++) { + for (i = 0; environ[i] != NULL; i++) env_count++; - } /* +2: one for the process handle value, and the last * one is NULL */ - env_strings = g_new0 (gchar *, env_count + 2); + env_strings = g_new0 (char *, env_count + 2); /* Copy each environ string into 'strings' turning it * into utf8 (or the requested encoding) at the same @@ -976,20 +988,17 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, } /* Close all file descriptors */ - for (i = getdtablesize () - 1; i > 2; i--) { + for (i = getdtablesize () - 1; i > 2; i--) close (i); - } #ifdef DEBUG_ENABLED DEBUG ("%s: exec()ing [%s] in dir [%s]", __func__, cmd, - dir==NULL?".":dir); - for (i = 0; argv[i] != NULL; i++) { + dir == NULL?".":dir); + for (i = 0; argv[i] != NULL; i++) g_message ("arg %d: [%s]", i, argv[i]); - } - for (i = 0; env_strings[i] != NULL; i++) { + for (i = 0; env_strings[i] != NULL; i++) g_message ("env %d: [%s]", i, env_strings[i]); - } #endif /* set cwd */ @@ -1006,9 +1015,8 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, } /* parent */ - ret = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handle_data); - if (ret == FALSE) { + process_handle_data = lookup_process_handle (handle); + if (!process_handle_data) { g_warning ("%s: error looking up process handle %p", __func__, handle); _wapi_handle_unref (handle); @@ -1067,27 +1075,20 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, } free_strings: - if (cmd != NULL) { + if (cmd) g_free (cmd); - } - if (full_prog != NULL) { + if (full_prog) g_free (full_prog); - } - if (prog != NULL) { + if (prog) g_free (prog); - } - if (args != NULL) { + if (args) g_free (args); - } - if (dir != NULL) { + if (dir) g_free (dir); - } - if(env_strings != NULL) { + if (env_strings) g_strfreev (env_strings); - } - if (argv != NULL) { + if (argv) g_strfreev (argv); - } DEBUG ("%s: returning handle %p for pid %d", __func__, handle, pid); @@ -1095,44 +1096,37 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, /* Check if something needs to be cleaned up. */ mono_processes_cleanup (); - return(ret); + return ret; } -static void process_set_name (struct _WapiHandle_process *process_handle) +static void +process_set_name (WapiHandle_process *process_handle) { - gchar *progname, *utf8_progname, *slash; + char *progname, *utf8_progname, *slash; - progname=g_get_prgname (); - utf8_progname=mono_utf8_from_external (progname); + progname = g_get_prgname (); + utf8_progname = mono_utf8_from_external (progname); DEBUG ("%s: using [%s] as prog name", __func__, progname); - if(utf8_progname!=NULL) { - slash=strrchr (utf8_progname, '/'); - if(slash!=NULL) { + if (utf8_progname) { + slash = strrchr (utf8_progname, '/'); + if (slash) g_strlcpy (process_handle->proc_name, slash+1, _WAPI_PROC_NAME_MAX_LEN - 1); - } else { + else g_strlcpy (process_handle->proc_name, utf8_progname, _WAPI_PROC_NAME_MAX_LEN - 1); - } g_free (utf8_progname); } } -extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime); - -#if !GLIB_CHECK_VERSION (2,4,0) -#define g_setenv(a,b,c) setenv(a,b,c) -#define g_unsetenv(a) unsetenv(a) -#endif - void wapi_processes_init (void) { pid_t pid = _wapi_getpid (); - struct _WapiHandle_process process_handle = {0}; + WapiHandle_process process_handle = {0}; _wapi_handle_register_capabilities (WAPI_HANDLE_PROCESS, WAPI_HANDLE_CAP_WAIT | @@ -1163,40 +1157,37 @@ GetCurrentProcess (void) return _WAPI_PROCESS_CURRENT; } -guint32 GetProcessId (gpointer handle) +guint32 +GetProcessId (gpointer handle) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; - if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) /* This is a pseudo handle */ - return(GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED_PID_MASK); - } + return WAPI_HANDLE_TO_PID (handle); - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handle); - if (ok == FALSE) { + process_handle = lookup_process_handle (handle); + if (!process_handle) { SetLastError (ERROR_INVALID_HANDLE); - return (0); + return 0; } - return (process_handle->id); + return process_handle->id; } /* Returns the process id as a convenience to the functions that call this */ -static pid_t signal_process_if_gone (gpointer handle) +static pid_t +signal_process_if_gone (gpointer handle) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; - g_assert ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) != _WAPI_PROCESS_UNHANDLED); + g_assert (!WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)); /* Make sure the process is signalled if it has exited - if * the parent process didn't wait for it then it won't be */ - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handle); - if (ok == FALSE) { + process_handle = lookup_process_handle (handle); + if (!process_handle) { /* It's possible that the handle has vanished during * the _wapi_search_handle before it gets here, so * don't spam the console with warnings. @@ -1204,7 +1195,7 @@ static pid_t signal_process_if_gone (gpointer handle) /* g_warning ("%s: error looking up process handle %p", __func__, handle);*/ - return (0); + return 0; } DEBUG ("%s: looking at process %d", __func__, process_handle->id); @@ -1219,22 +1210,22 @@ static pid_t signal_process_if_gone (gpointer handle) _wapi_shared_handle_set_signal_state (handle, TRUE); } - return (process_handle->id); + return process_handle->id; } -#ifdef UNUSED_CODE -static gboolean process_enum (gpointer handle, gpointer user_data) +#if 0 +static gboolean +process_enum (gpointer handle, gpointer user_data) { - GArray *processes=user_data; + GArray *processes = user_data; pid_t pid = signal_process_if_gone (handle); int i; - if (pid == 0) { - return (FALSE); - } + if (pid == 0) + return FALSE; /* Ignore processes that have already exited (ie they are signalled) */ - if (_wapi_handle_issignalled (handle) == FALSE) { + if (!_wapi_handle_issignalled (handle)) { DEBUG ("%s: process %d added to array", __func__, pid); /* This ensures that duplicates aren't returned (see @@ -1246,7 +1237,7 @@ static gboolean process_enum (gpointer handle, gpointer user_data) /* We've already got this one, return * FALSE to keep searching */ - return (FALSE); + return FALSE; } } @@ -1254,18 +1245,18 @@ static gboolean process_enum (gpointer handle, gpointer user_data) } /* Return false to keep searching */ - return(FALSE); + return FALSE; } -#endif /* UNUSED_CODE */ +#endif /* 0 */ -static gboolean process_open_compare (gpointer handle, gpointer user_data) +static gboolean +process_open_compare (gpointer handle, gpointer user_data) { pid_t wanted_pid; pid_t checking_pid = signal_process_if_gone (handle); - if (checking_pid == 0) { - return(FALSE); - } + if (checking_pid == 0) + return FALSE; wanted_pid = GPOINTER_TO_UINT (user_data); @@ -1274,31 +1265,30 @@ static gboolean process_open_compare (gpointer handle, gpointer user_data) * unsignalled */ if (checking_pid == wanted_pid && - _wapi_handle_issignalled (handle) == FALSE) { + !_wapi_handle_issignalled (handle)) { /* If the handle is blown away in the window between * returning TRUE here and _wapi_search_handle pinging * the timestamp, the search will continue */ - return(TRUE); + return TRUE; } else { - return(FALSE); + return FALSE; } } -gboolean CloseProcess(gpointer handle) +gboolean +CloseProcess (gpointer handle) { - if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { - /* This is a pseudo handle */ - return(TRUE); - } - + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) + return TRUE; return CloseHandle (handle); } /* * The caller owns the returned handle and must call CloseProcess () on it to clean it up. */ -gpointer OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 pid) +gpointer +OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 pid) { /* Find the process handle that corresponds to pid */ gpointer handle = NULL; @@ -1313,32 +1303,31 @@ gpointer OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_ /* Return a pseudo handle for processes we * don't have handles for */ - return GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + pid); + return WAPI_PID_TO_HANDLE (pid); } else { DEBUG ("%s: Can't find pid %d", __func__, pid); SetLastError (ERROR_PROC_NOT_FOUND); - return(NULL); + return NULL; } } /* _wapi_search_handle () already added a ref */ - return(handle); + return handle; } -gboolean GetExitCodeProcess (gpointer process, guint32 *code) +gboolean +GetExitCodeProcess (gpointer process, guint32 *code) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; guint32 pid = -1; - if(code==NULL) { - return(FALSE); - } + if (!code) + return FALSE; - pid = GPOINTER_TO_UINT (process) - _WAPI_PROCESS_UNHANDLED; - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) { + pid = WAPI_HANDLE_TO_PID (process); /* This is a pseudo handle, so we don't know what the * exit code was, but we can check whether it's alive or not */ @@ -1350,12 +1339,11 @@ gboolean GetExitCodeProcess (gpointer process, guint32 *code) } } - ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handle); - if(ok==FALSE) { + process_handle = lookup_process_handle (process); + if (!process_handle) { DEBUG ("%s: Can't find process %p", __func__, process); - return(FALSE); + return FALSE; } /* A process handle is only signalled if the process has exited @@ -1366,51 +1354,46 @@ gboolean GetExitCodeProcess (gpointer process, guint32 *code) */ process_wait (process, 0, TRUE); - if (_wapi_handle_issignalled (process) == TRUE) { + if (_wapi_handle_issignalled (process)) *code = process_handle->exitstatus; - } else { + else *code = STILL_ACTIVE; - } - return(TRUE); + return TRUE; } -gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time, - WapiFileTime *exit_time, WapiFileTime *kernel_time, - WapiFileTime *user_time) +gboolean +GetProcessTimes (gpointer process, WapiFileTime *create_time, + WapiFileTime *exit_time, WapiFileTime *kernel_time, + WapiFileTime *user_time) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; gboolean ku_times_set = FALSE; - if(create_time==NULL || exit_time==NULL || kernel_time==NULL || - user_time==NULL) { + if (create_time == NULL || exit_time == NULL || kernel_time == NULL || + user_time == NULL) /* Not sure if w32 allows NULLs here or not */ - return(FALSE); - } + return FALSE; - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) /* This is a pseudo handle, so just fail for now */ - return(FALSE); - } + return FALSE; - ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handle); - if(ok==FALSE) { + process_handle = lookup_process_handle (process); + if (!process_handle) { DEBUG ("%s: Can't find process %p", __func__, process); - return(FALSE); + return FALSE; } - *create_time=process_handle->create_time; + *create_time = process_handle->create_time; /* A process handle is only signalled if the process has * exited. Otherwise exit_time isn't set */ - if(_wapi_handle_issignalled (process)==TRUE) { - *exit_time=process_handle->exit_time; - } + if (_wapi_handle_issignalled (process)) + *exit_time = process_handle->exit_time; #ifdef HAVE_GETRUSAGE if (process_handle->id == getpid ()) { @@ -1430,18 +1413,18 @@ gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time, memset (user_time, 0, sizeof (WapiFileTime)); } - return(TRUE); + return TRUE; } typedef struct { gpointer address_start; gpointer address_end; - gchar *perms; + char *perms; gpointer address_offset; dev_t device; ino_t inode; - gchar *filename; + char *filename; } WapiProcModule; static void free_procmodule (WapiProcModule *mod) @@ -1618,9 +1601,9 @@ static GSList *load_modules (FILE *fp) { GSList *ret = NULL; WapiProcModule *mod; - gchar buf[MAXPATHLEN + 1], *p, *endp; - gchar *start_start, *end_start, *prot_start, *offset_start; - gchar *maj_dev_start, *min_dev_start, *inode_start, prot_buf[5]; + char buf[MAXPATHLEN + 1], *p, *endp; + char *start_start, *end_start, *prot_start, *offset_start; + char *maj_dev_start, *min_dev_start, *inode_start, prot_buf[5]; gpointer address_start, address_end, address_offset; guint32 maj_dev, min_dev; ino_t inode; @@ -1734,7 +1717,7 @@ static GSList *load_modules (FILE *fp) } #endif -static gboolean match_procname_to_modulename (gchar *procname, gchar *modulename) +static gboolean match_procname_to_modulename (char *procname, char *modulename) { char* lastsep = NULL; char* lastsep2 = NULL; @@ -1781,13 +1764,13 @@ static FILE * open_process_map (int pid, const char *mode) { FILE *fp = NULL; - const gchar *proc_path[] = { + const char *proc_path[] = { "/proc/%d/maps", /* GNU/Linux */ "/proc/%d/map", /* FreeBSD */ NULL }; int i; - gchar *filename; + char *filename; for (i = 0; fp == NULL && proc_path [i]; i++) { filename = g_strdup_printf (proc_path[i], pid); @@ -1802,8 +1785,7 @@ open_process_map (int pid, const char *mode) gboolean EnumProcessModules (gpointer process, gpointer *modules, guint32 size, guint32 *needed) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; #if !defined(__OpenBSD__) && !defined(PLATFORM_MACOSX) FILE *fp; #endif @@ -1812,7 +1794,7 @@ gboolean EnumProcessModules (gpointer process, gpointer *modules, guint32 count, avail = size / sizeof(gpointer); int i; pid_t pid; - gchar *proc_name = NULL; + char *proc_name = NULL; /* Store modules in an array of pointers (main module as * modules[0]), using the load address for each module as a @@ -1823,20 +1805,17 @@ gboolean EnumProcessModules (gpointer process, gpointer *modules, * implement /dev/kmem reading or whatever other horrid * technique is needed. */ - if (size < sizeof(gpointer)) { - return(FALSE); - } + if (size < sizeof(gpointer)) + return FALSE; - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { - /* This is a pseudo handle */ - pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK); + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) { + pid = WAPI_HANDLE_TO_PID (process); } else { - ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handle); - if (ok == FALSE) { + process_handle = lookup_process_handle (process); + if (!process_handle) { DEBUG ("%s: Can't find process %p", __func__, process); - return(FALSE); + return FALSE; } pid = process_handle->id; proc_name = process_handle->proc_name; @@ -1885,10 +1864,11 @@ gboolean EnumProcessModules (gpointer process, gpointer *modules, g_slist_free (mods); } - return(TRUE); + return TRUE; } -static gchar *get_process_name_from_proc (pid_t pid) +static char * +get_process_name_from_proc (pid_t pid) { #if defined(__OpenBSD__) int mib [6]; @@ -1902,10 +1882,10 @@ static gchar *get_process_name_from_proc (pid_t pid) #endif #else FILE *fp; - gchar *filename = NULL; + char *filename = NULL; #endif - gchar buf[256]; - gchar *ret = NULL; + char buf[256]; + char *ret = NULL; #if defined(PLATFORM_SOLARIS) filename = g_strdup_printf ("/proc/%d/psinfo", pid); @@ -2014,7 +1994,7 @@ static gchar *get_process_name_from_proc (pid_t pid) filename = g_strdup_printf ("/proc/%d/stat", pid); if ((fp = fopen (filename, "r")) != NULL) { if (fgets (buf, 256, fp) != NULL) { - gchar *start, *end; + char *start, *end; start = strchr (buf, '('); if (start != NULL) { @@ -2041,11 +2021,11 @@ static gchar *get_process_name_from_proc (pid_t pid) * Return the full path of the executable of the process PID, or NULL if it cannot be determined. * Returns malloc-ed memory. */ -gchar* +char* wapi_process_get_path (pid_t pid) { #if defined(PLATFORM_MACOSX) && !defined(__mono_ppc__) && defined(TARGET_OSX) - gchar buf [PROC_PIDPATHINFO_MAXSIZE]; + char buf [PROC_PIDPATHINFO_MAXSIZE]; int res; res = proc_pidpath (pid, buf, sizeof (buf)); @@ -2071,15 +2051,15 @@ wapi_process_set_cli_launcher (char *path) cli_launcher = path ? g_strdup (path) : NULL; } -static guint32 get_module_name (gpointer process, gpointer module, - gunichar2 *basename, guint32 size, - gboolean base) +static guint32 +get_module_name (gpointer process, gpointer module, + gunichar2 *basename, guint32 size, + gboolean base) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; pid_t pid; gunichar2 *procname; - gchar *procname_ext = NULL; + char *procname_ext = NULL; glong len; gsize bytes; #if !defined(__OpenBSD__) && !defined(PLATFORM_MACOSX) @@ -2089,29 +2069,27 @@ static guint32 get_module_name (gpointer process, gpointer module, WapiProcModule *found_module; guint32 count; int i; - gchar *proc_name = NULL; + char *proc_name = NULL; DEBUG ("%s: Getting module base name, process handle %p module %p", __func__, process, module); - size = size*sizeof(gunichar2); /* adjust for unicode characters */ + size = size * sizeof(gunichar2); /* adjust for unicode characters */ - if (basename == NULL || size == 0) { - return(0); - } + if (basename == NULL || size == 0) + return 0; - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) { /* This is a pseudo handle */ - pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK); + pid = (pid_t)WAPI_HANDLE_TO_PID (process); proc_name = get_process_name_from_proc (pid); } else { - ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handle); - if (ok == FALSE) { + process_handle = lookup_process_handle (process); + if (!process_handle) { DEBUG ("%s: Can't find process %p", __func__, process); - return(0); + return 0; } pid = process_handle->id; proc_name = g_strdup (process_handle->proc_name); @@ -2206,23 +2184,25 @@ static guint32 get_module_name (gpointer process, gpointer module, return(0); } -guint32 GetModuleBaseName (gpointer process, gpointer module, - gunichar2 *basename, guint32 size) +guint32 + GetModuleBaseName (gpointer process, gpointer module, + gunichar2 *basename, guint32 size) { - return(get_module_name (process, module, basename, size, TRUE)); + return get_module_name (process, module, basename, size, TRUE); } -guint32 GetModuleFileNameEx (gpointer process, gpointer module, - gunichar2 *filename, guint32 size) +guint32 + GetModuleFileNameEx (gpointer process, gpointer module, + gunichar2 *filename, guint32 size) { - return(get_module_name (process, module, filename, size, FALSE)); + return get_module_name (process, module, filename, size, FALSE); } -gboolean GetModuleInformation (gpointer process, gpointer module, - WapiModuleInfo *modinfo, guint32 size) +gboolean +GetModuleInformation (gpointer process, gpointer module, + WapiModuleInfo *modinfo, guint32 size) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; pid_t pid; #if !defined(__OpenBSD__) && !defined(PLATFORM_MACOSX) FILE *fp; @@ -2232,27 +2212,24 @@ gboolean GetModuleInformation (gpointer process, gpointer module, guint32 count; int i; gboolean ret = FALSE; - gchar *proc_name = NULL; + char *proc_name = NULL; DEBUG ("%s: Getting module info, process handle %p module %p", __func__, process, module); - if (modinfo == NULL || size < sizeof(WapiModuleInfo)) { - return(FALSE); - } + if (modinfo == NULL || size < sizeof (WapiModuleInfo)) + return FALSE; - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { - /* This is a pseudo handle */ - pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK); + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) { + pid = (pid_t)WAPI_HANDLE_TO_PID (process); proc_name = get_process_name_from_proc (pid); } else { - ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handle); - if (ok == FALSE) { + process_handle = lookup_process_handle (process); + if (!process_handle) { DEBUG ("%s: Can't find process %p", __func__, process); - return(FALSE); + return FALSE; } pid = process_handle->id; proc_name = g_strdup (process_handle->proc_name); @@ -2268,7 +2245,7 @@ gboolean GetModuleInformation (gpointer process, gpointer module, * for now */ g_free (proc_name); - return(FALSE); + return FALSE; } else { mods = load_modules (fp); fclose (fp); @@ -2281,7 +2258,7 @@ gboolean GetModuleInformation (gpointer process, gpointer module, */ for (i = 0; i < count; i++) { found_module = (WapiProcModule *)g_slist_nth_data (mods, i); - if ( ret == FALSE && + if (ret == FALSE && ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) || (module != NULL && found_module->address_start == module))) { modinfo->lpBaseOfDll = found_module->address_start; @@ -2297,84 +2274,74 @@ gboolean GetModuleInformation (gpointer process, gpointer module, g_free (proc_name); } - return(ret); + return ret; } -gboolean GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max) +gboolean +GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; - if(min==NULL || max==NULL) { + if (min == NULL || max == NULL) /* Not sure if w32 allows NULLs here or not */ - return(FALSE); - } + return FALSE; - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { - /* This is a pseudo handle, so just fail for now - */ - return(FALSE); - } + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) + /* This is a pseudo handle, so just fail for now */ + return FALSE; - ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handle); - if(ok==FALSE) { + process_handle = lookup_process_handle (process); + if (!process_handle) { DEBUG ("%s: Can't find process %p", __func__, process); - return(FALSE); + return FALSE; } - *min=process_handle->min_working_set; - *max=process_handle->max_working_set; + *min = process_handle->min_working_set; + *max = process_handle->max_working_set; - return(TRUE); + return TRUE; } -gboolean SetProcessWorkingSetSize (gpointer process, size_t min, size_t max) +gboolean +SetProcessWorkingSetSize (gpointer process, size_t min, size_t max) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) /* This is a pseudo handle, so just fail for now */ - return(FALSE); - } + return FALSE; - ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS, - (gpointer *)&process_handle); - if(ok==FALSE) { + process_handle = lookup_process_handle (process); + if (!process_handle) { DEBUG ("%s: Can't find process %p", __func__, process); - return(FALSE); + return FALSE; } - process_handle->min_working_set=min; - process_handle->max_working_set=max; + process_handle->min_working_set = min; + process_handle->max_working_set = max; - return(TRUE); + return TRUE; } gboolean TerminateProcess (gpointer process, gint32 exitCode) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; int signo; int ret; pid_t pid; - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) { /* This is a pseudo handle */ - pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK); + pid = (pid_t)WAPI_HANDLE_TO_PID (process); } else { - ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS, - (gpointer *) &process_handle); - - if (ok == FALSE) { - DEBUG ("%s: Can't find process %p", __func__, - process); + process_handle = lookup_process_handle (process); + if (!process_handle) { + DEBUG ("%s: Can't find process %p", __func__, process); SetLastError (ERROR_INVALID_HANDLE); return FALSE; } @@ -2406,19 +2373,16 @@ guint32 GetPriorityClass (gpointer process) { #ifdef HAVE_GETPRIORITY - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; int ret; pid_t pid; - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) { /* This is a pseudo handle */ - pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK); + pid = (pid_t)WAPI_HANDLE_TO_PID (process); } else { - ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS, - (gpointer *) &process_handle); - - if (!ok) { + process_handle = lookup_process_handle (process); + if (!process_handle) { SetLastError (ERROR_INVALID_HANDLE); return FALSE; } @@ -2466,20 +2430,17 @@ gboolean SetPriorityClass (gpointer process, guint32 priority_class) { #ifdef HAVE_SETPRIORITY - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; int ret; int prio; pid_t pid; - if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) { /* This is a pseudo handle */ - pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK); + pid = (pid_t)WAPI_HANDLE_TO_PID (process); } else { - ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS, - (gpointer *) &process_handle); - - if (!ok) { + process_handle = lookup_process_handle (process); + if (!process_handle) { SetLastError (ERROR_INVALID_HANDLE); return FALSE; } @@ -2624,11 +2585,11 @@ mono_processes_cleanup (void) static void process_close (gpointer handle, gpointer data) { - struct _WapiHandle_process *process_handle; + WapiHandle_process *process_handle; DEBUG ("%s", __func__); - process_handle = (struct _WapiHandle_process *) data; + process_handle = (WapiHandle_process *) data; if (process_handle->mono_process && process_handle->self == _wapi_getpid ()) InterlockedDecrement (&process_handle->mono_process->handle_count); mono_processes_cleanup (); @@ -2641,9 +2602,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi int pid; struct MonoProcess *p; -#if DEBUG - fprintf (stdout, "SIG CHILD handler for pid: %i\n", info->si_pid); -#endif + DEBUG ("SIG CHILD handler for pid: %i\n", info->si_pid); InterlockedIncrement (&mono_processes_read_lock); @@ -2655,9 +2614,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi if (pid <= 0) break; -#if DEBUG - fprintf (stdout, "child ended: %i", pid); -#endif + DEBUG ("child ended: %i", pid); p = mono_processes; while (p != NULL) { if (p->pid == pid) { @@ -2672,14 +2629,13 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi InterlockedDecrement (&mono_processes_read_lock); -#if DEBUG - fprintf (stdout, "SIG CHILD handler: done looping."); -#endif + DEBUG ("SIG CHILD handler: done looping."); } #endif -static void process_add_sigchld_handler (void) +static void +process_add_sigchld_handler (void) { #if HAVE_SIGACTION struct sigaction sa; @@ -2692,10 +2648,10 @@ static void process_add_sigchld_handler (void) #endif } -static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertable) +static guint32 +process_wait (gpointer handle, guint32 timeout, gboolean alertable) { - struct _WapiHandle_process *process_handle; - gboolean ok; + WapiHandle_process *process_handle; pid_t pid, ret; int status; guint32 start; @@ -2705,7 +2661,7 @@ static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertabl gpointer current_thread; current_thread = wapi_get_current_thread_handle (); - if (current_thread == NULL) { + if (!current_thread) { SetLastError (ERROR_INVALID_HANDLE); return WAIT_FAILED; } @@ -2716,8 +2672,8 @@ static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertabl DEBUG ("%s (%p, %u)", __func__, handle, timeout); - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS, (gpointer *)&process_handle); - if (ok == FALSE) { + process_handle = lookup_process_handle (handle); + if (!process_handle) { g_warning ("%s: error looking up process handle %p", __func__, handle); return WAIT_FAILED; } From f927c83afe311e4fc3fcb4e996351cbbd2cad802 Mon Sep 17 00:00:00 2001 From: Joerg Rosenkranz Date: Fri, 10 Oct 2014 15:01:37 +0200 Subject: [PATCH 392/543] Prevent NullReferenceException in case of missing Host Do not throw a NullReferenceException when Host variable is not set. Ignore the calls to RegisterObject and UnregisterObject instead. --- .../System.Web.Hosting/HostingEnvironment.cs | 8 ++++++-- .../System.Web.Hosting/HostingEnvironmentTest.cs | 13 +++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/mcs/class/System.Web/System.Web.Hosting/HostingEnvironment.cs b/mcs/class/System.Web/System.Web.Hosting/HostingEnvironment.cs index f5855311943..a2b87e029ce 100644 --- a/mcs/class/System.Web/System.Web.Hosting/HostingEnvironment.cs +++ b/mcs/class/System.Web/System.Web.Hosting/HostingEnvironment.cs @@ -160,7 +160,9 @@ public static void RegisterObject (IRegisteredObject obj) { if (obj == null) throw new ArgumentNullException ("obj"); - Host.RegisterObject (obj, false); + + if (Host != null) + Host.RegisterObject (obj, false); } public static void RegisterVirtualPathProvider (VirtualPathProvider virtualPathProvider) @@ -200,7 +202,9 @@ public static void UnregisterObject (IRegisteredObject obj) { if (obj == null) throw new ArgumentNullException ("obj"); - Host.UnregisterObject (obj); + + if (Host != null) + Host.UnregisterObject (obj); } } } diff --git a/mcs/class/System.Web/Test/System.Web.Hosting/HostingEnvironmentTest.cs b/mcs/class/System.Web/Test/System.Web.Hosting/HostingEnvironmentTest.cs index eb3aa2a3e00..2f039d02894 100644 --- a/mcs/class/System.Web/Test/System.Web.Hosting/HostingEnvironmentTest.cs +++ b/mcs/class/System.Web/Test/System.Web.Hosting/HostingEnvironmentTest.cs @@ -35,6 +35,10 @@ using MonoTests.SystemWeb.Framework; namespace MonoTests.System.Web.Hosting { + public class MyRegisteredObject : IRegisteredObject { + public void Stop(bool immediate) {} + } + [TestFixture] public class HostingEnvironmentTest { [Test] @@ -105,6 +109,15 @@ public void MapPath3 () { Assert.IsNull (HostingEnvironment.MapPath ("hola")); } + + [Test] + public void RegisterAndUnregisterObject () + { + var registered = new MyRegisteredObject (); + + HostingEnvironment.RegisterObject (registered); + HostingEnvironment.UnregisterObject (registered); + } } } #endif From 6e4ab1d3eba3a4ed827016859444711624b83f10 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 12 Oct 2014 18:02:29 -0400 Subject: [PATCH 393/543] [runtime] Remove some dead code from the io-layer process code, avoid mixing ifdefs with control flow. --- mono/io-layer/processes.c | 144 +++++++++++++++----------------------- 1 file changed, 56 insertions(+), 88 deletions(-) diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index 6e19ab98317..43da2d850cb 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -237,42 +237,6 @@ utf16_concat (const gunichar2 *first, ...) return ret; } -#ifdef PLATFORM_MACOSX - -/* 0 = no detection; -1 = not 10.5 or higher; 1 = 10.5 or higher */ -static int osx_10_5_or_higher; - -static void -detect_osx_10_5_or_higher (void) -{ - struct utsname u; - char *p; - int v; - - if (uname (&u) != 0){ - osx_10_5_or_higher = 1; - return; - } - - p = u.release; - v = atoi (p); - - if (v < 9) - osx_10_5_or_higher = -1; - else - osx_10_5_or_higher = 1; -} - -static gboolean -is_macos_10_5_or_higher (void) -{ - if (osx_10_5_or_higher == 0) - detect_osx_10_5_or_higher (); - - return (osx_10_5_or_higher == 1); -} -#endif - static const gunichar2 utf16_space_bytes [2] = { 0x20, 0 }; static const gunichar2 *utf16_space = utf16_space_bytes; static const gunichar2 utf16_quote_bytes [2] = { 0x22, 0 }; @@ -1822,47 +1786,53 @@ gboolean EnumProcessModules (gpointer process, gpointer *modules, } #if defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__HAIKU__) - { - mods = load_modules (); + mods = load_modules (); + if (!proc_name) { + modules[0] = NULL; + *needed = sizeof(gpointer); + return TRUE; + } #else - if ((fp = open_process_map (pid, "r")) == NULL) { + fp = open_process_map (pid, "r"); + if (!fp) { /* No /proc//maps so just return the main module * shortcut for now */ modules[0] = NULL; *needed = sizeof(gpointer); - } else { - mods = load_modules (fp); - fclose (fp); + return TRUE; + } + mods = load_modules (fp); + fclose (fp); #endif - count = g_slist_length (mods); + count = g_slist_length (mods); - /* count + 1 to leave slot 0 for the main module */ - *needed = sizeof(gpointer) * (count + 1); - - /* Use the NULL shortcut, as the first line in - * /proc//maps isn't the executable, and we need - * that first in the returned list. Check the module name - * to see if it ends with the proc name and substitute - * the first entry with it. FIXME if this turns out to - * be a problem. - */ - modules[0] = NULL; - for (i = 0; i < (avail - 1) && i < count; i++) { - module = (WapiProcModule *)g_slist_nth_data (mods, i); - if (modules[0] != NULL) - modules[i] = module->address_start; - else if (match_procname_to_modulename (proc_name, module->filename)) - modules[0] = module->address_start; - else - modules[i + 1] = module->address_start; - } + /* count + 1 to leave slot 0 for the main module */ + *needed = sizeof(gpointer) * (count + 1); + + /* + * Use the NULL shortcut, as the first line in + * /proc//maps isn't the executable, and we need + * that first in the returned list. Check the module name + * to see if it ends with the proc name and substitute + * the first entry with it. FIXME if this turns out to + * be a problem. + */ + modules[0] = NULL; + for (i = 0; i < (avail - 1) && i < count; i++) { + module = (WapiProcModule *)g_slist_nth_data (mods, i); + if (modules[0] != NULL) + modules[i] = module->address_start; + else if (match_procname_to_modulename (proc_name, module->filename)) + modules[0] = module->address_start; + else + modules[i + 1] = module->address_start; + } - for (i = 0; i < count; i++) { - free_procmodule (g_slist_nth_data (mods, i)); - } - g_slist_free (mods); + for (i = 0; i < count; i++) { + free_procmodule (g_slist_nth_data (mods, i)); } + g_slist_free (mods); return TRUE; } @@ -2185,15 +2155,15 @@ get_module_name (gpointer process, gpointer module, } guint32 - GetModuleBaseName (gpointer process, gpointer module, - gunichar2 *basename, guint32 size) +GetModuleBaseName (gpointer process, gpointer module, + gunichar2 *basename, guint32 size) { return get_module_name (process, module, basename, size, TRUE); } guint32 - GetModuleFileNameEx (gpointer process, gpointer module, - gunichar2 *filename, guint32 size) +GetModuleFileNameEx (gpointer process, gpointer module, + gunichar2 *filename, guint32 size) { return get_module_name (process, module, filename, size, FALSE); } @@ -2236,8 +2206,7 @@ GetModuleInformation (gpointer process, gpointer module, } #if defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__HAIKU__) - { - mods = load_modules (); + mods = load_modules (); #else /* Look up the address in /proc//maps */ if ((fp = open_process_map (pid, "r")) == NULL) { @@ -2246,21 +2215,21 @@ GetModuleInformation (gpointer process, gpointer module, */ g_free (proc_name); return FALSE; - } else { - mods = load_modules (fp); - fclose (fp); + } + mods = load_modules (fp); + fclose (fp); #endif - count = g_slist_length (mods); + count = g_slist_length (mods); - /* If module != NULL compare the address. - * If module == NULL we are looking for the main module. - * The best we can do for now check it the module name end with the process name. - */ - for (i = 0; i < count; i++) { + /* If module != NULL compare the address. + * If module == NULL we are looking for the main module. + * The best we can do for now check it the module name end with the process name. + */ + for (i = 0; i < count; i++) { found_module = (WapiProcModule *)g_slist_nth_data (mods, i); if (ret == FALSE && - ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) || - (module != NULL && found_module->address_start == module))) { + ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) || + (module != NULL && found_module->address_start == module))) { modinfo->lpBaseOfDll = found_module->address_start; modinfo->SizeOfImage = (gsize)(found_module->address_end) - (gsize)(found_module->address_start); modinfo->EntryPoint = found_module->address_offset; @@ -2268,12 +2237,11 @@ GetModuleInformation (gpointer process, gpointer module, } free_procmodule (found_module); - } - - g_slist_free (mods); - g_free (proc_name); } + g_slist_free (mods); + g_free (proc_name); + return ret; } From f600c130efd744e284a344496e9cc287294f52e1 Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Wed, 1 Oct 2014 11:10:03 +0100 Subject: [PATCH 394/543] Add a third AOT location, alongside ~/.mono/aot-cache and the assembly dir Unless running in on-demand AOT mode, the AOT runtime will look for an AOT cache alongside the assembly (e.g. /usr/lib/mono/4.5/mscorlib.dll.so). This patch adds a second search path to the non-on-demand AOT loader, /usr/lib/mono/aot-cache/ARCHITECTURE/path/to/assembly.dll.so This new structure makes it possible to have more than one Mono architecture on a system, sharing assemblies but not sharing AOT caches (for example, i386 and amd64 Mono on the same system, for different needs) --- mono/mini/aot-runtime.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index e9b5f42668a..e651a278e83 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1779,6 +1779,14 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) if (!sofile) { mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module '%s' not found: %s\n", aot_name, err); g_free (err); + + aot_name = g_strdup_printf ("%s/mono/aot-cache/%s/%s%s", mono_assembly_getrootdir(), ARCHITECTURE, basename (assembly->image->name), SHARED_EXT); + sofile = mono_dl_open (aot_name, MONO_DL_LAZY, &err); + if (!sofile) { + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module '%s' not found: %s\n", aot_name, err); + g_free (err); + } + } } } From 10b5567b3d477902d2eb4ffa9b606c52edf68964 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 13 Oct 2014 12:28:08 +0200 Subject: [PATCH 395/543] [mcs] A pointer-type may be used as the type of a volatile field. Fixes #23770 --- mcs/errors/cs0677-5.cs | 11 +++++++++++ mcs/mcs/field.cs | 16 +++++++++++++++- mcs/tests/test-251.cs | 7 +++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 mcs/errors/cs0677-5.cs diff --git a/mcs/errors/cs0677-5.cs b/mcs/errors/cs0677-5.cs new file mode 100644 index 00000000000..a6d22486408 --- /dev/null +++ b/mcs/errors/cs0677-5.cs @@ -0,0 +1,11 @@ +// CS0677: `X.e': A volatile field cannot be of the type `E' +// Line: 10 + +enum E : long +{ +} + +class X +{ + volatile E e; +} diff --git a/mcs/mcs/field.cs b/mcs/mcs/field.cs index e3555b9383e..3531af044f3 100644 --- a/mcs/mcs/field.cs +++ b/mcs/mcs/field.cs @@ -605,9 +605,23 @@ bool CanBeVolatile () if (TypeSpec.IsReferenceType (MemberType)) return true; - if (MemberType.IsEnum) + if (MemberType.IsPointer) return true; + if (MemberType.IsEnum) { + switch (EnumSpec.GetUnderlyingType (MemberType).BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + return true; + default: + return false; + } + } + return false; } diff --git a/mcs/tests/test-251.cs b/mcs/tests/test-251.cs index 7878999c1d1..3b2ffbaa9c4 100644 --- a/mcs/tests/test-251.cs +++ b/mcs/tests/test-251.cs @@ -1,3 +1,4 @@ +// Compiler options: -unsafe // // Tests the valid value types for volatile fields. // @@ -11,6 +12,9 @@ enum XX { A } +struct S { +} + class X { volatile byte a; volatile sbyte b; @@ -26,6 +30,9 @@ class X { volatile XX dd; volatile IntPtr ip; volatile UIntPtr uip; + unsafe volatile ushort* uc; + unsafe volatile XX* udd; + unsafe volatile S* us; public static void Main () {} } From e3abaa85d8398fccdc931ef4d672acb6c01bd0a5 Mon Sep 17 00:00:00 2001 From: Lance Hepler Date: Mon, 13 Oct 2014 09:28:19 -0700 Subject: [PATCH 396/543] Fix relocatable mono --- mono/mini/driver.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mono/mini/driver.c b/mono/mini/driver.c index 7b34b18df0e..258bae6cbab 100644 --- a/mono/mini/driver.c +++ b/mono/mini/driver.c @@ -1903,6 +1903,9 @@ mono_main (int argc, char* argv[]) mono_load_coree (argv [i]); #endif + /* Set rootdir before loading config */ + mono_set_rootdir (); + /* Parse gac loading options before loading assemblies. */ if (mono_compile_aot || action == DO_EXEC || action == DO_DEBUGGER) { mono_config_parse (config_file); From 4cba98f8c002cdaca0031d07c348704d27c8f8a7 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 13 Oct 2014 18:39:56 -0400 Subject: [PATCH 397/543] [runtime] Fix an SRE assert. Fixes #19039. --- mono/metadata/reflection.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index 1b7570ef8cb..6614b01e1e9 100644 --- a/mono/metadata/reflection.c +++ b/mono/metadata/reflection.c @@ -7802,12 +7802,15 @@ mono_reflection_get_token (MonoObject *obj) if (is_field_on_inst (f->field)) { MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class; - int field_index = f->field - dgclass->fields; - MonoObject *obj; - g_assert (field_index >= 0 && field_index < dgclass->count_fields); - obj = dgclass->field_objects [field_index]; - return mono_reflection_get_token (obj); + if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) { + int field_index = f->field - dgclass->fields; + MonoObject *obj; + + g_assert (field_index >= 0 && field_index < dgclass->count_fields); + obj = dgclass->field_objects [field_index]; + return mono_reflection_get_token (obj); + } } token = mono_class_get_field_token (f->field); } else if (strcmp (klass->name, "MonoProperty") == 0) { From 8f41328a7811fee2798d95ed140e62b3198fc323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Matos?= Date: Tue, 14 Oct 2014 11:46:14 -0400 Subject: [PATCH 398/543] Fixed buildver generated headers automake dependency tracking. We now include buildver-sgen/boehm.h in BUILT_SOURCES to have proper dependency tracking for these generated files. Fixes the MinGW OSX cross build. --- mono/mini/Makefile.am.in | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index f928eec806d..85165ffcb6e 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -726,10 +726,18 @@ clean-local: pkgconfigdir = $(libdir)/pkgconfig +if SUPPORT_SGEN +sgen_built_sources = buildver-sgen.h +endif + +if SUPPORT_BOEHM +boehm_built_sources = buildver-boehm.h +endif + if JIT_SUPPORTED -BUILT_SOURCES = version.h $(arch_built) +BUILT_SOURCES = version.h $(arch_built) $(sgen_built_sources) $(boehm_built_sources) else -BUILT_SOURCES = version.h +BUILT_SOURCES = version.h $(sgen_built_sources) $(boehm_built_sources) endif CLEANFILES= $(BUILT_SOURCES) *.exe *.dll From 55fc7c277ff276b3124c323829f624d3cd294005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= Date: Tue, 14 Oct 2014 19:42:44 +0200 Subject: [PATCH 399/543] Add missing header --- mono/utils/mono-threads-freebsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mono/utils/mono-threads-freebsd.c b/mono/utils/mono-threads-freebsd.c index 7cbbca14b57..cdee0ab4061 100644 --- a/mono/utils/mono-threads-freebsd.c +++ b/mono/utils/mono-threads-freebsd.c @@ -2,6 +2,7 @@ #if defined(__FreeBSD__) +#include #include #include From 855bb5648bbef9ddd9ae021f52086afce33a681d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= Date: Tue, 14 Oct 2014 19:48:31 +0200 Subject: [PATCH 400/543] Fix build on FreeBSD pid_t (used at line 216) is available on Linux in `unistd.h` and so on on FreeBSD (`sys/types.h` to be precise, included in `unistd.h`), yet on FreeBSD this header is not automatically included. --- mono/io-layer/processes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/mono/io-layer/processes.h b/mono/io-layer/processes.h index 99a62faeb1d..26db64fe7dd 100644 --- a/mono/io-layer/processes.h +++ b/mono/io-layer/processes.h @@ -10,6 +10,7 @@ #ifndef _WAPI_PROCESSES_H_ #define _WAPI_PROCESSES_H_ +#include #include #include From 54f5b48d44e61cca5862aca35d0903dd403bd490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= Date: Tue, 14 Oct 2014 20:03:29 +0200 Subject: [PATCH 401/543] Protect #include Protect inclusion as reported by @vargaz --- mono/io-layer/processes.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mono/io-layer/processes.h b/mono/io-layer/processes.h index 26db64fe7dd..c2b78d44387 100644 --- a/mono/io-layer/processes.h +++ b/mono/io-layer/processes.h @@ -10,7 +10,9 @@ #ifndef _WAPI_PROCESSES_H_ #define _WAPI_PROCESSES_H_ +#ifdef HAVE_UNISTD_H #include +#endif #include #include From 30ed59ce3eaf6fa1e1c78681da5443644b12565a Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 14 Oct 2014 15:59:24 -0400 Subject: [PATCH 402/543] Revert "Fixed buildver generated headers automake dependency tracking." This reverts commit 8f41328a7811fee2798d95ed140e62b3198fc323. Revert this for now as it breaks the parallel build. --- mono/mini/Makefile.am.in | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index 85165ffcb6e..f928eec806d 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -726,18 +726,10 @@ clean-local: pkgconfigdir = $(libdir)/pkgconfig -if SUPPORT_SGEN -sgen_built_sources = buildver-sgen.h -endif - -if SUPPORT_BOEHM -boehm_built_sources = buildver-boehm.h -endif - if JIT_SUPPORTED -BUILT_SOURCES = version.h $(arch_built) $(sgen_built_sources) $(boehm_built_sources) +BUILT_SOURCES = version.h $(arch_built) else -BUILT_SOURCES = version.h $(sgen_built_sources) $(boehm_built_sources) +BUILT_SOURCES = version.h endif CLEANFILES= $(BUILT_SOURCES) *.exe *.dll From a9f31e63db668955e2723796201d5c12dd146eae Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 14 Oct 2014 18:11:36 -0400 Subject: [PATCH 403/543] [build] Rework the buildver dep check. --- mono/mini/Makefile.am.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index f928eec806d..104294b401a 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -195,6 +195,8 @@ buildver-boehm.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntime-stat endif @echo "const char *build_date = \"`date`\";" > buildver-boehm.h mono_boehm-main.$(OBJEXT): buildver-boehm.h +main.c: buildver-boehm.h + endif if DISABLE_EXECUTABLES @@ -204,6 +206,8 @@ buildver-sgen.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntimesgen-s endif @echo "const char *build_date = \"`date`\";" > buildver-sgen.h mono_sgen-main-sgen.$(OBJEXT): buildver-sgen.h +main-sgen.c: buildver-sgen.h + if DTRACE_G_REQUIRED LIBMONO_DTRACE_OBJECT = .libs/mono-dtrace.$(OBJEXT) From 727f8fe28dff2b0cdd1d791e29a72bc5346f7971 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 12:53:30 -0400 Subject: [PATCH 404/543] [jit] Fix the return of vtypes containing a single fp member from pinvoke methods on osx/x86. Fixes #23813. --- mono/mini/decompose.c | 17 ++++++++++++----- mono/mini/mini-x86.c | 4 ++++ mono/mini/mini.h | 2 ++ mono/tests/libtest.c | 14 ++++++++++++++ mono/tests/pinvoke2.cs | 16 ++++++++++++++++ 5 files changed, 48 insertions(+), 5 deletions(-) diff --git a/mono/mini/decompose.c b/mono/mini/decompose.c index 07242d86138..84db9c7eab4 100644 --- a/mono/mini/decompose.c +++ b/mono/mini/decompose.c @@ -1330,18 +1330,18 @@ mono_decompose_vtype_opts (MonoCompile *cfg) if (call->vret_in_reg) { MonoCallInst *call2; - /* Replace the vcall with an integer call */ + /* Replace the vcall with a scalar call */ MONO_INST_NEW_CALL (cfg, call2, OP_NOP); memcpy (call2, call, sizeof (MonoCallInst)); switch (ins->opcode) { case OP_VCALL: - call2->inst.opcode = OP_CALL; + call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL : OP_CALL; break; case OP_VCALL_REG: - call2->inst.opcode = OP_CALL_REG; + call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_REG : OP_CALL_REG; break; case OP_VCALL_MEMBASE: - call2->inst.opcode = OP_CALL_MEMBASE; + call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_MEMBASE : OP_CALL_MEMBASE; break; } call2->inst.dreg = alloc_preg (cfg); @@ -1367,12 +1367,19 @@ mono_decompose_vtype_opts (MonoCompile *cfg) break; case 3: case 4: - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg); + if (call->vret_in_reg_fp) + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg); + else + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg); break; case 5: case 6: case 7: case 8: + if (call->vret_in_reg_fp) { + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg); + break; + } #if SIZEOF_REGISTER == 4 /* FIXME Other ABIs might return in different regs than the ones used for LCALL. diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index 5f589b258b8..05b72c05f6b 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -1440,6 +1440,10 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) * result there. */ call->vret_in_reg = TRUE; +#if defined(__APPLE__) + if (cinfo->ret.pair_storage [0] == ArgOnDoubleFpStack || cinfo->ret.pair_storage [0] == ArgOnFloatFpStack) + call->vret_in_reg_fp = TRUE; +#endif if (call->vret_var) NULLIFY_INS (call->vret_var); } diff --git a/mono/mini/mini.h b/mono/mini/mini.h index d507b960ef6..cd38442570c 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -851,6 +851,8 @@ struct MonoCallInst { * calling convention as OP_CALL. */ guint vret_in_reg : 1; + /* Whenever vret_in_reg returns fp values */ + guint vret_in_reg_fp : 1; /* Whenever there is an IMT argument and it is dynamic */ guint dynamic_imt_arg : 1; /* Whenever there is an RGCTX argument */ diff --git a/mono/tests/libtest.c b/mono/tests/libtest.c index e057944bbd7..ceecaf02ae4 100644 --- a/mono/tests/libtest.c +++ b/mono/tests/libtest.c @@ -5313,6 +5313,20 @@ mono_test_marshal_return_lpwstr (void) return res; } +typedef struct { + double d; +} SingleDoubleStruct; + +LIBTEST_API SingleDoubleStruct STDCALL +mono_test_marshal_return_single_double_struct (void) +{ + SingleDoubleStruct res; + + res.d = 3.0; + + return res; +} + #ifndef TARGET_X86 diff --git a/mono/tests/pinvoke2.cs b/mono/tests/pinvoke2.cs index 71c51a7d814..edf9a6dad45 100644 --- a/mono/tests/pinvoke2.cs +++ b/mono/tests/pinvoke2.cs @@ -71,6 +71,11 @@ public struct DelegateStruct { public SimpleDelegate del3; } + [StructLayout (LayoutKind.Sequential)] + public struct SingleDoubleStruct { + public double d; + } + /* sparcv9 has complex conventions when passing structs with doubles in them by value, some simple tests for them */ [StructLayout (LayoutKind.Sequential)] @@ -1800,5 +1805,16 @@ public static int test_0_native_thiscall () return 0; } + + [DllImport ("libtest", EntryPoint = "mono_test_marshal_return_single_double_struct")] + public static extern SingleDoubleStruct mono_test_marshal_return_single_double_struct (); + + public static int test_0_x86_single_double_struct_ret () { + double d = mono_test_marshal_return_single_double_struct ().d; + if (d != 3.0) + return 1; + else + return 0; + } } From e78e74cc1cda118a5c127009e52e2a9f5a2d433a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Matos?= Date: Wed, 15 Oct 2014 14:37:25 -0400 Subject: [PATCH 405/543] Fixed linking on MinGW. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 38b678c9d80..7b675e4a1ef 100644 --- a/configure.ac +++ b/configure.ac @@ -117,7 +117,7 @@ case "$host" in HOST_CC="gcc" # Windows XP SP2 is required CPPFLAGS="$CPPFLAGS -DWINVER=0x0502 -D_WIN32_WINNT=0x0502 -D_WIN32_IE=0x0501 -D_UNICODE -DUNICODE -DWIN32_THREADS -DFD_SETSIZE=1024" - LDFLAGS="$LDFLAGS -lmswsock -lws2_32 -lole32 -loleaut32 -lpsapi -lversion -ladvapi32 -lwinmm -lkernel32" + LDFLAGS="$LDFLAGS -lmswsock -lws2_32 -lole32 -loleaut32 -lpsapi -lversion -ladvapi32 -lwinmm -lkernel32 -liphlpapi" libmono_cflags="-mms-bitfields -mwindows" libmono_ldflags="-mms-bitfields -mwindows" libdl= From bf87077ac90946229f356cc2f6eded8d77189da3 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 14:50:58 -0400 Subject: [PATCH 406/543] [io-layer] Make process handles non-shared. Fixes #23423. --- mono/io-layer/processes.c | 80 ++++-------------------------------- mono/io-layer/wapi-private.h | 5 +-- mono/mini/wapihandles.c | 17 +------- 3 files changed, 11 insertions(+), 91 deletions(-) diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index 43da2d850cb..e248a86e72a 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -1139,85 +1139,21 @@ GetProcessId (gpointer handle) return process_handle->id; } -/* Returns the process id as a convenience to the functions that call this */ -static pid_t -signal_process_if_gone (gpointer handle) +static gboolean +process_open_compare (gpointer handle, gpointer user_data) { + pid_t wanted_pid; WapiHandle_process *process_handle; - + pid_t checking_pid; + g_assert (!WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)); - /* Make sure the process is signalled if it has exited - if - * the parent process didn't wait for it then it won't be - */ process_handle = lookup_process_handle (handle); - if (!process_handle) { - /* It's possible that the handle has vanished during - * the _wapi_search_handle before it gets here, so - * don't spam the console with warnings. - */ -/* g_warning ("%s: error looking up process handle %p", - __func__, handle);*/ - - return 0; - } + g_assert (process_handle); DEBUG ("%s: looking at process %d", __func__, process_handle->id); - if (kill (process_handle->id, 0) == -1 && - (errno == ESRCH || - errno == EPERM)) { - /* The process is dead, (EPERM tells us a new process - * has that ID, but as it's owned by someone else it - * can't be the one listed in our shared memory file) - */ - _wapi_shared_handle_set_signal_state (handle, TRUE); - } - - return process_handle->id; -} - -#if 0 -static gboolean -process_enum (gpointer handle, gpointer user_data) -{ - GArray *processes = user_data; - pid_t pid = signal_process_if_gone (handle); - int i; - - if (pid == 0) - return FALSE; - - /* Ignore processes that have already exited (ie they are signalled) */ - if (!_wapi_handle_issignalled (handle)) { - DEBUG ("%s: process %d added to array", __func__, pid); - - /* This ensures that duplicates aren't returned (see - * the comment above _wapi_search_handle () for why - * it's needed - */ - for (i = 0; i < processes->len; i++) { - if (g_array_index (processes, pid_t, i) == pid) { - /* We've already got this one, return - * FALSE to keep searching - */ - return FALSE; - } - } - - g_array_append_val (processes, pid); - } - - /* Return false to keep searching */ - return FALSE; -} -#endif /* 0 */ - -static gboolean -process_open_compare (gpointer handle, gpointer user_data) -{ - pid_t wanted_pid; - pid_t checking_pid = signal_process_if_gone (handle); + checking_pid = process_handle->id; if (checking_pid == 0) return FALSE; @@ -2745,7 +2681,7 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) DEBUG ("%s (%p, %u): Setting pid %d signalled, exit status %d", __func__, handle, timeout, process_handle->id, process_handle->exitstatus); - _wapi_shared_handle_set_signal_state (handle, TRUE); + _wapi_handle_set_signal_state (handle, TRUE, TRUE); _wapi_handle_unlock_shared_handles (); diff --git a/mono/io-layer/wapi-private.h b/mono/io-layer/wapi-private.h index f982d860607..34de2f0fd99 100644 --- a/mono/io-layer/wapi-private.h +++ b/mono/io-layer/wapi-private.h @@ -42,8 +42,7 @@ typedef enum { extern const char *_wapi_handle_typename[]; -#define _WAPI_SHARED_HANDLE(type) (type == WAPI_HANDLE_PROCESS || \ - type == WAPI_HANDLE_NAMEDMUTEX || \ +#define _WAPI_SHARED_HANDLE(type) (type == WAPI_HANDLE_NAMEDMUTEX || \ type == WAPI_HANDLE_NAMEDSEM || \ type == WAPI_HANDLE_NAMEDEVENT) @@ -136,6 +135,7 @@ struct _WapiHandleUnshared struct _WapiHandle_sem sem; struct _WapiHandle_socket sock; struct _WapiHandle_thread thread; + struct _WapiHandle_process process; struct _WapiHandle_shared_ref shared; } u; }; @@ -149,7 +149,6 @@ struct _WapiHandleShared union { - struct _WapiHandle_process process; struct _WapiHandle_namedmutex namedmutex; struct _WapiHandle_namedsem namedsem; struct _WapiHandle_namedevent namedevent; diff --git a/mono/mini/wapihandles.c b/mono/mini/wapihandles.c index c2a31ce1ea3..5f89bcd9eb7 100644 --- a/mono/mini/wapihandles.c +++ b/mono/mini/wapihandles.c @@ -42,7 +42,6 @@ static const gchar *thread_details (struct _WapiHandleShared *handle); static const gchar *namedmutex_details (struct _WapiHandleShared *handle); static const gchar *namedsem_details (struct _WapiHandleShared *handle); static const gchar *namedevent_details (struct _WapiHandleShared *handle); -static const gchar *process_details (struct _WapiHandleShared *handle); /* This depends on the ordering of the enum WapiHandleType in * io-layer/wapi-private.h @@ -58,7 +57,7 @@ static const gchar * (*details[])(struct _WapiHandleShared *)= unshared_details, /* event */ unshared_details, /* socket */ unshared_details, /* find */ - process_details, + unshared_details, /* process */ unshared_details, /* pipe */ namedmutex_details, namedsem_details, @@ -191,20 +190,6 @@ static const gchar *namedevent_details (struct _WapiHandleShared *handle) return(buf); } -static const gchar *process_details (struct _WapiHandleShared *handle) -{ - static gchar buf[80]; - gchar *name; - struct _WapiHandle_process *proc=&handle->u.process; - - name = proc->proc_name; - - g_snprintf (buf, sizeof(buf), "[%25.25s] pid: %5u exit: %u", - name==NULL?(gchar *)"":name, proc->id, proc->exitstatus); - - return(buf); -} - /* The old handles/semdel.c */ int mini_wapi_semdel (int argc, char **argv) { From 2ec479b762d68f1eef16e009bcf3bb1b78601f97 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 15:08:54 -0400 Subject: [PATCH 407/543] [io-layer] Fix the linux build. --- mono/io-layer/handles.c | 59 ----------------------------------------- 1 file changed, 59 deletions(-) diff --git a/mono/io-layer/handles.c b/mono/io-layer/handles.c index 6644f568d59..4e8c5223c75 100644 --- a/mono/io-layer/handles.c +++ b/mono/io-layer/handles.c @@ -1842,65 +1842,6 @@ void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd) } } - for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) { - struct _WapiHandleShared *shared; - struct _WapiHandle_process *process_handle; - - shared = &_wapi_shared_layout->handles[i]; - - if (shared->type == WAPI_HANDLE_PROCESS) { - DIR *fd_dir; - struct dirent *fd_entry; - char subdir[_POSIX_PATH_MAX]; - - process_handle = &shared->u.process; - pid = process_handle->id; - - /* Look in /proc//fd/ but ignore - * /proc//fd/, as we have the - * file open too - */ - g_snprintf (subdir, _POSIX_PATH_MAX, "/proc/%d/fd", - pid); - - fd_dir = opendir (subdir); - if (fd_dir == NULL) { - continue; - } - - DEBUG ("%s: Looking in %s", __func__, subdir); - - proc_fds = TRUE; - - while ((fd_entry = readdir (fd_dir)) != NULL) { - char path[_POSIX_PATH_MAX]; - struct stat link_stat; - - if (!strcmp (fd_entry->d_name, ".") || - !strcmp (fd_entry->d_name, "..") || - (pid == self && - fd == atoi (fd_entry->d_name))) { - continue; - } - - g_snprintf (path, _POSIX_PATH_MAX, - "/proc/%d/fd/%s", pid, - fd_entry->d_name); - - stat (path, &link_stat); - if (link_stat.st_dev == share_info->device && - link_stat.st_ino == share_info->inode) { - DEBUG ("%s: Found it at %s", - __func__, path); - - found = TRUE; - } - } - - closedir (fd_dir); - } - } - if (proc_fds == FALSE) { _wapi_handle_check_share_by_pid (share_info); } else if (found == FALSE) { From b58da19a66d5657e5f302de69938cf29d1ac098d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 15:21:53 -0400 Subject: [PATCH 408/543] [corlib] Implement MonoGenericClass:GetCustomAttributes () for created types. Fixes #23769. --- mcs/class/corlib/System.Reflection/MonoGenericClass.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mcs/class/corlib/System.Reflection/MonoGenericClass.cs b/mcs/class/corlib/System.Reflection/MonoGenericClass.cs index c053a4bbfc3..34c2b848949 100644 --- a/mcs/class/corlib/System.Reflection/MonoGenericClass.cs +++ b/mcs/class/corlib/System.Reflection/MonoGenericClass.cs @@ -495,11 +495,15 @@ public override bool IsDefined (Type attributeType, bool inherit) public override object [] GetCustomAttributes (bool inherit) { + if (IsCreated) + return generic_type.GetCustomAttributes (inherit); throw new NotSupportedException (); } public override object [] GetCustomAttributes (Type attributeType, bool inherit) { + if (IsCreated) + return generic_type.GetCustomAttributes (attributeType, inherit); throw new NotSupportedException (); } From 8e6ae1349970ef2eaa68847ad88094ce7e1d9600 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 16:28:47 -0400 Subject: [PATCH 409/543] [io-layer] More coding convention/formatting fixes. --- mono/io-layer/processes.c | 72 +++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index e248a86e72a..f2b79a43469 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -1980,7 +1980,7 @@ get_module_name (gpointer process, gpointer module, DEBUG ("%s: Getting module base name, process handle %p module %p", __func__, process, module); - size = size * sizeof(gunichar2); /* adjust for unicode characters */ + size = size * sizeof (gunichar2); /* adjust for unicode characters */ if (basename == NULL || size == 0) return 0; @@ -2003,10 +2003,10 @@ get_module_name (gpointer process, gpointer module, /* Look up the address in /proc//maps */ #if defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__HAIKU__) - { - mods = load_modules (); + mods = load_modules (); #else - if ((fp = open_process_map (pid, "r")) == NULL) { + fp = open_process_map (pid, "r"); + if (fp == NULL) { if (errno == EACCES && module == NULL && base == TRUE) { procname_ext = get_process_name_from_proc (pid); } else { @@ -2014,47 +2014,45 @@ get_module_name (gpointer process, gpointer module, * for now */ g_free (proc_name); - return(0); + return 0; } } else { mods = load_modules (fp); fclose (fp); + } #endif - count = g_slist_length (mods); - - /* If module != NULL compare the address. - * If module == NULL we are looking for the main module. - * The best we can do for now check it the module name end with the process name. - */ - for (i = 0; i < count; i++) { - found_module = (WapiProcModule *)g_slist_nth_data (mods, i); - if (procname_ext == NULL && - ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) || - (module != NULL && found_module->address_start == module))) { - if (base) { - procname_ext = g_path_get_basename (found_module->filename); - } else { - procname_ext = g_strdup (found_module->filename); - } - } + count = g_slist_length (mods); - free_procmodule (found_module); + /* If module != NULL compare the address. + * If module == NULL we are looking for the main module. + * The best we can do for now check it the module name end with the process name. + */ + for (i = 0; i < count; i++) { + found_module = (WapiProcModule *)g_slist_nth_data (mods, i); + if (procname_ext == NULL && + ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) || + (module != NULL && found_module->address_start == module))) { + if (base) + procname_ext = g_path_get_basename (found_module->filename); + else + procname_ext = g_strdup (found_module->filename); } - if (procname_ext == NULL) - { - /* If it's *still* null, we might have hit the - * case where reading /proc/$pid/maps gives an - * empty file for this user. - */ - procname_ext = get_process_name_from_proc (pid); - } + free_procmodule (found_module); + } - g_slist_free (mods); - g_free (proc_name); + if (procname_ext == NULL) { + /* If it's *still* null, we might have hit the + * case where reading /proc/$pid/maps gives an + * empty file for this user. + */ + procname_ext = get_process_name_from_proc (pid); } - if (procname_ext != NULL) { + g_slist_free (mods); + g_free (proc_name); + + if (procname_ext) { DEBUG ("%s: Process name is [%s]", __func__, procname_ext); @@ -2062,7 +2060,7 @@ get_module_name (gpointer process, gpointer module, if (procname == NULL) { /* bugger */ g_free (procname_ext); - return(0); + return 0; } len = (bytes / 2); @@ -2084,10 +2082,10 @@ get_module_name (gpointer process, gpointer module, g_free (procname); g_free (procname_ext); - return(len); + return len; } - return(0); + return 0; } guint32 From 179fbf4b2336b27862850f164aa9e1f7df95fa7f Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 16:45:19 -0400 Subject: [PATCH 410/543] [runtime] Use getrlimit () to obtain the size of the fd table instead of getdtablesize () which is getting deprecated in Android. --- configure.ac | 3 ++- mono/io-layer/handles.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 7b675e4a1ef..b7898abe061 100644 --- a/configure.ac +++ b/configure.ac @@ -1194,7 +1194,7 @@ if test x$target_win32 = xno; then AC_CHECK_HEADERS(execinfo.h) - AC_CHECK_HEADERS(sys/auxv.h) + AC_CHECK_HEADERS(sys/auxv.h sys/resource.h) AC_CHECK_FUNCS(getgrgid_r) AC_CHECK_FUNCS(getgrnam_r) @@ -1213,6 +1213,7 @@ if test x$target_win32 = xno; then AC_CHECK_FUNCS(dl_iterate_phdr) AC_CHECK_FUNCS(dladdr) AC_CHECK_FUNCS(sysconf) + AC_CHECK_FUNCS(getrlimit) AC_CHECK_FUNCS(sched_setaffinity) AC_CHECK_FUNCS(sched_getcpu) diff --git a/mono/io-layer/handles.c b/mono/io-layer/handles.c index 4e8c5223c75..cb0033f5a1b 100644 --- a/mono/io-layer/handles.c +++ b/mono/io-layer/handles.c @@ -29,6 +29,9 @@ # include #endif #include +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif #include #include @@ -224,7 +227,18 @@ wapi_init (void) g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0])) == WAPI_HANDLE_COUNT); +#ifdef HAVE_GETRLIMIT + { + struct rlimit limit; + int res; + + res = getrlimit (RLIMIT_NOFILE, &limit); + g_assert (res == 0); + _wapi_fd_reserve = limit.rlim_cur; + } +#else _wapi_fd_reserve = getdtablesize(); +#endif /* This is needed by the code in _wapi_handle_new_internal */ _wapi_fd_reserve = (_wapi_fd_reserve + (_WAPI_HANDLE_INITIAL_COUNT - 1)) & ~(_WAPI_HANDLE_INITIAL_COUNT - 1); From ba6a479e5ddaa77cca7df6f20f01caf954b60d88 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 16:52:56 -0400 Subject: [PATCH 411/543] [io-layer] Remove another usage of getdtablesize (). --- mono/io-layer/handles.c | 28 ++++++++++++++++------------ mono/io-layer/handles.h | 2 ++ mono/io-layer/processes.c | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/mono/io-layer/handles.c b/mono/io-layer/handles.c index cb0033f5a1b..5e706fb7280 100644 --- a/mono/io-layer/handles.c +++ b/mono/io-layer/handles.c @@ -216,6 +216,21 @@ static void handle_cleanup (void) g_free (_wapi_private_handles [i]); } +int +wapi_getdtablesize (void) +{ +#ifdef HAVE_GETRLIMIT + struct rlimit limit; + int res; + + res = getrlimit (RLIMIT_NOFILE, &limit); + g_assert (res == 0); + return limit.rlim_cur; +#else + return getdtablesize (); +#endif +} + /* * wapi_init: * @@ -226,19 +241,8 @@ wapi_init (void) { g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0])) == WAPI_HANDLE_COUNT); - -#ifdef HAVE_GETRLIMIT - { - struct rlimit limit; - int res; - res = getrlimit (RLIMIT_NOFILE, &limit); - g_assert (res == 0); - _wapi_fd_reserve = limit.rlim_cur; - } -#else - _wapi_fd_reserve = getdtablesize(); -#endif + _wapi_fd_reserve = wapi_getdtablesize (); /* This is needed by the code in _wapi_handle_new_internal */ _wapi_fd_reserve = (_wapi_fd_reserve + (_WAPI_HANDLE_INITIAL_COUNT - 1)) & ~(_WAPI_HANDLE_INITIAL_COUNT - 1); diff --git a/mono/io-layer/handles.h b/mono/io-layer/handles.h index 04444d0ae82..31cab7bdb94 100644 --- a/mono/io-layer/handles.h +++ b/mono/io-layer/handles.h @@ -20,6 +20,8 @@ extern gboolean DuplicateHandle (gpointer srcprocess, gpointer src, gpointer tar extern void wapi_init (void); extern void wapi_cleanup (void); +int wapi_getdtablesize (void); + G_END_DECLS #endif /* _WAPI_HANDLES_H_ */ diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index f2b79a43469..9e180d7773c 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -952,7 +952,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, } /* Close all file descriptors */ - for (i = getdtablesize () - 1; i > 2; i--) + for (i = wapi_getdtablesize () - 1; i > 2; i--) close (i); #ifdef DEBUG_ENABLED From 04967b8dba276a86cc8250c7758e3592fc83cdae Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 17:17:41 -0400 Subject: [PATCH 412/543] Fix a warning. --- mono/mini/unwind.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mono/mini/unwind.c b/mono/mini/unwind.c index 31024bfee0f..517c7fbc827 100644 --- a/mono/mini/unwind.c +++ b/mono/mini/unwind.c @@ -498,6 +498,8 @@ mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len, int state_stack_pos; memset (reg_saved, 0, sizeof (reg_saved)); + state_stack [0].cfa_reg = -1; + state_stack [0].cfa_offset = 0; p = unwind_info; pos = 0; From 5a4cd56c04874b6981015da7f969eebd970b1229 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 17:18:21 -0400 Subject: [PATCH 413/543] [runtime] Add a 'shared_handles' --enable-minimal option, same as --disable-shared-handles. --- configure.ac | 8 +++++++- mono/io-layer/shared.c | 3 ++- mono/mini/wapihandles.c | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index b7898abe061..66d9a98c359 100644 --- a/configure.ac +++ b/configure.ac @@ -767,7 +767,7 @@ DISABLED_FEATURES=none AC_ARG_ENABLE(minimal, [ --enable-minimal=LIST drop support for LIST subsystems. LIST is a comma-separated list from: aot, profiler, decimal, pinvoke, debug, appdomains, verifier, reflection_emit, reflection_emit_save, large_code, logging, com, ssa, generics, attach, jit, simd, soft_debug, perfcounters, normalization, assembly_remapping, shared_perfcounters, remoting, - security, sgen_remset, sgen_marksweep_par, sgen_marksweep_fixed, sgen_marksweep_fixed_par, sgen_copying.], + security, sgen_remset, sgen_marksweep_par, sgen_marksweep_fixed, sgen_marksweep_fixed_par, sgen_copying, shared_handles.], [ for feature in `echo "$enable_minimal" | sed -e "s/,/ /g"`; do eval "mono_feature_disable_$feature='yes'" @@ -941,6 +941,11 @@ if test "x$mono_feature_disable_sgen_copying" = "xyes"; then AC_MSG_NOTICE([Disabled major=copying support in SGEN.]) fi +if test "x$mono_feature_disable_shared_handles" = "xyes"; then + AC_DEFINE(DISABLE_SHARED_HANDLES, 1, [Disable inter-process shared handles]) + AC_SUBST(DISABLE_SHARED_HANDLES) +fi + AC_ARG_ENABLE(executables, [ --disable-executables disable the build of the runtime executables], enable_executables=$enableval, enable_executables=yes) AM_CONDITIONAL(DISABLE_EXECUTABLES, test x$enable_executables = xno) @@ -2283,6 +2288,7 @@ if test "x$ac_cv_have_dev_random" = "xno" \ fi AC_MSG_CHECKING([if inter-process shared handles are requested]) +# Same as --enable-minimal=shared_handles AC_ARG_ENABLE(shared-handles, [ --disable-shared-handles disable inter-process shared handles], try_shared_handles=$enableval, try_shared_handles=yes) AC_MSG_RESULT($try_shared_handles) if test "x$try_shared_handles" != "xyes"; then diff --git a/mono/io-layer/shared.c b/mono/io-layer/shared.c index 1800f9b74a7..bfbcd7a1bdf 100644 --- a/mono/io-layer/shared.c +++ b/mono/io-layer/shared.c @@ -157,7 +157,8 @@ _wapi_shm_enabled (void) return FALSE; } -#else +#else /* DISABLE_SHARED_HANDLES */ + /* * Use POSIX shared memory if possible, it is simpler, and it has the advantage that * writes to the shared area does not need to be written to disk, avoiding spinning up diff --git a/mono/mini/wapihandles.c b/mono/mini/wapihandles.c index 5f89bcd9eb7..7bda38843ef 100644 --- a/mono/mini/wapihandles.c +++ b/mono/mini/wapihandles.c @@ -3,7 +3,7 @@ #include "mini.h" -#if defined(HOST_WIN32) || !defined(HAVE_SYS_IPC_H) || !defined(HAVE_SYS_SEM_H) || (defined(__native_client__) && defined(__GLIBC__)) +#if defined(HOST_WIN32) || !defined(HAVE_SYS_IPC_H) || !defined(HAVE_SYS_SEM_H) || (defined(__native_client__) && defined(__GLIBC__)) || defined(DISABLE_SHARED_HANDLES) int mini_wapi_hps (int argc, char **argv) { From 1784575ef20f486c45f816b94756c86e143714d2 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 17:22:08 -0400 Subject: [PATCH 414/543] Include ucontext.h on android if it exists. --- mono/utils/mono-sigcontext.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mono/utils/mono-sigcontext.h b/mono/utils/mono-sigcontext.h index 05817a842f3..eb1e23c6ff9 100644 --- a/mono/utils/mono-sigcontext.h +++ b/mono/utils/mono-sigcontext.h @@ -4,6 +4,9 @@ #include #if defined(PLATFORM_ANDROID) #include +#ifdef HAVE_UCONTEXT_H +#include +#endif #endif #ifdef HAVE_UNISTD_H From b0077e8c2a1a0336ddffecdf3857d689b7f092a0 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 18:50:09 -0400 Subject: [PATCH 415/543] [io-layer] Remove WapiHandle_process.self field, its no longer needed. --- mono/io-layer/process-private.h | 6 +----- mono/io-layer/processes.c | 7 +------ 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/mono/io-layer/process-private.h b/mono/io-layer/process-private.h index a70f6586c12..97b716ad21f 100644 --- a/mono/io-layer/process-private.h +++ b/mono/io-layer/process-private.h @@ -50,8 +50,7 @@ struct MonoProcess { gint32 handle_count; /* the number of handles to this mono_process instance */ /* we keep a ref to the creating _WapiHandle_process handle until * the process has exited, so that the information there isn't lost. - * If we put the information there in this structure, it won't be - * available to other processes when using shared handles. */ + */ gpointer handle; struct MonoProcess *next; }; @@ -60,8 +59,6 @@ struct MonoProcess { /* * _WapiHandle_process is a structure containing all the required information * for process handling. - * The mono_process field is only present if this process has created - * the corresponding process. */ struct _WapiHandle_process { @@ -74,7 +71,6 @@ struct _WapiHandle_process size_t min_working_set; size_t max_working_set; gboolean exited; - pid_t self; /* mono_process is shared among processes, but only usable in the process that created it */ struct MonoProcess *mono_process; }; diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index 9e180d7773c..dc76d2e1488 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -1005,7 +1005,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, _wapi_handle_ref (handle); mono_process->handle = handle; - process_handle_data->self = _wapi_getpid (); process_handle_data->mono_process = mono_process; mono_mutex_lock (&mono_processes_mutex); @@ -2492,7 +2491,7 @@ process_close (gpointer handle, gpointer data) DEBUG ("%s", __func__); process_handle = (WapiHandle_process *) data; - if (process_handle->mono_process && process_handle->self == _wapi_getpid ()) + if (process_handle->mono_process) InterlockedDecrement (&process_handle->mono_process->handle_count); mono_processes_cleanup (); } @@ -2593,10 +2592,6 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) /* We don't need to lock mono_processes here, the entry * has a handle_count > 0 which means it will not be freed. */ mp = process_handle->mono_process; - if (mp && process_handle->self != _wapi_getpid ()) { - /* mono_process points to memory in another process' address space: we can't use it */ - mp = NULL; - } start = mono_msec_ticks (); now = start; From 45deb48384d293e137251815c94044ee428e161e Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 15 Oct 2014 18:56:01 -0400 Subject: [PATCH 416/543] [io-layer] Allocate the process name dynamically to make WapiHandle_process smaller. --- mono/io-layer/process-private.h | 4 +--- mono/io-layer/processes.c | 12 +++++------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/mono/io-layer/process-private.h b/mono/io-layer/process-private.h index 97b716ad21f..1da7f472f00 100644 --- a/mono/io-layer/process-private.h +++ b/mono/io-layer/process-private.h @@ -34,8 +34,6 @@ extern void wapi_processes_cleanup (void); extern struct _WapiHandleOps _wapi_process_ops; -#define _WAPI_PROC_NAME_MAX_LEN _POSIX_PATH_MAX - /* * MonoProcess describes processes we create. * It contains a semaphore that can be waited on in order to wait @@ -67,7 +65,7 @@ struct _WapiHandle_process gpointer main_thread; WapiFileTime create_time; WapiFileTime exit_time; - gchar proc_name[_WAPI_PROC_NAME_MAX_LEN]; + char *proc_name; size_t min_working_set; size_t max_working_set; gboolean exited; diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index dc76d2e1488..fed2a3da24e 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -838,8 +838,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, err_fd = GPOINTER_TO_UINT (GetStdHandle (STD_ERROR_HANDLE)); } - g_strlcpy (process_handle.proc_name, prog, - _WAPI_PROC_NAME_MAX_LEN - 1); + process_handle.proc_name = g_strdup (prog); process_set_defaults (&process_handle); @@ -1075,12 +1074,9 @@ process_set_name (WapiHandle_process *process_handle) if (utf8_progname) { slash = strrchr (utf8_progname, '/'); if (slash) - g_strlcpy (process_handle->proc_name, slash+1, - _WAPI_PROC_NAME_MAX_LEN - 1); + process_handle->proc_name = g_strdup (slash+1); else - g_strlcpy (process_handle->proc_name, utf8_progname, - _WAPI_PROC_NAME_MAX_LEN - 1); - + process_handle->proc_name = g_strdup (utf8_progname); g_free (utf8_progname); } } @@ -2491,6 +2487,8 @@ process_close (gpointer handle, gpointer data) DEBUG ("%s", __func__); process_handle = (WapiHandle_process *) data; + g_free (process_handle->proc_name); + process_handle->proc_name = NULL; if (process_handle->mono_process) InterlockedDecrement (&process_handle->mono_process->handle_count); mono_processes_cleanup (); From 885b065e0633318eec99cb3c55c910c8946fb951 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 16 Oct 2014 14:08:53 +0200 Subject: [PATCH 417/543] [MWF] Use full width for measuring text Previously we applied the padding twice. --- .../System.Windows.Forms/TextRenderer.cs | 14 +++++++++++--- .../System.Windows.Forms/ThemeWin32Classic.cs | 19 ++++++++----------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextRenderer.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextRenderer.cs index 6f3be9db10b..bda5da96f78 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextRenderer.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextRenderer.cs @@ -258,11 +258,19 @@ internal static Size MeasureTextInternal (IDeviceContext dc, string text, Font f StringFormat sf = FlagsToStringFormat (flags); Size retval; - + + int proposedWidth; + if (proposedSize.Width == 0) + proposedWidth = Int32.MaxValue; + else { + proposedWidth = proposedSize.Width; + if ((flags & TextFormatFlags.NoPadding) == 0) + proposedWidth -= 9; + } if (dc is Graphics) - retval = (dc as Graphics).MeasureString (text, font, proposedSize.Width == 0 ? Int32.MaxValue : proposedSize.Width, sf).ToSize (); + retval = (dc as Graphics).MeasureString (text, font, proposedWidth, sf).ToSize (); else - retval = TextRenderer.MeasureString (text, font, proposedSize.Width == 0 ? Int32.MaxValue : proposedSize.Width, sf).ToSize (); + retval = TextRenderer.MeasureString (text, font, proposedWidth, sf).ToSize (); if (retval.Width > 0 && (flags & TextFormatFlags.NoPadding) == 0) retval.Width += 9; diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs index a9ed1ebec31..78a5679ade6 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs @@ -369,21 +369,18 @@ public override void CalculateButtonTextAndImageLayout (Graphics g, ButtonBase b Image image = button.Image; string text = button.Text; Rectangle content_rect = button.PaddingClientRectangle; - if (button.TextImageRelation != TextImageRelation.Overlay) - content_rect.Inflate(-4, -4); - Size text_size = TextRenderer.MeasureTextInternal (g, text, button.Font, content_rect.Size, button.TextFormatFlags, button.UseCompatibleTextRendering); + Size text_size = TextRenderer.MeasureTextInternal (g, text, button.Font, content_rect.Size, button.TextFormatFlags | TextFormatFlags.NoPadding, button.UseCompatibleTextRendering); Size image_size = image == null ? Size.Empty : image.Size; - textRectangle = Rectangle.Empty; + textRectangle = Rectangle.Inflate (content_rect, -4, -4); imageRectangle = Rectangle.Empty; switch (button.TextImageRelation) { case TextImageRelation.Overlay: // Overlay is easy, text always goes here - textRectangle = Rectangle.Inflate (content_rect, -4, -4); - if (button.Pressed) - textRectangle.Offset (1, 1); + if (button.Pressed) + textRectangle.Offset (1, 1); // Image is dependent on ImageAlign if (image == null) @@ -440,16 +437,16 @@ public override void CalculateButtonTextAndImageLayout (Graphics g, ButtonBase b imageRectangle = new Rectangle (image_x, image_y, image_width, image_height); break; case TextImageRelation.ImageAboveText: - LayoutTextAboveOrBelowImage (content_rect, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); + LayoutTextAboveOrBelowImage (textRectangle, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); break; case TextImageRelation.TextAboveImage: - LayoutTextAboveOrBelowImage (content_rect, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); + LayoutTextAboveOrBelowImage (textRectangle, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); break; case TextImageRelation.ImageBeforeText: - LayoutTextBeforeOrAfterImage (content_rect, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); + LayoutTextBeforeOrAfterImage (textRectangle, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); break; case TextImageRelation.TextBeforeImage: - LayoutTextBeforeOrAfterImage (content_rect, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); + LayoutTextBeforeOrAfterImage (textRectangle, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); break; } } From 1189d3706a921f589c4dcc55dcaed5c51fbe6720 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 16 Oct 2014 14:09:24 +0200 Subject: [PATCH 418/543] [MWF] Use full available height for text This is especially relevant if we have to shrink the width because of padding. In this case it is possible that MeasureString calculated that the string would fit in one line, but because of padding we reduce the width. If the button is large enough we want to display additional lines even if MeasureString told us we only need one line. --- .../System.Windows.Forms/ThemeWin32Classic.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs index 78a5679ade6..29921942b4e 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs @@ -532,12 +532,14 @@ private void LayoutTextAboveOrBelowImage (Rectangle totalArea, bool textFirst, S offset += (int)(2 * (excess_height / 3)); if (textFirst) { - final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, totalArea.Top + offset, textSize.Width, textSize.Height); + var textHeight = excess_height >= 0 ? totalArea.Height - imageSize.Height - element_spacing: textSize.Height; + final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, totalArea.Top + offset, textSize.Width, textHeight); final_image_rect = new Rectangle (AlignInRectangle (totalArea, imageSize, imageAlign).Left, final_text_rect.Bottom + element_spacing, imageSize.Width, imageSize.Height); } else { final_image_rect = new Rectangle (AlignInRectangle (totalArea, imageSize, imageAlign).Left, totalArea.Top + offset, imageSize.Width, imageSize.Height); - final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, final_image_rect.Bottom + element_spacing, textSize.Width, textSize.Height); + var textHeight = excess_height >= 0 ? totalArea.Height - final_image_rect.Height : textSize.Height; + final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, final_image_rect.Bottom + element_spacing, textSize.Width, textHeight); if (final_text_rect.Bottom > totalArea.Bottom) final_text_rect.Y = totalArea.Top; From c5d4e39545216fdf5b637eca12774195d9c7cab5 Mon Sep 17 00:00:00 2001 From: Paolo Molaro Date: Thu, 16 Oct 2014 10:39:33 -0400 Subject: [PATCH 419/543] [jit] Fix -O=precomp option to skip generic methods and not crash. --- mono/mini/mini.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 6b4d8bfddad..1ab0ac22f20 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -7955,6 +7955,8 @@ mono_precompile_assembly (MonoAssembly *ass, void *user_data) method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL); if (method->flags & METHOD_ATTRIBUTE_ABSTRACT) continue; + if (method->is_generic || method->klass->generic_container) + continue; count++; if (mini_verbose > 1) { From 97866fc14501588f8773d02fe1596fa2e7cc9a70 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 16 Oct 2014 12:59:06 -0400 Subject: [PATCH 420/543] [io-layer] Remove more dead process code, add comments. --- mono/io-layer/processes.c | 84 ++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 50 deletions(-) diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index fed2a3da24e..3c0531f3de0 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -537,9 +537,9 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, int dummy; struct MonoProcess *mono_process; gboolean fork_failed = FALSE; - + mono_once (&process_sig_chld_once, process_add_sigchld_handler); - + /* appname and cmdline specify the executable and its args: * * If appname is not NULL, it is the name of the executable. @@ -2421,6 +2421,12 @@ mono_processes_cleanup (void) mp = mp->next; } + /* + * Remove processes which exited from the mono_processes list. + * We need to synchronize with the sigchld handler here, which runs + * asynchronously. The handler requires that the mono_processes list + * remain valid. + */ mp = mono_processes; spin = 0; while (mp != NULL) { @@ -2432,6 +2438,10 @@ mono_processes_cleanup (void) /* We've found a candidate */ mono_mutex_lock (&mono_processes_mutex); + /* + * This code can run parallel with the sigchld handler, but the + * modifications it makes are safe. + */ if (candidate == NULL) { /* unlink it */ if (mp == mono_processes) { @@ -2556,14 +2566,6 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) guint32 start; guint32 now; struct MonoProcess *mp; - gboolean spin; - gpointer current_thread; - - current_thread = wapi_get_current_thread_handle (); - if (!current_thread) { - SetLastError (ERROR_INVALID_HANDLE); - return WAIT_FAILED; - } /* FIXME: We can now easily wait on processes that aren't our own children, * but WaitFor*Object won't call us for pseudo handles. */ @@ -2590,44 +2592,33 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) /* We don't need to lock mono_processes here, the entry * has a handle_count > 0 which means it will not be freed. */ mp = process_handle->mono_process; + g_assert (mp); start = mono_msec_ticks (); now = start; - spin = mp == NULL; while (1) { - if (mp != NULL) { - /* We have a semaphore we can wait on */ - if (timeout != INFINITE) { - DEBUG ("%s (%p, %u): waiting on semaphore for %li ms...", - __func__, handle, timeout, (timeout - (now - start))); + if (timeout != INFINITE) { + DEBUG ("%s (%p, %u): waiting on semaphore for %li ms...", + __func__, handle, timeout, (timeout - (now - start))); - ret = MONO_SEM_TIMEDWAIT_ALERTABLE (&mp->exit_sem, (timeout - (now - start)), alertable); - } else { - DEBUG ("%s (%p, %u): waiting on semaphore forever...", - __func__, handle, timeout); - ret = MONO_SEM_WAIT_ALERTABLE (&mp->exit_sem, alertable); - } + ret = MONO_SEM_TIMEDWAIT_ALERTABLE (&mp->exit_sem, (timeout - (now - start)), alertable); + } else { + DEBUG ("%s (%p, %u): waiting on semaphore forever...", + __func__, handle, timeout); + ret = MONO_SEM_WAIT_ALERTABLE (&mp->exit_sem, alertable); + } - if (ret == -1 && errno != EINTR && errno != ETIMEDOUT) { - DEBUG ("%s (%p, %u): sem_timedwait failure: %s", - __func__, handle, timeout, g_strerror (errno)); - /* Should we return a failure here? */ - } + if (ret == -1 && errno != EINTR && errno != ETIMEDOUT) { + DEBUG ("%s (%p, %u): sem_timedwait failure: %s", + __func__, handle, timeout, g_strerror (errno)); + /* Should we return a failure here? */ + } - if (ret == 0) { - /* Success, process has exited */ - MONO_SEM_POST (&mp->exit_sem); - break; - } - } else { - /* We did not create this process, so we can't waidpid / sem_wait it. - * We need to poll for the pid existence */ - DEBUG ("%s (%p, %u): polling on pid...", __func__, handle, timeout); - if (!is_pid_valid (pid)) { - /* Success, process has exited */ - break; - } + if (ret == 0) { + /* Success, process has exited */ + MONO_SEM_POST (&mp->exit_sem); + break; } if (timeout == 0) { @@ -2640,14 +2631,8 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) DEBUG ("%s (%p, %u): WAIT_TIMEOUT", __func__, handle, timeout); return WAIT_TIMEOUT; } - - if (spin) { - /* "timeout - (now - start)" will not underflow, since timeout is always >=0, - * and we passed the check just above */ - _wapi_handle_spin (MIN (100, timeout - (now - start))); - } - if (alertable && _wapi_thread_apc_pending (current_thread)) { + if (alertable && _wapi_thread_cur_apc_pending ()) { DEBUG ("%s (%p, %u): WAIT_IO_COMPLETION", __func__, handle, timeout); return WAIT_IO_COMPLETION; } @@ -2660,11 +2645,10 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) g_assert (ret == 0); status = mp ? mp->status : 0; - if (WIFSIGNALED (status)) { + if (WIFSIGNALED (status)) process_handle->exitstatus = 128 + WTERMSIG (status); - } else { + else process_handle->exitstatus = WEXITSTATUS (status); - } _wapi_time_t_to_filetime (time (NULL), &process_handle->exit_time); process_handle->exited = TRUE; From 6f53824f3513d8e1ebaa47ec259763dbdd6acf70 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 16 Oct 2014 13:53:56 -0400 Subject: [PATCH 421/543] [io-layer] Make _wapi_shm_enabled () inline so more code can be optimized away if shared handles are disabled. --- mono/io-layer/shared.c | 6 +++--- mono/io-layer/shared.h | 14 +++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/mono/io-layer/shared.c b/mono/io-layer/shared.c index bfbcd7a1bdf..eb3ed5a0458 100644 --- a/mono/io-layer/shared.c +++ b/mono/io-layer/shared.c @@ -44,7 +44,7 @@ static mono_mutex_t noshm_sems[_WAPI_SHARED_SEM_COUNT]; -gboolean _wapi_shm_disabled = TRUE; +static gboolean _wapi_shm_disabled = TRUE; static gpointer wapi_storage [16]; @@ -152,7 +152,7 @@ _wapi_shm_detach (_wapi_shm_t type) } gboolean -_wapi_shm_enabled (void) +_wapi_shm_enabled_internal (void) { return FALSE; } @@ -405,7 +405,7 @@ _wapi_shm_file_open (const gchar *filename, guint32 wanted_size) } gboolean -_wapi_shm_enabled (void) +_wapi_shm_enabled_internal (void) { static gboolean env_checked; diff --git a/mono/io-layer/shared.h b/mono/io-layer/shared.h index b175b6e306b..5f66a732e6d 100644 --- a/mono/io-layer/shared.h +++ b/mono/io-layer/shared.h @@ -17,15 +17,23 @@ typedef enum { WAPI_SHM_FILESHARE } _wapi_shm_t; -extern gboolean _wapi_shm_disabled; - extern gpointer _wapi_shm_attach (_wapi_shm_t type); extern void _wapi_shm_detach (_wapi_shm_t type); -extern gboolean _wapi_shm_enabled (void); +extern gboolean _wapi_shm_enabled_internal (void); extern void _wapi_shm_semaphores_init (void); extern void _wapi_shm_semaphores_remove (void); extern int _wapi_shm_sem_lock (int sem); extern int _wapi_shm_sem_trylock (int sem); extern int _wapi_shm_sem_unlock (int sem); +static inline gboolean +_wapi_shm_enabled (void) +{ +#ifdef DISABLE_SHARED_HANDLES + return FALSE; +#else + return _wapi_shm_enabled_internal (); +#endif +} + #endif /* _WAPI_SHARED_H_ */ From ddb83ce17205a60749f965bee44df889b3af5f23 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 16 Oct 2014 16:03:49 -0400 Subject: [PATCH 422/543] [bcl] Add an AppDomain.DoUnhandledException () internal method which can be used to invoke the UnhandledException event handlers. --- mcs/class/corlib/System/AppDomain.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mcs/class/corlib/System/AppDomain.cs b/mcs/class/corlib/System/AppDomain.cs index 07b6fd45590..f04fe2a006d 100644 --- a/mcs/class/corlib/System/AppDomain.cs +++ b/mcs/class/corlib/System/AppDomain.cs @@ -1354,6 +1354,11 @@ private void DoDomainUnload () DomainUnload(this, null); } + internal void DoUnhandledException (UnhandledExceptionEventArgs args) { + if (UnhandledException != null) + UnhandledException (this, args); + } + internal byte[] GetMarshalledDomainObjRef () { ObjRef oref = RemotingServices.Marshal (AppDomain.CurrentDomain, null, typeof (AppDomain)); From 77f9b3dc10c6a2180f950912361407743730483f Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 16 Oct 2014 17:11:19 -0400 Subject: [PATCH 423/543] Fix a warning. --- mono/metadata/sgen-stw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/sgen-stw.c b/mono/metadata/sgen-stw.c index 5a2ab0e9687..2a9bf34788c 100644 --- a/mono/metadata/sgen-stw.c +++ b/mono/metadata/sgen-stw.c @@ -52,7 +52,7 @@ align_pointer (void *ptr) #ifdef USE_MONO_CTX static MonoContext cur_thread_ctx; #else -static mword cur_thread_regs [ARCH_NUM_REGS] = {0}; +static mword cur_thread_regs [ARCH_NUM_REGS]; #endif static void From 36bfeec103adf7a5a492214ef22a58b1b794a727 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 16 Oct 2014 18:35:51 -0400 Subject: [PATCH 424/543] Fix a warning. --- mono/metadata/class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index baa9565e8c9..54d2d5c85a8 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -2477,7 +2477,7 @@ mono_class_setup_events (MonoClass *class) if (class->generic_class) { MonoClass *gklass = class->generic_class->container_class; - MonoGenericContext *context; + MonoGenericContext *context = NULL; mono_class_setup_events (gklass); if (gklass->exception_type) { From b67c4fe1c50905d396d3053f0fd5f28f192646f1 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 17 Oct 2014 12:14:13 -0400 Subject: [PATCH 425/543] Fix a warning. --- mono/io-layer/shared.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mono/io-layer/shared.c b/mono/io-layer/shared.c index eb3ed5a0458..f8539039cad 100644 --- a/mono/io-layer/shared.c +++ b/mono/io-layer/shared.c @@ -44,8 +44,6 @@ static mono_mutex_t noshm_sems[_WAPI_SHARED_SEM_COUNT]; -static gboolean _wapi_shm_disabled = TRUE; - static gpointer wapi_storage [16]; static void @@ -168,6 +166,8 @@ _wapi_shm_enabled_internal (void) #define USE_SHM 1 #endif +static gboolean _wapi_shm_disabled = TRUE; + static gchar * _wapi_shm_base_name (_wapi_shm_t type) { From 6edd8bf89e0e30a08d0ba0a5391a796d94f61abc Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Fri, 17 Oct 2014 15:37:14 -0400 Subject: [PATCH 426/543] [runtime] Don't define ucontext_t for android if PLATFORM is not android. --- mono/utils/mono-sigcontext.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/utils/mono-sigcontext.h b/mono/utils/mono-sigcontext.h index eb1e23c6ff9..cc70df01822 100644 --- a/mono/utils/mono-sigcontext.h +++ b/mono/utils/mono-sigcontext.h @@ -90,7 +90,7 @@ #define UCONTEXT_REG_EIP(ctx) (((ucontext_t*)(ctx))->uc_mcontext.gregs [EIP]) #else -#if defined(TARGET_ANDROID) +#if defined(PLATFORM_ANDROID) /* No ucontext.h as of NDK v6b */ typedef int greg_t; #define NGREG 19 From 0db6c1418f0cea38d6ffa1316989d1b521b8fad1 Mon Sep 17 00:00:00 2001 From: Martin Thwaites Date: Sat, 18 Oct 2014 21:55:47 +0100 Subject: [PATCH 427/543] Implement the ReadEntityBodyMode properties --- .../System.Web/HttpRequestBase.cs | 5 +++ .../System.Web/System.Web-net_4_5.csproj | 1 + .../System.Web/ReadEntityBodyMode.cs | 34 +++++++++++++++++++ .../System.Web/net_4_5_System.Web.dll.sources | 2 ++ 4 files changed, 42 insertions(+) create mode 100644 mcs/class/System.Web/System.Web/ReadEntityBodyMode.cs diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs index 3a4c58e9513..d85d67d55f7 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs @@ -136,6 +136,11 @@ public virtual RequestContext RequestContext { public virtual int TotalBytes { get { NotImplemented (); return 0; } } +#if NET_4_5 + public virtual ReadEntityBodyMode ReadEntityBodyMode { get { NotImplemented(); return ReadEntityBodyMode.Classic; } } + + public virtual UnvalidatedRequestValuesBase Unvalidated { get { NotImplemented (); return null; } } +#endif public virtual Uri Url { get { NotImplemented (); return null; } } public virtual Uri UrlReferrer { get { NotImplemented (); return null; } } diff --git a/mcs/class/System.Web/System.Web-net_4_5.csproj b/mcs/class/System.Web/System.Web-net_4_5.csproj index 787662b4184..186581616b8 100644 --- a/mcs/class/System.Web/System.Web-net_4_5.csproj +++ b/mcs/class/System.Web/System.Web-net_4_5.csproj @@ -1321,6 +1321,7 @@ + diff --git a/mcs/class/System.Web/System.Web/ReadEntityBodyMode.cs b/mcs/class/System.Web/System.Web/ReadEntityBodyMode.cs new file mode 100644 index 00000000000..a97c3cf5f11 --- /dev/null +++ b/mcs/class/System.Web/System.Web/ReadEntityBodyMode.cs @@ -0,0 +1,34 @@ +// +// ReadEntityBodyMode.cs +// +// Author: Martin Thwaites (github@my2cents.co.uk) +// +// Copyright (C) 2014 Martin Thwaites +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +namespace System.Web { + public enum ReadEntityBodyMode { + None, + Classic, + Bufferless, + Buffered, + } +} diff --git a/mcs/class/System.Web/net_4_5_System.Web.dll.sources b/mcs/class/System.Web/net_4_5_System.Web.dll.sources index a7957a0019c..04c7cacd659 100644 --- a/mcs/class/System.Web/net_4_5_System.Web.dll.sources +++ b/mcs/class/System.Web/net_4_5_System.Web.dll.sources @@ -1,3 +1,5 @@ #include net_4_0_System.Web.dll.sources System.Web/MimeMapping.cs +System.Web/ReadEntityBodyMode.cs + From 7eeb7f14f3f6d2adb99d74ec38f810bf03d39983 Mon Sep 17 00:00:00 2001 From: Martin Thwaites Date: Sat, 18 Oct 2014 22:31:14 +0100 Subject: [PATCH 428/543] Implement Request.Abort() --- .../System.Web.Abstractions/System.Web/HttpRequestBase.cs | 6 ++++++ .../System.Web/HttpRequestWrapper.cs | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs index 3a4c58e9513..c2fd990c3d0 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs @@ -148,6 +148,12 @@ public virtual RequestContext RequestContext { public virtual string [] UserLanguages { get { NotImplemented (); return null; } } +#if NET_4_5 + public virtual void Abort () + { + NotImplemented(); + } +#endif public virtual byte [] BinaryRead (int count) { diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs index 41969c6468b..dc5098a3bec 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs @@ -232,6 +232,13 @@ public override string [] UserLanguages { get { return w.UserLanguages; } } +#if NET_4_5 + public void Abort () + { + w.WorkerRequest.CloseConnection(); + } +#endif + public override byte [] BinaryRead (int count) { return w.BinaryRead (count); From ce348f12da5fc1b01124f5dba41f7b8e636628b7 Mon Sep 17 00:00:00 2001 From: Martin Thwaites Date: Mon, 20 Oct 2014 21:34:27 +0100 Subject: [PATCH 429/543] Removed erroneously added property to HttpRequestBase in pull #1353 --- mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs index e80cbe6ad62..3a31754b949 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs @@ -138,8 +138,6 @@ public virtual RequestContext RequestContext { #if NET_4_5 public virtual ReadEntityBodyMode ReadEntityBodyMode { get { NotImplemented(); return ReadEntityBodyMode.Classic; } } - - public virtual UnvalidatedRequestValuesBase Unvalidated { get { NotImplemented (); return null; } } #endif public virtual Uri Url { get { NotImplemented (); return null; } } From 5ae9f7d93f265f2a424cf20171e846f37335824c Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Mon, 6 Oct 2014 17:11:20 -0700 Subject: [PATCH 430/543] [sgen] Fix allowance calculation. The formula for calculating allowance was not only overly complicated but completely broken, which resulted in the allowance always being the minimum (4 times the nursery size). That resulted in too frequent garbage collections when the heap grew larger. Now we do something very similar to what Boehm does: Allow the heap to grow by a third before the next major collection happens. --- mono/metadata/sgen-memory-governor.c | 36 +++++----------------------- 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/mono/metadata/sgen-memory-governor.c b/mono/metadata/sgen-memory-governor.c index 448ebef3f05..881fff34f05 100644 --- a/mono/metadata/sgen-memory-governor.c +++ b/mono/metadata/sgen-memory-governor.c @@ -72,21 +72,13 @@ static mword last_collection_los_memory_alloced; static mword sgen_memgov_available_free_space (void); -static mword -double_to_mword_with_saturation (double value) -{ - if (value >= (double)MWORD_MAX_VALUE) - return MWORD_MAX_VALUE; - return (mword)value; -} - /* GC trigger heuristics. */ static void sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite) { - size_t num_major_sections, num_major_sections_saved; - mword los_memory_saved, new_major, new_heap_size, save_target, allowance_target; + size_t num_major_sections; + mword new_major, new_heap_size, allowance_target; if (overwrite) g_assert (need_calculate_minor_collection_allowance); @@ -102,32 +94,16 @@ sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite) num_major_sections = major_collector.get_num_major_sections (); - num_major_sections_saved = MAX (last_collection_old_num_major_sections - num_major_sections, 0); - los_memory_saved = MAX (last_collection_old_los_memory_usage - last_collection_los_memory_usage, 1); - new_major = num_major_sections * major_collector.section_size; new_heap_size = new_major + last_collection_los_memory_usage; - save_target = (mword)((new_major + last_collection_los_memory_usage) * SGEN_DEFAULT_SAVE_TARGET_RATIO); - /* - * We aim to allow the allocation of as many sections as is - * necessary to reclaim save_target sections in the next - * collection. We assume the collection pattern won't change. - * In the last cycle, we had num_major_sections_saved for - * minor_collection_sections_alloced. Assuming things won't - * change, this must be the same ratio as save_target for - * allowance_target, i.e. - * - * num_major_sections_saved save_target - * --------------------------------- == ---------------- - * minor_collection_sections_alloced allowance_target - * - * hence: + * We allow the heap to grow by one third its current size before we start the next + * major collection. */ - allowance_target = double_to_mword_with_saturation ((double)save_target * (double)(minor_collection_sections_alloced * major_collector.section_size + last_collection_los_memory_alloced) / (double)(num_major_sections_saved * major_collector.section_size + los_memory_saved)); + allowance_target = new_heap_size / 3; - minor_collection_allowance = MAX (MIN (allowance_target, num_major_sections * major_collector.section_size + los_memory_usage), MIN_MINOR_COLLECTION_ALLOWANCE); + minor_collection_allowance = MAX (allowance_target, MIN_MINOR_COLLECTION_ALLOWANCE); if (new_heap_size + minor_collection_allowance > soft_heap_limit) { if (new_heap_size > soft_heap_limit) From 950d9c8a567273c3363f43cee454f2b95a9f5da7 Mon Sep 17 00:00:00 2001 From: Ryan Melena Date: Mon, 13 Oct 2014 21:03:25 -0500 Subject: [PATCH 431/543] Additional JWT Security Token Support Fix line endings. Add test for JavaScriptSerializer.Deserialize(string input, Type targetType). --- .../System.IdentityModel-net_4_5.csproj | 33 +++++++----- .../SecurityTokenExpiredException.cs | 54 +++++++++++++++++++ .../SecurityTokenNotYetValidException.cs | 54 +++++++++++++++++++ .../SecurityTokenReplayDetectedException.cs | 54 +++++++++++++++++++ .../System.IdentityModel.dll.sources | 6 ++- .../SignatureVerificationFailedException.cs | 54 +++++++++++++++++++ .../JavaScriptSerializer.cs | 7 ++- .../JsonDeserializer.cs | 4 +- .../JavaScriptSerializerTest.cs | 16 ++++++ .../corlib/System.Security.Claims/Claim.cs | 5 +- 10 files changed, 268 insertions(+), 19 deletions(-) create mode 100644 mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs create mode 100644 mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs create mode 100644 mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs create mode 100644 mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs diff --git a/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj b/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj index 3022c52ab5b..1e07337738e 100644 --- a/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj +++ b/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj @@ -50,6 +50,7 @@ + @@ -147,9 +148,12 @@ - + + + + @@ -170,7 +174,8 @@ - + + - - - - - - + + + + + + + + + + + - - - - - @@ -236,4 +241,4 @@ - + diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs new file mode 100644 index 00000000000..2f10c949029 --- /dev/null +++ b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs @@ -0,0 +1,54 @@ +// +// SecurityTokenExpiredException.cs +// +// Author: +// Noesis Labs (Ryan.Melena@noesislabs.com) +// +// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#if NET_4_5 + +using System; +using System.Runtime.Serialization; + +namespace System.IdentityModel.Tokens +{ + public class SecurityTokenExpiredException : SecurityTokenValidationException + { + public SecurityTokenExpiredException() + : base("ID4181: The security token has expired.") + { } + + public SecurityTokenExpiredException(string message) + : base(message) + { } + + public SecurityTokenExpiredException(string message, Exception innerException) + : base(message, innerException) + { } + + public SecurityTokenExpiredException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} +#endif diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs new file mode 100644 index 00000000000..9f15b7b6448 --- /dev/null +++ b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs @@ -0,0 +1,54 @@ +// +// SecurityTokenNotYetValidException.cs +// +// Author: +// Noesis Labs (Ryan.Melena@noesislabs.com) +// +// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#if NET_4_5 + +using System; +using System.Runtime.Serialization; + +namespace System.IdentityModel.Tokens +{ + public class SecurityTokenNotYetValidException : SecurityTokenValidationException + { + public SecurityTokenNotYetValidException() + : base("ID4182: The security token is not valid yet.") + { } + + public SecurityTokenNotYetValidException(string message) + : base(message) + { } + + public SecurityTokenNotYetValidException(string message, Exception innerException) + : base(message, innerException) + { } + + public SecurityTokenNotYetValidException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} +#endif diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs new file mode 100644 index 00000000000..eb4a786b336 --- /dev/null +++ b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs @@ -0,0 +1,54 @@ +// +// SecurityTokenReplayDetectedException.cs +// +// Author: +// Noesis Labs (Ryan.Melena@noesislabs.com) +// +// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#if NET_4_5 + +using System; +using System.Runtime.Serialization; + +namespace System.IdentityModel.Tokens +{ + public class SecurityTokenReplayDetectedException : SecurityTokenValidationException + { + public SecurityTokenReplayDetectedException() + : base("ID1070: Replay has been detected for a SecurityToken.") + { } + + public SecurityTokenReplayDetectedException(string message) + : base(message) + { } + + public SecurityTokenReplayDetectedException(string message, Exception innerException) + : base(message, innerException) + { } + + public SecurityTokenReplayDetectedException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} +#endif diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources b/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources index 2c86355259a..4d705d24d57 100755 --- a/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources +++ b/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources @@ -3,6 +3,7 @@ Assembly/AssemblyInfo.cs System.IdentityModel/CookieTransform.cs System.IdentityModel/OpenObject.cs +System.IdentityModel/SignatureVerificationFailedException.cs System.IdentityModel.Claims/Claim.cs System.IdentityModel.Claims/ClaimSet.cs System.IdentityModel.Claims/ClaimTypes.cs @@ -100,9 +101,12 @@ System.IdentityModel.Tokens/SecurityKeyUsage.cs System.IdentityModel.Tokens/SecurityToken.cs System.IdentityModel.Tokens/SecurityTokenDescriptor.cs System.IdentityModel.Tokens/SecurityTokenException.cs +System.IdentityModel.Tokens/SecurityTokenExpiredException.cs System.IdentityModel.Tokens/SecurityTokenHandler.cs System.IdentityModel.Tokens/SecurityTokenHandlerCollection.cs System.IdentityModel.Tokens/SecurityTokenHandlerConfiguration.cs +System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs +System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs System.IdentityModel.Tokens/SecurityTokenTypes.cs System.IdentityModel.Tokens/SecurityTokenValidationException.cs System.IdentityModel.Tokens/SessionSecurityToken.cs @@ -124,4 +128,4 @@ System.IdentityModel.Tokens/X509SubjectKeyIdentifierClause.cs System.IdentityModel.Tokens/X509ThumbprintKeyIdentifierClause.cs System.IdentityModel.Tokens/X509WindowsSecurityToken.cs System.Security.Claims/AuthenticationTypes.cs -System.ServiceModel.Security/X509CertificateValidationMode.cs \ No newline at end of file +System.ServiceModel.Security/X509CertificateValidationMode.cs diff --git a/mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs b/mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs new file mode 100644 index 00000000000..2e1e7115ca9 --- /dev/null +++ b/mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs @@ -0,0 +1,54 @@ +// +// SignatureVerificationFailedException.cs +// +// Author: +// Noesis Labs (Ryan.Melena@noesislabs.com) +// +// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#if NET_4_5 + +using System; +using System.Runtime.Serialization; + +namespace System.IdentityModel +{ + public class SignatureVerificationFailedException : Exception + { + public SignatureVerificationFailedException() + : base("ID4038: Signature verification failed.") + { } + + public SignatureVerificationFailedException(string message) + : base(message) + { } + + public SignatureVerificationFailedException(string message, Exception innerException) + : base(message, innerException) + { } + + public SignatureVerificationFailedException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} +#endif diff --git a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs index 14a03b2f0dc..6a147e2e03e 100644 --- a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs +++ b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs @@ -204,7 +204,12 @@ public T Deserialize (string input) { } public object Deserialize (string input, Type targetType) { - return DeserializeObjectInternal (input); + object obj = DeserializeObjectInternal (input); + + if (obj == null) + return Activator.CreateInstance (targetType); + + return ConvertToType (obj, targetType); } static object Evaluate (object value) { diff --git a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs index 46bef52a7b4..8593e532bf0 100644 --- a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs +++ b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs @@ -833,7 +833,7 @@ bool ProcessCharacter (char ch) void CreateArray () { - var arr = new ArrayList (); + var arr = new List (); PushObject (arr); } @@ -865,7 +865,7 @@ void StoreValue (object o) { Dictionary dict = PeekObject () as Dictionary ; if (dict == null) { - ArrayList arr = PeekObject () as ArrayList; + List arr = PeekObject () as List ; if (arr == null) throw new InvalidOperationException ("Internal error: current object is not a dictionary or an array."); arr.Add (o); diff --git a/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs b/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs index 995590eeb2e..8274ef9c3f8 100644 --- a/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs +++ b/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs @@ -415,6 +415,22 @@ public void TestDeserialize () { //object oo = ser.DeserializeObject ("{value:'Purple\\r \\n monkey\\'s:\\tdishwasher'}"); } + [Test] + public void TestDeserializeNonGenericOverload() + { + JavaScriptSerializer ser = new JavaScriptSerializer(); + Assert.IsNull(ser.Deserialize("", typeof(X))); + + X s = new X(); + s.Init(); + string x = ser.Serialize(s); + + Assert.AreEqual("{\"z\":8,\"ch\":\"v\",\"ch_null\":null,\"str\":\"vwF59g\",\"b\":253,\"sb\":-48,\"sh\":-32740,\"ush\":65511,\"i\":-234235453,\"ui\":4294733061,\"l\":-9223372036854775780,\"ul\":18446744073709551612,\"f\":NaN,\"f1\":-Infinity,\"f2\":Infinity,\"f3\":-3.40282347E+38,\"f4\":3.40282347E+38,\"d\":NaN,\"d1\":-Infinity,\"d2\":Infinity,\"d3\":-1.7976931348623157E+308,\"d4\":1.7976931348623157E+308,\"de\":-1,\"de1\":0,\"de2\":1,\"de3\":-79228162514264337593543950335,\"de4\":79228162514264337593543950335,\"g\":\"000000ea-0002-0162-0102-030405060708\",\"nb\":null,\"dbn\":null,\"uri\":\"http://kostat@mainsoft/adfasdf/asdfasdf.aspx/asda/ads?a=b&c=d\",\"hash\":{\"mykey\":{\"BB\":10}},\"point\":{\"IsEmpty\":false,\"X\":150,\"Y\":150},\"MyEnum\":[1,10,345],\"MyEnum1\":[1,10,345],\"AA\":5,\"AA1\":[{\"BB\":10},{\"BB\":10}],\"BB\":18446744073709551610,\"YY\":[{\"BB\":10},{\"BB\":10}]}", x, "#A1"); + + X n = ser.Deserialize(x, typeof(X)) as X; + Assert.AreEqual(s, n, "#A2"); + } + [Test] public void TestDeserializeTypeResolver () { diff --git a/mcs/class/corlib/System.Security.Claims/Claim.cs b/mcs/class/corlib/System.Security.Claims/Claim.cs index ffb7ce73449..0347052d236 100644 --- a/mcs/class/corlib/System.Security.Claims/Claim.cs +++ b/mcs/class/corlib/System.Security.Claims/Claim.cs @@ -58,6 +58,9 @@ public Claim (string type, string value, string valueType, string issuer, string throw new ArgumentNullException ("type"); if (value == null) throw new ArgumentNullException ("value"); + + Properties = new Dictionary (); + Type = type; Value = value; ValueType = valueType == null ? ClaimValueTypes.String : valueType; @@ -91,4 +94,4 @@ public override string ToString () } } } -#endif \ No newline at end of file +#endif From 8410c9bb00a738a105ed416aae0ddd6e6bfd7523 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 20 Oct 2014 18:07:13 -0400 Subject: [PATCH 432/543] [runtime] Clean up the signal handling code by moving the signal handler signature definitions to mono-signal-handler.h and using them everywhere. --- mono/metadata/console-unix.c | 10 +++--- mono/metadata/sgen-os-posix.c | 8 ++--- mono/mini/mini-posix.c | 43 ++++++++++++-------------- mono/mini/mini.c | 34 +++++++++------------ mono/mini/mini.h | 52 ++++---------------------------- mono/utils/mono-signal-handler.h | 44 +++++++++++++++++++++------ 6 files changed, 85 insertions(+), 106 deletions(-) diff --git a/mono/metadata/console-unix.c b/mono/metadata/console-unix.c index 6a70b350085..dffba190e31 100644 --- a/mono/metadata/console-unix.c +++ b/mono/metadata/console-unix.c @@ -277,7 +277,7 @@ mono_console_handle_async_ops (void) static gboolean in_sigint; -MONO_SIGNAL_HANDLER_FUNC (static, sigint_handler, (int signo)) +MONO_SIG_HANDLER_FUNC (static, sigint_handler) { int save_errno; MONO_ARCH_SAVE_REGS; @@ -295,7 +295,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, sigint_handler, (int signo)) static struct sigaction save_sigcont, save_sigint, save_sigwinch; -MONO_SIGNAL_HANDLER_FUNC (static, sigcont_handler, (int signo, void *the_siginfo, void *data)) +MONO_SIG_HANDLER_FUNC (static, sigcont_handler) { int unused; // Ignore error, there is not much we can do in the sigcont handler. @@ -308,10 +308,10 @@ MONO_SIGNAL_HANDLER_FUNC (static, sigcont_handler, (int signo, void *the_siginfo if (save_sigcont.sa_sigaction != NULL && save_sigcont.sa_sigaction != (void *)SIG_DFL && save_sigcont.sa_sigaction != (void *)SIG_IGN) - (*save_sigcont.sa_sigaction) (signo, the_siginfo, data); + (*save_sigcont.sa_sigaction) (MONO_SIG_HANDLER_PARAMS); } -MONO_SIGNAL_HANDLER_FUNC (static, sigwinch_handler, (int signo, void *the_siginfo, void *data)) +MONO_SIG_HANDLER_FUNC (static, sigwinch_handler) { int dims = terminal_get_dimensions (); if (dims != -1) @@ -321,7 +321,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, sigwinch_handler, (int signo, void *the_siginf if (save_sigwinch.sa_sigaction != NULL && save_sigwinch.sa_sigaction != (void *)SIG_DFL && save_sigwinch.sa_sigaction != (void *)SIG_IGN) - (*save_sigwinch.sa_sigaction) (signo, the_siginfo, data); + (*save_sigwinch.sa_sigaction) (MONO_SIG_HANDLER_PARAMS); } /* diff --git a/mono/metadata/sgen-os-posix.c b/mono/metadata/sgen-os-posix.c index 9918d16adc5..55acf5137c3 100644 --- a/mono/metadata/sgen-os-posix.c +++ b/mono/metadata/sgen-os-posix.c @@ -135,7 +135,7 @@ suspend_thread (SgenThreadInfo *info, void *context) } /* LOCKING: assumes the GC lock is held (by the stopping thread) */ -MONO_SIGNAL_HANDLER_FUNC (static, suspend_handler, (int sig, siginfo_t *siginfo, void *context)) +MONO_SIG_HANDLER_FUNC (static, suspend_handler) { /* * The suspend signal handler potentially uses syscalls that @@ -144,19 +144,19 @@ MONO_SIGNAL_HANDLER_FUNC (static, suspend_handler, (int sig, siginfo_t *siginfo, * must restore those to the values they had when we * interrupted. */ - SgenThreadInfo *info; int old_errno = errno; int hp_save_index = mono_hazard_pointer_save_for_signal_handler (); + MONO_SIG_HANDLER_GET_CONTEXT; info = mono_thread_info_current (); - suspend_thread (info, context); + suspend_thread (info, ctx); mono_hazard_pointer_restore_for_signal_handler (hp_save_index); errno = old_errno; } -MONO_SIGNAL_HANDLER_FUNC (static, restart_handler, (int sig)) +MONO_SIG_HANDLER_FUNC (static, restart_handler) { SgenThreadInfo *info; int old_errno = errno; diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index d26b4af4e92..98b396bbf26 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -81,7 +81,7 @@ mono_runtime_shutdown_stat_profiler (void) gboolean -SIG_HANDLER_SIGNATURE (mono_chain_signal) +MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) { return FALSE; } @@ -173,12 +173,11 @@ free_saved_signal_handlers (void) * was called, false otherwise. */ gboolean -SIG_HANDLER_SIGNATURE (mono_chain_signal) +MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) { - int signal = _dummy; + int signal = MONO_SIG_HANDLER_GET_SIGNO (); struct sigaction *saved_handler = get_saved_signal_handler (signal); - - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; if (saved_handler && saved_handler->sa_handler) { if (!(saved_handler->sa_flags & SA_SIGINFO)) { @@ -193,29 +192,28 @@ SIG_HANDLER_SIGNATURE (mono_chain_signal) return FALSE; } -SIG_HANDLER_FUNC (static, sigabrt_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler) { MonoJitInfo *ji = NULL; - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; if (mono_thread_internal_current ()) - ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx)); + ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx)); if (!ji) { - if (mono_chain_signal (SIG_HANDLER_PARAMS)) + if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; mono_handle_native_sigsegv (SIGABRT, ctx); } } -SIG_HANDLER_FUNC (static, sigusr1_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigusr1_signal_handler) { gboolean running_managed; MonoException *exc; MonoInternalThread *thread = mono_thread_internal_current (); MonoDomain *domain = mono_domain_get (); void *ji; - - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; if (!thread || !domain) { /* The thread might not have started up yet */ @@ -299,9 +297,9 @@ SIG_HANDLER_FUNC (static, sigusr1_signal_handler) #ifdef SIGPROF #if defined(__ia64__) || defined(__sparc__) || defined(sparc) || defined(__s390__) || defined(s390) -SIG_HANDLER_FUNC (static, sigprof_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) { - if (mono_chain_signal (SIG_HANDLER_PARAMS)) + if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; NOT_IMPLEMENTED; @@ -309,11 +307,11 @@ SIG_HANDLER_FUNC (static, sigprof_signal_handler) #else -SIG_HANDLER_FUNC (static, sigprof_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) { int call_chain_depth = mono_profiler_stat_get_call_chain_depth (); MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy (); - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; if (call_chain_depth == 0) { mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx); @@ -382,17 +380,16 @@ SIG_HANDLER_FUNC (static, sigprof_signal_handler) mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx); } - mono_chain_signal (SIG_HANDLER_PARAMS); + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); } #endif #endif -SIG_HANDLER_FUNC (static, sigquit_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigquit_signal_handler) { gboolean res; - - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; /* We use this signal to start the attach agent too */ res = mono_attach_start (); @@ -415,16 +412,16 @@ SIG_HANDLER_FUNC (static, sigquit_signal_handler) mono_print_thread_dump (ctx); } - mono_chain_signal (SIG_HANDLER_PARAMS); + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); } -SIG_HANDLER_FUNC (static, sigusr2_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigusr2_signal_handler) { gboolean enabled = mono_trace_is_enabled (); mono_trace_enable (!enabled); - mono_chain_signal (SIG_HANDLER_PARAMS); + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); } static void diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 1ab0ac22f20..971ac30d295 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -6724,14 +6724,11 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec return runtime_invoke (obj, params, exc, info->compiled_method); } -SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler) +MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler) { MonoException *exc = NULL; MonoJitInfo *ji; -#if !(defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32)) - void *info = NULL; -#endif - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx)); @@ -6749,12 +6746,12 @@ SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler) #endif if (!ji) { - if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS)) + if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; mono_handle_native_sigsegv (SIGSEGV, ctx); if (mono_do_crash_chaining) { - mono_chain_signal (SIG_HANDLER_PARAMS); + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); return; } } @@ -6762,10 +6759,10 @@ SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler) mono_arch_handle_exception (ctx, exc); } -SIG_HANDLER_FUNC (, mono_sigill_signal_handler) +MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler) { MonoException *exc; - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; exc = mono_get_exception_execution_engine ("SIGILL"); @@ -6776,13 +6773,12 @@ SIG_HANDLER_FUNC (, mono_sigill_signal_handler) #define HAVE_SIG_INFO #endif -SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) +MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) { MonoJitInfo *ji; MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); gpointer fault_addr = NULL; - - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO) if (mono_arch_is_single_step_event (info, ctx)) { @@ -6804,11 +6800,11 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) /* The thread might no be registered with the runtime */ if (!mono_domain_get () || !jit_tls) { - if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS)) + if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; mono_handle_native_sigsegv (SIGSEGV, ctx); if (mono_do_crash_chaining) { - mono_chain_signal (SIG_HANDLER_PARAMS); + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); return; } } @@ -6841,7 +6837,7 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) g_assert_not_reached (); } else { /* The original handler might not like that it is executed on an altstack... */ - if (!ji && mono_chain_signal (SIG_HANDLER_PARAMS)) + if (!ji && mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE); @@ -6849,13 +6845,13 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) #else if (!ji) { - if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS)) + if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; mono_handle_native_sigsegv (SIGSEGV, ctx); if (mono_do_crash_chaining) { - mono_chain_signal (SIG_HANDLER_PARAMS); + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); return; } } @@ -6864,10 +6860,10 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) #endif } -SIG_HANDLER_FUNC (, mono_sigint_signal_handler) +MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler) { MonoException *exc; - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; exc = mono_get_exception_execution_engine ("Interrupted (SIGINT)."); diff --git a/mono/mini/mini.h b/mono/mini/mini.h index cd38442570c..df6c54a7a52 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -31,6 +31,7 @@ #include #include #include +#include #define MONO_BREAKPOINT_ARRAY_SIZE 64 @@ -2826,53 +2827,12 @@ void mono_cross_helpers_run (void) MONO_INTERNAL; /* * Signal handling */ -#ifdef MONO_GET_CONTEXT -#define GET_CONTEXT MONO_GET_CONTEXT -#endif - -#ifndef GET_CONTEXT -#ifdef HOST_WIN32 -/* seh_vectored_exception_handler () passes in a CONTEXT* */ -#define GET_CONTEXT \ - void *ctx = context; -#else -#ifdef MONO_ARCH_USE_SIGACTION -#define GET_CONTEXT \ - void *ctx = context; -#elif defined(__HAIKU__) -#define GET_CONTEXT \ - void *ctx = ®s; -#else -#define GET_CONTEXT \ - void **_p = (void **)&_dummy; \ - struct sigcontext *ctx = (struct sigcontext *)++_p; -#endif -#endif -#endif - -#if defined(MONO_ARCH_USE_SIGACTION) && !defined(HOST_WIN32) -#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *info, void *context) -#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, siginfo_t *info, void *context)) -#define SIG_HANDLER_PARAMS _dummy, info, context -#elif defined(HOST_WIN32) -#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_POINTERS *info, void *context) -#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, EXCEPTION_POINTERS *info, void *context)) -#define SIG_HANDLER_PARAMS _dummy, info, context -#elif defined(__HAIKU__) -#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, void *userData, vregs regs) -#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, void *userData, vregs regs)) -#define SIG_HANDLER_PARAMS _dummy, userData, regs -#else -#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy) -#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy)) -#define SIG_HANDLER_PARAMS _dummy -#endif -void SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler) MONO_INTERNAL; -void SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler) MONO_INTERNAL; -void SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) MONO_INTERNAL; -void SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler) MONO_INTERNAL; -gboolean SIG_HANDLER_SIGNATURE (mono_chain_signal) MONO_INTERNAL; +void MONO_SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler) MONO_INTERNAL; +void MONO_SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler) MONO_INTERNAL; +void MONO_SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) MONO_INTERNAL; +void MONO_SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler) MONO_INTERNAL; +gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) MONO_INTERNAL; #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE #define ARCH_HAVE_DELEGATE_TRAMPOLINES 1 diff --git a/mono/utils/mono-signal-handler.h b/mono/utils/mono-signal-handler.h index 3a01146d5e1..92cb299a150 100644 --- a/mono/utils/mono-signal-handler.h +++ b/mono/utils/mono-signal-handler.h @@ -12,18 +12,44 @@ #ifdef ENABLE_EXTENSION_MODULE #include "../../../mono-extensions/mono/utils/mono-signal-handler.h" #endif -/* -Not all platforms support signal handlers in the same way. Some have the same concept but -for some weird reason pass different kind of arguments. - -All signal handler helpers should go here so they can be properly shared across the JIT, -utils and sgen. - -TODO: Cleanup & move mini's macros to here so they can leveraged by other parts. -*/ +/* Don't use this */ #ifndef MONO_SIGNAL_HANDLER_FUNC #define MONO_SIGNAL_HANDLER_FUNC(access, name, arglist) access void name arglist #endif +/* + * Macros to work around signal handler differences on various platforms. + * + * To declare a signal handler function: + * void MONO_SIG_HANDLER_SIGNATURE (handler_func) + * To define a signal handler function: + * MONO_SIG_HANDLER_FUNC(access, name) + * To call another signal handler function: + * handler_func (SIG_HANDLER_PARAMS); + * To obtain the signal number: + * int signo = MONO_SIG_HANDLER_GET_SIGNO (); + * To obtain the signal context: + * MONO_SIG_HANDLER_GET_CONTEXT (). + * This will define a variable name 'ctx'. + */ + +#ifdef HOST_WIN32 +#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_POINTERS *info, void *context) +#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, EXCEPTION_POINTERS *info, void *context)) +#define MONO_SIG_HANDLER_PARAMS _dummy, info, context +#define MONO_SIG_HANDLER_GET_SIGNO() (_dummy) +/* seh_vectored_exception_handler () passes in a CONTEXT* */ +#define MONO_SIG_HANDLER_GET_CONTEXT \ + void *ctx = context; +#else +/* sigaction */ +#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *info, void *context) +#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, siginfo_t *info, void *context)) +#define MONO_SIG_HANDLER_PARAMS _dummy, info, context +#define MONO_SIG_HANDLER_GET_SIGNO() (_dummy) +#define MONO_SIG_HANDLER_GET_CONTEXT \ + void *ctx = context; +#endif + #endif From c3bd8334a3bf106225b11ec12be01153d5f3fb1a Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 20 Oct 2014 18:08:19 -0400 Subject: [PATCH 433/543] Fix a typo. --- mono/utils/mono-signal-handler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/utils/mono-signal-handler.h b/mono/utils/mono-signal-handler.h index 92cb299a150..0274136ffbc 100644 --- a/mono/utils/mono-signal-handler.h +++ b/mono/utils/mono-signal-handler.h @@ -26,7 +26,7 @@ * To define a signal handler function: * MONO_SIG_HANDLER_FUNC(access, name) * To call another signal handler function: - * handler_func (SIG_HANDLER_PARAMS); + * handler_func (MONO_SIG_HANDLER_PARAMS); * To obtain the signal number: * int signo = MONO_SIG_HANDLER_GET_SIGNO (); * To obtain the signal context: From 6716d439e95baece22b51ea4547d304c2738111b Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 20 Oct 2014 18:22:40 -0400 Subject: [PATCH 434/543] [jit] Remove some unused definitions. --- mono/mini/mini.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/mono/mini/mini.h b/mono/mini/mini.h index df6c54a7a52..9a9acad4054 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -54,19 +54,6 @@ #error "The code in mini/ should not depend on these defines." #endif -#ifndef G_LIKELY -#define G_LIKELY(a) (a) -#define G_UNLIKELY(a) (a) -#endif - -#ifndef G_MAXINT32 -#define G_MAXINT32 2147483647 -#endif - -#ifndef G_MININT32 -#define G_MININT32 (-G_MAXINT32 - 1) -#endif - #ifndef __GNUC__ /*#define __alignof__(a) sizeof(a)*/ #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x) From 639413ef89819b875ee004b069a9c17a14e2a4ed Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 20 Oct 2014 19:19:27 -0400 Subject: [PATCH 435/543] Fix the build after the signals changes. --- mono/mini/mini-posix.c | 3 +-- mono/mini/mini.c | 4 ++++ mono/utils/mono-signal-handler.h | 14 ++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index 98b396bbf26..0c2fa1dc1f0 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -177,14 +177,13 @@ MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) { int signal = MONO_SIG_HANDLER_GET_SIGNO (); struct sigaction *saved_handler = get_saved_signal_handler (signal); - MONO_SIG_HANDLER_GET_CONTEXT; if (saved_handler && saved_handler->sa_handler) { if (!(saved_handler->sa_flags & SA_SIGINFO)) { saved_handler->sa_handler (signal); } else { #ifdef MONO_ARCH_USE_SIGACTION - saved_handler->sa_sigaction (signal, info, ctx); + saved_handler->sa_sigaction (MONO_SIG_HANDLER_PARAMS); #endif /* MONO_ARCH_USE_SIGACTION */ } return TRUE; diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 971ac30d295..275a6f8cc6a 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -6728,6 +6728,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler) { MonoException *exc = NULL; MonoJitInfo *ji; + void *info = MONO_SIG_HANDLER_GET_INFO (); MONO_SIG_HANDLER_GET_CONTEXT; ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx)); @@ -6779,6 +6780,9 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); gpointer fault_addr = NULL; MONO_SIG_HANDLER_GET_CONTEXT; +#ifdef HAVE_SIG_INFO + siginfo_t *info = MONO_SIG_HANDLER_GET_INFO (); +#endif #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO) if (mono_arch_is_single_step_event (info, ctx)) { diff --git a/mono/utils/mono-signal-handler.h b/mono/utils/mono-signal-handler.h index 0274136ffbc..c5b609f17df 100644 --- a/mono/utils/mono-signal-handler.h +++ b/mono/utils/mono-signal-handler.h @@ -35,19 +35,21 @@ */ #ifdef HOST_WIN32 -#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_POINTERS *info, void *context) -#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, EXCEPTION_POINTERS *info, void *context)) -#define MONO_SIG_HANDLER_PARAMS _dummy, info, context +#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_POINTERS *_info, void *context) +#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, EXCEPTION_POINTERS *_info, void *context)) +#define MONO_SIG_HANDLER_PARAMS _dummy, _info, context #define MONO_SIG_HANDLER_GET_SIGNO() (_dummy) +#define MONO_SIG_HANDLER_GET_INFO() (_info) /* seh_vectored_exception_handler () passes in a CONTEXT* */ #define MONO_SIG_HANDLER_GET_CONTEXT \ void *ctx = context; #else /* sigaction */ -#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *info, void *context) -#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, siginfo_t *info, void *context)) -#define MONO_SIG_HANDLER_PARAMS _dummy, info, context +#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *_info, void *context) +#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, siginfo_t *_info, void *context)) +#define MONO_SIG_HANDLER_PARAMS _dummy, _info, context #define MONO_SIG_HANDLER_GET_SIGNO() (_dummy) +#define MONO_SIG_HANDLER_GET_INFO() (_info) #define MONO_SIG_HANDLER_GET_CONTEXT \ void *ctx = context; #endif From 26364535a038e436b82c590246519537bf2272b6 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 30 Sep 2014 13:46:47 -0400 Subject: [PATCH 436/543] [sgen] Cleanup some allocation code --- mono/utils/lock-free-alloc.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/mono/utils/lock-free-alloc.c b/mono/utils/lock-free-alloc.c index 4befb3b86a0..4a48298ec9a 100644 --- a/mono/utils/lock-free-alloc.c +++ b/mono/utils/lock-free-alloc.c @@ -139,29 +139,10 @@ prot_flags_for_activate (int activate) return prot_flags | MONO_MMAP_PRIVATE | MONO_MMAP_ANON; } -static void* -mono_sgen_alloc_os_memory (size_t size, int activate) -{ - return mono_valloc (0, size, prot_flags_for_activate (activate)); -} - -static void -mono_sgen_free_os_memory (void *addr, size_t size) -{ - mono_vfree (addr, size); -} - -/* size must be a power of 2 */ -static void* -mono_sgen_alloc_os_memory_aligned (size_t size, size_t alignment, gboolean activate) -{ - return mono_valloc_aligned (size, alignment, prot_flags_for_activate (activate)); -} - static gpointer alloc_sb (Descriptor *desc) { - gpointer sb_header = mono_sgen_alloc_os_memory_aligned (SB_SIZE, SB_SIZE, TRUE); + gpointer sb_header = mono_valloc_aligned (SB_SIZE, SB_SIZE, prot_flags_for_activate (TRUE)); g_assert (sb_header == SB_HEADER_FOR_ADDR (sb_header)); DESCRIPTOR_FOR_ADDR (sb_header) = desc; //g_print ("sb %p for %p\n", sb_header, desc); @@ -173,7 +154,7 @@ free_sb (gpointer sb) { gpointer sb_header = SB_HEADER_FOR_ADDR (sb); g_assert ((char*)sb_header + SB_HEADER_SIZE == sb); - mono_sgen_free_os_memory (sb_header, SB_SIZE); + mono_vfree (sb_header, SB_SIZE); //g_print ("free sb %p\n", sb_header); } @@ -198,7 +179,7 @@ desc_alloc (void) Descriptor *d; int i; - desc = mono_sgen_alloc_os_memory (desc_size * NUM_DESC_BATCH, TRUE); + desc = mono_valloc (0, desc_size * NUM_DESC_BATCH, prot_flags_for_activate (TRUE)); /* Organize into linked list. */ d = desc; @@ -214,7 +195,7 @@ desc_alloc (void) success = (InterlockedCompareExchangePointer ((gpointer * volatile)&desc_avail, desc->next, NULL) == NULL); if (!success) - mono_sgen_free_os_memory (desc, desc_size * NUM_DESC_BATCH); + mono_vfree (desc, desc_size * NUM_DESC_BATCH); } mono_hazard_pointer_clear (hp, 1); From d3788f892f2c6f114526bcb203a247b91edcfd91 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 30 Sep 2014 17:09:50 -0400 Subject: [PATCH 437/543] [sgen] Utility function to compute number of unfaulted pages. --- mono/metadata/sgen-cardtable.c | 16 -------------- mono/utils/Makefile.am | 1 + mono/utils/mono-mmap-internal.h | 28 ++++++++++++++++++++++++ mono/utils/mono-mmap.c | 38 +++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 mono/utils/mono-mmap-internal.h diff --git a/mono/metadata/sgen-cardtable.c b/mono/metadata/sgen-cardtable.c index 7ee7e07bee3..6dd91e24442 100644 --- a/mono/metadata/sgen-cardtable.c +++ b/mono/metadata/sgen-cardtable.c @@ -479,22 +479,6 @@ mono_gc_card_table_nursery_check (void) } #if 0 -static void -collect_faulted_cards (void) -{ -#define CARD_PAGES (CARD_COUNT_IN_BYTES / 4096) - int i, count = 0; - unsigned char faulted [CARD_PAGES] = { 0 }; - mincore (sgen_cardtable, CARD_COUNT_IN_BYTES, faulted); - - for (i = 0; i < CARD_PAGES; ++i) { - if (faulted [i]) - ++count; - } - - printf ("TOTAL card pages %d faulted %d\n", CARD_PAGES, count); -} - void sgen_card_table_dump_obj_card (char *object, size_t size, void *dummy) { diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am index c5464d16b16..c2c8a0d790c 100644 --- a/mono/utils/Makefile.am +++ b/mono/utils/Makefile.am @@ -32,6 +32,7 @@ monoutils_sources = \ mono-math.c \ mono-mmap.c \ mono-mmap.h \ + mono-mmap-internal.h \ mono-mutex.c \ mono-mutex.h \ mono-networkinterfaces.c \ diff --git a/mono/utils/mono-mmap-internal.h b/mono/utils/mono-mmap-internal.h new file mode 100644 index 00000000000..1818e5c303d --- /dev/null +++ b/mono/utils/mono-mmap-internal.h @@ -0,0 +1,28 @@ +/* + * mono-mmap-internal.h: Internal virtual memory stuff. + * + * Copyright (C) 2014 Xamarin Inc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License 2.0 as published by the Free Software Foundation; + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License 2.0 along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MONO_UTILS_MMAP_INTERNAL_H__ +#define __MONO_UTILS_MMAP_INTERNAL_H__ + +#include "mono-compiler.h" + +int mono_pages_not_faulted (void *addr, size_t length) MONO_INTERNAL; + +#endif /* __MONO_UTILS_MMAP_INTERNAL_H__ */ + diff --git a/mono/utils/mono-mmap.c b/mono/utils/mono-mmap.c index 60ef156b15a..6caf9628380 100644 --- a/mono/utils/mono-mmap.c +++ b/mono/utils/mono-mmap.c @@ -29,6 +29,7 @@ #endif #include "mono-mmap.h" +#include "mono-mmap-internal.h" #include "mono-proclib.h" #ifndef MAP_ANONYMOUS @@ -243,6 +244,12 @@ mono_shared_area_instances (void **array, int count) return 0; } +int +mono_pages_not_faulted (void *addr, size_t length) +{ + return -1; +} + #else #if defined(HAVE_MMAP) @@ -443,6 +450,30 @@ mono_mprotect (void *addr, size_t length, int flags) } #endif // __native_client__ +int +mono_pages_not_faulted (void *addr, size_t size) +{ + int i; + gint64 count; + int pagesize = mono_pagesize (); + int npages = (size + pagesize - 1) / pagesize; + char *faulted = g_malloc0 (sizeof (char*) * npages); + + if (mincore (addr, size, faulted) != 0) { + count = -1; + } else { + count = 0; + for (i = 0; i < npages; ++i) { + if (faulted [i] != 0) + ++count; + } + } + + g_free (faulted); + + return count; +} + #else /* dummy malloc-based implementation */ @@ -481,6 +512,13 @@ mono_mprotect (void *addr, size_t length, int flags) } return 0; } + +int +mono_pages_not_faulted (void *addr, size_t length) +{ + return -1; +} + #endif // HAVE_MMAP #if defined(HAVE_SHM_OPEN) && !defined (DISABLE_SHARED_PERFCOUNTERS) From 4619f9f070007b0077ba1ea2b7c848a78e5cfc64 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 30 Sep 2014 17:11:33 -0400 Subject: [PATCH 438/543] [sgen] Add internal allocator default sizes usage statistic --- mono/metadata/sgen-internal.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/mono/metadata/sgen-internal.c b/mono/metadata/sgen-internal.c index 9474d7cec5a..d45b5d6112e 100644 --- a/mono/metadata/sgen-internal.c +++ b/mono/metadata/sgen-internal.c @@ -46,6 +46,10 @@ static const int allocator_sizes [] = { static MonoLockFreeAllocSizeClass size_classes [NUM_ALLOCATORS]; static MonoLockFreeAllocator allocators [NUM_ALLOCATORS]; +#ifdef HEAVY_STATISTICS +static int allocator_sizes_stats [NUM_ALLOCATORS]; +#endif + /* * Find the allocator index for memory chunks that can contain @size * objects. @@ -75,6 +79,7 @@ sgen_register_fixed_internal_mem_type (int type, size_t size) int slot; g_assert (type >= 0 && type < INTERNAL_MEM_MAX); + g_assert (size <= allocator_sizes [NUM_ALLOCATORS - 1]); slot = index_for_size (size); g_assert (slot >= 0); @@ -143,6 +148,10 @@ sgen_alloc_internal_dynamic (size_t size, int type, gboolean assert_on_failure) } else { index = index_for_size (size); +#ifdef HEAVY_STATISTICS + ++ allocator_sizes_stats [index]; +#endif + p = mono_lock_free_alloc (&allocators [index]); if (!p) sgen_assert_memory_alloc (NULL, size, description_for_type (type)); @@ -170,10 +179,18 @@ sgen_free_internal_dynamic (void *addr, size_t size, int type) void* sgen_alloc_internal (int type) { - int index = fixed_type_allocator_indexes [type]; - int size = allocator_sizes [index]; + int index, size; void *p; + + index = fixed_type_allocator_indexes [type]; g_assert (index >= 0 && index < NUM_ALLOCATORS); + +#ifdef HEAVY_STATISTICS + ++ allocator_sizes_stats [index]; +#endif + + size = allocator_sizes [index]; + p = mono_lock_free_alloc (&allocators [index]); memset (p, 0, size); @@ -219,8 +236,12 @@ sgen_dump_internal_mem_usage (FILE *heap_dump_file) void sgen_report_internal_mem_usage (void) { - /* FIXME: implement */ - printf ("not implemented yet\n"); + int i G_GNUC_UNUSED; +#ifdef HEAVY_STATISTICS + printf ("size -> # allocations\n"); + for (i = 0; i < NUM_ALLOCATORS; ++i) + printf ("%d -> %d\n", allocator_sizes [i], allocator_sizes_stats [i]); +#endif } void From 1daac38948716591c9f214322359fee7e6513964 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 30 Sep 2014 18:02:55 -0400 Subject: [PATCH 439/543] [sgen] Add assertion on power of 2 for internal allocator section size --- mono/utils/lock-free-alloc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mono/utils/lock-free-alloc.c b/mono/utils/lock-free-alloc.c index 4a48298ec9a..26b145a2361 100644 --- a/mono/utils/lock-free-alloc.c +++ b/mono/utils/lock-free-alloc.c @@ -590,6 +590,8 @@ mono_lock_free_allocator_check_consistency (MonoLockFreeAllocator *heap) void mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size) { + g_assert (SB_SIZE > 0); + g_assert ((SB_SIZE & (SB_SIZE - 1)) == 0); /* check if power of 2 */ g_assert (slot_size <= SB_USABLE_SIZE / 2); mono_lock_free_queue_init (&sc->partial); From 18cd82b38069a891f064f029e319a1d91fb6c1ee Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 30 Sep 2014 15:22:42 -0400 Subject: [PATCH 440/543] [sgen] Adjust internal allocator block size to slot size. The internal allocator used size segregated blocks which were always 16k large. Since we have quite a few different size classes this led to a lot of allocation even for very small programs. We now use block sizes that are determined by the slot size and are as small as possible. They're power-of-two multiples of the page size, so we end up with blocks of 4k, 8k and 16k. --- mono/metadata/sgen-internal.c | 39 ++++++++++++++-- mono/utils/lock-free-alloc.c | 83 +++++++++++++++++++++-------------- mono/utils/lock-free-alloc.h | 9 +++- 3 files changed, 91 insertions(+), 40 deletions(-) diff --git a/mono/metadata/sgen-internal.c b/mono/metadata/sgen-internal.c index d45b5d6112e..dd479f325b7 100644 --- a/mono/metadata/sgen-internal.c +++ b/mono/metadata/sgen-internal.c @@ -23,6 +23,7 @@ #include "utils/mono-counters.h" #include "metadata/sgen-gc.h" +#include "utils/mono-mmap.h" #include "utils/lock-free-alloc.h" #include "metadata/sgen-memory-governor.h" @@ -43,6 +44,8 @@ static const int allocator_sizes [] = { #define NUM_ALLOCATORS (sizeof (allocator_sizes) / sizeof (int)) +static int allocator_block_sizes [NUM_ALLOCATORS]; + static MonoLockFreeAllocSizeClass size_classes [NUM_ALLOCATORS]; static MonoLockFreeAllocator allocators [NUM_ALLOCATORS]; @@ -50,6 +53,23 @@ static MonoLockFreeAllocator allocators [NUM_ALLOCATORS]; static int allocator_sizes_stats [NUM_ALLOCATORS]; #endif +static size_t +block_size (size_t slot_size) +{ + static int pagesize = -1; + + int size; + + if (pagesize == -1) + pagesize = mono_pagesize (); + + for (size = pagesize; size < LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) { + if (slot_size * 2 <= LOCK_FREE_ALLOC_SB_USABLE_SIZE (size)) + return size; + } + return LOCK_FREE_ALLOC_SB_MAX_SIZE; +} + /* * Find the allocator index for memory chunks that can contain @size * objects. @@ -171,7 +191,7 @@ sgen_free_internal_dynamic (void *addr, size_t size, int type) if (size > allocator_sizes [NUM_ALLOCATORS - 1]) sgen_free_os_memory (addr, size, SGEN_ALLOC_INTERNAL); else - mono_lock_free_free (addr); + mono_lock_free_free (addr, block_size (size)); MONO_GC_INTERNAL_DEALLOC ((mword)addr, size, type); } @@ -210,7 +230,7 @@ sgen_free_internal (void *addr, int type) index = fixed_type_allocator_indexes [type]; g_assert (index >= 0 && index < NUM_ALLOCATORS); - mono_lock_free_free (addr); + mono_lock_free_free (addr, allocator_block_sizes [index]); if (MONO_GC_INTERNAL_DEALLOC_ENABLED ()) { int size G_GNUC_UNUSED = allocator_sizes [index]; @@ -247,15 +267,26 @@ sgen_report_internal_mem_usage (void) void sgen_init_internal_allocator (void) { - int i; + int i, size; for (i = 0; i < INTERNAL_MEM_MAX; ++i) fixed_type_allocator_indexes [i] = -1; for (i = 0; i < NUM_ALLOCATORS; ++i) { - mono_lock_free_allocator_init_size_class (&size_classes [i], allocator_sizes [i]); + allocator_block_sizes [i] = block_size (allocator_sizes [i]); + mono_lock_free_allocator_init_size_class (&size_classes [i], allocator_sizes [i], allocator_block_sizes [i]); mono_lock_free_allocator_init_allocator (&allocators [i], &size_classes [i]); } + + for (size = mono_pagesize (); size <= LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) { + int max_size = LOCK_FREE_ALLOC_SB_USABLE_SIZE (size) / 2; + /* + * we assert that allocator_sizes contains the biggest possible object size + * per block (4K => 4080 / 2 = 2040, 8k => 8176 / 2 = 4088, 16k => 16368 / 2 = 8184), + * so that we do not get different block sizes for sizes that should go to the same one + */ + g_assert (allocator_sizes [index_for_size (max_size)] == max_size); + } } #endif diff --git a/mono/utils/lock-free-alloc.c b/mono/utils/lock-free-alloc.c index 26b145a2361..33fed096ea4 100644 --- a/mono/utils/lock-free-alloc.c +++ b/mono/utils/lock-free-alloc.c @@ -113,6 +113,7 @@ struct _MonoLockFreeAllocDescriptor { MonoLockFreeAllocator *heap; volatile Anchor anchor; unsigned int slot_size; + unsigned int block_size; unsigned int max_count; gpointer sb; #ifndef DESC_AVAIL_DUMMY @@ -123,12 +124,11 @@ struct _MonoLockFreeAllocDescriptor { #define NUM_DESC_BATCH 64 -#define SB_SIZE 16384 -#define SB_HEADER_SIZE 16 -#define SB_USABLE_SIZE (SB_SIZE - SB_HEADER_SIZE) - -#define SB_HEADER_FOR_ADDR(a) ((gpointer)((size_t)(a) & ~(size_t)(SB_SIZE-1))) -#define DESCRIPTOR_FOR_ADDR(a) (*(Descriptor**)SB_HEADER_FOR_ADDR (a)) +static MONO_ALWAYS_INLINE gpointer +sb_header_for_addr (gpointer addr, size_t block_size) +{ + return (gpointer)(((size_t)addr) & (~(block_size - 1))); +} /* Taken from SGen */ @@ -142,19 +142,31 @@ prot_flags_for_activate (int activate) static gpointer alloc_sb (Descriptor *desc) { - gpointer sb_header = mono_valloc_aligned (SB_SIZE, SB_SIZE, prot_flags_for_activate (TRUE)); - g_assert (sb_header == SB_HEADER_FOR_ADDR (sb_header)); - DESCRIPTOR_FOR_ADDR (sb_header) = desc; + static int pagesize = -1; + + gpointer sb_header; + + if (pagesize == -1) + pagesize = mono_pagesize (); + + sb_header = desc->block_size == pagesize ? + mono_valloc (0, desc->block_size, prot_flags_for_activate (TRUE)) : + mono_valloc_aligned (desc->block_size, desc->block_size, prot_flags_for_activate (TRUE)); + + g_assert (sb_header == sb_header_for_addr (sb_header, desc->block_size)); + + *(Descriptor**)sb_header = desc; //g_print ("sb %p for %p\n", sb_header, desc); - return (char*)sb_header + SB_HEADER_SIZE; + + return (char*)sb_header + LOCK_FREE_ALLOC_SB_HEADER_SIZE; } static void -free_sb (gpointer sb) +free_sb (gpointer sb, size_t block_size) { - gpointer sb_header = SB_HEADER_FOR_ADDR (sb); - g_assert ((char*)sb_header + SB_HEADER_SIZE == sb); - mono_vfree (sb_header, SB_SIZE); + gpointer sb_header = sb_header_for_addr (sb, block_size); + g_assert ((char*)sb_header + LOCK_FREE_ALLOC_SB_HEADER_SIZE == sb); + mono_vfree (sb_header, block_size); //g_print ("free sb %p\n", sb_header); } @@ -232,7 +244,7 @@ desc_retire (Descriptor *desc) g_assert (desc->anchor.data.state == STATE_EMPTY); g_assert (desc->in_use); desc->in_use = FALSE; - free_sb (desc->sb); + free_sb (desc->sb, desc->block_size); mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, FALSE, TRUE); } #else @@ -252,7 +264,7 @@ desc_alloc (void) static void desc_retire (Descriptor *desc) { - free_sb (desc->sb); + free_sb (desc->sb, desc->block_size); mono_lock_free_queue_enqueue (&available_descs, &desc->node); } #endif @@ -369,7 +381,7 @@ alloc_from_active_or_partial (MonoLockFreeAllocator *heap) mono_memory_read_barrier (); next = *(unsigned int*)addr; - g_assert (next < SB_USABLE_SIZE / desc->slot_size); + g_assert (next < LOCK_FREE_ALLOC_SB_USABLE_SIZE (desc->block_size) / desc->slot_size); new_anchor.data.avail = next; --new_anchor.data.count; @@ -390,17 +402,12 @@ alloc_from_active_or_partial (MonoLockFreeAllocator *heap) static gpointer alloc_from_new_sb (MonoLockFreeAllocator *heap) { - unsigned int slot_size, count, i; + unsigned int slot_size, block_size, count, i; Descriptor *desc = desc_alloc (); - desc->sb = alloc_sb (desc); - slot_size = desc->slot_size = heap->sc->slot_size; - count = SB_USABLE_SIZE / slot_size; - - /* Organize blocks into linked list. */ - for (i = 1; i < count - 1; ++i) - *(unsigned int*)((char*)desc->sb + i * slot_size) = i + 1; + block_size = desc->block_size = heap->sc->block_size; + count = LOCK_FREE_ALLOC_SB_USABLE_SIZE (block_size) / slot_size; desc->heap = heap; /* @@ -414,6 +421,12 @@ alloc_from_new_sb (MonoLockFreeAllocator *heap) desc->anchor.data.count = desc->max_count - 1; desc->anchor.data.state = STATE_PARTIAL; + desc->sb = alloc_sb (desc); + + /* Organize blocks into linked list. */ + for (i = 1; i < count - 1; ++i) + *(unsigned int*)((char*)desc->sb + i * slot_size) = i + 1; + mono_memory_write_barrier (); /* Make it active or free it again. */ @@ -446,22 +459,23 @@ mono_lock_free_alloc (MonoLockFreeAllocator *heap) } void -mono_lock_free_free (gpointer ptr) +mono_lock_free_free (gpointer ptr, size_t block_size) { Anchor old_anchor, new_anchor; Descriptor *desc; gpointer sb; MonoLockFreeAllocator *heap = NULL; - desc = DESCRIPTOR_FOR_ADDR (ptr); + desc = *(Descriptor**) sb_header_for_addr (ptr, block_size); + g_assert (block_size == desc->block_size); + sb = desc->sb; - g_assert (SB_HEADER_FOR_ADDR (ptr) == SB_HEADER_FOR_ADDR (sb)); do { new_anchor = old_anchor = *(volatile Anchor*)&desc->anchor.value; *(unsigned int*)ptr = old_anchor.data.avail; new_anchor.data.avail = ((char*)ptr - (char*)sb) / desc->slot_size; - g_assert (new_anchor.data.avail < SB_USABLE_SIZE / desc->slot_size); + g_assert (new_anchor.data.avail < LOCK_FREE_ALLOC_SB_USABLE_SIZE (block_size) / desc->slot_size); if (old_anchor.data.state == STATE_FULL) new_anchor.data.state = STATE_PARTIAL; @@ -511,7 +525,7 @@ static void descriptor_check_consistency (Descriptor *desc, gboolean print) { int count = desc->anchor.data.count; - int max_count = SB_USABLE_SIZE / desc->slot_size; + int max_count = LOCK_FREE_ALLOC_SB_USABLE_SIZE (desc->block_size) / desc->slot_size; #if _MSC_VER gboolean* linked = alloca(max_count*sizeof(gboolean)); #else @@ -588,14 +602,15 @@ mono_lock_free_allocator_check_consistency (MonoLockFreeAllocator *heap) } void -mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size) +mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size, unsigned int block_size) { - g_assert (SB_SIZE > 0); - g_assert ((SB_SIZE & (SB_SIZE - 1)) == 0); /* check if power of 2 */ - g_assert (slot_size <= SB_USABLE_SIZE / 2); + g_assert (block_size > 0); + g_assert ((block_size & (block_size - 1)) == 0); /* check if power of 2 */ + g_assert (slot_size * 2 <= LOCK_FREE_ALLOC_SB_USABLE_SIZE (block_size)); mono_lock_free_queue_init (&sc->partial); sc->slot_size = slot_size; + sc->block_size = block_size; } void diff --git a/mono/utils/lock-free-alloc.h b/mono/utils/lock-free-alloc.h index ed07a2971a5..84935646d37 100644 --- a/mono/utils/lock-free-alloc.h +++ b/mono/utils/lock-free-alloc.h @@ -33,6 +33,7 @@ typedef struct { MonoLockFreeQueue partial; unsigned int slot_size; + unsigned int block_size; } MonoLockFreeAllocSizeClass; struct _MonoLockFreeAllocDescriptor; @@ -42,11 +43,15 @@ typedef struct { MonoLockFreeAllocSizeClass *sc; } MonoLockFreeAllocator; -void mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size) MONO_INTERNAL; +#define LOCK_FREE_ALLOC_SB_MAX_SIZE 16384 +#define LOCK_FREE_ALLOC_SB_HEADER_SIZE (sizeof (MonoLockFreeAllocator)) +#define LOCK_FREE_ALLOC_SB_USABLE_SIZE(block_size) ((block_size) - LOCK_FREE_ALLOC_SB_HEADER_SIZE) + +void mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size, unsigned int block_size) MONO_INTERNAL; void mono_lock_free_allocator_init_allocator (MonoLockFreeAllocator *heap, MonoLockFreeAllocSizeClass *sc) MONO_INTERNAL; gpointer mono_lock_free_alloc (MonoLockFreeAllocator *heap) MONO_INTERNAL; -void mono_lock_free_free (gpointer ptr) MONO_INTERNAL; +void mono_lock_free_free (gpointer ptr, size_t block_size) MONO_INTERNAL; gboolean mono_lock_free_allocator_check_consistency (MonoLockFreeAllocator *heap) MONO_INTERNAL; From a26b297e111e93263c084d5ad373b4af5e4f8d6f Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 20 Oct 2014 20:48:55 -0400 Subject: [PATCH 441/543] Fix a warning. --- mono/mini/mini.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 275a6f8cc6a..f0857512e61 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -6779,10 +6779,10 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) MonoJitInfo *ji; MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); gpointer fault_addr = NULL; - MONO_SIG_HANDLER_GET_CONTEXT; #ifdef HAVE_SIG_INFO siginfo_t *info = MONO_SIG_HANDLER_GET_INFO (); #endif + MONO_SIG_HANDLER_GET_CONTEXT; #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO) if (mono_arch_is_single_step_event (info, ctx)) { From 066bdb9c2449e14437ffca59c5bdcb884c384bd6 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 20 Oct 2014 22:51:49 -0400 Subject: [PATCH 442/543] [jit] Add some micro-optimizations to speed up the AOT compiler. --- mono/mini/aot-compiler.c | 10 +++++++--- mono/mini/method-to-ir.c | 8 -------- mono/mini/mini-amd64.c | 3 +-- mono/mini/mini-codegen.c | 6 +++++- mono/mini/mini.c | 32 +++++++++++++++++++++----------- mono/mini/mini.h | 9 ++++++++- mono/mini/unwind.c | 6 +++--- 7 files changed, 45 insertions(+), 29 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 70e11b7730f..592567e89f5 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -3371,8 +3371,9 @@ add_wrappers (MonoAotCompile *acfg) if (info && !has_nullable) { /* Supported by the dynamic runtime-invoke wrapper */ skip = TRUE; - g_free (info); } + if (info) + mono_arch_dyn_call_free (info); } #endif @@ -6464,9 +6465,10 @@ add_token_info_hash (gpointer key, gpointer value, gpointer user_data) { MonoMethod *method = (MonoMethod*)key; MonoJumpInfoToken *ji = (MonoJumpInfoToken*)value; - MonoJumpInfoToken *new_ji = g_new0 (MonoJumpInfoToken, 1); MonoAotCompile *acfg = user_data; + MonoJumpInfoToken *new_ji; + new_ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfoToken)); new_ji->image = ji->image; new_ji->token = ji->token; g_hash_table_insert (acfg->token_info_hash, method, new_ji); @@ -6685,6 +6687,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) mono_acfg_lock (acfg); g_hash_table_foreach (cfg->token_info_hash, add_token_info_hash, acfg); mono_acfg_unlock (acfg); + g_hash_table_destroy (cfg->token_info_hash); + cfg->token_info_hash = NULL; /* * Check for absolute addresses. @@ -8741,7 +8745,7 @@ acfg_create (MonoAssembly *ass, guint32 opts) acfg->patch_to_got_offset_by_type [i] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal); acfg->got_patches = g_ptr_array_new (); acfg->method_to_cfg = g_hash_table_new (NULL, NULL); - acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, g_free); + acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, NULL); acfg->method_to_pinvoke_import = g_hash_table_new_full (NULL, NULL, NULL, g_free); acfg->image_hash = g_hash_table_new (NULL, NULL); acfg->image_table = g_ptr_array_new (); diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 6f757ff8e97..e9c1fa3dcd5 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -190,14 +190,6 @@ const gint8 ins_sreg_counts[] = { (vi)->idx = (id); \ } while (0) -void -mono_inst_set_src_registers (MonoInst *ins, int *regs) -{ - ins->sreg1 = regs [0]; - ins->sreg2 = regs [1]; - ins->sreg3 = regs [2]; -} - guint32 mono_alloc_ireg (MonoCompile *cfg) { diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 9317394473a..a809de49e05 100755 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -6417,7 +6417,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) guint alignment_check; #endif - cfg->code_size = MAX (cfg->header->code_size * 4, 10240); + cfg->code_size = MAX (cfg->header->code_size * 4, 1024); #if defined(__default_codegen__) code = cfg->native_code = g_malloc (cfg->code_size); @@ -6972,7 +6972,6 @@ mono_arch_emit_epilog (MonoCompile *cfg) cfg->native_code = mono_realloc_native_code (cfg); cfg->stat_code_reallocs++; } - code = cfg->native_code + cfg->code_len; cfg->has_unwind_info_for_epilog = TRUE; diff --git a/mono/mini/mini-codegen.c b/mono/mini/mini-codegen.c index 66eb8fcdcf2..f4bdecb727a 100644 --- a/mono/mini/mini-codegen.c +++ b/mono/mini/mini-codegen.c @@ -1173,6 +1173,8 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) * bblock. */ for (ins = bb->code; ins; ins = ins->next) { + gboolean modify = FALSE; + spec = ins_get_spec (ins->opcode); if ((ins->dreg != -1) && (ins->dreg < max)) { @@ -1198,12 +1200,14 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) #if SIZEOF_REGISTER == 4 if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC1 + j])) { sregs [j]++; + modify = TRUE; memset (®info [sregs [j] + 1], 0, sizeof (RegTrack)); } #endif } } - mono_inst_set_src_registers (ins, sregs); + if (modify) + mono_inst_set_src_registers (ins, sregs); } /*if (cfg->opt & MONO_OPT_COPYPROP) diff --git a/mono/mini/mini.c b/mono/mini/mini.c index f0857512e61..551cde95816 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -711,17 +711,22 @@ mono_debug_count (void) { static int count = 0; count ++; + static gboolean inited; + static const char *value; - if (!g_getenv ("COUNT")) + if (!inited) { + value = g_getenv ("COUNT"); + inited = TRUE; + } + + if (!value) return TRUE; - if (count == atoi (g_getenv ("COUNT"))) { + if (count == atoi (value)) break_count (); - } - if (count > atoi (g_getenv ("COUNT"))) { + if (count > atoi (value)) return FALSE; - } return TRUE; } @@ -1241,7 +1246,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, if ((num + 1) >= cfg->varinfo_count) { int orig_count = cfg->varinfo_count; - cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 64; + cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 32; cfg->varinfo = (MonoInst **)g_realloc (cfg->varinfo, sizeof (MonoInst*) * cfg->varinfo_count); cfg->vars = (MonoMethodVar *)g_realloc (cfg->vars, sizeof (MonoMethodVar) * cfg->varinfo_count); memset (&cfg->vars [orig_count], 0, (cfg->varinfo_count - orig_count) * sizeof (MonoMethodVar)); @@ -4920,6 +4925,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl #ifdef ENABLE_LLVM gboolean llvm = (flags & JIT_FLAG_LLVM) ? 1 : 0; #endif + static gboolean verbose_method_inited; + static const char *verbose_method_name; InterlockedIncrement (&mono_jit_stats.methods_compiled); if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION) @@ -5070,9 +5077,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl { static gboolean inited; - if (!inited) { + if (!inited) inited = TRUE; - } /* * Check for methods which cannot be compiled by LLVM early, to avoid @@ -5148,8 +5154,12 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl cfg->opt |= MONO_OPT_ABCREM; } - if (g_getenv ("MONO_VERBOSE_METHOD")) { - const char *name = g_getenv ("MONO_VERBOSE_METHOD"); + if (!verbose_method_inited) { + verbose_method_name = g_getenv ("MONO_VERBOSE_METHOD"); + verbose_method_inited = TRUE; + } + if (verbose_method_name) { + const char *name = verbose_method_name; if ((strchr (name, '.') > name) || strchr (name, ':')) { MonoMethodDesc *desc; @@ -5160,7 +5170,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl } mono_method_desc_free (desc); } else { - if (strcmp (cfg->method->name, g_getenv ("MONO_VERBOSE_METHOD")) == 0) + if (strcmp (cfg->method->name, name) == 0) cfg->verbose_level = 4; } } diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 9a9acad4054..61de960970f 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -946,6 +946,14 @@ enum { #define inst_phi_args data.op[1].phi_args #define inst_eh_block data.op[1].exception_clause +static inline void +mono_inst_set_src_registers (MonoInst *ins, int *regs) +{ + ins->sreg1 = regs [0]; + ins->sreg2 = regs [1]; + ins->sreg3 = regs [2]; +} + /* instruction description for use in regalloc/scheduling */ enum { MONO_INST_DEST, @@ -2023,7 +2031,6 @@ MONO_API void mono_print_method_from_ip (void *ip); MONO_API char *mono_pmip (void *ip); gboolean mono_debug_count (void) MONO_INTERNAL; MONO_API const char* mono_inst_name (int op); -void mono_inst_set_src_registers (MonoInst *ins, int *regs) MONO_INTERNAL; int mono_op_to_op_imm (int opcode) MONO_INTERNAL; int mono_op_imm_to_op (int opcode) MONO_INTERNAL; int mono_load_membase_to_load_mem (int opcode) MONO_INTERNAL; diff --git a/mono/mini/unwind.c b/mono/mini/unwind.c index 517c7fbc827..d6710939787 100644 --- a/mono/mini/unwind.c +++ b/mono/mini/unwind.c @@ -349,9 +349,10 @@ mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len) GSList *l; MonoUnwindOp *op; int loc; - guint8 *buf, *p, *res; + guint8 buf [4096]; + guint8 *p, *res; - p = buf = g_malloc0 (4096); + p = buf; loc = 0; l = unwind_ops; @@ -443,7 +444,6 @@ mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len) *out_len = p - buf; res = g_malloc (p - buf); memcpy (res, buf, p - buf); - g_free (buf); return res; } From 2a14bc4dad10850631656b97396413e6c6a8be83 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 21 Oct 2014 10:03:31 -0400 Subject: [PATCH 443/543] [sgen] Fix assertion error on 32bits --- mono/metadata/sgen-internal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mono/metadata/sgen-internal.c b/mono/metadata/sgen-internal.c index dd479f325b7..333f8c3ee41 100644 --- a/mono/metadata/sgen-internal.c +++ b/mono/metadata/sgen-internal.c @@ -33,7 +33,7 @@ static const int allocator_sizes [] = { 8, 16, 24, 32, 40, 48, 64, 80, 96, 128, 160, 192, 224, 248, 296, 320, 384, 448, 504, 528, 584, 680, 816, 1088, - 1360, 2040, 2336, 2728, 3272, 4088, 5456, 8184 }; + 1360, 2044, 2336, 2728, 3272, 4092, 5456, 8188 }; #else static const int allocator_sizes [] = { 8, 16, 24, 32, 40, 48, 64, 80, @@ -282,7 +282,7 @@ sgen_init_internal_allocator (void) int max_size = LOCK_FREE_ALLOC_SB_USABLE_SIZE (size) / 2; /* * we assert that allocator_sizes contains the biggest possible object size - * per block (4K => 4080 / 2 = 2040, 8k => 8176 / 2 = 4088, 16k => 16368 / 2 = 8184), + * per block (4K => 4080 / 2 = 2040, 8k => 8176 / 2 = 4088, 16k => 16368 / 2 = 8184 on 64bits), * so that we do not get different block sizes for sizes that should go to the same one */ g_assert (allocator_sizes [index_for_size (max_size)] == max_size); From c4f72def5796e2962cc8874d657d7c98b33fc116 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Mon, 13 Oct 2014 17:09:05 -0400 Subject: [PATCH 444/543] [sgen] Add memory governor allocated size counter --- mono/metadata/sgen-memory-governor.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mono/metadata/sgen-memory-governor.c b/mono/metadata/sgen-memory-governor.c index 881fff34f05..5d17a0d721c 100644 --- a/mono/metadata/sgen-memory-governor.c +++ b/mono/metadata/sgen-memory-governor.c @@ -48,6 +48,7 @@ static double save_target_ratio = SGEN_DEFAULT_SAVE_TARGET_RATIO; /**/ static mword allocated_heap; static mword total_alloc = 0; +static mword total_alloc_max = 0; /* GC triggers. */ @@ -287,6 +288,7 @@ sgen_alloc_os_memory (size_t size, SgenAllocFlags flags, const char *assert_desc SGEN_ATOMIC_ADD_P (total_alloc, size); if (flags & SGEN_ALLOC_HEAP) MONO_GC_HEAP_ALLOC ((mword)ptr, size); + total_alloc_max = MAX (total_alloc_max, total_alloc); } return ptr; } @@ -305,6 +307,7 @@ sgen_alloc_os_memory_aligned (size_t size, mword alignment, SgenAllocFlags flags SGEN_ATOMIC_ADD_P (total_alloc, size); if (flags & SGEN_ALLOC_HEAP) MONO_GC_HEAP_ALLOC ((mword)ptr, size); + total_alloc_max = MAX (total_alloc_max, total_alloc); } return ptr; } @@ -321,6 +324,7 @@ sgen_free_os_memory (void *addr, size_t size, SgenAllocFlags flags) SGEN_ATOMIC_ADD_P (total_alloc, -(gssize)size); if (flags & SGEN_ALLOC_HEAP) MONO_GC_HEAP_FREE ((mword)addr, size); + total_alloc_max = MAX (total_alloc_max, total_alloc); } int64_t @@ -368,6 +372,9 @@ sgen_memgov_init (size_t max_heap, size_t soft_limit, gboolean debug_allowance, debug_print_allowance = debug_allowance; minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE; + mono_counters_register ("Memgov alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, &total_alloc); + mono_counters_register ("Memgov max alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_MONOTONIC, &total_alloc_max); + if (max_heap == 0) return; From e15463e38a2d404fa837937f9716eebc7c1d8d61 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Mon, 13 Oct 2014 17:54:03 -0400 Subject: [PATCH 445/543] [sgen] Add GC max collection time counter --- mono/metadata/sgen-gc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 1364cc0a9e0..4b0b5a32012 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -347,6 +347,8 @@ static long long time_major_los_sweep = 0; static long long time_major_sweep = 0; static long long time_major_fragment_creation = 0; +static long long time_max = 0; + static SGEN_TV_DECLARE (time_major_conc_collection_start); static SGEN_TV_DECLARE (time_major_conc_collection_end); @@ -1928,6 +1930,8 @@ init_stats (void) if (inited) return; + mono_counters_register ("Collection max time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME | MONO_COUNTER_MONOTONIC, &time_max); + mono_counters_register ("Minor fragment clear", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_pre_collection_fragment_clear); mono_counters_register ("Minor pinning", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_pinning); mono_counters_register ("Minor scan remembered set", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_scan_remsets); @@ -3144,6 +3148,8 @@ void sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish) { TV_DECLARE (gc_end); + TV_DECLARE (gc_total_start); + TV_DECLARE (gc_total_end); GGTimingInfo infos [2]; int overflow_generation_to_collect = -1; int oldest_generation_collected = generation_to_collect; @@ -3166,6 +3172,8 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const sgen_stop_world (generation_to_collect); + TV_GETTIME (gc_total_start); + if (concurrent_collection_in_progress) { if (major_update_or_finish_concurrent_collection (wait_to_finish && generation_to_collect == GENERATION_OLD)) { oldest_generation_collected = GENERATION_OLD; @@ -3245,6 +3253,9 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const done: g_assert (sgen_gray_object_queue_is_empty (&gray_queue)); + TV_GETTIME (gc_total_end); + time_max = MAX (time_max, TV_ELAPSED (gc_total_start, gc_total_end)); + sgen_restart_world (oldest_generation_collected, infos); mono_profiler_gc_event (MONO_GC_EVENT_END, generation_to_collect); From 87e7f1c2d7cb85b9edb81382628664824ef28bdc Mon Sep 17 00:00:00 2001 From: Dan Parnham Date: Wed, 22 Oct 2014 16:21:20 +0100 Subject: [PATCH 446/543] Included /dev/ttyACM in the search for serial port devices, since CDC ACM is a standard protocol for emulating serial ports over USB. --- mcs/class/System/System.IO.Ports/SerialPort.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mcs/class/System/System.IO.Ports/SerialPort.cs b/mcs/class/System/System.IO.Ports/SerialPort.cs index 08a9a655b2e..65189c5813f 100644 --- a/mcs/class/System/System.IO.Ports/SerialPort.cs +++ b/mcs/class/System/System.IO.Ports/SerialPort.cs @@ -529,7 +529,7 @@ public static string [] GetPortNames () // Probe for Linux-styled devices: /dev/ttyS* or /dev/ttyUSB* // foreach (string dev in ttys) { - if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB")){ + if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM")) { linux_style = true; break; } @@ -537,7 +537,7 @@ public static string [] GetPortNames () foreach (string dev in ttys) { if (linux_style){ - if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB")) + if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM")) serial_ports.Add (dev); } else { if (dev != "/dev/tty" && dev.StartsWith ("/dev/tty") && !dev.StartsWith ("/dev/ttyC")) From bb86670c280aa1bc0b60ec53fdd93272af30f50c Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 22 Oct 2014 14:22:12 -0400 Subject: [PATCH 447/543] [bcl] Fix races in task tests. --- .../Test/System.Threading.Tasks/TaskTest.cs | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs index 4e358cadd94..d93122f7b3c 100644 --- a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs +++ b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs @@ -788,19 +788,53 @@ public void DoubleWaitTest () { ParallelTestHelper.Repeat (delegate { var evt = new ManualResetEventSlim (); - var t = Task.Factory.StartNew (() => evt.Wait (5000)); + var monitor = new object (); + int finished = 0; + var t = Task.Factory.StartNew (delegate { + var r = evt.Wait (5000); + lock (monitor) { + finished ++; + Monitor.Pulse (monitor); + } + return r; + }); var cntd = new CountdownEvent (2); var cntd2 = new CountdownEvent (2); bool r1 = false, r2 = false; - ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000) && t.Result; cntd2.Signal (); }); - ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000) && t.Result; cntd2.Signal (); }); - + ThreadPool.QueueUserWorkItem (delegate { + cntd.Signal (); + r1 = t.Wait (1000) && t.Result; + cntd2.Signal (); + lock (monitor) { + finished ++; + Monitor.Pulse (monitor); + } + }); + ThreadPool.QueueUserWorkItem (delegate { + cntd.Signal (); + r2 = t.Wait (1000) && t.Result; + cntd2.Signal (); + lock (monitor) { + finished ++; + Monitor.Pulse (monitor); + } + }); Assert.IsTrue (cntd.Wait (2000), "#1"); evt.Set (); Assert.IsTrue (cntd2.Wait (2000), "#2"); Assert.IsTrue (r1, "r1"); Assert.IsTrue (r2, "r2"); + + // Wait for everything to finish to avoid overloading the tpool + lock (monitor) { + while (true) { + if (finished == 3) + break; + else + Monitor.Wait (monitor); + } + } }, 10); } From 21656fd89f25a0dfb74d6b4918d389e6314715c8 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Wed, 22 Oct 2014 15:19:10 -0500 Subject: [PATCH 448/543] Fix win32 build. This commit licensed as MIT/X11. --- mono/mini/mini-windows.c | 2 +- mono/mini/mini.c | 2 +- mono/utils/mono-signal-handler.h | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mono/mini/mini-windows.c b/mono/mini/mini-windows.c index 614f7af6fed..9488ac895d9 100644 --- a/mono/mini/mini-windows.c +++ b/mono/mini/mini-windows.c @@ -79,7 +79,7 @@ mono_runtime_cleanup_handlers (void) * was called, false otherwise. */ gboolean -SIG_HANDLER_SIGNATURE (mono_chain_signal) +MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) { MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); jit_tls->mono_win_chained_exception_needs_run = TRUE; diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 551cde95816..dd40298565b 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -6790,7 +6790,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); gpointer fault_addr = NULL; #ifdef HAVE_SIG_INFO - siginfo_t *info = MONO_SIG_HANDLER_GET_INFO (); + MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO (); #endif MONO_SIG_HANDLER_GET_CONTEXT; diff --git a/mono/utils/mono-signal-handler.h b/mono/utils/mono-signal-handler.h index c5b609f17df..fbe798eeb0e 100644 --- a/mono/utils/mono-signal-handler.h +++ b/mono/utils/mono-signal-handler.h @@ -40,6 +40,7 @@ #define MONO_SIG_HANDLER_PARAMS _dummy, _info, context #define MONO_SIG_HANDLER_GET_SIGNO() (_dummy) #define MONO_SIG_HANDLER_GET_INFO() (_info) +#define MONO_SIG_HANDLER_INFO_TYPE EXCEPTION_POINTERS /* seh_vectored_exception_handler () passes in a CONTEXT* */ #define MONO_SIG_HANDLER_GET_CONTEXT \ void *ctx = context; @@ -50,6 +51,7 @@ #define MONO_SIG_HANDLER_PARAMS _dummy, _info, context #define MONO_SIG_HANDLER_GET_SIGNO() (_dummy) #define MONO_SIG_HANDLER_GET_INFO() (_info) +#define MONO_SIG_HANDLER_INFO_TYPE siginfo_t #define MONO_SIG_HANDLER_GET_CONTEXT \ void *ctx = context; #endif From a142d922aa159f6fcb5b0d07f4c32b7eb014037f Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 22 Oct 2014 17:08:08 -0400 Subject: [PATCH 449/543] [threadpool] Fix deadlock/starvation of the thread pool The issue was with the new heuristic of the thread pool which would not create new threads, leading to deadlock between dependent tasks. The fix is to check if every worker threads are sleeping, waiting or joining, and if that's the case, then we create a new thread because we might be in the case where the tasks being currently run depends on one still being enqueued in the cq or one of the wsq. The following tests would previously fail : 1) MonoTests.System.Threading.Tasks.TaskTests.DoubleWaitTest : #1 Expected: True But was: False at MonoTests.System.Threading.Tasks.TaskTests.m__27 () [0x00077] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs:800 at MonoTests.System.Threading.Tasks.ParallelTestHelper.Repeat (System.Action action, Int32 numRun) [0x00007] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/ParallelTestHelper.cs:48 at MonoTests.System.Threading.Tasks.TaskTests.DoubleWaitTest () [0x00000] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs:790 at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00054] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:230 2) MonoTests.System.Threading.Tasks.TaskTests.HideSchedulerTest : #1 Expected: True But was: False at MonoTests.System.Threading.Tasks.TaskTests.HideSchedulerTest () [0x0003d] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs:1914 at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00054] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:230 3) MonoTests.System.Threading.Tasks.TaskTests.WaitAll_TimeoutWithExceptionsAfter : #1 Expected: True But was: False at MonoTests.System.Threading.Tasks.TaskTests.WaitAll_TimeoutWithExceptionsAfter () [0x00070] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs:317 at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00054] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:230 4) MonoTests.System.Threading.Tasks.TaskTests.WaitAll_TimeoutWithExceptionsBefore : #1 Expected: True But was: False at MonoTests.System.Threading.Tasks.TaskTests.WaitAll_TimeoutWithExceptionsBefore () [0x00070] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs:341 at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00054] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:230 5) MonoTests.System.Threading.Tasks.TaskTests.WaitAnyTest : #3 Expected: not -1 But was: -1 at MonoTests.System.Threading.Tasks.TaskTests.m__0 () [0x00026] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs:142 at MonoTests.System.Threading.Tasks.ParallelTestHelper.Repeat (System.Action action, Int32 numRun) [0x00007] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/ParallelTestHelper.cs:48 at MonoTests.System.Threading.Tasks.ParallelTestHelper.Repeat (System.Action action) [0x00000] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/ParallelTestHelper.cs:42 at MonoTests.System.Threading.Tasks.TaskTests.WaitAnyTest () [0x00000] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs:128 at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00054] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:230 6) MonoTests.System.Threading.Tasks.TaskTests.WaitChildTestCase : #0b Expected: True But was: False at MonoTests.System.Threading.Tasks.TaskTests.m__25 () [0x0006d] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs:705 at MonoTests.System.Threading.Tasks.ParallelTestHelper.Repeat (System.Action action, Int32 numRun) [0x00007] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/ParallelTestHelper.cs:48 at MonoTests.System.Threading.Tasks.TaskTests.WaitChildTestCase () [0x00000] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs:684 at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00054] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:230 7) MonoTests.System.Threading.Tasks.TaskTests.WaitingForChildrenToComplete : #3 Expected: True But was: False at MonoTests.System.Threading.Tasks.TaskTests.WaitingForChildrenToComplete () [0x00048] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs:734 at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00054] in /Users/ludovic/Xamarin/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:230 --- .../Test/System.Threading.Tasks/TaskTest.cs | 2 + mono/metadata/threadpool.c | 71 +++++++++++++++---- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs index d93122f7b3c..a7c006a204b 100644 --- a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs +++ b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs @@ -111,6 +111,8 @@ protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQ [SetUp] public void Setup() { + ThreadPool.SetMinThreads (1, 1); + tasks = new Task[max]; } diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c index 02acb073a85..3c712920d4f 100644 --- a/mono/metadata/threadpool.c +++ b/mono/metadata/threadpool.c @@ -158,6 +158,8 @@ static MonoClass *async_call_klass; static MonoClass *socket_async_call_klass; static MonoClass *process_async_call_klass; +static GPtrArray *threads; +mono_mutex_t threads_lock; static GPtrArray *wsqs; mono_mutex_t wsqs_lock; static gboolean suspended; @@ -789,6 +791,8 @@ monitor_heuristic (gint16 *current, gint16 *history_size, SamplesHistory *histor int i; gint8 decision; gint16 cur, max = 0; + gboolean all_waitsleepjoin; + MonoInternalThread *thread; /* * The following heuristic tries to approach the optimal number of threads to maximize jobs throughput. To @@ -824,22 +828,39 @@ monitor_heuristic (gint16 *current, gint16 *history_size, SamplesHistory *histor history [cur].nthreads_diff = 1; decision = 2; } else { - max = cur == 0 ? 1 : 0; - for (i = 0; i < *history_size; i++) { - if (i == cur) - continue; - if (history [i].nexecuted > history [max].nexecuted) - max = i; + mono_mutex_lock (&threads_lock); + all_waitsleepjoin = TRUE; + for (i = 0; i < threads->len; ++i) { + thread = g_ptr_array_index (threads, i); + if (!(thread->state & ThreadState_WaitSleepJoin)) { + all_waitsleepjoin = FALSE; + break; + } } + mono_mutex_unlock (&threads_lock); - if (history [cur].nexecuted >= history [max].nexecuted) { - /* we improved the situation, let's continue ! */ - history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? 1 : -1; - decision = 3; + if (all_waitsleepjoin) { + /* we might be in a condition of starvation/deadlock with tasks waiting for each others */ + history [cur].nthreads_diff = 1; + decision = 5; } else { - /* we made it worse, let's return to previous situation */ - history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? -1 : 1; - decision = 4; + max = cur == 0 ? 1 : 0; + for (i = 0; i < *history_size; i++) { + if (i == cur) + continue; + if (history [i].nexecuted > history [max].nexecuted) + max = i; + } + + if (history [cur].nexecuted >= history [max].nexecuted) { + /* we improved the situation, let's continue ! */ + history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? 1 : -1; + decision = 3; + } else { + /* we made it worse, let's return to previous situation */ + history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? -1 : 1; + decision = 4; + } } } @@ -969,6 +990,9 @@ mono_thread_pool_init (void) async_call_klass = mono_class_from_name (mono_defaults.corlib, "System", "MonoAsyncCall"); g_assert (async_call_klass); + mono_mutex_init (&threads_lock); + threads = g_ptr_array_sized_new (thread_count); + mono_mutex_init_recursive (&wsqs_lock); wsqs = g_ptr_array_sized_new (MAX (100 * cpu_count, thread_count)); @@ -1120,6 +1144,14 @@ mono_thread_pool_cleanup (void) threadpool_kill_idle_threads (&async_tp); threadpool_free_queue (&async_tp); } + + if (threads) { + mono_mutex_lock (&threads_lock); + if (threads) + g_ptr_array_free (threads, FALSE); + threads = NULL; + mono_mutex_unlock (&threads_lock); + } if (wsqs) { mono_mutex_lock (&wsqs_lock); @@ -1139,6 +1171,7 @@ threadpool_start_thread (ThreadPool *tp) { gint n; guint32 stack_size; + MonoInternalThread *thread; stack_size = (!tp->is_io) ? 0 : SMALL_STACK; while (!mono_runtime_is_shutting_down () && (n = tp->nthreads) < tp->max_threads) { @@ -1146,7 +1179,12 @@ threadpool_start_thread (ThreadPool *tp) #ifndef DISABLE_PERFCOUNTERS mono_perfcounter_update_value (tp->pc_nthreads, TRUE, 1); #endif - mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size); + thread = mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size); + if (!tp->is_io) { + mono_mutex_lock (&threads_lock); + g_ptr_array_add (threads, thread); + mono_mutex_unlock (&threads_lock); + } return TRUE; } } @@ -1665,6 +1703,11 @@ async_invoke_thread (gpointer data) if (tp_finish_func) tp_finish_func (tp_hooks_user_data); + + mono_mutex_lock (&threads_lock); + g_ptr_array_remove_fast (threads, mono_thread_current ()->internal_thread); + mono_mutex_unlock (&threads_lock); + return; } } From 6ec1ebf99078a996ca16fd0c56cbd4e96e32ed41 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 22 Oct 2014 17:13:27 -0400 Subject: [PATCH 450/543] [llvm] Rewrite the way direct calls are made between llvm methods. Previously all calls were made to plt entries and the plt entry symbols were aliased to point to the corresponding method if the method was directly callable using the .set assembler directive. This doesn't seem to work with newer LLVM/CLANG versions, so do this completely on the LLVM side using Value::replaceAllUsesWith (). Fixes #23976. --- mono/mini/aot-compiler.c | 51 +++++++++++++++------------------------- mono/mini/mini-llvm.c | 38 ++++++++++++++++++++++++++++++ mono/mini/mini.h | 2 ++ 3 files changed, 59 insertions(+), 32 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 592567e89f5..4b53f0cae19 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -5776,41 +5776,16 @@ emit_plt (MonoAotCompile *acfg) plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i)); ji = plt_entry->ji; - if (acfg->llvm) { - /* - * If the target is directly callable, alias the plt symbol to point to - * the method code. - * FIXME: Use this to simplify emit_and_reloc_code (). - * FIXME: Avoid the got slot. - * FIXME: Add support to the binary writer. - */ - if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer) { - MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, ji->data.method); - - if (callee_cfg) { - if (acfg->thumb_mixed && !callee_cfg->compile_llvm) { - /* LLVM calls the PLT entries using bl, so emit a stub */ - emit_set_thumb_mode (acfg); - fprintf (acfg->fp, "\n.thumb_func\n"); - emit_label (acfg, plt_entry->llvm_symbol); - fprintf (acfg->fp, "bx pc\n"); - fprintf (acfg->fp, "nop\n"); - emit_set_arm_mode (acfg); - fprintf (acfg->fp, "b %s\n", callee_cfg->asm_symbol); - } else { - fprintf (acfg->fp, "\n.set %s, %s\n", plt_entry->llvm_symbol, callee_cfg->asm_symbol); - } - continue; - } - } - } - debug_sym = plt_entry->debug_sym; if (acfg->thumb_mixed && !plt_entry->jit_used) /* Emit only a thumb version */ continue; + /* Skip plt entries not actually called */ + if (!plt_entry->jit_used && !plt_entry->llvm_used) + continue; + if (acfg->llvm && !acfg->thumb_mixed) emit_label (acfg, plt_entry->llvm_symbol); @@ -5850,9 +5825,6 @@ emit_plt (MonoAotCompile *acfg) plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i)); ji = plt_entry->ji; - if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer) - continue; - /* Skip plt entries not actually called by LLVM code */ if (!plt_entry->llvm_used) continue; @@ -7027,6 +6999,21 @@ mono_aot_get_method_name (MonoCompile *cfg) return get_debug_sym (cfg->orig_method, "", llvm_acfg->method_label_hash); } +gboolean +mono_aot_is_direct_callable (MonoJumpInfo *patch_info) +{ + return is_direct_callable (llvm_acfg, NULL, patch_info); +} + +void +mono_aot_mark_unused_llvm_plt_entry (MonoJumpInfo *patch_info) +{ + MonoPltEntry *plt_entry; + + plt_entry = get_plt_entry (llvm_acfg, patch_info); + plt_entry->llvm_used = FALSE; +} + char* mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data) { diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index 6551f78e021..2b778c3aaab 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -10,6 +10,7 @@ #include #include #include +#include #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS @@ -35,6 +36,8 @@ typedef struct { LLVMValueRef got_var; const char *got_symbol; GHashTable *plt_entries; + GHashTable *plt_entries_ji; + GHashTable *method_to_lmethod; char **bb_names; int bb_names_len; GPtrArray *used; @@ -1272,6 +1275,7 @@ get_plt_entry (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gc { char *callee_name = mono_aot_get_plt_symbol (type, data); LLVMValueRef callee; + MonoJumpInfo *ji = NULL; if (!callee_name) return NULL; @@ -1290,6 +1294,14 @@ get_plt_entry (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gc g_hash_table_insert (ctx->lmodule->plt_entries, (char*)callee_name, callee); } + if (ctx->cfg->compile_aot) { + ji = g_new0 (MonoJumpInfo, 1); + ji->type = type; + ji->data.target = data; + + g_hash_table_insert (ctx->lmodule->plt_entries_ji, ji, callee); + } + return callee; } @@ -4675,6 +4687,9 @@ mono_llvm_emit_method (MonoCompile *cfg) /* FIXME: Free the LLVM IL for the function */ } + if (ctx->lmodule->method_to_lmethod) + g_hash_table_insert (ctx->lmodule->method_to_lmethod, cfg->method, method); + goto CLEANUP; FAILURE: @@ -5331,6 +5346,8 @@ mono_llvm_create_aot_module (const char *got_symbol) aot_module.llvm_types = g_hash_table_new (NULL, NULL); aot_module.plt_entries = g_hash_table_new (g_str_hash, g_str_equal); + aot_module.plt_entries_ji = g_hash_table_new (NULL, NULL); + aot_module.method_to_lmethod = g_hash_table_new (NULL, NULL); } /* @@ -5341,6 +5358,7 @@ mono_llvm_emit_aot_module (const char *filename, int got_size) { LLVMTypeRef got_type; LLVMValueRef real_got; + MonoLLVMModule *module = &aot_module; /* * Create the real got variable and replace all uses of the dummy variable with @@ -5360,6 +5378,26 @@ mono_llvm_emit_aot_module (const char *filename, int got_size) emit_llvm_used (&aot_module); + /* Replace PLT entries for directly callable methods with the methods themselves */ + { + GHashTableIter iter; + MonoJumpInfo *ji; + LLVMValueRef callee; + + g_hash_table_iter_init (&iter, aot_module.plt_entries_ji); + while (g_hash_table_iter_next (&iter, (void**)&ji, (void**)&callee)) { + if (mono_aot_is_direct_callable (ji)) { + LLVMValueRef lmethod; + + lmethod = g_hash_table_lookup (module->method_to_lmethod, ji->data.method); + if (lmethod) { + mono_llvm_replace_uses_of (callee, lmethod); + mono_aot_mark_unused_llvm_plt_entry (ji); + } + } + } + } + #if 0 { char *verifier_err; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 61de960970f..8d9bcc9f206 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2174,6 +2174,8 @@ guint32 mono_aot_method_hash (MonoMethod *method) MONO_INTERNAL; MonoMethod* mono_aot_get_array_helper_from_wrapper (MonoMethod *method) MONO_INTERNAL; guint32 mono_aot_get_got_offset (MonoJumpInfo *ji) MONO_LLVM_INTERNAL; char* mono_aot_get_method_name (MonoCompile *cfg) MONO_LLVM_INTERNAL; +gboolean mono_aot_is_direct_callable (MonoJumpInfo *patch_info) MONO_LLVM_INTERNAL; +void mono_aot_mark_unused_llvm_plt_entry(MonoJumpInfo *patch_info) MONO_LLVM_INTERNAL; char* mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data) MONO_LLVM_INTERNAL; int mono_aot_get_method_index (MonoMethod *method) MONO_LLVM_INTERNAL; MonoJumpInfo* mono_aot_patch_info_dup (MonoJumpInfo* ji) MONO_LLVM_INTERNAL; From 8d9f05ea9a943ff1a36bb0ef3dd0521853d3a489 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 22 Oct 2014 18:20:34 -0400 Subject: [PATCH 451/543] [runtime] Add checks for overlapping reference and non-reference fields when using explicit layout. Fixes #23954. --- mono/metadata/class.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 54d2d5c85a8..6516e2366aa 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -1943,7 +1943,10 @@ mono_class_layout_fields (MonoClass *class) } } break; - case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: + case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: { + guint8 *ref_bitmap; + + ref_bitmap = g_new0 (guint8, class->instance_size / sizeof (gpointer)); real_size = 0; for (i = 0; i < top; i++) { gint32 align; @@ -1956,7 +1959,6 @@ mono_class_layout_fields (MonoClass *class) * There must be info about all the fields in a type if it * uses explicit layout. */ - if (mono_field_is_deleted (field)) continue; if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) @@ -1979,6 +1981,7 @@ mono_class_layout_fields (MonoClass *class) if (field->offset % sizeof (gpointer)) { mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL); } + ref_bitmap [field->offset / sizeof (gpointer)] = 1; } /* @@ -1986,6 +1989,23 @@ mono_class_layout_fields (MonoClass *class) */ real_size = MAX (real_size, size + field->offset); } + + /* Check for overlapping reference and non-reference fields */ + for (i = 0; i < top; i++) { + field = &class->fields [i]; + + if (mono_field_is_deleted (field)) + continue; + if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) + continue; + + if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) { + char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset); + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg); + } + } + g_free (ref_bitmap); + class->instance_size = MAX (real_size, class->instance_size); if (class->instance_size & (class->min_align - 1)) { class->instance_size += class->min_align - 1; @@ -1993,6 +2013,7 @@ mono_class_layout_fields (MonoClass *class) } break; } + } if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) { /* From 916abe5f57b986acec10e33b81e758b6f1fdeb15 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Thu, 23 Oct 2014 11:00:12 -0400 Subject: [PATCH 452/543] [bcl] Restore ThreadPool number of threads configuration after each test --- mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs index a7c006a204b..524988828b9 100644 --- a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs +++ b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs @@ -104,6 +104,8 @@ protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQ } } + int workerThreads; + int completionPortThreads; Task[] tasks; const int max = 6; @@ -111,11 +113,18 @@ protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQ [SetUp] public void Setup() { + ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads); ThreadPool.SetMinThreads (1, 1); tasks = new Task[max]; } + [TearDown] + public void Teardown() + { + ThreadPool.SetMinThreads (workerThreads, completionPortThreads); + } + void InitWithDelegate(Action action) { for (int i = 0; i < max; i++) { From 87f4b147522e1c55ebdfe4de1d4679bab4acfa04 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 23 Oct 2014 13:56:33 -0400 Subject: [PATCH 453/543] [jit] Print out methods which failed to JIT when using --regression. --- mono/mini/driver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mono/mini/driver.c b/mono/mini/driver.c index 258bae6cbab..c6c8e20628c 100644 --- a/mono/mini/driver.c +++ b/mono/mini/driver.c @@ -408,8 +408,7 @@ mini_regression_step (MonoImage *image, int verbose, int *total_run, int *total, } else { cfailed++; - if (verbose) - g_print ("Test '%s' failed compilation.\n", method->name); + g_print ("Test '%s' failed compilation.\n", method->name); } if (mini_stats_fd) fprintf (mini_stats_fd, "%f, ", From 2d3dd5a40af0d687cb5bbbd018fe4d10803ff8c3 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 23 Oct 2014 14:04:32 -0400 Subject: [PATCH 454/543] [runtime] Fix a regression introduced by 8d9f05ea9a943ff1a36bb0ef3dd0521853d3a489. Only do the check for overlapping fields when the size of the type is known. --- mono/metadata/class.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 6516e2366aa..519eec9a191 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -1946,7 +1946,6 @@ mono_class_layout_fields (MonoClass *class) case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: { guint8 *ref_bitmap; - ref_bitmap = g_new0 (guint8, class->instance_size / sizeof (gpointer)); real_size = 0; for (i = 0; i < top; i++) { gint32 align; @@ -1981,7 +1980,6 @@ mono_class_layout_fields (MonoClass *class) if (field->offset % sizeof (gpointer)) { mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL); } - ref_bitmap [field->offset / sizeof (gpointer)] = 1; } /* @@ -1990,21 +1988,38 @@ mono_class_layout_fields (MonoClass *class) real_size = MAX (real_size, size + field->offset); } - /* Check for overlapping reference and non-reference fields */ - for (i = 0; i < top; i++) { - field = &class->fields [i]; + if (class->has_references) { + ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer)); - if (mono_field_is_deleted (field)) - continue; - if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) - continue; + /* Check for overlapping reference and non-reference fields */ + for (i = 0; i < top; i++) { + MonoType *ftype; + + field = &class->fields [i]; + + if (mono_field_is_deleted (field)) + continue; + if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) + continue; + ftype = mono_type_get_underlying_type (field->type); + if (MONO_TYPE_IS_REFERENCE (ftype)) + ref_bitmap [field->offset / sizeof (gpointer)] = 1; + } + for (i = 0; i < top; i++) { + field = &class->fields [i]; + + if (mono_field_is_deleted (field)) + continue; + if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) + continue; - if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) { - char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset); - mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg); + if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) { + char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset); + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg); + } } + g_free (ref_bitmap); } - g_free (ref_bitmap); class->instance_size = MAX (real_size, class->instance_size); if (class->instance_size & (class->min_align - 1)) { From e1da8e304d3b330a968de9c14305632e9285e5ca Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 23 Oct 2014 14:47:19 -0400 Subject: [PATCH 455/543] [jit] Use NULLIFY_INS () to nullify instructions and use MONO_INST_NEW to create phi node instructions to avoid asserts in the spill pass. Fixes #24006. --- mono/mini/branch-opts.c | 2 +- mono/mini/decompose.c | 18 +++++++++--------- mono/mini/liveness.c | 4 +--- mono/mini/method-to-ir.c | 6 +++--- mono/mini/ssa.c | 18 ++++++------------ 5 files changed, 20 insertions(+), 28 deletions(-) diff --git a/mono/mini/branch-opts.c b/mono/mini/branch-opts.c index 44a78aa476b..2be95e73642 100644 --- a/mono/mini/branch-opts.c +++ b/mono/mini/branch-opts.c @@ -1299,7 +1299,7 @@ mono_optimize_branches (MonoCompile *cfg) /* branches to the following block can be removed */ if (bb->last_ins && bb->last_ins->opcode == OP_BR && !bbn->out_of_line) { - bb->last_ins->opcode = OP_NOP; + NULLIFY_INS (bb->last_ins); changed = TRUE; if (cfg->verbose_level > 2) g_print ("br removal triggered %d -> %d\n", bb->block_num, bbn->block_num); diff --git a/mono/mini/decompose.c b/mono/mini/decompose.c index 84db9c7eab4..907d7582ae2 100644 --- a/mono/mini/decompose.c +++ b/mono/mini/decompose.c @@ -470,7 +470,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) } #endif MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2); - ins->opcode = OP_NOP; + NULLIFY_INS (ins); } else { emulate = TRUE; } @@ -980,7 +980,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0); MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } case OP_LBGE: @@ -998,7 +998,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb); MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1); MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; case OP_LCEQ: { int d1, d2; @@ -1012,7 +1012,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0); MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } case OP_LCLT: @@ -1034,7 +1034,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_START_BB (cfg, set_to_1); MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1); MONO_START_BB (cfg, set_to_0); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } default: @@ -1066,7 +1066,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0); MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } @@ -1085,7 +1085,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm); MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; case OP_LCEQ: { int d1, d2; @@ -1099,7 +1099,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0); MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } case OP_LCLT: @@ -1121,7 +1121,7 @@ mono_decompose_long_opts (MonoCompile *cfg) MONO_START_BB (cfg, set_to_1); MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1); MONO_START_BB (cfg, set_to_0); - next->opcode = OP_NOP; + NULLIFY_INS (next); break; } default: diff --git a/mono/mini/liveness.c b/mono/mini/liveness.c index a5cbabb53a5..5f304b390fd 100644 --- a/mono/mini/liveness.c +++ b/mono/mini/liveness.c @@ -812,9 +812,7 @@ update_liveness2 (MonoCompile *cfg, MonoInst *ins, gboolean set_volatile, int in /* Try dead code elimination */ if ((var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST)) && !(var->flags & MONO_INST_VOLATILE)) { LIVENESS_DEBUG (printf ("\tdead def of R%d, eliminated\n", ins->dreg)); - ins->opcode = OP_NOP; - ins->dreg = -1; - MONO_INST_NULLIFY_SREGS (ins); + NULLIFY_INS (ins); return; } diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index e9c1fa3dcd5..7a8c4d3f9f8 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -9310,7 +9310,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b ins->inst_p1 = (gpointer)(gssize)(sp [1]->inst_c0); ins->sreg2 = -1; - sp [1]->opcode = OP_NOP; + NULLIFY_INS (sp [1]); } } @@ -9371,7 +9371,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b /* Might be followed by an instruction added by ADD_WIDEN_OP */ if (sp [1]->next == NULL) - sp [1]->opcode = OP_NOP; + NULLIFY_INS (sp [1]); } } MONO_ADD_INS ((cfg)->cbb, (ins)); @@ -11779,9 +11779,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b * The backends expect the fceq opcodes to do the * comparison too. */ - cmp->opcode = OP_NOP; ins->sreg1 = cmp->sreg1; ins->sreg2 = cmp->sreg2; + NULLIFY_INS (cmp); } MONO_ADD_INS (bblock, ins); *sp++ = ins; diff --git a/mono/mini/ssa.c b/mono/mini/ssa.c index 801826b96e8..160db5fec57 100644 --- a/mono/mini/ssa.c +++ b/mono/mini/ssa.c @@ -26,10 +26,8 @@ //#define DEBUG_SSA 1 #define NEW_PHI(cfg,dest,val) do { \ - (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \ - (dest)->opcode = OP_PHI; \ - (dest)->inst_c0 = (val); \ - (dest)->dreg = (dest)->sreg1 = (dest)->sreg2 = -1; \ + MONO_INST_NEW ((cfg), (dest), OP_PHI); \ + (dest)->inst_c0 = (val); \ } while (0) typedef struct { @@ -530,8 +528,7 @@ mono_ssa_remove (MonoCompile *cfg) } } - ins->opcode = OP_NOP; - ins->dreg = -1; + NULLIFY_INS (ins); } } } @@ -1287,12 +1284,10 @@ mono_ssa_deadce (MonoCompile *cfg) MonoInst *src_var = get_vreg_to_inst (cfg, def->sreg1); if (src_var && !(src_var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT))) add_to_dce_worklist (cfg, info, MONO_VARINFO (cfg, src_var->inst_c0), &work_list); - def->opcode = OP_NOP; - def->dreg = def->sreg1 = def->sreg2 = -1; + NULLIFY_INS (def); info->reg = -1; } else if ((def->opcode == OP_ICONST) || (def->opcode == OP_I8CONST) || MONO_IS_ZERO (def)) { - def->opcode = OP_NOP; - def->dreg = def->sreg1 = def->sreg2 = -1; + NULLIFY_INS (def); info->reg = -1; } else if (MONO_IS_PHI (def)) { int j; @@ -1300,8 +1295,7 @@ mono_ssa_deadce (MonoCompile *cfg) MonoMethodVar *u = MONO_VARINFO (cfg, get_vreg_to_inst (cfg, def->inst_phi_args [j])->inst_c0); add_to_dce_worklist (cfg, info, u, &work_list); } - def->opcode = OP_NOP; - def->dreg = def->sreg1 = def->sreg2 = -1; + NULLIFY_INS (def); info->reg = -1; } else if (def->opcode == OP_NOP) { From dd68e53636c48f743f75fc67a272bb16c410ba5e Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Thu, 11 Sep 2014 16:50:00 -0500 Subject: [PATCH 456/543] File URI's without a host are not UNC paths on Windows. NUnit breaks when these URI's are treated as UNC paths, so I have no way of running the tests on Windows without this change to see if it broke anything. Not all URI tests pass, but the ones that fail seem unrelated to my change. On Unix, the tests all work, but of course on Unix this is a no-op. This commit licensed as MIT/X11. --- mcs/class/System/System/UriParseComponents.cs | 21 ++-- mcs/class/System/Test/System/UriTest2.cs | 96 +++++++++++++++++++ 2 files changed, 107 insertions(+), 10 deletions(-) diff --git a/mcs/class/System/System/UriParseComponents.cs b/mcs/class/System/System/UriParseComponents.cs index 5e94d3bdf53..dfbd0e75b21 100644 --- a/mcs/class/System/System/UriParseComponents.cs +++ b/mcs/class/System/System/UriParseComponents.cs @@ -269,15 +269,6 @@ private static bool ParseScheme (ParserState state) return state.remaining.Length > 0; } - if (state.elements.scheme == Uri.UriSchemeFile) { - // under Windows all file:// URI are considered UNC, which is not the case other MacOS (e.g. Silverlight) -#if BOOTSTRAP_BASIC - state.elements.isUnc = (Path.DirectorySeparatorChar == '\\'); -#else - state.elements.isUnc = Environment.IsRunningOnWindows; -#endif - } - return ParseDelimiter (state); } @@ -430,7 +421,17 @@ private static bool ParseHost (ParserState state) state.elements.host = state.elements.host.ToLowerInvariant (); state.remaining = part.Substring (state.elements.host.Length); - + + if (state.elements.scheme == Uri.UriSchemeFile && + state.elements.host != "") { + // under Windows all file://host URI are considered UNC, which is not the case other MacOS (e.g. Silverlight) +#if BOOTSTRAP_BASIC + state.elements.isUnc = (Path.DirectorySeparatorChar == '\\'); +#else + state.elements.isUnc = Environment.IsRunningOnWindows; +#endif + } + return state.remaining.Length > 0; } diff --git a/mcs/class/System/Test/System/UriTest2.cs b/mcs/class/System/Test/System/UriTest2.cs index 73b143aae2f..e3a4530e0c6 100644 --- a/mcs/class/System/Test/System/UriTest2.cs +++ b/mcs/class/System/Test/System/UriTest2.cs @@ -919,6 +919,102 @@ public void FileScheme () Assert.AreEqual ("/%3C%3E%25%22%7B%7D%7C/%5E%60;/:@&=+$,%5B%5D%3F", uri.AbsolutePath, "Special"); } + [Test] + public void LocalFile () + { + Uri uri = new Uri ("file:///c:/subdir/file"); + + Assert.AreEqual ("c:/subdir/file", uri.AbsolutePath, "AbsolutePath"); + Assert.AreEqual ("file:///c:/subdir/file", uri.AbsoluteUri, "AbsoluteUri"); + Assert.AreEqual ("c:\\subdir\\file", uri.LocalPath, "LocalPath"); + Assert.AreEqual ("c:/subdir/file", uri.PathAndQuery, "PathAndQuery"); + Assert.AreEqual (String.Empty, uri.Query, "Query"); + Assert.AreEqual ("file", uri.Segments [3], "Segments [3]"); + + Assert.AreEqual (String.Empty, uri.Authority, "Authority"); + Assert.AreEqual (String.Empty, uri.DnsSafeHost, "DnsSafeHost"); + Assert.AreEqual (String.Empty, uri.Fragment, "Fragment"); + Assert.AreEqual (String.Empty, uri.Host, "Host"); + Assert.AreEqual (UriHostNameType.Basic, uri.HostNameType, "HostNameType"); + Assert.IsTrue (uri.IsAbsoluteUri, "IsAbsoluteUri"); + Assert.IsTrue (uri.IsDefaultPort, "IsDefaultPort"); + Assert.IsTrue (uri.IsFile, "IsFile"); + Assert.IsTrue (uri.IsLoopback, "IsLoopback"); + Assert.IsFalse (uri.IsUnc, "IsUnc"); + Assert.AreEqual ("file:///c:/subdir/file", uri.OriginalString, "OriginalString"); + Assert.AreEqual (-1, uri.Port, "Port"); + Assert.AreEqual ("file", uri.Scheme, "Scheme"); + Assert.AreEqual ("/", uri.Segments [0], "Segments [0]"); + Assert.AreEqual ("c:/", uri.Segments [1], "Segments [1]"); + Assert.AreEqual ("subdir/", uri.Segments [2], "Segments [2]"); + Assert.IsFalse (uri.UserEscaped, "UserEscaped"); + Assert.AreEqual (String.Empty, uri.UserInfo, "UserInfo"); + } + + [Test] + public void LocalhostWinFile () + { + Uri uri = new Uri ("file://localhost/c:/subdir/file"); + + Assert.AreEqual ("/c:/subdir/file", uri.AbsolutePath, "AbsolutePath"); + Assert.AreEqual ("file://localhost/c:/subdir/file", uri.AbsoluteUri, "AbsoluteUri"); + Assert.AreEqual (isWin32 ? "\\\\localhost\\c:\\subdir\\file" : "/c:/subdir/file", uri.LocalPath, "LocalPath"); + Assert.AreEqual ("/c:/subdir/file", uri.PathAndQuery, "PathAndQuery"); + Assert.AreEqual (String.Empty, uri.Query, "Query"); + Assert.AreEqual ("file", uri.Segments [3], "Segments [3]"); + + Assert.AreEqual ("localhost", uri.Authority, "Authority"); + Assert.AreEqual ("localhost", uri.DnsSafeHost, "DnsSafeHost"); + Assert.AreEqual (String.Empty, uri.Fragment, "Fragment"); + Assert.AreEqual ("localhost", uri.Host, "Host"); + Assert.AreEqual (UriHostNameType.Dns, uri.HostNameType, "HostNameType"); + Assert.IsTrue (uri.IsAbsoluteUri, "IsAbsoluteUri"); + Assert.IsTrue (uri.IsDefaultPort, "IsDefaultPort"); + Assert.IsTrue (uri.IsFile, "IsFile"); + Assert.IsTrue (uri.IsLoopback, "IsLoopback"); + Assert.AreEqual (isWin32, uri.IsUnc, "IsUnc"); + Assert.AreEqual ("file://localhost/c:/subdir/file", uri.OriginalString, "OriginalString"); + Assert.AreEqual (-1, uri.Port, "Port"); + Assert.AreEqual ("file", uri.Scheme, "Scheme"); + Assert.AreEqual ("/", uri.Segments [0], "Segments [0]"); + Assert.AreEqual ("c:/", uri.Segments [1], "Segments [1]"); + Assert.AreEqual ("subdir/", uri.Segments [2], "Segments [2]"); + Assert.IsFalse (uri.UserEscaped, "UserEscaped"); + Assert.AreEqual (String.Empty, uri.UserInfo, "UserInfo"); + } + + [Test] + public void LocalhostFile () + { + Uri uri = new Uri ("file://localhost/dir/subdir/file"); + + Assert.AreEqual ("/dir/subdir/file", uri.AbsolutePath, "AbsolutePath"); + Assert.AreEqual ("file://localhost/dir/subdir/file", uri.AbsoluteUri, "AbsoluteUri"); + Assert.AreEqual (isWin32 ? "\\\\localhost\\dir\\subdir\\file" : "/dir/subdir/file", uri.LocalPath, "LocalPath"); + Assert.AreEqual ("/dir/subdir/file", uri.PathAndQuery, "PathAndQuery"); + Assert.AreEqual (String.Empty, uri.Query, "Query"); + Assert.AreEqual ("file", uri.Segments [3], "Segments [3]"); + + Assert.AreEqual ("localhost", uri.Authority, "Authority"); + Assert.AreEqual ("localhost", uri.DnsSafeHost, "DnsSafeHost"); + Assert.AreEqual (String.Empty, uri.Fragment, "Fragment"); + Assert.AreEqual ("localhost", uri.Host, "Host"); + Assert.AreEqual (UriHostNameType.Dns, uri.HostNameType, "HostNameType"); + Assert.IsTrue (uri.IsAbsoluteUri, "IsAbsoluteUri"); + Assert.IsTrue (uri.IsDefaultPort, "IsDefaultPort"); + Assert.IsTrue (uri.IsFile, "IsFile"); + Assert.IsTrue (uri.IsLoopback, "IsLoopback"); + Assert.AreEqual (isWin32, uri.IsUnc, "IsUnc"); + Assert.AreEqual ("file://localhost/dir/subdir/file", uri.OriginalString, "OriginalString"); + Assert.AreEqual (-1, uri.Port, "Port"); + Assert.AreEqual ("file", uri.Scheme, "Scheme"); + Assert.AreEqual ("/", uri.Segments [0], "Segments [0]"); + Assert.AreEqual ("dir/", uri.Segments [1], "Segments [1]"); + Assert.AreEqual ("subdir/", uri.Segments [2], "Segments [2]"); + Assert.IsFalse (uri.UserEscaped, "UserEscaped"); + Assert.AreEqual (String.Empty, uri.UserInfo, "UserInfo"); + } + [Test] public void PathReduction_2e () { From ede4f3a8c6383d91e4072d38589774666ee7cd0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Fri, 24 Oct 2014 00:11:03 +0200 Subject: [PATCH 457/543] [MWF] Use overload of Marshal.PtrToStringUni that reads up until the first null instead of explicitly specifying length This fixes the two tests broken by 0ac61b03fcd9baf75739d3c567b36647bde08025 --- .../Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs index 1f3af258464..657a42457c9 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs @@ -1296,7 +1296,7 @@ void TranslatePropertyToClipboard(IntPtr property) { buffer [i] = Marshal.ReadByte (prop, i); Clipboard.Item = Encoding.UTF8.GetString (buffer); } else if (property == UTF16_STRING) { - Clipboard.Item = Marshal.PtrToStringUni (prop, Encoding.Unicode.GetMaxCharCount ((int)nitems)); + Clipboard.Item = Marshal.PtrToStringUni (prop); } else if (property == RICHTEXTFORMAT) Clipboard.Item = Marshal.PtrToStringAnsi(prop); else if (DataFormats.ContainsFormat (property.ToInt32 ())) { From 3d9a2b7175525f8451476f4b6d63c88c2cd4a197 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Fri, 24 Oct 2014 07:14:58 +0800 Subject: [PATCH 458/543] [relaxng] fix default namespace handling in compact syntax. Also had to disable RNC tests that depended on vanished web resource... --- .../Commons.Xml.Relaxng.Rnc/RncParser.jay | 2 +- mcs/class/Commons.Xml.Relaxng/Test/RncTests.cs | 14 ++++++++++++++ .../Test/standalone_tests/Makefile | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng.Rnc/RncParser.jay b/mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng.Rnc/RncParser.jay index df3157f022a..625df5ca152 100644 --- a/mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng.Rnc/RncParser.jay +++ b/mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng.Rnc/RncParser.jay @@ -107,7 +107,7 @@ namespace Commons.Xml.Relaxng.Rnc public RelaxngPattern Parse (TextReader source, string baseUri, string defaultNamespace) { - this.defaultNamespace = defaultNamespace; + this.defaultNamespace = defaultNamespace ?? string.Empty; if (defaultNamespace != null && defaultNamespace.Length != 0) nsmgr.AddNamespace (String.Empty, defaultNamespace); try { diff --git a/mcs/class/Commons.Xml.Relaxng/Test/RncTests.cs b/mcs/class/Commons.Xml.Relaxng/Test/RncTests.cs index d25fcb1e1c7..fb7ac65e9c7 100644 --- a/mcs/class/Commons.Xml.Relaxng/Test/RncTests.cs +++ b/mcs/class/Commons.Xml.Relaxng/Test/RncTests.cs @@ -95,5 +95,19 @@ public void InheritDefaultNamespace () r.Close (); } } + + [Test] + public void SimpleDefaultNamespace () + { + var g = RncParser.ParseRnc (new StringReader ("element e { empty }")); + var x = XmlReader.Create (new StringReader ("")); + var r = new RelaxngValidatingReader (x, g); + try { + while (!r.EOF) + r.Read (); + } finally { + r.Close (); + } + } } } diff --git a/mcs/class/Commons.Xml.Relaxng/Test/standalone_tests/Makefile b/mcs/class/Commons.Xml.Relaxng/Test/standalone_tests/Makefile index 6653702d556..9be0e7ff400 100644 --- a/mcs/class/Commons.Xml.Relaxng/Test/standalone_tests/Makefile +++ b/mcs/class/Commons.Xml.Relaxng/Test/standalone_tests/Makefile @@ -8,7 +8,7 @@ TEST_ARCHIVE = testSuite.zip RNCTESTS = test/RNCTest.xml RNCTEST_ARCHIVE = anglia-test-suite.zip -all : relaxngtest.exe anglia-test-runner.exe +all : relaxngtest.exe #anglia-test-runner.exe relaxngtest.exe : relaxngtest.cs $(TESTS) $(MCS_RUNTIME) $(MCS) -debug+ relaxngtest.cs -r:Commons.Xml.Relaxng.dll From e6b335e7f7b6d2a9038b603eacb9757ad14db330 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 23 Oct 2014 23:01:22 -0400 Subject: [PATCH 459/543] [runtime] Remove build system support for the interpreter. --- configure.ac | 37 +------------------------------------ data/Makefile.am | 4 ---- mono/dis/Makefile.am | 4 ---- mono/mini/Makefile.am.in | 10 +--------- mono/monograph/Makefile.am | 4 ---- mono/profiler/Makefile.am | 2 -- scripts/Makefile.am | 4 ---- 7 files changed, 2 insertions(+), 63 deletions(-) diff --git a/configure.ac b/configure.ac index 66d9a98c359..7e8f26199ad 100644 --- a/configure.ac +++ b/configure.ac @@ -2505,7 +2505,6 @@ AM_CONDITIONAL(LOADED_LLVM, [test x$enable_loadedllvm = xyes]) TARGET="unknown" ACCESS_UNALIGNED="yes" -JIT_SUPPORTED=no LIBC="libc.so.6" INTL="libc.so.6" SQLITE="libsqlite.so.0" @@ -2526,7 +2525,6 @@ case "$host" in arch_target=mips; sgen_supported=true ACCESS_UNALIGNED="no" - JIT_SUPPORTED=yes AC_MSG_CHECKING(for mips n32) AC_TRY_COMPILE([],[ @@ -2544,7 +2542,6 @@ case "$host" in i*86-*-*) TARGET=X86; arch_target=x86; - JIT_SUPPORTED=yes case $host_os in solaris*) LIBC="libc.so" @@ -2590,7 +2587,6 @@ case "$host" in x86_64-*-* | amd64-*-*) TARGET=AMD64; arch_target=amd64; - JIT_SUPPORTED=yes if test "x$ac_cv_sizeof_void_p" = "x4"; then AC_DEFINE(__mono_ilp32__, 1, [64 bit mode with 4 byte longs and pointers]) sizeof_register=8 @@ -2622,7 +2618,6 @@ case "$host" in TARGET=IA64 arch_target=ia64 ACCESS_UNALIGNED="no" - JIT_SUPPORTED=yes LIBC="libc.so.6.1" INTL="libc.so.6.1" AC_CHECK_LIB(unwind, _U_dyn_register, [], [AC_MSG_ERROR(library libunwind not found)]) @@ -2635,7 +2630,6 @@ case "$host" in TARGET=SPARC fi arch_target=sparc; - JIT_SUPPORTED=yes ACCESS_UNALIGNED="no" case $host_os in linux*) ;; @@ -2668,7 +2662,6 @@ case "$host" in CPPFLAGS="$CPPFLAGS -D__mono_ppc__" fi arch_target=ppc; - JIT_SUPPORTED=yes case $host_os in linux*|darwin*) sgen_supported=true @@ -2679,7 +2672,6 @@ case "$host" in TARGET=ARM; arch_target=arm; ACCESS_UNALIGNED="no" - JIT_SUPPORTED=yes CPPFLAGS="$CPPFLAGS -D__ARM_EABI__" sgen_supported=true ;; @@ -2687,7 +2679,6 @@ case "$host" in TARGET=ARM; arch_target=arm; ACCESS_UNALIGNED="no" - JIT_SUPPORTED=yes sgen_supported=true AOT_SUPPORTED="yes" CPPFLAGS="$CPPFLAGS -D__ARM_EABI__" @@ -2697,7 +2688,6 @@ case "$host" in # TARGET=ARM; # arch_target=arm; # ACCESS_UNALIGNED="no" -# JIT_SUPPORTED=yes # sgen_supported=true # AOT_SUPPORTED="no" # ;; @@ -2705,7 +2695,6 @@ case "$host" in # https://lkml.org/lkml/2012/7/15/133 TARGET=ARM64 arch_target=arm64 - JIT_SUPPORTED=yes sgen_supported=true boehm_supported=false ;; @@ -2713,7 +2702,6 @@ case "$host" in TARGET=S390X; arch_target=s390x; ACCESS_UNALIGNED="yes" - JIT_SUPPORTED=yes sgen_supported=true CFLAGS="$CFLAGS -mbackchain -D__USE_STRING_INLINES" ;; @@ -2729,9 +2717,7 @@ if test "x$host" != "x$target"; then TARGET=ARM; arch_target=arm; ACCESS_UNALIGNED="no" - JIT_SUPPORTED=yes CPPFLAGS="$CPPFLAGS -D__ARM_EABI__" - jit_wanted=true # Can't use tls, since it depends on the runtime detection of tls offsets # in mono-compiler.h with_tls=pthread @@ -2769,7 +2755,6 @@ if test "x$host" != "x$target"; then # arch_target=arm # AC_DEFINE(TARGET_ARM, 1, [...]) # ACCESS_UNALIGNED="no" -# JIT_SUPPORTED=yes # sizeof_register=4 # CPPFLAGS="$CPPFLAGS \ # -D__ARM_EABI__ \ @@ -2779,7 +2764,6 @@ if test "x$host" != "x$target"; then # -DDISABLE_SOCKETS \ # -DDISABLE_ATTACH \ # -DUSE_NEWLIB" -# jit_wanted=true # Can't use tls, since it depends on the runtime detection of tls offsets # in mono-compiler.h # with_tls=pthread @@ -2796,9 +2780,7 @@ if test "x$host" != "x$target"; then AC_DEFINE(TARGET_ARM, 1, [...]) AC_DEFINE(TARGET_ANDROID, 1, [...]) ACCESS_UNALIGNED="no" - JIT_SUPPORTED=yes CPPFLAGS="$CPPFLAGS -D__ARM_EABI__" - jit_wanted=true # Can't use tls, since it depends on the runtime detection of tls offsets # in mono-compiler.h with_tls=pthread @@ -2818,9 +2800,7 @@ if test "x$host" != "x$target"; then arch_target=x86; AC_DEFINE(TARGET_X86, 1, [...]) AC_DEFINE(TARGET_ANDROID, 1, [...]) - JIT_SUPPORTED=yes CPPFLAGS="$CPPFLAGS" - jit_wanted=true sgen_supported=true # Can't use tls, since it depends on the runtime detection of tls offsets # in mono-compiler.h @@ -2829,8 +2809,6 @@ if test "x$host" != "x$target"; then ;; aarch64-*) TARGET=ARM64 - JIT_SUPPORTED=yes - jit_wanted=true ;; *) AC_MSG_ERROR([Cross compiling is not supported for target $target]) @@ -2953,19 +2931,7 @@ fi AC_SUBST(SGEN_DEFINES) AM_CONDITIONAL(SUPPORT_SGEN, test x$buildsgen = xyes) -USEJIT=false -if test x$JIT_SUPPORTED = xyes; then - if $jit_wanted; then - USEJIT=true - jit_status="Building and using the JIT" - else - AC_ERROR(No JIT support available or selected.) - fi -else - AC_ERROR(No JIT support available or selected.) -fi - -AM_CONDITIONAL(USE_JIT, test x$USEJIT = xtrue) +jit_status="Building and using the JIT" libsuffix=".so" @@ -3368,7 +3334,6 @@ AM_CONDITIONAL(HOST_ARM, test x$HOST = xARM) AM_CONDITIONAL(HOST_ARM64, test x$HOST = xARM64) AM_CONDITIONAL(CROSS_COMPILE, test "x$host" != "x$target") -AM_CONDITIONAL(JIT_SUPPORTED, test x$JIT_SUPPORTED = xyes) AM_CONDITIONAL(INCLUDED_LIBGC, test x$libgc = xincluded) AC_SUBST(LIBC) diff --git a/data/Makefile.am b/data/Makefile.am index 32a13623cb9..daf6f38a79b 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -26,12 +26,8 @@ else SGENPCFILE= endif -if JIT_SUPPORTED pkgconfig_DATA= mono.pc mono-2.pc dotnet.pc dotnet35.pc wcf.pc mono-nunit.pc mono-cairo.pc mono-options.pc cecil.pc monodoc.pc mono-lineeditor.pc system.web.extensions_1.0.pc \ system.web.extensions.design_1.0.pc system.web.mvc.pc system.web.mvc2.pc system.web.mvc3.pc aspnetwebstack.pc reactive.pc xbuild12.pc $(SGENPCFILE) -else -pkgconfig_DATA= mint.pc mono-nunit.pc mono-cairo.pc mono-options.pc cecil.pc monodoc.pc mono-lineeditor.pc -endif DISTCLEANFILES= mono-2.pc mono.pc mint.pc dotnet.pc dotnet35.pc wcf.pc mono-nunit.pc mono-cairo.pc mono-options.pc cecil.pc monodoc.pc mono-lineeditor.pc system.web.extensions_1.0.pc \ system.web.extensions.design_1.0.pc system.web.mvc.pc system.web.mvc2.pc system.web.mvc3.pc aspnetwebstack.pc reactive.pc $(SGENPCFILE) mono-sgen-gdb.py diff --git a/mono/dis/Makefile.am b/mono/dis/Makefile.am index fd581ff5514..0a6e86d0c0c 100644 --- a/mono/dis/Makefile.am +++ b/mono/dis/Makefile.am @@ -4,7 +4,6 @@ if HOST_WIN32 export HOST_CC endif -if JIT_SUPPORTED if !SHARED_MONO static_libs= \ $(top_builddir)/mono/metadata/libmonoruntime-static.la \ @@ -17,9 +16,6 @@ runtime_lib=../mini/$(LIBMONO_LA) $(static_libs) else runtime_lib=../mini/$(LIBMONO_LA) endif -else -runtime_lib=../interpreter/libmint.la -endif if DISABLE_EXECUTABLES bin_PROGRAMS = diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index 104294b401a..b4c85e1a4d3 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -83,8 +83,6 @@ libmonoldflags=$(monoldflags) -version-info 1:0:0 endif endif -if JIT_SUPPORTED - if SUPPORT_SGEN sgen_binaries = mono-sgen sgen_libraries = libmonosgen-2.0.la @@ -166,8 +164,6 @@ libmono_llvm_la_LIBADD += $(top_builddir)/mono/mini/libmonoboehm-$(API_VER).la $ endif endif -endif - mono_boehm_SOURCES = \ main.c @@ -196,7 +192,7 @@ endif @echo "const char *build_date = \"`date`\";" > buildver-boehm.h mono_boehm-main.$(OBJEXT): buildver-boehm.h main.c: buildver-boehm.h - + endif if DISABLE_EXECUTABLES @@ -730,11 +726,7 @@ clean-local: pkgconfigdir = $(libdir)/pkgconfig -if JIT_SUPPORTED BUILT_SOURCES = version.h $(arch_built) -else -BUILT_SOURCES = version.h -endif CLEANFILES= $(BUILT_SOURCES) *.exe *.dll EXTRA_DIST = TestDriver.cs ldscript ldscript.mono \ diff --git a/mono/monograph/Makefile.am b/mono/monograph/Makefile.am index 585b5641829..25555809f1d 100644 --- a/mono/monograph/Makefile.am +++ b/mono/monograph/Makefile.am @@ -3,7 +3,6 @@ if HOST_WIN32 export HOST_CC endif -if JIT_SUPPORTED if DISABLE_EXECUTABLES runtime_lib=../mini/$(LIBMONO_LA) $(static_libs) else @@ -20,9 +19,6 @@ else runtime_lib=../mini/$(LIBMONO_LA) endif endif -else -runtime_lib=../interpreter/libmint.la -endif if DISABLE_EXECUTABLES bin_PROGRAMS = diff --git a/mono/profiler/Makefile.am b/mono/profiler/Makefile.am index 25bb9b51f70..b0d1e2f77de 100644 --- a/mono/profiler/Makefile.am +++ b/mono/profiler/Makefile.am @@ -11,7 +11,6 @@ AM_CPPFLAGS = \ if !DISABLE_LIBRARIES if !DISABLE_PROFILER -if JIT_SUPPORTED bin_PROGRAMS = mprof-report lib_LTLIBRARIES = libmono-profiler-cov.la libmono-profiler-aot.la libmono-profiler-iomap.la libmono-profiler-log.la if PLATFORM_DARWIN @@ -22,7 +21,6 @@ libmono_profiler_log_la_LDFLAGS = -avoid-version endif endif endif -endif if HAVE_OPROFILE # Do something that uses OPROFILE_CFLAGS and OPROFILE_LIBS diff --git a/scripts/Makefile.am b/scripts/Makefile.am index ac0e3a9a957..be62dd633ef 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -165,11 +165,7 @@ EXTRA_DIST = \ get-cygwin-deps.sh \ mono-configuration-crypto.in -if USE_JIT mono_interp = mono -else -mono_interp = mint -endif if HOST_WIN32 if CROSS_COMPILING From 976be3404577572decbb362b9878f94f736b3ef6 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Fri, 24 Oct 2014 12:20:09 +0800 Subject: [PATCH 460/543] [xml] XmlTextReader: Value was wrong after ReadAttributeValue() on xml declaration. --- .../System.XML/System.Xml/XmlTextReader.cs | 2 +- .../Test/System.Xml/XmlTextReaderTests.cs | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/mcs/class/System.XML/System.Xml/XmlTextReader.cs b/mcs/class/System.XML/System.Xml/XmlTextReader.cs index 7dc686ba352..eee0580d44d 100644 --- a/mcs/class/System.XML/System.Xml/XmlTextReader.cs +++ b/mcs/class/System.XML/System.Xml/XmlTextReader.cs @@ -716,7 +716,6 @@ public virtual string Value { if (valueCache != null) return valueCache; if (ValueBufferStart >= 0) { -//Console.WriteLine (NodeType + " / " + ValueBuffer.Length + " / " + ValueBufferStart + " / " + ValueBufferEnd); valueCache = Reader.valueBuffer.ToString (ValueBufferStart, ValueBufferEnd - ValueBufferStart); return valueCache; } @@ -1800,6 +1799,7 @@ private void AddAttributeWithValue (string name, string value) value, false); ati.Value = value; + ati.ValueTokenStartIndex = ati.ValueTokenEndIndex = currentAttributeValue; attributeCount++; } diff --git a/mcs/class/System.XML/Test/System.Xml/XmlTextReaderTests.cs b/mcs/class/System.XML/Test/System.Xml/XmlTextReaderTests.cs index 7ecd83780ae..d0898923255 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlTextReaderTests.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlTextReaderTests.cs @@ -1382,5 +1382,56 @@ public void BOMLessUTF16Detection () // bug #674580 var xtr = new XmlTextReader (ms); xtr.Read (); } + + [Test] + public void XmlDeclarationReadAttributeValue () + { + const string input = ""; + var reader = new XmlTextReader (new StringReader (input)); + reader.WhitespaceHandling = WhitespaceHandling.All; + reader.Read (); + + Assert.AreEqual ("1.0", reader.GetAttribute ("version"), "#0"); + Assert.AreEqual ("utf-8", reader.GetAttribute ("encoding"), "#0-2"); + + Assert.IsTrue (reader.MoveToNextAttribute (), "#1"); + Assert.AreEqual ("1.0", reader.Value, "#1-1"); + Assert.IsTrue (reader.ReadAttributeValue (), "#2"); + Assert.AreEqual ("1.0", reader.Value, "#3"); + Assert.IsFalse (reader.ReadAttributeValue (), "#4"); + + Assert.IsTrue (reader.MoveToNextAttribute (), "#5"); + Assert.AreEqual ("utf-8", reader.Value, "#5-1"); + Assert.IsTrue (reader.ReadAttributeValue (), "#6"); + Assert.AreEqual ("utf-8", reader.Value, "#7"); + Assert.IsFalse (reader.ReadAttributeValue (), "#8"); + + Assert.IsFalse (reader.MoveToNextAttribute (), "#9"); + Assert.IsFalse (reader.ReadAttributeValue (), "#10"); + } + + [Test] + public void XmlDeclarationReadAttributeValue2 () + { + const string input = ""; + var reader = new XmlTextReader (new StringReader (input)); + reader.WhitespaceHandling = WhitespaceHandling.All; + reader.Read (); + Assert.IsTrue (reader.MoveToNextAttribute (), "#1a"); + Assert.IsTrue (reader.ReadAttributeValue (), "#1b"); + Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#1c"); + Assert.AreEqual ("1.0", reader.Value, "#1d"); + Assert.IsFalse (reader.ReadAttributeValue(), "#1e"); + + Assert.IsTrue (reader.MoveToNextAttribute(), "#2a"); + Assert.IsTrue (reader.ReadAttributeValue(), "#2b"); + Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#2c"); + Assert.AreEqual ("utf-8", reader.Value, "#2d"); + Assert.IsFalse (reader.ReadAttributeValue(), "#2e"); + + Assert.IsFalse (reader.MoveToNextAttribute(), "#3"); + Assert.IsFalse (reader.ReadAttributeValue(), "#4"); + Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#5"); + } } } From 8630afbd9bf9d5ba5183adf10eaf3adb098444e5 Mon Sep 17 00:00:00 2001 From: Etienne CHAMPETIER Date: Thu, 23 Oct 2014 17:44:36 +0200 Subject: [PATCH 461/543] HttpApplication: set StatusCode = 500 when we send an exception to the client Signed-off-by: Etienne CHAMPETIER --- mcs/class/System.Web/System.Web/HttpApplication.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/mcs/class/System.Web/System.Web/HttpApplication.cs b/mcs/class/System.Web/System.Web/HttpApplication.cs index efa4432011a..4d7ce11e283 100644 --- a/mcs/class/System.Web/System.Web/HttpApplication.cs +++ b/mcs/class/System.Web/System.Web/HttpApplication.cs @@ -1549,6 +1549,7 @@ void Start (object x) if (initialization_exception != null) { Exception e = initialization_exception; HttpException exc = HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort); + context.Response.StatusCode = 500; FinalErrorWrite (context.Response, exc.GetHtmlErrorMessage ()); PipelineDone (); return; From 3fd35417049e27eef6d7a8f38fed7f48c85ba22f Mon Sep 17 00:00:00 2001 From: Etienne CHAMPETIER Date: Fri, 24 Oct 2014 09:35:12 +0200 Subject: [PATCH 462/543] WebConfigurationManager: protect GetSection all public static should be thread-safe Signed-off-by: Etienne CHAMPETIER --- .../System.Web.Configuration_2.0/WebConfigurationManager.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/WebConfigurationManager.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/WebConfigurationManager.cs index 14bcf13a6e0..39190d234e1 100644 --- a/mcs/class/System.Web/System.Web.Configuration_2.0/WebConfigurationManager.cs +++ b/mcs/class/System.Web/System.Web.Configuration_2.0/WebConfigurationManager.cs @@ -67,6 +67,7 @@ public ConfigPath (string path, bool inAnotherApp) static readonly char[] pathTrimChars = { '/' }; static readonly object suppressAppReloadLock = new object (); static readonly object saveLocationsCacheLock = new object (); + static readonly object getSectionLock = new object (); // See comment for the cacheLock field at top of System.Web.Caching/Cache.cs static readonly ReaderWriterLockSlim sectionCacheLock; @@ -517,7 +518,10 @@ internal static object GetSection (string sectionName, string path, HttpContext cachePath = path; } - ConfigurationSection section = c.GetSection (sectionName); + ConfigurationSection section; + lock (getSectionLock) { + section = c.GetSection (sectionName); + } if (section == null) return null; From 9b7b75d7ec5ecc1f7b18e8d4711b411ed3128b25 Mon Sep 17 00:00:00 2001 From: Etienne CHAMPETIER Date: Fri, 24 Oct 2014 12:45:01 +0200 Subject: [PATCH 463/543] WebConfigurationManager: simplify call to ConfigurationSection.GetRuntimeObject () this call come from an obfuscation contest :) ? Signed-off-by: Etienne CHAMPETIER --- .../System.Web.Configuration_2.0/WebConfigurationManager.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/WebConfigurationManager.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/WebConfigurationManager.cs index 39190d234e1..75fd8723e70 100644 --- a/mcs/class/System.Web/System.Web.Configuration_2.0/WebConfigurationManager.cs +++ b/mcs/class/System.Web/System.Web.Configuration_2.0/WebConfigurationManager.cs @@ -533,7 +533,7 @@ internal static object GetSection (string sectionName, string path, HttpContext value = collection; } #else - object value = SettingsMappingManager.MapSection (get_runtime_object.Invoke (section, new object [0])); + object value = SettingsMappingManager.MapSection (section.GetRuntimeObject ()); #endif if (cachePath != null) cacheKey = baseCacheKey ^ cachePath.GetHashCode (); @@ -681,7 +681,9 @@ internal static void RemoveConfigurationFromCache (HttpContext ctx) configurations.Remove (GetCurrentPath (ctx)); } +#if TARGET_J2EE readonly static MethodInfo get_runtime_object = typeof (ConfigurationSection).GetMethod ("GetRuntimeObject", BindingFlags.NonPublic | BindingFlags.Instance); +#endif public static object GetWebApplicationSection (string sectionName) { From c46234bf0c8be5d68d4ead17a0eea630ea2693c4 Mon Sep 17 00:00:00 2001 From: Etienne CHAMPETIER Date: Fri, 24 Oct 2014 13:39:35 +0200 Subject: [PATCH 464/543] HttpApplication: if there is an exception in InitOnce, output it on the Console Signed-off-by: Etienne CHAMPETIER --- mcs/class/System.Web/System.Web/HttpApplication.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mcs/class/System.Web/System.Web/HttpApplication.cs b/mcs/class/System.Web/System.Web/HttpApplication.cs index 4d7ce11e283..da393081d5e 100644 --- a/mcs/class/System.Web/System.Web/HttpApplication.cs +++ b/mcs/class/System.Web/System.Web/HttpApplication.cs @@ -230,6 +230,10 @@ internal void InitOnce (bool full_init) } } catch (Exception e) { initialization_exception = e; + Console.Error.WriteLine("Exception while initOnce: "+e.ToString()); + // Once initialization_exception != null, we always respond with this exception + // You have to restart the HttpApplication to "unlock" it + Console.Error.WriteLine("Please restart your app to unlock it"); } finally { if (mustNullContext) context = null; From f7fd52ad18464ad9c40516c2c59b406c1b12e8c9 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Fri, 24 Oct 2014 15:41:20 -0400 Subject: [PATCH 465/543] [mscorlib/Android] TimeZoneInfo.Local.Id should be "Local". On Mono/.NET, TimeZoneInfo.Local has a TimeZoneInfo.Id value of "Local" and a TimeZoneInfo.DisplayName value of "Local": $ csharp csharp> TimeZoneInfo.Local.Id; "Local" csharp> TimeZoneInfo.Local.DisplayName; "Local" That isn't the case on Xamarin.Android, which returns the timezoneinfo ID value from both DisplayName and Id, e.g. TimeZoneInfo.Local could have Id and DisplayName values of "Australia/Sydney". Rework things so that the TimeZoneInfo.Id and TimeZoneInfo.DisplayName properties return "Local" on Xamarin.Android for the instance returned from TimeZoneInfo.Local, just like normal Mono/.NET does. --- .../System/TimeZoneInfo.Android.cs | 26 +++++++++---------- mcs/class/System.Core/System/TimeZoneInfo.cs | 6 ++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.Android.cs b/mcs/class/System.Core/System/TimeZoneInfo.Android.cs index bd35e657343..079af3722d6 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.Android.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.Android.cs @@ -453,29 +453,29 @@ internal static IEnumerable GetAvailableIds () : db.GetAvailableIds (); } - static TimeZoneInfo _GetTimeZone (string name) + static TimeZoneInfo _GetTimeZone (string id, string name) { if (db == null) return null; byte[] buffer = db.GetTimeZoneData (name); if (buffer == null) return null; - return TimeZoneInfo.ParseTZBuffer (name, buffer, buffer.Length); + return TimeZoneInfo.ParseTZBuffer (id, buffer, buffer.Length); } - internal static TimeZoneInfo GetTimeZone (string id) + internal static TimeZoneInfo GetTimeZone (string id, string name) { - if (id != null) { - if (id == "GMT" || id == "UTC") - return new TimeZoneInfo (id, TimeSpan.FromSeconds (0), id, id, id, null, true); - if (id.StartsWith ("GMT")) + if (name != null) { + if (name == "GMT" || name == "UTC") + return new TimeZoneInfo (id, TimeSpan.FromSeconds (0), id, name, name, null, disableDaylightSavingTime:true); + if (name.StartsWith ("GMT")) return new TimeZoneInfo (id, - TimeSpan.FromSeconds (ParseNumericZone (id)), - id, id, id, null, true); + TimeSpan.FromSeconds (ParseNumericZone (name)), + id, name, name, null, disableDaylightSavingTime:true); } try { - return _GetTimeZone (id); + return _GetTimeZone (id, name); } catch (Exception) { return null; } @@ -533,12 +533,12 @@ static int ParseNumericZone (string name) static readonly object _lock = new object (); static TimeZoneInfo defaultZone; - internal static TimeZoneInfo Default { + internal static TimeZoneInfo Local { get { lock (_lock) { if (defaultZone != null) return defaultZone; - return defaultZone = GetTimeZone (GetDefaultTimeZoneName ()); + return defaultZone = GetTimeZone ("Local", GetDefaultTimeZoneName ()); } } } @@ -617,7 +617,7 @@ static void Main (string[] args) foreach (var id in GetAvailableIds ()) { Console.Write ("name={0,-40}", id); try { - TimeZoneInfo zone = _GetTimeZone (id); + TimeZoneInfo zone = _GetTimeZone (id, id); if (zone != null) { Console.Write (" {0,-40}", zone); if (offset.HasValue) { diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index aead18c764f..9994b125c79 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -103,7 +103,7 @@ public static TimeZoneInfo Local { static TimeZoneInfo CreateLocal () { #if MONODROID - return AndroidTimeZones.Default; + return AndroidTimeZones.Local; #elif MONOTOUCH using (Stream stream = GetMonoTouchData (null)) { return BuildFromStream ("Local", stream); @@ -415,7 +415,7 @@ public static TimeZoneInfo FindSystemTimeZoneById (string id) } #endif #if MONODROID - var timeZoneInfo = AndroidTimeZones.GetTimeZone (id); + var timeZoneInfo = AndroidTimeZones.GetTimeZone (id, id); if (timeZoneInfo == null) throw new TimeZoneNotFoundException (); return timeZoneInfo; @@ -644,7 +644,7 @@ public static ReadOnlyCollection GetSystemTimeZones () #endif #if MONODROID foreach (string id in AndroidTimeZones.GetAvailableIds ()) { - var tz = AndroidTimeZones.GetTimeZone (id); + var tz = AndroidTimeZones.GetTimeZone (id, id); if (tz != null) systemTimeZones.Add (tz); } From ab361102dbc30326eacbe52ecdcea16476f94488 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 16 Oct 2014 12:24:41 +0200 Subject: [PATCH 466/543] [MWF] Display visual feedback on pressed button (#23869) When a button is pressed the image and the text needs to be rendered one pixel to the right and to the bottom so that there is some visual feedback of the button press. Previously this was only the case if TextImageRelation was set to Overlay. --- .../System.Windows.Forms/ThemeWin32Classic.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs index 29921942b4e..2804060aeb8 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs @@ -379,12 +379,12 @@ public override void CalculateButtonTextAndImageLayout (Graphics g, ButtonBase b case TextImageRelation.Overlay: // Overlay is easy, text always goes here - if (button.Pressed) - textRectangle.Offset (1, 1); - // Image is dependent on ImageAlign - if (image == null) + if (image == null) { + if (button.Pressed) + textRectangle.Offset (1, 1); return; + } int image_x = 0; int image_y = 0; @@ -449,6 +449,8 @@ public override void CalculateButtonTextAndImageLayout (Graphics g, ButtonBase b LayoutTextBeforeOrAfterImage (textRectangle, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); break; } + if (button.Pressed) + textRectangle.Offset (1, 1); } private void LayoutTextBeforeOrAfterImage (Rectangle totalArea, bool textFirst, Size textSize, Size imageSize, System.Drawing.ContentAlignment textAlign, System.Drawing.ContentAlignment imageAlign, out Rectangle textRect, out Rectangle imageRect) From 5d869be79424a314362c331ec125a3d61378f176 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 16 Oct 2014 14:03:04 +0200 Subject: [PATCH 467/543] [MWF] Improve ellipsis handling - Don't subtract room for ellipsis. Ellipsis should be handled by the renderer so we shouldn't reserve space for it. Otherwise we end up not getting ellipsis (because the renderer thinks there is enough space available), or we don't use up the available space. - Don't allow text to go below button if we want to show ellipsis. --- .../System.Windows.Forms/TextRenderer.cs | 3 --- .../System.Windows.Forms/ThemeWin32Classic.cs | 22 +++++++++++++------ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextRenderer.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextRenderer.cs index bda5da96f78..b82629a0483 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextRenderer.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextRenderer.cs @@ -492,9 +492,6 @@ private static Rectangle PadDrawStringRectangle (Rectangle r, TextFormatFlags fl r.X += 2; r.Width -= 2; } - if ((flags & TextFormatFlags.WordEllipsis) == TextFormatFlags.WordEllipsis || (flags & TextFormatFlags.EndEllipsis) == TextFormatFlags.EndEllipsis || (flags & TextFormatFlags.WordBreak) == TextFormatFlags.WordBreak) { - r.Width -= 4; - } if ((flags & TextFormatFlags.VerticalCenter) == TextFormatFlags.VerticalCenter && XplatUI.RunningOnUnix) { r.Y -= 1; } diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs index 2804060aeb8..d6214c5e93b 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs @@ -375,14 +375,16 @@ public override void CalculateButtonTextAndImageLayout (Graphics g, ButtonBase b textRectangle = Rectangle.Inflate (content_rect, -4, -4); imageRectangle = Rectangle.Empty; + bool displayEllipsis = (button.TextFormatFlags & (TextFormatFlags.EndEllipsis | TextFormatFlags.PathEllipsis | TextFormatFlags.WordEllipsis)) != 0; + switch (button.TextImageRelation) { case TextImageRelation.Overlay: // Overlay is easy, text always goes here // Image is dependent on ImageAlign if (image == null) { - if (button.Pressed) - textRectangle.Offset (1, 1); + if (button.Pressed) + textRectangle.Offset (1, 1); return; } @@ -437,10 +439,10 @@ public override void CalculateButtonTextAndImageLayout (Graphics g, ButtonBase b imageRectangle = new Rectangle (image_x, image_y, image_width, image_height); break; case TextImageRelation.ImageAboveText: - LayoutTextAboveOrBelowImage (textRectangle, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); + LayoutTextAboveOrBelowImage (textRectangle, false, text_size, image_size, button.TextAlign, button.ImageAlign, displayEllipsis, out textRectangle, out imageRectangle); break; case TextImageRelation.TextAboveImage: - LayoutTextAboveOrBelowImage (textRectangle, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); + LayoutTextAboveOrBelowImage (textRectangle, true, text_size, image_size, button.TextAlign, button.ImageAlign, displayEllipsis, out textRectangle, out imageRectangle); break; case TextImageRelation.ImageBeforeText: LayoutTextBeforeOrAfterImage (textRectangle, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); @@ -498,7 +500,7 @@ private void LayoutTextBeforeOrAfterImage (Rectangle totalArea, bool textFirst, imageRect = final_image_rect; } - private void LayoutTextAboveOrBelowImage (Rectangle totalArea, bool textFirst, Size textSize, Size imageSize, System.Drawing.ContentAlignment textAlign, System.Drawing.ContentAlignment imageAlign, out Rectangle textRect, out Rectangle imageRect) + private void LayoutTextAboveOrBelowImage (Rectangle totalArea, bool textFirst, Size textSize, Size imageSize, System.Drawing.ContentAlignment textAlign, System.Drawing.ContentAlignment imageAlign, bool displayEllipsis, out Rectangle textRect, out Rectangle imageRect) { int element_spacing = 0; // Spacing between the Text and the Image int total_height = textSize.Height + element_spacing + imageSize.Height; @@ -547,6 +549,12 @@ private void LayoutTextAboveOrBelowImage (Rectangle totalArea, bool textFirst, S final_text_rect.Y = totalArea.Top; } + if (displayEllipsis) { + // Don't use more space than is available otherwise ellipsis won't show + if (final_text_rect.Height > totalArea.Bottom) + final_text_rect.Height = totalArea.Bottom - final_text_rect.Top; + } + textRect = final_text_rect; imageRect = final_image_rect; } @@ -1094,11 +1102,11 @@ public override void CalculateCheckBoxTextAndImageLayout (ButtonBase button, Poi break; case TextImageRelation.ImageAboveText: content_rect.Inflate (-4, -4); - LayoutTextAboveOrBelowImage (content_rect, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); + LayoutTextAboveOrBelowImage (content_rect, false, text_size, image_size, button.TextAlign, button.ImageAlign, false, out textRectangle, out imageRectangle); break; case TextImageRelation.TextAboveImage: content_rect.Inflate (-4, -4); - LayoutTextAboveOrBelowImage (content_rect, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle); + LayoutTextAboveOrBelowImage (content_rect, true, text_size, image_size, button.TextAlign, button.ImageAlign, false, out textRectangle, out imageRectangle); break; case TextImageRelation.ImageBeforeText: content_rect.Inflate (-4, -4); From dc30595ace1f02ae50879fd9bcb7bdb1e18ebb3d Mon Sep 17 00:00:00 2001 From: Kei Nakazawa Date: Sat, 25 Oct 2014 21:58:29 +0900 Subject: [PATCH 468/543] [System] Added missing ctor to Socket for initializing dual-mode socket - Ref: https://bugzilla.xamarin.com/show_bug.cgi?id=20048 - Mono currently doesn't support 2-args Socket ctor added in .NET 4.5 - Absence of this ctor prevents KestrelHttpServer (web server for ASP.NET vNext: https://github.com/aspnet/KestrelHttpServer ) test code from working - I hesitated to put IPv4 only implementation, but full dual stack (IPv4/v6) support would need bunch of works to be done. So, I pinned supported protocol of new ctor to IPv4. Also, I filed v4/v6 support issue as a MonoTODO entry inside the source code. --- mcs/class/System/System.Net.Sockets/Socket_2_1.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mcs/class/System/System.Net.Sockets/Socket_2_1.cs b/mcs/class/System/System.Net.Sockets/Socket_2_1.cs index b0295bef71b..b44a0611592 100644 --- a/mcs/class/System/System.Net.Sockets/Socket_2_1.cs +++ b/mcs/class/System/System.Net.Sockets/Socket_2_1.cs @@ -952,6 +952,14 @@ public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType p #endif } +#if NET_4_5 + [MonoTODO ("Currently hardcoded to IPv4. Ideally, support v4/v6 dual-stack.")] + public Socket (SocketType socketType, ProtocolType protocolType) + : this (AddressFamily.InterNetwork, socketType, protocolType) + { + } +#endif + ~Socket () { Dispose (false); From f1108aabbadd839ca9f09ede072919aae63d7df1 Mon Sep 17 00:00:00 2001 From: Stone Gislason Date: Sat, 11 Oct 2014 19:24:16 +0100 Subject: [PATCH 469/543] [eval] Fix delegate; add caching for PrepareEmit The delegate class did not use the internal cache flag as other type definitions which caused the next evaluation to fail. --- mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs | 8 ++++++++ mcs/mcs/delegate.cs | 3 +++ 2 files changed, 11 insertions(+) diff --git a/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs b/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs index 970aa33443d..c124ad3739f 100644 --- a/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs +++ b/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs @@ -104,7 +104,15 @@ public void NestedType () { Evaluator.Run ("class A { class B { } }"); Evaluator.Run ("var x = new A ();"); + } + [Test] + public void DelegateType () + { + Evaluator.Run ("public delegate int D();"); + Evaluator.Run ("D d = delegate () { return 7; };"); + object res = Evaluator.Evaluate ("d();"); + Assert.AreEqual (7, res); } } } \ No newline at end of file diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs index 0dd759823f1..b50e65e0077 100644 --- a/mcs/mcs/delegate.cs +++ b/mcs/mcs/delegate.cs @@ -294,6 +294,9 @@ void DefineAsyncMethods (TypeExpression returnType) public override void PrepareEmit () { + if ((caching_flags & Flags.CloseTypeCreated) != 0) + return; + if (!Parameters.IsEmpty) { parameters.ResolveDefaultValues (this); } From d663c9f65cae23c4a68111316c4824bf46398d05 Mon Sep 17 00:00:00 2001 From: Alex J Lennon Date: Sun, 26 Oct 2014 12:40:01 +0100 Subject: [PATCH 470/543] Fix Windows build by including wstcpip.h before winsock.h is included Error generated by socket-io.c was: /usr/i686-pc-mingw32/sys-root/mingw/include/ws2tcpip.h:38:2: error: #error "ws2tcpip.h is not compatible with winsock.h. Include winsock2.h instead." Signed-off-by: Alex J Lennon --- mono/metadata/socket-io.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mono/metadata/socket-io.c b/mono/metadata/socket-io.c index cbce0f77269..949164e5548 100644 --- a/mono/metadata/socket-io.c +++ b/mono/metadata/socket-io.c @@ -20,12 +20,6 @@ #include #include #include -#ifdef HAVE_UNISTD_H -#include -#endif -#include - -#include #ifdef HOST_WIN32 #include #else @@ -36,6 +30,12 @@ #include #include #endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +#include #include #include From ff1817f017385a6d4e04ab13e2e27cc2708b4c9a Mon Sep 17 00:00:00 2001 From: Alex J Lennon Date: Sun, 26 Oct 2014 14:06:08 +0100 Subject: [PATCH 471/543] [CI] Add appveyor.yml configuration file to support Windows build Adds a configuration file to facilitate build of Mono with Cygwin on Appveyor Windows-based build workers. Dependencies are installed on a clean Appveyor build image for each build and the result of the 'make install' step is stored as a build output 'artifact' for further testing or deployment. Signed-off-by: Alex J Lennon --- appveyor.yml | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000000..58c9a3a60b5 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,98 @@ +# +# Appveyor configuration file for CI build of Mono on Windows (under Cygwin) +# +# For further details see http://www.appveyor.com +# + +# Use 'unstable' Appveyor build worker image as Appveyor have added Cygwin to this for us +os: Unstable + +# +# Custom environment variables +# +environment: + global: + CYG_ROOT: C:/cygwin + CYG_MIRROR: http://cygwin.mirror.constant.com + CYG_CACHE: C:/cygwin/var/cache/setup + NSIS_ROOT: C:\nsis + +# +# Initialisation prior to pulling the Mono repository +# +init: + - 'echo Building Mono for Windows' + - 'echo System architecture: %PLATFORM%' + - 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%' + - 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%' +# Attempt to ensure we don't try to convert line endings to Win32 CRLF as this will cause build to fail + - 'git config --global core.autocrlf input' + +# +# Install needed build dependencies +# +install: +# NOTE: Already installed on current Appveyor unstable image +# - 'echo Retrieving Cygwin' +# - 'appveyor DownloadFile http://cygwin.com/setup-x86.exe -FileName %CYGROOT%/setup-x86.exe' + - 'echo Setting up Cygwin dependencies' + - '%CYG_ROOT%\setup-x86.exe -qnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P autoconf -P automake -P bison -P gcc-core -P gcc-g++ -P mingw-runtime -P mingw-binutils -P mingw-gcc-core -P mingw-gcc-g++ -P mingw-pthreads -P mingw-w32api -P libtool -P make -P python -P gettext-devel -P gettext -P intltool -P libiconv -P pkg-config -P git -P wget -P curl > NUL' + - 'echo Check Cygwin setup' + - '%CYG_ROOT%/bin/bash -lc "cygcheck -dc cygwin"' + - 'echo Done setting up Cygwin' + - 'echo Retrieving NSIS' + - 'appveyor DownloadFile "http://sunet.dl.sourceforge.net/project/nsis/NSIS 2/2.46/nsis-2.46-setup.exe" -FileName nsissetup.exe' + - 'echo Setting up NSIS' + - 'nsissetup.exe /S /D=%NSIS_ROOT%' + - 'echo Done setting up NSIS' + +# +# NOTE: msbuild doesn't work at present so use Cygwin to build +# +#build: +# project: C:\projects\mono\msvc\mono.sln +# verbosity: detailed + +# Cygwin build script +# +# NOTES: +# +# The stdin/stdout file descriptor appears not to be valid for the Appveyor +# build which causes failures as certain functions attempt to redirect +# default file handles. Ensure a dummy file descriptor is opened with exec. +# +build_script: + - cmd: 'echo Cygwin root is: %CYG_ROOT%' + - cmd: 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%' + - cmd: 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%' + - cmd: 'echo Repo build commit is: %APPVEYOR_REPO_COMMIT%' + - cmd: 'echo Autogen running...' + - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0 Date: Sun, 26 Oct 2014 14:49:45 +0100 Subject: [PATCH 472/543] [build] Enable dolt on mingw32 --- acinclude.m4 | 2 +- eglib/acinclude.m4 | 2 +- libgc/acinclude.m4 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 5216cd14a5e..bbc2781eab0 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -26,7 +26,7 @@ i?86-*-linux*|i?86-apple-darwin*|x86_64-*-linux*|powerpc-*-linux*|powerpc64-*-li |amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*) pic_options='-fPIC' ;; -?86-pc-cygwin*|i?86-pc-cygwin*) +?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*) pic_options='-DDLL_EXPORT' ;; i?86-apple-darwin*|arm-apple-darwin*) diff --git a/eglib/acinclude.m4 b/eglib/acinclude.m4 index 5216cd14a5e..bbc2781eab0 100644 --- a/eglib/acinclude.m4 +++ b/eglib/acinclude.m4 @@ -26,7 +26,7 @@ i?86-*-linux*|i?86-apple-darwin*|x86_64-*-linux*|powerpc-*-linux*|powerpc64-*-li |amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*) pic_options='-fPIC' ;; -?86-pc-cygwin*|i?86-pc-cygwin*) +?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*) pic_options='-DDLL_EXPORT' ;; i?86-apple-darwin*|arm-apple-darwin*) diff --git a/libgc/acinclude.m4 b/libgc/acinclude.m4 index 5216cd14a5e..bbc2781eab0 100644 --- a/libgc/acinclude.m4 +++ b/libgc/acinclude.m4 @@ -26,7 +26,7 @@ i?86-*-linux*|i?86-apple-darwin*|x86_64-*-linux*|powerpc-*-linux*|powerpc64-*-li |amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*) pic_options='-fPIC' ;; -?86-pc-cygwin*|i?86-pc-cygwin*) +?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*) pic_options='-DDLL_EXPORT' ;; i?86-apple-darwin*|arm-apple-darwin*) From e55e70f8c720c7b56dc7380c4f80e0c74c042a70 Mon Sep 17 00:00:00 2001 From: Martin Thwaites Date: Sun, 26 Oct 2014 14:29:45 +0000 Subject: [PATCH 473/543] Implement the SuppressFormsAuthenticationRedirect properties --- .../System.Web.Abstractions/System.Web/HttpResponseBase.cs | 4 ++++ .../System.Web/HttpResponseWrapper.cs | 7 +++++++ .../System.Web.Security/FormsAuthenticationModule.cs | 5 +++++ mcs/class/System.Web/System.Web/HttpResponse.cs | 7 +++++++ 4 files changed, 23 insertions(+) diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpResponseBase.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpResponseBase.cs index 0a3aa6694dd..921ace9ea84 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpResponseBase.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpResponseBase.cs @@ -105,6 +105,10 @@ void NotImplemented () public virtual bool SuppressContent { get { NotImplemented (); return false; } set { NotImplemented (); } } +#if NET_4_5 + public virtual bool SuppressFormsAuthenticationRedirect { get { NotImplemented (); return false; } set { NotImplemented (); } } +#endif + public virtual bool TrySkipIisCustomErrors { get { NotImplemented (); return false; } set { NotImplemented (); } } diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpResponseWrapper.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpResponseWrapper.cs index eed3415cd1c..1d9c2078171 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpResponseWrapper.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpResponseWrapper.cs @@ -169,6 +169,13 @@ public override bool SuppressContent { set { w.SuppressContent = value; } } +#if NET_4_5 + public override bool SuppressFormsAuthenticationRedirect { + get { return w.SuppressFormsAuthenticationRedirect; } + set { w.SuppressFormsAuthenticationRedirect = value; } + } +#endif + public override bool TrySkipIisCustomErrors { get { return w.TrySkipIisCustomErrors; } set { w.TrySkipIisCustomErrors = value; } diff --git a/mcs/class/System.Web/System.Web.Security/FormsAuthenticationModule.cs b/mcs/class/System.Web/System.Web.Security/FormsAuthenticationModule.cs index cab57fea2f2..54f07294e28 100644 --- a/mcs/class/System.Web/System.Web.Security/FormsAuthenticationModule.cs +++ b/mcs/class/System.Web/System.Web.Security/FormsAuthenticationModule.cs @@ -180,6 +180,11 @@ void OnEndRequest (object sender, EventArgs args) if (context.Response.StatusCode != 401 || context.Request.QueryString ["ReturnUrl"] != null) return; +#if NET_4_5 + if (context.Response.StatusCode == 401 && context.Response.SuppressFormsAuthenticationRedirect) + return; +#endif + string loginPage; InitConfig (context); #if NET_2_0 diff --git a/mcs/class/System.Web/System.Web/HttpResponse.cs b/mcs/class/System.Web/System.Web/HttpResponse.cs index 65718e5cd9b..4bd3380a8f8 100644 --- a/mcs/class/System.Web/System.Web/HttpResponse.cs +++ b/mcs/class/System.Web/System.Web/HttpResponse.cs @@ -400,6 +400,13 @@ public int SubStatusCode { set; } +#if NET_4_5 + public bool SuppressFormsAuthenticationRedirect { + get; + set; + } +#endif + public bool TrySkipIisCustomErrors { get; set; From d35449e99bc1315657ec41de2c90661bb82fc66a Mon Sep 17 00:00:00 2001 From: Mike Morano Date: Sun, 26 Oct 2014 11:14:08 -0400 Subject: [PATCH 474/543] Add/update missing bits in order to support MVC5.2. --- .../System.Web/HttpContextWrapper.cs | 3 +- .../System.Web/HttpRequestBase.cs | 3 + .../System.Web/HttpRequestWrapper.cs | 6 ++ .../System.Web/System.Web/HttpRequest.cs | 95 ++++++++++++++++--- .../System.Web/UnvalidatedRequestValues.cs | 66 +++++++++++++ .../UnvalidatedRequestValuesBase.cs | 90 ++++++++++++++++++ .../UnvalidatedRequestValuesWrapper.cs | 92 ++++++++++++++++++ .../System.Web/net_4_5_System.Web.dll.sources | 4 +- 8 files changed, 341 insertions(+), 18 deletions(-) create mode 100644 mcs/class/System.Web/System.Web/UnvalidatedRequestValues.cs create mode 100644 mcs/class/System.Web/System.Web/UnvalidatedRequestValuesBase.cs create mode 100644 mcs/class/System.Web/System.Web/UnvalidatedRequestValuesWrapper.cs diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpContextWrapper.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpContextWrapper.cs index 22feb8530d7..6581c0c1f77 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpContextWrapper.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpContextWrapper.cs @@ -183,10 +183,9 @@ public override object GetSection (string sectionName) return w.GetSection (sectionName); } - [MonoTODO] public override object GetService (Type serviceType) { - throw new NotImplementedException (); + return ((IServiceProvider)w).GetService (serviceType); } #if NET_4_0 public override void RemapHandler (IHttpHandler handler) diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs index 3a31754b949..bf1d6f576aa 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs @@ -138,7 +138,10 @@ public virtual RequestContext RequestContext { #if NET_4_5 public virtual ReadEntityBodyMode ReadEntityBodyMode { get { NotImplemented(); return ReadEntityBodyMode.Classic; } } + + public virtual UnvalidatedRequestValuesBase Unvalidated { get { NotImplemented (); return null; } } #endif + public virtual Uri Url { get { NotImplemented (); return null; } } public virtual Uri UrlReferrer { get { NotImplemented (); return null; } } diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs index dc5098a3bec..35f631e37e7 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs @@ -208,6 +208,12 @@ public override int TotalBytes { get { return w.TotalBytes; } } +#if NET_4_5 + public override UnvalidatedRequestValuesBase Unvalidated { + get { return new UnvalidatedRequestValuesWrapper (w.Unvalidated); } + } +#endif + public override Uri Url { get { return w.Url; } } diff --git a/mcs/class/System.Web/System.Web/HttpRequest.cs b/mcs/class/System.Web/System.Web/HttpRequest.cs index a2dd750eff4..6f845dbe108 100755 --- a/mcs/class/System.Web/System.Web/HttpRequest.cs +++ b/mcs/class/System.Web/System.Web/HttpRequest.cs @@ -80,13 +80,17 @@ public sealed partial class HttpRequest string unescaped_path; string original_path; string path_info; + string path_info_unvalidated; string raw_url; + string raw_url_unvalidated; WebROCollection all_params; - WebROCollection headers; + NameValueCollection headers; + WebROCollection headers_unvalidated; Stream input_stream; InputFilterStream input_filter; Stream filter; HttpCookieCollection cookies; + HttpCookieCollection cookies_unvalidated; string http_method; WebROCollection form; @@ -440,17 +444,27 @@ public string ContentType { } } - public HttpCookieCollection Cookies { + internal HttpCookieCollection CookiesNoValidation { get { - if (cookies == null) { + if (cookies_unvalidated == null) { if (worker_request == null) { - cookies = new HttpCookieCollection (); + cookies_unvalidated = new HttpCookieCollection (); } else { string cookie_hv = worker_request.GetKnownRequestHeader (HttpWorkerRequest.HeaderCookie); - cookies = new HttpCookieCollection (cookie_hv); + cookies_unvalidated = new HttpCookieCollection (cookie_hv); } } + return cookies_unvalidated; + } + } + + public HttpCookieCollection Cookies { + get { + if (cookies == null) { + cookies = CookiesNoValidation; + } + #if TARGET_J2EE // For J2EE portal support we emulate cookies using the session. GetSessionCookiesForPortal (cookies); @@ -737,10 +751,20 @@ public NameValueCollection Form { } } + internal NameValueCollection HeadersNoValidation { + get { + if (headers_unvalidated == null) { + headers_unvalidated = new HeadersCollection (this); + } + + return headers_unvalidated; + } + } + public NameValueCollection Headers { get { if (headers == null) { - headers = new HeadersCollection (this); + headers = HeadersNoValidation; #if NET_4_0 if (validateRequestNewMode) { RequestValidator validator = RequestValidator.Current; @@ -1226,12 +1250,23 @@ public string Path { } } + internal string PathInfoNoValidation { + get { + if (path_info_unvalidated == null) { + if (worker_request == null) + return String.Empty; + + path_info_unvalidated = worker_request.GetPathInfo () ?? String.Empty; + } + + return path_info_unvalidated; + } + } + public string PathInfo { get { if (path_info == null) { - if (worker_request == null) - return String.Empty; - path_info = worker_request.GetPathInfo () ?? String.Empty; + path_info = PathInfoNoValidation; #if NET_4_0 if (validateRequestNewMode) { RequestValidator validator = RequestValidator.Current; @@ -1335,16 +1370,26 @@ public NameValueCollection QueryString { } } - public string RawUrl { + internal string RawUrlUnvalidated { get { - if (raw_url == null) { + if (raw_url_unvalidated == null) { if (worker_request != null) - raw_url = worker_request.GetRawUrl (); + raw_url_unvalidated = worker_request.GetRawUrl (); else - raw_url = UrlComponents.Path + UrlComponents.Query; + raw_url_unvalidated = UrlComponents.Path + UrlComponents.Query; - if (raw_url == null) - raw_url = String.Empty; + if (raw_url_unvalidated == null) + raw_url_unvalidated = String.Empty; + } + + return raw_url_unvalidated; + } + } + + public string RawUrl { + get { + if (raw_url == null) { + raw_url = RawUrlUnvalidated; #if NET_4_0 if (validateRequestNewMode) { RequestValidator validator = RequestValidator.Current; @@ -1398,6 +1443,26 @@ public int TotalBytes { } } +#if NET_4_5 + public UnvalidatedRequestValues Unvalidated { + get { + var vals = new UnvalidatedRequestValues (); + + vals.Cookies = CookiesNoValidation; + vals.Files = Files; + vals.Form = FormUnvalidated; + vals.Headers = HeadersNoValidation; + vals.Path = PathNoValidation; + vals.PathInfo = PathInfoNoValidation; + vals.QueryString = QueryStringUnvalidated; + vals.RawUrl = RawUrlUnvalidated; + vals.Url = Url; + + return vals; + } + } +#endif + public Uri Url { get { if (cached_url == null) { diff --git a/mcs/class/System.Web/System.Web/UnvalidatedRequestValues.cs b/mcs/class/System.Web/System.Web/UnvalidatedRequestValues.cs new file mode 100644 index 00000000000..707b67e4139 --- /dev/null +++ b/mcs/class/System.Web/System.Web/UnvalidatedRequestValues.cs @@ -0,0 +1,66 @@ +// +// System.Web.UnvalidatedRequestValues.cs +// +// Author: +// Mike Morano +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Specialized; + + +namespace System.Web { + public sealed class UnvalidatedRequestValues { + public HttpCookieCollection Cookies { get; internal set; } + public HttpFileCollection Files { get; internal set; } + public NameValueCollection Form { get; internal set; } + public NameValueCollection Headers { get; internal set; } + public string Path { get; internal set; } + public string PathInfo { get; internal set; } + public NameValueCollection QueryString { get; internal set; } + public string RawUrl { get; internal set; } + public Uri Url { get; internal set; } + + public string this[string field] { + get { + if (Form != null && Form [field] != null) { + return Form [field]; + } + + if (Cookies != null && Cookies [field] != null) { + return Cookies [field].Value; + } + + if (QueryString != null && QueryString [field] != null) { + return QueryString [field]; + } + + // msdn docs also suggest the ServerVariables are inspected by this indexer, + // but that seems odd given what is available in this class + + return null; + } + } + } +} diff --git a/mcs/class/System.Web/System.Web/UnvalidatedRequestValuesBase.cs b/mcs/class/System.Web/System.Web/UnvalidatedRequestValuesBase.cs new file mode 100644 index 00000000000..9b54b072e28 --- /dev/null +++ b/mcs/class/System.Web/System.Web/UnvalidatedRequestValuesBase.cs @@ -0,0 +1,90 @@ +// +// System.Web.UnvalidatedRequestValuesBase.cs +// +// Author: +// Mike Morano +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Specialized; + + +namespace System.Web { + public abstract class UnvalidatedRequestValuesBase { + void NotImplemented () + { + throw new NotImplementedException (); + } + + public virtual HttpCookieCollection Cookies + { + get { NotImplemented (); return null; } + } + + public virtual HttpFileCollection Files + { + get { NotImplemented (); return null; } + } + + public virtual NameValueCollection Form + { + get { NotImplemented (); return null; } + } + + public virtual NameValueCollection Headers + { + get { NotImplemented (); return null; } + } + + public virtual string this[string field] + { + get { NotImplemented (); return null; } + } + + public virtual string Path + { + get { NotImplemented (); return null; } + } + + public virtual string PathInfo + { + get { NotImplemented (); return null; } + } + + public virtual NameValueCollection QueryString + { + get { NotImplemented (); return null; } + } + + public virtual string RawUrl + { + get { NotImplemented (); return null; } + } + + public virtual Uri Url + { + get { NotImplemented (); return null; } + } + } +} diff --git a/mcs/class/System.Web/System.Web/UnvalidatedRequestValuesWrapper.cs b/mcs/class/System.Web/System.Web/UnvalidatedRequestValuesWrapper.cs new file mode 100644 index 00000000000..e6b6084f2f2 --- /dev/null +++ b/mcs/class/System.Web/System.Web/UnvalidatedRequestValuesWrapper.cs @@ -0,0 +1,92 @@ +// +// System.Web.UnvalidatedRequestValuesWrapper.cs +// +// Author: +// Mike Morano +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Specialized; + + +namespace System.Web { + public class UnvalidatedRequestValuesWrapper : UnvalidatedRequestValuesBase { + UnvalidatedRequestValues rv; + + public UnvalidatedRequestValuesWrapper (UnvalidatedRequestValues requestValues) + { + rv = requestValues; + } + + public override HttpCookieCollection Cookies + { + get { return rv.Cookies; } + } + + public override HttpFileCollection Files + { + get { return rv.Files; } + } + + public override NameValueCollection Form + { + get { return rv.Form; } + } + + public override NameValueCollection Headers + { + get { return rv.Headers; } + } + + public override string this[string field] + { + get { return rv[field]; } + } + + public override string Path + { + get { return rv.Path; } + } + + public override string PathInfo + { + get { return rv.PathInfo; } + } + + public override NameValueCollection QueryString + { + get { return rv.QueryString; } + } + + public override string RawUrl + { + get { return rv.RawUrl; } + } + + public override Uri Url + { + get { return rv.Url; } + } + } +} diff --git a/mcs/class/System.Web/net_4_5_System.Web.dll.sources b/mcs/class/System.Web/net_4_5_System.Web.dll.sources index 04c7cacd659..f53e5bb9b76 100644 --- a/mcs/class/System.Web/net_4_5_System.Web.dll.sources +++ b/mcs/class/System.Web/net_4_5_System.Web.dll.sources @@ -2,4 +2,6 @@ System.Web/MimeMapping.cs System.Web/ReadEntityBodyMode.cs - +System.Web/UnvalidatedRequestValues.cs +System.Web/UnvalidatedRequestValuesBase.cs +System.Web/UnvalidatedRequestValuesWrapper.cs From b7b94a8024dcfa46fd6575e0af3e2f28dd3da625 Mon Sep 17 00:00:00 2001 From: Martin Thwaites Date: Sun, 26 Oct 2014 23:42:54 +0000 Subject: [PATCH 475/543] Add ClientDisconnectedToken property to HttpResponseBase and Wrapper as default None --- .../System.Web.Abstractions/System.Web/HttpResponseBase.cs | 5 +++++ .../System.Web/HttpResponseWrapper.cs | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpResponseBase.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpResponseBase.cs index 0a3aa6694dd..1fda018a955 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpResponseBase.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpResponseBase.cs @@ -39,6 +39,7 @@ using System.Security.Principal; using System.Text; using System.Web.Caching; +using System.Threading; #if NET_4_0 using System.Web.Routing; @@ -69,6 +70,10 @@ void NotImplemented () public virtual string Charset { get { NotImplemented (); return null; } set { NotImplemented (); } } +#if NET_4_5 + public virtual CancellationToken ClientDisconnectedToken { get { NotImplemented (); return CancellationToken.None; } } +#endif + public virtual Encoding ContentEncoding { get { NotImplemented (); return null; } set { NotImplemented (); } } public virtual string ContentType { get { NotImplemented (); return null; } set { NotImplemented (); } } diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpResponseWrapper.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpResponseWrapper.cs index eed3415cd1c..f4a17c349d3 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpResponseWrapper.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpResponseWrapper.cs @@ -39,6 +39,7 @@ using System.Security.Principal; using System.Text; using System.Web.Caching; +using System.Threading; namespace System.Web { @@ -82,6 +83,12 @@ public override string Charset { set { w.Charset = value; } } +#if NET_4_5 + public override CancellationToken ClientDisconnectedToken { + get { return CancellationToken.None; } + } +#endif + public override Encoding ContentEncoding { get { return w.ContentEncoding; } set { w.ContentEncoding = value; } From 7174b069cf6696a1b994259ec4c066b534f06f81 Mon Sep 17 00:00:00 2001 From: michaldobrodenka Date: Mon, 27 Oct 2014 13:28:59 +0100 Subject: [PATCH 476/543] Fix for ObjectDiposedException in DispatcherCB class https://bugzilla.xamarin.com/show_bug.cgi?id=23700 --- mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs b/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs index a7eeb67d883..c7f6259172d 100644 --- a/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs +++ b/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs @@ -260,6 +260,8 @@ void ConnectCallback (IAsyncResult ares) curSocket.EndConnect (ares); } catch (SocketException se) { SocketError = se.SocketErrorCode; + } catch (ObjectDisposedException) { + SocketError = SocketError.OperationAborted; } finally { OnCompleted (this); } From 447975c12c271a7d81d0d1ce631e8c62fd8cb79d Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Mon, 27 Oct 2014 12:28:19 -0400 Subject: [PATCH 477/543] [threadpool] Fix race condition on threads variable cleanup --- mono/metadata/threadpool.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c index 3c712920d4f..36514cc6ea8 100644 --- a/mono/metadata/threadpool.c +++ b/mono/metadata/threadpool.c @@ -785,6 +785,13 @@ typedef struct { gint8 nthreads_diff; } SamplesHistory; +/* + * returns : + * - 1 if the number of threads should increase + * - 0 if it should not change + * - -1 if it should decrease + * - -2 in case of error + */ static gint8 monitor_heuristic (gint16 *current, gint16 *history_size, SamplesHistory *history, ThreadPool *tp) { @@ -829,6 +836,10 @@ monitor_heuristic (gint16 *current, gint16 *history_size, SamplesHistory *histor decision = 2; } else { mono_mutex_lock (&threads_lock); + if (threads == NULL) { + mono_mutex_unlock (&threads_lock); + return -2; + } all_waitsleepjoin = TRUE; for (i = 0; i < threads->len; ++i) { thread = g_ptr_array_index (threads, i); @@ -910,6 +921,10 @@ monitor_thread (gpointer unused) if (suspended) continue; + /* threadpool is cleaning up */ + if (async_tp.pool_status == 2 || async_io_tp.pool_status == 2) + break; + switch (monitor_state) { case MONITOR_STATE_AWAKE: num_waiting_iterations = 0; @@ -939,9 +954,9 @@ monitor_thread (gpointer unused) } else { gint8 nthreads_diff = monitor_heuristic (¤t, &history_size, history, tp); - if (nthreads_diff > 0) + if (nthreads_diff == 1) threadpool_start_thread (tp); - else if (nthreads_diff < 0) + else if (nthreads_diff == -1) threadpool_kill_thread (tp); } } @@ -992,6 +1007,7 @@ mono_thread_pool_init (void) mono_mutex_init (&threads_lock); threads = g_ptr_array_sized_new (thread_count); + g_assert (threads); mono_mutex_init_recursive (&wsqs_lock); wsqs = g_ptr_array_sized_new (MAX (100 * cpu_count, thread_count)); @@ -1182,6 +1198,7 @@ threadpool_start_thread (ThreadPool *tp) thread = mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size); if (!tp->is_io) { mono_mutex_lock (&threads_lock); + g_assert (threads != NULL); g_ptr_array_add (threads, thread); mono_mutex_unlock (&threads_lock); } @@ -1704,9 +1721,14 @@ async_invoke_thread (gpointer data) if (tp_finish_func) tp_finish_func (tp_hooks_user_data); - mono_mutex_lock (&threads_lock); - g_ptr_array_remove_fast (threads, mono_thread_current ()->internal_thread); - mono_mutex_unlock (&threads_lock); + if (!tp->is_io) { + if (threads) { + mono_mutex_lock (&threads_lock); + if (threads) + g_ptr_array_remove_fast (threads, mono_thread_current ()->internal_thread); + mono_mutex_unlock (&threads_lock); + } + } return; } From 8b8017811520ed6f919f95516b052b11c8ccb7bd Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Mon, 27 Oct 2014 22:51:47 +0000 Subject: [PATCH 478/543] Add missing header file to s390x_sources, otherwise a required header file for s390x builds is missing from tarball builds. --- mono/mini/Makefile.am.in | 1 + 1 file changed, 1 insertion(+) diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index 104294b401a..c76d61848d9 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -348,6 +348,7 @@ sparc_sources = \ s390x_sources = \ mini-s390x.c \ mini-s390x.h \ + support-s390x.h \ exceptions-s390x.c \ tramp-s390x.c From 80ca0394cd422b8ce849b4f9064c422c8bf03390 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 27 Oct 2014 20:55:48 -0400 Subject: [PATCH 479/543] [jit] Fix the decomposition of OP_IREM_IMM on arm64. --- mono/mini/decompose.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mono/mini/decompose.c b/mono/mini/decompose.c index 907d7582ae2..6e9d4aaef71 100644 --- a/mono/mini/decompose.c +++ b/mono/mini/decompose.c @@ -497,12 +497,12 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) if (power > 1) { intermediate_reg = compensator_reg; - MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_SHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31); + MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_ISHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31); } else { intermediate_reg = ins->sreg1; } - MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_SHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power); + MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_ISHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power); MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LADD : OP_IADD, ins->dreg, ins->sreg1, compensator_reg); /* Compute remainder */ MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LAND_IMM : OP_AND_IMM, ins->dreg, ins->dreg, (1 << power) - 1); From 13fd028ee87066b157b66904f8cc7ee8d8cf7181 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Sun, 8 Jun 2014 16:46:18 -0500 Subject: [PATCH 480/543] [System.IO] Reimplemented much of the kqueue-based file watcher so that watching subdirectories works. Reworked a lot of the internals of the kqueue FileSystemWatcher. There is now a separate thread and a separate kqueue for each FileSystemWatcher object. https://bugzilla.xamarin.com/show_bug.cgi?id=16259 --- mcs/class/System/System.IO/KeventWatcher.cs | 537 +++++++++++--------- 1 file changed, 285 insertions(+), 252 deletions(-) diff --git a/mcs/class/System/System.IO/KeventWatcher.cs b/mcs/class/System/System.IO/KeventWatcher.cs index e673f99739b..2b96de34404 100644 --- a/mcs/class/System/System.IO/KeventWatcher.cs +++ b/mcs/class/System/System.IO/KeventWatcher.cs @@ -3,6 +3,7 @@ // // Authors: // Geoff Norton (gnorton@customerdna.com) +// Cody Russell (cody@xamarin.com) // // (c) 2004 Geoff Norton // Copyright 2014 Xamarin Inc @@ -29,6 +30,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -123,13 +125,14 @@ enum FilterFlags : uint { TimerNanoSeconds = 0x00000004, TimerAbsolute = 0x00000008, } - + + [StructLayout(LayoutKind.Sequential)] struct kevent : IDisposable { public int ident; public EventFilter filter; public EventFlags flags; public FilterFlags fflags; - public int data; + public IntPtr data; public IntPtr udata; public void Dispose () @@ -144,300 +147,238 @@ struct timespec { public int tv_usec; } - class KeventFileData { - public FileSystemInfo fsi; - public DateTime LastAccessTime; - public DateTime LastWriteTime; + class PathData + { + public string Path; + public bool IsDirectory; + } - public KeventFileData(FileSystemInfo fsi, DateTime LastAccessTime, DateTime LastWriteTime) { - this.fsi = fsi; - this.LastAccessTime = LastAccessTime; - this.LastWriteTime = LastWriteTime; + class KqueueMonitor : IDisposable + { + public int Connection + { + get { return conn; } } - } - class KeventData { - public FileSystemWatcher FSW; - public string Directory; - public string FileMask; - public bool IncludeSubdirs; - public bool Enabled; - public Hashtable DirEntries; - public kevent ev; - } + public KqueueMonitor (FileSystemWatcher fsw) + { + this.fsw = fsw; + this.conn = -1; + } - class KeventWatcher : IFileWatcher - { - static bool failed; - static KeventWatcher instance; - static Hashtable watches; - static Hashtable requests; - static Thread thread; - static int conn; - static bool stop; - - private KeventWatcher () + public void Dispose () { + Stop (); } - - // Locked by caller - public static bool GetInstance (out IFileWatcher watcher) + + public void Start () { - if (failed == true) { - watcher = null; - return false; - } + conn = kqueue (); - if (instance != null) { - watcher = instance; - return true; + if (thread == null) { + thread = new Thread (new ThreadStart (Monitor)); + thread.IsBackground = true; + thread.Start (); } - watches = Hashtable.Synchronized (new Hashtable ()); - requests = Hashtable.Synchronized (new Hashtable ()); - conn = kqueue(); - if (conn == -1) { - failed = true; - watcher = null; - return false; - } + var pathData = Add (fsw.FullPath); - instance = new KeventWatcher (); - watcher = instance; - return true; + Scan (pathData); } - - public void StartDispatching (FileSystemWatcher fsw) + + public void Stop () { - KeventData data; - lock (this) { - if (thread == null) { - thread = new Thread (new ThreadStart (Monitor)); - thread.IsBackground = true; - thread.Start (); - } + stop = true; - data = (KeventData) watches [fsw]; - } + if (thread != null) + thread.Interrupt (); - if (data == null) { - data = new KeventData (); - data.FSW = fsw; - data.Directory = fsw.FullPath; - data.FileMask = fsw.MangledFilter; - data.IncludeSubdirs = fsw.IncludeSubdirectories; - - data.Enabled = true; - lock (this) { - StartMonitoringDirectory (data); - watches [fsw] = data; - stop = false; - } - } + if (conn != -1) + close (conn); + + conn = -1; } - static void StartMonitoringDirectory (KeventData data) + private PathData FindPath (string path) { - DirectoryInfo dir = new DirectoryInfo (data.Directory); - if(data.DirEntries == null) { - data.DirEntries = new Hashtable(); - foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() ) - data.DirEntries.Add(fsi.FullName, new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime)); + foreach (KeyValuePair kv in paths) { + if (kv.Key.Path == path) + return kv.Key; } - int fd = open(data.Directory, 0, 0); - kevent ev = new kevent(); - ev.udata = IntPtr.Zero; - timespec nullts = new timespec(); - nullts.tv_sec = 0; - nullts.tv_usec = 0; - if (fd > 0) { - ev.ident = fd; - ev.filter = EventFilter.Vnode; - ev.flags = EventFlags.Add | EventFlags.Enable | EventFlags.OneShot; - ev.fflags = // 20 | 2 | 1 | 8; - FilterFlags.VNodeDelete | - FilterFlags.VNodeWrite | - FilterFlags.VNodeAttrib | - // The following two values are the equivalent of the original value "20", but we suspect the original author meant - // 0x20, we will review later with some test cases - FilterFlags.VNodeLink | - FilterFlags.VNodeExtend; - ev.data = 0; - ev.udata = Marshal.StringToHGlobalAuto (data.Directory); - kevent outev = new kevent(); - outev.udata = IntPtr.Zero; - kevent (conn, ref ev, 1, ref outev, 0, ref nullts); - data.ev = ev; - requests [fd] = data; - } - - if (!data.IncludeSubdirs) - return; - + return null; } - public void StopDispatching (FileSystemWatcher fsw) + private PathData FindPath (int fd) { - KeventData data; - lock (this) { - data = (KeventData) watches [fsw]; - if (data == null) - return; - - StopMonitoringDirectory (data); - watches.Remove (fsw); - if (watches.Count == 0) - stop = true; - - if (!data.IncludeSubdirs) - return; - + foreach (KeyValuePair kv in paths) { + if (kv.Value == fd) + return kv.Key; } - } - static void StopMonitoringDirectory (KeventData data) - { - close(data.ev.ident); + return null; } - void Monitor () + private void Monitor () { - + bool firstRun = true; + while (!stop) { - kevent ev = new kevent(); - ev.udata = IntPtr.Zero; - kevent nullev = new kevent(); - nullev.udata = IntPtr.Zero; - timespec ts = new timespec(); - ts.tv_sec = 0; - ts.tv_usec = 0; - int haveEvents; - lock (this) { - haveEvents = kevent (conn, ref nullev, 0, ref ev, 1, ref ts); + removeQueue.ForEach (Remove); + + var changes = new List (); + var outEvents = new List (); + + rescanQueue.ForEach (fd => { + var path = FindPath (fd); + Scan (path, !firstRun); + }); + rescanQueue.Clear (); + + foreach (KeyValuePair kv in paths) { + var change = new kevent { + ident = kv.Value, + filter = EventFilter.Vnode, + flags = EventFlags.Add | EventFlags.Enable | EventFlags.Clear, + fflags = FilterFlags.VNodeDelete | FilterFlags.VNodeExtend | + FilterFlags.VNodeRename | FilterFlags.VNodeAttrib | + FilterFlags.VNodeLink | FilterFlags.VNodeRevoke | + FilterFlags.VNodeWrite, + data = IntPtr.Zero, + udata = IntPtr.Zero + }; + + changes.Add (change); + outEvents.Add (new kevent ()); } - if (haveEvents > 0) { - // Restart monitoring - KeventData data = (KeventData) requests [ev.ident]; - StopMonitoringDirectory (data); - StartMonitoringDirectory (data); - ProcessEvent (ev); + if (changes.Count > 0) { + var outArray = outEvents.ToArray (); + var changesArray = changes.ToArray (); + int numEvents = kevent (conn, changesArray, changesArray.Length, outArray, outArray.Length, IntPtr.Zero); + + for (var i = 0; i < numEvents; i++) { + var kevt = outArray [i]; + var pathData = FindPath (kevt.ident); + + if ((kevt.fflags & FilterFlags.VNodeDelete) != 0) { + removeQueue.Add (kevt.ident); + PostEvent (FileAction.Removed, pathData.Path); + } else if (((kevt.fflags & FilterFlags.VNodeRename) != 0) || ((kevt.fflags & FilterFlags.VNodeRevoke) != 0) || ((kevt.fflags & FilterFlags.VNodeWrite) != 0)) { + if (pathData.IsDirectory && Directory.Exists (pathData.Path)) + rescanQueue.Add (kevt.ident); + + if ((kevt.fflags & FilterFlags.VNodeRename) != 0) { + var fd = paths [pathData]; + var newFilename = GetFilenameFromFd (fd); + var oldFilename = pathData.Path; + + Remove (pathData); + PostEvent (FileAction.RenamedNewName, oldFilename, newFilename); + + Add (newFilename, false); + } + } else if ((kevt.fflags & FilterFlags.VNodeAttrib) != 0) { + PostEvent (FileAction.Modified, pathData.Path); + } + } } else { - System.Threading.Thread.Sleep (500); + Thread.Sleep (500); } - } - lock (this) { - thread = null; - stop = false; + firstRun = false; } } - void ProcessEvent (kevent ev) + private PathData Add (string path, bool postEvents = false) { - lock (this) { - KeventData data = (KeventData) requests [ev.ident]; - if (!data.Enabled) - return; - - FileSystemWatcher fsw; - string filename = ""; - - fsw = data.FSW; - FileAction fa = 0; - DirectoryInfo dir = new DirectoryInfo (data.Directory); - FileSystemInfo changedFsi = null; - - try { - foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() ) - if (data.DirEntries.ContainsKey (fsi.FullName) && (fsi is FileInfo)) { - KeventFileData entry = (KeventFileData) data.DirEntries [fsi.FullName]; - if (entry.LastWriteTime != fsi.LastWriteTime) { - filename = fsi.Name; - fa = FileAction.Modified; - data.DirEntries [fsi.FullName] = new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime); - if (fsw.IncludeSubdirectories && fsi is DirectoryInfo) { - data.Directory = filename; - requests [ev.ident] = data; - ProcessEvent(ev); - } - changedFsi = fsi; - PostEvent(filename, fsw, fa, changedFsi); - } - } - } catch (Exception) { - // The file system infos were changed while we processed them - } - // Deleted - try { - bool deleteMatched = true; - while(deleteMatched) { - foreach (KeventFileData entry in data.DirEntries.Values) { - if (!File.Exists (entry.fsi.FullName) && !Directory.Exists (entry.fsi.FullName)) { - filename = entry.fsi.Name; - fa = FileAction.Removed; - data.DirEntries.Remove (entry.fsi.FullName); - changedFsi = entry.fsi; - PostEvent(filename, fsw, fa, changedFsi); - break; - } - } - deleteMatched = false; - } - } catch (Exception) { - // The file system infos were changed while we processed them - } - // Added - try { - foreach (FileSystemInfo fsi in dir.GetFileSystemInfos()) - if (!data.DirEntries.ContainsKey (fsi.FullName)) { - changedFsi = fsi; - filename = fsi.Name; - fa = FileAction.Added; - data.DirEntries [fsi.FullName] = new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime); - PostEvent(filename, fsw, fa, changedFsi); - } - } catch (Exception) { - // The file system infos were changed while we processed them - } - + var fd = open (path, O_EVTONLY, 0); + + if (fd == -1) + return null; + var attrs = File.GetAttributes (path); + bool isDir = false; + if ((attrs & FileAttributes.Directory) == FileAttributes.Directory) + isDir = true; + + var pathData = new PathData { + Path = path, + IsDirectory = isDir + }; + + if (FindPath (path) == null) { + paths.Add (pathData, fd); + + if (postEvents) + PostEvent (FileAction.Added, path); } + + return pathData; } - private void PostEvent (string filename, FileSystemWatcher fsw, FileAction fa, FileSystemInfo changedFsi) { - RenamedEventArgs renamed = null; - if (fa == 0) + private void Remove (int fd) + { + var path = FindPath (fd); + paths.Remove (path); + removeQueue.Remove (fd); + + close (fd); + } + + private void Remove (PathData pathData) + { + var fd = paths [pathData]; + paths.Remove (pathData); + removeQueue.Remove (fd); + + close (fd); + } + + private void Scan (PathData pathData, bool postEvents = false) + { + var path = pathData.Path; + + Add (path, postEvents); + + if (!fsw.IncludeSubdirectories) return; - - if (fsw.IncludeSubdirectories && fa == FileAction.Added) { - if (changedFsi is DirectoryInfo) { - KeventData newdirdata = new KeventData (); - newdirdata.FSW = fsw; - newdirdata.Directory = changedFsi.FullName; - newdirdata.FileMask = fsw.MangledFilter; - newdirdata.IncludeSubdirs = fsw.IncludeSubdirectories; - - newdirdata.Enabled = true; - lock (this) { - StartMonitoringDirectory (newdirdata); + + var attrs = File.GetAttributes (path); + if ((attrs & FileAttributes.Directory) == FileAttributes.Directory) { + var dirsToProcess = new List (); + dirsToProcess.Add (path); + + while (dirsToProcess.Count > 0) { + var tmp = dirsToProcess [0]; + dirsToProcess.RemoveAt (0); + + var info = new DirectoryInfo (tmp); + foreach (var fsi in info.GetFileSystemInfos ()) { + if (Add (fsi.FullName, postEvents) == null) + continue; + + var childAttrs = File.GetAttributes (fsi.FullName); + if ((childAttrs & FileAttributes.Directory) == FileAttributes.Directory) + dirsToProcess.Add (fsi.FullName); } } } - - if (!fsw.Pattern.IsMatch(filename, true)) + } + + private void PostEvent (FileAction action, string path, string newPath = null) + { + RenamedEventArgs renamed = null; + + if (action == 0) return; + if (action == FileAction.RenamedNewName) + renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, "", newPath, path); + lock (fsw) { - if (changedFsi.FullName.StartsWith (fsw.FullPath, StringComparison.Ordinal)) { - if (fsw.FullPath.EndsWith ("/", StringComparison.Ordinal)) { - filename = changedFsi.FullName.Substring (fsw.FullPath.Length); - } else { - filename = changedFsi.FullName.Substring (fsw.FullPath.Length + 1); - } - } - fsw.DispatchEvents (fa, filename, ref renamed); + fsw.DispatchEvents (action, path, ref renamed); + if (fsw.Waiting) { fsw.Waiting = false; System.Threading.Monitor.PulseAll (fsw); @@ -445,17 +386,109 @@ private void PostEvent (string filename, FileSystemWatcher fsw, FileAction fa, F } } + private string GetFilenameFromFd (int fd) + { + var sb = new StringBuilder (1024); + + if (fcntl (fd, F_GETPATH, sb) != -1) + return sb.ToString (); + else + return String.Empty; + } + + private const int O_EVTONLY = 0x8000; + private const int F_GETPATH = 50; + private FileSystemWatcher fsw; + private int conn; + private Thread thread; + private bool stop; + private readonly List removeQueue = new List (); + private readonly List rescanQueue = new List (); + private readonly Dictionary paths = new Dictionary (); + + [DllImport ("libc", EntryPoint="fcntl", CharSet=CharSet.Auto, SetLastError=true)] + static extern int fcntl (int file_names_by_descriptor, int cmd, StringBuilder sb); + [DllImport ("libc")] - extern static int open(string path, int flags, int mode_t); - + extern static int open (string path, int flags, int mode_t); + + [DllImport ("libc")] + extern static int close (int fd); + + [DllImport ("libc")] + extern static int kqueue (); + [DllImport ("libc")] - extern static int close(int fd); + extern static int kevent(int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, IntPtr time); + } + + class KeventWatcher : IFileWatcher + { + static bool failed; + static KeventWatcher instance; + static Hashtable watches; // + + private KeventWatcher () + { + } + + // Locked by caller + public static bool GetInstance (out IFileWatcher watcher) + { + if (failed == true) { + watcher = null; + return false; + } + + if (instance != null) { + watcher = instance; + return true; + } + + watches = Hashtable.Synchronized (new Hashtable ()); + var conn = kqueue(); + if (conn == -1) { + failed = true; + watcher = null; + return false; + } + close (conn); + + instance = new KeventWatcher (); + watcher = instance; + return true; + } + + public void StartDispatching (FileSystemWatcher fsw) + { + KqueueMonitor monitor; + + if (watches.ContainsKey (fsw)) { + monitor = (KqueueMonitor)watches [fsw]; + } else { + monitor = new KqueueMonitor (fsw); + } + + watches.Add (fsw, monitor); + + monitor.Start (); + } + + public void StopDispatching (FileSystemWatcher fsw) + { + KqueueMonitor monitor = (KqueueMonitor)watches [fsw]; + if (monitor == null) + return; + + monitor.Stop (); + } + [DllImport ("libc")] - extern static int kqueue(); + extern static int close (int fd); [DllImport ("libc")] - extern static int kevent(int kqueue, ref kevent ev, int nchanges, ref kevent evtlist, int nevents, ref timespec ts); + extern static int kqueue (); } } From 717c6de1cc49dabb2ecaa2a844a8b2b162c21440 Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Wed, 8 Oct 2014 22:16:40 -0700 Subject: [PATCH 481/543] [System.IO] Phase 2 of revamping KeventWatcher (FileSystemWatcher implementation for OS X/kqueue). Dozens of bugs and reliability issues fixed. FileSystemWatcher.cs: Fixed multicast events. SearchPattern.cs : Fixed issue where case insensitivity was not being honored. KeventWatcher.cs: * Fixed several race conditions * Fixed file descriptor duplication & leaks * thread-safe/cleaner state transitions for watcher, and much cleaner stopping * Now uses fsw.Filter parameter and respects IncludeSubdirectories = false. Use fsw.Filter to watch very large trees * Added more error handling + OnError event * Lots of behavior/reliability fixes and optimizations for Monitor() loop * Fixed kevent/timespec struct definitions (for 64-bit build) --- .../System/System.IO/FileSystemWatcher.cs | 69 +-- mcs/class/System/System.IO/KeventWatcher.cs | 466 ++++++++++++------ mcs/class/System/System.IO/SearchPattern.cs | 23 +- 3 files changed, 370 insertions(+), 188 deletions(-) diff --git a/mcs/class/System/System.IO/FileSystemWatcher.cs b/mcs/class/System/System.IO/FileSystemWatcher.cs index 125f07805f9..0d293e53188 100644 --- a/mcs/class/System/System.IO/FileSystemWatcher.cs +++ b/mcs/class/System/System.IO/FileSystemWatcher.cs @@ -183,7 +183,10 @@ internal string MangledFilter { internal SearchPattern2 Pattern { get { if (pattern == null) { - pattern = new SearchPattern2 (MangledFilter); + if (watcher.GetType () == typeof (KeventWatcher)) + pattern = new SearchPattern2 (MangledFilter, true); //assume we want to ignore case (OS X) + else + pattern = new SearchPattern2 (MangledFilter); } return pattern; } @@ -372,52 +375,60 @@ enum EventType { ErrorEvent, RenameEvent } - private void RaiseEvent (Delegate ev, EventArgs arg, EventType evtype) - { - if (ev == null) - return; - - if (synchronizingObject == null) { - switch (evtype) { - case EventType.RenameEvent: - ((RenamedEventHandler)ev).BeginInvoke (this, (RenamedEventArgs) arg, null, null); - break; - case EventType.ErrorEvent: - ((ErrorEventHandler)ev).BeginInvoke (this, (ErrorEventArgs) arg, null, null); - break; - case EventType.FileSystemEvent: - ((FileSystemEventHandler)ev).BeginInvoke (this, (FileSystemEventArgs) arg, null, null); - break; - } - return; - } - synchronizingObject.BeginInvoke (ev, new object [] {this, arg}); - } - protected void OnChanged (FileSystemEventArgs e) { - RaiseEvent (Changed, e, EventType.FileSystemEvent); + if (Changed == null) + return; + + if (synchronizingObject == null) + Changed (this, e); + else + synchronizingObject.BeginInvoke (Changed, new object[] { this, e }); } protected void OnCreated (FileSystemEventArgs e) { - RaiseEvent (Created, e, EventType.FileSystemEvent); + if (Created == null) + return; + + if (synchronizingObject == null) + Created (this, e); + else + synchronizingObject.BeginInvoke (Created, new object[] { this, e }); } protected void OnDeleted (FileSystemEventArgs e) { - RaiseEvent (Deleted, e, EventType.FileSystemEvent); + if (Deleted == null) + return; + + if (synchronizingObject == null) + Deleted (this, e); + else + synchronizingObject.BeginInvoke (Deleted, new object[] { this, e }); } - protected void OnError (ErrorEventArgs e) + internal void OnError (ErrorEventArgs e) { - RaiseEvent (Error, e, EventType.ErrorEvent); + if (Error == null) + return; + + if (synchronizingObject == null) + Error (this, e); + else + synchronizingObject.BeginInvoke (Error, new object[] { this, e }); } protected void OnRenamed (RenamedEventArgs e) { - RaiseEvent (Renamed, e, EventType.RenameEvent); + if (Renamed == null) + return; + + if (synchronizingObject == null) + Renamed (this, e); + else + synchronizingObject.BeginInvoke (Renamed, new object[] { this, e }); } public WaitForChangedResult WaitForChanged (WatcherChangeTypes changeType) diff --git a/mcs/class/System/System.IO/KeventWatcher.cs b/mcs/class/System/System.IO/KeventWatcher.cs index 2b96de34404..f3cc7dcc183 100644 --- a/mcs/class/System/System.IO/KeventWatcher.cs +++ b/mcs/class/System/System.IO/KeventWatcher.cs @@ -4,6 +4,7 @@ // Authors: // Geoff Norton (gnorton@customerdna.com) // Cody Russell (cody@xamarin.com) +// Alexis Christoforides (lexas@xamarin.com) // // (c) 2004 Geoff Norton // Copyright 2014 Xamarin Inc @@ -36,6 +37,7 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading; +using System.Reflection; namespace System.IO { @@ -73,6 +75,7 @@ enum EventFilter : short { VM = -11 } + [Flags] enum FilterFlags : uint { ReadPoll = EventFlags.Flag0, ReadOutOfBand = EventFlags.Flag1, @@ -128,7 +131,7 @@ enum FilterFlags : uint { [StructLayout(LayoutKind.Sequential)] struct kevent : IDisposable { - public int ident; + public UIntPtr ident; public EventFilter filter; public EventFlags flags; public FilterFlags fflags; @@ -140,17 +143,21 @@ public void Dispose () if (udata != IntPtr.Zero) Marshal.FreeHGlobal (udata); } + + } + [StructLayout(LayoutKind.Sequential)] struct timespec { - public int tv_sec; - public int tv_usec; + public IntPtr tv_sec; + public IntPtr tv_usec; } class PathData { public string Path; public bool IsDirectory; + public int Fd; } class KqueueMonitor : IDisposable @@ -168,211 +175,367 @@ public KqueueMonitor (FileSystemWatcher fsw) public void Dispose () { - Stop (); + CleanUp (); } public void Start () { - conn = kqueue (); + lock (stateLock) { + if (started) + return; - if (thread == null) { - thread = new Thread (new ThreadStart (Monitor)); + conn = kqueue (); + + if (conn == -1) + throw new IOException (String.Format ( + "kqueue() error at init, error code = '{0}'", Marshal.GetLastWin32Error ())); + + thread = new Thread (() => DoMonitor ()); thread.IsBackground = true; thread.Start (); - } - var pathData = Add (fsw.FullPath); + startedEvent.WaitOne (); - Scan (pathData); + if (failedInit) { + thread.Join (); + CleanUp (); + throw new IOException ("Monitor thread failed while initializing."); + } + else + started = true; + } } public void Stop () { - stop = true; - - if (thread != null) - thread.Interrupt (); + lock (stateLock) { + if (!started) + return; + + requestStop = true; + thread.Join (); + requestStop = false; + + CleanUp (); + started = false; + } + } + void CleanUp () + { if (conn != -1) close (conn); conn = -1; + + foreach (int fd in fdsDict.Keys) + close (fd); + + fdsDict.Clear (); + pathsDict.Clear (); } - private PathData FindPath (string path) + void DoMonitor () { - foreach (KeyValuePair kv in paths) { - if (kv.Key.Path == path) - return kv.Key; + Exception exc = null; + failedInit = false; + + try { + Setup (); + } catch (Exception e) { + failedInit = true; + exc = e; + } finally { + startedEvent.Set (); + } + + if (failedInit) { + fsw.OnError (new ErrorEventArgs (exc)); + return; } - return null; + try { + Monitor (); + } catch (Exception e) { + exc = e; + } finally { + if (!requestStop) { // failure + CleanUp (); + started = false; + } + if (exc != null) + fsw.OnError (new ErrorEventArgs (exc)); + } } - private PathData FindPath (int fd) + void Setup () + { + var initialFds = new List (); + + // GetFilenameFromFd() returns the *realpath* which can be different than fsw.FullPath because symlinks. + // If so, introduce a fixup step. + int fd = open (fsw.FullPath, O_EVTONLY, 0); + var resolvedFullPath = GetFilenameFromFd (fd); + close (fd); + + if (resolvedFullPath != fsw.FullPath) + fixupPath = resolvedFullPath; + else + fixupPath = null; + + Scan (fsw.FullPath, false, ref initialFds); + + var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)0 }; + var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point + var changes = CreateChangeList (ref initialFds); + + int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout); + + if (numEvents == -1) { + var errMsg = String.Format ("kevent() error at initial event registration, error code = '{0}'", Marshal.GetLastWin32Error ()); + throw new IOException (errMsg); + } + } + + kevent[] CreateChangeList (ref List FdList) { - foreach (KeyValuePair kv in paths) { - if (kv.Value == fd) - return kv.Key; + if (FdList.Count == 0) + return emptyEventList; + + var changes = new List (); + foreach (int fd in FdList) { + var change = new kevent { + + ident = (UIntPtr)fd, + filter = EventFilter.Vnode, + flags = EventFlags.Add | EventFlags.Enable | EventFlags.Clear, + fflags = FilterFlags.VNodeDelete | FilterFlags.VNodeExtend | + FilterFlags.VNodeRename | FilterFlags.VNodeAttrib | + FilterFlags.VNodeLink | FilterFlags.VNodeRevoke | + FilterFlags.VNodeWrite, + data = IntPtr.Zero, + udata = IntPtr.Zero + }; + + changes.Add (change); } + FdList.Clear (); - return null; + return changes.ToArray (); } - private void Monitor () + void Monitor () { - bool firstRun = true; + var timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)500000000 }; + var eventBuffer = new kevent[32]; + var newFds = new List (); + List removeQueue = new List (); + List rescanQueue = new List (); - while (!stop) { - removeQueue.ForEach (Remove); + while (!requestStop) { + var changes = CreateChangeList (ref newFds); - var changes = new List (); - var outEvents = new List (); + int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref timeout); - rescanQueue.ForEach (fd => { - var path = FindPath (fd); - Scan (path, !firstRun); - }); - rescanQueue.Clear (); - - foreach (KeyValuePair kv in paths) { - var change = new kevent { - ident = kv.Value, - filter = EventFilter.Vnode, - flags = EventFlags.Add | EventFlags.Enable | EventFlags.Clear, - fflags = FilterFlags.VNodeDelete | FilterFlags.VNodeExtend | - FilterFlags.VNodeRename | FilterFlags.VNodeAttrib | - FilterFlags.VNodeLink | FilterFlags.VNodeRevoke | - FilterFlags.VNodeWrite, - data = IntPtr.Zero, - udata = IntPtr.Zero - }; - - changes.Add (change); - outEvents.Add (new kevent ()); + if (numEvents == -1) { + var errMsg = String.Format ("kevent() error, error code = '{0}'", Marshal.GetLastWin32Error ()); + fsw.OnError (new ErrorEventArgs (new IOException (errMsg))); } - if (changes.Count > 0) { - var outArray = outEvents.ToArray (); - var changesArray = changes.ToArray (); - int numEvents = kevent (conn, changesArray, changesArray.Length, outArray, outArray.Length, IntPtr.Zero); - - for (var i = 0; i < numEvents; i++) { - var kevt = outArray [i]; - var pathData = FindPath (kevt.ident); - - if ((kevt.fflags & FilterFlags.VNodeDelete) != 0) { - removeQueue.Add (kevt.ident); - PostEvent (FileAction.Removed, pathData.Path); - } else if (((kevt.fflags & FilterFlags.VNodeRename) != 0) || ((kevt.fflags & FilterFlags.VNodeRevoke) != 0) || ((kevt.fflags & FilterFlags.VNodeWrite) != 0)) { - if (pathData.IsDirectory && Directory.Exists (pathData.Path)) - rescanQueue.Add (kevt.ident); - - if ((kevt.fflags & FilterFlags.VNodeRename) != 0) { - var fd = paths [pathData]; - var newFilename = GetFilenameFromFd (fd); - var oldFilename = pathData.Path; - - Remove (pathData); - PostEvent (FileAction.RenamedNewName, oldFilename, newFilename); - - Add (newFilename, false); - } - } else if ((kevt.fflags & FilterFlags.VNodeAttrib) != 0) { - PostEvent (FileAction.Modified, pathData.Path); - } + if (numEvents == 0) + continue; + + for (var i = 0; i < numEvents; i++) { + var kevt = eventBuffer [i]; + var pathData = fdsDict [(int)kevt.ident]; + + if ((kevt.flags & EventFlags.Error) == EventFlags.Error) { + var errMsg = String.Format ("kevent() error watching path '{0}', error code = '{1}'", pathData.Path, kevt.data); + fsw.OnError (new ErrorEventArgs (new IOException (errMsg))); + continue; } - } else { - Thread.Sleep (500); + + if ((kevt.fflags & FilterFlags.VNodeDelete) == FilterFlags.VNodeDelete || (kevt.fflags & FilterFlags.VNodeRevoke) == FilterFlags.VNodeRevoke) + removeQueue.Add (pathData); + + else if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) { + if (pathData.IsDirectory) + rescanQueue.Add (pathData.Path); + else + PostEvent (FileAction.Modified, pathData.Path); + } + + else if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) { + var newFilename = GetFilenameFromFd (pathData.Fd); + + if (newFilename.StartsWith (fsw.FullPath)) + Rename (pathData, newFilename); + else //moved outside of our watched dir so stop watching + RemoveTree (pathData); + } + + else if ((kevt.fflags & FilterFlags.VNodeAttrib) == FilterFlags.VNodeAttrib || (kevt.fflags & FilterFlags.VNodeExtend) == FilterFlags.VNodeExtend) + PostEvent (FileAction.Modified, pathData.Path); } - firstRun = false; + removeQueue.ForEach (Remove); + removeQueue.Clear (); + + rescanQueue.ForEach (path => { + Scan (path, true, ref newFds); + }); + rescanQueue.Clear (); } } - private PathData Add (string path, bool postEvents = false) + PathData Add (string path, bool postEvents, ref List fds) { + PathData pathData; + pathsDict.TryGetValue (path, out pathData); + + if (pathData != null) + return pathData; + var fd = open (path, O_EVTONLY, 0); - if (fd == -1) + if (fd == -1) { + fsw.OnError (new ErrorEventArgs (new IOException (String.Format ( + "open() error while attempting to process path '{0}', error code = '{1}'", path, Marshal.GetLastWin32Error ())))); return null; + } - var attrs = File.GetAttributes (path); - bool isDir = false; - if ((attrs & FileAttributes.Directory) == FileAttributes.Directory) - isDir = true; + try { + fds.Add (fd); - var pathData = new PathData { - Path = path, - IsDirectory = isDir - }; + var attrs = File.GetAttributes (path); - if (FindPath (path) == null) { - paths.Add (pathData, fd); + pathData = new PathData { + Path = path, + Fd = fd, + IsDirectory = (attrs & FileAttributes.Directory) == FileAttributes.Directory + }; + + pathsDict.Add (path, pathData); + fdsDict.Add (fd, pathData); if (postEvents) PostEvent (FileAction.Added, path); + + return pathData; + } catch (Exception e) { + close (fd); + fsw.OnError (new ErrorEventArgs (e)); + return null; } - return pathData; } - private void Remove (int fd) + void Remove (PathData pathData) { - var path = FindPath (fd); - paths.Remove (path); - removeQueue.Remove (fd); - - close (fd); + fdsDict.Remove (pathData.Fd); + pathsDict.Remove (pathData.Path); + close (pathData.Fd); + PostEvent (FileAction.Removed, pathData.Path); } - private void Remove (PathData pathData) + void RemoveTree (PathData pathData) { - var fd = paths [pathData]; - paths.Remove (pathData); - removeQueue.Remove (fd); + var toRemove = new List (); - close (fd); + toRemove.Add (pathData); + + if (pathData.IsDirectory) { + var prefix = pathData.Path + Path.DirectorySeparatorChar; + foreach (var path in pathsDict.Keys) + if (path.StartsWith (prefix)) { + toRemove.Add (pathsDict [path]); + } + } + toRemove.ForEach (Remove); } - private void Scan (PathData pathData, bool postEvents = false) + void Rename (PathData pathData, string newRoot) { - var path = pathData.Path; + var toRename = new List (); + var oldRoot = pathData.Path; + + toRename.Add (pathData); + + if (pathData.IsDirectory) { + var prefix = oldRoot + Path.DirectorySeparatorChar; + foreach (var path in pathsDict.Keys) + if (path.StartsWith (prefix)) + toRename.Add (pathsDict [path]); + } - Add (path, postEvents); + toRename.ForEach ((pd) => { + var oldPath = pd.Path; + var newPath = newRoot + oldPath.Substring (oldRoot.Length); + pd.Path = newPath; + pathsDict.Remove (oldPath); + pathsDict.Add (newPath, pd); + }); - if (!fsw.IncludeSubdirectories) + PostEvent (FileAction.RenamedNewName, oldRoot, newRoot); + } + + void Scan (string path, bool postEvents, ref List fds) + { + if (requestStop) + return; + + var pathData = Add (path, postEvents, ref fds); + + if (pathData == null) + return; + + if (!pathData.IsDirectory) return; - var attrs = File.GetAttributes (path); - if ((attrs & FileAttributes.Directory) == FileAttributes.Directory) { - var dirsToProcess = new List (); - dirsToProcess.Add (path); + var dirsToProcess = new List (); + dirsToProcess.Add (path); + + while (dirsToProcess.Count > 0) { + var tmp = dirsToProcess [0]; + dirsToProcess.RemoveAt (0); + + var info = new DirectoryInfo (tmp); + FileSystemInfo[] fsInfos = null; + try { + fsInfos = info.GetFileSystemInfos (); + + } catch (IOException) { + // this can happen if the directory has been deleted already. + // that's okay, just keep processing the other dirs. + fsInfos = new FileSystemInfo[0]; + } - while (dirsToProcess.Count > 0) { - var tmp = dirsToProcess [0]; - dirsToProcess.RemoveAt (0); + foreach (var fsi in fsInfos) { + if ((fsi.Attributes & FileAttributes.Directory) == FileAttributes.Directory && !fsw.IncludeSubdirectories) + continue; - var info = new DirectoryInfo (tmp); - foreach (var fsi in info.GetFileSystemInfos ()) { - if (Add (fsi.FullName, postEvents) == null) - continue; + if ((fsi.Attributes & FileAttributes.Directory) != FileAttributes.Directory && !fsw.Pattern.IsMatch (fsi.FullName)) + continue; - var childAttrs = File.GetAttributes (fsi.FullName); - if ((childAttrs & FileAttributes.Directory) == FileAttributes.Directory) - dirsToProcess.Add (fsi.FullName); - } + var currentPathData = Add (fsi.FullName, postEvents, ref fds); + + if (currentPathData != null && currentPathData.IsDirectory) + dirsToProcess.Add (fsi.FullName); } } } - - private void PostEvent (FileAction action, string path, string newPath = null) + + void PostEvent (FileAction action, string path, string newPath = null) { RenamedEventArgs renamed = null; if (action == 0) return; + // only post events that match filter pattern. check both old and new paths for renames + if (!fsw.Pattern.IsMatch (path) && (newPath == null || !fsw.Pattern.IsMatch (newPath))) + return; + if (action == FileAction.RenamedNewName) renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, "", newPath, path); @@ -388,23 +551,36 @@ private void PostEvent (FileAction action, string path, string newPath = null) private string GetFilenameFromFd (int fd) { - var sb = new StringBuilder (1024); + var sb = new StringBuilder (__DARWIN_MAXPATHLEN); - if (fcntl (fd, F_GETPATH, sb) != -1) + if (fcntl (fd, F_GETPATH, sb) != -1) { + if (fixupPath != null) + sb.Replace (fixupPath, fsw.FullPath, 0, fixupPath.Length); // see Setup() return sb.ToString (); - else + } else { + fsw.OnError (new ErrorEventArgs (new IOException (String.Format ( + "fcntl() error while attempting to get path for fd '{0}', error code = '{1}'", fd, Marshal.GetLastWin32Error ())))); return String.Empty; + } } - private const int O_EVTONLY = 0x8000; - private const int F_GETPATH = 50; - private FileSystemWatcher fsw; - private int conn; - private Thread thread; - private bool stop; - private readonly List removeQueue = new List (); - private readonly List rescanQueue = new List (); - private readonly Dictionary paths = new Dictionary (); + const int O_EVTONLY = 0x8000; + const int F_GETPATH = 50; + const int __DARWIN_MAXPATHLEN = 1024; + static readonly kevent[] emptyEventList = new System.IO.kevent[0]; + + FileSystemWatcher fsw; + int conn; + Thread thread; + volatile bool requestStop = false; + AutoResetEvent startedEvent = new AutoResetEvent (false); + bool started = false; + bool failedInit = false; + object stateLock = new object (); + + readonly Dictionary pathsDict = new Dictionary (); + readonly Dictionary fdsDict = new Dictionary (); + string fixupPath = null; [DllImport ("libc", EntryPoint="fcntl", CharSet=CharSet.Auto, SetLastError=true)] static extern int fcntl (int file_names_by_descriptor, int cmd, StringBuilder sb); @@ -419,7 +595,7 @@ private string GetFilenameFromFd (int fd) extern static int kqueue (); [DllImport ("libc")] - extern static int kevent(int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, IntPtr time); + extern static int kevent (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, [In] ref timespec time); } class KeventWatcher : IFileWatcher @@ -467,10 +643,9 @@ public void StartDispatching (FileSystemWatcher fsw) monitor = (KqueueMonitor)watches [fsw]; } else { monitor = new KqueueMonitor (fsw); + watches.Add (fsw, monitor); } - - watches.Add (fsw, monitor); - + monitor.Start (); } @@ -482,8 +657,7 @@ public void StopDispatching (FileSystemWatcher fsw) monitor.Stop (); } - - + [DllImport ("libc")] extern static int close (int fd); diff --git a/mcs/class/System/System.IO/SearchPattern.cs b/mcs/class/System/System.IO/SearchPattern.cs index 0fbab4e5e7e..f302dffaaa0 100644 --- a/mcs/class/System/System.IO/SearchPattern.cs +++ b/mcs/class/System/System.IO/SearchPattern.cs @@ -47,7 +47,7 @@ public SearchPattern2 (string pattern, bool ignore) Compile (pattern); } - // OSX has a retarded case-insensitive yet case-aware filesystem + // OSX has a case-insensitive yet case-aware filesystem // so we need a overload in here for the Kqueue watcher public bool IsMatch (string text, bool ignorecase) { @@ -55,20 +55,17 @@ public bool IsMatch (string text, bool ignorecase) bool match = String.Compare (pattern, text, ignorecase) == 0; if (match) return true; - - // This is a special case for FSW. It needs to match e.g. subdir/file.txt - // when the pattern is "file.txt" - int idx = text.LastIndexOf ('/'); - if (idx == -1) - return false; - idx++; - if (idx == text.Length) - return false; - - return (String.Compare (pattern, text.Substring (idx), ignorecase) == 0); } + + // This is a special case for FSW. It needs to match e.g. subdir/file.txt + // when the pattern is "file.txt" + var fileName = Path.GetFileName (text); + + if (!hasWildcard) + return (String.Compare (pattern, fileName, ignorecase) == 0); + - return Match (ops, text, 0); + return Match (ops, fileName, 0); } public bool IsMatch (string text) From 328defdcdea4b9d42d8ae3dcacd4a3b68696ab1b Mon Sep 17 00:00:00 2001 From: Stephen McConnel Date: Tue, 28 Oct 2014 12:10:43 -0500 Subject: [PATCH 482/543] Zero out pointers to freed memory in AudioDevice This fixes https://bugzilla.xamarin.com/show_bug.cgi?id=24109. --- mcs/class/System/System.Media/AudioDevice.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mcs/class/System/System.Media/AudioDevice.cs b/mcs/class/System/System.Media/AudioDevice.cs index 628c04d8edd..a1d0896dba6 100644 --- a/mcs/class/System/System.Media/AudioDevice.cs +++ b/mcs/class/System/System.Media/AudioDevice.cs @@ -200,6 +200,8 @@ protected virtual void Dispose (bool disposing) { snd_pcm_hw_params_free (hw_param); if (handle != IntPtr.Zero) snd_pcm_close (handle); + sw_param = IntPtr.Zero; + hw_param = IntPtr.Zero; handle = IntPtr.Zero; } @@ -278,10 +280,14 @@ public override bool SetFormat (AudioFormat format, int channels, int rate) { Console.WriteLine ("failed to alloc Alsa sw param struct"); } - if (hw_param != IntPtr.Zero) + if (hw_param != IntPtr.Zero) { snd_pcm_hw_params_free (hw_param); // free hw params - if (sw_param != IntPtr.Zero) + hw_param = IntPtr.Zero; + } + if (sw_param != IntPtr.Zero) { snd_pcm_sw_params_free (sw_param); // free sw params + sw_param = IntPtr.Zero; + } return alsa_err == 0; } From 872e97cb30cc9e9f827d6540ca327ee8869dda33 Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Tue, 28 Oct 2014 14:48:45 -0400 Subject: [PATCH 483/543] Add OP_LREM_IMM support;Add implementation of mono_arch_get_delegate_virtual_invoke_impl --- mono/mini/cpu-s390x.md | 1 + mono/mini/decompose.c | 4 ++++ mono/mini/mini-s390x.c | 50 ++++++++++++++++++++++++++++++++++----- mono/mini/support-s390x.h | 6 ++++- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/mono/mini/cpu-s390x.md b/mono/mini/cpu-s390x.md index b3dce352ec6..2eee2e4e57d 100644 --- a/mono/mini/cpu-s390x.md +++ b/mono/mini/cpu-s390x.md @@ -283,6 +283,7 @@ long_xor: dest:i src1:i src2:i len:8 long_neg: dest:i src1:i len:6 long_not: dest:i src1:i len:12 long_rem: dest:i src1:i src2:i len:12 +long_rem_imm: dest:i src1:i src2:i len:12 long_rem_un: dest:i src1:i src2:i len:16 long_shl: dest:i src1:i src2:i len:14 long_shl_imm: dest:i src1:i len:14 diff --git a/mono/mini/decompose.c b/mono/mini/decompose.c index 6e9d4aaef71..f29e913acf9 100644 --- a/mono/mini/decompose.c +++ b/mono/mini/decompose.c @@ -486,6 +486,9 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) ins->opcode = OP_ICONST; MONO_INST_NULLIFY_SREGS (ins); ins->inst_c0 = 0; +#if __s390__ + } +#else } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1)) { gboolean is_long = ins->opcode == OP_LREM_IMM; int compensator_reg = alloc_ireg (cfg); @@ -511,6 +514,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) NULLIFY_INS (ins); } +#endif break; } diff --git a/mono/mini/mini-s390x.c b/mono/mini/mini-s390x.c index 435ef2904a4..d84c87860d1 100644 --- a/mono/mini/mini-s390x.c +++ b/mono/mini/mini-s390x.c @@ -624,7 +624,7 @@ indent (int diff) { if (diff < 0) indent_level += diff; v = indent_level; - printf("%p [%3d] ",pthread_self(),v); + printf("%p [%3d] ",(void *)pthread_self(),v); while (v-- > 0) { printf (". "); } @@ -2798,6 +2798,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) case OP_IREM_UN_IMM: case OP_LAND_IMM: case OP_LOR_IMM: + case OP_LREM_IMM: case OP_LXOR_IMM: case OP_LOCALLOC_IMM: mono_decompose_op_imm (cfg, bb, ins); @@ -3312,6 +3313,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_lgr (code, ins->dreg, s390_r0); break; } + case OP_LREM_IMM: { + if (s390_is_imm16 (ins->inst_imm)) { + s390_lghi (code, s390_r13, ins->inst_imm); + } else { + s390_lgfi (code, s390_r13, ins->inst_imm); + } + s390_lgr (code, s390_r0, ins->sreg1); + s390_dsgr (code, s390_r0, s390_r13); + s390_lgfr (code, ins->dreg, s390_r0); + } + break; case OP_LREM_UN: { s390_lgr (code, s390_r1, ins->sreg1); s390_lghi (code, s390_r0, 0); @@ -5735,9 +5747,35 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe /*------------------------------------------------------------------*/ gpointer -mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg) +mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, + int offset, gboolean load_imt_reg) { - return NULL; + guint8 *code, *start; + int size = 20; + + start = code = mono_global_codeman_reserve (size); + + /* + * Replace the "this" argument with the target + */ + s390_lgr (code, s390_r1, s390_r2); + s390_lg (code, s390_r2, s390_r1, 0, MONO_STRUCT_OFFSET(MonoDelegate, target)); + + /* + * Load the IMT register, if needed + */ + if (load_imt_reg) { + s390_lg (code, MONO_ARCH_IMT_REG, s390_r2, 0, MONO_STRUCT_OFFSET(MonoDelegate, method)); + } + + /* + * Load the vTable + */ + s390_lg (code, s390_r1, s390_r2, 0, MONO_STRUCT_OFFSET(MonoObject, vtable)); + s390_agfi(code, s390_r1, offset); + s390_br (code, s390_r1); + + return(start); } /*========================= End of Function ========================*/ @@ -5833,7 +5871,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, s390_lg (code, s390_r1, 0, s390_r1, 0); } s390_br (code, s390_r1); - target = S390_RELATIVE(code, item->jmp_code); + target = (gint64) S390_RELATIVE(code, item->jmp_code); s390_patch_rel(item->jmp_code+2, target); S390_SET (code, s390_r1, fail_tramp); s390_br (code, s390_r1); @@ -5863,7 +5901,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, if (item->jmp_code) { if (item->check_target_idx) { gint64 offset; - offset = S390_RELATIVE(imt_entries [item->check_target_idx]->code_target, + offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target, item->jmp_code); s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset); } @@ -5932,7 +5970,7 @@ mono_arch_get_cie_program (void) { GSList *l = NULL; - mono_add_unwind_op_def_cfa (l, NULL, NULL, STK_BASE, 0); + mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0); return(l); } diff --git a/mono/mini/support-s390x.h b/mono/mini/support-s390x.h index 62edcc4e7e9..f93dc88c0c6 100644 --- a/mono/mini/support-s390x.h +++ b/mono/mini/support-s390x.h @@ -4,8 +4,12 @@ #define S390_SET(loc, dr, v) \ do { \ guint64 val = (guint64) v; \ - if (s390_is_uimm16(val)) { \ + if (s390_is_imm16(val)) { \ + s390_lghi(loc, dr, val); \ + } else if (s390_is_uimm16(val)) { \ s390_llill(loc, dr, val); \ + } else if (s390_is_imm32(val)) { \ + s390_lgfi(loc, dr, val); \ } else if (s390_is_uimm32(val)) { \ s390_llilf(loc, dr, val); \ } else { \ From 7e8a11f8880ed5310b7d6ad20aa1827b2e92155d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 28 Oct 2014 17:07:11 -0400 Subject: [PATCH 484/543] [runtime] Disable the check for overlapping reference and non-reference fields, too much code depends on this to work. --- mono/metadata/class.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 519eec9a191..e9ff58249ef 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -2013,10 +2013,13 @@ mono_class_layout_fields (MonoClass *class) if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; + // FIXME: Too much code does this +#if 0 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) { char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset); mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg); } +#endif } g_free (ref_bitmap); } From 2e8f21d4f2402516b81ed42aacf0f1d43103621e Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 28 Oct 2014 23:30:44 -0400 Subject: [PATCH 485/543] [llvm] Fix a regression caused by 6ec1ebf99078a996ca16fd0c56cbd4e96e32ed41. Do the direct call rewrite only if the caller and callee signature matches. --- mono/mini/mini-llvm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index 2b778c3aaab..f3bb3ac33c7 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -5390,7 +5390,8 @@ mono_llvm_emit_aot_module (const char *filename, int got_size) LLVMValueRef lmethod; lmethod = g_hash_table_lookup (module->method_to_lmethod, ji->data.method); - if (lmethod) { + /* The types might not match because the caller might pass an rgctx */ + if (lmethod && LLVMTypeOf (callee) == LLVMTypeOf (lmethod)) { mono_llvm_replace_uses_of (callee, lmethod); mono_aot_mark_unused_llvm_plt_entry (ji); } From 41981cdca12b15e7ee25b1b145db1c8b150b051b Mon Sep 17 00:00:00 2001 From: Alex J Lennon Date: Wed, 29 Oct 2014 14:27:01 +0100 Subject: [PATCH 486/543] [libgc] Eliminate warning about redefinition of GC_WIN32_THREADS Makefile defines GC_WIN32_THREADS as 1 but gc_config_macros was redefining as defined but with no value. Signed-off-by: Alex J Lennon --- libgc/include/gc_config_macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgc/include/gc_config_macros.h b/libgc/include/gc_config_macros.h index c11caa7748e..caf8de527c3 100644 --- a/libgc/include/gc_config_macros.h +++ b/libgc/include/gc_config_macros.h @@ -32,7 +32,7 @@ # define GC_LINUX_THREADS #endif #if defined(WIN32_THREADS) -# define GC_WIN32_THREADS +# define GC_WIN32_THREADS 1 #endif #if defined(USE_LD_WRAP) # define GC_USE_LD_WRAP From dcdc8414df2cb881392b13bb9b39899590f72858 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 29 Oct 2014 12:55:31 -0400 Subject: [PATCH 487/543] [llvm] Disable the extension of i8/i16 arguments to i32 on arm64, since the ios calling convention passes them differently than i32. Fixes #22800. --- mono/mini/mini-llvm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index f3bb3ac33c7..28e76665e16 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -420,6 +420,7 @@ type_is_unsigned (EmitContext *ctx, MonoType *t) switch (t->type) { case MONO_TYPE_U1: case MONO_TYPE_U2: + case MONO_TYPE_CHAR: case MONO_TYPE_U4: case MONO_TYPE_U8: return TRUE; @@ -437,7 +438,12 @@ static LLVMTypeRef type_to_llvm_arg_type (EmitContext *ctx, MonoType *t) { LLVMTypeRef ptype = type_to_llvm_type (ctx, t); - + + /* + * This works on all abis except arm64/ios which passes multiple + * arguments in one stack slot. + */ +#ifndef TARGET_ARM64 if (ptype == LLVMInt8Type () || ptype == LLVMInt16Type ()) { /* * LLVM generates code which only sets the lower bits, while JITted @@ -445,6 +451,7 @@ type_to_llvm_arg_type (EmitContext *ctx, MonoType *t) */ ptype = LLVMInt32Type (); } +#endif return ptype; } @@ -1817,7 +1824,7 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], ""); } } else { - ctx->values [reg] = convert (ctx, ctx->values [reg], llvm_type_to_stack_type (type_to_llvm_type (ctx, sig->params [i]))); + ctx->values [reg] = convert_full (ctx, ctx->values [reg], llvm_type_to_stack_type (type_to_llvm_type (ctx, sig->params [i])), type_is_unsigned (ctx, sig->params [i])); } } From d5853815554a3dca0f5fabc802a72c7c26e1c137 Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Wed, 29 Oct 2014 13:16:04 -0400 Subject: [PATCH 488/543] Bump Mono version -> 3.12.1 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 7e8f26199ad..664808a4977 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # Process this file with autoconf to produce a configure script. #AC_PREREQ([2.62]) -AC_INIT(mono, [3.10.1], +AC_INIT(mono, [3.12.1], [http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono]) AC_CONFIG_SRCDIR([README.md]) From 6a738caa5a156fb60275aeb9f5dc47bd2c9290c2 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 29 Oct 2014 17:08:42 -0400 Subject: [PATCH 489/543] [corlib] Add some missing memory barriers to the ConcurrentQueue methods to order memory operations. Fixes #22788. --- .../System.Collections.Concurrent/ConcurrentQueue.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mcs/class/corlib/System.Collections.Concurrent/ConcurrentQueue.cs b/mcs/class/corlib/System.Collections.Concurrent/ConcurrentQueue.cs index ea8984394b4..958fc615359 100644 --- a/mcs/class/corlib/System.Collections.Concurrent/ConcurrentQueue.cs +++ b/mcs/class/corlib/System.Collections.Concurrent/ConcurrentQueue.cs @@ -63,7 +63,7 @@ public void Enqueue (T item) { Node node = new Node (); node.Value = item; - + Node oldTail = null; Node oldNext = null; @@ -71,6 +71,8 @@ public void Enqueue (T item) while (!update) { oldTail = tail; oldNext = oldTail.Next; + + Thread.MemoryBarrier (); // Did tail was already updated ? if (tail == oldTail) { @@ -104,6 +106,8 @@ public bool TryDequeue (out T result) Node oldHead = head; Node oldTail = tail; oldNext = oldHead.Next; + + Thread.MemoryBarrier (); if (oldHead == head) { // Empty case ? @@ -146,6 +150,8 @@ public bool TryPeek (out T result) } result = oldNext.Value; + + Thread.MemoryBarrier (); //check if head has been updated update = head != oldHead; From ac1dcc6adefd4887543cd73612580aca2497c543 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 30 Oct 2014 12:33:33 -0400 Subject: [PATCH 490/543] [System.Core/Android] Update TimeZone database self test. Add Makefile rules to automagically download the TimeZone database from the Android target $(ADB_TARGET), and build the tzi.exe app. $ make android-dump-tzdata ADB_TARGET=-d # downloads timezone data into ./android/tzdb. # dumps timezone data into ./android/tzdata # builds ./tzi.exe # Show adjustment rules for a given timezone dump $ mono tzi.exe -i=tzdata/Asia/Amman Add `tzi.exe -R` option to show the TimeZoneInfo.GetAdjustmentRules() output for all encountered timezones. Add `tzi.exe -o=PATH` option to dump the TimeZone data to disk for interrogation. Add `tzi.exe -i=PATH` option to read in the specified TimeZone data file and dump the rules contained therein. Update usage comments. --- mcs/class/System.Core/Makefile | 19 +++++ .../System/TimeZoneInfo.Android.cs | 78 ++++++++++++++++++- 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/mcs/class/System.Core/Makefile b/mcs/class/System.Core/Makefile index f8cc33c7e8b..eeca6391a14 100644 --- a/mcs/class/System.Core/Makefile +++ b/mcs/class/System.Core/Makefile @@ -72,3 +72,22 @@ csproj-local: $(MAKE) csproj-local intermediate=plaincore/ endif endif + +# +# Android TimeZoneInfo testing.... +# + +tzi.exe: ../corlib/System/AndroidPlatform.cs $(wildcard System/TimeZone*.cs) ../../build/common/Consts.cs ../Mono.Options/Mono.Options/Options.cs + mcs /debug+ /out:$@ /unsafe "/d:INSIDE_CORLIB;MONODROID;NET_4_0;LIBC;SELF_TEST" $^ + +android-pull-tzdb: + mkdir -p android/tzdb/usr/share/zoneinfo + mkdir -p android/tzdb/misc/zoneinfo/zoneinfo + android_root=`adb shell echo '$$ANDROID_ROOT' | tr -d "\r"` ; \ + android_data=`adb shell echo '$$ANDROID_DATA' | tr -d "\r"` ; \ + adb $(ADB_TARGET) pull $$android_root/usr/share/zoneinfo android/tzdb/usr/share/zoneinfo ; \ + adb $(ADB_TARGET) pull $$android_data/misc/zoneinfo/tzdata android/tzdb/misc/zoneinfo + mkdir -p android/tzdb/ + +android-dump-tzdata: tzi.exe android-pull-tzdb + __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe -o android/tzdata diff --git a/mcs/class/System.Core/System/TimeZoneInfo.Android.cs b/mcs/class/System.Core/System/TimeZoneInfo.Android.cs index 079af3722d6..72285cc0dab 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.Android.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.Android.cs @@ -246,6 +246,7 @@ public byte[] GetTimeZoneData (string id) tzdataPath, offset, length, r, buffer.Length)); } + TimeZoneInfo.DumpTimeZoneDataToFile (id, buffer); return buffer; } } @@ -581,21 +582,37 @@ static string GetDefaultTimeZoneName () * Compile: * mcs /debug+ /out:tzi.exe /unsafe "/d:INSIDE_CORLIB;MONODROID;NET_4_0;LIBC;SELF_TEST" ../corlib/System/AndroidPlatform.cs System/TimeZone*.cs ../../build/common/Consts.cs ../Mono.Options/Mono.Options/Options.cs * Prep: - * mkdir -p usr/share/zoneinfo - * mkdir -p misc/zoneinfo/zoneinfo + * mkdir -p android/tzdb/usr/share/zoneinfo + * mkdir -p android/tzdb/misc/zoneinfo/zoneinfo * android_root=`adb shell echo '$ANDROID_ROOT' | tr -d "\r"` * android_data=`adb shell echo '$ANDROID_DATA' | tr -d "\r"` - * adb pull $android_root/usr/share/zoneinfo usr/share/zoneinfo - * adb pull $android_data/misc/zoneinfo/tzdata misc/zoneinfo + * adb pull $android_root/usr/share/zoneinfo android/tzdb/usr/share/zoneinfo + * adb pull $android_data/misc/zoneinfo/tzdata android/tzdb/misc/zoneinfo * Run: + * # Dump all timezone names * __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe --offset=1969-01-01 + * + * # Dump TimeZone data to files under path `tzdata` + * __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe -o android/tzdata + * + * # Dump TimeZone rules for specific timezone data (as dumped above) + * mono tzi.exe --offset=2012-10-24 -i=tzdata/Asia/Amman */ static void Main (string[] args) { DateTime? offset = null; Func c = () => GetDefaultTimeZoneDB (); + bool dump_rules = false; Mono.Options.OptionSet p = null; p = new Mono.Options.OptionSet () { + { "i=", + "TimeZone data {FILE} to parse and dump", + v => DumpTimeZoneFile (v, offset) + }, + { "o=", + "Write TimeZone data files to {PATH}", + v => TimeZoneInfo.TimeZoneDataExportPath = v + }, { "T=", "Create AndroidTzData from {PATH}.", v => { c = () => new AndroidTzData (v); } }, @@ -606,6 +623,9 @@ static void Main (string[] args) offset = DateTime.Parse (v); Console.WriteLine ("Using DateTime Offset: {0}", offset); } }, + { "R|dump-rules", + "Show timezone info offset for DateTime {OFFSET}.", + v => dump_rules = v != null }, { "help", "Show this message and exit", v => { p.WriteOptionDescriptions (Console.Out); Environment.Exit (0); @@ -623,6 +643,9 @@ static void Main (string[] args) if (offset.HasValue) { Console.Write ("From Offset: {0}", zone.GetUtcOffset (offset.Value)); } + if (dump_rules) { + WriteZoneRules (zone); + } } else { Console.Write (" ERROR:null"); @@ -634,6 +657,53 @@ static void Main (string[] args) Console.WriteLine (); } } + + static void WriteZoneRules (TimeZoneInfo zone) + { + var rules = zone.GetAdjustmentRules (); + for (int i = 0; i < rules.Length; ++i) { + var rule = rules [i]; + Console.WriteLine (); + Console.Write ("\tAdjustmentRules[{0,3}]: DaylightDelta={1}; DateStart={2:yyyy-MM}; DateEnd={3:yyyy-MM}; DaylightTransitionStart={4:D2}-{5:D2}T{6}; DaylightTransitionEnd={7:D2}-{8:D2}T{9}", + i, + rule.DaylightDelta, + rule.DateStart, rule.DateEnd, + rule.DaylightTransitionStart.Month, rule.DaylightTransitionStart.Day, rule.DaylightTransitionStart.TimeOfDay.TimeOfDay, + rule.DaylightTransitionEnd.Month, rule.DaylightTransitionEnd.Day, rule.DaylightTransitionEnd.TimeOfDay.TimeOfDay); + } + } + + static void DumpTimeZoneFile (string path, DateTime? time) + { + var buffer = File.ReadAllBytes (path); + var zone = ParseTZBuffer (path, buffer, buffer.Length); + Console.Write ("Rules for: {0}", path); + WriteZoneRules (zone); + Console.WriteLine (); + if (time.HasValue) { + var offset = zone.GetUtcOffset (time.Value); + var isDst = zone.IsDaylightSavingTime (time.Value); + Console.WriteLine ("\tDate({0}): Offset({1}) IsDST({2})", time.Value, offset, isDst); + } + } +#endif + } + +#if SELF_TEST + static string TimeZoneDataExportPath; +#endif + + internal static void DumpTimeZoneDataToFile (string id, byte[] buffer) + { +#if SELF_TEST + int p = id.LastIndexOf ('/'); + var o = Path.Combine (TimeZoneDataExportPath, + p >= 0 ? id.Substring (0, p) : id); + if (p >= 0) + o = Path.Combine (o, id.Substring (p+1)); + Directory.CreateDirectory (Path.GetDirectoryName (o)); + using (var f = File.OpenWrite (o)) + f.Write (buffer, 0, buffer.Length); #endif } } From 112079b844ae91cbf592292041a52947c4974b65 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Thu, 30 Oct 2014 13:54:33 -0400 Subject: [PATCH 491/543] Revert this patch, as it broke the test suite --- .../System.IdentityModel-net_4_5.csproj | 33 +++++------- .../SecurityTokenExpiredException.cs | 54 ------------------- .../SecurityTokenNotYetValidException.cs | 54 ------------------- .../SecurityTokenReplayDetectedException.cs | 54 ------------------- .../System.IdentityModel.dll.sources | 6 +-- .../SignatureVerificationFailedException.cs | 54 ------------------- .../JavaScriptSerializer.cs | 7 +-- .../JsonDeserializer.cs | 4 +- .../JavaScriptSerializerTest.cs | 16 ------ .../corlib/System.Security.Claims/Claim.cs | 5 +- 10 files changed, 19 insertions(+), 268 deletions(-) delete mode 100644 mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs delete mode 100644 mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs delete mode 100644 mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs delete mode 100644 mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs diff --git a/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj b/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj index 1e07337738e..3022c52ab5b 100644 --- a/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj +++ b/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj @@ -50,7 +50,6 @@ - @@ -148,12 +147,9 @@ - - + - - @@ -174,8 +170,7 @@ - - + - - - - - - - - - - - + + + + + + + + + + + @@ -241,4 +236,4 @@ - + diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs deleted file mode 100644 index 2f10c949029..00000000000 --- a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// SecurityTokenExpiredException.cs -// -// Author: -// Noesis Labs (Ryan.Melena@noesislabs.com) -// -// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -#if NET_4_5 - -using System; -using System.Runtime.Serialization; - -namespace System.IdentityModel.Tokens -{ - public class SecurityTokenExpiredException : SecurityTokenValidationException - { - public SecurityTokenExpiredException() - : base("ID4181: The security token has expired.") - { } - - public SecurityTokenExpiredException(string message) - : base(message) - { } - - public SecurityTokenExpiredException(string message, Exception innerException) - : base(message, innerException) - { } - - public SecurityTokenExpiredException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } -} -#endif diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs deleted file mode 100644 index 9f15b7b6448..00000000000 --- a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// SecurityTokenNotYetValidException.cs -// -// Author: -// Noesis Labs (Ryan.Melena@noesislabs.com) -// -// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -#if NET_4_5 - -using System; -using System.Runtime.Serialization; - -namespace System.IdentityModel.Tokens -{ - public class SecurityTokenNotYetValidException : SecurityTokenValidationException - { - public SecurityTokenNotYetValidException() - : base("ID4182: The security token is not valid yet.") - { } - - public SecurityTokenNotYetValidException(string message) - : base(message) - { } - - public SecurityTokenNotYetValidException(string message, Exception innerException) - : base(message, innerException) - { } - - public SecurityTokenNotYetValidException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } -} -#endif diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs deleted file mode 100644 index eb4a786b336..00000000000 --- a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// SecurityTokenReplayDetectedException.cs -// -// Author: -// Noesis Labs (Ryan.Melena@noesislabs.com) -// -// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -#if NET_4_5 - -using System; -using System.Runtime.Serialization; - -namespace System.IdentityModel.Tokens -{ - public class SecurityTokenReplayDetectedException : SecurityTokenValidationException - { - public SecurityTokenReplayDetectedException() - : base("ID1070: Replay has been detected for a SecurityToken.") - { } - - public SecurityTokenReplayDetectedException(string message) - : base(message) - { } - - public SecurityTokenReplayDetectedException(string message, Exception innerException) - : base(message, innerException) - { } - - public SecurityTokenReplayDetectedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } -} -#endif diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources b/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources index 4d705d24d57..2c86355259a 100755 --- a/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources +++ b/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources @@ -3,7 +3,6 @@ Assembly/AssemblyInfo.cs System.IdentityModel/CookieTransform.cs System.IdentityModel/OpenObject.cs -System.IdentityModel/SignatureVerificationFailedException.cs System.IdentityModel.Claims/Claim.cs System.IdentityModel.Claims/ClaimSet.cs System.IdentityModel.Claims/ClaimTypes.cs @@ -101,12 +100,9 @@ System.IdentityModel.Tokens/SecurityKeyUsage.cs System.IdentityModel.Tokens/SecurityToken.cs System.IdentityModel.Tokens/SecurityTokenDescriptor.cs System.IdentityModel.Tokens/SecurityTokenException.cs -System.IdentityModel.Tokens/SecurityTokenExpiredException.cs System.IdentityModel.Tokens/SecurityTokenHandler.cs System.IdentityModel.Tokens/SecurityTokenHandlerCollection.cs System.IdentityModel.Tokens/SecurityTokenHandlerConfiguration.cs -System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs -System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs System.IdentityModel.Tokens/SecurityTokenTypes.cs System.IdentityModel.Tokens/SecurityTokenValidationException.cs System.IdentityModel.Tokens/SessionSecurityToken.cs @@ -128,4 +124,4 @@ System.IdentityModel.Tokens/X509SubjectKeyIdentifierClause.cs System.IdentityModel.Tokens/X509ThumbprintKeyIdentifierClause.cs System.IdentityModel.Tokens/X509WindowsSecurityToken.cs System.Security.Claims/AuthenticationTypes.cs -System.ServiceModel.Security/X509CertificateValidationMode.cs +System.ServiceModel.Security/X509CertificateValidationMode.cs \ No newline at end of file diff --git a/mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs b/mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs deleted file mode 100644 index 2e1e7115ca9..00000000000 --- a/mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// SignatureVerificationFailedException.cs -// -// Author: -// Noesis Labs (Ryan.Melena@noesislabs.com) -// -// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -#if NET_4_5 - -using System; -using System.Runtime.Serialization; - -namespace System.IdentityModel -{ - public class SignatureVerificationFailedException : Exception - { - public SignatureVerificationFailedException() - : base("ID4038: Signature verification failed.") - { } - - public SignatureVerificationFailedException(string message) - : base(message) - { } - - public SignatureVerificationFailedException(string message, Exception innerException) - : base(message, innerException) - { } - - public SignatureVerificationFailedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } -} -#endif diff --git a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs index 6a147e2e03e..14a03b2f0dc 100644 --- a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs +++ b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs @@ -204,12 +204,7 @@ public T Deserialize (string input) { } public object Deserialize (string input, Type targetType) { - object obj = DeserializeObjectInternal (input); - - if (obj == null) - return Activator.CreateInstance (targetType); - - return ConvertToType (obj, targetType); + return DeserializeObjectInternal (input); } static object Evaluate (object value) { diff --git a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs index 8593e532bf0..46bef52a7b4 100644 --- a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs +++ b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs @@ -833,7 +833,7 @@ bool ProcessCharacter (char ch) void CreateArray () { - var arr = new List (); + var arr = new ArrayList (); PushObject (arr); } @@ -865,7 +865,7 @@ void StoreValue (object o) { Dictionary dict = PeekObject () as Dictionary ; if (dict == null) { - List arr = PeekObject () as List ; + ArrayList arr = PeekObject () as ArrayList; if (arr == null) throw new InvalidOperationException ("Internal error: current object is not a dictionary or an array."); arr.Add (o); diff --git a/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs b/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs index 8274ef9c3f8..995590eeb2e 100644 --- a/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs +++ b/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs @@ -415,22 +415,6 @@ public void TestDeserialize () { //object oo = ser.DeserializeObject ("{value:'Purple\\r \\n monkey\\'s:\\tdishwasher'}"); } - [Test] - public void TestDeserializeNonGenericOverload() - { - JavaScriptSerializer ser = new JavaScriptSerializer(); - Assert.IsNull(ser.Deserialize("", typeof(X))); - - X s = new X(); - s.Init(); - string x = ser.Serialize(s); - - Assert.AreEqual("{\"z\":8,\"ch\":\"v\",\"ch_null\":null,\"str\":\"vwF59g\",\"b\":253,\"sb\":-48,\"sh\":-32740,\"ush\":65511,\"i\":-234235453,\"ui\":4294733061,\"l\":-9223372036854775780,\"ul\":18446744073709551612,\"f\":NaN,\"f1\":-Infinity,\"f2\":Infinity,\"f3\":-3.40282347E+38,\"f4\":3.40282347E+38,\"d\":NaN,\"d1\":-Infinity,\"d2\":Infinity,\"d3\":-1.7976931348623157E+308,\"d4\":1.7976931348623157E+308,\"de\":-1,\"de1\":0,\"de2\":1,\"de3\":-79228162514264337593543950335,\"de4\":79228162514264337593543950335,\"g\":\"000000ea-0002-0162-0102-030405060708\",\"nb\":null,\"dbn\":null,\"uri\":\"http://kostat@mainsoft/adfasdf/asdfasdf.aspx/asda/ads?a=b&c=d\",\"hash\":{\"mykey\":{\"BB\":10}},\"point\":{\"IsEmpty\":false,\"X\":150,\"Y\":150},\"MyEnum\":[1,10,345],\"MyEnum1\":[1,10,345],\"AA\":5,\"AA1\":[{\"BB\":10},{\"BB\":10}],\"BB\":18446744073709551610,\"YY\":[{\"BB\":10},{\"BB\":10}]}", x, "#A1"); - - X n = ser.Deserialize(x, typeof(X)) as X; - Assert.AreEqual(s, n, "#A2"); - } - [Test] public void TestDeserializeTypeResolver () { diff --git a/mcs/class/corlib/System.Security.Claims/Claim.cs b/mcs/class/corlib/System.Security.Claims/Claim.cs index 0347052d236..ffb7ce73449 100644 --- a/mcs/class/corlib/System.Security.Claims/Claim.cs +++ b/mcs/class/corlib/System.Security.Claims/Claim.cs @@ -58,9 +58,6 @@ public Claim (string type, string value, string valueType, string issuer, string throw new ArgumentNullException ("type"); if (value == null) throw new ArgumentNullException ("value"); - - Properties = new Dictionary (); - Type = type; Value = value; ValueType = valueType == null ? ClaimValueTypes.String : valueType; @@ -94,4 +91,4 @@ public override string ToString () } } } -#endif +#endif \ No newline at end of file From f269254917ea7362bf8248e121303b4756ed6834 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 30 Oct 2014 14:39:38 -0400 Subject: [PATCH 492/543] [Mono.Data.Tds] Allow sending of text data longer than 4000 characters by using a different column type. Fixes #21172. --- .../Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs index 991727bbc00..2f4fef03e19 100644 --- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs +++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds70.cs @@ -489,6 +489,19 @@ protected void ExecRPC (TdsRpcProcId rpcId, string sql, Comm.Append ((byte) 0x00); // no param meta data name Comm.Append ((byte) 0x00); // no status flags + + // Convert BigNVarChar values larger than 4000 chars to nvarchar(max) + // Need to do this here so WritePreparedParameterInfo emit the + // correct data type + foreach (TdsMetaParameter param2 in parameters) { + var colType = param2.GetMetaType (); + + if (colType == TdsColumnType.BigNVarChar) { + int size = param2.GetActualSize (); + if ((size >> 1) > 4000) + param2.Size = -1; + } + } // Write sql as a parameter value - UCS2 TdsMetaParameter param = new TdsMetaParameter ("sql", From 6af798962810054fcf68f8e597de56b6490271a2 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Thu, 30 Oct 2014 16:18:59 -0400 Subject: [PATCH 493/543] Re-apply the patch, there isa fix for it --- .../System.IdentityModel-net_4_5.csproj | 33 +++++++++++-------- .../System.IdentityModel.dll.sources | 6 +++- .../JavaScriptSerializer.cs | 7 +++- .../JsonDeserializer.cs | 4 +-- .../JavaScriptSerializerTest.cs | 16 +++++++++ .../corlib/System.Security.Claims/Claim.cs | 5 ++- 6 files changed, 52 insertions(+), 19 deletions(-) diff --git a/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj b/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj index 3022c52ab5b..1e07337738e 100644 --- a/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj +++ b/mcs/class/System.IdentityModel/System.IdentityModel-net_4_5.csproj @@ -50,6 +50,7 @@ + @@ -147,9 +148,12 @@ - + + + + @@ -170,7 +174,8 @@ - + + - - - - - - + + + + + + + + + + + - - - - - @@ -236,4 +241,4 @@ - + diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources b/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources index 2c86355259a..4d705d24d57 100755 --- a/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources +++ b/mcs/class/System.IdentityModel/System.IdentityModel.dll.sources @@ -3,6 +3,7 @@ Assembly/AssemblyInfo.cs System.IdentityModel/CookieTransform.cs System.IdentityModel/OpenObject.cs +System.IdentityModel/SignatureVerificationFailedException.cs System.IdentityModel.Claims/Claim.cs System.IdentityModel.Claims/ClaimSet.cs System.IdentityModel.Claims/ClaimTypes.cs @@ -100,9 +101,12 @@ System.IdentityModel.Tokens/SecurityKeyUsage.cs System.IdentityModel.Tokens/SecurityToken.cs System.IdentityModel.Tokens/SecurityTokenDescriptor.cs System.IdentityModel.Tokens/SecurityTokenException.cs +System.IdentityModel.Tokens/SecurityTokenExpiredException.cs System.IdentityModel.Tokens/SecurityTokenHandler.cs System.IdentityModel.Tokens/SecurityTokenHandlerCollection.cs System.IdentityModel.Tokens/SecurityTokenHandlerConfiguration.cs +System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs +System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs System.IdentityModel.Tokens/SecurityTokenTypes.cs System.IdentityModel.Tokens/SecurityTokenValidationException.cs System.IdentityModel.Tokens/SessionSecurityToken.cs @@ -124,4 +128,4 @@ System.IdentityModel.Tokens/X509SubjectKeyIdentifierClause.cs System.IdentityModel.Tokens/X509ThumbprintKeyIdentifierClause.cs System.IdentityModel.Tokens/X509WindowsSecurityToken.cs System.Security.Claims/AuthenticationTypes.cs -System.ServiceModel.Security/X509CertificateValidationMode.cs \ No newline at end of file +System.ServiceModel.Security/X509CertificateValidationMode.cs diff --git a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs index 14a03b2f0dc..6a147e2e03e 100644 --- a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs +++ b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs @@ -204,7 +204,12 @@ public T Deserialize (string input) { } public object Deserialize (string input, Type targetType) { - return DeserializeObjectInternal (input); + object obj = DeserializeObjectInternal (input); + + if (obj == null) + return Activator.CreateInstance (targetType); + + return ConvertToType (obj, targetType); } static object Evaluate (object value) { diff --git a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs index 46bef52a7b4..8593e532bf0 100644 --- a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs +++ b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs @@ -833,7 +833,7 @@ bool ProcessCharacter (char ch) void CreateArray () { - var arr = new ArrayList (); + var arr = new List (); PushObject (arr); } @@ -865,7 +865,7 @@ void StoreValue (object o) { Dictionary dict = PeekObject () as Dictionary ; if (dict == null) { - ArrayList arr = PeekObject () as ArrayList; + List arr = PeekObject () as List ; if (arr == null) throw new InvalidOperationException ("Internal error: current object is not a dictionary or an array."); arr.Add (o); diff --git a/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs b/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs index 995590eeb2e..8274ef9c3f8 100644 --- a/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs +++ b/mcs/class/System.Web.Extensions/Test/System.Web.Script.Serialization/JavaScriptSerializerTest.cs @@ -415,6 +415,22 @@ public void TestDeserialize () { //object oo = ser.DeserializeObject ("{value:'Purple\\r \\n monkey\\'s:\\tdishwasher'}"); } + [Test] + public void TestDeserializeNonGenericOverload() + { + JavaScriptSerializer ser = new JavaScriptSerializer(); + Assert.IsNull(ser.Deserialize("", typeof(X))); + + X s = new X(); + s.Init(); + string x = ser.Serialize(s); + + Assert.AreEqual("{\"z\":8,\"ch\":\"v\",\"ch_null\":null,\"str\":\"vwF59g\",\"b\":253,\"sb\":-48,\"sh\":-32740,\"ush\":65511,\"i\":-234235453,\"ui\":4294733061,\"l\":-9223372036854775780,\"ul\":18446744073709551612,\"f\":NaN,\"f1\":-Infinity,\"f2\":Infinity,\"f3\":-3.40282347E+38,\"f4\":3.40282347E+38,\"d\":NaN,\"d1\":-Infinity,\"d2\":Infinity,\"d3\":-1.7976931348623157E+308,\"d4\":1.7976931348623157E+308,\"de\":-1,\"de1\":0,\"de2\":1,\"de3\":-79228162514264337593543950335,\"de4\":79228162514264337593543950335,\"g\":\"000000ea-0002-0162-0102-030405060708\",\"nb\":null,\"dbn\":null,\"uri\":\"http://kostat@mainsoft/adfasdf/asdfasdf.aspx/asda/ads?a=b&c=d\",\"hash\":{\"mykey\":{\"BB\":10}},\"point\":{\"IsEmpty\":false,\"X\":150,\"Y\":150},\"MyEnum\":[1,10,345],\"MyEnum1\":[1,10,345],\"AA\":5,\"AA1\":[{\"BB\":10},{\"BB\":10}],\"BB\":18446744073709551610,\"YY\":[{\"BB\":10},{\"BB\":10}]}", x, "#A1"); + + X n = ser.Deserialize(x, typeof(X)) as X; + Assert.AreEqual(s, n, "#A2"); + } + [Test] public void TestDeserializeTypeResolver () { diff --git a/mcs/class/corlib/System.Security.Claims/Claim.cs b/mcs/class/corlib/System.Security.Claims/Claim.cs index ffb7ce73449..0347052d236 100644 --- a/mcs/class/corlib/System.Security.Claims/Claim.cs +++ b/mcs/class/corlib/System.Security.Claims/Claim.cs @@ -58,6 +58,9 @@ public Claim (string type, string value, string valueType, string issuer, string throw new ArgumentNullException ("type"); if (value == null) throw new ArgumentNullException ("value"); + + Properties = new Dictionary (); + Type = type; Value = value; ValueType = valueType == null ? ClaimValueTypes.String : valueType; @@ -91,4 +94,4 @@ public override string ToString () } } } -#endif \ No newline at end of file +#endif From ef13507552da30ab080e09c9e12ce015352c1b70 Mon Sep 17 00:00:00 2001 From: "Ryan J. Melena" Date: Thu, 30 Oct 2014 11:47:56 -0500 Subject: [PATCH 494/543] Revert incorrect changes from commit 950d9c8a567273c3363f43cee454f2b95a9f5da7 Correctly handle null value deserialization in non-generic Deserialize(string, Type) method. --- .../System.Web.Script.Serialization/JavaScriptSerializer.cs | 3 +-- .../System.Web.Script.Serialization/JsonDeserializer.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs index 6a147e2e03e..9095cb866d3 100644 --- a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs +++ b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JavaScriptSerializer.cs @@ -206,8 +206,7 @@ public T Deserialize (string input) { public object Deserialize (string input, Type targetType) { object obj = DeserializeObjectInternal (input); - if (obj == null) - return Activator.CreateInstance (targetType); + if (obj == null) return null; return ConvertToType (obj, targetType); } diff --git a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs index 8593e532bf0..46bef52a7b4 100644 --- a/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs +++ b/mcs/class/System.Web.Extensions/System.Web.Script.Serialization/JsonDeserializer.cs @@ -833,7 +833,7 @@ bool ProcessCharacter (char ch) void CreateArray () { - var arr = new List (); + var arr = new ArrayList (); PushObject (arr); } @@ -865,7 +865,7 @@ void StoreValue (object o) { Dictionary dict = PeekObject () as Dictionary ; if (dict == null) { - List arr = PeekObject () as List ; + ArrayList arr = PeekObject () as ArrayList; if (arr == null) throw new InvalidOperationException ("Internal error: current object is not a dictionary or an array."); arr.Add (o); From 03494c7387269158ca2d42aac9ae3acfab372e01 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 29 Oct 2014 11:48:09 -0700 Subject: [PATCH 495/543] [sgen] Don't loop endlessly when out of memory. --- mono/metadata/sgen-alloc.c | 39 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/mono/metadata/sgen-alloc.c b/mono/metadata/sgen-alloc.c index 3b0c3a3ec33..ed28184ae4b 100644 --- a/mono/metadata/sgen-alloc.c +++ b/mono/metadata/sgen-alloc.c @@ -291,20 +291,15 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size) available_in_tlab = (int)(TLAB_REAL_END - TLAB_NEXT);//We'll never have tlabs > 2Gb if (size > tlab_size || available_in_tlab > SGEN_MAX_NURSERY_WASTE) { /* Allocate directly from the nursery */ - do { - p = sgen_nursery_alloc (size); - if (!p) { - sgen_ensure_free_space (real_size); - if (degraded_mode) - return alloc_degraded (vtable, size, FALSE); - else - p = sgen_nursery_alloc (size); - } - } while (!p); + p = sgen_nursery_alloc (size); if (!p) { - // no space left - g_assert (0); + sgen_ensure_free_space (real_size); + if (degraded_mode) + return alloc_degraded (vtable, size, FALSE); + else + p = sgen_nursery_alloc (size); } + SGEN_ASSERT (0, p, "Out of memory"); zero_tlab_if_necessary (p, size); } else { @@ -313,21 +308,15 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size) SGEN_LOG (3, "Retire TLAB: %p-%p [%ld]", TLAB_START, TLAB_REAL_END, (long)(TLAB_REAL_END - TLAB_NEXT - size)); sgen_nursery_retire_region (p, available_in_tlab); - do { - p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size); - if (!p) { - sgen_ensure_free_space (tlab_size); - if (degraded_mode) - return alloc_degraded (vtable, size, FALSE); - else - p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size); - } - } while (!p); - + p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size); if (!p) { - // no space left - g_assert (0); + sgen_ensure_free_space (tlab_size); + if (degraded_mode) + return alloc_degraded (vtable, size, FALSE); + else + p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size); } + SGEN_ASSERT (0, p, "Out of memory"); /* Allocate a new TLAB from the current nursery fragment */ TLAB_START = (char*)p; From 45fc2e14fdbfaf515e3208dd29775c5403f1aec4 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 29 Oct 2014 11:50:51 -0700 Subject: [PATCH 496/543] [sgen] Fix crash in late pinning. Our code assumed that late-pinned objects don't have a tag, but they obviously have the pin tag, so use the safe function. --- mono/metadata/sgen-gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 4b0b5a32012..41dc35f40e7 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -1101,7 +1101,7 @@ sgen_pin_object (void *object, GrayQueue *queue) if (G_UNLIKELY (do_pin_stats)) sgen_pin_stats_register_object (object, safe_object_get_size (object)); - GRAY_OBJECT_ENQUEUE (queue, object, sgen_obj_get_descriptor (object)); + GRAY_OBJECT_ENQUEUE (queue, object, sgen_obj_get_descriptor_safe (object)); binary_protocol_pin (object, (gpointer)LOAD_VTABLE (object), safe_object_get_size (object)); #ifdef ENABLE_DTRACE From 5eec4d0c848adfd73174016b2e681329aa6a5840 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 29 Oct 2014 16:36:02 -0700 Subject: [PATCH 497/543] [sgen] Don't store pin queue addresses, only indexes. Fixes #24084. The pin queue can get relocated as a side-effect of resizing when late pinning happens, so we can't count on pointers into it to remain valid. --- mono/metadata/sgen-gc.c | 32 ++++++----- mono/metadata/sgen-gc.h | 10 ++-- mono/metadata/sgen-marksweep.c | 22 ++++---- mono/metadata/sgen-nursery-allocator.c | 25 +++++---- mono/metadata/sgen-pinning.c | 75 +++++++++++++++++++------- mono/metadata/sgen-pinning.h | 5 ++ 6 files changed, 113 insertions(+), 56 deletions(-) diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 41dc35f40e7..c9a0792c519 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -912,8 +912,8 @@ static int pin_objects_from_nursery_pin_queue (ScanCopyContext ctx) { GCMemSection *section = nursery_section; - void **start = section->pin_queue_start; - void **end = start + section->pin_queue_num_entries; + void **start = sgen_pinning_get_entry (section->pin_queue_first_entry); + void **end = sgen_pinning_get_entry (section->pin_queue_last_entry); void *start_nursery = section->data; void *end_nursery = section->next_data; void *last = NULL; @@ -1080,13 +1080,11 @@ pin_objects_in_nursery (ScanCopyContext ctx) { size_t reduced_to; - if (!nursery_section->pin_queue_num_entries) + if (nursery_section->pin_queue_first_entry == nursery_section->pin_queue_last_entry) return; reduced_to = pin_objects_from_nursery_pin_queue (ctx); - nursery_section->pin_queue_num_entries = reduced_to; - if (!reduced_to) - nursery_section->pin_queue_start = NULL; + nursery_section->pin_queue_last_entry = nursery_section->pin_queue_first_entry + reduced_to; } @@ -2407,9 +2405,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) * next allocations. */ mono_profiler_gc_event (MONO_GC_EVENT_RECLAIM_START, 0); - fragment_total = sgen_build_nursery_fragments (nursery_section, - nursery_section->pin_queue_start, nursery_section->pin_queue_num_entries, - unpin_queue); + fragment_total = sgen_build_nursery_fragments (nursery_section, unpin_queue); if (!fragment_total) degraded_mode = 1; @@ -2600,7 +2596,7 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, gboolean finish_up_con SGEN_LOG (6, "Pinning from large objects"); for (bigobj = los_object_list; bigobj; bigobj = bigobj->next) { size_t dummy; - if (sgen_find_optimized_pin_queue_area (bigobj->data, (char*)bigobj->data + sgen_los_object_size (bigobj), &dummy)) { + if (sgen_find_optimized_pin_queue_area (bigobj->data, (char*)bigobj->data + sgen_los_object_size (bigobj), &dummy, &dummy)) { binary_protocol_pin (bigobj->data, (gpointer)LOAD_VTABLE (bigobj->data), safe_object_get_size (((MonoObject*)(bigobj->data)))); #ifdef ENABLE_DTRACE @@ -2860,8 +2856,20 @@ major_finish_collection (const char *reason, size_t old_next_pin_slot, gboolean if (objects_pinned) { g_assert (!concurrent_collection_in_progress); - /*This is slow, but we just OOM'd*/ + /* + * This is slow, but we just OOM'd. + * + * See comment at `sgen_pin_queue_clear_discarded_entries` for how the pin + * queue is laid out at this point. + */ sgen_pin_queue_clear_discarded_entries (nursery_section, old_next_pin_slot); + /* + * We need to reestablish all pinned nursery objects in the pin queue + * because they're needed for fragment creation. Unpinning happens by + * walking the whole queue, so it's not necessary to reestablish where major + * heap block pins are - all we care is that they're still in there + * somewhere. + */ sgen_optimize_pin_queue (); sgen_find_section_pin_queue_start_end (nursery_section); objects_pinned = 0; @@ -2918,7 +2926,7 @@ major_finish_collection (const char *reason, size_t old_next_pin_slot, gboolean * pinned objects as we go, memzero() the empty fragments so they are ready for the * next allocations. */ - if (!sgen_build_nursery_fragments (nursery_section, nursery_section->pin_queue_start, nursery_section->pin_queue_num_entries, NULL)) + if (!sgen_build_nursery_fragments (nursery_section, NULL)) degraded_mode = 1; /* prepare the pin queue for the next collection */ diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 12121dc723f..0fa76130411 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -144,8 +144,8 @@ struct _GCMemSection { */ char **scan_starts; /* in major collections indexes in the pin_queue for objects that pin this section */ - void **pin_queue_start; - size_t pin_queue_num_entries; + size_t pin_queue_first_entry; + size_t pin_queue_last_entry; size_t num_scan_start; }; @@ -486,10 +486,6 @@ void sgen_free_internal (void *addr, int type) MONO_INTERNAL; void* sgen_alloc_internal_dynamic (size_t size, int type, gboolean assert_on_failure) MONO_INTERNAL; void sgen_free_internal_dynamic (void *addr, size_t size, int type) MONO_INTERNAL; -void** sgen_find_optimized_pin_queue_area (void *start, void *end, size_t *num) MONO_INTERNAL; -void sgen_find_section_pin_queue_start_end (GCMemSection *section) MONO_INTERNAL; -void sgen_pin_objects_in_section (GCMemSection *section, ScanCopyContext ctx) MONO_INTERNAL; - void sgen_pin_stats_register_object (char *obj, size_t size); void sgen_pin_stats_register_global_remset (char *obj); void sgen_pin_stats_print_class_stats (void); @@ -978,7 +974,7 @@ gboolean sgen_los_object_is_pinned (char *obj) MONO_INTERNAL; void sgen_clear_nursery_fragments (void) MONO_INTERNAL; void sgen_nursery_allocator_prepare_for_pinning (void) MONO_INTERNAL; void sgen_nursery_allocator_set_nursery_bounds (char *nursery_start, char *nursery_end) MONO_INTERNAL; -mword sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_t num_entries, SgenGrayQueue *unpin_queue) MONO_INTERNAL; +mword sgen_build_nursery_fragments (GCMemSection *nursery_section, SgenGrayQueue *unpin_queue) MONO_INTERNAL; void sgen_init_nursery_allocator (void) MONO_INTERNAL; void sgen_nursery_allocator_init_heavy_stats (void) MONO_INTERNAL; void sgen_alloc_init_heavy_stats (void) MONO_INTERNAL; diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index 89806871343..dfe7504242f 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -41,6 +41,7 @@ #include "metadata/sgen-layout-stats.h" #include "metadata/gc-internal.h" #include "metadata/sgen-pointer-queue.h" +#include "metadata/sgen-pinning.h" #define SGEN_HAVE_CONCURRENT_MARK @@ -74,7 +75,6 @@ typedef struct _MSBlockInfo MSBlockInfo; struct _MSBlockInfo { int obj_size; int obj_size_index; - size_t pin_queue_num_entries; unsigned int pinned : 1; unsigned int has_references : 1; unsigned int has_pinned : 1; /* means cannot evacuate */ @@ -83,7 +83,8 @@ struct _MSBlockInfo { char *block; void **free_list; MSBlockInfo *next_free; - void **pin_queue_start; + size_t pin_queue_first_entry; + size_t pin_queue_last_entry; #ifdef SGEN_HAVE_CONCURRENT_MARK guint8 *cardtable_mod_union; #endif @@ -1074,18 +1075,21 @@ major_get_and_reset_num_major_objects_marked (void) static void mark_pinned_objects_in_block (MSBlockInfo *block, SgenGrayQueue *queue) { - int i; + void **entry, **end; int last_index = -1; - if (!block->pin_queue_num_entries) + if (block->pin_queue_first_entry == block->pin_queue_last_entry) return; block->has_pinned = TRUE; - for (i = 0; i < block->pin_queue_num_entries; ++i) { - int index = MS_BLOCK_OBJ_INDEX (block->pin_queue_start [i], block); + entry = sgen_pinning_get_entry (block->pin_queue_first_entry); + end = sgen_pinning_get_entry (block->pin_queue_last_entry); + + for (; entry < end; ++entry) { + int index = MS_BLOCK_OBJ_INDEX (*entry, block); char *obj; - SGEN_ASSERT (9, index >= 0 && index < MS_BLOCK_FREE / block->obj_size, "invalid object %p index %d max-index %d", block->pin_queue_start [i], index, MS_BLOCK_FREE / block->obj_size); + SGEN_ASSERT (9, index >= 0 && index < MS_BLOCK_FREE / block->obj_size, "invalid object %p index %d max-index %d", *entry, index, MS_BLOCK_FREE / block->obj_size); if (index == last_index) continue; obj = MS_BLOCK_OBJ (block, index); @@ -1626,8 +1630,8 @@ major_find_pin_queue_start_ends (SgenGrayQueue *queue) MSBlockInfo *block; FOREACH_BLOCK (block) { - block->pin_queue_start = sgen_find_optimized_pin_queue_area (MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SKIP, MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE, - &block->pin_queue_num_entries); + sgen_find_optimized_pin_queue_area (MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SKIP, MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE, + &block->pin_queue_first_entry, &block->pin_queue_last_entry); } END_FOREACH_BLOCK; } diff --git a/mono/metadata/sgen-nursery-allocator.c b/mono/metadata/sgen-nursery-allocator.c index 01d1bd1a796..75297a7e1b1 100644 --- a/mono/metadata/sgen-nursery-allocator.c +++ b/mono/metadata/sgen-nursery-allocator.c @@ -71,6 +71,7 @@ #include "metadata/sgen-archdep.h" #include "metadata/sgen-bridge.h" #include "metadata/sgen-memory-governor.h" +#include "metadata/sgen-pinning.h" #include "metadata/mono-gc.h" #include "metadata/method-builder.h" #include "metadata/profiler-private.h" @@ -747,12 +748,12 @@ fragment_list_reverse (SgenFragmentAllocator *allocator) } mword -sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_t num_entries, SgenGrayQueue *unpin_queue) +sgen_build_nursery_fragments (GCMemSection *nursery_section, SgenGrayQueue *unpin_queue) { char *frag_start, *frag_end; size_t frag_size; - size_t i = 0; SgenFragment *frags_ranges; + void **pin_start, **pin_entry, **pin_end; #ifdef NALLOC_DEBUG reset_alloc_records (); @@ -769,14 +770,17 @@ sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_ /* clear scan starts */ memset (nursery_section->scan_starts, 0, nursery_section->num_scan_start * sizeof (gpointer)); - while (i < num_entries || frags_ranges) { + pin_start = pin_entry = sgen_pinning_get_entry (nursery_section->pin_queue_first_entry); + pin_end = sgen_pinning_get_entry (nursery_section->pin_queue_last_entry); + + while (pin_entry < pin_end || frags_ranges) { char *addr0, *addr1; size_t size; SgenFragment *last_frag = NULL; addr0 = addr1 = sgen_nursery_end; - if (i < num_entries) - addr0 = start [i]; + if (pin_entry < pin_end) + addr0 = *pin_entry; if (frags_ranges) addr1 = frags_ranges->fragment_start; @@ -789,7 +793,7 @@ sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_ CANARIFY_SIZE (size); sgen_set_nursery_scan_start (addr0); frag_end = addr0; - ++i; + ++pin_entry; } else { frag_end = addr1; size = frags_ranges->fragment_next - addr1; @@ -809,7 +813,7 @@ sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_ frag_size = size; #ifdef NALLOC_DEBUG - add_alloc_record (start [i], frag_size, PINNING); + add_alloc_record (*pin_entry, frag_size, PINNING); #endif frag_start = frag_end + frag_size; } @@ -830,9 +834,10 @@ sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_ sgen_minor_collector.build_fragments_finish (&mutator_allocator); if (!unmask (mutator_allocator.alloc_head)) { - SGEN_LOG (1, "Nursery fully pinned (%zd)", num_entries); - for (i = 0; i < num_entries; ++i) { - SGEN_LOG (3, "Bastard pinning obj %p (%s), size: %zd", start [i], sgen_safe_name (start [i]), sgen_safe_object_get_size (start [i])); + SGEN_LOG (1, "Nursery fully pinned"); + for (pin_entry = pin_start; pin_entry < pin_end; ++pin_entry) { + void *p = *pin_entry; + SGEN_LOG (3, "Bastard pinning obj %p (%s), size: %zd", p, sgen_safe_name (p), sgen_safe_object_get_size (p)); } } return fragment_total; diff --git a/mono/metadata/sgen-pinning.c b/mono/metadata/sgen-pinning.c index 71a8dbefebe..c895d7471ea 100644 --- a/mono/metadata/sgen-pinning.c +++ b/mono/metadata/sgen-pinning.c @@ -59,50 +59,89 @@ sgen_pin_stage_ptr (void *ptr) sgen_pointer_queue_add (&pin_queue, ptr); } +gboolean +sgen_find_optimized_pin_queue_area (void *start, void *end, size_t *first_out, size_t *last_out) +{ + size_t first = sgen_pointer_queue_search (&pin_queue, start); + size_t last = sgen_pointer_queue_search (&pin_queue, end); + SGEN_ASSERT (0, last == pin_queue.next_slot || pin_queue.data [last] >= end, "Pin queue search gone awry"); + *first_out = first; + *last_out = last; + return first != last; +} + void** -sgen_find_optimized_pin_queue_area (void *start, void *end, size_t *num) +sgen_pinning_get_entry (size_t index) { - size_t first, last; - first = sgen_pointer_queue_search (&pin_queue, start); - last = sgen_pointer_queue_search (&pin_queue, end); - *num = last - first; - if (first == last) - return NULL; - return pin_queue.data + first; + SGEN_ASSERT (0, index <= pin_queue.next_slot, "Pin queue entry out of range"); + return &pin_queue.data [index]; } void sgen_find_section_pin_queue_start_end (GCMemSection *section) { SGEN_LOG (6, "Pinning from section %p (%p-%p)", section, section->data, section->end_data); - section->pin_queue_start = sgen_find_optimized_pin_queue_area (section->data, section->end_data, §ion->pin_queue_num_entries); - SGEN_LOG (6, "Found %zd pinning addresses in section %p", section->pin_queue_num_entries, section); + + sgen_find_optimized_pin_queue_area (section->data, section->end_data, + §ion->pin_queue_first_entry, §ion->pin_queue_last_entry); + + SGEN_LOG (6, "Found %zd pinning addresses in section %p", + section->pin_queue_last_entry - section->pin_queue_first_entry, section); } /*This will setup the given section for the while pin queue. */ void sgen_pinning_setup_section (GCMemSection *section) { - section->pin_queue_start = pin_queue.data; - section->pin_queue_num_entries = pin_queue.next_slot; + section->pin_queue_first_entry = 0; + section->pin_queue_last_entry = pin_queue.next_slot; } void sgen_pinning_trim_queue_to_section (GCMemSection *section) { - pin_queue.next_slot = section->pin_queue_num_entries; + SGEN_ASSERT (0, section->pin_queue_first_entry == 0, "Pin queue trimming assumes the whole pin queue is used by the nursery"); + pin_queue.next_slot = section->pin_queue_last_entry; } +/* + * This is called when we've run out of memory during a major collection. + * + * After collecting potential pin entries and sorting the array, this is what it looks like: + * + * +--------------------+---------------------------------------------+--------------------+ + * | major heap entries | nursery entries | major heap entries | + * +--------------------+---------------------------------------------+--------------------+ + * + * Of course there might not be major heap entries before and/or after the nursery entries, + * depending on where the major heap sections are in the address space, and whether there + * were any potential pointers there. + * + * When we pin nursery objects, we compact the nursery part of the pin array, which leaves + * discarded entries after the ones that actually pointed to nursery objects: + * + * +--------------------+-----------------+---------------------------+--------------------+ + * | major heap entries | nursery entries | discarded nursery entries | major heap entries | + * +--------------------+-----------------+---------------------------+--------------------+ + * + * When, due to being out of memory, we late pin more objects, the pin array looks like + * this: + * + * +--------------------+-----------------+---------------------------+--------------------+--------------+ + * | major heap entries | nursery entries | discarded nursery entries | major heap entries | late entries | + * +--------------------+-----------------+---------------------------+--------------------+--------------+ + * + * This function gets rid of the discarded nursery entries by nulling them out. Note that + * we can late pin objects not only in the nursery but also in the major heap, which happens + * when evacuation fails. + */ void sgen_pin_queue_clear_discarded_entries (GCMemSection *section, size_t max_pin_slot) { - void **start = section->pin_queue_start + section->pin_queue_num_entries; - void **end = pin_queue.data + max_pin_slot; + void **start = sgen_pinning_get_entry (section->pin_queue_last_entry); + void **end = sgen_pinning_get_entry (max_pin_slot); void *addr; - if (!start) - return; - for (; start < end; ++start) { addr = *start; if ((char*)addr < section->data || (char*)addr > section->end_data) diff --git a/mono/metadata/sgen-pinning.h b/mono/metadata/sgen-pinning.h index 19840beb646..9a2dcbb2c57 100644 --- a/mono/metadata/sgen-pinning.h +++ b/mono/metadata/sgen-pinning.h @@ -38,6 +38,11 @@ void sgen_pinning_trim_queue_to_section (GCMemSection *section) MONO_INTERNAL; void sgen_dump_pin_queue (void) MONO_INTERNAL; +gboolean sgen_find_optimized_pin_queue_area (void *start, void *end, size_t *first_out, size_t *last_out) MONO_INTERNAL; +void sgen_find_section_pin_queue_start_end (GCMemSection *section) MONO_INTERNAL; +void** sgen_pinning_get_entry (size_t index) MONO_INTERNAL; +void sgen_pin_objects_in_section (GCMemSection *section, ScanCopyContext ctx) MONO_INTERNAL; + /* Pinning stats */ void sgen_pin_stats_register_address (char *addr, int pin_type) MONO_INTERNAL; From 3c533de4a8953cbc937b5e37ced6b4e5b16bd1dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Thu, 30 Oct 2014 22:16:20 +0100 Subject: [PATCH 498/543] Add files that were forgotten in 6af798962810054fcf68f8e597de56b6490271a2, which is the re-apply of 950d9c8a567273c3363f43cee454f2b95a9f5da7 --- .../SecurityTokenExpiredException.cs | 54 +++++++++++++++++++ .../SecurityTokenNotYetValidException.cs | 54 +++++++++++++++++++ .../SecurityTokenReplayDetectedException.cs | 54 +++++++++++++++++++ .../SignatureVerificationFailedException.cs | 54 +++++++++++++++++++ 4 files changed, 216 insertions(+) create mode 100644 mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs create mode 100644 mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs create mode 100644 mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs create mode 100644 mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs new file mode 100644 index 00000000000..2f10c949029 --- /dev/null +++ b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenExpiredException.cs @@ -0,0 +1,54 @@ +// +// SecurityTokenExpiredException.cs +// +// Author: +// Noesis Labs (Ryan.Melena@noesislabs.com) +// +// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#if NET_4_5 + +using System; +using System.Runtime.Serialization; + +namespace System.IdentityModel.Tokens +{ + public class SecurityTokenExpiredException : SecurityTokenValidationException + { + public SecurityTokenExpiredException() + : base("ID4181: The security token has expired.") + { } + + public SecurityTokenExpiredException(string message) + : base(message) + { } + + public SecurityTokenExpiredException(string message, Exception innerException) + : base(message, innerException) + { } + + public SecurityTokenExpiredException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} +#endif diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs new file mode 100644 index 00000000000..9f15b7b6448 --- /dev/null +++ b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs @@ -0,0 +1,54 @@ +// +// SecurityTokenNotYetValidException.cs +// +// Author: +// Noesis Labs (Ryan.Melena@noesislabs.com) +// +// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#if NET_4_5 + +using System; +using System.Runtime.Serialization; + +namespace System.IdentityModel.Tokens +{ + public class SecurityTokenNotYetValidException : SecurityTokenValidationException + { + public SecurityTokenNotYetValidException() + : base("ID4182: The security token is not valid yet.") + { } + + public SecurityTokenNotYetValidException(string message) + : base(message) + { } + + public SecurityTokenNotYetValidException(string message, Exception innerException) + : base(message, innerException) + { } + + public SecurityTokenNotYetValidException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} +#endif diff --git a/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs new file mode 100644 index 00000000000..eb4a786b336 --- /dev/null +++ b/mcs/class/System.IdentityModel/System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs @@ -0,0 +1,54 @@ +// +// SecurityTokenReplayDetectedException.cs +// +// Author: +// Noesis Labs (Ryan.Melena@noesislabs.com) +// +// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#if NET_4_5 + +using System; +using System.Runtime.Serialization; + +namespace System.IdentityModel.Tokens +{ + public class SecurityTokenReplayDetectedException : SecurityTokenValidationException + { + public SecurityTokenReplayDetectedException() + : base("ID1070: Replay has been detected for a SecurityToken.") + { } + + public SecurityTokenReplayDetectedException(string message) + : base(message) + { } + + public SecurityTokenReplayDetectedException(string message, Exception innerException) + : base(message, innerException) + { } + + public SecurityTokenReplayDetectedException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} +#endif diff --git a/mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs b/mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs new file mode 100644 index 00000000000..2e1e7115ca9 --- /dev/null +++ b/mcs/class/System.IdentityModel/System.IdentityModel/SignatureVerificationFailedException.cs @@ -0,0 +1,54 @@ +// +// SignatureVerificationFailedException.cs +// +// Author: +// Noesis Labs (Ryan.Melena@noesislabs.com) +// +// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#if NET_4_5 + +using System; +using System.Runtime.Serialization; + +namespace System.IdentityModel +{ + public class SignatureVerificationFailedException : Exception + { + public SignatureVerificationFailedException() + : base("ID4038: Signature verification failed.") + { } + + public SignatureVerificationFailedException(string message) + : base(message) + { } + + public SignatureVerificationFailedException(string message, Exception innerException) + : base(message, innerException) + { } + + public SignatureVerificationFailedException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} +#endif From 7c162f952c4d76ee1f0b3d2e0b54d972d95da12a Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 30 Oct 2014 17:23:13 -0400 Subject: [PATCH 499/543] [llvm] Remove the unused LLVM_MAJOR_VERSION/LLVM_MINOR_VERSION defines. --- configure.ac | 8 -------- mono/mini/mini-llvm-cpp.cpp | 4 ---- mono/mini/mini.h | 8 -------- 3 files changed, 20 deletions(-) diff --git a/configure.ac b/configure.ac index 664808a4977..b858aab7f3d 100644 --- a/configure.ac +++ b/configure.ac @@ -2459,8 +2459,6 @@ if test "x$enable_llvm" = "xyes"; then # Should be something like '2.6' or '2.7svn' llvm_version=`$LLVM_CONFIG --version` - major_version=`echo $llvm_version | cut -c 1` - minor_version=`echo $llvm_version | cut -c 3` llvm_api_version=`$LLVM_CONFIG --mono-api-version 2>/dev/null` AC_MSG_CHECKING(LLVM version) AC_MSG_RESULT($llvm_version) @@ -2481,14 +2479,8 @@ if test "x$enable_llvm" = "xyes"; then AC_MSG_ERROR([Compiling with stock LLVM is not supported, please use the Mono LLVM repo at https://github.com/mono/llvm, with the GIT branch which matches this version of mono, i.e. 'mono-2-10' for Mono 2.10.]) fi - AC_DEFINE_UNQUOTED(LLVM_MAJOR_VERSION, $major_version, [Major version of LLVM libraries]) - AC_DEFINE_UNQUOTED(LLVM_MINOR_VERSION, $minor_version, [Minor version of LLVM libraries]) AC_DEFINE_UNQUOTED(LLVM_VERSION, "$llvm_version", [Full version of LLVM libraties]) - # Have to pass these on the command line since mini-llvm-cpp.h already includes - # llvm's config.h - LLVM_CXXFLAGS="$LLVM_CXXFLAGS -DLLVM_MAJOR_VERSION=$major_version -DLLVM_MINOR_VERSION=$minor_version" - AC_SUBST(LLVM_CFLAGS) AC_SUBST(LLVM_CXXFLAGS) AC_SUBST(LLVM_LIBS) diff --git a/mono/mini/mini-llvm-cpp.cpp b/mono/mini/mini-llvm-cpp.cpp index 7560fcf012b..6f7a336a25d 100644 --- a/mono/mini/mini-llvm-cpp.cpp +++ b/mono/mini/mini-llvm-cpp.cpp @@ -60,10 +60,6 @@ #include "mini-llvm-cpp.h" -#define LLVM_CHECK_VERSION(major,minor) \ - ((LLVM_MAJOR_VERSION > (major)) || \ - ((LLVM_MAJOR_VERSION == (major)) && (LLVM_MINOR_VERSION >= (minor)))) - // extern "C" void LLVMInitializeARMTargetInfo(); // extern "C" void LLVMInitializeARMTarget (); // extern "C" void LLVMInitializeARMTargetMC (); diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 8d9bcc9f206..e345cadc55b 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -83,14 +83,6 @@ #define COMPILE_SOFT_FLOAT(cfg) (0) #endif -#ifdef ENABLE_LLVM -#define LLVM_CHECK_VERSION(major,minor) \ - ((LLVM_MAJOR_VERSION > (major)) || \ - ((LLVM_MAJOR_VERSION == (major)) && (LLVM_MINOR_VERSION >= (minor)))) -#else -#define LLVM_CHECK_VERSION(major,minor) 0 -#endif - #define NOT_IMPLEMENTED do { g_assert_not_reached (); } while (0) /* for 32 bit systems */ From b40386d4f40b849df637672545b0399bf2556af3 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 30 Oct 2014 17:28:22 -0400 Subject: [PATCH 500/543] Add the -Qunused-arguments warning to CPPFLAGS too. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index b858aab7f3d..2bc3c0d08f5 100644 --- a/configure.ac +++ b/configure.ac @@ -578,6 +578,7 @@ else fi CFLAGS="$CFLAGS -g $WARN" CFLAGS_FOR_LIBGC="$CFLAGS_FOR_LIBGC -g" +CPPFLAGS="$CPPFLAGS -g $WARN" # Where's the 'mcs' source tree? if test -d $srcdir/mcs; then From 74d2172cd1d6365ada5fc040786c7391ef493b3b Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 30 Oct 2014 17:28:31 -0400 Subject: [PATCH 501/543] Fix a warning. --- mono/mini/mini-llvm-cpp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/mono/mini/mini-llvm-cpp.cpp b/mono/mini/mini-llvm-cpp.cpp index 6f7a336a25d..bf5e16f8fac 100644 --- a/mono/mini/mini-llvm-cpp.cpp +++ b/mono/mini/mini-llvm-cpp.cpp @@ -602,7 +602,6 @@ mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, Func // EngineBuilder no longer has a copy assignment operator (?) std::unique_ptr Owner(unwrap(MP)); EngineBuilder b (std::move(Owner)); - EngineBuilder &eb = b; #ifdef TARGET_AMD64 ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).setMCPU (cpu_name).setCodeModel (CodeModel::Large).create (); #else From bf6fea51af57a924b4e6e187b3aeded82751bda0 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 30 Oct 2014 17:52:33 -0400 Subject: [PATCH 502/543] [aot] Use the info->tramp_page_code_offsets array on arm as well. --- mono/mini/aot-compiler.c | 5 +++++ mono/mini/aot-runtime.c | 11 ----------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 4b53f0cae19..b6b74d3e569 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -1274,6 +1274,11 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg) g_assert (code - buf == 8); emit_bytes (acfg, buf, code - buf); } + + acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = 16; + acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = 16; + acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = 72; + acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16; #elif defined(TARGET_ARM64) arm64_emit_specific_trampoline_pages (acfg); #endif diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index e9b5f42668a..97d22706db0 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -4476,13 +4476,6 @@ mono_aot_get_trampoline (const char *name) #include static TrampolinePage* trampoline_pages [MONO_AOT_TRAMP_NUM]; -/* these sizes are for ARM code, parametrize if porting to other architectures (see arch_emit_specific_trampoline_pages) - * trampoline size is assumed to be 8 bytes below as well (8 is the minimum for 32 bit archs, since we need to store - * two pointers for trampoline in the data page). - * the minimum for the common code must be at least sizeof(TrampolinePage), since we store the page info at the - * beginning of the data page. - */ -static const int trampolines_pages_code_offsets [MONO_AOT_TRAMP_NUM] = {16, 16, 72, 16}; static unsigned char* get_new_trampoline_from_page (int tramp_type) @@ -4571,11 +4564,7 @@ get_new_trampoline_from_page (int tramp_type) page = (TrampolinePage*)addr; page->next = trampoline_pages [tramp_type]; trampoline_pages [tramp_type] = page; -#ifdef TARGET_ARM64 page->trampolines = (void*)(taddr + amodule->info.tramp_page_code_offsets [tramp_type]); -#else - page->trampolines = (void*)(taddr + trampolines_pages_code_offsets [tramp_type]); -#endif page->trampolines_end = (void*)(taddr + psize - 64); code = page->trampolines; page->trampolines += specific_trampoline_size; From dbfee6a3404e684b1ce811ca3bdea45b01bb98b0 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 30 Oct 2014 17:56:19 -0400 Subject: [PATCH 503/543] [aot] Remove some obsolete TODOs. --- mono/mini/aot-compiler.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index b6b74d3e569..d5bb922e142 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -10,17 +10,6 @@ * Copyright 2011 Xamarin Inc (http://www.xamarin.com) */ -/* Remaining AOT-only work: - * - optimize the trampolines, generate more code in the arch files. - * - make things more consistent with how elf works, for example, use ELF - * relocations. - * Remaining generics sharing work: - * - optimize the size of the data which is encoded. - * - optimize the runtime loading of data: - * - the trampoline code calls mono_jit_info_table_find () to find the rgctx, - * which loads the debugging+exception handling info for the method. This is a - * huge waste of time and code, since the rgctx structure is currently empty. - */ #include "config.h" #include #ifdef HAVE_UNISTD_H @@ -42,7 +31,6 @@ #include #include - #include #include #include From f85a6bc77c654eef07f6c6178c4e88d29651f316 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 30 Oct 2014 18:44:01 -0400 Subject: [PATCH 504/543] [runtime] Fix the android build with ndk r10c. --- mono/utils/mono-sigcontext.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mono/utils/mono-sigcontext.h b/mono/utils/mono-sigcontext.h index cc70df01822..f61f3dd3ee3 100644 --- a/mono/utils/mono-sigcontext.h +++ b/mono/utils/mono-sigcontext.h @@ -19,9 +19,6 @@ #if defined(TARGET_X86) -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__DragonFly__) -#include -#endif #if defined(__APPLE__) #include #endif @@ -90,7 +87,7 @@ #define UCONTEXT_REG_EIP(ctx) (((ucontext_t*)(ctx))->uc_mcontext.gregs [EIP]) #else -#if defined(PLATFORM_ANDROID) +#if defined(PLATFORM_ANDROID) && !defined(HAVE_UCONTEXT_H) /* No ucontext.h as of NDK v6b */ typedef int greg_t; #define NGREG 19 From 000c01816959a7926c048a55731e2e344027934f Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Thu, 30 Oct 2014 16:28:03 -0700 Subject: [PATCH 505/543] [sgen] Add an explanatory comment about OOM. --- mono/metadata/sgen-alloc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/mono/metadata/sgen-alloc.c b/mono/metadata/sgen-alloc.c index ed28184ae4b..368388a5dab 100644 --- a/mono/metadata/sgen-alloc.c +++ b/mono/metadata/sgen-alloc.c @@ -293,6 +293,21 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size) /* Allocate directly from the nursery */ p = sgen_nursery_alloc (size); if (!p) { + /* + * We couldn't allocate from the nursery, so we try + * collecting. Even after the collection, we might + * still not have enough memory to allocate the + * object. The reason will most likely be that we've + * run out of memory, but there is the theoretical + * possibility that other threads might have consumed + * the freed up memory ahead of us, so doing another + * collection and trying again might actually help. + * Of course the same thing might happen again. + * + * Ideally we'd like to detect that case and loop (if + * we always loop we will loop endlessly in the case of + * OOM). What we do here is give up right away. + */ sgen_ensure_free_space (real_size); if (degraded_mode) return alloc_degraded (vtable, size, FALSE); @@ -310,6 +325,7 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size) p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size); if (!p) { + /* See comment above in similar case. */ sgen_ensure_free_space (tlab_size); if (degraded_mode) return alloc_degraded (vtable, size, FALSE); From 661430fd1f052c5589bcd5d116f37b9ee4e27210 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Sat, 1 Nov 2014 00:06:05 +0800 Subject: [PATCH 506/543] [xml] XmlDocument.ReadNode() should not special case XmlTextReader. Added test case that proves this change (by baulig). --- .../System.XML/System.Xml/XmlDocument.cs | 15 +------- .../Test/System.Xml/XmlTextReaderTests.cs | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/mcs/class/System.XML/System.Xml/XmlDocument.cs b/mcs/class/System.XML/System.Xml/XmlDocument.cs index 4d1db5db58f..c93d68b5f37 100644 --- a/mcs/class/System.XML/System.Xml/XmlDocument.cs +++ b/mcs/class/System.XML/System.Xml/XmlDocument.cs @@ -858,20 +858,7 @@ internal void ReadAttributeNodeValue (XmlReader reader, XmlAttribute attribute) [PermissionSet (SecurityAction.InheritanceDemand, Unrestricted = true)] public virtual XmlNode ReadNode (XmlReader reader) { - if (PreserveWhitespace) - return ReadNodeCore (reader); - XmlTextReader xtr = reader as XmlTextReader; - if (xtr != null && xtr.WhitespaceHandling == - WhitespaceHandling.All) { - try { - xtr.WhitespaceHandling = WhitespaceHandling.Significant; - return ReadNodeCore (reader); - } finally { - xtr.WhitespaceHandling = WhitespaceHandling.All; - } - } - else - return ReadNodeCore (reader); + return ReadNodeCore (reader); } XmlNode ReadNodeCore (XmlReader reader) diff --git a/mcs/class/System.XML/Test/System.Xml/XmlTextReaderTests.cs b/mcs/class/System.XML/Test/System.Xml/XmlTextReaderTests.cs index d0898923255..596a808aac3 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlTextReaderTests.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlTextReaderTests.cs @@ -1433,5 +1433,43 @@ public void XmlDeclarationReadAttributeValue2 () Assert.IsFalse (reader.ReadAttributeValue(), "#4"); Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#5"); } + + [Test] + public void Whitespaces () + { + const string xml = " World Bar"; + var reader = new XmlTextReader (new StringReader (xml)); + //reader.WhitespaceHandling = WhitespaceHandling.All; + + reader.Read (); + Assert.AreEqual (XmlNodeType.XmlDeclaration, reader.NodeType, "#1a"); + reader.Read (); + Assert.AreEqual (XmlNodeType.Element, reader.NodeType, "#1b"); + Assert.AreEqual ("test", reader.Name, "#1c"); + + reader.Read (); + if (reader.NodeType == XmlNodeType.Whitespace) + reader.Read (); + + Assert.AreEqual (XmlNodeType.Element, reader.NodeType, "#2a"); + Assert.AreEqual ("foo", reader.Name, "#2b"); + + var doc = new XmlDocument (); + //doc.PreserveWhitespace = true; + doc.ReadNode (reader); + + Assert.AreEqual (XmlNodeType.Whitespace, reader.NodeType, "#3"); + + reader.Read (); + if (reader.NodeType == XmlNodeType.Whitespace) + reader.Read (); + + Assert.AreEqual (XmlNodeType.Element, reader.NodeType, "#4"); + Assert.AreEqual ("foo", reader.Name, "#4b"); + + doc.ReadNode (reader); + + Assert.AreEqual (XmlNodeType.EndElement, reader.NodeType, "#5"); + } } } From b11044a9a64a6b1eff3a0c79c2da2b2ba78808d3 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Sat, 1 Nov 2014 20:48:12 -0400 Subject: [PATCH 507/543] [asp.net] Implement the EventHandlerTaskAsyncHelper and HttpTaskAsyncHandler classes; Manually bring Pull Request 1365 from Kornel Pal --- mcs/class/System.Web/System.Web-net_4_5.csproj | 4 ++++ mcs/class/System.Web/System.Web-plainweb-net_4_5.csproj | 5 +++++ mcs/class/System.Web/System.Web-tests-net_4_5.csproj | 3 +++ mcs/class/System.Web/System.Web_test.dll.sources | 3 +++ mcs/class/System.Web/net_4_5_System.Web.dll.sources | 4 ++++ 5 files changed, 19 insertions(+) diff --git a/mcs/class/System.Web/System.Web-net_4_5.csproj b/mcs/class/System.Web/System.Web-net_4_5.csproj index 186581616b8..0c32f157647 100644 --- a/mcs/class/System.Web/System.Web-net_4_5.csproj +++ b/mcs/class/System.Web/System.Web-net_4_5.csproj @@ -1249,6 +1249,7 @@ + @@ -1294,6 +1295,7 @@ + @@ -1333,6 +1335,8 @@ + + diff --git a/mcs/class/System.Web/System.Web-plainweb-net_4_5.csproj b/mcs/class/System.Web/System.Web-plainweb-net_4_5.csproj index 5f49197e3f6..d4a107dec05 100644 --- a/mcs/class/System.Web/System.Web-plainweb-net_4_5.csproj +++ b/mcs/class/System.Web/System.Web-plainweb-net_4_5.csproj @@ -1249,6 +1249,7 @@ + @@ -1294,6 +1295,7 @@ + @@ -1321,6 +1323,7 @@ + @@ -1332,6 +1335,8 @@ + + diff --git a/mcs/class/System.Web/System.Web-tests-net_4_5.csproj b/mcs/class/System.Web/System.Web-tests-net_4_5.csproj index 6db954a2f78..bb9302e4995 100644 --- a/mcs/class/System.Web/System.Web-tests-net_4_5.csproj +++ b/mcs/class/System.Web/System.Web-tests-net_4_5.csproj @@ -556,6 +556,7 @@ + @@ -591,6 +592,7 @@ + @@ -602,6 +604,7 @@ + diff --git a/mcs/class/System.Web/System.Web_test.dll.sources b/mcs/class/System.Web/System.Web_test.dll.sources index fd634af76c3..055791f7b96 100644 --- a/mcs/class/System.Web/System.Web_test.dll.sources +++ b/mcs/class/System.Web/System.Web_test.dll.sources @@ -45,6 +45,7 @@ mainsoft/NunitWeb/NunitWeb/Tests/AuthorConverter.cs mainsoft/NunitWeb/NunitWeb/Tests/Book.cs mainsoft/NunitWeb/NunitWeb/Tests/BookType.cs System.Web/AppBrowsersTest.cs +System.Web/EventHandlerTaskAsyncHelperTest.cs System.Web/HttpApplicationTest.cs System.Web/HttpBrowserCapabilitiesTest.cs System.Web/HttpCacheVaryByContentEncodingsTest.cs @@ -58,10 +59,12 @@ System.Web/HttpRequestTest.cs System.Web/HttpResponseTest.cs System.Web/HttpRuntimeTest.cs System.Web/HttpServerUtilityTest.cs +System.Web/HttpTaskAsyncHandlerTest.cs System.Web/HttpUtilityTest.cs System.Web/SiteMapProviderTest.cs System.Web/SiteMapNodeTest.cs System.Web/StaticSiteMapProviderTest.cs +System.Web/TaskAsyncResultTest.cs System.Web/TraceContextRecordTest.cs System.Web.Compilation/BuildManagerTest.cs System.Web.Compilation/ClientBuildManagerParameterTest.cs diff --git a/mcs/class/System.Web/net_4_5_System.Web.dll.sources b/mcs/class/System.Web/net_4_5_System.Web.dll.sources index f53e5bb9b76..e4912ae193a 100644 --- a/mcs/class/System.Web/net_4_5_System.Web.dll.sources +++ b/mcs/class/System.Web/net_4_5_System.Web.dll.sources @@ -1,7 +1,11 @@ #include net_4_0_System.Web.dll.sources +System.Web/EventHandlerTaskAsyncHelper.cs +System.Web/HttpTaskAsyncHandler.cs System.Web/MimeMapping.cs System.Web/ReadEntityBodyMode.cs System.Web/UnvalidatedRequestValues.cs System.Web/UnvalidatedRequestValuesBase.cs System.Web/UnvalidatedRequestValuesWrapper.cs +System.Web/TaskAsyncResult.cs +System.Web/TaskEventHandler.cs \ No newline at end of file From 5c23f1e15dc241f8f2f214d485eb186c04f09903 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Sat, 1 Nov 2014 20:49:10 -0400 Subject: [PATCH 508/543] Set ReadEntityBodyMode default to Classic to force clients to use the old method for reading the input stream. According to the MSDN docs, if ReadEntityBodyMode returns "Classic" the code should use the old method to read the input stream (HttpRequestBase.InputStream) which is fully implemented in mono. Manually applied patch from martinjt --- .../System.Web/HttpRequestWrapper.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs index 35f631e37e7..197a7abd1c4 100644 --- a/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs +++ b/mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs @@ -214,6 +214,12 @@ public override UnvalidatedRequestValuesBase Unvalidated { } #endif +#if NET_4_5 + public override ReadEntityBodyMode ReadEntityBodyMode { + get { return ReadEntityBodyMode.Classic; } + } +#endif + public override Uri Url { get { return w.Url; } } From 716c7ad122c08c2e7d203066e9ce5bcd8fa5e42b Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Sat, 1 Nov 2014 21:23:05 -0400 Subject: [PATCH 509/543] [asp.net] Implement the EventHandlerTaskAsyncHelper and HttpTaskAsyncHandler classes; Manually bring Pull Request 1365 from Kornel Pal --- .../System.Web/EventHandlerTaskAsyncHelper.cs | 62 ++++ .../System.Web/HttpTaskAsyncHandler.cs | 59 ++++ .../System.Web/System.Web/TaskAsyncResult.cs | 101 ++++++ .../System.Web/System.Web/TaskEventHandler.cs | 34 ++ .../EventHandlerTaskAsyncHelperTest.cs | 118 +++++++ .../System.Web/HttpTaskAsyncHandlerTest.cs | 132 +++++++ .../Test/System.Web/TaskAsyncResultTest.cs | 334 ++++++++++++++++++ 7 files changed, 840 insertions(+) create mode 100644 mcs/class/System.Web/System.Web/EventHandlerTaskAsyncHelper.cs create mode 100644 mcs/class/System.Web/System.Web/HttpTaskAsyncHandler.cs create mode 100644 mcs/class/System.Web/System.Web/TaskAsyncResult.cs create mode 100644 mcs/class/System.Web/System.Web/TaskEventHandler.cs create mode 100644 mcs/class/System.Web/Test/System.Web/EventHandlerTaskAsyncHelperTest.cs create mode 100644 mcs/class/System.Web/Test/System.Web/HttpTaskAsyncHandlerTest.cs create mode 100644 mcs/class/System.Web/Test/System.Web/TaskAsyncResultTest.cs diff --git a/mcs/class/System.Web/System.Web/EventHandlerTaskAsyncHelper.cs b/mcs/class/System.Web/System.Web/EventHandlerTaskAsyncHelper.cs new file mode 100644 index 00000000000..d80188befb3 --- /dev/null +++ b/mcs/class/System.Web/System.Web/EventHandlerTaskAsyncHelper.cs @@ -0,0 +1,62 @@ +// +// System.Web.EventHandlerTaskAsyncHelper.cs +// +// Author: +// Kornel Pal (kornelpal@gmail.com) +// +// Copyright (C) 2014 Kornel Pal +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Threading.Tasks; + +namespace System.Web +{ + public sealed class EventHandlerTaskAsyncHelper + { + readonly TaskEventHandler taskEventHandler; + readonly BeginEventHandler beginEventHandler; + static readonly EndEventHandler endEventHandler = TaskAsyncResult.Wait; + + public BeginEventHandler BeginEventHandler { + get { return beginEventHandler; } + } + + public EndEventHandler EndEventHandler { + get { return endEventHandler; } + } + + public EventHandlerTaskAsyncHelper (TaskEventHandler handler) + { + if (handler == null) + throw new ArgumentNullException ("handler"); + + taskEventHandler = handler; + beginEventHandler = GetAsyncResult; + } + + IAsyncResult GetAsyncResult (object sender, EventArgs e, AsyncCallback callback, object state) + { + Task task = taskEventHandler (sender, e); + return TaskAsyncResult.GetAsyncResult (task, callback, state); + } + } +} diff --git a/mcs/class/System.Web/System.Web/HttpTaskAsyncHandler.cs b/mcs/class/System.Web/System.Web/HttpTaskAsyncHandler.cs new file mode 100644 index 00000000000..9cdcf730793 --- /dev/null +++ b/mcs/class/System.Web/System.Web/HttpTaskAsyncHandler.cs @@ -0,0 +1,59 @@ +// +// System.Web.HttpTaskAsyncHandler.cs +// +// Author: +// Kornel Pal (kornelpal@gmail.com) +// +// Copyright (C) 2014 Kornel Pal +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.ComponentModel; +using System.Threading.Tasks; + +namespace System.Web +{ + public abstract class HttpTaskAsyncHandler : IHttpAsyncHandler, IHttpHandler + { + public virtual bool IsReusable { + get { return false; } + } + + [EditorBrowsable (EditorBrowsableState.Never)] + public virtual void ProcessRequest (HttpContext context) + { + throw new NotSupportedException ("This handler cannot be executed synchronously."); + } + + public abstract Task ProcessRequestAsync (HttpContext context); + + IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData) + { + Task task = ProcessRequestAsync (context); + return TaskAsyncResult.GetAsyncResult (task, cb, extraData); + } + + void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result) + { + TaskAsyncResult.Wait (result); + } + } +} diff --git a/mcs/class/System.Web/System.Web/TaskAsyncResult.cs b/mcs/class/System.Web/System.Web/TaskAsyncResult.cs new file mode 100644 index 00000000000..2e3bd2737f0 --- /dev/null +++ b/mcs/class/System.Web/System.Web/TaskAsyncResult.cs @@ -0,0 +1,101 @@ +// +// System.Web.TaskAsyncResult.cs +// +// Author: +// Kornel Pal (kornelpal@gmail.com) +// +// Copyright (C) 2014 Kornel Pal +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Threading; +using System.Threading.Tasks; + +namespace System.Web +{ + sealed class TaskAsyncResult : IAsyncResult + { + static readonly Action invokeCallback = InvokeCallback; + readonly Task task; + readonly AsyncCallback callback; + + public object AsyncState { + get; + private set; + } + + public WaitHandle AsyncWaitHandle { + get { return ((IAsyncResult) task).AsyncWaitHandle; } + } + + public bool CompletedSynchronously { + get; + private set; + } + + public bool IsCompleted { + get { return task.IsCompleted; } + } + + TaskAsyncResult (Task task, AsyncCallback callback, object state) + { + this.task = task; + this.callback = callback; + this.AsyncState = state; + this.CompletedSynchronously = task.IsCompleted; + } + + public static IAsyncResult GetAsyncResult (Task task, AsyncCallback callback, object state) + { + if (task == null) + return null; + + var result = new TaskAsyncResult (task, callback, state); + + if (callback != null) { + if (result.CompletedSynchronously) + callback (result); + else + task.ContinueWith (invokeCallback, result); + } + + return result; + } + + public static void Wait (IAsyncResult result) + { + if (result == null) + throw new ArgumentNullException ("result"); + + var taskAsyncResult = result as TaskAsyncResult; + if (taskAsyncResult == null) + throw new ArgumentException ("The provided IAsyncResult is invalid.", "result"); + + taskAsyncResult.task.GetAwaiter ().GetResult (); + } + + static void InvokeCallback (Task task, object state) + { + var result = (TaskAsyncResult) state; + result.callback (result); + } + } +} diff --git a/mcs/class/System.Web/System.Web/TaskEventHandler.cs b/mcs/class/System.Web/System.Web/TaskEventHandler.cs new file mode 100644 index 00000000000..9fc7988ce50 --- /dev/null +++ b/mcs/class/System.Web/System.Web/TaskEventHandler.cs @@ -0,0 +1,34 @@ +// +// System.Web.TaskEventHandler.cs +// +// Author: +// Kornel Pal (kornelpal@gmail.com) +// +// Copyright (C) 2014 Kornel Pal +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Threading.Tasks; + +namespace System.Web +{ + public delegate Task TaskEventHandler (object sender, EventArgs e); +} diff --git a/mcs/class/System.Web/Test/System.Web/EventHandlerTaskAsyncHelperTest.cs b/mcs/class/System.Web/Test/System.Web/EventHandlerTaskAsyncHelperTest.cs new file mode 100644 index 00000000000..9ae8aae0554 --- /dev/null +++ b/mcs/class/System.Web/Test/System.Web/EventHandlerTaskAsyncHelperTest.cs @@ -0,0 +1,118 @@ +// +// MonoTests.System.Web.EventHandlerTaskAsyncHelperTest.cs +// +// Author: +// Kornel Pal (kornelpal@gmail.com) +// +// Copyright (C) 2014 Kornel Pal +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if NET_4_5 + +using System; +using System.Threading.Tasks; +using System.Web; +using NUnit.Framework; + +namespace MonoTests.System.Web +{ + [TestFixture] + public sealed class EventHandlerTaskAsyncHelperTest : TaskAsyncResultTest + { + EventHandlerTaskAsyncHelper helper; + object expectedSender; + EventArgs expectedEventArgs; + + static Task DummyTaskEventHandler (object sender, EventArgs e) + { + throw new AssertionException ("Should not be called."); + } + + protected override void SetNullArguments () + { + expectedSender = null; + expectedEventArgs = null; + } + + protected override IAsyncResult GetAsyncResult (Func taskFactory, AsyncCallback callback, object state) + { + Assert.IsNull (helper, "GetAsyncResult#A01"); + + TaskEventHandler handler = (sender, e) => { + Assert.AreSame (expectedSender, sender, "GetAsyncResult#A02"); + Assert.AreSame (expectedEventArgs, e, "GetAsyncResult#A03"); + + return taskFactory (); + }; + + helper = new EventHandlerTaskAsyncHelper (handler); + return helper.BeginEventHandler (expectedSender, expectedEventArgs, callback, state); + } + + protected override void Wait (IAsyncResult result) + { + Assert.IsNotNull (helper, "Wait#A01"); + + helper.EndEventHandler (result); + } + + protected override void TestSetUp () + { + base.TestSetUp (); + + helper = null; + expectedSender = new object (); + expectedEventArgs = new EventArgs (); + } + + [Test] + public void Constructor () + { + var helper = new EventHandlerTaskAsyncHelper (DummyTaskEventHandler); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void Constructor_NullHandler () + { + var helper = new EventHandlerTaskAsyncHelper (null); + } + + [Test] + public void BeginEventHandler () + { + var helper = new EventHandlerTaskAsyncHelper (DummyTaskEventHandler); + + Assert.IsNotNull (helper.BeginEventHandler, "#A01"); + } + + [Test] + public void EndEventHandler () + { + var helper = new EventHandlerTaskAsyncHelper (DummyTaskEventHandler); + + Assert.IsNotNull (helper.EndEventHandler, "#A01"); + } + } +} + +#endif diff --git a/mcs/class/System.Web/Test/System.Web/HttpTaskAsyncHandlerTest.cs b/mcs/class/System.Web/Test/System.Web/HttpTaskAsyncHandlerTest.cs new file mode 100644 index 00000000000..50afda19bcb --- /dev/null +++ b/mcs/class/System.Web/Test/System.Web/HttpTaskAsyncHandlerTest.cs @@ -0,0 +1,132 @@ +// +// MonoTests.System.Web.HttpTaskAsyncHandlerTest.cs +// +// Author: +// Kornel Pal (kornelpal@gmail.com) +// +// Copyright (C) 2014 Kornel Pal +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if NET_4_5 + +using System; +using System.IO; +using System.Threading.Tasks; +using System.Web; +using NUnit.Framework; + +namespace MonoTests.System.Web +{ + [TestFixture] + public sealed class HttpTaskAsyncHandlerTest : TaskAsyncResultTest + { + sealed class DummyHttpTaskAsyncHandler : HttpTaskAsyncHandler + { + public DummyHttpTaskAsyncHandler () + { + } + + public override Task ProcessRequestAsync (HttpContext context) + { + throw new AssertionException ("Should not be called."); + } + } + + sealed class TestHttpTaskAsyncHandler : HttpTaskAsyncHandler + { + readonly Func taskFactory; + readonly HttpContext expectedContext; + + public TestHttpTaskAsyncHandler (Func taskFactory, HttpContext expectedContext) + { + this.taskFactory = taskFactory; + this.expectedContext = expectedContext; + } + + public override Task ProcessRequestAsync (HttpContext context) + { + Assert.AreSame (expectedContext, context, "TestHttpTaskAsyncHandler#A01"); + + return taskFactory (); + } + } + + IHttpAsyncHandler handler; + HttpContext expectedContext; + + protected override void SetNullArguments () + { + expectedContext = null; + } + + protected override IAsyncResult GetAsyncResult (Func taskFactory, AsyncCallback callback, object state) + { + Assert.IsNull (handler, "GetAsyncResult#A01"); + + handler = new TestHttpTaskAsyncHandler (taskFactory, expectedContext); + return handler.BeginProcessRequest (expectedContext, callback, state); + } + + protected override void Wait (IAsyncResult result) + { + Assert.IsNotNull (handler, "Wait#A01"); + + handler.EndProcessRequest (result); + } + + protected override void TestSetUp () + { + base.TestSetUp (); + + handler = null; + + var request = new HttpRequest (string.Empty, "http://localhost/", string.Empty); + var response = new HttpResponse (TextWriter.Null); + expectedContext = new HttpContext (request, response); + } + + [Test] + public void IsReusable () + { + var handler = new DummyHttpTaskAsyncHandler (); + Assert.IsFalse (handler.IsReusable, "#A01"); + } + + [Test] + [ExpectedException (typeof (NotSupportedException))] + public void ProcessRequest () + { + var handler = new DummyHttpTaskAsyncHandler (); + handler.ProcessRequest (expectedContext); + } + + [Test] + [ExpectedException (typeof (NotSupportedException))] + public void ProcessRequest_NullContext () + { + var handler = new DummyHttpTaskAsyncHandler (); + handler.ProcessRequest (null); + } + } +} + +#endif diff --git a/mcs/class/System.Web/Test/System.Web/TaskAsyncResultTest.cs b/mcs/class/System.Web/Test/System.Web/TaskAsyncResultTest.cs new file mode 100644 index 00000000000..301a2988a3c --- /dev/null +++ b/mcs/class/System.Web/Test/System.Web/TaskAsyncResultTest.cs @@ -0,0 +1,334 @@ +// +// MonoTests.System.Web.TaskAsyncResultTest.cs +// +// Author: +// Kornel Pal (kornelpal@gmail.com) +// +// Copyright (C) 2014 Kornel Pal +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if NET_4_5 + +using System; +using System.Threading; +using System.Threading.Tasks; +using NUnit.Framework; + +namespace MonoTests.System.Web +{ + public abstract class TaskAsyncResultTest + { + sealed class TestException : Exception + { + public TestException () + : base ("Test exception") + { + } + } + + sealed class DummyAsyncResult : IAsyncResult + { + public object AsyncState { + get { throw new AssertionException ("Should not be called."); } + } + + public WaitHandle AsyncWaitHandle { + get { throw new AssertionException ("Should not be called."); } + } + + public bool CompletedSynchronously { + get { throw new AssertionException ("Should not be called."); } + } + + public bool IsCompleted { + get { throw new AssertionException ("Should not be called."); } + } + } + + int testThreadId; + int factoryCount; + int callbackCount; + object expectedState; + Exception expectedException; + TaskCompletionSource taskCompletion; + TaskCompletionSource callbackCompletion; + IAsyncResult taskAsyncResult; + + static Task NullTaskFatory () + { + return null; + } + + static Task CompletedTaskFatory () + { + return Task.FromResult (null); + } + + static Task FailingTaskFatory () + { + throw new TestException (); + } + + void DummyCallback (IAsyncResult result) + { + Interlocked.Increment (ref callbackCount); + + Assert.Fail ("Should not be called."); + } + + void FailingCallback (IAsyncResult result) + { + Interlocked.Increment (ref callbackCount); + + throw new TestException (); + } + + protected abstract void SetNullArguments (); + protected abstract IAsyncResult GetAsyncResult (Func taskFactory, AsyncCallback callback, object state); + protected abstract void Wait (IAsyncResult result); + + [SetUp] + protected virtual void TestSetUp () + { + testThreadId = Thread.CurrentThread.ManagedThreadId; + factoryCount = 0; + callbackCount = 0; + expectedState = new object (); + expectedException = null; + taskCompletion = new TaskCompletionSource (); + callbackCompletion = new TaskCompletionSource (); + taskAsyncResult = null; + } + + [Test] + public void Invoke_NullArguments () + { + SetNullArguments (); + + IAsyncResult result = GetAsyncResult (CompletedTaskFatory, null, null); + Wait (result); + } + + [Test] + public void Invoke_NullTask () + { + IAsyncResult result = GetAsyncResult (NullTaskFatory, DummyCallback, null); + + Assert.AreEqual (0, callbackCount, "#A01"); + Assert.IsNull (result, "#A02"); + } + + [Test] + [ExpectedException (typeof (TestException))] + public void Invoke_TaskFatoryException () + { + try { + GetAsyncResult (FailingTaskFatory, DummyCallback, expectedState); + } finally { + Assert.AreEqual (0, callbackCount, "#A01"); + } + } + + [Test] + [ExpectedException (typeof (TestException))] + public void Invoke_CallbackException () + { + try { + GetAsyncResult (CompletedTaskFatory, FailingCallback, expectedState); + } finally { + Assert.AreEqual (1, callbackCount, "#A01"); + } + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void Invoke_NullResult () + { + GetAsyncResult (NullTaskFatory, DummyCallback, null); + Wait (null); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public void Invoke_InvalidResult () + { + GetAsyncResult (NullTaskFatory, DummyCallback, null); + Wait (new DummyAsyncResult ()); + } + + void SetTaskResult () + { + if (expectedException == null) + taskCompletion.SetResult (null); + else + taskCompletion.SetException (expectedException); + } + + void WaitTaskResult () + { + if (expectedException == null) { + Wait (taskAsyncResult); + return; + } + + try { + Wait (taskAsyncResult); + + Assert.Fail ("Expected exception was not thrown."); + } catch (AssertionException) { + throw; + } catch (Exception ex) { + Assert.AreSame (expectedException, ex, "WaitTaskResult#A01"); + } + } + + [Test] + public void InvokeSync () + { + InvokeSyncCore (); + } + + [Test] + public void InvokeSync_Failed () + { + expectedException = new TestException (); + + InvokeSyncCore (); + } + + void InvokeSyncCore () + { + IAsyncResult result = GetAsyncResult (SyncTaskFatory, SyncCallback, expectedState); + + Assert.IsNotNull (result, "InvokeSyncCore#A01"); + Assert.AreSame (taskAsyncResult, result, "InvokeSyncCore#A02"); + + WaitTaskResult (); + + Assert.AreEqual (1, factoryCount, "InvokeSyncCore#A03"); + Assert.AreEqual (1, callbackCount, "InvokeSyncCore#A04"); + } + + Task SyncTaskFatory () + { + Interlocked.Increment (ref factoryCount); + + Assert.AreEqual (testThreadId, Thread.CurrentThread.ManagedThreadId, "SyncTaskFatory#A01"); + + SetTaskResult (); + + return taskCompletion.Task; + } + + void SyncCallback (IAsyncResult result) + { + Interlocked.Increment (ref callbackCount); + + Assert.AreEqual (testThreadId, Thread.CurrentThread.ManagedThreadId, "SyncCallback#A01"); + + Assert.IsNotNull (result, "SyncCallback#A02"); + Assert.AreSame (expectedState, result.AsyncState, "SyncCallback#A03"); + Assert.IsTrue (result.IsCompleted, "SyncCallback#A04"); + Assert.IsTrue (result.CompletedSynchronously, "SyncCallback#A05"); + Assert.IsNotNull (result.AsyncWaitHandle, "SyncCallback#A06"); + Assert.IsTrue (result.AsyncWaitHandle.WaitOne (0), "SyncCallback#A07"); + + taskAsyncResult = result; + + Assert.AreEqual (1, factoryCount, "SyncCallback#A08"); + Assert.AreEqual (1, callbackCount, "SyncCallback#A09"); + } + + [Test] + public void InvokeAsync () + { + InvokeAsyncCore (); + } + + [Test] + public void InvokeAsync_Failed () + { + expectedException = new TestException (); + + InvokeAsyncCore (); + } + + void InvokeAsyncCore () + { + IAsyncResult result = GetAsyncResult (AsyncTaskFatory, AsyncCallback, expectedState); + + Assert.IsNotNull (result, "InvokeAsyncCore#A01"); + Assert.AreSame (expectedState, result.AsyncState, "InvokeAsyncCore#A02"); + Assert.IsFalse (result.IsCompleted, "InvokeAsyncCore#A03"); + Assert.IsFalse (result.CompletedSynchronously, "InvokeAsyncCore#A04"); + Assert.IsNotNull (result.AsyncWaitHandle, "InvokeAsyncCore#A05"); + Assert.IsFalse (result.AsyncWaitHandle.WaitOne (0), "InvokeAsyncCore#A06"); + + Assert.AreEqual (1, factoryCount, "InvokeAsyncCore#A07"); + Assert.AreEqual (0, callbackCount, "InvokeAsyncCore#A08"); + + taskAsyncResult = result; + + SetTaskResult (); + + callbackCompletion.Task.GetAwaiter ().GetResult (); + + Assert.AreEqual (1, factoryCount, "InvokeAsyncCore#A09"); + Assert.AreEqual (1, callbackCount, "InvokeAsyncCore#A10"); + } + + Task AsyncTaskFatory () + { + Interlocked.Increment (ref factoryCount); + + Assert.AreEqual (testThreadId, Thread.CurrentThread.ManagedThreadId, "AsyncTaskFatory#A01"); + + return taskCompletion.Task; + } + + void AsyncCallback (IAsyncResult result) + { + try { + Interlocked.Increment (ref callbackCount); + + Assert.AreNotEqual (testThreadId, Thread.CurrentThread.ManagedThreadId, "AsyncCallback#A01"); + + Assert.IsNotNull (result, "AsyncCallback#A02"); + Assert.AreSame (expectedState, result.AsyncState, "AsyncCallback#A03"); + Assert.IsTrue (result.IsCompleted, "AsyncCallback#A04"); + Assert.IsFalse (result.CompletedSynchronously, "AsyncCallback#A05"); + Assert.IsNotNull (result.AsyncWaitHandle, "AsyncCallback#A06"); + Assert.IsTrue (result.AsyncWaitHandle.WaitOne (0), "AsyncCallback#A07"); + + Assert.AreSame (taskAsyncResult, result, "AsyncCallback#A08"); + + WaitTaskResult (); + + callbackCompletion.TrySetResult (null); + } catch (Exception ex) { + callbackCompletion.TrySetException (ex); + } + } + } +} + +#endif From 57feacab954cd61844bf28b2ec285c3704b0bdd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Fri, 31 Oct 2014 23:07:28 +0100 Subject: [PATCH 510/543] Add missing newline in .sources file, should fix build --- mcs/class/System.Web/net_4_5_System.Web.dll.sources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.Web/net_4_5_System.Web.dll.sources b/mcs/class/System.Web/net_4_5_System.Web.dll.sources index e4912ae193a..ea8508f9110 100644 --- a/mcs/class/System.Web/net_4_5_System.Web.dll.sources +++ b/mcs/class/System.Web/net_4_5_System.Web.dll.sources @@ -8,4 +8,4 @@ System.Web/UnvalidatedRequestValues.cs System.Web/UnvalidatedRequestValuesBase.cs System.Web/UnvalidatedRequestValuesWrapper.cs System.Web/TaskAsyncResult.cs -System.Web/TaskEventHandler.cs \ No newline at end of file +System.Web/TaskEventHandler.cs From 7b4bd74b4db0f7516f9b7d1d6867d4105fde1ab6 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 3 Nov 2014 16:06:46 -0500 Subject: [PATCH 511/543] [jit] Reenable the more efficient cast code in gshared methods. --- mono/mini/method-to-ir.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 7a8c4d3f9f8..19c7eec8d0d 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -4081,8 +4081,7 @@ mini_class_has_reference_variant_generic_argument (MonoCompile *cfg, MonoClass * return FALSE; } -// FIXME: This doesn't work yet (class libs tests fail?) -#define is_complex_isinst(klass) (TRUE || (klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) +#define is_complex_isinst(klass) ((klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) static MonoInst* emit_castclass_with_cache (MonoCompile *cfg, MonoClass *klass, MonoInst **args, MonoBasicBlock **out_bblock) From 1c6da6b912f6e647bdb2313d65cb54cdca630605 Mon Sep 17 00:00:00 2001 From: Martin Thwaites Date: Fri, 24 Oct 2014 22:42:49 +0100 Subject: [PATCH 512/543] Added the MembershipPasswordAttribute class and associated unit tests --- mcs/class/Makefile | 2 +- mcs/class/System.Web/Makefile | 3 +- .../MembershipPasswordAttribute.cs | 110 ++++++++++++++ .../System.Web/System.Web_test.dll.sources | 1 + .../MembershipPasswordAttributeTest.cs | 137 ++++++++++++++++++ .../System.Web/net_4_5_System.Web.dll.sources | 1 + 6 files changed, 252 insertions(+), 2 deletions(-) create mode 100644 mcs/class/System.Web/System.Web.Security/MembershipPasswordAttribute.cs create mode 100644 mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs diff --git a/mcs/class/Makefile b/mcs/class/Makefile index 8ca914dca53..3ab5668acc7 100644 --- a/mcs/class/Makefile +++ b/mcs/class/Makefile @@ -33,6 +33,7 @@ net_2_0_dirs := \ System.EnterpriseServices \ Mono.Data.Tds \ System.Data \ + System.ComponentModel.DataAnnotations \ Accessibility \ Mono.WebBrowser \ System.Runtime.Serialization.Formatters.Soap \ @@ -81,7 +82,6 @@ net_2_0_dirs := \ System.ServiceModel \ System.Web.Extensions \ System.Web.Extensions.Design \ - System.ComponentModel.DataAnnotations \ System.Web.DynamicData \ System.Web.Mvc2 \ Mono.C5 \ diff --git a/mcs/class/System.Web/Makefile b/mcs/class/System.Web/Makefile index c11810f1f8a..bcde5188662 100644 --- a/mcs/class/System.Web/Makefile +++ b/mcs/class/System.Web/Makefile @@ -255,6 +255,7 @@ LIB_MCS_FLAGS = \ -r:System.Xml.dll \ -r:System.EnterpriseServices.dll \ -r:System.Runtime.Serialization.Formatters.Soap \ + -r:System.ComponentModel.DataAnnotations.dll \ $(OTHER_LIB_MCS_FLAGS) \ $(RESX_RES:%=/resource:%) \ $(OTHER_RES:%=/resource:%) @@ -447,4 +448,4 @@ ifneq ($(PROFILE),basic) csproj-local: $(MAKE) csproj-local intermediate=plainweb/ endif -endif \ No newline at end of file +endif diff --git a/mcs/class/System.Web/System.Web.Security/MembershipPasswordAttribute.cs b/mcs/class/System.Web/System.Web.Security/MembershipPasswordAttribute.cs new file mode 100644 index 00000000000..7c85bd06e6f --- /dev/null +++ b/mcs/class/System.Web/System.Web.Security/MembershipPasswordAttribute.cs @@ -0,0 +1,110 @@ +// +// System.Web.Security.MembershipPasswordAttribute +// +// Authors: +// Martin Thwaites (github@my2cents.co.uk) +// +// (C) 2014 Martin Thwaites +// +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text.RegularExpressions; + +namespace System.Web.Security +{ + [AttributeUsageAttribute (AttributeTargets.Property|AttributeTargets.Field|AttributeTargets.Parameter, AllowMultiple = false)] + public class MembershipPasswordAttribute : ValidationAttribute + { + public string MinNonAlphanumericCharactersError { get; set; } + public string MinPasswordLengthError { get; set; } + public int MinRequiredNonAlphanumericCharacters { get; set; } + public int MinRequiredPasswordLength { get; set; } + public string PasswordStrengthError { get; set; } + public string PasswordStrengthRegularExpression { get; set; } + public Type ResourceType { get; set; } + + public MembershipPasswordAttribute () + { + if (Membership.Provider != null) + { + MinRequiredNonAlphanumericCharacters = Membership.Provider.MinRequiredNonAlphanumericCharacters; + MinRequiredPasswordLength = Membership.Provider.MinRequiredPasswordLength; + PasswordStrengthRegularExpression = Membership.Provider.PasswordStrengthRegularExpression; + } + else + { + MinRequiredPasswordLength = 7; + MinRequiredNonAlphanumericCharacters = 1; + PasswordStrengthRegularExpression = @"(?=.{6,})(?=(.*\d){1,})(?=(.*\W){1,})"; + } + MinNonAlphanumericCharactersError = "The '{0}' field is an invalid password. Password must have {1} or more non-alphanumeric characters."; + MinPasswordLengthError = "The '{0}' field is an invalid password. Password must have {1} or more characters."; + PasswordStrengthError = "The '{0}' field is an invalid password. It does not meet the password strength requirements"; + ErrorMessage = "The field {0} is invalid."; + } + + protected override ValidationResult IsValid (object value, ValidationContext validationContext) + { + var password = value as string; + var isError = false; + if (string.IsNullOrEmpty(password)) + return null; + + var errorMessage = string.Empty; + var parameter = 0; + var pattern = new Regex (@"\W|_"); + + if (MinRequiredPasswordLength > 0 && + password.Length < MinRequiredPasswordLength) { + errorMessage = MinPasswordLengthError; + parameter = MinRequiredPasswordLength; + isError = true; + } + + if (!isError && MinRequiredNonAlphanumericCharacters > 0 && + pattern.Matches (password).Count < MinRequiredNonAlphanumericCharacters) { + errorMessage = MinNonAlphanumericCharactersError; + parameter = MinRequiredNonAlphanumericCharacters; + isError = true; + } + + if (!isError && !string.IsNullOrEmpty (PasswordStrengthRegularExpression) && + new Regex (PasswordStrengthRegularExpression).IsMatch (password)) { + errorMessage = PasswordStrengthError; + isError = true; + } + + if (isError) { + if (validationContext == null) + return new ValidationResult("error"); + + return new ValidationResult ( + string.Format (errorMessage, validationContext.DisplayName, parameter), + new[] {validationContext.MemberName}); + } + + return ValidationResult.Success; + } + } +} diff --git a/mcs/class/System.Web/System.Web_test.dll.sources b/mcs/class/System.Web/System.Web_test.dll.sources index 055791f7b96..29339b428c9 100644 --- a/mcs/class/System.Web/System.Web_test.dll.sources +++ b/mcs/class/System.Web/System.Web_test.dll.sources @@ -106,6 +106,7 @@ System.Web.Profile/ProfileInfoTest.cs System.Web.Security/FormsAuthenticationTest.cs System.Web.Security/FormsIdentityTest.cs System.Web.Security/MembershipTest.cs +System.Web.Security/MembershipPasswordAttributeTest.cs System.Web.Security/MembershipProviderCollectionTest.cs System.Web.Security/MembershipProviderTest.cs System.Web.Security/MembershipUserCollectionTest.cs diff --git a/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs b/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs new file mode 100644 index 00000000000..2559089b92b --- /dev/null +++ b/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs @@ -0,0 +1,137 @@ +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Web.Security; +using NUnit.Framework; + +namespace MonoTests.System.Web.Security { + + [TestFixture] + public class MembershipPasswordAttributeTest + { + private ValidationContext _validationContext; + + public MembershipPasswordAttributeTest () + { + _validationContext = new ValidationContext (new object ()) + { + DisplayName = "testDisplay", + MemberName = "testMember" + }; + } + + [Test] + public void IsValid () + { + var passwordAttribute = new MembershipPasswordAttributeTestClass (); + Assert.IsTrue (passwordAttribute.IsValid (""), "sending an empty password password should should be treated as valid"); + } + + [Test] + public void IsValid_with_ValidationContext () + { + var passwordAttribute = new MembershipPasswordAttributeTestClass (); + var result = passwordAttribute.TestValidation ("", _validationContext); + Assert.IsNull (result, "sending an empty password password should return a null response"); + + result = passwordAttribute.TestValidation ("a!12345", _validationContext); + Assert.AreEqual (ValidationResult.Success, result, "Should suceed with a 7 character length and a single nonalphanumeric"); + + // test error priority + passwordAttribute.MinRequiredPasswordLength = 4; + passwordAttribute.MinRequiredNonAlphanumericCharacters = 2; + result = passwordAttribute.TestValidation ("aaa", _validationContext); + Assert.AreEqual ("The 'testDisplay' field is an invalid password. Password must have 4 or more characters.", result.ErrorMessage); + + } + + [Test] + public void MinRequiredPasswordLength () + { + var passwordAttribute = new MembershipPasswordAttributeTestClass (); + var result = passwordAttribute.TestValidation ("a!1234", _validationContext); + Assert.AreEqual ("The 'testDisplay' field is an invalid password. Password must have 7 or more characters.", result.ErrorMessage, "Error message not correct for lower Min characters"); + Assert.AreEqual (_validationContext.MemberName, result.MemberNames.FirstOrDefault (), "Member name not correct"); + + passwordAttribute.MinRequiredPasswordLength = 6; + result = passwordAttribute.TestValidation ("a!1234", _validationContext); + Assert.AreEqual (ValidationResult.Success, result, "Should suceed with a 6 character length after it's reset"); + + result = passwordAttribute.TestValidation ("a!123", _validationContext); + Assert.AreEqual("The 'testDisplay' field is an invalid password. Password must have 6 or more characters.", result.ErrorMessage, "Error message not correct for Min characters of 6"); + + + passwordAttribute.MinRequiredPasswordLength = 1; + result = passwordAttribute.TestValidation ("!", _validationContext); + Assert.AreEqual(ValidationResult.Success, result, "Should suceed with a 6 character length after it's reset"); + + // Note there is no test for empty password here as it returns null and is therefore in the generic test + + // Error Message changes + passwordAttribute.MinRequiredPasswordLength = 5; + passwordAttribute.MinPasswordLengthError = "There was an error"; + result = passwordAttribute.TestValidation ("a!13", _validationContext); + Assert.AreEqual("There was an error", result.ErrorMessage, "Error Message wasn't correct without parameters."); + + passwordAttribute.MinPasswordLengthError = "There was an error parameter1: {0}"; + result = passwordAttribute.TestValidation ("a!13", _validationContext); + Assert.AreEqual("There was an error parameter1: testDisplay", result.ErrorMessage, "Error Message wasn't correct with 1 parameter."); + + passwordAttribute.MinPasswordLengthError = "There was an error parameter1: {0} parameter2: {1}"; + result = passwordAttribute.TestValidation ("a!13", _validationContext); + Assert.AreEqual ("There was an error parameter1: testDisplay parameter2: 5", result.ErrorMessage, "Error Message wasn't correct with 2 parameters."); + + } + + [Test] + public void MinRequiredNonAlphanumericCharacters () + { + var passwordAttribute = new MembershipPasswordAttributeTestClass (); + var result = passwordAttribute.TestValidation ("a!12345", _validationContext); + Assert.AreEqual (ValidationResult.Success, result, "Should succeed with the default 1 non alpha numeric"); + + result = passwordAttribute.TestValidation ("a123456", _validationContext); + Assert.AreEqual ("The 'testDisplay' field is an invalid password. Password must have 1 or more non-alphanumeric characters.", result.ErrorMessage, "Expected validation to fail without non-alphanumerics"); + + + passwordAttribute.MinRequiredNonAlphanumericCharacters = 3; + result = passwordAttribute.TestValidation ("a!&12345", _validationContext); + Assert.AreEqual ("The 'testDisplay' field is an invalid password. Password must have 3 or more non-alphanumeric characters.", result.ErrorMessage, "Expected validation to fail without 3 non-alphanumerics"); + + result = passwordAttribute.TestValidation ("a!?&132154", _validationContext); + Assert.AreEqual (ValidationResult.Success, result, "Should succeed with 3 non alpha numerics"); + + passwordAttribute.MinRequiredNonAlphanumericCharacters = 0; + result = passwordAttribute.TestValidation ("a123456", _validationContext); + Assert.AreEqual (ValidationResult.Success, result, "Should succeed with 0 non alpha numerics"); + + // Error Message changes + passwordAttribute.MinRequiredNonAlphanumericCharacters = 1; + passwordAttribute.MinNonAlphanumericCharactersError = "There was an error"; + result = passwordAttribute.TestValidation ("a123456", _validationContext); + Assert.AreEqual ("There was an error", result.ErrorMessage, "Error Message wasn't correct without parameters."); + + passwordAttribute.MinNonAlphanumericCharactersError = "There was an error parameter1: {0}"; + result = passwordAttribute.TestValidation ("a123456", _validationContext); + Assert.AreEqual("There was an error parameter1: testDisplay", result.ErrorMessage, "Error Message wasn't correct with 1 parameter."); + + passwordAttribute.MinNonAlphanumericCharactersError = "There was an error parameter1: {0} parameter2: {1}"; + result = passwordAttribute.TestValidation ("a123456", _validationContext); + Assert.AreEqual ("There was an error parameter1: testDisplay parameter2: 1", result.ErrorMessage, "Error Message wasn't correct with 2 parameters."); + } + + [Test] + public void FormatErrorMessage () + { + var passwordAttribute = new MembershipPasswordAttribute (); + Assert.AreEqual ("The field testDisplay2 is invalid.", passwordAttribute.FormatErrorMessage ("testDisplay2")); + } + + internal class MembershipPasswordAttributeTestClass : MembershipPasswordAttribute + { + public ValidationResult TestValidation (object val, ValidationContext context) + { + return IsValid (val, context); + } + } + } +} diff --git a/mcs/class/System.Web/net_4_5_System.Web.dll.sources b/mcs/class/System.Web/net_4_5_System.Web.dll.sources index ea8508f9110..8703eb00471 100644 --- a/mcs/class/System.Web/net_4_5_System.Web.dll.sources +++ b/mcs/class/System.Web/net_4_5_System.Web.dll.sources @@ -9,3 +9,4 @@ System.Web/UnvalidatedRequestValuesBase.cs System.Web/UnvalidatedRequestValuesWrapper.cs System.Web/TaskAsyncResult.cs System.Web/TaskEventHandler.cs +System.Web.Security/MembershipPasswordAttribute.cs From 92c91d75f0dfd91a0b1a29bf3af2917dc3f44655 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 3 Nov 2014 17:53:21 -0500 Subject: [PATCH 513/543] [jit] Factor out duplicate code from the castclass/unbox.any opcode implementation. --- mono/mini/method-to-ir.c | 157 ++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 94 deletions(-) diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 19c7eec8d0d..9a78a549a31 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -134,6 +134,9 @@ int mono_op_to_op_imm_noemul (int opcode); MONO_API MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args); +static int inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp, + guchar *ip, guint real_offset, gboolean inline_always, MonoBasicBlock **out_cbb); + /* helper methods signatures */ static MonoMethodSignature *helper_sig_class_init_trampoline; static MonoMethodSignature *helper_sig_domain_get; @@ -4129,12 +4132,46 @@ emit_castclass_with_cache_nonshared (MonoCompile *cfg, MonoInst *obj, MonoClass * Returns NULL and set the cfg exception on error. */ static MonoInst* -handle_castclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context_used) +handle_castclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src, guint8 *ip, MonoBasicBlock **out_bb, int *inline_costs) { MonoBasicBlock *is_null_bb; int obj_reg = src->dreg; int vtable_reg = alloc_preg (cfg); - MonoInst *klass_inst = NULL; + int context_used; + MonoInst *klass_inst = NULL, *res; + MonoBasicBlock *bblock; + + *out_bb = cfg->cbb; + + context_used = mini_class_check_context_used (cfg, klass); + + if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { + res = emit_castclass_with_cache_nonshared (cfg, src, klass, &bblock); + (*inline_costs) += 2; + *out_bb = cfg->cbb; + return res; + } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) { + MonoMethod *mono_castclass; + MonoInst *iargs [1]; + int costs; + + mono_castclass = mono_marshal_get_castclass (klass); + iargs [0] = src; + + save_cast_details (cfg, klass, src->dreg, TRUE, &bblock); + costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), + iargs, ip, cfg->real_offset, TRUE, &bblock); + reset_cast_details (cfg); + CHECK_CFG_EXCEPTION; + g_assert (costs > 0); + + cfg->real_offset += 5; + + (*inline_costs) += costs; + + *out_bb = cfg->cbb; + return src; + } if (context_used) { MonoInst *args [3]; @@ -4199,7 +4236,12 @@ handle_castclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context reset_cast_details (cfg); + *out_bb = cfg->cbb; + return src; + +exception_exit: + return NULL; } /* @@ -9832,42 +9874,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (sp [0]->type != STACK_OBJ) UNVERIFIED; - context_used = mini_class_check_context_used (cfg, klass); - - if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { - *sp = emit_castclass_with_cache_nonshared (cfg, sp [0], klass, &bblock); - sp ++; - ip += 5; - inline_costs += 2; - } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) { - MonoMethod *mono_castclass; - MonoInst *iargs [1]; - int costs; - - mono_castclass = mono_marshal_get_castclass (klass); - iargs [0] = sp [0]; - - save_cast_details (cfg, klass, sp [0]->dreg, TRUE, &bblock); - costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), - iargs, ip, cfg->real_offset, TRUE, &bblock); - reset_cast_details (cfg); - CHECK_CFG_EXCEPTION; - g_assert (costs > 0); - - ip += 5; - cfg->real_offset += 5; - - *sp++ = iargs [0]; + ins = handle_castclass (cfg, klass, *sp, ip, &bblock, &inline_costs); + CHECK_CFG_EXCEPTION; - inline_costs += costs; - } - else { - ins = handle_castclass (cfg, klass, *sp, context_used); - CHECK_CFG_EXCEPTION; - bblock = cfg->cbb; - *sp ++ = ins; - ip += 5; - } + *sp ++ = ins; + ip += 5; break; case CEE_ISINST: { CHECK_STACK (1); @@ -9930,6 +9941,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b break; } case CEE_UNBOX_ANY: { + MonoInst *res, *addr; + CHECK_STACK (1); --sp; CHECK_OPSIZE (5); @@ -9942,67 +9955,23 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b context_used = mini_class_check_context_used (cfg, klass); if (mini_is_gsharedvt_klass (cfg, klass)) { - *sp = handle_unbox_gsharedvt (cfg, klass, *sp, &bblock); - sp ++; - - ip += 5; + res = handle_unbox_gsharedvt (cfg, klass, *sp, &bblock); + inline_costs += 2; + } else if (generic_class_is_reference_type (cfg, klass)) { + res = handle_castclass (cfg, klass, *sp, ip, &bblock, &inline_costs); + CHECK_CFG_EXCEPTION; + } else if (mono_class_is_nullable (klass)) { + res = handle_unbox_nullable (cfg, *sp, klass, context_used); + } else { + addr = handle_unbox (cfg, klass, sp, context_used); + /* LDOBJ */ + EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0); + res = ins; inline_costs += 2; - break; - } - - if (generic_class_is_reference_type (cfg, klass)) { - /* CASTCLASS FIXME kill this huge slice of duplicated code*/ - if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) { - *sp = emit_castclass_with_cache_nonshared (cfg, sp [0], klass, &bblock); - sp ++; - ip += 5; - inline_costs += 2; - } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) { - MonoMethod *mono_castclass; - MonoInst *iargs [1]; - int costs; - - mono_castclass = mono_marshal_get_castclass (klass); - iargs [0] = sp [0]; - - costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), - iargs, ip, cfg->real_offset, TRUE, &bblock); - CHECK_CFG_EXCEPTION; - g_assert (costs > 0); - - ip += 5; - cfg->real_offset += 5; - - *sp++ = iargs [0]; - inline_costs += costs; - } else { - ins = handle_castclass (cfg, klass, *sp, context_used); - CHECK_CFG_EXCEPTION; - bblock = cfg->cbb; - *sp ++ = ins; - ip += 5; - } - break; - } - - if (mono_class_is_nullable (klass)) { - ins = handle_unbox_nullable (cfg, *sp, klass, context_used); - *sp++= ins; - ip += 5; - break; } - /* UNBOX */ - ins = handle_unbox (cfg, klass, sp, context_used); - *sp = ins; - + *sp ++ = res; ip += 5; - - /* LDOBJ */ - EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, sp [0]->dreg, 0); - *sp++ = ins; - - inline_costs += 2; break; } case CEE_BOX: { From b160f1e3b7b62f374c7b07dcfe3a877790384d41 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Thu, 30 Oct 2014 15:04:48 -0700 Subject: [PATCH 514/543] [sgen] Use hash based on current address for finalization hashes. Extend functionality of SgenPointerQueue. The purpose of this commit is to avoid dependency between GC code and the obtaining of the hash from the object's synchronisation field, which might require additional processing. --- mono/metadata/sgen-fin-weak-hash.c | 41 ++++++++++++++++++++++++++---- mono/metadata/sgen-gc.h | 1 + mono/metadata/sgen-internal.c | 1 + mono/metadata/sgen-pinning.c | 1 + mono/metadata/sgen-pointer-queue.c | 34 +++++++++++++++++++++++-- mono/metadata/sgen-pointer-queue.h | 7 +++++ 6 files changed, 78 insertions(+), 7 deletions(-) diff --git a/mono/metadata/sgen-fin-weak-hash.c b/mono/metadata/sgen-fin-weak-hash.c index 3793c9435be..99639432683 100644 --- a/mono/metadata/sgen-fin-weak-hash.c +++ b/mono/metadata/sgen-fin-weak-hash.c @@ -30,6 +30,7 @@ #include "metadata/sgen-gc.h" #include "metadata/sgen-gray.h" #include "metadata/sgen-protocol.h" +#include "metadata/sgen-pointer-queue.h" #include "utils/dtrace.h" #include "utils/mono-counters.h" @@ -73,7 +74,7 @@ tagged_object_apply (void *object, int tag_bits) static int tagged_object_hash (MonoObject *o) { - return mono_object_hash (tagged_object_get_object (o)); + return mono_aligned_addr_hash (tagged_object_get_object (o)); } static gboolean @@ -116,6 +117,9 @@ sgen_collect_bridge_objects (int generation, ScanCopyContext ctx) MonoObject *object; gpointer dummy; char *copy; + SgenPointerQueue moved_fin_objects; + + sgen_pointer_queue_init (&moved_fin_objects, INTERNAL_MEM_TEMPORARY); if (no_finalize) return; @@ -154,12 +158,24 @@ sgen_collect_bridge_objects (int generation, ScanCopyContext ctx) SGEN_LOG (5, "Promoting finalization of object %p (%s) (was at %p) to major table", copy, sgen_safe_name (copy), object); continue; - } else { + } else if (copy != (char*)object) { /* update pointer */ + SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE); + + /* register for reinsertion */ + sgen_pointer_queue_add (&moved_fin_objects, tagged_object_apply (copy, tag)); + SGEN_LOG (5, "Updating object for finalization: %p (%s) (was at %p)", copy, sgen_safe_name (copy), object); - SGEN_HASH_TABLE_FOREACH_SET_KEY (tagged_object_apply (copy, tag)); + + continue; } } SGEN_HASH_TABLE_FOREACH_END; + + while (!sgen_pointer_queue_is_empty (&moved_fin_objects)) { + sgen_hash_table_replace (hash_table, sgen_pointer_queue_pop (&moved_fin_objects), NULL, NULL); + } + + sgen_pointer_queue_free (&moved_fin_objects); } @@ -172,6 +188,9 @@ sgen_finalize_in_range (int generation, ScanCopyContext ctx) SgenHashTable *hash_table = get_finalize_entry_hash_table (generation); MonoObject *object; gpointer dummy; + SgenPointerQueue moved_fin_objects; + + sgen_pointer_queue_init (&moved_fin_objects, INTERNAL_MEM_TEMPORARY); if (no_finalize) return; @@ -201,14 +220,26 @@ sgen_finalize_in_range (int generation, ScanCopyContext ctx) SGEN_LOG (5, "Promoting finalization of object %p (%s) (was at %p) to major table", copy, sgen_safe_name (copy), object); continue; - } else { + } else if (copy != object) { /* update pointer */ + SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE); + + /* register for reinsertion */ + sgen_pointer_queue_add (&moved_fin_objects, tagged_object_apply (copy, tag)); + SGEN_LOG (5, "Updating object for finalization: %p (%s) (was at %p)", copy, sgen_safe_name (copy), object); - SGEN_HASH_TABLE_FOREACH_SET_KEY (tagged_object_apply (copy, tag)); + + continue; } } } } SGEN_HASH_TABLE_FOREACH_END; + + while (!sgen_pointer_queue_is_empty (&moved_fin_objects)) { + sgen_hash_table_replace (hash_table, sgen_pointer_queue_pop (&moved_fin_objects), NULL, NULL); + } + + sgen_pointer_queue_free (&moved_fin_objects); } /* LOCKING: requires that the GC lock is held */ diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 0fa76130411..041d4faa87d 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -437,6 +437,7 @@ enum { INTERNAL_MEM_TOGGLEREF_DATA, INTERNAL_MEM_CARDTABLE_MOD_UNION, INTERNAL_MEM_BINARY_PROTOCOL, + INTERNAL_MEM_TEMPORARY, INTERNAL_MEM_MAX }; diff --git a/mono/metadata/sgen-internal.c b/mono/metadata/sgen-internal.c index 333f8c3ee41..f5b8995355f 100644 --- a/mono/metadata/sgen-internal.c +++ b/mono/metadata/sgen-internal.c @@ -150,6 +150,7 @@ description_for_type (int type) case INTERNAL_MEM_TOGGLEREF_DATA: return "toggleref-data"; case INTERNAL_MEM_CARDTABLE_MOD_UNION: return "cardtable-mod-union"; case INTERNAL_MEM_BINARY_PROTOCOL: return "binary-protocol"; + case INTERNAL_MEM_TEMPORARY: return "temporary"; default: g_assert_not_reached (); } diff --git a/mono/metadata/sgen-pinning.c b/mono/metadata/sgen-pinning.c index c895d7471ea..9c8c819a097 100644 --- a/mono/metadata/sgen-pinning.c +++ b/mono/metadata/sgen-pinning.c @@ -37,6 +37,7 @@ void sgen_init_pinning (void) { memset (pin_hash_filter, 0, sizeof (pin_hash_filter)); + pin_queue.mem_type = INTERNAL_MEM_PIN_QUEUE; } void diff --git a/mono/metadata/sgen-pointer-queue.c b/mono/metadata/sgen-pointer-queue.c index 3c1d8fb6c61..7ace7dfa4b6 100644 --- a/mono/metadata/sgen-pointer-queue.c +++ b/mono/metadata/sgen-pointer-queue.c @@ -28,13 +28,23 @@ sgen_pointer_queue_clear (SgenPointerQueue *queue) queue->next_slot = 0; } +void +sgen_pointer_queue_init (SgenPointerQueue *queue, int mem_type) +{ + queue->next_slot = 0; + queue->size = 0; + queue->data = NULL; + queue->mem_type = mem_type; +} + static void realloc_queue (SgenPointerQueue *queue) { size_t new_size = queue->size ? queue->size + queue->size/2 : 1024; - void **new_data = sgen_alloc_internal_dynamic (sizeof (void*) * new_size, INTERNAL_MEM_PIN_QUEUE, TRUE); + void **new_data = sgen_alloc_internal_dynamic (sizeof (void*) * new_size, queue->mem_type, TRUE); + memcpy (new_data, queue->data, sizeof (void*) * queue->next_slot); - sgen_free_internal_dynamic (queue->data, sizeof (void*) * queue->size, INTERNAL_MEM_PIN_QUEUE); + sgen_free_internal_dynamic (queue->data, sizeof (void*) * queue->size, queue->mem_type); queue->data = new_data; queue->size = new_size; SGEN_LOG (4, "Reallocated pointer queue to size: %lu", new_size); @@ -49,6 +59,14 @@ sgen_pointer_queue_add (SgenPointerQueue *queue, void *ptr) queue->data [queue->next_slot++] = ptr; } +void* +sgen_pointer_queue_pop (SgenPointerQueue *queue) +{ + g_assert (queue->next_slot); + + return queue->data [--queue->next_slot]; +} + size_t sgen_pointer_queue_search (SgenPointerQueue *queue, void *addr) { @@ -120,4 +138,16 @@ sgen_pointer_queue_find (SgenPointerQueue *queue, void *ptr) return (size_t)-1; } +gboolean +sgen_pointer_queue_is_empty (SgenPointerQueue *queue) +{ + return !queue->next_slot; +} + +void +sgen_pointer_queue_free (SgenPointerQueue *queue) +{ + sgen_free_internal_dynamic (queue->data, sizeof (void*) * queue->size, queue->mem_type); +} + #endif diff --git a/mono/metadata/sgen-pointer-queue.h b/mono/metadata/sgen-pointer-queue.h index d972f3cc92e..0bbeedfdd67 100644 --- a/mono/metadata/sgen-pointer-queue.h +++ b/mono/metadata/sgen-pointer-queue.h @@ -20,10 +20,13 @@ #ifndef __MONO_SGEN_POINTER_QUEUE_H__ #define __MONO_SGEN_POINTER_QUEUE_H__ +#include + typedef struct { void **data; size_t size; size_t next_slot; + int mem_type; } SgenPointerQueue; void sgen_pointer_queue_add (SgenPointerQueue *queue, void *ptr) MONO_INTERNAL; @@ -32,5 +35,9 @@ void sgen_pointer_queue_remove_nulls (SgenPointerQueue *queue) MONO_INTERNAL; void sgen_pointer_queue_sort_uniq (SgenPointerQueue *queue) MONO_INTERNAL; size_t sgen_pointer_queue_search (SgenPointerQueue *queue, void *addr) MONO_INTERNAL; size_t sgen_pointer_queue_find (SgenPointerQueue *queue, void *ptr) MONO_INTERNAL; +void sgen_pointer_queue_init (SgenPointerQueue *queue, int mem_type) MONO_INTERNAL; +void* sgen_pointer_queue_pop (SgenPointerQueue *queue) MONO_INTERNAL; +gboolean sgen_pointer_queue_is_empty (SgenPointerQueue *queue) MONO_INTERNAL; +void sgen_pointer_queue_free (SgenPointerQueue *queue) MONO_INTERNAL; #endif From fc02486d6a8b6c29b177031b69ddddc43bccb91e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Tue, 4 Nov 2014 10:49:57 +0100 Subject: [PATCH 515/543] Fix NET_2_0 build --- .../System.Web.Security/MembershipPasswordAttributeTest.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs b/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs index 2559089b92b..4ace2ca1b37 100644 --- a/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs +++ b/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs @@ -1,4 +1,6 @@ -using System.ComponentModel.DataAnnotations; +#if NET_4_5 + +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web.Security; using NUnit.Framework; @@ -135,3 +137,4 @@ public ValidationResult TestValidation (object val, ValidationContext context) } } } +#endif From c84d28ca735a4f98cf92e4f589f58e9d66556d28 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 4 Nov 2014 14:26:32 -0500 Subject: [PATCH 516/543] [mscorlib] Marshal.GetExceptionForHR() takes an `errorInfo` parameter. Parameter names are part of the ABI because of C#4 named parameter. Consequently, they *must* be consistent with .NET, and .NET a parameter name of "errorInfo", *not* "errorInfoPtr" [0]: public static Exception GetExceptionForHR( int errorCode, IntPtr errorInfo ) Change the parameter name from `errorCodeInfo` to `errorCode` so that the parameter name is consistent with .NET. [0]: http://msdn.microsoft.com/en-us/library/3xade62s(v=vs.100).aspx --- .../System.Runtime.InteropServices/Marshal.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs index 243984706ce..48c5db2ea62 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs @@ -1583,33 +1583,33 @@ public static Exception GetExceptionForHR (int errorCode) return GetExceptionForHR (errorCode, IntPtr.Zero); } - public static Exception GetExceptionForHR (int errorCode, IntPtr errorInfoPtr) + public static Exception GetExceptionForHR (int errorCode, IntPtr errorInfo) { - IErrorInfo errorInfo = null; - if (errorInfoPtr != (IntPtr)(-1)) { - if (errorInfoPtr == IntPtr.Zero) { - if (GetErrorInfo (0, out errorInfo) != 0) { - errorInfo = null; + IErrorInfo info = null; + if (errorInfo != (IntPtr)(-1)) { + if (errorInfo == IntPtr.Zero) { + if (GetErrorInfo (0, out info) != 0) { + info = null; } } else { - errorInfo = Marshal.GetObjectForIUnknown (errorInfoPtr) as IErrorInfo; + info = Marshal.GetObjectForIUnknown (errorInfo) as IErrorInfo; } } - if (errorInfo is ManagedErrorInfo && ((ManagedErrorInfo)errorInfo).Exception.hresult == errorCode) { - return ((ManagedErrorInfo)errorInfo).Exception; + if (info is ManagedErrorInfo && ((ManagedErrorInfo) info).Exception.hresult == errorCode) { + return ((ManagedErrorInfo) info).Exception; } Exception e = ConvertHrToException (errorCode); - if (errorInfo != null && e != null) { + if (info != null && e != null) { uint helpContext; - errorInfo.GetHelpContext (out helpContext); + info.GetHelpContext (out helpContext); string str; - errorInfo.GetSource (out str); + info.GetSource (out str); e.Source = str; - errorInfo.GetDescription (out str); + info.GetDescription (out str); e.SetMessage (str); - errorInfo.GetHelpFile (out str); + info.GetHelpFile (out str); if (helpContext == 0) { e.HelpLink = str; From d3ee9252dadaf1024fd3e9847a5c91c37224d703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Tue, 4 Nov 2014 11:38:01 +0100 Subject: [PATCH 517/543] [System.ServiceModel] Fixed Bug652331_2 test that failed on Jenkins by increasing timeout Looks like the test takes quite a while so 10 seconds was just too short. Increasing the timeout to 20s seems to fix it. --- .../Test/System.ServiceModel.Dispatcher/Bug652331Test.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/class/System.ServiceModel/Test/System.ServiceModel.Dispatcher/Bug652331Test.cs b/mcs/class/System.ServiceModel/Test/System.ServiceModel.Dispatcher/Bug652331Test.cs index d0e0ea09ba0..ed5fb8b65c9 100644 --- a/mcs/class/System.ServiceModel/Test/System.ServiceModel.Dispatcher/Bug652331Test.cs +++ b/mcs/class/System.ServiceModel/Test/System.ServiceModel.Dispatcher/Bug652331Test.cs @@ -70,7 +70,7 @@ public void Bug652331_2 () // test in one of the comment }; client.GetDataAsync (); - if (!wait.WaitOne (TimeSpan.FromSeconds (10))) + if (!wait.WaitOne (TimeSpan.FromSeconds (20))) Assert.Fail ("timeout"); } finally { serviceHost.Close (); From f812f43d2e8c17331d0d7365b2f613515b0285ce Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 4 Nov 2014 16:19:57 -0500 Subject: [PATCH 518/543] [llvm] Add beginnings of support for emitting dwarf debug info for LLVM code. Not enabled yet, since it would clash with the dwarf info emitted by the AOT compiler for JITted code. --- mono/mini/aot-compiler.c | 7 +- mono/mini/mini-llvm.c | 240 ++++++++++++++++++++++++++++++++++++++- mono/mini/mini.h | 2 +- 3 files changed, 242 insertions(+), 7 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index d5bb922e142..44812084153 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -4872,13 +4872,14 @@ get_debug_sym (MonoMethod *method, const char *prefix, GHashTable *cache) char *name1, *name2, *cached; int i, j, len, count; + name1 = mono_method_full_name (method, TRUE); + #ifdef TARGET_MACH // This is so that we don't accidentally create a local symbol (which starts with 'L') - if (!prefix || !*prefix) + if ((!prefix || !*prefix) && name1 [0] == 'L') prefix = "_"; #endif - name1 = mono_method_full_name (method, TRUE); len = strlen (name1); name2 = malloc (strlen (prefix) + len + 16); memcpy (name2, prefix, strlen (prefix)); @@ -7102,7 +7103,7 @@ emit_llvm_file (MonoAotCompile *acfg) tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename); - mono_llvm_emit_aot_module (tempbc, acfg->final_got_size); + mono_llvm_emit_aot_module (tempbc, g_path_get_basename (acfg->image->name), acfg->final_got_size); g_free (tempbc); /* diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index 28e76665e16..a28570344ef 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -7,10 +7,12 @@ #include "mini.h" #include +#include #include #include #include #include +#include #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS @@ -42,6 +44,7 @@ typedef struct { int bb_names_len; GPtrArray *used; LLVMTypeRef ptr_type; + GPtrArray *subprogram_mds; MonoEERef *mono_ee; LLVMExecutionEngineRef ee; } MonoLLVMModule; @@ -99,7 +102,8 @@ typedef struct { int *pindexes; LLVMValueRef imt_rgctx_loc; GHashTable *llvm_types; - + LLVMValueRef dbg_md; + MonoDebugMethodInfo *minfo; char temp_name [32]; } EmitContext; @@ -209,6 +213,10 @@ static const char *memcpy_func_name; static void init_jit_module (MonoDomain *domain); +static void emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code); +static LLVMValueRef emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name); +static void emit_dbg_info (MonoLLVMModule *lmodule, const char *filename, const char *cu_name); + /* * IntPtrType: * @@ -2346,6 +2354,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) char *dname = NULL; char dname_buf [128]; + emit_dbg_loc (ctx, builder, ins->cil_code); + nins ++; if (nins > 5000 && builder == starting_builder) { /* some steps in llc are non-linear in the size of basic blocks, see #5714 */ @@ -4245,8 +4255,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) if (!has_terminator && bb->next_bb && (bb == cfg->bb_entry || bb->in_count > 0)) LLVMBuildBr (builder, get_bb (ctx, bb->next_bb)); - if (bb == cfg->bb_exit && sig->ret->type == MONO_TYPE_VOID) + if (bb == cfg->bb_exit && sig->ret->type == MONO_TYPE_VOID) { + emit_dbg_loc (ctx, builder, cfg->header->code + cfg->header->code_size - 1); LLVMBuildRetVoid (builder); + } if (bb == cfg->bb_entry) ctx->last_alloca = LLVMGetLastInstruction (get_bb (ctx, cfg->bb_entry)); @@ -4484,6 +4496,12 @@ mono_llvm_emit_method (MonoCompile *cfg) } g_free (names); + // See emit_dbg_info () + if (FALSE && cfg->compile_aot && mono_debug_enabled ()) { + ctx->minfo = mono_debug_lookup_method (cfg->method); + ctx->dbg_md = emit_dbg_subprogram (ctx, cfg, method, method_name); + } + max_block_num = 0; for (bb = cfg->bb_entry; bb; bb = bb->next_bb) max_block_num = MAX (max_block_num, bb->block_num); @@ -5361,7 +5379,7 @@ mono_llvm_create_aot_module (const char *got_symbol) * Emit the aot module into the LLVM bitcode file FILENAME. */ void -mono_llvm_emit_aot_module (const char *filename, int got_size) +mono_llvm_emit_aot_module (const char *filename, const char *cu_name, int got_size) { LLVMTypeRef got_type; LLVMValueRef real_got; @@ -5384,6 +5402,7 @@ mono_llvm_emit_aot_module (const char *filename, int got_size) LLVMDeleteGlobal (aot_module.got_var); emit_llvm_used (&aot_module); + emit_dbg_info (&aot_module, filename, cu_name); /* Replace PLT entries for directly callable methods with the methods themselves */ { @@ -5419,6 +5438,221 @@ mono_llvm_emit_aot_module (const char *filename, int got_size) LLVMWriteBitcodeToFile (aot_module.module, filename); } + +static LLVMValueRef +md_string (const char *s) +{ + return LLVMMDString (s, strlen (s)); +} + +/* Debugging support */ + +static void +emit_dbg_info (MonoLLVMModule *lmodule, const char *filename, const char *cu_name) +{ + LLVMModuleRef module = lmodule->module; + LLVMValueRef args [16], cu_args [16], cu, ver; + int n_cuargs; + char *build_info, *s, *dir; + + // + // FIXME: This cannot be enabled, since the AOT compiler also emits dwarf info, + // and the abbrev indexes will not be correct since llvm has added its own + // abbrevs. + // + return; + + /* + * Emit dwarf info in the form of LLVM metadata. There is some + * out-of-date documentation at: + * http://llvm.org/docs/SourceLevelDebugging.html + * but most of this was gathered from the llvm and + * clang sources. + */ + + n_cuargs = 0; + cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), DW_TAG_compile_unit, FALSE); + /* CU name/compilation dir */ + dir = g_path_get_dirname (filename); + args [0] = LLVMMDString (cu_name, strlen (cu_name)); + args [1] = LLVMMDString (dir, strlen (dir)); + cu_args [n_cuargs ++] = LLVMMDNode (args, 2); + g_free (dir); + /* Language */ + cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), DW_LANG_C99, FALSE); + /* Producer */ + build_info = mono_get_runtime_build_info (); + s = g_strdup_printf ("Mono AOT Compiler %s (LLVM)", build_info); + cu_args [n_cuargs ++] = LLVMMDString (s, strlen (s)); + g_free (build_info); + /* Optimized */ + cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE); + /* Flags */ + cu_args [n_cuargs ++] = LLVMMDString ("", strlen ("")); + /* Runtime version */ + cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 0, FALSE); + /* Enums */ + cu_args [n_cuargs ++] = LLVMMDNode (args, 0); + cu_args [n_cuargs ++] = LLVMMDNode (args, 0); + /* Subprograms */ + if (lmodule->subprogram_mds) { + LLVMValueRef *mds; + int i; + + mds = g_new0 (LLVMValueRef, lmodule->subprogram_mds->len); + for (i = 0; i < lmodule->subprogram_mds->len; ++i) + mds [i] = g_ptr_array_index (lmodule->subprogram_mds, i); + cu_args [n_cuargs ++] = LLVMMDNode (mds, lmodule->subprogram_mds->len); + } else { + cu_args [n_cuargs ++] = LLVMMDNode (args, 0); + } + /* GVs */ + cu_args [n_cuargs ++] = LLVMMDNode (args, 0); + /* Imported modules */ + cu_args [n_cuargs ++] = LLVMMDNode (args, 0); + /* SplitName */ + cu_args [n_cuargs ++] = LLVMMDString ("", strlen ("")); + /* DebugEmissionKind = FullDebug */ + cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE); + cu = LLVMMDNode (cu_args, n_cuargs); + LLVMAddNamedMetadataOperand (module, "llvm.dbg.cu", cu); + + args [0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE); + args [1] = LLVMMDString ("Dwarf Version", strlen ("Dwarf Version")); + args [2] = LLVMConstInt (LLVMInt32Type (), 2, FALSE); + ver = LLVMMDNode (args, 3); + LLVMAddNamedMetadataOperand (module, "llvm.module.flags", ver); + + args [0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE); + args [1] = LLVMMDString ("Debug Info Version", strlen ("Debug Info Version")); + args [2] = LLVMConstInt (LLVMInt32Type (), 1, FALSE); + ver = LLVMMDNode (args, 3); + LLVMAddNamedMetadataOperand (module, "llvm.module.flags", ver); +} + +static LLVMValueRef +emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name) +{ + MonoLLVMModule *module = ctx->lmodule; + MonoDebugMethodInfo *minfo = ctx->minfo; + char *source_file, *dir, *filename; + LLVMValueRef md, args [16], ctx_args [16], md_args [64], type_args [16], ctx_md, type_md; + int n_il_offsets; + int *il_offsets; + int *line_numbers; + + if (!minfo) + return NULL; + + mono_debug_symfile_get_line_numbers_full (minfo, &source_file, NULL, &n_il_offsets, &il_offsets, &line_numbers, NULL, NULL, NULL, NULL); + if (!source_file) + source_file = g_strdup (""); + dir = g_path_get_dirname (source_file); + filename = g_path_get_basename (source_file); + + ctx_args [0] = LLVMConstInt (LLVMInt32Type (), 0x29, FALSE); + args [0] = md_string (filename); + args [1] = md_string (dir); + ctx_args [1] = LLVMMDNode (args, 2); + ctx_md = LLVMMDNode (ctx_args, 2); + + type_args [0] = LLVMConstInt (LLVMInt32Type (), DW_TAG_subroutine_type, FALSE); + type_args [1] = NULL; + type_args [2] = NULL; + type_args [3] = LLVMMDString ("", 0); + type_args [4] = LLVMConstInt (LLVMInt32Type (), 0, FALSE); + type_args [5] = LLVMConstInt (LLVMInt64Type (), 0, FALSE); + type_args [6] = LLVMConstInt (LLVMInt64Type (), 0, FALSE); + type_args [7] = LLVMConstInt (LLVMInt64Type (), 0, FALSE); + type_args [8] = LLVMConstInt (LLVMInt32Type (), 0, FALSE); + type_args [9] = NULL; + type_args [10] = NULL; + type_args [11] = LLVMConstInt (LLVMInt32Type (), 0, FALSE); + type_args [12] = NULL; + type_args [13] = NULL; + type_args [14] = NULL; + type_md = LLVMMDNode (type_args, 14); + + /* http://llvm.org/docs/SourceLevelDebugging.html#subprogram-descriptors */ + md_args [0] = LLVMConstInt (LLVMInt32Type (), DW_TAG_subprogram, FALSE); + /* Source directory + file pair */ + args [0] = md_string (filename); + args [1] = md_string (dir); + md_args [1] = LLVMMDNode (args ,2); + md_args [2] = ctx_md; + md_args [3] = md_string (cfg->method->name); + md_args [4] = md_string (name); + md_args [5] = md_string (name); + /* Line number */ + if (n_il_offsets) + md_args [6] = LLVMConstInt (LLVMInt32Type (), line_numbers [0], FALSE); + else + md_args [6] = LLVMConstInt (LLVMInt32Type (), 1, FALSE); + /* Type */ + md_args [7] = type_md; + /* static */ + md_args [8] = LLVMConstInt (LLVMInt1Type (), 0, FALSE); + /* not extern */ + md_args [9] = LLVMConstInt (LLVMInt1Type (), 1, FALSE); + /* Virtuality */ + md_args [10] = LLVMConstInt (LLVMInt32Type (), 0, FALSE); + /* Index into a virtual function */ + md_args [11] = NULL; + md_args [12] = NULL; + /* Flags */ + md_args [13] = LLVMConstInt (LLVMInt1Type (), 0, FALSE); + /* isOptimized */ + md_args [14] = LLVMConstInt (LLVMInt1Type (), 1, FALSE); + /* Pointer to LLVM function */ + md_args [15] = method; + /* Function template parameter */ + md_args [16] = NULL; + /* Function declaration descriptor */ + md_args [17] = NULL; + /* List of function variables */ + md_args [18] = LLVMMDNode (args, 0); + /* Line number */ + md_args [19] = LLVMConstInt (LLVMInt32Type (), 1, FALSE); + md = LLVMMDNode (md_args, 20); + + if (!module->subprogram_mds) + module->subprogram_mds = g_ptr_array_new (); + g_ptr_array_add (module->subprogram_mds, md); + + g_free (dir); + g_free (filename); + g_free (source_file); + g_free (il_offsets); + g_free (line_numbers); + + return md; +} + +static void +emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code) +{ + MonoCompile *cfg = ctx->cfg; + + if (ctx->minfo && cil_code && cil_code >= cfg->header->code && cil_code < cfg->header->code + cfg->header->code_size) { + MonoDebugSourceLocation *loc; + LLVMValueRef loc_md, md_args [16]; + int nmd_args; + + loc = mono_debug_symfile_lookup_location (ctx->minfo, cil_code - cfg->header->code); + + if (loc) { + nmd_args = 0; + md_args [nmd_args ++] = LLVMConstInt (LLVMInt32Type (), loc->row, FALSE); + md_args [nmd_args ++] = LLVMConstInt (LLVMInt32Type (), loc->column, FALSE); + md_args [nmd_args ++] = ctx->dbg_md; + md_args [nmd_args ++] = NULL; + loc_md = LLVMMDNode (md_args, nmd_args); + LLVMSetCurrentDebugLocation (builder, loc_md); + mono_debug_symfile_free_location (loc); + } + } +} + /* DESIGN: - Emit LLVM IR from the mono IR using the LLVM C API. diff --git a/mono/mini/mini.h b/mono/mini/mini.h index e345cadc55b..658f2701c60 100755 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2194,7 +2194,7 @@ void mono_llvm_cleanup (void) MONO_LLVM_INTERNAL; void mono_llvm_emit_method (MonoCompile *cfg) MONO_LLVM_INTERNAL; void mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call) MONO_LLVM_INTERNAL; void mono_llvm_create_aot_module (const char *got_symbol) MONO_LLVM_INTERNAL; -void mono_llvm_emit_aot_module (const char *filename, int got_size) MONO_LLVM_INTERNAL; +void mono_llvm_emit_aot_module (const char *filename, const char *cu_name, int got_size) MONO_LLVM_INTERNAL; void mono_llvm_check_method_supported (MonoCompile *cfg) MONO_LLVM_INTERNAL; void mono_llvm_free_domain_info (MonoDomain *domain) MONO_LLVM_INTERNAL; From f6da6fa9eadbf5e4865004e8a6b2f8e95ad9c3fd Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 4 Nov 2014 16:44:39 -0500 Subject: [PATCH 519/543] Fix the loadable llvm build. --- mono/mini/mini-llvm.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mono/mini/mini-llvm.h b/mono/mini/mini-llvm.h index 541ae3dd390..644b9b392dc 100644 --- a/mono/mini/mini-llvm.h +++ b/mono/mini/mini-llvm.h @@ -16,7 +16,7 @@ typedef void (*MonoLLVMVoidFunc)(void); typedef void (*MonoLLVMCFGFunc)(MonoCompile *cfg); typedef void (*MonoLLVMEmitCallFunc)(MonoCompile *cfg, MonoCallInst *call); typedef void (*MonoLLVMCreateAotFunc)(const char *got_symbol); -typedef void (*MonoLLVMEmitAotFunc)(const char *filename, int got_size); +typedef void (*MonoLLVMEmitAotFunc)(const char *filename, const char *cu_name, int got_size); typedef void (*MonoLLVMFreeDomainFunc)(MonoDomain *domain); static MonoLLVMVoidFunc mono_llvm_init_fptr; @@ -60,10 +60,10 @@ mono_llvm_create_aot_module (const char *got_symbol) } void -mono_llvm_emit_aot_module (const char *filename, int got_size) +mono_llvm_emit_aot_module (const char *filename, const char *cu_name, int got_size) { g_assert (mono_llvm_emit_aot_module_fptr); - mono_llvm_emit_aot_module_fptr (filename, got_size); + mono_llvm_emit_aot_module_fptr (filename, cu_name, got_size); } void From fe265502cc517e8374ce2988f31e88d4f3554d8a Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 4 Nov 2014 17:49:18 -0500 Subject: [PATCH 520/543] Disable building the NET 2.0 profile by default. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2bc3c0d08f5..671b3a23d66 100644 --- a/configure.ac +++ b/configure.ac @@ -3199,7 +3199,7 @@ case "x$libgc" in ;; esac -AC_ARG_WITH(profile2, [ --with-profile2=yes,no If you want to install the 2.0/3.5 FX (defaults to yes)], [], [with_profile2=yes]) +AC_ARG_WITH(profile2, [ --with-profile2=yes,no If you want to install the 2.0/3.5 FX (defaults to no)], [], [with_profile2=no]) AC_ARG_WITH(profile4, [ --with-profile4=yes,no If you want to install the 4.0 FX (defaults to yes)], [], [with_profile4=yes]) AC_ARG_WITH(profile4_5,[ --with-profile4_5=yes,no If you want to install the 4.5 FX (defaults to yes)], [], [with_profile4_5=yes]) AC_ARG_WITH(monodroid, [ --with-monodroid=yes,no If you want to build the MonoDroid assemblies (defaults to no)], [], [with_monodroid=no]) From 82cfc3ea311af14333415b78f8d58605477a5791 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 4 Nov 2014 18:24:27 -0500 Subject: [PATCH 521/543] Make the build in docs/ uses the net 4.5 profile. --- docs/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 39527b5f8eb..811955257bb 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -99,14 +99,14 @@ mono-file-formats.tree: $(srcdir)/docs.make $(srcdir)/Makefile.am $(srcdir)/depl deploy/.stamp: convert.exe Makefile.am $(mkdir_p) html runtimedir=`cd ../runtime && pwd`; export runtimedir; \ - MONO_PATH=../mcs/class/lib/net_2_0 perl $(srcdir)/exdoc -h $(srcdir) -t . $(srcdir)/../mono/*/*.c + MONO_PATH=../mcs/class/lib/net_4_5 perl $(srcdir)/exdoc -h $(srcdir) -t . $(srcdir)/../mono/*/*.c touch $@ extract: deploy/.stamp convert.exe: convert.cs AgilityPack.dll - $(TOOL_MAKE) PROFILE=net_2_0 convert.exe + $(TOOL_MAKE) PROFILE=net_4_5 convert.exe AgilityPack.dll: - $(TOOL_MAKE) PROFILE=net_2_0 AgilityPack.dll + $(TOOL_MAKE) PROFILE=net_4_5 AgilityPack.dll From f34e6426f9dc016bdc2acf79e3d062b80b7cf07a Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 4 Nov 2014 19:02:15 -0500 Subject: [PATCH 522/543] Make mono_threads_pthread_kill available to mach targets. --- mono/utils/mono-threads-posix.c | 40 ++++++++++++++++----------------- mono/utils/mono-threads.h | 2 -- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index 80f283f8878..51bdc8df76e 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -260,6 +260,26 @@ mono_threads_core_clear_interruption (void) wapi_clear_interruption (); } +int +mono_threads_pthread_kill (MonoThreadInfo *info, int signum) +{ +#if defined (PLATFORM_ANDROID) + int result, old_errno = errno; + result = tkill (info->native_handle, signum); + if (result < 0) { + result = errno; + errno = old_errno; + } + return result; +#elif defined(__native_client__) + /* Workaround pthread_kill abort() in NaCl glibc. */ + return 0; +#else + return pthread_kill (mono_thread_info_get_tid (info), signum); +#endif + +} + #if !defined (__MACH__) #if !defined(__native_client__) @@ -341,26 +361,6 @@ mono_threads_core_interrupt (MonoThreadInfo *info) { } -int -mono_threads_pthread_kill (MonoThreadInfo *info, int signum) -{ -#if defined (PLATFORM_ANDROID) - int result, old_errno = errno; - result = tkill (info->native_handle, signum); - if (result < 0) { - result = errno; - errno = old_errno; - } - return result; -#elif defined(__native_client__) - /* Workaround pthread_kill abort() in NaCl glibc. */ - return 0; -#else - return pthread_kill (mono_thread_info_get_tid (info), signum); -#endif - -} - void mono_threads_core_abort_syscall (MonoThreadInfo *info) { diff --git a/mono/utils/mono-threads.h b/mono/utils/mono-threads.h index 91a7df5f0fc..b26ccbec35c 100644 --- a/mono/utils/mono-threads.h +++ b/mono/utils/mono-threads.h @@ -328,11 +328,9 @@ mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) MONO_INT #if !defined(HOST_WIN32) -#if !defined(__MACH__) /*Use this instead of pthread_kill */ int mono_threads_pthread_kill (THREAD_INFO_TYPE *info, int signum) MONO_INTERNAL; -#endif #endif /* !defined(HOST_WIN32) */ From 53cd89d23a0175f83534f3a7463d24a3221a452c Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 4 Nov 2014 19:06:27 -0500 Subject: [PATCH 523/543] [profiler] Fix signal based profiling to sample all registered threads. The current signal profiling code depended on invalid linux behavior of setitimer allowing multiple threads to register for the same timer. Linux kernel 2.6.12 fixed this and only the main thread gets the signal. Always. The correct POSIX behavior happens on OSX/iOS. On Linux we could use timer_create and SIGEV_THREAD_ID but that would not work on iOS/OSX since it's specific to it. Given that little detail, I'll leave implementing it as an exercise to the reader. The solution, which aims to be as portable as possible, is to use a pair of signals and have the first one fire the second one against all other threads. We use a pair of signals since it's not well defined which thread will receive the signal so detecting this from the signal is non-trivial. --- mono/mini/mini-posix.c | 71 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index 0c2fa1dc1f0..2dedd99d84f 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -25,6 +25,8 @@ #ifdef HAVE_SYS_SYSCALL_H #include #endif +#include + #include #include @@ -55,6 +57,7 @@ #include #include #include +#include #include "mini.h" #include @@ -306,12 +309,43 @@ MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) #else -MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) +static int +get_stage2_signal_handler (void) +{ +#if defined(PLATFORM_ANDROID) + return SIGINFO; +#elif !defined (SIGRTMIN) +#ifdef SIGUSR2 + return SIGUSR2; +#else + return -1; +#endif /* SIGUSR2 */ +#else + static int prof2_signum = -1; + int i; + if (prof2_signum != -1) + return prof2_signum; + /* we try to avoid SIGRTMIN and any one that might have been set already */ + for (i = SIGRTMIN + 2; i < SIGRTMAX; ++i) { + struct sigaction sinfo; + sigaction (i, NULL, &sinfo); + if (sinfo.sa_handler == SIG_DFL && (void*)sinfo.sa_sigaction == (void*)SIG_DFL) { + prof2_signum = i; + return i; + } + } + /* fallback to the old way */ + return SIGRTMIN + 2; +#endif +} + + +static void +per_thread_profiler_hit (void *ctx) { int call_chain_depth = mono_profiler_stat_get_call_chain_depth (); MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy (); - MONO_SIG_HANDLER_GET_CONTEXT; - + if (call_chain_depth == 0) { mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx); } else { @@ -378,6 +412,34 @@ MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx); } +} + +MONO_SIG_HANDLER_FUNC (static, sigprof_stage2_signal_handler) +{ + MONO_SIG_HANDLER_GET_CONTEXT; + + per_thread_profiler_hit (ctx); + + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); +} + +MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) +{ + MonoThreadInfo *info; + int old_errno = errno; + int hp_save_index = mono_hazard_pointer_save_for_signal_handler (); + MONO_SIG_HANDLER_GET_CONTEXT; + + FOREACH_THREAD_SAFE (info) { + if (mono_thread_info_get_tid (info) == mono_native_thread_id_get ()) + continue; + mono_threads_pthread_kill (info, get_stage2_signal_handler ()); + } END_FOREACH_THREAD_SAFE; + + per_thread_profiler_hit (ctx); + + mono_hazard_pointer_restore_for_signal_handler (hp_save_index); + errno = old_errno; mono_chain_signal (MONO_SIG_HANDLER_PARAMS); } @@ -647,11 +709,12 @@ mono_runtime_setup_stat_profiler (void) itval.it_interval.tv_usec = 999; itval.it_interval.tv_sec = 0; itval.it_value = itval.it_interval; - setitimer (ITIMER_PROF, &itval, NULL); if (inited) return; inited = 1; add_signal_handler (SIGPROF, sigprof_signal_handler); + add_signal_handler (get_stage2_signal_handler (), sigprof_stage2_signal_handler); + setitimer (ITIMER_PROF, &itval, NULL); #endif } From 9522723493629b0d7230f6b3c31117b840a579b0 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 4 Nov 2014 19:27:20 -0500 Subject: [PATCH 524/543] [profiler] Add new profiler API mono_profiler_set_statistical_mode that gives control to statistical mode and sampling rate. --- mono/metadata/profiler-private.h | 3 +++ mono/metadata/profiler.c | 34 ++++++++++++++++++++++++++++++++ mono/metadata/profiler.h | 9 +++++++++ mono/mini/mini-posix.c | 30 +++++++++++++++++++++++++--- 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/mono/metadata/profiler-private.h b/mono/metadata/profiler-private.h index 18ec96b7aea..ed8a32f44fe 100644 --- a/mono/metadata/profiler-private.h +++ b/mono/metadata/profiler-private.h @@ -77,5 +77,8 @@ void mono_profiler_code_buffer_new (gpointer buffer, int size, MonoProfilerCodeB void mono_profiler_runtime_initialized (void) MONO_INTERNAL; +int64_t mono_profiler_get_sampling_rate (void) MONO_INTERNAL; +MonoProfileSamplingMode mono_profiler_get_sampling_mode (void) MONO_INTERNAL; + #endif /* __MONO_PROFILER_PRIVATE_H__ */ diff --git a/mono/metadata/profiler.c b/mono/metadata/profiler.c index 53f8ff0c907..dccf0930711 100644 --- a/mono/metadata/profiler.c +++ b/mono/metadata/profiler.c @@ -273,6 +273,28 @@ mono_profiler_install_monitor (MonoProfileMonitorFunc callback) prof_list->monitor_event_cb = callback; } +static MonoProfileSamplingMode sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS; +static int64_t sampling_frequency = 1000; //1ms + +/** + * mono_profiler_set_statistical_mode: + * @mode the sampling mode used. + * @sample_frequency_is_us the sampling frequency in microseconds. + * + * Set the sampling parameters for the profiler. Sampling mode affects the effective sampling rate as in samples/s you'll witness. + * The default sampling mode is process mode, which only reports samples when there's activity in the process. + * + * Sampling frequency should be interpreted as a suggestion that can't always be honored due to how most kernels expose alarms. + * + * Said that, when using statistical sampling, always assume variable rate sampling as all sort of external factors can interfere. + */ +void +mono_profiler_set_statistical_mode (MonoProfileSamplingMode mode, int64_t sampling_frequency_is_us) +{ + sampling_mode = mode; + sampling_frequency = sampling_frequency_is_us; +} + void mono_profiler_install_statistical (MonoProfileStatFunc callback) { @@ -281,6 +303,18 @@ mono_profiler_install_statistical (MonoProfileStatFunc callback) prof_list->statistical_cb = callback; } +int64_t +mono_profiler_get_sampling_rate (void) +{ + return sampling_frequency; +} + +MonoProfileSamplingMode +mono_profiler_get_sampling_mode (void) +{ + return sampling_mode; +} + void mono_profiler_install_statistical_call_chain (MonoProfileStatCallChainFunc callback, int call_chain_depth, MonoProfilerCallChainStrategy call_chain_strategy) { if (!prof_list) diff --git a/mono/metadata/profiler.h b/mono/metadata/profiler.h index c7b8f6d8a88..408cac8ba31 100644 --- a/mono/metadata/profiler.h +++ b/mono/metadata/profiler.h @@ -193,6 +193,15 @@ MONO_API void mono_profiler_install_iomap (MonoProfileIomapFunc callback); MONO_API void mono_profiler_load (const char *desc); +typedef enum { + /* Elapsed time is tracked by user+kernel time of the process - this is the default*/ + MONO_PROFILER_STAT_MODE_PROCESS = 0, + /* Elapsed time is tracked by wallclock time */ + MONO_PROFILER_STAT_MODE_REAL = 1, +} MonoProfileSamplingMode; + +MONO_API void mono_profiler_set_statistical_mode (MonoProfileSamplingMode mode, int64_t sampling_frequency_is_us); + MONO_END_DECLS #endif /* __MONO_PROFILER_H__ */ diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index 2dedd99d84f..5831d0976b6 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -662,6 +662,30 @@ mono_runtime_shutdown_stat_profiler (void) #endif } +#ifdef ITIMER_PROF +static int +get_itimer_mode (void) +{ + switch (mono_profiler_get_sampling_mode ()) { + case MONO_PROFILER_STAT_MODE_PROCESS: return ITIMER_PROF; + case MONO_PROFILER_STAT_MODE_REAL: return ITIMER_REAL; + } + g_assert_not_reached (); + return 0; +} + +static int +get_itimer_signal (void) +{ + switch (mono_profiler_get_sampling_mode ()) { + case MONO_PROFILER_STAT_MODE_PROCESS: return SIGPROF; + case MONO_PROFILER_STAT_MODE_REAL: return SIGALRM; + } + g_assert_not_reached (); + return 0; +} +#endif + void mono_runtime_setup_stat_profiler (void) { @@ -706,15 +730,15 @@ mono_runtime_setup_stat_profiler (void) return; #endif - itval.it_interval.tv_usec = 999; + itval.it_interval.tv_usec = (1000000 / mono_profiler_get_sampling_rate ()) - 1; itval.it_interval.tv_sec = 0; itval.it_value = itval.it_interval; if (inited) return; inited = 1; - add_signal_handler (SIGPROF, sigprof_signal_handler); + add_signal_handler (get_itimer_signal (), sigprof_signal_handler); add_signal_handler (get_stage2_signal_handler (), sigprof_stage2_signal_handler); - setitimer (ITIMER_PROF, &itval, NULL); + setitimer (get_itimer_mode (), &itval, NULL); #endif } From d51f34fd214dc9e03150d299a27f7f8db2d7f43f Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 4 Nov 2014 19:29:45 -0500 Subject: [PATCH 525/543] [profiler] Expose new profiling modes and allow sampling rate to be set when using signal-based sampling. --- mono/profiler/proflog.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mono/profiler/proflog.c b/mono/profiler/proflog.c index 520b3b228d5..edf903a7442 100644 --- a/mono/profiler/proflog.c +++ b/mono/profiler/proflog.c @@ -90,6 +90,7 @@ static int do_mono_sample = 0; static int in_shutdown = 0; static int do_debug = 0; static int do_counters = 0; +static MonoProfileSamplingMode sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS; /* For linux compile with: * gcc -fPIC -shared -o libmono-profiler-log.so proflog.c utils.c -Wall -g -lz `pkg-config --cflags --libs mono-2` @@ -2692,6 +2693,14 @@ mono_profiler_startup (const char *desc) do_debug = 1; continue; } + if ((opt = match_option (p, "sampling-real", NULL)) != p) { + sampling_mode = MONO_PROFILER_STAT_MODE_REAL; + continue; + } + if ((opt = match_option (p, "sampling-process", NULL)) != p) { + sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS; + continue; + } if ((opt = match_option (p, "heapshot", &val)) != p) { events &= ~MONO_PROFILE_ALLOCATIONS; events &= ~MONO_PROFILE_ENTER_LEAVE; @@ -2781,6 +2790,7 @@ mono_profiler_startup (const char *desc) if (do_mono_sample && sample_type == SAMPLE_CYCLES) { events |= MONO_PROFILE_STATISTICAL; + mono_profiler_set_statistical_mode (sampling_mode, 1000000 / sample_freq); mono_profiler_install_statistical (mono_sample_hit); } From 2a11a2f11b485ac4b749909758ab41fb75c82f08 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 4 Nov 2014 22:45:14 -0500 Subject: [PATCH 526/543] [arm] Fix OP_LOCALLOC on arm so it correctly adjusts sp with the param area size even if the size is large. Fixes #24221. --- mono/mini/mini-arm.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index 9491a442d1a..7e7c5937b97 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -247,9 +247,32 @@ emit_big_add (guint8 *code, int dreg, int sreg, int imm) ARM_ADD_REG_IMM (code, dreg, sreg, imm8, rot_amount); return code; } - g_assert (dreg != sreg); - code = mono_arm_emit_load_imm (code, dreg, imm); - ARM_ADD_REG_REG (code, dreg, dreg, sreg); + if (dreg == sreg) { + code = mono_arm_emit_load_imm (code, ARMREG_IP, imm); + ARM_ADD_REG_REG (code, dreg, sreg, ARMREG_IP); + } else { + code = mono_arm_emit_load_imm (code, dreg, imm); + ARM_ADD_REG_REG (code, dreg, dreg, sreg); + } + return code; +} + +/* If dreg == sreg, this clobbers IP */ +static guint8* +emit_sub_imm (guint8 *code, int dreg, int sreg, int imm) +{ + int imm8, rot_amount; + if ((imm8 = mono_arm_is_rotated_imm8 (imm, &rot_amount)) >= 0) { + ARM_SUB_REG_IMM (code, dreg, sreg, imm8, rot_amount); + return code; + } + if (dreg == sreg) { + code = mono_arm_emit_load_imm (code, ARMREG_IP, imm); + ARM_SUB_REG_REG (code, dreg, sreg, ARMREG_IP); + } else { + code = mono_arm_emit_load_imm (code, dreg, imm); + ARM_SUB_REG_REG (code, dreg, dreg, sreg); + } return code; } @@ -4945,15 +4968,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; } case OP_LOCALLOC: { - /* keep alignment */ - int alloca_waste = cfg->param_area; - alloca_waste += 7; - alloca_waste &= ~7; /* round the size to 8 bytes */ ARM_ADD_REG_IMM8 (code, ins->dreg, ins->sreg1, 7); ARM_BIC_REG_IMM8 (code, ins->dreg, ins->dreg, 7); - if (alloca_waste) - ARM_ADD_REG_IMM8 (code, ins->dreg, ins->dreg, alloca_waste); ARM_SUB_REG_REG (code, ARMREG_SP, ARMREG_SP, ins->dreg); /* memzero the area: dreg holds the size, sp is the pointer */ if (ins->flags & MONO_INST_INIT) { @@ -4969,7 +4986,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ARM_B_COND (code, ARMCOND_GE, 0); arm_patch (code - 4, start_loop); } - ARM_ADD_REG_IMM8 (code, ins->dreg, ARMREG_SP, alloca_waste); + ARM_MOV_REG_REG (code, ins->dreg, ARMREG_SP); + if (cfg->param_area) + code = emit_sub_imm (code, ARMREG_SP, ARMREG_SP, ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT)); break; } case OP_DYN_CALL: { From d8aad87c88882a980e8c43b78d24d8fa760ba5fc Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Wed, 5 Nov 2014 13:00:37 +0100 Subject: [PATCH 527/543] [linker] blacklist System.Net.Sockets.MulticastOption fields - merge fix for https://bugzilla.xamarin.com/show_bug.cgi?id=21578 the MulticastOption's 'private IPAddress local' field was removed by linker and the app crashed later at runtime. - when System.Net.Sockets.MulticastOption object is passed to System.Net.Sockets.Socket.SetSocketOption and thru it to System.Net.Sockets.Socket.SetSocketOption_internal it accesses passed object fields (thru few more native calls). --- mcs/tools/linker/Descriptors/System.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/mcs/tools/linker/Descriptors/System.xml b/mcs/tools/linker/Descriptors/System.xml index 181a3ebc36c..f70c020412d 100644 --- a/mcs/tools/linker/Descriptors/System.xml +++ b/mcs/tools/linker/Descriptors/System.xml @@ -13,6 +13,7 @@ + From b324cecd4f7dabec0d34c8b5c12ce764bfda8475 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 5 Nov 2014 16:30:13 +0000 Subject: [PATCH 528/543] TZ display name changes no longer reset adjustment rules. Reset of adjustment rules is mandatory when the base offset is changed because the rules are relative to the base offset. Adjustment rules are now kept until the base offset changes. --- mcs/class/System.Core/System/TimeZoneInfo.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index f6fa19c0d34..354b47a2a06 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -1179,9 +1179,9 @@ private static TimeZoneInfo ParseTZBuffer (string id, byte [] buffer, int length DateTime ttime = pair.Key; TimeType ttype = pair.Value; if (!ttype.IsDst) { - if (standardDisplayName != ttype.Name || baseUtcOffset.TotalSeconds != ttype.Offset) { + if (standardDisplayName != ttype.Name) standardDisplayName = ttype.Name; - daylightDisplayName = null; + if (baseUtcOffset.TotalSeconds != ttype.Offset) { baseUtcOffset = new TimeSpan (0, 0, ttype.Offset); if (adjustmentRules.Count > 0) // We ignore AdjustmentRules but store transitions. storeTransition = true; @@ -1217,10 +1217,11 @@ private static TimeZoneInfo ParseTZBuffer (string id, byte [] buffer, int length } dst_observed = false; } else { - if (daylightDisplayName != ttype.Name || dstDelta.TotalSeconds != ttype.Offset - baseUtcOffset.TotalSeconds) { + if (daylightDisplayName != ttype.Name) daylightDisplayName = ttype.Name; + if (dstDelta.TotalSeconds != ttype.Offset - baseUtcOffset.TotalSeconds) dstDelta = new TimeSpan(0, 0, ttype.Offset) - baseUtcOffset; - } + dst_start = ttime; dst_observed = true; } From 570cb1a10a8046ded21cdad160a30dbd12cf9a59 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 5 Nov 2014 16:38:39 +0000 Subject: [PATCH 529/543] Changed script DateTime.Now_Test.sh to use the compiled csharp.exe. --- mcs/class/corlib/DateTime.Now_Test.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mcs/class/corlib/DateTime.Now_Test.sh b/mcs/class/corlib/DateTime.Now_Test.sh index 27b9c2014d2..2d43f635d0c 100755 --- a/mcs/class/corlib/DateTime.Now_Test.sh +++ b/mcs/class/corlib/DateTime.Now_Test.sh @@ -1,7 +1,10 @@ #!/bin/sh SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -export MONO_PATH=${MONO_PATH:-$SCRIPT_PATH/../lib/net_4_5/} +CSHARP=$SCRIPT_PATH/../lib/net_4_5/csharp.exe +MONO=$SCRIPT_PATH/../../../mono/mini/mono + +export MONO_PATH=${MONO_PATH:-$SCRIPT_PATH/../lib/net_4_5} TZ_FAILS=0 TZ_COUNT=0 @@ -10,7 +13,7 @@ FORMAT="%a %b %d %T %Y" for tz in $(cd /usr/share/zoneinfo/; find * -type f -print); do TZ_COUNT=$(expr $TZ_COUNT + 1) SYS_DATETIME=$(date -ju -f "$FORMAT" "$(TZ=$tz date "+$FORMAT")" "+%s") - CS_DATETIME=$(TZ=$tz csharp -e '(int)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;') + CS_DATETIME=$(TZ=$tz $MONO $CSHARP -e '(int)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;') DIFF=$(expr $SYS_DATETIME - $CS_DATETIME) if [ "$DIFF" -gt "5" ] || [ "$DIFF" -lt "-5" ]; then TZ_FAILS=$(expr $TZ_FAILS + 1) From ed65bc251d3d9df0868358c7febcc6168e5bf0e7 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 5 Nov 2014 16:56:38 -0500 Subject: [PATCH 530/543] Revert "Disable building the NET 2.0 profile by default." This reverts commit fe265502cc517e8374ce2988f31e88d4f3554d8a. Revert this for now as it breaks too much stuff. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 671b3a23d66..2bc3c0d08f5 100644 --- a/configure.ac +++ b/configure.ac @@ -3199,7 +3199,7 @@ case "x$libgc" in ;; esac -AC_ARG_WITH(profile2, [ --with-profile2=yes,no If you want to install the 2.0/3.5 FX (defaults to no)], [], [with_profile2=no]) +AC_ARG_WITH(profile2, [ --with-profile2=yes,no If you want to install the 2.0/3.5 FX (defaults to yes)], [], [with_profile2=yes]) AC_ARG_WITH(profile4, [ --with-profile4=yes,no If you want to install the 4.0 FX (defaults to yes)], [], [with_profile4=yes]) AC_ARG_WITH(profile4_5,[ --with-profile4_5=yes,no If you want to install the 4.5 FX (defaults to yes)], [], [with_profile4_5=yes]) AC_ARG_WITH(monodroid, [ --with-monodroid=yes,no If you want to build the MonoDroid assemblies (defaults to no)], [], [with_monodroid=no]) From 363302f71fb49ee3e70b60ff04d6fcb0f01b77e5 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 5 Nov 2014 17:31:48 -0500 Subject: [PATCH 531/543] Install Mono.Cecil in the net 4.5 profile. --- mcs/class/Mono.Cecil/Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mcs/class/Mono.Cecil/Makefile b/mcs/class/Mono.Cecil/Makefile index d9643b7f5a9..37d7fb0f56d 100644 --- a/mcs/class/Mono.Cecil/Makefile +++ b/mcs/class/Mono.Cecil/Makefile @@ -9,8 +9,4 @@ LIB_MCS_FLAGS = /r:$(corlib) -keyfile:$(LIBRARY_SNK) -r:System.Core.dll -d:NET_3 NO_TEST = yes -ifneq (net_2_0, $(PROFILE)) -NO_INSTALL = yes -endif - include ../../build/library.make From edb931dfb9741660fefe73528c503b17e1341f4d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 6 Nov 2014 19:44:57 -0500 Subject: [PATCH 532/543] [runtime] Use a separate signal with the SA_RESTART flag set for suspending/resuming threads during debugging on android, since lots of android native code cannot handle the interruptions caused by the normal abort signal. Fixes #22968/#23987. --- mono/utils/mono-threads-mach.c | 2 +- mono/utils/mono-threads-posix.c | 44 +++++++++++++++++++++++++------ mono/utils/mono-threads-windows.c | 2 +- mono/utils/mono-threads.c | 2 +- mono/utils/mono-threads.h | 2 +- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/mono/utils/mono-threads-mach.c b/mono/utils/mono-threads-mach.c index 4ed6820e900..6270c57f1d6 100644 --- a/mono/utils/mono-threads-mach.c +++ b/mono/utils/mono-threads-mach.c @@ -48,7 +48,7 @@ mono_threads_core_needs_abort_syscall (void) } gboolean -mono_threads_core_suspend (MonoThreadInfo *info) +mono_threads_core_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { kern_return_t ret; gboolean res; diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index 51bdc8df76e..5fb6fc51e15 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -39,6 +39,10 @@ typedef struct { HANDLE handle; } StartInfo; +#ifdef PLATFORM_ANDROID +static int no_interrupt_signo; +#endif + static void* inner_start_thread (void *arg) { @@ -325,7 +329,7 @@ suspend_signal_handler (int _dummy, siginfo_t *info, void *context) #endif static void -mono_posix_add_signal_handler (int signo, gpointer handler) +mono_posix_add_signal_handler (int signo, gpointer handler, int flags) { #if !defined(__native_client__) /*FIXME, move the code from mini to utils and do the right thing!*/ @@ -335,7 +339,7 @@ mono_posix_add_signal_handler (int signo, gpointer handler) sa.sa_sigaction = handler; sigemptyset (&sa.sa_mask); - sa.sa_flags = SA_SIGINFO; + sa.sa_flags = SA_SIGINFO | flags; ret = sigaction (signo, &sa, &previous_sa); g_assert (ret != -1); @@ -346,19 +350,36 @@ void mono_threads_init_platform (void) { #if !defined(__native_client__) + int abort_signo; + /* FIXME we should use all macros from mini to make this more portable FIXME it would be very sweet if sgen could end up using this too. */ - if (mono_thread_info_new_interrupt_enabled ()) - mono_posix_add_signal_handler (mono_thread_get_abort_signal (), suspend_signal_handler); + if (!mono_thread_info_new_interrupt_enabled ()) + return; + abort_signo = mono_thread_get_abort_signal (); + mono_posix_add_signal_handler (abort_signo, suspend_signal_handler, 0); + +#ifdef PLATFORM_ANDROID + /* + * Lots of android native code can't handle the EINTR caused by + * the normal abort signal, so use a different signal for the + * no interruption case, which is used by sdb. + * FIXME: Use this on all platforms. + * SIGUSR1 is used by dalvik/art. + */ + no_interrupt_signo = SIGUSR2; + g_assert (abort_signo != no_interrupt_signo); + mono_posix_add_signal_handler (abort_signo, suspend_signal_handler, SA_RESTART); +#endif #endif } -/*nothing to be done here since suspend always abort syscalls due using signals*/ void mono_threads_core_interrupt (MonoThreadInfo *info) { + /* Handled in mono_threads_core_suspend () */ } void @@ -379,10 +400,17 @@ mono_threads_core_needs_abort_syscall (void) } gboolean -mono_threads_core_suspend (MonoThreadInfo *info) +mono_threads_core_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { /*FIXME, check return value*/ - mono_threads_pthread_kill (info, mono_thread_get_abort_signal ()); +#ifdef PLATFORM_ANDROID + if (interrupt_kernel) + mono_threads_pthread_kill (info, no_interrupt_signo); + else + mono_threads_pthread_kill (info, mono_thread_get_abort_signal ()); +#else + mono_threads_pthread_kill (info, mono_thread_get_abort_signal ()); +#endif while (MONO_SEM_WAIT (&info->begin_suspend_semaphore) != 0) { /* g_assert (errno == EINTR); */ } @@ -406,7 +434,7 @@ mono_threads_platform_register (MonoThreadInfo *info) MONO_SEM_INIT (&info->begin_suspend_semaphore, 0); #if defined (PLATFORM_ANDROID) - info->native_handle = (gpointer) gettid (); + info->native_handle = gettid (); #endif } diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index 04430fb021f..02bd26e0c79 100755 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -58,7 +58,7 @@ mono_threads_core_self_suspend (MonoThreadInfo *info) } gboolean -mono_threads_core_suspend (MonoThreadInfo *info) +mono_threads_core_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { DWORD id = mono_thread_info_get_tid (info); HANDLE handle; diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index 9aa70ac20b0..dd500372404 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -426,7 +426,7 @@ mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel return info; } - if (!mono_threads_core_suspend (info)) { + if (!mono_threads_core_suspend (info, interrupt_kernel)) { MONO_SEM_POST (&info->suspend_semaphore); mono_hazard_pointer_clear (hp, 1); *error_condition = "Could not suspend thread"; diff --git a/mono/utils/mono-threads.h b/mono/utils/mono-threads.h index b26ccbec35c..f09a957e84f 100644 --- a/mono/utils/mono-threads.h +++ b/mono/utils/mono-threads.h @@ -336,7 +336,7 @@ mono_threads_pthread_kill (THREAD_INFO_TYPE *info, int signum) MONO_INTERNAL; /* Plartform specific functions DON'T use them */ void mono_threads_init_platform (void) MONO_INTERNAL; //ok -gboolean mono_threads_core_suspend (THREAD_INFO_TYPE *info) MONO_INTERNAL; +gboolean mono_threads_core_suspend (THREAD_INFO_TYPE *info, gboolean interrupt_kernel) MONO_INTERNAL; gboolean mono_threads_core_resume (THREAD_INFO_TYPE *info) MONO_INTERNAL; void mono_threads_platform_register (THREAD_INFO_TYPE *info) MONO_INTERNAL; //ok void mono_threads_platform_free (THREAD_INFO_TYPE *info) MONO_INTERNAL; From bf39f5aec034800abcfe5e73a63ddd1414cb8078 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Fri, 7 Nov 2014 15:35:40 +0800 Subject: [PATCH 533/543] [xml] XmlElement.InnserXml seems to preserve whitespaces. Fix for mdoc test regression (see commit comments on #661430f). --- mcs/class/System.XML/System.Xml/XmlElement.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/mcs/class/System.XML/System.Xml/XmlElement.cs b/mcs/class/System.XML/System.Xml/XmlElement.cs index 120355f5843..2d9d1e0e930 100644 --- a/mcs/class/System.XML/System.Xml/XmlElement.cs +++ b/mcs/class/System.XML/System.Xml/XmlElement.cs @@ -152,11 +152,17 @@ public override string InnerXml { XmlTextReader xmlReader = new XmlTextReader (value, XmlNodeType.Element, ctx); xmlReader.XmlResolver = OwnerDocument.Resolver; - do { - XmlNode n = OwnerDocument.ReadNode (xmlReader); - if(n == null) break; - AppendChild (n); - } while (true); + bool pw = OwnerDocument.PreserveWhitespace; + OwnerDocument.PreserveWhitespace = true; + try { + do { + XmlNode n = OwnerDocument.ReadNode (xmlReader); + if(n == null) break; + AppendChild (n); + } while (true); + } finally { + OwnerDocument.PreserveWhitespace = pw; + } } } From 367d417207d81e519e57102efc48004daab7a54a Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Fri, 7 Nov 2014 20:42:25 +0800 Subject: [PATCH 534/543] [Mono.Posix] consider nano time info in UnixFileSystemInfo.Last*Time. Before this change, those Last*Time properties returned only based on seconds (truncated), which could cause inaccurate time comparison. Consider code like this: var fileUpdated = DateTime.Now; ... File.WriteAllText (path, "foobar"); ... if (fileUpdated > new UnixFileInfo (path).LastWriteTime) OnUpdatedFile (path); This could always result in raising update event, even if there was no update after writing. Last*Time With milliseconds makes it very unlikely to happen. --- mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.cs | 5 +++++ mcs/class/Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.cs b/mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.cs index 7951d08ae17..ffa329f1b5b 100644 --- a/mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.cs +++ b/mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.cs @@ -195,6 +195,11 @@ public static DateTime ToDateTime (long time) return FromTimeT (time); } + public static DateTime ToDateTime (long time, long nanoTime) + { + return FromTimeT (time).AddMilliseconds (nanoTime / 1000); + } + public static long FromDateTime (DateTime time) { return ToTimeT (time); diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs index c6a9b283b5f..149f79b84ed 100644 --- a/mcs/class/Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs +++ b/mcs/class/Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs @@ -192,7 +192,7 @@ public long BlocksAllocated { } public DateTime LastAccessTime { - get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_atime);} + get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_atime, stat.st_atime_nsec);} } public DateTime LastAccessTimeUtc { @@ -200,7 +200,7 @@ public DateTime LastAccessTimeUtc { } public DateTime LastWriteTime { - get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_mtime);} + get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_mtime, stat.st_mtime_nsec);} } public DateTime LastWriteTimeUtc { @@ -208,7 +208,7 @@ public DateTime LastWriteTimeUtc { } public DateTime LastStatusChangeTime { - get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_ctime);} + get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_ctime, stat.st_ctime_nsec);} } public DateTime LastStatusChangeTimeUtc { From db2381da04c167cb6e6e162497265ee1e45cb180 Mon Sep 17 00:00:00 2001 From: Kenneth Pouncey Date: Fri, 7 Nov 2014 16:41:05 +0100 Subject: [PATCH 535/543] Fix GetUsing to output the using name instead of -> using Mono.CSharp.NamespaceExpression; <- for every using statement that was set + Fix NRE when source_file or source_file.Usings is null. This will now return back an empty string or empty List + **Note** that we are returning the ToString() value of NamespaceExpression which is the full resolved namespace of "System.Drawing" instead of "Drawing". + Add ToString override for NamespaceExpression to return the full resolved name of the namespace. --- mcs/mcs/ecore.cs | 5 +++++ mcs/mcs/eval.cs | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 3143908b63a..a91f3dc6b82 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -3208,6 +3208,11 @@ public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string nam { return ns.LookupTypeOrNamespace (ctx, name, arity, mode, loc); } + + public override string ToString() + { + return Namespace.Name; + } } /// diff --git a/mcs/mcs/eval.cs b/mcs/mcs/eval.cs index 059ffb82d1d..384d8dd3199 100644 --- a/mcs/mcs/eval.cs +++ b/mcs/mcs/eval.cs @@ -863,13 +863,19 @@ static string Quote (string s) public string GetUsing () { + if (source_file == null || source_file.Usings == null) + return string.Empty; + StringBuilder sb = new StringBuilder (); // TODO: //foreach (object x in ns.using_alias_list) // sb.AppendFormat ("using {0};\n", x); foreach (var ue in source_file.Usings) { - sb.AppendFormat ("using {0};", ue.ToString ()); + if (ue.Alias != null || ue.ResolvedExpression == null) + continue; + + sb.AppendFormat("using {0};", ue.ToString()); sb.Append (Environment.NewLine); } @@ -880,7 +886,11 @@ internal List GetUsingList () { var res = new List (); - foreach (var ue in source_file.Usings) { + if (source_file == null || source_file.Usings == null) + return res; + + foreach (var ue in source_file.Usings) + { if (ue.Alias != null || ue.ResolvedExpression == null) continue; From 3664e4c5a7f95a2e837fce9eca45deef669306fa Mon Sep 17 00:00:00 2001 From: Kenneth Pouncey Date: Fri, 7 Nov 2014 16:57:41 +0100 Subject: [PATCH 536/543] Add space --- mcs/mcs/ecore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index a91f3dc6b82..49a56e78f67 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -3209,7 +3209,7 @@ public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string nam return ns.LookupTypeOrNamespace (ctx, name, arity, mode, loc); } - public override string ToString() + public override string ToString () { return Namespace.Name; } From de3ff228dc04cfa5cccd247bc09283688b3c50ba Mon Sep 17 00:00:00 2001 From: Kenneth Pouncey Date: Fri, 7 Nov 2014 16:59:42 +0100 Subject: [PATCH 537/543] Add space --- mcs/mcs/eval.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcs/mcs/eval.cs b/mcs/mcs/eval.cs index 384d8dd3199..c1ea5aaa576 100644 --- a/mcs/mcs/eval.cs +++ b/mcs/mcs/eval.cs @@ -875,7 +875,7 @@ public string GetUsing () if (ue.Alias != null || ue.ResolvedExpression == null) continue; - sb.AppendFormat("using {0};", ue.ToString()); + sb.AppendFormat("using {0};", ue.ToString ()); sb.Append (Environment.NewLine); } From f06badd7ba41d8d7a7530257ad6d05911a4515c5 Mon Sep 17 00:00:00 2001 From: SushiHangover Date: Tue, 1 Sep 2015 21:45:02 -0700 Subject: [PATCH 538/543] Update version to bump pull request to get travis to run (did not pick up the pull request) --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 0de87159a12..a33ba7d654c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # Process this file with autoconf to produce a configure script. #AC_PREREQ([2.62]) -AC_INIT(mono, [3.10.1], +AC_INIT(mono, [3.10.1001], [http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono]) AC_CONFIG_SRCDIR([README.md]) From 5b9835524cbb0d96178345602ad0f5ec9b7787df Mon Sep 17 00:00:00 2001 From: SushiHangover Date: Wed, 2 Sep 2015 01:59:31 -0700 Subject: [PATCH 539/543] Added 9 more tests to track AS operators regressions, need more tests, tests, tests... From: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/operators.html# Added Issue #80 to track "typeof" not returning the proper strings --- mcs/playc_tests/as/test-as-LogicalOr-02.as | 16 +++++++++ mcs/playc_tests/as/test-as-LogicalOr-03.as | 32 ++++++++++++++++++ mcs/playc_tests/as/test-as-LogicalOr.as | 21 ++++++++++++ mcs/playc_tests/as/test-as-Modulo.as | 21 ++++++++++++ mcs/playc_tests/as/test-as-NewOperator.as | 26 +++++++++++++++ .../test-as-ObjectInitializerOperator-01.as | 25 ++++++++++++++ .../test-as-ObjectInitializerOperator-02.as | 32 ++++++++++++++++++ mcs/playc_tests/as/test-as-Parentheses.as | 21 ++++++++++++ mcs/playc_tests/as/test-as-Typeof.as | 33 +++++++++++++++++++ mcs/playc_tests/play-issues-net_4_5 | 2 ++ 10 files changed, 229 insertions(+) create mode 100644 mcs/playc_tests/as/test-as-LogicalOr-02.as create mode 100644 mcs/playc_tests/as/test-as-LogicalOr-03.as create mode 100644 mcs/playc_tests/as/test-as-LogicalOr.as create mode 100644 mcs/playc_tests/as/test-as-Modulo.as create mode 100644 mcs/playc_tests/as/test-as-NewOperator.as create mode 100644 mcs/playc_tests/as/test-as-ObjectInitializerOperator-01.as create mode 100644 mcs/playc_tests/as/test-as-ObjectInitializerOperator-02.as create mode 100644 mcs/playc_tests/as/test-as-Parentheses.as create mode 100644 mcs/playc_tests/as/test-as-Typeof.as diff --git a/mcs/playc_tests/as/test-as-LogicalOr-02.as b/mcs/playc_tests/as/test-as-LogicalOr-02.as new file mode 100644 index 00000000000..1b42839cb4c --- /dev/null +++ b/mcs/playc_tests/as/test-as-LogicalOr-02.as @@ -0,0 +1,16 @@ +// Compiler options: -psstrict+ +package { + public class Foo { + public static function Main():int { + + var a:Number = 10; + var b:Number = 250; + var start:Boolean = false; + if ((a > 25) || (b > 200) || (start)) { + trace("the logical OR test passed"); // the logical OR test passed + return 0; + } + return 1; + } + } +} diff --git a/mcs/playc_tests/as/test-as-LogicalOr-03.as b/mcs/playc_tests/as/test-as-LogicalOr-03.as new file mode 100644 index 00000000000..b6c2a5f5396 --- /dev/null +++ b/mcs/playc_tests/as/test-as-LogicalOr-03.as @@ -0,0 +1,32 @@ +// Compiler options: -psstrict- +package { + public class Foo { + + static var fail:Boolean = false; + + static function fx1():Boolean { + trace("fx1 called"); + return true; + } + + static function fx2():Boolean { + trace("fx2 called"); + fail = true; + return true; + } + + // The following example demonstrates how using a function call as + // the second operand can lead to unexpected results. If the expression + // on the left of the operator evaluates to true, that result is returned + // without evaluating the expression on the right (the function fx2() + // is not called). + + public static function Main():int { + if (fx1() || fx2()) { + trace("IF statement entered"); + if (fail) return 1; + } + return 0; + } + } +} diff --git a/mcs/playc_tests/as/test-as-LogicalOr.as b/mcs/playc_tests/as/test-as-LogicalOr.as new file mode 100644 index 00000000000..df54f43498c --- /dev/null +++ b/mcs/playc_tests/as/test-as-LogicalOr.as @@ -0,0 +1,21 @@ +// Compiler options: -psstrict+ +package { + public class Foo { + public static function Main():int { + + var x:Boolean = false; + var y:Boolean = true; + + x ||= y; + trace (x); + if (!x) return 1; + + x = false; + x = x || y; + trace (x); + if (!x) return 1; + + return 0; + } + } +} diff --git a/mcs/playc_tests/as/test-as-Modulo.as b/mcs/playc_tests/as/test-as-Modulo.as new file mode 100644 index 00000000000..8f19141b1dc --- /dev/null +++ b/mcs/playc_tests/as/test-as-Modulo.as @@ -0,0 +1,21 @@ +// Compiler options: -psstrict+ +package { + public class Foo { + public static function Main():int { + + trace(12 % 5); // 2 + if (12 % 5 != 2) return 1; + + trace(-4 % 3); // -1 + if (-4 % 3 != -1) return 2; + + trace(-4 % -3); // -1 + if (-4 % -3 != -1) return 3; + + trace(4 % 4); // 0 + if (4 % 4 != 0) return 4; + + return 0; + } + } +} diff --git a/mcs/playc_tests/as/test-as-NewOperator.as b/mcs/playc_tests/as/test-as-NewOperator.as new file mode 100644 index 00000000000..e457c7874e8 --- /dev/null +++ b/mcs/playc_tests/as/test-as-NewOperator.as @@ -0,0 +1,26 @@ +// Compiler options: -psstrict+ +package { + + class Book { + public var bName:String; + public var bPrice:Number; + + public function Book(nameParam:String, priceParam:Number){ + bName = nameParam; + bPrice = priceParam; + } + } + + public class Foo { + public static function Main():int { + var book1:Book = new Book("Confederacy of Dunces", 19.95); + var book2:Book = new Book("The Floating Opera", 10.95); + trace(book1); // [object Book] + if (book1.bName != "Confederacy of Dunces") return 1; + if (book2.bPrice != 10.95) return 2; + trace(book1); // [object Book] + if (book1.toString() != "[object Book]") return 3; + return 0; + } + } +} diff --git a/mcs/playc_tests/as/test-as-ObjectInitializerOperator-01.as b/mcs/playc_tests/as/test-as-ObjectInitializerOperator-01.as new file mode 100644 index 00000000000..d442f3c4c14 --- /dev/null +++ b/mcs/playc_tests/as/test-as-ObjectInitializerOperator-01.as @@ -0,0 +1,25 @@ +// Compiler options: -psstrict+ +package { + public class Foo { + public static function Main():int { + + var object:Object = {}; + var object:Object = new Object(); + + var x:int = 0; + var account:Object = {name:"Adobe Systems, Inc.", address:"601 Townsend Street", city:"San Francisco", state:"California", zip:"94103", balance:"1000"}; + + for (var i:* in account) { + trace("account."+i+" = "+account[i]); + + x++; + if (x == 6) { + if (i != "balance") return 1; + if (account[i] != "1000") return 2; + } + } + + return 0; + } + } +} diff --git a/mcs/playc_tests/as/test-as-ObjectInitializerOperator-02.as b/mcs/playc_tests/as/test-as-ObjectInitializerOperator-02.as new file mode 100644 index 00000000000..d3204805fd9 --- /dev/null +++ b/mcs/playc_tests/as/test-as-ObjectInitializerOperator-02.as @@ -0,0 +1,32 @@ +// Compiler options: -psstrict- +package { + public class Foo { + public static function Main():int { + + // The following example shows how array and object initializers can + // be nested within each other: + + var person2:Object = {name:"Gina Vechio", children:["Ruby", "Chickie", "Puppa"]}; + + // The following code uses the information in the previous example + // and produces the same result using a constructor function: + + var person:Object = new Object(); + person.name = "Gina Vechio"; + person.children = new Array(); + person.children[0] = "Ruby"; + person.children[1] = "Chickie"; + person.children[2] = "Puppa"; + + // Thus person and person2 should contain identicial values + + if (person.name != person2.name) return 9; + + if (person.children[2] != person2.children[2]) return 1; + if (person.children[1] != person2.children[1]) return 2; + if (person.children[0] != person2.children[0]) return 3; + + return 0; + } + } +} diff --git a/mcs/playc_tests/as/test-as-Parentheses.as b/mcs/playc_tests/as/test-as-Parentheses.as new file mode 100644 index 00000000000..78ea2583720 --- /dev/null +++ b/mcs/playc_tests/as/test-as-Parentheses.as @@ -0,0 +1,21 @@ +// Compiler options: -psstrict- +package { + public class Foo { + public static function Main():int { + + trace((2 + 3) * (4 + 5)); // 45 + if ((2 + 3) * (4 + 5) != 45) return 1; + + trace(2 + (3 * (4 + 5))); // 29 + if (2 + (3 * (4 + 5)) != 29) return 2; + + trace(2 + (3 * 4) + 5); // 19 + if (2 + (3 * 4) + 5 != 19) return 3; + + trace(2 + (3 * 4) + 5); // 19 + if (2 + (3 * 4) + 5 != 19) return 4; + + return 0; + } + } +} diff --git a/mcs/playc_tests/as/test-as-Typeof.as b/mcs/playc_tests/as/test-as-Typeof.as new file mode 100644 index 00000000000..3196b244d47 --- /dev/null +++ b/mcs/playc_tests/as/test-as-Typeof.as @@ -0,0 +1,33 @@ +// Compiler options: -psstrict+ +package { + public class Foo { + public static function Main():int { + + trace(typeof Array); // object + trace(typeof Boolean); // boolean + trace(typeof Function); // function + trace(typeof int); + trace(typeof Number); + trace(typeof Object); + trace(typeof String); + trace(typeof uint); + trace(typeof XML); + trace(typeof XMLList); + //trace(typeof *); + + if ((typeof Array) == "object") return 1; + if ((typeof Boolean) == "boolean") return 2; + if ((typeof Function) == "function") return 3; + if ((typeof int) == "number") return 4; + if ((typeof Number) == "number") return 5; + if ((typeof Object) == "object") return 6; + if ((typeof String) == "string") return 7; + if ((typeof uint) == "number") return 8; + if ((typeof XML) == "xml") return 9; + if ((typeof XMLList) == "xml") return 10; + //if ((typeof *) == "undefined") return 11; + + return 0; + } + } +} diff --git a/mcs/playc_tests/play-issues-net_4_5 b/mcs/playc_tests/play-issues-net_4_5 index 4c211da2e0e..c21e47b2faf 100644 --- a/mcs/playc_tests/play-issues-net_4_5 +++ b/mcs/playc_tests/play-issues-net_4_5 @@ -4,6 +4,8 @@ # csXXXX.as : test case causes error # csXXXX.as IGNORE : adds test to ignore list +# Issue #80 - Typeof not returning the proper (string) values +as/test-as-Typeof.as # Issue #62 - XML.attributes - Implement function - Currently System.NotImplementedException ./as/test-as-XML-Attributes-Access.as IGNORE From 0a8538de1b173d1b9e1b7032ab10a42aae40c6c7 Mon Sep 17 00:00:00 2001 From: SushiHangover Date: Wed, 2 Sep 2015 02:52:11 -0700 Subject: [PATCH 540/543] Update play test il, fixed path of known test failure (Issue #70) --- mcs/playc_tests/play-il-net_4_5.xml | 94 +++++++++++++++++++++++++++++ mcs/playc_tests/play-issues-net_4_5 | 2 +- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/mcs/playc_tests/play-il-net_4_5.xml b/mcs/playc_tests/play-il-net_4_5.xml index dcb48972bfc..aeb91ff469b 100644 --- a/mcs/playc_tests/play-il-net_4_5.xml +++ b/mcs/playc_tests/play-il-net_4_5.xml @@ -640,6 +640,70 @@ + + + + 86 + + + 7 + + + + + + + 20 + + + 26 + + + 59 + + + 7 + + + 7 + + + + + + + 86 + + + 7 + + + + + + + 54 + + + 7 + + + + + + + 22 + + + + + 145 + + + 7 + + + @@ -663,6 +727,36 @@ + + + + 436 + + + 7 + + + + + + + 934 + + + 7 + + + + + + + 58 + + + 7 + + + diff --git a/mcs/playc_tests/play-issues-net_4_5 b/mcs/playc_tests/play-issues-net_4_5 index c21e47b2faf..589252982a8 100644 --- a/mcs/playc_tests/play-issues-net_4_5 +++ b/mcs/playc_tests/play-issues-net_4_5 @@ -5,7 +5,7 @@ # csXXXX.as IGNORE : adds test to ignore list # Issue #80 - Typeof not returning the proper (string) values -as/test-as-Typeof.as +./as/test-as-Typeof.as # Issue #62 - XML.attributes - Implement function - Currently System.NotImplementedException ./as/test-as-XML-Attributes-Access.as IGNORE From 0b8a7604e1af7dd70f72318c681058efa03cd21a Mon Sep 17 00:00:00 2001 From: SushiHangover Date: Wed, 2 Sep 2015 17:46:21 -0700 Subject: [PATCH 541/543] Parity in .play for: declaration expression after ref/out arguments from upstream: commit 5ad92e6b10d5c19dd9974ecd762ab97fb811b29a Author: Marek Safar Date: Mon Sep 22 17:26:55 2014 +0200 [mcs] declaration expression after ref/out argument --- mcs/mcs/ps-parser.jay | 50 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/mcs/mcs/ps-parser.jay b/mcs/mcs/ps-parser.jay index 8edfd4bbdc9..4ec68182b48 100644 --- a/mcs/mcs/ps-parser.jay +++ b/mcs/mcs/ps-parser.jay @@ -4198,11 +4198,61 @@ non_simple_argument $$ = new Argument ((Expression) $2, Argument.AType.Ref); lbag.AddLocation ($$, GetLocation ($1)); } + | REF declaration_expression + { + $$ = new Argument ((Expression) $2, Argument.AType.Ref); + } | OUT variable_reference { $$ = new Argument ((Expression) $2, Argument.AType.Out); lbag.AddLocation ($$, GetLocation ($1)); } + | OUT declaration_expression + { + $$ = new Argument ((Expression) $2, Argument.AType.Out); + } + ; + +declaration_expression + : OPEN_PARENS declaration_expression CLOSE_PARENS + { + $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } +/* + | CHECKED open_parens_any declaration_expression CLOSE_PARENS + { + $$ = new CheckedExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + | UNCHECKED open_parens_any declaration_expression CLOSE_PARENS + { + $$ = new UnCheckedExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } +*/ + | variable_type identifier_inside_body + { + if (lang_version < LanguageVersion.V_6) + FeatureIsNotAvailable (GetLocation ($1), "declaration expression"); + + var lt = (LocatedToken) $2; + var lv = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (lv); + $$ = new DeclarationExpression ((FullNamedExpression) $1, lv); + } + | variable_type identifier_inside_body ASSIGN expression + { + if (lang_version < LanguageVersion.V_6) + FeatureIsNotAvailable (GetLocation ($1), "declaration expression"); + + var lt = (LocatedToken) $2; + var lv = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (lv); + $$ = new DeclarationExpression ((FullNamedExpression) $1, lv) { + Initializer = (Expression) $4 + }; + } ; variable_reference From f8cdfc72cdc8d4e66233cd5ae4a2acc2f3bc45ad Mon Sep 17 00:00:00 2001 From: SushiHangover Date: Wed, 2 Sep 2015 21:34:59 -0700 Subject: [PATCH 542/543] Fix build / bad merges leading up to 3.12.1 --- mono/io-layer/processes.c | 32 ++++------------------- mono/metadata/sgen-fin-weak-hash.c | 41 ++++-------------------------- mono/metadata/sgen-gc.h | 1 - mono/metadata/sgen-internal.c | 1 - mono/metadata/sgen-pinning.c | 1 - mono/metadata/sgen-pointer-queue.c | 34 ++----------------------- mono/metadata/sgen-pointer-queue.h | 7 ----- mono/mini/aot-runtime.c | 8 ------ mono/mini/exceptions-amd64.c | 14 ++++------ mono/mini/mini-amd64.c | 4 --- mono/tests/Makefile.am | 11 +------- 11 files changed, 18 insertions(+), 136 deletions(-) diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index 65e32011199..3c0531f3de0 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -489,19 +489,6 @@ CreateProcessWithLogonW (const gunichar2 *username, return CreateProcess (appname, cmdline, NULL, NULL, FALSE, create_flags, env, cwd, startup, process_info); } -static gboolean -is_readable (const char *prog) -{ - struct stat buf; - if (access (prog, R_OK) != 0) - return FALSE; - if (stat (prog, &buf)) - return FALSE; - if (S_ISREG (buf.st_mode)) - return TRUE; - return FALSE; -} - static gboolean is_executable (const char *prog) { @@ -634,7 +621,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, prog = g_strdup (unquoted); /* Executable existing ? */ - if (!is_readable (prog)) { + if (!is_executable (prog)) { DEBUG ("%s: Couldn't find executable %s", __func__, prog); g_free (unquoted); @@ -650,8 +637,8 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, prog = g_strdup_printf ("%s/%s", curdir, unquoted); g_free (curdir); - /* And make sure it's readable */ - if (!is_readable (prog)) { + /* And make sure it's executable */ + if (!is_executable (prog)) { DEBUG ("%s: Couldn't find executable %s", __func__, prog); g_free (unquoted); @@ -742,7 +729,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, prog = g_strdup (token); /* Executable existing ? */ - if (!is_readable (prog)) { + if (!is_executable (prog)) { DEBUG ("%s: Couldn't find executable %s", __func__, token); g_free (token); @@ -763,10 +750,8 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, /* I assume X_OK is the criterion to use, * rather than F_OK - * - * X_OK is too strict *if* the target is a CLR binary */ - if (!is_readable (prog)) { + if (!is_executable (prog)) { g_free (prog); prog = g_find_program_in_path (token); if (prog == NULL) { @@ -823,13 +808,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, goto free_strings; } } - } else { - if (!is_executable (prog)) { - DEBUG ("%s: Executable permisson not set on %s", __func__, prog); - g_free (prog); - SetLastError (ERROR_ACCESS_DENIED); - goto free_strings; - } } if (args_after_prog != NULL && *args_after_prog) { diff --git a/mono/metadata/sgen-fin-weak-hash.c b/mono/metadata/sgen-fin-weak-hash.c index 99639432683..3793c9435be 100644 --- a/mono/metadata/sgen-fin-weak-hash.c +++ b/mono/metadata/sgen-fin-weak-hash.c @@ -30,7 +30,6 @@ #include "metadata/sgen-gc.h" #include "metadata/sgen-gray.h" #include "metadata/sgen-protocol.h" -#include "metadata/sgen-pointer-queue.h" #include "utils/dtrace.h" #include "utils/mono-counters.h" @@ -74,7 +73,7 @@ tagged_object_apply (void *object, int tag_bits) static int tagged_object_hash (MonoObject *o) { - return mono_aligned_addr_hash (tagged_object_get_object (o)); + return mono_object_hash (tagged_object_get_object (o)); } static gboolean @@ -117,9 +116,6 @@ sgen_collect_bridge_objects (int generation, ScanCopyContext ctx) MonoObject *object; gpointer dummy; char *copy; - SgenPointerQueue moved_fin_objects; - - sgen_pointer_queue_init (&moved_fin_objects, INTERNAL_MEM_TEMPORARY); if (no_finalize) return; @@ -158,24 +154,12 @@ sgen_collect_bridge_objects (int generation, ScanCopyContext ctx) SGEN_LOG (5, "Promoting finalization of object %p (%s) (was at %p) to major table", copy, sgen_safe_name (copy), object); continue; - } else if (copy != (char*)object) { + } else { /* update pointer */ - SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE); - - /* register for reinsertion */ - sgen_pointer_queue_add (&moved_fin_objects, tagged_object_apply (copy, tag)); - SGEN_LOG (5, "Updating object for finalization: %p (%s) (was at %p)", copy, sgen_safe_name (copy), object); - - continue; + SGEN_HASH_TABLE_FOREACH_SET_KEY (tagged_object_apply (copy, tag)); } } SGEN_HASH_TABLE_FOREACH_END; - - while (!sgen_pointer_queue_is_empty (&moved_fin_objects)) { - sgen_hash_table_replace (hash_table, sgen_pointer_queue_pop (&moved_fin_objects), NULL, NULL); - } - - sgen_pointer_queue_free (&moved_fin_objects); } @@ -188,9 +172,6 @@ sgen_finalize_in_range (int generation, ScanCopyContext ctx) SgenHashTable *hash_table = get_finalize_entry_hash_table (generation); MonoObject *object; gpointer dummy; - SgenPointerQueue moved_fin_objects; - - sgen_pointer_queue_init (&moved_fin_objects, INTERNAL_MEM_TEMPORARY); if (no_finalize) return; @@ -220,26 +201,14 @@ sgen_finalize_in_range (int generation, ScanCopyContext ctx) SGEN_LOG (5, "Promoting finalization of object %p (%s) (was at %p) to major table", copy, sgen_safe_name (copy), object); continue; - } else if (copy != object) { + } else { /* update pointer */ - SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE); - - /* register for reinsertion */ - sgen_pointer_queue_add (&moved_fin_objects, tagged_object_apply (copy, tag)); - SGEN_LOG (5, "Updating object for finalization: %p (%s) (was at %p)", copy, sgen_safe_name (copy), object); - - continue; + SGEN_HASH_TABLE_FOREACH_SET_KEY (tagged_object_apply (copy, tag)); } } } } SGEN_HASH_TABLE_FOREACH_END; - - while (!sgen_pointer_queue_is_empty (&moved_fin_objects)) { - sgen_hash_table_replace (hash_table, sgen_pointer_queue_pop (&moved_fin_objects), NULL, NULL); - } - - sgen_pointer_queue_free (&moved_fin_objects); } /* LOCKING: requires that the GC lock is held */ diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 041d4faa87d..0fa76130411 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -437,7 +437,6 @@ enum { INTERNAL_MEM_TOGGLEREF_DATA, INTERNAL_MEM_CARDTABLE_MOD_UNION, INTERNAL_MEM_BINARY_PROTOCOL, - INTERNAL_MEM_TEMPORARY, INTERNAL_MEM_MAX }; diff --git a/mono/metadata/sgen-internal.c b/mono/metadata/sgen-internal.c index f5b8995355f..333f8c3ee41 100644 --- a/mono/metadata/sgen-internal.c +++ b/mono/metadata/sgen-internal.c @@ -150,7 +150,6 @@ description_for_type (int type) case INTERNAL_MEM_TOGGLEREF_DATA: return "toggleref-data"; case INTERNAL_MEM_CARDTABLE_MOD_UNION: return "cardtable-mod-union"; case INTERNAL_MEM_BINARY_PROTOCOL: return "binary-protocol"; - case INTERNAL_MEM_TEMPORARY: return "temporary"; default: g_assert_not_reached (); } diff --git a/mono/metadata/sgen-pinning.c b/mono/metadata/sgen-pinning.c index 9c8c819a097..c895d7471ea 100644 --- a/mono/metadata/sgen-pinning.c +++ b/mono/metadata/sgen-pinning.c @@ -37,7 +37,6 @@ void sgen_init_pinning (void) { memset (pin_hash_filter, 0, sizeof (pin_hash_filter)); - pin_queue.mem_type = INTERNAL_MEM_PIN_QUEUE; } void diff --git a/mono/metadata/sgen-pointer-queue.c b/mono/metadata/sgen-pointer-queue.c index 7ace7dfa4b6..3c1d8fb6c61 100644 --- a/mono/metadata/sgen-pointer-queue.c +++ b/mono/metadata/sgen-pointer-queue.c @@ -28,23 +28,13 @@ sgen_pointer_queue_clear (SgenPointerQueue *queue) queue->next_slot = 0; } -void -sgen_pointer_queue_init (SgenPointerQueue *queue, int mem_type) -{ - queue->next_slot = 0; - queue->size = 0; - queue->data = NULL; - queue->mem_type = mem_type; -} - static void realloc_queue (SgenPointerQueue *queue) { size_t new_size = queue->size ? queue->size + queue->size/2 : 1024; - void **new_data = sgen_alloc_internal_dynamic (sizeof (void*) * new_size, queue->mem_type, TRUE); - + void **new_data = sgen_alloc_internal_dynamic (sizeof (void*) * new_size, INTERNAL_MEM_PIN_QUEUE, TRUE); memcpy (new_data, queue->data, sizeof (void*) * queue->next_slot); - sgen_free_internal_dynamic (queue->data, sizeof (void*) * queue->size, queue->mem_type); + sgen_free_internal_dynamic (queue->data, sizeof (void*) * queue->size, INTERNAL_MEM_PIN_QUEUE); queue->data = new_data; queue->size = new_size; SGEN_LOG (4, "Reallocated pointer queue to size: %lu", new_size); @@ -59,14 +49,6 @@ sgen_pointer_queue_add (SgenPointerQueue *queue, void *ptr) queue->data [queue->next_slot++] = ptr; } -void* -sgen_pointer_queue_pop (SgenPointerQueue *queue) -{ - g_assert (queue->next_slot); - - return queue->data [--queue->next_slot]; -} - size_t sgen_pointer_queue_search (SgenPointerQueue *queue, void *addr) { @@ -138,16 +120,4 @@ sgen_pointer_queue_find (SgenPointerQueue *queue, void *ptr) return (size_t)-1; } -gboolean -sgen_pointer_queue_is_empty (SgenPointerQueue *queue) -{ - return !queue->next_slot; -} - -void -sgen_pointer_queue_free (SgenPointerQueue *queue) -{ - sgen_free_internal_dynamic (queue->data, sizeof (void*) * queue->size, queue->mem_type); -} - #endif diff --git a/mono/metadata/sgen-pointer-queue.h b/mono/metadata/sgen-pointer-queue.h index 0bbeedfdd67..d972f3cc92e 100644 --- a/mono/metadata/sgen-pointer-queue.h +++ b/mono/metadata/sgen-pointer-queue.h @@ -20,13 +20,10 @@ #ifndef __MONO_SGEN_POINTER_QUEUE_H__ #define __MONO_SGEN_POINTER_QUEUE_H__ -#include - typedef struct { void **data; size_t size; size_t next_slot; - int mem_type; } SgenPointerQueue; void sgen_pointer_queue_add (SgenPointerQueue *queue, void *ptr) MONO_INTERNAL; @@ -35,9 +32,5 @@ void sgen_pointer_queue_remove_nulls (SgenPointerQueue *queue) MONO_INTERNAL; void sgen_pointer_queue_sort_uniq (SgenPointerQueue *queue) MONO_INTERNAL; size_t sgen_pointer_queue_search (SgenPointerQueue *queue, void *addr) MONO_INTERNAL; size_t sgen_pointer_queue_find (SgenPointerQueue *queue, void *ptr) MONO_INTERNAL; -void sgen_pointer_queue_init (SgenPointerQueue *queue, int mem_type) MONO_INTERNAL; -void* sgen_pointer_queue_pop (SgenPointerQueue *queue) MONO_INTERNAL; -gboolean sgen_pointer_queue_is_empty (SgenPointerQueue *queue) MONO_INTERNAL; -void sgen_pointer_queue_free (SgenPointerQueue *queue) MONO_INTERNAL; #endif diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index b88819883d0..97d22706db0 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1779,14 +1779,6 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) if (!sofile) { mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module '%s' not found: %s\n", aot_name, err); g_free (err); - - aot_name = g_strdup_printf ("%s/mono/aot-cache/%s/%s%s", mono_assembly_getrootdir(), ARCHITECTURE, basename (assembly->image->name), SHARED_EXT); - sofile = mono_dl_open (aot_name, MONO_DL_LAZY, &err); - if (!sofile) { - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module '%s' not found: %s\n", aot_name, err); - g_free (err); - } - } } } diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 757c5f265e0..a0865b7e2b6 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -552,7 +552,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, guint8 *cfa; guint32 unwind_info_len; guint8 *unwind_info; - guint8 *epilog; + guint8 *epilog = NULL; frame->type = FRAME_TYPE_MANAGED; @@ -565,7 +565,9 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, printf ("%s %p %p\n", ji->d.method->name, ji->code_start, ip); mono_print_unwind_info (unwind_info, unwind_info_len); */ - epilog = (guint8*)ji->code_start + ji->code_size - mono_jinfo_get_epilog_size (ji); + /* LLVM compiled code doesn't have this info */ + if (ji->has_arch_eh_info) + epilog = (guint8*)ji->code_start + ji->code_size - mono_jinfo_get_epilog_size (ji); regs [AMD64_RAX] = new_ctx->rax; regs [AMD64_RBX] = new_ctx->rbx; @@ -583,7 +585,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, (guint8*)ji->code_start + ji->code_size, - ip, &epilog, regs, MONO_MAX_IREGS + 1, + ip, epilog ? &epilog : NULL, regs, MONO_MAX_IREGS + 1, save_locations, MONO_MAX_IREGS, &cfa); new_ctx->rax = regs [AMD64_RAX]; @@ -606,12 +608,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, /* Adjust IP */ new_ctx->rip --; -#ifndef MONO_AMD64_NO_PUSHES - /* Pop arguments off the stack */ - if (ji->has_arch_eh_info) - new_ctx->rsp += mono_jit_info_get_arch_eh_info (ji)->stack_size; -#endif - return TRUE; } else if (*lmf) { guint64 rip; diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index cd8eedfa1a6..a809de49e05 100755 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -1986,10 +1986,6 @@ mono_arch_create_vars (MonoCompile *cfg) cfg->lmf_ir_mono_lmf = TRUE; #endif } - -#ifndef HOST_WIN32 - cfg->arch_eh_jit_info = 1; -#endif } static void diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 9d9f09dde14..6268cadb4f0 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -401,8 +401,7 @@ BASE_TEST_CS_SRC= \ unload-appdomain-on-shutdown.cs \ block_guard_restore_aligment_on_exit.cs \ thread_static_gc_layout.cs \ - sleep.cs \ - bug-17537.cs + sleep.cs TEST_CS_SRC_DIST= \ $(BASE_TEST_CS_SRC) \ @@ -1189,14 +1188,6 @@ bug-382986-lib.dll: bug-382986-lib.cs bug-382986.exe: bug-382986.cs bug-382986-lib.dll $(MCS) -out:$@ -r:bug-382986-lib.dll $(srcdir)/bug-382986.cs -EXTRA_DIST += bug-17537-helper.cs -bug-17537-helper.exe: bug-17537-helper.cs - $(MCS) -out:$@ $(srcdir)/bug-17537-helper.cs - chmod -x $@ - -bug-17537.exe: bug-17537.cs bug-17537-helper.exe - $(MCS) -out:$@ $(srcdir)/bug-17537.cs - EXTRA_DIST += coreclr-security.cs coreclr-security.exe : coreclr-security.cs From a8b08d3b885790b725d69d65c5d0a58e2878d868 Mon Sep 17 00:00:00 2001 From: SushiHangover Date: Wed, 2 Sep 2015 22:30:48 -0700 Subject: [PATCH 543/543] Upstream regression on test-903.cs, created Issue #81 to track --- mcs/tests/known-issues-net_4_5 | 4 ++++ mcs/tests/test-903.cs | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mcs/tests/known-issues-net_4_5 b/mcs/tests/known-issues-net_4_5 index 5f738216208..8e195f0d543 100644 --- a/mcs/tests/known-issues-net_4_5 +++ b/mcs/tests/known-issues-net_4_5 @@ -8,3 +8,7 @@ gtest-230.cs # IL Regresssion. gtest-409.cs IGNORE + +# +test-903.cs + diff --git a/mcs/tests/test-903.cs b/mcs/tests/test-903.cs index 7dedb674daf..9da077d6f91 100644 --- a/mcs/tests/test-903.cs +++ b/mcs/tests/test-903.cs @@ -11,6 +11,7 @@ class C public static implicit operator S (C c) { ++ConversionCalled; +Console.WriteLine("ConversionCalled"); return new S (); } } @@ -38,4 +39,4 @@ static int Main () return 0; } -} \ No newline at end of file +}