Mono 4.0.0 Release Notes

Release date: 29 Apr 2015


  • Adoption of Microsoft’s open source code
  • C# 6.0
  • Floating point optimizations
  • We dropped support for the 2.0, 3.5 and 4.0 assemblies
  • Updated IKVM
  • Lighter Debugger overhead
  • Basic PowerPC64 LE support

Floating Point Optimizations

Mono has historically chosen to use the highest possible precision for all floating point operations. This means that both 64-bit math and 32-bit math were done with the highest precision available.

But performance sensitive code that might not need high precision was negatively impacted.

With this release we are introducing support for performing 32-bit floating operations using 32-bit math. This produces faster code at the expense of fidelity. This mode of operation can be enabled with the -O=float32 option.

With a sample Mandelbrot generator program, on x86-64 these are the results:

  ARM32 x86-64
Original 1m56 17.2
Original/LLVM   10.3
Float32 1m12 12.2
Float32/LLVM   8.8

This option currently needs to be enabled manually, it is not part of the -O=all options.


Mono’s C# compiler now defaults to C# 6.0

The compiler will now avoid generating a GUID each time it builds, generating identical builds across recompilations. Following the steps of Roslyn’s new default.

Microsoft Source Code Adoption

This is the first release of Mono that replaces various components of Mono with code that was released by Microsoft under the MIT license in one of three places:

  • Microsoft’s ReferenceSource drop
  • Microsoft’s CoreFX
  • Microsoft’s CoreCLR

While Microsoft is working towards .NET Core: a redistributable and re-imagined version of .NET, the project remains a work in progress. Mono at this point continues to provide an API that tracks the .NET desktop/server version.

This means that most of the code that we have integrated comes from the ReferenceSource drop. In the future, we will deliver a “Mono Core” along the same lines of .NET Core to allow the use of the Mono runtime with the new library distribution system that is being developed with CoreFX.

In this release, we have ported components that were either incomplete or buggy in Mono and were relatively easy to port to Mono. There is much more to be done in this area. If you are interested in tracking those efforts, check the project status:

Mono ships now with a subset of the referencesource that have been adjusted to work with Mono’s class libraries or have been updated to be cross platform.


We have replaced Mono’s System.Decimal implementation with Microsoft’s version. This fixed a couple of formatting bugs. While Mono’s code did not have any major bugs, Microsoft’s implementation is more efficient and is actively maintained. Fixing bugs in System.Decimal was always difficult.

Assorted Microsoft Classes Imported

These are some highlights of code imported from Microsoft (smaller bits like attributes, enumerations, event arguments, exceptions or other simple bits are not shown):

The following namespaces have been entirely, or almost entirely replaced with ReferenceSource code:

  • System.Collections
  • System.Collections.Concurrent
  • System.Collections.Generic
  • System.Collections.Specialized
  • System.ComponentModel
  • System.ComponentModel.Design
  • System.Diagnostic.Contracts
  • System.Linq
  • System.Linq.Parallel
  • System.Text.RegularExpressions
  • System.Runtime.CompilerServices
  • System.Threading.Tasks

Partial changes:

  • System:
    • ArraySegment
    • BitConverter
    • Boolean, Byte, Char, Decimal, Int16, Int32, Int64, SByte, UInt16, UInt32, UInt64,
    • Convert
    • DateTime, Decimal
    • Guid
    • Lazy
    • Random
    • TimeSpan
    • Version
  • System.Collections.Generic
    • HashSet
    • Mostly replaced
  • System.Diagnostics.Contracts
  • System.Globalization
    • Entire calendar stack
    • DaylightTime
    • TextInfo (replaces text categorization tables, replaces it with .NET which is half the size)
  • System.IO
    • BufferedStream
    • Stream
    • MemoryStream
    • StreamReader, StreamWriter, StringReader, StringWriter, TextReader, TextWriter
  • System.Linq.Expressions
    • DynamicExpression, ExpressionVisitor
  • System.Net
    • Cookie, CookieCollection, CookieContainer,
    • FtpWebRequest
    • WebClient
  • System.Text
    • Bring the non-code page encoders
  • System.Threading (about 60% replaced)

Also the System.Numerics has been updated to use ReferenceSource (it used an older Microsoft open sourced version of the library in the past)

Garbage Collector

The Xamarin performance team has been fine tuning Mono’s SGen garbage collector.

Dropped Support for Old Frameworks

Reference Assemblies

We no longer build the reference assemblies for the .NET 2.0, .NET 3.5 or .NET 4.0 APIs, we now ship binaries of the reference assemblies (API contracts, without any actual executable code in them).

Mono will now only build the .NET 4.5 assemblies as well as the mobile-based profiles.

Note: You can still run assemblies compiled for earlier .NET profiles on Mono, there’s no need to recompile them (they’ll just run on the .NET 4.5 assemblies instead).


Mono no longer distributes the Npgsql driver. Developers that need it will be better served by using the actively maintained Npgsql driver from this site:


The version of EntityFramework that we shipped had not been updated in a long time, and users are currently getting EntityFramework with NuGet.

Other Features

  • Added LLDB scripts to assist developers debugging the runtime with LLDB
  • MonoIO method and classes now uses SafeHandles
  • System.Net.NetworkInformation implements more features on more platforms

Fine tuning

We now inline copies of structures up to eight machine words, up from the previous five. Values larger than that still call memcpy to complete the operation.

We now support returning floating point structures by value and can better pack floating point structures.

LLVM is now given more lattitude to inline generated code.

More methods can be compiled with LLVM on ARM. This helps many methods that passed large structures as parameters.

All atomic methods in the framework are now recognized by the JIT as intrinsics and are inlined as specialized code on platforms that support it. This includes all methods on Interlocked and Volatile, as well as the MemoryBarrier, VolatileRead, and VolatileWrite methods on Thread.

On x86-64, Thread.MemoryBarrier is now implemented with mfence instead of lock add rsp, 0. Also, Interlocked.Exchange is now implemented with xchg [dst], val instead of the overly expensive lock cmpxchg [dst], val loop we previously emitted.

For atomic methods with acquire/release semantics, we now emit memory barriers with those semantics instead of the overly strong sequentially consistent kind.

The Enum.HasFlag method is now significantly faster for the most typical usage pattern, which is a.HasFlag (b) where a and b are the exact same type. We transform such calls to an actual bitwise AND and skip all the heavy reflection normally done in the method. This is about 60x faster than before. Additionally, the regular implementation of the method which is only used for rare/pathological cases is now 4x faster than before.

The JIT now avoids emitting pointless move opcodes when the destination register is the same as the source register.

The runtime now supports performing calls directly to some internal calls (those that are known not to raise exceptions). This eliminates the overheads of wrapper methods, both a performance and memory usage benefit.

When precompiling your assemblies, you can use the “direct-calls” option to enable this feature.

monop tool

The monop tool now uses IKVM.Reflection to load assemblies, so it will work with foreign mscorlibs. In addition the -xi and -xa flags can be used to search types in the Xamarin.Android and Xamarin.iOS frameworks.

musl libc

There is now rudimentary support for building Mono with the musl libc on Linux. To do this, pass --disable-boehm --without-sigaltstack to configure.

Mac Changes

System.Net now supports Mac’s .pac proxy configurations.

C99 switch

The runtime now requires a compiler with C99 support. For Windows users, this means that Visual Studio 2013 is now required to build Mono. Cygwin or MinGW users should not be affected by this change. Similarly, compilers on most Unix platforms have supported C99 for a long time.

Bug Fixes

  • 14277: Stepping in static constructor exits
  • 17944: mono: mini-amd64.c:492: amd64_patch: Assertion `0’ failed.
  • 18800: IndexOutOfRangeException when MultipartFormDataContent filename value contains whitespace
  • 19334: BeginWrite failure at System.Net.Sockets.NetworkStream.BeginWrite
  • 19823: InvalidOperationException in ServicePoint.RemoveConnectionGroup
  • 19881: ProductInfoHeaderValue fails to parse User-Agent string without version
  • 20764: WebMessageFormatter crashes with void return type OperationContract
  • 21072: DataContractSerializer does not serialize enum flags the same as .net 4
  • 21172: text field type nvarchar(max) is truncated to 4000 chars
  • 22501: XmlSchema.Read raises InvalidElementError for certain inputs which work fine in MS.NET
  • 23242: Null reference exception occurs after the call to Int.ToString() from multiple threads
  • 23401: Sgen’s marksweep-conc fails under load test
  • 23771: UTF8 Decoder’s Convert does not keep internal state between calls when ‘flush’ parameter is false
  • 23808: HMACSHA256 default ctor creates 64-bit key, expected 64-byte
  • 23966: HttpClient.GetStreamAsync behaves differently from .Net
  • 23981: Some [Assembly*] attributes are not “compiled” correctly in the PE files
  • 23987: Unable to debug on Lollipop
  • 24084: sgen assert in sgen_obj_get_descriptor () when frequently allocating with FormatterServices.GetUninitializedObject()
  • 24086: Runtime test - TestDaylightSavingsTime failed for Casablanca (Western European Standard Time)
  • 24172: C# Invalid code generation with nested types in namespace
  • 24221: Sorting of large structs with wrong result.
  • 24300: Bad Xml produced by XmlSerializer writing on XDocument
  • 24342: Debugger race condition
  • 24419: Synchronized static methods of generic classes lock on the open type instead of the closed one
  • 24431: CultureInfo constructor error message decimal and hex lcid should be different
  • 24452: yield statement used in foreach returns first record only
  • 24511: mcs hangs during compile
  • 24537: mcs ignores missing bracket
  • 24577: Fatal Unhandled Exсeption: System.FormatException
  • 24588: __clear_cache in mini-arm.c not supported in gcc toolchain
  • 24638: Crash occurs when passing an array of objects to a COM method
  • 24675: Mono C# parser encounters a CS0584 internal compiler error when loading a constant from a legal dll
  • 24704: System.Net.Http.HttpClient PostAsync ignores timeout if webproxy isn’t accessible
  • 24720: Crash when freeing COM callable wrappers
  • 24757: LogicalCallContext not flowing with async calls
  • 24775: List.ForEach does not throw InvalidOperationException when collection was modified
  • 24784: Multiplication when passing optional parameter is now failing to compile
  • 24785: System.Net.Http, need to escape more RFC characters
  • 24935: Dynamic property is case sensitive
  • 25009: Mono crash when stopping a debug session
  • 25050: DST transition bug
  • 25059: StructLayout.Pack <= 16 throws TypeLoadException at runtime
  • 25086: Embed assemblies in native code option causing sample build failures on windows
  • 25087: System.Uri constructor throws an exception when parsing an HTTP URI with a username or password that contains certain escaped characters
  • 25095: Struct w/nested structs as return value from P/Invoke is incorrectly marshalled on x86_64/OSX
  • 25106: Microsoft.Win32.Registry.GetValue() requires write permission on Windows
  • 25107: Compiled method names differ between 32 and 64 bit builds
  • 25132: SafeHandle always called with Disposed(true)
  • 25165: Bad code and async/await in a Task causes “Internal compiler error”
  • 25213: HttpClient.SendAsync throws out of memory exception on large files
  • 25224: stack overflow after printfn something
  • 25357: .mdb has invalid scopes
  • 25358: Invalid mdb scopes for variables
  • 25498: System.IO.SynchronizedStream does not call Close on wrapped Stream
  • 25544: Documentation on method with co/contravariant parameters raises CS1569: Error generating XML documentation
  • 25629: nunit-console leaves zombie processes in mono 3.12 vs proper behavior in prior versions (3.10)
  • 25631: Mono throws OutOfMemoryException on Ubuntu but not OSX or Windows
  • 25646: Microsoft_FSharp_Core_LanguagePrimitives_HashCompare_GenericCompare causes assertion
  • 25664: FieldInfo.GetValue causes segmentation fault when field is of pointer type
  • 25679: Memory leak and buffer overflow in get_gsharedvt_type()
  • 25690: * Assertion: should not be reached at icall.c:1902
  • 25720: Runtime crashing when evaluating System.Diagnostics.Process.HasExited property
  • 25798: LessThanOrEqual wrong result for nuint type on 32bit platform
  • 25808: DataContractJsonSerializer cannot deserialize array to IEnumerable<T>
  • 25821: Generic symbol names exported from libmono
  • 25850: SafeHandle.Close() is not idempotent.
  • 25891: Custom marshaler broken in 8.6
  • 25895: Wrong exception is thrown when calling System.Globalization.CharUnicodeInfo.GetNumericValue(string s, int index) with invalid index
  • 25928: Barrier constructed with 0 participants will hang on AddParticipant
  • 26008: Wrong DST when TimeZoneInfo has floating date rules.
  • 26033: Set next statement(CMD_THREAD_SET_IP) + stepping doesn’t work as expected
  • 26109: System.Net.Http.Headers.RangeHeaderValue fails to parse with large byte range
  • 26219: Result of cast from double to int is different on Mono amd64 than on .NET and Mono x86
  • 26346: Full AOT crash: Instructions.cpp:281: void llvm::CallInst::init(llvm::Value *, ArrayRef<llvm::Value *>;, const llvm::Twine &):
  • 26384: Assembly.GetType() fails to parse type names containing commas
  • 26412: ConstructorInfo.ContainsGenericParameters behaves differently to MS.NET
  • 26436: .mdb generated on Windows and used on *nix fails on some sdb commands
  • 26688: RFE: Update valgrind headers
  • 26736: C# async lambda with nested lambda and “goto” statement causes compiler to crash.
  • 26753: Project compiles in Visual Studio but not in Xamarin Studio.
  • 26840: InternalErrorException on specifying Optional attribute
  • 26842: Support reproducible builds
  • 26892: mcs generates CS0254 error for cast in fixed statement
  • 27001: Using alias not in scope for nested class inheritence
  • 27020: Compiling class with “fixed” member against System.Runtime.dll contract fails with StructLayoutAttribute not accessible
  • 27036: Adding the user-agent header to HttpClient object throws a System.FormatException: Invalid format.
  • 27086: Writing in asynchronous FileStream adds 0 bytes at the beginning of the file
  • 27352: HttpRequestMessage: adding Accept header with multiple values fails
  • 27386: HttpClient doesn’t honor BaseAddress with the Get*Async methods
  • 27525: C#6 interpolated string raises NotImplementedException: CloneTo during compilation
  • 27533: C#6 interpolated string raises Internal compiler error during parsingSystem during compilation
  • 27597: csharp REPL on Windows doesn’t accept any input
  • 27697: Debugger crash: error: * Assertion at ../../../../../mono/mono/mini/debugger-agent.c:2475, condition `tls’ not met
  • 28098: After running a mono process the shell no longer shows input chars
  • 28172: 3.12.1.
  • 28196: FlowAnalysis issue with out parameter and finally and delegate containing a return
  • 28211: Getting “error MT3001: Could not AOT the assembly” When Building for Device
  • 28213: Xamarin Studio on OSX fails to compile where Visual Studio 2013 succeeds
  • 28292: Internal compiler error when an interpolated string is too long
  • 28293: Unexpected symbol error when two interpolated strings are used with the ternary operator
  • 28383: Marshal.AllocCoTaskMem(0) incorrectly returns null


  • Fixed some cases where some runtime-internal memory barriers would not actually be emitted because the barrier kind field was being set to nonsensical values. Note: This did not affect Thread.MemoryBarrier.
  • Fixed memory ordering of Interlocked.CompareExchange to be sequentially consistent instead of combined acquire/release when using LLVM.
  • Fixed some atomic intrinsics not getting a stack type set, leading to issues in the method-to-ir code generation pass.
  • Fixed marshalling bug when invoking differently typed delegates obtained through Marshal.GetDelegateForFunctionPointer with the same native function pointer.
  • Dropped old Mono JIT conventions for saving registers on function entry.
  • Optimized allocation of small objects (1% speed improvement to Roslyn compiling our mscorlib)


Bill Seurer, Michael Matz, Aetf, Alex J Lennon, Alex Rønne Petersen, Alex Soto, Alexander Kyte, Alexander Köplinger, Alexis Christoforides, Alistair Bush, Alistair Leslie-Hughes, Atsushi Eno, Ben Woods, Bill Seurer, Brendan Zagaeski, Chris Hubbard, Craig Minihan, Crisdut, Damien Daspit, Dave Curylo, David Karlaš, David Karlaš, Eberhard Beilharz, Etienne CHAMPETIER, Fritz Elfert, Guillaume Turri, Henrik Feldt, Jb Evain, Jeffrey Stedfast, Jim Westfall, Jo Shields, Joao Matos, João Matos, Jon Purdy, Jonathan Pryor, Jonathon Rossi, João Matos, Kai Ruhnau, Kenneth Pouncey, Leonid Shalupov, Liam McSherry, Lluis Sanchez, Ludovic Henry, Marc-Andre Ferland, Marcos Henrich, Marek Habersack, Marek Safar, Marius Ungureanu, Mark Probst, MarkS, Martin Baulig, Martin Thwaites, Mauricio Faria de Oliveira, Michael Matz, Miguel de Icaza, Mike Morano, Mirco Bauer, Neale Ferguson, Paolo Molaro, Radek Doulik, Reuben Bond, RiJo, Robin Neatherway, Rodrigo Kumpera, Rolf Bjarne Kvinge, Ryan J. Melena, Ryan Melena, Sebastien Pouliot, Sergey Odinokov, Stephen McConnel, Stone Gislason, Thomas Petazzoni, Ungureanu Marius, Vincent Povirk, Vlad Brezae, Vladimir Kargov, Zoltan Varga, fquiroz01, irodriguez, zevane.