Merge pull request #1326 from BrzVlad/master
authorMark Probst <mark.probst@gmail.com>
Thu, 9 Oct 2014 18:43:03 +0000 (11:43 -0700)
committerMark Probst <mark.probst@gmail.com>
Thu, 9 Oct 2014 18:43:03 +0000 (11:43 -0700)
[sgen] Fix pointer access.

229 files changed:
CONTRIBUTING.md
configure.ac
man/mono.1
mcs/class/Facades/System.Runtime.InteropServices/TypeForwarders.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Button.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Theme.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.Engine-net_4_5.csproj
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/InvokeOptions.cs
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs
mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
mcs/class/Mono.Debugger.Soft/Test/dtest.cs
mcs/class/Mono.Security/Mono.Security.Cryptography/KeyPairPersistence.cs
mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs
mcs/class/System.Core/System/TimeZoneInfo.Android.cs
mcs/class/System.Data/System.Data-net_4_5.csproj
mcs/class/System.Data/mobile_System.Data.dll.sources
mcs/class/System.IdentityModel/System.IdentityModel.Tokens/BootstrapContext.cs [new file with mode: 0644]
mcs/class/System.IdentityModel/System.IdentityModel.dll.sources
mcs/class/System.IdentityModel/System.IdentityModel_test.dll.sources
mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs [new file with mode: 0644]
mcs/class/System.Management/System.Management/ManagementObjectSearcher.cs
mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs
mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs
mcs/class/System.ServiceModel.Web/System.ServiceModel.Syndication/Rss20ItemFormatter.cs
mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs
mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/JsonReaderTest.cs
mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Syndication/Rss20ItemFormatterTest.cs
mcs/class/System.Web/System.Web.Security/MembershipUser.cs
mcs/class/System.Web/System.Web/HttpUtility.cs
mcs/class/System.Web/Test/System.Web/HttpUtilityTest.cs
mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs
mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs
mcs/class/System.XML/System.Xml/XmlTextReader.cs
mcs/class/System.XML/System.Xml/XmlTextReader2.cs
mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs
mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs
mcs/class/System.Xml.Linq/System.Xml.Linq/XComment.cs
mcs/class/System.Xml.Linq/System.Xml.Linq_test.dll.sources
mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XCommentTest.cs [new file with mode: 0644]
mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs
mcs/class/System/System.Diagnostics/LocalFileEventLog.cs
mcs/class/System/System.Diagnostics/Process.cs
mcs/class/System/System.Diagnostics/Win32EventLog.cs
mcs/class/System/System.IO/DefaultWatcher.cs
mcs/class/System/System.Net/MacProxy.cs
mcs/class/System/System/UriParseComponents.cs
mcs/class/System/Test/System.CodeDom.Compiler/CodeDomProviderCas.cs
mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs
mcs/class/System/Test/System.ComponentModel.Design.Serialization/InstanceDescriptorTest.cs
mcs/class/System/Test/System.ComponentModel/CharConverterTest.cs
mcs/class/System/Test/System.ComponentModel/ContainerTest.cs
mcs/class/System/Test/System.Diagnostics/ProcessTest.cs
mcs/class/System/Test/System.Net.Sockets/TcpClientCas.cs
mcs/class/System/Test/System.Net.Sockets/UdpClientTest.cs
mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs
mcs/class/System/Test/System.Net/DnsCas.cs
mcs/class/System/Test/System.Net/HttpListenerTest.cs
mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X500DistinguishedNameTest.cs
mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X509ChainTest.cs
mcs/class/System/Test/System.Text.RegularExpressions/RegexReplaceTests.cs
mcs/class/System/Test/System.Text.RegularExpressions/RegexResultTests.cs
mcs/class/System/Test/System/UriParserTest.cs
mcs/class/System/Test/System/UriTest.cs
mcs/class/corlib/System.Security.Cryptography/HMAC.cs
mcs/class/corlib/System.Text/UTF8Encoding.cs
mcs/class/corlib/System.Text/UnicodeEncoding.cs
mcs/class/corlib/System.Threading.Tasks/Task.cs
mcs/class/corlib/System.Threading.Tasks/TaskContinuation.cs
mcs/class/corlib/System/AppDomain.cs
mcs/class/corlib/System/Environment.cs
mcs/class/corlib/System/FirstChanceExceptionEventArgs.cs [new file with mode: 0644]
mcs/class/corlib/System/String.cs
mcs/class/corlib/System/TimeSpan.cs
mcs/class/corlib/Test/System.Reflection.Emit/DynamicMethodTest.cs
mcs/class/corlib/Test/System.Reflection.Emit/GenericTypeParameterBuilderTest.cs
mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs
mcs/class/corlib/Test/System.Reflection/AssemblyNameCas.cs
mcs/class/corlib/Test/System.Reflection/FieldInfoTest.cs
mcs/class/corlib/Test/System.Reflection/MethodInfoTest.cs
mcs/class/corlib/Test/System.Reflection/MonoGenericClassTest.cs
mcs/class/corlib/Test/System.Reflection/ReflectedTypeTest.cs
mcs/class/corlib/Test/System.Runtime.CompilerServices/ConditionalWeakTableTest.cs
mcs/class/corlib/Test/System.Runtime.CompilerServices/RuntimeHelpersTest.cs
mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs
mcs/class/corlib/Test/System.Runtime.InteropServices/GCHandleTest.cs
mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs
mcs/class/corlib/Test/System.Runtime.Serialization/SerializationTest.cs
mcs/class/corlib/Test/System.Security.Cryptography/CryptoStreamTest.cs
mcs/class/corlib/Test/System.Security.Cryptography/HMACSHA384Test.cs
mcs/class/corlib/Test/System.Security.Cryptography/HMACSHA512Test.cs
mcs/class/corlib/Test/System.Security.Permissions/RegistryPermissionTest.cs
mcs/class/corlib/Test/System.Security.Permissions/UrlIdentityPermissionTest.cs
mcs/class/corlib/Test/System.Text/UnicodeEncodingTest.cs
mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs
mcs/class/corlib/Test/System.Threading/ThreadTest.cs
mcs/class/corlib/Test/System/AppDomainTest.cs
mcs/class/corlib/Test/System/SByteTest.cs
mcs/class/corlib/Test/System/TimeSpanTest.cs
mcs/class/corlib/Test/System/TypeTest.cs
mcs/class/corlib/corlib-net_4_5.csproj
mcs/class/corlib/corlib.dll.sources
mcs/errors/cs0023-25.cs [new file with mode: 0644]
mcs/errors/cs0429-5.cs [deleted file]
mcs/errors/cs0573-2.cs [new file with mode: 0644]
mcs/errors/cs0573.cs [new file with mode: 0644]
mcs/errors/cs1644-46.cs [deleted file]
mcs/errors/cs1736-2.cs [new file with mode: 0644]
mcs/mcs/class.cs
mcs/mcs/codegen.cs
mcs/mcs/cs-tokenizer.cs
mcs/mcs/ecore.cs
mcs/mcs/expression.cs
mcs/mcs/nullable.cs
mcs/mcs/parameter.cs
mcs/mcs/statement.cs
mcs/tests/gtest-409.cs
mcs/tests/gtest-625.cs [new file with mode: 0644]
mcs/tests/gtest-autoproperty-09.cs
mcs/tests/gtest-autoproperty-10.cs
mcs/tests/test-898.cs [deleted file]
mcs/tests/test-903.cs
mcs/tests/test-906.cs
mcs/tests/test-907.cs [new file with mode: 0644]
mcs/tests/test-null-operator-010.cs [new file with mode: 0644]
mcs/tests/test-primary-ctor-01.cs
mcs/tests/test-primary-ctor-07.cs
mcs/tests/ver-il-net_4_5.xml
mcs/tools/corcompare/mono-api-html/ApiDiff.cs
mcs/tools/corcompare/mono-api-html/ClassComparer.cs
mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs
mcs/tools/corcompare/mono-api-info.cs
mcs/tools/mdoc/Makefile
mcs/tools/mdoc/Mono.Documentation/monodocer.cs
mcs/tools/mdoc/Test/DocTest-InternalInterface.cs [new file with mode: 0644]
mcs/tools/mdoc/Test/en.expected-internal-interface/MyNamespace/MyClass.xml [new file with mode: 0644]
mcs/tools/mdoc/Test/en.expected-internal-interface/index.xml [new file with mode: 0644]
mcs/tools/mdoc/Test/en.expected-internal-interface/ns-MyNamespace.xml [new file with mode: 0644]
mono/io-layer/processes.c
mono/io-layer/processes.h
mono/metadata/Makefile.am
mono/metadata/boehm-gc.c
mono/metadata/class-internals.h
mono/metadata/class.c
mono/metadata/domain-internals.h
mono/metadata/domain.c
mono/metadata/gc-internal.h
mono/metadata/gc.c
mono/metadata/icall-def.h
mono/metadata/jit-info.c [new file with mode: 0644]
mono/metadata/metadata-internals.h
mono/metadata/mono-config.c
mono/metadata/mono-wsq.c
mono/metadata/mono-wsq.h
mono/metadata/object.c
mono/metadata/process.c
mono/metadata/security.c
mono/metadata/sgen-alloc.c
mono/metadata/sgen-archdep.h
mono/metadata/sgen-cardtable.c
mono/metadata/sgen-conf.h
mono/metadata/sgen-copy-object.h
mono/metadata/sgen-debug.c
mono/metadata/sgen-descriptor.c
mono/metadata/sgen-descriptor.h
mono/metadata/sgen-gc.c
mono/metadata/sgen-gc.h
mono/metadata/sgen-gray.c
mono/metadata/sgen-gray.h
mono/metadata/sgen-major-scan-object.h
mono/metadata/sgen-marksweep-fixed-par.c [deleted file]
mono/metadata/sgen-marksweep-fixed.c [deleted file]
mono/metadata/sgen-marksweep-par.c [deleted file]
mono/metadata/sgen-marksweep.c
mono/metadata/sgen-minor-copy-object.h
mono/metadata/sgen-minor-scan-object.h
mono/metadata/sgen-new-bridge.c
mono/metadata/sgen-nursery-allocator.c
mono/metadata/sgen-old-bridge.c
mono/metadata/sgen-os-posix.c
mono/metadata/sgen-pinning.c
mono/metadata/sgen-pinning.h
mono/metadata/sgen-pointer-queue.c
mono/metadata/sgen-pointer-queue.h
mono/metadata/sgen-scan-object.h
mono/metadata/sgen-simple-nursery.c
mono/metadata/sgen-split-nursery.c
mono/metadata/sgen-tagged-pointer.h [new file with mode: 0644]
mono/metadata/sgen-tarjan-bridge.c
mono/metadata/sgen-workers.c
mono/metadata/sgen-workers.h
mono/metadata/string-icalls.c
mono/metadata/string-icalls.h
mono/metadata/threadpool.c
mono/metadata/threads-types.h
mono/metadata/threads.c
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/cpu-arm.md
mono/mini/debugger-agent.c
mono/mini/exceptions-amd64.c
mono/mini/exceptions-x86.c
mono/mini/generics.cs
mono/mini/method-to-ir.c
mono/mini/mini-amd64.c
mono/mini/mini-amd64.h
mono/mini/mini-arm.c
mono/mini/mini-arm.h
mono/mini/mini-exceptions.c
mono/mini/mini-ia64.h
mono/mini/mini-mips.h
mono/mini/mini-ppc.h
mono/mini/mini-s390x.h
mono/mini/mini-sparc.h
mono/mini/mini-trampolines.c
mono/mini/mini-x86.c
mono/mini/mini-x86.h
mono/mini/mini.c
mono/mini/mini.h
mono/mini/tramp-arm.c
mono/tests/Makefile.am
mono/tests/test-runner.cs
mono/utils/mono-compiler.h
mono/utils/mono-context.h
mono/utils/mono-proclib.c
mono/utils/mono-threads.c
scripts/.gitignore
winconfig.h

index c56d15a99a006239e87eda8edb4bbd51323d59df..a04886ff4b0d0317bc1a2caa6d093c101ec5c83f 100644 (file)
@@ -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
 
index 0de87159a127f0997cc18d19a3ebe1ccb01a2181..38b678c9d80255f947a3af7d89219bdf3da426dc 100644 (file)
@@ -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"
@@ -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
index 3d4bd54e9895550c8f348828da97a6dc819a2a9a..784c078d3815302c80e86dfbf9fe73a2672e557f 100644 (file)
@@ -1075,19 +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,
-`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.
+\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
@@ -1266,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
index 060d92922652b2f08b9a97ee7ecb20bd2f5ff145..3fb4b16a43528bc50955432f52eb232e5a016e8d 100644 (file)
@@ -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))]
index dc640e836cd242f4906eb100c04174895549966b..e04f3997168772d76d1497f97ac8e1b9dadc1f1d 100644 (file)
@@ -175,7 +175,7 @@ namespace System.Windows.Forms {
                        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)
index 18ee3dd8117ad2359379172886bca6eef8afec92..b8cc63b7e812b8592a36f56bb84d274c78b64098 100644 (file)
@@ -698,7 +698,7 @@ namespace System.Windows.Forms
 
                #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);
index 522dec40ec616af384bc431f1c9406aabdaec3fb..a9ed1ebec31cff77c3038a0458d0e0ebc8ca1ade 100644 (file)
@@ -364,12 +364,14 @@ namespace System.Windows.Forms
                        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 @@ namespace System.Windows.Forms
                                        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;
                        }
index df6603cfa8569c53f1ea348724911660b08ee8d4..2c42dc4da76a6ae9586a4a01f2994522743f09e6 100644 (file)
     <Compile Include="Microsoft.Build.BuildEngine\TaskBatchingImpl.cs" />\r
     <Compile Include="Microsoft.Build.BuildEngine\TaskDatabase.cs" />\r
     <Compile Include="Microsoft.Build.BuildEngine\TaskEngine.cs" />\r
+    <Compile Include="Microsoft.Build.BuildEngine\TaskExecutionMode.cs" />\r
     <Compile Include="Microsoft.Build.BuildEngine\Token.cs" />\r
     <Compile Include="Microsoft.Build.BuildEngine\Toolset.cs" />\r
     <Compile Include="Microsoft.Build.BuildEngine\ToolsetCollection.cs" />\r
index 14bf701f46fa8cae6f7082e63c161f91e010a553..a54315f175e5f4fc2f49ffb2f070c027bcc2d4a1 100644 (file)
@@ -155,11 +155,12 @@ namespace Mono.Debugger.Soft
 
        [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 @@ namespace Mono.Debugger.Soft
                 * 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,
index 5ca987ec69495c7d68293c8fdcae1c81ea68d84b..99dc87fa805b77c83b2e2e12d707fff553ee12d7 100644 (file)
@@ -22,6 +22,11 @@ namespace Mono.Debugger.Soft
                /*
                 * Return the values of out arguments
                 */
-               ReturnOutArgs = 8
+               ReturnOutArgs = 8,
+               /*
+                * Do a virtual invoke
+                * Since protocol version 2.37
+                */
+               Virtual = 16
        }
 }
index d83e3a1a4813052efc3bd3654aa3e6858aa66d38..e65f62fc945c092b86a9922e6a1c1bd7883eb8e7 100644 (file)
@@ -307,6 +307,8 @@ namespace Mono.Debugger.Soft
                                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 ();
index 3c9b2877c21c617f2ebb292b48568995923b28b5..f75951b8bc6477e3c32cb8d717a96c362fa2274f 100644 (file)
@@ -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 class Tests : TestsBase, ITest2
                j = 5;
                set_ip_2 ();
        }
+
+       public override string virtual_method () {
+               return "V2";
+       }
 }
 
 class TypeLoadClass {
index 9a671202a82027cf99d0b9ded34611eb72772d33..df4fbcc664872601920c32151eaa134ffafa9461 100644 (file)
@@ -2137,6 +2137,11 @@ public class DebuggerTests
                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");
index f07db9ec101aa7b2eee6c5718198511e7e18809c..14f8c73a8aeab2db00f782a1e971c334048820fe 100644 (file)
@@ -221,15 +221,13 @@ namespace Mono.Security.Cryptography {
                                                                string msg = Locale.GetText ("Could not create user key store '{0}'.");
                                                                throw new CryptographicException (String.Format (msg, _userPath), e);
                                                        }
-
-                                                       if (!ProtectUser (_userPath)) {
-                                                               string msg = Locale.GetText ("Could not secure user key store '{0}'.");
-                                                               throw new IOException (String.Format (msg, _userPath));
-                                                       } 
-
                                                        _userPathExists = true;
                                                }
                                        }
+                                       if (!IsUserProtected (_userPath) && !ProtectUser (_userPath)) {
+                                               string msg = Locale.GetText ("Could not secure user key store '{0}'.");
+                                               throw new IOException (String.Format (msg, _userPath));
+                                       }
                                }
                                // is it properly protected ?
                                if (!IsUserProtected (_userPath)) {
@@ -258,15 +256,13 @@ namespace Mono.Security.Cryptography {
                                                                string msg = Locale.GetText ("Could not create machine key store '{0}'.");
                                                                throw new CryptographicException (String.Format (msg, _machinePath), e);
                                                        }
-
-                                                       if (!ProtectMachine (_machinePath)) {
-                                                               string msg = Locale.GetText ("Could not secure machine key store '{0}'.");
-                                                               throw new IOException (String.Format (msg, _machinePath));
-                                                       }
-
                                                        _machinePathExists = true;
                                                }
                                        }
+                                       if (!IsMachineProtected (_machinePath) && !ProtectMachine (_machinePath)) {
+                                               string msg = Locale.GetText ("Could not secure machine key store '{0}'.");
+                                               throw new IOException (String.Format (msg, _machinePath));
+                                       }
                                }
                                // is it properly protected ?
                                if (!IsMachineProtected (_machinePath)) {
index b22f1b5ae25e12fc20f9250a0e5e4a415b3a49a0..d3671c0bf9fa234bfa28f40eea84dfbffe3f4c6f 100644 (file)
@@ -97,10 +97,26 @@ namespace Mono.Security.X509 {
                // 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 @@ namespace Mono.Security.X509 {
                                        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 @@ namespace Mono.Security.X509 {
                                        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 @@ namespace Mono.Security.X509 {
                        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 @@ namespace Mono.Security.X509 {
                        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.
                        }
                }
 
index 63502e555faaecfae8e0a5a6dd0e6e0b1a20e32b..bd35e657343646b39de3a0cda9448ba17d45297e 100644 (file)
@@ -553,7 +553,10 @@ namespace System {
                        {
                                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 @@ namespace System {
 #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<IAndroidTimeZoneDB> c = () => GetDefaultTimeZoneDB ();
                                Mono.Options.OptionSet p = null;
                                p = new Mono.Options.OptionSet () {
@@ -595,6 +602,10 @@ namespace System {
                                        { "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 @@ namespace System {
                                        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");
                                                }
index 95dead37499f066bc460e7be0cb115b2c6bea82f..eb65112a4177b6fc546d5ff9877b508be17ed94f 100644 (file)
     <Compile Include="System.Data.SqlClient\SqlCommandBuilder.cs" />\r
     <Compile Include="System.Data.SqlClient\SqlConnection.cs" />\r
     <Compile Include="System.Data.SqlClient\SqlConnectionStringBuilder.cs" />\r
+    <Compile Include="System.Data.SqlClient\SqlCredential.cs" />\r
     <Compile Include="System.Data.SqlClient\SqlDataAdapter.cs" />\r
     <Compile Include="System.Data.SqlClient\SqlDataReader.cs" />\r
     <Compile Include="System.Data.SqlClient\SqlDataSourceConverter.cs" />\r
index b1174b836153b2507a9dfbdcc5b18e1a54ea3dcd..5a5ed877c5535b5930f85255aa17d4cb9b229120 100644 (file)
@@ -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
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 (file)
index 0000000..5e9f589
--- /dev/null
@@ -0,0 +1,117 @@
+//
+// 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.IO;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Xml;
+
+namespace System.IdentityModel.Tokens {
+       [Serializable]
+       public class BootstrapContext : ISerializable {
+               /// <summary>Gets the string that was used to initialize the context.</summary>
+               public string Token { get; private set; }
+               /// <summary>Gets the array that was used to initialize the context.</summary>
+               public byte [] TokenBytes { get; private set; }
+               /// <summary>Gets the security token that was used to initialize the context.</summary>
+               public SecurityToken SecurityToken { get; private set; }
+               /// <summary>Gets the token handler that was used to initialize the context.</summary>
+               public SecurityTokenHandler SecurityTokenHandler { get; private set; }
+
+               /// <summary>Initializes a new instance of the <see cref="BootstrapContext"/> class by using the specified string.</summary>
+               public BootstrapContext (string token)
+               {
+                       if (token == null)
+                               throw new ArgumentNullException ("token");
+                       Token = token;
+               }
+
+               /// <summary>Initializes a new instance of the <see cref="BootstrapContext"/> class by using the specified array.</summary>
+               public BootstrapContext (byte [] token)
+               {
+                       if (token == null)
+                               throw new ArgumentNullException ("token");
+                       TokenBytes = token;
+               }
+
+               /// <summary>Initializes a new instance of the <see cref="BootstrapContext"/> class by using the specified security token and token handler.</summary>
+               public BootstrapContext (SecurityToken token, SecurityTokenHandler handler)
+               {
+                       if (token == null)
+                               throw new ArgumentNullException ("token");
+                       if (handler == null)
+                               throw new ArgumentNullException ("handler");
+                       SecurityToken = token;
+                       SecurityTokenHandler = handler;
+               }
+
+               /// <summary>Initializes a new instance of the <see cref="BootstrapContext"/> class from a stream.</summary>
+               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");
+                               break;
+                       case 'B':
+                               TokenBytes = (byte [])info.GetValue ("T", typeof (byte []));
+                               break;
+                       case 'T':
+                               Token = Encoding.UTF8.GetString (Convert.FromBase64String (info.GetString ("T")));
+                               break;
+                       }
+               }
+
+               /// <summary>Populates the <see cref="SerializationInfo"/> with data needed to serialize the current <see cref="BootstrapContext"/> object.</summary>
+               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 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
index 32942efdb5c23dbedd4f1f79839a9a9e10c31aa8..2c86355259a44a1e3fb982560175c28fe6597538 100755 (executable)
@@ -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
index 86d286ce11caeb7c69515072c6f1c1309821337c..2fcb687a3a5171031037f9078091e1a54dde70e6 100644 (file)
@@ -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 (file)
index 0000000..1d50907
--- /dev/null
@@ -0,0 +1,251 @@
+//
+// 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 System.Text;
+using System.Xml;
+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 = "<UserNameSecurityToken Id=\"uuid-927c0b98-ba18-49d2-a653-306d60f85751-3\" Username=\"" + user + "\" Password=\"" + 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, 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 ()
+               {
+                       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);
+                               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");
+                       }
+               }
+
+               [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);
+                               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");
+                       }
+               }
+
+               [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);
+                               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.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");
+                       }
+               }
+
+               [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 static void DumpAsText (byte [] data)
+               {
+                       Console.WriteLine ("{0}", Encoding.ASCII.GetString (data));
+               }
+
+               private static void Dump (byte [] data)
+               {
+                       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);
+                       }
+                       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 ();
+                       }
+               }
+       }
+}
+#endif
index 90ed57e3dce7ab273d349a98890e3fbeb24bd4ab..f79d9662bcdc3b3fe12393e402137f0297d4c6d7 100644 (file)
 // 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 @@ namespace System.Management
 
                public ObjectQuery Query {
                        get {
-                               throw new NotImplementedException ();
+                               return mQueryObject;
                        }
                        set {
-                               throw new NotImplementedException ();
+                               mQueryObject = value;
                        }
                }
 
index 295161932b55c2bc9b4873d642d094ceef59b064..8ae0ce57356002636911dc5d32c903933703483b 100644 (file)
@@ -84,7 +84,17 @@ namespace System.Runtime.Serialization.Json
                                throw new ArgumentOutOfRangeException ("maxItemsInObjectGraph");
 
                        this.type = type;
-                       known_types = new ReadOnlyCollection<Type> (knownTypes != null ? knownTypes.ToArray () : Type.EmptyTypes);
+
+                       var knownTypesFromAttributes = new List<Type> ();
+
+                       foreach (var attr in type.GetCustomAttributes (typeof (KnownTypeAttribute), false))
+                               knownTypesFromAttributes.Add ((attr as KnownTypeAttribute).Type);
+
+                       if (knownTypes != null)
+                               knownTypesFromAttributes.AddRange (knownTypes);
+
+                       known_types = new ReadOnlyCollection<Type> (knownTypesFromAttributes);
+
                        root = rootName;
                        max_items = maxItemsInObjectGraph;
                        ignore_extension = ignoreExtensionDataObject;
@@ -134,8 +144,6 @@ namespace System.Runtime.Serialization.Json
                public bool IgnoreExtensionDataObject {
                        get { return ignore_extension; }
                }
-
-               [MonoTODO]
                public ReadOnlyCollection<Type> KnownTypes {
                        get { return known_types; }
                }
index 8f8fe7171fe51a2edc99763e6a79ba4d215e2bed..d0f84d0f93a6a66ee3a5cb41bc97ce2a14371a38 100644 (file)
@@ -182,8 +182,18 @@ namespace System.Runtime.Serialization.Json
                                        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 @@ namespace System.Runtime.Serialization.Json
                }
                
 
-               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), false))
+                                       if ((attr as KnownTypeAttribute).Type.FullName.Equals (properName))
+                                               return (attr as KnownTypeAttribute).Type;
 
                        return null;
                }
@@ -230,7 +238,7 @@ namespace System.Runtime.Serialization.Json
                        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);
@@ -264,7 +272,7 @@ namespace System.Runtime.Serialization.Json
                                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:
index cd4c1ffccdf0e3bd92ecf58033526bfcd4966010..cd586fa05c3a2276c9077328b6f6c7540e2dc2f1 100644 (file)
@@ -203,10 +203,9 @@ namespace System.ServiceModel.Syndication
                                                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 ());
index 68d9fb6a083ce21a6a60b36523769bf4afbd47ba..8a11d70baf12597633b386afe2b730be9546d3ed 100644 (file)
@@ -1191,6 +1191,15 @@ namespace MonoTests.System.Runtime.Serialization.Json
                        return ser.ReadObject (xr);
                }
 
+               public T Deserialize<T>(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 @@ namespace MonoTests.System.Runtime.Serialization.Json
                        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<ParentType> (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<ParentType> (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<ParentType> (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<ParentType> (serializedObj);
+               }
+                       
                #endregion
        }
        
@@ -2037,6 +2090,42 @@ namespace MonoTests.System.Runtime.Serialization.Json
                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]
index 0ca6f2fb050664813a9febe676ca4c71988908ee..de884aeac9affe6f8862702d74feceec931a54a5 100644 (file)
@@ -855,5 +855,16 @@ namespace MonoTests.System.Runtime.Serialization.Json
                        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);
+               }
        }
 }
index 3b83d230cb4ebfabc7d023a589db06785ef46c7a..d0ea17ff6adf4330ded915306ffb64b937622684 100644 (file)
@@ -351,6 +351,24 @@ namespace MonoTests.System.ServiceModel.Syndication
                {
                        Assert.IsNull (((IXmlSerializable) new Rss20ItemFormatter ()).GetSchema ());
                }
+
+               [Test]
+               public void ReadFromGuidPermaLink ()
+               {
+                       const string xml1 = "<item><guid isPermaLink=\"false\">urn:myid</guid><description /></item>";
+                       using (XmlReader r = CreateReader (xml1)) {
+                               var rss = new Rss20ItemFormatter ();
+                               rss.ReadFrom (r);
+                               Assert.AreEqual ("urn:myid", rss.Item.Id);
+                       }
+
+                       const string xml2 = "<item><guid isPermaLink=\"true\">urn:myid</guid><description /></item>";
+                       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
index b2bae459a52116303d52b0691a7ea04bf1f16b36..13a7319cbaed3428f4ba9501735f16f848855c40 100644 (file)
@@ -94,7 +94,7 @@ namespace System.Web.Security
 
                internal void UpdateUser ()
                {
-                       MembershipUser newUser = Provider.GetUser (name, false);
+                       MembershipUser newUser = Provider.GetUser (UserName, false);
                        UpdateSelf (newUser);
                }
 
index bb821a573cfc29f7bc7d0ba0ec1e224ceb956df2..7189276746944a768c178305d2d45f42ca2400da 100644 (file)
@@ -56,7 +56,7 @@ namespace System.Web {
                                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--;
index 4c7228dd6a2b17e05f75e64870770f6663546150..5ead2173893c8bc8607417922b5e856ed40e0dbf 100644 (file)
@@ -861,6 +861,15 @@ namespace MonoTests.System.Web {
        @"&#160;&#161;&#162;&#163;&#164;&#165;&#166;&#167;&#168;&#169;&#170;&#171;&#172;&#173;&#174;&#175;&#176;&#177;&#178;&#179;&#180;&#181;&#182;&#183;&#184;&#185;&#186;&#187;&#188;&#189;&#190;&#191;&#192;&#193;&#194;&#195;&#196;&#197;&#198;&#199;&#200;&#201;&#202;&#203;&#204;&#205;&#206;&#207;&#208;&#209;&#210;&#211;&#212;&#213;&#214;&#215;&#216;&#217;&#218;&#219;&#220;&#221;&#222;&#223;&#224;&#225;&#226;&#227;&#228;&#229;&#230;&#231;&#232;&#233;&#234;&#235;&#236;&#237;&#238;&#239;&#240;&#241;&#242;&#243;&#244;&#245;&#246;&#247;&#248;&#249;&#250;&#251;&#252;&#253;&#254;&#255;",
 };
 
+               [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());
+               }
        }
 }
 
index baedf04c7ec5aee4190f85c395226704a533f086..27848d10ea073aee33c40a78188d74462717de4f 100644 (file)
@@ -1955,14 +1955,12 @@ namespace System.Xml.Serialization
                                                {
                                                        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 ();
                                                }
index 1853ad1497615a244b44df1c26ef7fe79b75d621..5d9e4b24f341cd6a2054bb8d1ab9aea3d18342e5 100644 (file)
@@ -505,7 +505,7 @@ namespace System.Xml.Serialization
                                                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);
                                        }
index 63745fe3039117b51b56597d695550427ad8fa24..7dc686ba352503d26971f59ec116cd78b7971f91 100644 (file)
@@ -164,11 +164,6 @@ namespace Mono.Xml2
                        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 @@ namespace Mono.Xml2
                        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
index 2110bb62f17e0fbc51b3323dcef33b96073de5ba..52a7a9e687891f6a624ed2f77cc38787f7963e58 100644 (file)
@@ -254,6 +254,11 @@ namespace System.Xml
                        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; }
index b4ec87869e6c0bd59338d3e4be07070de3d4df6b..872e6cbdf712703be469408696aec3f86cfdf7cc 100644 (file)
@@ -1178,5 +1178,22 @@ namespace MonoTests.System.Xml.TestClasses
                [XmlArrayItem ("Element")]
                public List<SimpleClass> 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;
+               }
+    }
 }
 
index 8f03b0c2223a8b921dfda53ab1aec9a6c489492d..ef6ba78867fa3b99cb16bbe347f37608795cc92a 100644 (file)
@@ -3495,6 +3495,31 @@ namespace MonoTests.System.XmlSerialization
                                }
                        }
                }
+
+               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.
index edab3fb47757abb311d36a12b1a4bf25a6cd849e..f7b5e7b6c6626d7203a1a716425825641f65f8ed 100644 (file)
@@ -25,6 +25,7 @@
 //
 
 using System;
+using System.Linq;
 using System.Xml;
 
 namespace System.Xml.Linq
@@ -54,7 +55,9 @@ namespace System.Xml.Linq
 
                public override void WriteTo (XmlWriter writer)
                {
-                       writer.WriteComment (value);
+                       var v = value.Replace ("--", "- -");
+                       v = v.LastOrDefault () == '-' ? v.Substring (0, v.Length - 1) +"&#2D;" : v;
+                       writer.WriteComment (v);
                }
        }
 }
index 77007ae238d3a44e2d80493807a4d34562f8b500..693d4a2e296436b7c6c4cc7a24c97a727acd6c46 100644 (file)
@@ -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 (file)
index 0000000..b324bb6
--- /dev/null
@@ -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 ("<!--<- -foo- ->-->", 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 ("<!--- -foo- &#2D;-->", c.ToString (), "#4");
+                       XmlReader.Create (new StringReader (c.ToString ())).Read ();
+
+                       // What if <!-- appears in the value?
+                       c = new XComment ("<!--foo-->");
+                       Assert.AreEqual ("<!--foo-->", c.Value, "#5");
+                       Assert.AreEqual ("<!--<!- -foo- ->-->", c.ToString (), "#6");
+                       XmlReader.Create (new StringReader (c.ToString ())).Read ();
+               }
+       }
+}
index 893cd8e3a46fff54dab7039200b2ddefd09c82a3..395bc68e96d3f42fc93db9b82d25a64b2f204b75 100644 (file)
@@ -124,8 +124,12 @@ namespace System.Collections.Concurrent
                                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 @@ namespace System.Collections.Concurrent
                                        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;
@@ -291,30 +291,28 @@ namespace System.Collections.Concurrent
 
                public static int AddToAny (BlockingCollection<T>[] collections, T item)
                {
-                       CheckArray (collections);
-                       int index = 0;
-                       foreach (var coll in collections) {
-                               try {
-                                       coll.Add (item);
-                                       return index;
-                               } catch {}
-                               index++;
-                       }
-                       return -1;
+                       return AddToAny (collections, item, CancellationToken.None);
                }
 
                public static int AddToAny (BlockingCollection<T>[] 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<T>[] collections, T item)
@@ -368,21 +366,7 @@ namespace System.Collections.Concurrent
 
                public static int TakeFromAny (BlockingCollection<T>[] 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<T>[] collections, out T item, CancellationToken cancellationToken)
index e5a34ff1a41478735652b7c883839575fba532a6..c013223d08108d239bdc1c84481cc55c1d407358 100644 (file)
@@ -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 @@ namespace System.Diagnostics
                                        DateFormat, CultureInfo.InvariantCulture);
                                DateTime timeWritten = File.GetLastWriteTime (file);
                                int stringNums = int.Parse (tr.ReadLine ().Substring (20));
-                               ArrayList replacementTemp = new ArrayList ();
+                               var replacementTemp = new List<string> ();
                                StringBuilder sb = new StringBuilder ();
                                while (replacementTemp.Count < stringNums) {
                                        char c = (char) tr.Read ();
@@ -238,8 +238,7 @@ namespace System.Diagnostics
                                                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);
index 795ebaaa80ff60ae606417ac7d6cb9599363ecaa..0cf197af1dcac3be7c072c2ee3ac51b74573023f 100644 (file)
@@ -39,7 +39,7 @@ using System.ComponentModel.Design;
 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 @@ namespace System.Diagnostics {
                [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<Process> (pids.Length);
                        for (int i = 0; i < pids.Length; i++) {
                                try {
                                        proclist.Add (GetProcessById (pids [i]));
@@ -851,7 +851,7 @@ namespace System.Diagnostics {
                                }
                        }
 
-                       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 @@ namespace System.Diagnostics {
                        if (pids == null)
                                return new Process [0];
                        
-                       ArrayList proclist = new ArrayList (pids.Length);
+                       var proclist = new List<Process> (pids.Length);
                        for (int i = 0; i < pids.Length; i++) {
                                try {
                                        Process p = GetProcessById (pids [i]);
@@ -886,7 +886,7 @@ namespace System.Diagnostics {
                                }
                        }
 
-                       return ((Process []) proclist.ToArray (typeof (Process)));
+                       return proclist.ToArray ();
                }
 
                [MonoTODO]
@@ -940,7 +940,7 @@ namespace System.Diagnostics {
                                                               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 @@ namespace System.Diagnostics {
                                                              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) {
index 40fe3a36b157ac461654e70c532d17ec06966ce7..4002c3b7cdc4850dbe9490d4831005ed7024fc27 100644 (file)
@@ -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 @@ namespace System.Diagnostics
 
                                string [] sources = (string []) logKey.GetValue ("Sources");
                                if (sources != null) {
-                                       ArrayList temp = new ArrayList ();
+                                       var temp = new List<string> ();
                                        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);
                                }
                        }
index 8988a6b97030e2180008f7c7551ac043e366a0a3..d2d8b28d86cef4ebbeeff516308503d14cf10fe2 100644 (file)
@@ -30,6 +30,7 @@
 
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.IO;
 using System.Threading;
 
@@ -240,12 +241,12 @@ namespace System.IO {
                                return;
 
                        /* Removed files */
-                       ArrayList removed = null;
+                       List<string> 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<string> ();
 
                                        removed.Add (filename);
                                        DispatchEvents (data.FSW, FileAction.Removed, filename);
@@ -269,7 +270,7 @@ namespace System.IO {
                                } catch {
                                        /* Deleted */
                                        if (removed == null)
-                                               removed = new ArrayList ();
+                                               removed = new List<string> ();
 
                                        removed.Add (filename);
                                        DispatchEvents (data.FSW, FileAction.Removed, filename);
index 45740306db54d46b6c7ebb44c3b1ed35a169c786..0b5d6a76e4bde04bd6251048da01be9e720c9fb5 100644 (file)
@@ -225,6 +225,14 @@ namespace System.Net
                }
        }
 
+       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 @@ namespace System.Net
                }
        }
 
+       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 @@ namespace System.Net
                // 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 @@ namespace System.Net
                        
                        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 @@ namespace System.Net
                        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 @@ namespace System.Net
                                                                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:
index 0de6d8f91ef15bdec118d786fba901e5e37494b6..5e94d3bdf539e67969bdcc768a3c4464debf0a03 100644 (file)
@@ -336,7 +336,13 @@ namespace System {
                                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 == ':'){
index 979734af0599ced70243091e05f1e5e750ff62ee..a9d536085bbcfa5a65a81ddfd67514dc8ba708e3 100644 (file)
@@ -317,7 +317,7 @@ namespace MonoCasTests.System.CodeDom.Compiler {
                [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 @@ namespace MonoCasTests.System.CodeDom.Compiler {
                [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)
index 9f0e9b0190da47d2bb9bf8e4783eab871b46cdde..bf41aeee21af96b1c098b5bb30e596f11cdebb69 100644 (file)
@@ -237,7 +237,7 @@ namespace MonoTests.System.Collections.Concurrent
                        t = Task.Factory.StartNew (() => {
                                try {
                                        return BlockingCollection<string>.TakeFromAny (arr, out res, cts.Token);
-                               } catch (OperationCanceledException WE_GOT_CANCELED) {
+                               } catch (OperationCanceledException) {
                                        res = "canceled";
                                        return -10;
                                }
@@ -247,6 +247,40 @@ namespace MonoTests.System.Collections.Concurrent
                        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 <int> (elNumber);
+                       var token = new CancellationTokenSource (100);
+
+                       for (var i = 0; i < elNumber + 1; i++) {
+                               c.Add (1, token.Token);
+                       }
+               }
+
+               [Test]
+               public void AddAnyCancellable ()
+               {
+                       const int elNumber = 5;
+                       const int colNumber = 5;
+
+                       var cols = new BlockingCollection <int> [colNumber];
+                       for (var i = 0; i < colNumber; i++) {
+                               cols[i] = new BlockingCollection <int> (elNumber);
+                       }
+
+                       var token = new CancellationTokenSource (100);
+                       for (var i = 0; i < colNumber * elNumber; i++) {
+                               BlockingCollection <int>.AddToAny (cols, 1, token.Token);
+                       }
+
+                       foreach (var col in cols) {
+                               Assert.AreEqual (elNumber, col.Count);
+                       }
+               }
        }
 }
 #endif
index 16d12af943c993e9ac2a8cfbb46a474b760b2d86..dbc4110cb20c65a6822e4568331fc90b36091cd7 100644 (file)
@@ -277,7 +277,7 @@ namespace MonoTests.System.ComponentModel.Design.Serialization {
                        }
                }
 
-               class InstanceField
+               public class InstanceField
                {
                        public string Name;
                }
index d0b78f97fba9ddb86cf583cb57c02549f31ae8d8..815a9a62554e5fc5eedc49fe8b1361b69509509a 100644 (file)
@@ -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 @@ namespace MonoTests.System.ComponentModel
                        converter = new CharConverter ();
 
                        DateTimeFormatInfo info = CultureInfo.CurrentCulture.DateTimeFormat;
-                       pattern = info.ShortDatePattern + " " + info.ShortTimePattern;
                }
 
                [Test]
index 16a6a4124dccb83b45d44b3d889503340b92f153..46706fd348eec3b4f4bb82beb11bb16cda5884a0 100644 (file)
@@ -733,10 +733,6 @@ namespace MonoTests.System.ComponentModel
                                container.Add (this);
                                return container;
                        }
-
-                       public Container Container {
-                               get { return container; }
-                       }
                }
 
                class MyContainer : IContainer
index 88de1d72a8cb3b927e4f312097152b6e08ad32a5..d6ae37eb0f6ee9dd6effc0e1536c26c96c4c1334 100644 (file)
@@ -722,7 +722,7 @@ namespace MonoTests.System.Diagnostics
                        }
                }
 
-               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 @@ namespace MonoTests.System.Diagnostics
                        try {
                                var x = p.Handle;
                                Assert.Fail ("Handle should throw for unstated procs, but returned " + x);
-                       } catch (InvalidOperationException ex) {
+                       } catch (InvalidOperationException) {
                        }
                }
        }
index 9b2577c41e2b051ae069fbd46069984a0af074e2..e245fcd5b0604a97023a3dca0e4c9027c9f47acf 100644 (file)
@@ -29,7 +29,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                static ManualResetEvent reset;
                private string message;
-               private string uri = "http://www.google.com";
 
                [TestFixtureSetUp]
                public void FixtureSetUp ()
index 9b2453bd6f1d9cade2de2fdc27fecdd5544eabc3..51c3ac795b52decb800db45596cb972571e9f4d2 100644 (file)
@@ -936,7 +936,7 @@ namespace MonoTests.System.Net.Sockets {
                                try {
                                        client = new UdpClient (port);
                                        break;
-                               } catch (Exception ex) {
+                               } catch (Exception) {
                                        if (i == 5)
                                                throw;
                                }
index e193a5f53072d43025d0810d6e144911c15b4773..2140daac9bb866aa77fb5dcebd666424dcff6f1d 100644 (file)
@@ -49,7 +49,10 @@ namespace MonoTests.System.Net.WebSockets
                [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 @@ namespace MonoTests.System.Net.WebSockets
                [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 @@ namespace MonoTests.System.Net.WebSockets
                [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) {
index f362e8291ea0ee8bae8287e49b9553fd7e618233..b532428fd53549c559863c03a3bb6d267d63c8fe 100644 (file)
@@ -30,14 +30,13 @@ namespace MonoCasTests.System.Net {
                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]
index 25f7b96a9b935a7cabf64a58906476934aa19824..7f3011e2b9dc6ef6a7c55a20ef473fc595192b02 100644 (file)
@@ -36,6 +36,14 @@ using NUnit.Framework;
 namespace MonoTests.System.Net {
        [TestFixture]
        public class HttpListenerTest {
+
+               int port;
+
+               [SetUp]
+               public void SetUp () {
+                       port = new Random ().Next (7777, 8000);
+               }
+
                [Test]
                public void DefaultProperties ()
                {
@@ -115,7 +123,7 @@ namespace MonoTests.System.Net {
                                        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;
@@ -152,10 +160,12 @@ namespace MonoTests.System.Net {
                [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 @@ namespace MonoTests.System.Net {
                [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 @@ namespace MonoTests.System.Net {
                [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 @@ namespace MonoTests.System.Net {
                [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 @@ namespace MonoTests.System.Net {
                [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 @@ namespace MonoTests.System.Net {
                [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 @@ namespace MonoTests.System.Net {
                [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 @@ namespace MonoTests.System.Net {
                [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 ();
index 88bd3b1cddc69cb5b073fc2eefe8e4c6fb1f376f..799152f5bbd9f27a297d75a40827f30bcae77aae 100644 (file)
@@ -52,6 +52,7 @@ namespace MonoTests.System.Security.Cryptography.X509Certificates {
                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 @@ namespace MonoTests.System.Security.Cryptography.X509Certificates {
                        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 @@ namespace MonoTests.System.Security.Cryptography.X509Certificates {
                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)
index 9439f666cc81426a827153c47709eefe32fae101..0ef6418bc14601e65ab0f045a184b93d066b9cdf 100644 (file)
@@ -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 @@ namespace MonoTests.System.Security.Cryptography.X509Certificates {
                        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);
index 5d30f5d7ed0e7a90c79c11166ee0809f53f52306..55dd1e6d05da7e233d5576b095c6bafd12f33a4a 100644 (file)
@@ -22,7 +22,7 @@ namespace MonoTests.System.Text.RegularExpressions
                                try {
                                        result = Regex.Replace (original, pattern, replacement);
                                }
-                               catch (Exception e) {
+                               catch (Exception) {
                                        result = "Error.";
                                }
                                Assert.AreEqual (expected, result, "rr#: {0} ~ s,{1},{2},",
index 1cf18ee74dace4a3f68ec722b79399b6482ea14d..4129b75a1257442d45605de04ae63391cd9a8c5a 100644 (file)
@@ -24,7 +24,7 @@ namespace MonoTests.System.Text.RegularExpressions
                                        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},",
index 79111f90fc4f7a28a09be325acd3dd0b250a52d6..0373ef20c4cc5428e1bcf301aa4223b853621c01 100644 (file)
@@ -217,28 +217,28 @@ namespace MonoTests.System {
                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
index b3b33170c584a1912bc36937b57c60517dc91617..fa76c2a67d414aa1b5a280128d1e648cbe7885fc 100644 (file)
@@ -1968,6 +1968,21 @@ namespace MonoTests.System
                        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);
+               }
+
+               [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
@@ -1978,7 +1993,7 @@ namespace MonoTests.System
                private bool originalIriParsing;
 
                [TestFixtureSetUp]
-               public void GetReady ()
+               public void GetReady2 ()
                {
                        isWin32 = (Path.DirectorySeparatorChar == '\\');
 
index e83eb67e69e857bd494e65119123410ebb77159e..eb165dc56cb40783b21bd890ed6dfc867ea68ff9 100644 (file)
@@ -117,6 +117,7 @@ namespace System.Security.Cryptography {
                protected override void Dispose (bool disposing) 
                {
                        if (!_disposed) {
+                               _disposed = true;
                                base.Dispose (disposing);
                        }
                }
index 1ea7a9ea86a810057f6af52dc673bbff9b0cba86..b3a93f142747f45db8131aa974bdab05dec202a2 100644 (file)
@@ -831,7 +831,6 @@ fail_no_space:
                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);
        }
index edb57e69ca22a8c8fbcd998e08ed54dd4bbd1e56..48077a2452b3bfbb64ca3658268b1680397e352d 100644 (file)
@@ -345,7 +345,7 @@ public class UnicodeEncoding : Encoding
                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 class UnicodeEncoding : Encoding
                        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.
index 1f8165a0d480712cad9b3affb89b3ab076376147..4f4abd33e9cd8365c7919c890e59d3f4acf04a8e 100644 (file)
@@ -635,7 +635,7 @@ namespace System.Threading.Tasks
                
                #region Cancel and Wait related method
                
-               internal void CancelReal ()
+               internal void CancelReal (bool notifyParent = false)
                {
                        Status = TaskStatus.Canceled;
 
@@ -643,6 +643,9 @@ namespace System.Threading.Tasks
                                wait_handle.Set ();
 
                        ProcessCompleteDelegates ();
+
+                       if (notifyParent && parent != null && NotifyParentOnFinish ())
+                               parent = null;
                }
 
                void HandleGenericException (Exception e)
index 2a0547850bd044fd65d53eea6bd251ea3ea5aad9..8ede25eebe4f4c81e23bc67e0583afb05b444ee6 100644 (file)
@@ -94,7 +94,7 @@ namespace System.Threading.Tasks
                public void Execute ()
                {
                        if (!ContinuationStatusCheck (continuationOptions)) {
-                               task.CancelReal ();
+                               task.CancelReal (notifyParent : true);
                                task.Dispose ();
                                return;
                        }
index 5ebd4db216e38dbe783e4d6174a92d63f10acb41..07b6fd45590ff9c00027b3a991a24689b4e10197 100644 (file)
@@ -1405,6 +1405,10 @@ namespace System {
                [method: SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
                public event UnhandledExceptionEventHandler UnhandledException;
 
+#if NET_4_5
+               public event EventHandler<FirstChanceExceptionEventArgs> FirstChanceException;
+#endif
+
 #if NET_4_0
                [MonoTODO]
                public bool IsHomogenous {
index 122606212391a547dfc5f8b65547016ab8c02fe1..21128defd9ba7b1b5b39dd2b99dacbdabb50f8bc 100644 (file)
@@ -44,7 +44,7 @@ using System.Threading;
 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 @@ namespace System {
                }
 #endif
 
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern static string GetWindowsFolderPath (int folder);
-
                /// <summary>
                /// Returns the fully qualified path of the
                /// folder specified by the "folder" parameter
@@ -486,6 +483,12 @@ namespace System {
                {
                        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 @@ namespace System {
 
                        // 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 @@ namespace System {
                                return "/usr/share";
                        default:
                                throw new ArgumentException ("Invalid SpecialFolder");
-                        }
-                }
+                       }
+               }
+#endif
 
                
                [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
@@ -884,7 +865,7 @@ namespace System {
                }
 
                // private methods
-#if MOBILE 
+#if (MONOTOUCH || MONODROID || XAMMAC)
                internal const bool IsRunningOnWindows = false;
 #else
                internal static bool IsRunningOnWindows {
diff --git a/mcs/class/corlib/System/FirstChanceExceptionEventArgs.cs b/mcs/class/corlib/System/FirstChanceExceptionEventArgs.cs
new file mode 100644 (file)
index 0000000..d39fbdc
--- /dev/null
@@ -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
index 2a408933eacf42bb4dfa82e80fdcf142481997d1..65e460647ca4955aecd1a8c4b97cccae46d9f582 100644 (file)
@@ -2688,24 +2688,8 @@ namespace System
                        }
                }
 
-               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.
index 7762dfc9177d180adbe5d7ec43d4a55ef72d1ce7..f6937ef3ca21dcbe0febed672cb8fde222e6191b 100644 (file)
@@ -614,41 +614,76 @@ namespace System
 
                                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 ()));
index 271412269c01f5f2f8b590d5473cda7616677df3..f65ac28ef5ed8bed9c4d2c680c158dc52b6286d5 100644 (file)
@@ -317,10 +317,12 @@ namespace MonoTests.System.Reflection.Emit
                        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 ()
index 1559d66369a80322b317137719fb8930f7fe3dcb..7f9db3b99fd0e53290e51e533cda40e407d2e53d 100644 (file)
@@ -27,7 +27,6 @@ namespace MonoTests.System.Reflection.Emit
        {
                AssemblyBuilder assembly;
                ModuleBuilder module;
-               int typeCount;
                static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.TypeBuilderTest";
 
                [SetUp]
@@ -46,7 +45,6 @@ namespace MonoTests.System.Reflection.Emit
                                        assemblyName, mode, Path.GetTempPath ());
 
                        module = assembly.DefineDynamicModule ("module1");
-                       typeCount = 0;
                }
 
                [Test]
index 382f3f255279b48e53d7e85bf3b9d869cbf2488c..b1b7cf320f3f5346dd7e01ef4551018929f2d874 100644 (file)
@@ -92,8 +92,8 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                public class Tuple <A,B> {
-                       A a;
-                       B b;
+                       public A a;
+                       public B b;
                }
 
                private AssemblyBuilder assembly;
index a24a4868d9b60c75ebab37907145a6cb37681719..087297b6f24006566fe9f1838c48c35a1a206b09 100644 (file)
@@ -42,7 +42,6 @@ namespace MonoCasTests.System.Reflection {
        public class AssemblyNameCas {
 
                private MonoTests.System.Reflection.AssemblyNameTest ant;
-               private AssemblyName main;
 
                [TestFixtureSetUp]
                public void FixtureSetUp ()
index ccd923fa59c7517cbb2a74f803e8d769d37d02a3..a3639864f6a48730c1e7ac06d913f4c3aa44ceb3 100644 (file)
@@ -73,6 +73,8 @@ namespace MonoTests.System.Reflection
        {
        }
 
+       // 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 @@ namespace MonoTests.System.Reflection
                public Int64Enum field_Int64Enum;
                public UInt64Enum field_UInt64Enum;
        }
+       #pragma warning restore 649
 
        public enum ByteEnum : byte
        {
@@ -376,10 +379,13 @@ namespace MonoTests.System.Reflection
                        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 @@ namespace MonoTests.System.Reflection
 
        }
 
+       // 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<T>
index 65adf97aa51cb3fae0efc2b5d6374e45d5ebb2f2..00349880e1f1be6cbd4ca6336955cbb72830ad29 100644 (file)
@@ -42,9 +42,12 @@ using System.Collections.Generic;
 #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 @@ namespace MonoTests.System.Reflection
 
                public struct SimpleStruct
                {
-                       int a;
+                       public int a;
                }
 
                public static unsafe SimpleStruct* PtrFunc2 (SimpleStruct* a, A.B.C.MethodInfoTestStruct *b)
index 0b02596ec5bb273f7addb5fff8012667a47aa7f9..e47b5e1eb79fea692a19b050dcaa816515ee628e 100644 (file)
@@ -178,7 +178,7 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                public class Bar<T> {
-                       public class Foo<T> {}
+                       public class Foo<U> {}
                }
 
                [Test]
index bcc814e04d36734425e9969e7c975daff96b8964..8347b4dabf7bd17ea22966512997afef6bae431f 100644 (file)
@@ -29,6 +29,8 @@ using System;
 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]
index 92d19fe367eddda5638228faa7783c32bd345114..f6f4dabe2bad2eeee6dce0eeb2164a51b6645304 100644 (file)
@@ -402,9 +402,12 @@ namespace MonoTests.System.Runtime.CompilerServices {
        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 <object,object> cwt;
                int id;
+               #pragma warning restore 414
+               ConditionalWeakTable <object,object> cwt;
 
                public FinalizableLink (int id, object obj, ConditionalWeakTable <object,object> cwt) {
                        this.id = id;
index fc4010bd21cd22d3394c54eb71047e449fbe6a21..593305d4a67543f5f2d341765e1a4dfd9a385e5f 100644 (file)
@@ -94,8 +94,10 @@ namespace MonoTests.System.Runtime.CompilerServices {
                        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 @@ namespace MonoTests.System.Runtime.CompilerServices {
                }
 
                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))]
index 5237e377e38c80d9a73ce149db5dde8934bdc428..1bc9d38414758f89d626e21e369236701da04839 100644 (file)
@@ -72,6 +72,11 @@ namespace MonoTests.System.Runtime.CompilerServices
                                Interlocked.Increment (ref ic);
                                return false;
                        }
+
+                       public override string ToString ()
+                       {
+                               return "Scheduler-" + name;
+                       }
                }
 
                class SingleThreadSynchronizationContext : SynchronizationContext
index 1ac8a825b641fc5c77b46dae882d53c56c9b8baf..17fe0d9045df543807ec622c71fa8e48c1032cab 100644 (file)
@@ -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 ()
                {
index d6f2a49bf38d774f3ee0f8be8c7a3f1f2f37c685..28943159aa10520ef866a4c9b5d8c60355adfe6b 100644 (file)
@@ -28,7 +28,7 @@ namespace MonoTests.System.Runtime.InteropServices
                        public int field;
                }
 
-               class ClsNoLayout {
+               public class ClsNoLayout {
                        public int field;
                }
 
@@ -173,12 +173,12 @@ namespace MonoTests.System.Runtime.InteropServices
                        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]
index 90b2d3f73fc386c099bbace95e4a1f82707e1ba2..48e686ab8ddf840fa0d270485df8d622ae447611 100644 (file)
@@ -637,6 +637,8 @@ namespace MonoTests.System.Runtime.Serialization
                        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");
index 10328b8e60fa59ba34c76298cae2bbb000b0e58c..3ad6cce71f9c43393cee9af143f6f4349c908ea8 100644 (file)
@@ -144,7 +144,6 @@ namespace MonoTests.System.Security.Cryptography {
                Stream readStream;
                Stream writeStream;
                ICryptoTransform encryptor;
-               ICryptoTransform decryptor;
                CryptoStream cs;
                SymmetricAlgorithm aes;
 
@@ -156,7 +155,6 @@ namespace MonoTests.System.Security.Cryptography {
                                writeStream = new MemoryStream (new byte [0], true);
                                aes = SymmetricAlgorithm.Create ();
                                encryptor = aes.CreateEncryptor ();
-                               decryptor = aes.CreateEncryptor ();
                        }
                }
 
index 115bdf30cc40f2f400002f373e0ed99bb91a980d..e243712d80c065bda63dfbbe7b175d6305c41a24 100644 (file)
@@ -28,6 +28,9 @@ namespace MonoTests.System.Security.Cryptography {
 
        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 @@ namespace MonoTests.System.Security.Cryptography {
        public class HMACSHA384Test : KeyedHashAlgorithmTest {
 
                protected HMACSHA384 algo;
-               private bool legacy;
 
                [SetUp]
                public override void SetUp () 
@@ -53,8 +55,6 @@ namespace MonoTests.System.Security.Cryptography {
                        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
index 04497415d0e9cbe428e2d7061e39ed414733027a..55a7b87589c0a0ac859ef512bd4c46ea4a66fac6 100644 (file)
@@ -26,6 +26,9 @@ namespace MonoTests.System.Security.Cryptography {
 
        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 @@ namespace MonoTests.System.Security.Cryptography {
        public class HMACSHA512Test : KeyedHashAlgorithmTest {
 
                protected HMACSHA512 algo;
-               private bool legacy;
 
                [SetUp]
                public override void SetUp () 
@@ -51,8 +53,6 @@ namespace MonoTests.System.Security.Cryptography {
                        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
index fb3770db4b43d8ae4fbb04ce133a1a0ae533883f..f95691c7f54e4ae5cacd5486e62afc0f27d5cf6b 100644 (file)
@@ -38,7 +38,6 @@ namespace MonoTests.System.Security.Permissions {
 
                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\";
 
index 62a0c35e1cd5b78cbe3ead43b38cea1fda50e4fd..f9a7d8ae21aa412702fbb824e87b4ce39bc3a17d 100644 (file)
@@ -51,12 +51,6 @@ namespace MonoTests.System.Security.Permissions {
                        "*",
                };
 
-               // 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 ()
                {
index 9938bcef1ae1c92f007b804f1a6de9b82dfb2b52..e780524afe159689a756d40445428ab7361b38d2 100644 (file)
@@ -164,34 +164,18 @@ namespace MonoTests.System.Text
                 }
                 
                 [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 @@ namespace MonoTests.System.Text
                        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");
+               }
        }
 }
index 63eb8a2aff1a8b31d9b64fe0b40193d0a3a0430f..4e358cadd94cf3d2a7babad89de8bd23777a6e6a 100644 (file)
@@ -616,18 +616,18 @@ namespace MonoTests.System.Threading.Tasks
                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);
                }
 
@@ -905,7 +905,7 @@ namespace MonoTests.System.Threading.Tasks
                        };
                        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 ();
@@ -1094,7 +1094,7 @@ namespace MonoTests.System.Threading.Tasks
                        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 @@ namespace MonoTests.System.Threading.Tasks
                        }
                }
 
+               [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()
index 11e611563c8e791f86d121cb8da5eb540b0dd43e..67bcd941d45e3fc2084982b412516f9e69483f0d 100644 (file)
@@ -85,10 +85,10 @@ namespace MonoTests.System.Threading
        [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 @@ namespace MonoTests.System.Threading
                                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 @@ namespace MonoTests.System.Threading
                        Assert.AreEqual (this, arg, "obj");     
                }               
 
-               bool set_name_failed;
-
                [Test]
                public void SetNameTpThread () {
                        ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
index 8772d7afdea04e8771c54266715144cacfffa015..0836640057e3cfabdb47c8cc3ab4990f87869cad 100644 (file)
@@ -3240,6 +3240,7 @@ namespace MonoTests.System
                }
 #endif
 
+
                public class StuffToPick
                {
                        public StuffToPick () {}
@@ -3248,6 +3249,11 @@ namespace MonoTests.System
                        public event Action Event;
                        public int Field;
                        public void GenericMethod<T> () {}
+
+                       public void Dummy ()
+                       {
+                               Event += delegate {};
+                       }
                }
 
                public class StuffToPick<T>
@@ -3257,7 +3263,12 @@ namespace MonoTests.System
                        public int Property { get; set; }
                        public event Action Event;
                        public int Field;
-                       public void GenericMethod<T> () {}
+                       public void GenericMethod<U> () {}
+
+                       public void Dummy ()
+                       {
+                               Event += delegate {};
+                       }
                }
 
                static void TestSerialization (CrossDomainTester tester, object o)
index 9bf4d31a1cdffbcad8fd171426f40cff6c1971ce..c8d40396c299129c83d1754b1d718887b23b3b5c 100644 (file)
@@ -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 class SByteTest
                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));
index 101cad48a9240a15f3cb2b15d7b1fe71dc6976a0..2d9e0984996cc67c7e03c9de5ee740239415ea4c 100644 (file)
@@ -1430,6 +1430,18 @@ public class TimeSpanTest {
                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]
index 00131c8d47f1d59ef4266e335ec71b293424a720..6acbac2dd9f4343e294871c32192c68a76bef31b 100644 (file)
@@ -143,6 +143,10 @@ namespace MonoTests.System
                }
 
                public event EventHandler E;
+               public void Dummy ()
+               {
+                       E += delegate {};
+               }
        }
 
        class Derived1 : Base1
@@ -159,7 +163,11 @@ namespace MonoTests.System
                        set { }
                }
 
-               public event Action E;
+               public new event Action E;
+               public new void Dummy ()
+               {
+                       E += delegate {};
+               }
        }
 
        public class Foo<T>
@@ -1860,7 +1868,9 @@ PublicKeyToken=b77a5c561934e089"));
 
                struct B
                {
+                       #pragma warning disable 169
                        int value;
+                       #pragma warning restore 169
                }
 
                [Test]
@@ -2153,7 +2163,7 @@ PublicKeyToken=b77a5c561934e089"));
                        a1 = new string [10];
                }
 
-               class X
+               public class X
                {
                        public static int Value;
                }
index d80870fca6fd800b383a70095876efb58384e88c..bf5bf19095531491d14fcc25ace1b6995323dc6b 100644 (file)
     <Compile Include="System\Exception.cs" />\r
     <Compile Include="System\ExecutionEngineException.cs" />\r
     <Compile Include="System\FieldAccessException.cs" />\r
+    <Compile Include="System\FirstChanceExceptionEventArgs.cs" />\r
     <Compile Include="System\FlagsAttribute.cs" />\r
     <Compile Include="System\FormatException.cs" />\r
     <Compile Include="System\Funcs.cs" />\r
index 2626ca0fa3e3a219d2a44cd9f38b0657aeecee1d..b1516b8bb1427aa88926bb4cc09e2924cbf10579 100644 (file)
@@ -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
diff --git a/mcs/errors/cs0023-25.cs b/mcs/errors/cs0023-25.cs
new file mode 100644 (file)
index 0000000..d6f5c5b
--- /dev/null
@@ -0,0 +1,10 @@
+// CS0023: The `?' operator cannot be applied to operand of type `T'
+// Line: 8
+
+class C
+{
+       static void Foo<T> (T t) where T : struct
+       {
+               var r = t?.ToString ();
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs0429-5.cs b/mcs/errors/cs0429-5.cs
deleted file mode 100644 (file)
index 1cc67a2..0000000
+++ /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/errors/cs0573-2.cs b/mcs/errors/cs0573-2.cs
new file mode 100644 (file)
index 0000000..443bed3
--- /dev/null
@@ -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 (file)
index 0000000..fd8de1e
--- /dev/null
@@ -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 (file)
index a62e6d1..0000000
+++ /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
new file mode 100644 (file)
index 0000000..c9c9e84
--- /dev/null
@@ -0,0 +1,16 @@
+// CS1736: The expression being assigned to optional parameter `s' must be a constant or default value
+// Line: 11
+
+struct S
+{
+       public S ()
+       {               
+       }
+}
+
+class X
+{
+       public void Foo (S s = new S ())
+       {
+       }
+}
\ No newline at end of file
index 37b93b7141ad11137f5d1d89f1b2e62caeece92e..37e1667db6f7fbf1fa13a1af2e48ef512a96829c 100644 (file)
@@ -976,8 +976,11 @@ namespace Mono.CSharp
 
                                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)
index 7ab8f746f5309cba33a02f1c96e3a47c457e2c6a..6dfe7b6ce6b6e47574e132822483c1b3b2e099af 100644 (file)
@@ -549,13 +549,10 @@ namespace Mono.CSharp
                        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 @@ namespace Mono.CSharp
                                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:
@@ -1066,7 +1059,7 @@ namespace Mono.CSharp
                                        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 +1221,7 @@ namespace Mono.CSharp
                                                instance_address = instance as LocalTemporary;
 
                                        if (instance_address == null) {
-                                               EmitLoad (ec);
+                                               EmitLoad (ec, false);
                                                ec.Emit (OpCodes.Dup);
                                                ec.EmitLoadFromPtr (instance.Type);
 
@@ -1236,11 +1229,8 @@ namespace Mono.CSharp
                                        } 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 +1240,9 @@ namespace Mono.CSharp
                                }
 
                                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 +1275,7 @@ namespace Mono.CSharp
                        }
                }
 
-               public void EmitLoad (EmitContext ec)
+               public void EmitLoad (EmitContext ec, bool boxInstance)
                {
                        var instance_type = instance.Type;
 
@@ -1313,8 +1306,9 @@ namespace Mono.CSharp
                        instance.Emit (ec);
 
                        // Only to make verifier happy
-                       if (RequiresBoxing ())
+                       if (boxInstance && RequiresBoxing ()) {
                                ec.Emit (OpCodes.Box, instance_type);
+                       }
                }
 
                public TypeSpec GetStackType (EmitContext ec)
@@ -1342,6 +1336,9 @@ namespace Mono.CSharp
                        return false;
                }
 
+               //
+               // Returns true for cheap race-free load, where we can avoid using dup
+               //
                bool IsInexpensiveLoad ()
                {
                        if (instance is Constant)
@@ -1351,8 +1348,10 @@ namespace Mono.CSharp
                                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;
index 2147c145e6c74151380ea0962a61fc614b5f359f..9647a4bd7e64a1f2407da61f5bde02a195dfe797 100644 (file)
@@ -1268,6 +1268,7 @@ namespace Mono.CSharp
                        int next_token;
                        int parens = 0;
                        int generics = 0;
+                       int brackets = 0;
 
                        var nt = xtoken ();
                        switch (nt) {
@@ -1333,6 +1334,11 @@ namespace Mono.CSharp
                                        ++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 @@ namespace Mono.CSharp
                                        int interrs = 1;
                                        int colons = 0;
                                        int braces = 0;
-                                       int brackets = 0;
                                        //
                                        // All shorcuts failed, do it hard way
                                        //
index 7c2537c8bc7b8cdd386cacf6ad18349d7d3bbed9..3143908b63accad973ddba473d1f532987e364e5 100644 (file)
@@ -457,6 +457,8 @@ namespace Mono.CSharp {
                                return false;
                        case MemberKind.InternalCompilerType:
                                return type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
+                       case MemberKind.TypeParameter:
+                               return !((TypeParameterSpec) type).IsValueType;
                        default:
                                return true;
                        }
@@ -1042,7 +1044,11 @@ namespace Mono.CSharp {
                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;
 
index c784f62d1c1506055b58f9a284b7c5affb94dfb2..6699377f8df408e355b889789f3a2ffce55cdd2d 100644 (file)
@@ -4601,7 +4601,15 @@ namespace Mono.CSharp
                                        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);
@@ -7275,11 +7283,11 @@ namespace Mono.CSharp
                }
 
                //
-               // 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);
                        }
                }
 
@@ -11134,6 +11142,9 @@ namespace Mono.CSharp
                        get {
                                return source;
                        }
+                       set {
+                               source = value;
+                       }
                }
 
                public override bool ContainsEmitWithAwait ()
index e857e365410152f1613f0675e5fc83ffae1f8b30..f3ed348c14fa910174e4322e61e0651f4e487ac5 100644 (file)
@@ -1220,12 +1220,6 @@ namespace Mono.CSharp.Nullable
                                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 @@ namespace Mono.CSharp.Nullable
                                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);
index 1a30ae384c07cc553f5bebb8936b9ba957828686..adac136fdc07b1600a751e9f0fef356b019541e8 100644 (file)
@@ -1418,7 +1418,7 @@ namespace Mono.CSharp {
 
                        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",
index e46dca447eb4696c322dae674237ffbb2bcc4e40..00d61eba2b764a6a5a53607bae1860b887ed2303 100644 (file)
@@ -5044,7 +5044,17 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       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)
index 2071b625c3a40ca8c51338cbaf98ede4ae7c6cca..2f5ea10ae8f4ecd1b3a4ce2e527d11fb98871ef9 100644 (file)
@@ -155,6 +155,11 @@ public class ConditionalParsing
                var e = b ? () => { } : a;
        }
 
+       void Test_19 (int[,] table)
+       {
+               var x = 1 > 0  ? table[5, 1] : 0;
+       }
+
        static void Helper<T> (T arg)
        {
        }
diff --git a/mcs/tests/gtest-625.cs b/mcs/tests/gtest-625.cs
new file mode 100644 (file)
index 0000000..d733a80
--- /dev/null
@@ -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
index b6109d943c30897d893570b37fcfa374fa59a3ed..42c12e9add6072614d1298455fb7639a671df2ac 100644 (file)
@@ -1,3 +1,4 @@
+// Compiler options: -langversion:experimental
 using System;
 
 struct S
index a73085684683372fdf28f2bf33c466a81e67d3a5..036d9c3a43a7666eacc175149d0a4459049ecd83 100644 (file)
@@ -1,3 +1,4 @@
+// Compiler options: -langversion:experimental
 struct S
 {
        public decimal P { get; } = -3;
diff --git a/mcs/tests/test-898.cs b/mcs/tests/test-898.cs
deleted file mode 100644 (file)
index 5b69403..0000000
+++ /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
index 44513478a80b080c641168389a5dd71c6e20065f..7dedb674dafaa35d46aef4ffef41b6aa8c531353 100644 (file)
@@ -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
index 2af641f84c22c1509171c7f832c59d051bcb5c8d..9a34e43877330b5289d2540deab93d90c18405ac 100644 (file)
@@ -1,3 +1,4 @@
+// Compiler options: -langversion:experimental
 using System;
 
 struct S1
diff --git a/mcs/tests/test-907.cs b/mcs/tests/test-907.cs
new file mode 100644 (file)
index 0000000..0a832c9
--- /dev/null
@@ -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/test-null-operator-010.cs b/mcs/tests/test-null-operator-010.cs
new file mode 100644 (file)
index 0000000..2d72403
--- /dev/null
@@ -0,0 +1,41 @@
+using System;
+
+class Test
+{
+       static void Main ()
+       {
+               Test_1 ("");
+               Test_1<object> (null);
+
+               Test_2<object> (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> (T x) where T : class
+       {
+               x?.Call ();
+       }
+
+       static void Test_2<T> (T x)
+       {
+               x?.Call ();
+       }
+
+       static void Test_3<T> (T[] x)
+       {
+               x[0]?.Call ();
+       }
+}
+
+static class Ext
+{
+       public static void Call<T> (this T t)
+       {
+               Console.WriteLine (typeof (T));
+       }
+}
index f2b2239fd4d9e9caf6526986999c4212e08dacb8..5b2eeaed8d5b7d595b28f855d1c20d4aeb9ac98b 100644 (file)
@@ -1,3 +1,4 @@
+// Compiler options: -langversion:experimental
 class Simple(int arg)
 {
        int Property { get; } = arg;
index 2e2fc7adbbeb87951fd9fe59ed179d07880d1da1..79a1c2991e7de9b8303f427583b1dc319c527c1a 100644 (file)
@@ -1,3 +1,5 @@
+// Compiler options: -langversion:experimental
+
 using System;
 
 struct S (int x)
index d423fd25a71703afc6880bdb7a4804f2c45d6de0..ca08bdcbbb12cd27124bfe3c960929147e4d6e01 100644 (file)
       <method name="Void &lt;Test_18&gt;m__1()" attrs="145">\r
         <size>2</size>\r
       </method>\r
+      <method name="Void Test_19(Int32[,])" attrs="129">\r
+        <size>11</size>\r
+      </method>\r
     </type>\r
   </test>\r
   <test name="gtest-410.cs">\r
       </method>\r
     </type>\r
   </test>\r
+  <test name="gtest-625.cs">\r
+    <type name="S">\r
+      <method name="Boolean op_True(System.Nullable`1[S])" attrs="2198">\r
+        <size>10</size>\r
+      </method>\r
+      <method name="Boolean op_False(System.Nullable`1[S])" attrs="2198">\r
+        <size>10</size>\r
+      </method>\r
+    </type>\r
+    <type name="P">\r
+      <method name="Void Main()" attrs="145">\r
+        <size>23</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="gtest-anontype-01.cs">\r
     <type name="Test">\r
       <method name="Int32 Main()" attrs="150">\r
   <test name="test-146.cs">\r
     <type name="Test">\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>355</size>\r
+        <size>352</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
   <test name="test-729.cs">\r
     <type name="Primes.MainClass">\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>149</size>\r
+        <size>146</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
       </method>\r
     </type>\r
   </test>\r
-  <test name="test-898.cs">\r
-    <type name="BoolArrayWithByteValues">\r
-      <method name="Int32 Foo(Boolean ByRef)" attrs="145">\r
-        <size>58</size>\r
-      </method>\r
-      <method name="Int32 Main()" attrs="145">\r
-        <size>191</size>\r
-      </method>\r
-      <method name="Void .ctor()" attrs="6278">\r
-        <size>7</size>\r
-      </method>\r
-      <method name="Boolean Ptr()" attrs="145">\r
-        <size>167</size>\r
-      </method>\r
-    </type>\r
-  </test>\r
   <test name="test-899.cs">\r
     <type name="Test">\r
       <method name="Void Main()" attrs="150">\r
   <test name="test-903.cs">\r
     <type name="C">\r
       <method name="S op_Implicit(C)" attrs="2198">\r
-        <size>18</size>\r
+        <size>30</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
       </method>\r
     </type>\r
     <type name="Program">\r
-      <method name="Void Main()" attrs="145">\r
-        <size>15</size>\r
-      </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
       </method>\r
+      <method name="Int32 Main()" attrs="145">\r
+        <size>155</size>\r
+      </method>\r
     </type>\r
   </test>\r
   <test name="test-904.cs">\r
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-907.cs">\r
+    <type name="MainClass">\r
+      <method name="Int32 Main()" attrs="150">\r
+        <size>37</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-91.cs">\r
     <type name="Abstract">\r
       <method name="Void .ctor()" attrs="6276">\r
     </type>\r
     <type name="Tester+&lt;ArrayAccessTest_1&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>338</size>\r
+        <size>335</size>\r
       </method>\r
     </type>\r
     <type name="Tester+&lt;ArrayAccessTest_2&gt;c__async1">\r
     </type>\r
     <type name="Tester+&lt;ArrayAccessTest_10&gt;c__async9">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>235</size>\r
+        <size>232</size>\r
       </method>\r
       <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-null-operator-010.cs">\r
+    <type name="Test">\r
+      <method name="Void Main()" attrs="145">\r
+        <size>79</size>\r
+      </method>\r
+      <method name="Void Test_1[T](T)" attrs="145">\r
+        <size>22</size>\r
+      </method>\r
+      <method name="Void Test_2[T](T)" attrs="145">\r
+        <size>21</size>\r
+      </method>\r
+      <method name="Void Test_3[T](T[])" attrs="145">\r
+        <size>28</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+    <type name="Ext">\r
+      <method name="Void Call[T](T)" attrs="150">\r
+        <size>17</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-null-operator-02.cs">\r
     <type name="CI">\r
       <method name="Int32 get_Prop()" attrs="2182">\r
index 6a7f39d90f3de38354b5d2f8721c0f9a8b12f9cb..b79dd7b886a96bee9efbf21a1ea07a8176236729 100644 (file)
@@ -64,6 +64,11 @@ namespace Xamarin.ApiDiff {
                        get { return ignoreAdded; }
                }
 
+               static List<Regex> ignoreNew = new List<Regex> ();
+               public static List<Regex> IgnoreNew {
+                       get { return ignoreNew; }
+               }
+
                static List<Regex> ignoreRemoved = new List<Regex> ();
                public static List<Regex> IgnoreRemoved {
                        get { return ignoreRemoved; }
@@ -83,11 +88,12 @@ namespace Xamarin.ApiDiff {
                        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 @@ namespace Xamarin.ApiDiff {
                                { "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 }
                        };
 
index bdf22fea4895b2917e0884e0d7d62a11457739f2..d96613c3e8ac69fe3a1a121e84fc4c7b6d0ed700 100644 (file)
@@ -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 @@ namespace Xamarin.ApiDiff {
 
                public override void Added (XElement target)
                {
-                       Output.WriteLine ("<h3>New Type {0}.{1}</h3>", State.Namespace, target.Attribute ("name").Value);
+                       string name = target.Attribute ("name").Value;
+                       if (State.IgnoreNew.Any (re => re.IsMatch (name)))
+                               return;
+                       Output.WriteLine ("<h3>New Type {0}.{1}</h3>", State.Namespace, name);
                        Output.WriteLine ("<pre>");
                        State.Indent = 0;
                        AddedInner (target);
index 7239385870eba9811c0caa90dafb70fa574b439e..427df66e6eb9cef2350288359f7226862dfe28ea 100644 (file)
@@ -26,6 +26,7 @@
 
 using System;
 using System.IO;
+using System.Linq;
 using System.Xml.Linq;
 
 namespace Xamarin.ApiDiff {
@@ -55,7 +56,11 @@ namespace Xamarin.ApiDiff {
 
                public override void Added (XElement target)
                {
-                       Output.WriteLine ("<h2>New Namespace {0}</h2>", target.Attribute ("name").Value);
+                       string name = target.Attribute ("name").Value;
+                       if (State.IgnoreNew.Any (re => re.IsMatch (name)))
+                               return;
+
+                       Output.WriteLine ("<h2>New Namespace {0}</h2>", name);
                        Output.WriteLine ();
                        // list all new types
                        foreach (var addedType in target.Element ("classes").Elements ("class"))
index 2dc4bcebb3d99ef9ce3a736184c98627b0dda979..a689210b12bbcd6a1a791cef41794be3e1a4378c 100644 (file)
@@ -545,6 +545,9 @@ namespace CorCompare
                        if (TypeHelper.IsDelegate(t))
                                return "delegate";
 
+                       if (t.IsPointer)
+                               return "pointer";
+
                        return "class";
                }
 
@@ -907,6 +910,8 @@ namespace CorCompare
                                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");
 
index ad24c3d2d4e2078d16d3c98a6e16b3d7317c2c03..3b7e698d6042ad2e857de4ee831e078ab76da462 100644 (file)
@@ -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 \
index 09763096e5592bb4d1ab98594760c1f2d95e9bea..842a4ae439f36136fbb90c5e5942dcf8b5d56cbb 100644 (file)
@@ -980,7 +980,7 @@ class MDocUpdater : MDocCommand
                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 @@ class MDocUpdater : MDocCommand
                                                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 @@ static class DocUtils {
                        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 @@ class ILFullMemberFormatter : MemberFormatter {
                                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 (file)
index 0000000..5d65c34
--- /dev/null
@@ -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 (file)
index 0000000..614b7b7
--- /dev/null
@@ -0,0 +1,63 @@
+<Type Name="MyClass" FullName="MyNamespace.MyClass">
+  <TypeSignature Language="C#" Value="public class MyClass" />
+  <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit MyClass extends System.Object" />
+  <AssemblyInfo>
+    <AssemblyName>DocTest-InternalInterface</AssemblyName>
+    <AssemblyVersion>0.0.0.0</AssemblyVersion>
+  </AssemblyInfo>
+  <Base>
+    <BaseTypeName>System.Object</BaseTypeName>
+  </Base>
+  <Interfaces />
+  <Docs>
+    <summary>To be added.</summary>
+    <remarks>To be added.</remarks>
+  </Docs>
+  <Members>
+    <Member MemberName=".ctor">
+      <MemberSignature Language="C#" Value="public MyClass ();" />
+      <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+      <MemberType>Constructor</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>0.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <Parameters />
+      <Docs>
+        <summary>To be added.</summary>
+        <remarks>To be added.</remarks>
+      </Docs>
+    </Member>
+    <Member MemberName="Bar">
+      <MemberSignature Language="C#" Value="public string Bar { get; set; }" />
+      <MemberSignature Language="ILAsm" Value=".property instance string Bar" />
+      <MemberType>Property</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>0.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <ReturnValue>
+        <ReturnType>System.String</ReturnType>
+      </ReturnValue>
+      <Docs>
+        <summary>To be added.</summary>
+        <value>To be added.</value>
+        <remarks>To be added.</remarks>
+      </Docs>
+    </Member>
+    <Member MemberName="BarMeth">
+      <MemberSignature Language="C#" Value="public void BarMeth ();" />
+      <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void BarMeth() cil managed" />
+      <MemberType>Method</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>0.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <ReturnValue>
+        <ReturnType>System.Void</ReturnType>
+      </ReturnValue>
+      <Parameters />
+      <Docs>
+        <summary>To be added.</summary>
+        <remarks>To be added.</remarks>
+      </Docs>
+    </Member>
+  </Members>
+</Type>
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 (file)
index 0000000..5b49f3c
--- /dev/null
@@ -0,0 +1,22 @@
+<Overview>
+  <Assemblies>
+    <Assembly Name="DocTest-InternalInterface" Version="0.0.0.0">
+      <Attributes>
+        <Attribute>
+          <AttributeName>System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints)</AttributeName>
+        </Attribute>
+        <Attribute>
+          <AttributeName>System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true)</AttributeName>
+        </Attribute>
+      </Attributes>
+    </Assembly>
+  </Assemblies>
+  <Remarks>To be added.</Remarks>
+  <Copyright>To be added.</Copyright>
+  <Types>
+    <Namespace Name="MyNamespace">
+      <Type Name="MyClass" Kind="Class" />
+    </Namespace>
+  </Types>
+  <Title>DocTest-InternalInterface</Title>
+</Overview>
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 (file)
index 0000000..bd8d431
--- /dev/null
@@ -0,0 +1,6 @@
+<Namespace Name="MyNamespace">
+  <Docs>
+    <summary>To be added.</summary>
+    <remarks>To be added.</remarks>
+  </Docs>
+</Namespace>
index c65bf23813c0ce954166d7595113fdf40ca6a3e7..cd78783513277ce3a1397ba97596704044f05d93 100644 (file)
@@ -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)
 {
@@ -1343,140 +1336,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;
index 8e4c0aa558bf78da73681abd60b9710033109243..99a62faeb1de6e302e57a99823fdba1545b7753c 100644 (file)
@@ -188,8 +188,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);
index bfa08c4d39c0c0205d76487ea9ece586bb28f4cb..335484ae676054522cb7b99975e7a95947ba7dfc 100644 (file)
@@ -124,6 +124,7 @@ common_sources = \
        icall.c                 \
        icall-def.h             \
        image.c                 \
+       jit-info.c              \
        loader.c                \
        locales.c               \
        locales.h               \
@@ -222,9 +223,6 @@ 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           \
@@ -271,7 +269,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)
index 3320820f87797e0583a2fe745a242e1f1a700b8f..090f2f7a1dc98e9296d02c829debb4cba317c11c 100644 (file)
@@ -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);
@@ -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)
 {
index 32b5ef4561ef6d3ac52cbb93f3fdf3c48f2ebb56..2bf904143f12df4e7d1c06810fdf907c89c91440 100644 (file)
@@ -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,
index 240792536d330ec81651be3dab69f25e0769067a..baa9565e8c94c4daa1820f020fefd5edf3b3da66 100644 (file)
@@ -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;
+                               }
                        }
                }
 
index 24989f49afdf023e2c9fe55de278998f64019a9a..065e0458fa20021d2210bf4f71b7aecd588f09e4 100644 (file)
@@ -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,19 @@ 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;
+
+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;
 
index 013e73b69109354957aa54b70fea69d06a39703b..e30c0345c0abae993f6e0394aae83b1719aedd7d 100755 (executable)
@@ -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,870 +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;
-}
-
-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)))
 
@@ -1306,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);
@@ -2098,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);
 
index f2e59acb8443d5aa8f78679d1017c47a8b9bf7aa..7b8836363f8a2a769b980d2a063e7d4567c398b2 100644 (file)
@@ -13,7 +13,6 @@
 #include <glib.h>
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/threads-types.h>
-#include <mono/metadata/sgen-conf.h>
 #include <mono/utils/gc_wrapper.h>
 
 typedef struct {
@@ -21,14 +20,7 @@ typedef struct {
        int major_gc_count;
        long long minor_gc_time;
        long long major_gc_time;
-#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
+       long long major_gc_time_concurrent;
 } GCStats;
 
 #define mono_domain_finalizers_lock(domain) mono_mutex_lock (&(domain)->finalizable_objects_hash_lock);
@@ -337,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;
index 03b182b99f4da6d4cbcc8640ce56e7c9032054e5..4e025385b766151c779ad1f45f1e5341234c4d5d 100644 (file)
@@ -1154,14 +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);
-#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_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent);
 
        mono_gc_base_init ();
 
@@ -1231,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;
index 103eb3c4230490ba81c24dfa376d3291fcfe98ec..257b8332f5f4ac9abaf33200788483a60daf44b7 100644 (file)
@@ -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/jit-info.c b/mono/metadata/jit-info.c
new file mode 100644 (file)
index 0000000..cc0b766
--- /dev/null
@@ -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 <config.h>
+#include <glib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <mono/metadata/gc-internal.h>
+
+#include <mono/utils/atomic.h>
+#include <mono/utils/mono-compiler.h>
+#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-membar.h>
+#include <mono/utils/mono-counters.h>
+#include <mono/utils/hazard-pointer.h>
+#include <mono/utils/mono-tls.h>
+#include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-threads.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/domain-internals.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/exception.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/mono-debug-debugger.h>
+#include <mono/metadata/mono-config.h>
+#include <mono/metadata/threads-types.h>
+#include <mono/metadata/runtime.h>
+#include <metadata/threads.h>
+#include <metadata/profiler-private.h>
+#include <mono/metadata/coree.h>
+
+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;
+       }
+}
index c283b7aae365d41de7992da0773e812e7388c806..c738d53654ef315d6035d05158b4c962725a5962 100644 (file)
@@ -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)
index 1e85012dd0fb002c192bb4b0c973ddfb8b02bcb1..c9e9e030b8c41354b5ddf2af83701ec657a40b3a 100644 (file)
@@ -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]);
                }
        }
 }
index 7a9d2258d12eae120e02b9ceb83e293625d3dec6..859fb69c55bf16d3e46548a37aeba73973c843e8 100644 (file)
@@ -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);
index 7208dadb6b99da6700a0db4041a2e5031e76977a..ccb064d4f180f2db73e5fce54802c500242a3b49 100644 (file)
@@ -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
 
index a2aa759293b742fa9fb342ecee505d4949476464..b9abf073f057b6bff0a1ddf21a1464150c2f24b9 100644 (file)
@@ -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);
index c9e0f8bf63bf27db907c41d4c8a460e6c848da1f..d7cc110aec6bbca2ac91b363582f40410cf1fba0 100644 (file)
 #include <mono/utils/strenc.h>
 #include <mono/utils/mono-proclib.h>
 #include <mono/io-layer/io-layer.h>
-#ifndef HAVE_GETPROCESSID
-#if defined(_MSC_VER) || defined(HAVE_WINTERNL_H)
-#include <winternl.h>
-#ifndef NT_SUCCESS
-#define NT_SUCCESS(status) ((NTSTATUS) (status) >= 0)
-#endif /* !NT_SUCCESS */
-#else /* ! (defined(_MSC_VER) || defined(HAVE_WINTERNL_H)) */
-#include <ddk/ntddk.h>
-#include <ddk/ntapi.h>
-#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 <mono/metadata/class-internals.h>
 
 #define LOGDEBUG(...)  
@@ -60,11 +49,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,
@@ -525,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};
@@ -891,14 +811,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 +865,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)
index c61eab99f7bf0e1ca51e417c4799a0223d39d807..65a562da72cc34b0aee2e9d3aae346f793beda71 100644 (file)
@@ -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;
 }
index d9a52e9b195bc77f0fdd509add23ba094a7644e4..3b0c3a3ec335e070449a21edf73a0e16c527ac53 100644 (file)
@@ -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 ()))
@@ -887,7 +896,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 +904,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 +920,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 {
index b86ec318c7cb8bfb0e2139c578deacf455b507c9..420dc96e47d64a32daae9252133c0ff82f336693 100644 (file)
 #ifndef __MONO_SGENARCHDEP_H__
 #define __MONO_SGENARCHDEP_H__
 
-#include <mono/utils/mono-sigcontext.h>
+#include <mono/utils/mono-context.h>
+
+/*
+ * 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)
 
 
 #elif defined(TARGET_X86)
 
-#include <mono/utils/mono-context.h>
-
 #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 <mono/utils/mono-context.h>
-
 #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
 
 /* 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 <mono/utils/mono-sigcontext.h>
-
 #ifdef __linux__
 #define REDZONE_SIZE    0
 #elif defined(__APPLE__)
 #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
 #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 <mono/utils/mono-context.h>
-
 #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__)
 
index 472244b6312045f10e9556230a79cc826e50c4dd..7ee7e07bee31616d3ee43a3e3cc6324be5e41acf 100644 (file)
@@ -687,9 +687,9 @@ LOOP_HEAD:
                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));
index 009d0f66ee21db9968bac99939eaf4be1a268c74..babee94026e53d11e6051985f860f06ef64faf02 100644 (file)
@@ -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
index adad2514d08dd2d54350ee2c7b9950aeb66b8320..21331c18f0605a54fab15a1215c080eb6184a74c 100644 (file)
@@ -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));
        }
 }
 
index 1387676c75858cb57b6c6a403fb0f00d78705c1e..113078c1839661299582ad983a02433d8d511e6b 100644 (file)
@@ -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"
 }
index c578a91cfb2b1516e3f2076c1b1a4f545498e62e..6da8f7290d9316d930e1320d7ff2dba0ce5a8b85 100644 (file)
@@ -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
index 366c7667778a06284f8f27ac2c0692fda29b6347..c06354dd95820cc933b215680774bdce3b5522ca 100644 (file)
@@ -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)
@@ -168,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++;      \
@@ -183,20 +187,13 @@ sgen_gc_descr_has_references (mword desc)
                void **_objptr = (void**)(obj); \
                gsize _bmap = (desc) >> 16;     \
                _objptr += OBJECT_HEADER_WORDS; \
-               { \
-                       int _index = GNUC_BUILTIN_CTZ (_bmap);          \
-                       _objptr += _index; \
-                       _bmap >>= (_index + 1);                         \
-                       HANDLE_PTR (_objptr, (obj));            \
-                       _objptr ++;                                                     \
-                       } \
-               while (_bmap) { \
+               do { \
                        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 {    \
@@ -258,15 +255,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;      \
index 890001a8cb27ad093d8c2ae19984c84b873d7eee..1364cc0a9e0398d13a60a92f5656228540e54acb 100644 (file)
@@ -285,12 +285,12 @@ 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;
 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;
@@ -347,6 +347,12 @@ 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);
+
+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;
 
@@ -387,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*
@@ -597,8 +609,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 {
@@ -627,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;
        }
@@ -689,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
@@ -857,36 +874,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;
        ScanObjectFunc scan_func = ctx.scan_func;
        GrayQueue *queue = ctx.queue;
 
-       if (max_objs == -1) {
-               for (;;) {
-                       GRAY_OBJECT_DEQUEUE (queue, &obj);
+       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, queue);
+                       scan_func (obj, desc, queue);
                }
-       } else {
-               int i;
-
-               do {
-                       for (i = 0; i != max_objs; ++i) {
-                               GRAY_OBJECT_DEQUEUE (queue, &obj);
-                               if (!obj)
-                                       return TRUE;
-                               SGEN_LOG (9, "Precise gray object scan %p (%s)", obj, safe_name (obj));
-                               scan_func (obj, queue);
-                       }
-               } while (max_objs < 0);
-               return FALSE;
-       }
+       } while (max_objs < 0);
+       return FALSE;
 }
 
 /*
@@ -919,6 +929,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;
 
@@ -988,6 +999,11 @@ 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);
+                               CANARIFY_SIZE (obj_size);
+                               CANARIFY_SIZE (obj_to_pin_size);
+                       }
                        search_start = (void*)((char*)search_start + obj_size);
                } while (search_start <= addr);
 
@@ -1013,8 +1029,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);
@@ -1033,7 +1050,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;
@@ -1076,20 +1093,13 @@ 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));
-       }
-       GRAY_OBJECT_ENQUEUE (queue, 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, sgen_obj_get_descriptor (object));
        binary_protocol_pin (object, (gpointer)LOAD_VTABLE (object), safe_object_get_size (object));
 
 #ifdef ENABLE_DTRACE
@@ -1109,7 +1119,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;
                        }
@@ -1120,13 +1130,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;
        }
 }
@@ -1264,7 +1274,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));
@@ -1735,6 +1746,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
@@ -1899,9 +1912,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;
@@ -1992,19 +2002,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)
 {
@@ -2075,19 +2072,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
@@ -2123,6 +2114,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 ();
@@ -2151,6 +2145,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;
        }
@@ -2192,7 +2190,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 ());
@@ -2201,13 +2199,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.
@@ -2220,18 +2211,18 @@ 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;
-       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);
 
@@ -2242,11 +2233,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 ();
@@ -2264,9 +2252,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);
 
@@ -2297,7 +2282,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);
@@ -2336,12 +2321,11 @@ 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);
-       }
+       /* FIXME: why is this here? */
+       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 ();
@@ -2386,19 +2370,11 @@ 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);
-       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);
 
@@ -2446,8 +2422,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);
@@ -2489,7 +2465,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, 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
@@ -2514,7 +2494,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) {
@@ -2577,7 +2556,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)
@@ -2633,7 +2612,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));
@@ -2692,11 +2671,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);
@@ -2738,13 +2712,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);
@@ -2825,7 +2794,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 ();
        }
@@ -2846,7 +2815,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) {
@@ -2997,8 +2966,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 +2979,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 +2997,16 @@ 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);
+       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);
 
@@ -3048,15 +3022,22 @@ 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);
        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 +3048,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;
        }
 
@@ -3078,6 +3063,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 ();
 
@@ -3097,6 +3085,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 (last_minor_collection_start_tv, last_minor_collection_end_tv);
+
        current_collection_generation = -1;
 
        return TRUE;
@@ -4272,6 +4263,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"
 }
 
@@ -4366,6 +4359,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)
 {
@@ -4547,7 +4559,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;
@@ -4617,6 +4628,8 @@ mono_gc_base_init (void)
        sgen_init_fin_weak_hash ();
        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));
@@ -4667,12 +4680,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-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 {
@@ -4680,16 +4687,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;
@@ -4731,26 +4728,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")) {
@@ -4841,10 +4818,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;
                        }
@@ -4868,7 +4841,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");
@@ -4889,12 +4862,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);
@@ -4920,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;
@@ -5011,6 +4976,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);
 
@@ -5040,6 +5009,7 @@ mono_gc_base_init (void)
                                fprintf (stderr, "  print-pinning\n");
                                fprintf (stderr, "  heap-dump=<filename>\n");
                                fprintf (stderr, "  binary-protocol=<filename>[:<file-size-limit>]\n");
+                               fprintf (stderr, "  nursery-canaries\n");
                                sgen_bridge_print_gc_debug_usage ();
                                fprintf (stderr, "\n");
 
@@ -5049,18 +5019,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);
 
@@ -5432,4 +5390,8 @@ mono_gc_register_finalizer_callbacks (MonoGCFinalizerCallbacks *callbacks)
        fin_callbacks = *callbacks;
 }
 
+
+
+
+
 #endif /* HAVE_SGEN_GC */
index 41a7151ba298036f67ae16c4dfedf13d0f0089ff..12121dc723f7dadc9fad2acce63e771cbe8f99a8 100644 (file)
@@ -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 {        \
@@ -323,77 +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)
-
-static inline MONO_ALWAYS_INLINE void
-GRAY_OBJECT_ENQUEUE (SgenGrayQueue *queue, char* obj)
-{
-#if defined(SGEN_GRAY_OBJECT_ENQUEUE) || 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))) {
-               sgen_gray_object_enqueue (queue, obj);
-       } else {
-               HEAVY_STAT (gc_stats.gray_queue_enqueue_fast_path ++);
-
-               *++queue->cursor = obj;
-#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)
-{
-#if defined(SGEN_GRAY_OBJECT_ENQUEUE) || SGEN_MAX_DEBUG_LEVEL >= 9
-       *obj = sgen_gray_object_enqueue (queue);
-#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))) {
-               *obj = sgen_gray_object_dequeue (queue);
-       } else {
-               HEAVY_STAT (gc_stats.gray_queue_dequeue_fast_path ++);
-
-               *obj = *queue->cursor--;
-#ifdef SGEN_HEAVY_BINARY_PROTOCOL
-               binary_protocol_gray_dequeue (queue, queue->cursor + 1, *obj);
-#endif
-       }
-#endif
-}
+#define SGEN_LOAD_VTABLE(addr) SGEN_POINTER_UNTAG_12 (*(void**)(addr))
 
 /*
 List of what each bit on of the vtable gc bits means. 
@@ -500,7 +461,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
@@ -537,7 +498,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;
 
@@ -600,7 +560,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 ());
@@ -634,10 +594,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 +629,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 +654,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);
@@ -775,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);
@@ -791,6 +747,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, !SGEN_POINTER_IS_TAGGED_1_OR_2 (vtable), "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
@@ -805,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;
@@ -834,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;
@@ -1000,7 +993,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 */
 
@@ -1168,6 +1160,37 @@ 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) 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);   \
+                       }
+
+#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__ */
index 2393cbabb147b679a2b177e9d7b149052f8389da..247608751fe5fe850fdf6feed51797cf503b2715 100644 (file)
 #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);
@@ -69,13 +78,13 @@ 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
 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);
@@ -88,9 +97,11 @@ 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)
 {
-       HEAVY_STAT (gc_stats.gray_queue_enqueue_slow_path ++);
+       GrayQueueEntry entry = { obj, desc };
+
+       HEAVY_STAT (stat_gray_queue_enqueue_slow_path ++);
 
        SGEN_ASSERT (9, obj, "enqueueing a null object");
        //sgen_check_objref (obj);
@@ -110,33 +121,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 ++);
+       HEAVY_STAT (stat_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 +157,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 +175,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,36 +190,25 @@ 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
 }
 
 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 ++;
@@ -221,6 +223,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)
 {
@@ -338,11 +355,23 @@ 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
 
        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
index 2dfea35a146438c13388f9b5dbbda59fc8d31861..c0ccd616bd7cebb1090739d92cf61a1f4688d73a 100644 (file)
  * 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,12 @@ typedef enum {
 } GrayQueueSectionState;
 #endif
 
+typedef struct _GrayQueueEntry GrayQueueEntry;
+struct _GrayQueueEntry {
+       char *obj;
+       mword desc;
+};
+
 /*
  * 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 +88,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 +97,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,13 +118,25 @@ 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)
+
+#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) MONO_INTERNAL;
-char* sgen_gray_object_dequeue (SgenGrayQueue *queue) 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;
+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,
@@ -133,4 +158,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 (stat_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 (stat_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 (stat_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
index a4674a2139d4c7180b260fc8b9eac8c9799cd121..14b11317096b03fce9987c4264258ad8fdfa18e3 100644 (file)
@@ -37,12 +37,23 @@ 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);                                   \
-               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);                                \
@@ -56,10 +67,14 @@ 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;
 
+#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-marksweep-fixed-par.c b/mono/metadata/sgen-marksweep-fixed-par.c
deleted file mode 100644 (file)
index 7c03e5b..0000000
+++ /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 (file)
index 3d08895..0000000
+++ /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-par.c b/mono/metadata/sgen-marksweep-par.c
deleted file mode 100644 (file)
index 5bc7805..0000000
+++ /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
index d3093385805edaa25a5ff909771384024d13818b..89806871343ac9bee593570dd242f006527331db 100644 (file)
 #include "metadata/sgen-memory-governor.h"
 #include "metadata/sgen-layout-stats.h"
 #include "metadata/gc-internal.h"
+#include "metadata/sgen-pointer-queue.h"
 
-#if !defined(SGEN_PARALLEL_MARK) && !defined(FIXED_HEAP)
 #define SGEN_HAVE_CONCURRENT_MARK
-#endif
 
 #define MS_BLOCK_SIZE  (16*1024)
 #define MS_BLOCK_SIZE_SHIFT    14
 #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.
  * 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,11 +80,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;
        MSBlockInfo *next_free;
@@ -104,34 +90,20 @@ 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_FOR_BLOCK_INFO(b)     ((b)->block)
 
-#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_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)))
 
-#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))
+#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 {                            \
@@ -163,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))
 
@@ -182,12 +154,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
@@ -202,33 +168,28 @@ 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 MSBlockInfo *all_blocks;
+static SgenPointerQueue allocated_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      }
+#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)
 
 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;
@@ -264,55 +225,12 @@ 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 ?      \
         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,44 +242,13 @@ 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)
 {
-       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);
 }
 
-#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 +327,6 @@ ms_free_block (void *block)
 
        SGEN_ATOMIC_ADD_P (num_empty_blocks, 1);
 }
-#endif
 
 //#define MARKSWEEP_CONSISTENCY_CHECK
 
@@ -459,30 +345,19 @@ 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)
-                               break;
-               }
-               g_assert (b == block);
+               /* the block must be in the allocated_blocks array */
+               g_assert (sgen_pointer_queue_find (&allocated_blocks, BLOCK_TAG (block)) != (size_t)-1);
        }
 }
 
 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 +372,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) {
@@ -540,12 +413,7 @@ 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
-#ifndef FIXED_HEAP
        MSBlockHeader *header;
-#endif
        MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references);
        char *obj_start;
        int i;
@@ -553,11 +421,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 +438,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
@@ -587,7 +449,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) {
@@ -598,21 +460,10 @@ 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
+       sgen_pointer_queue_add (&allocated_blocks, BLOCK_TAG (info));
 
        ++num_major_sections;
        return TRUE;
@@ -624,7 +475,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;
@@ -656,86 +507,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)
 {
@@ -743,11 +514,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;
@@ -859,24 +625,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);
@@ -891,7 +649,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;
 
@@ -952,7 +710,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);
@@ -979,11 +737,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);
@@ -1061,7 +819,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;
                                }
                        }
@@ -1073,30 +831,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);       \
@@ -1104,7 +862,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 ();                \
                }                                                       \
@@ -1122,170 +880,11 @@ 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"
 
-#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 {
-#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);
-
-               /* 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)
-#endif
-               {
-                       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;
-
-#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;
-                       }
-
-                       MS_PAR_MARK_OBJECT_AND_ENQUEUE (obj, block, 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));
-                       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,18 +892,13 @@ 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);
+                       MS_MARK_OBJECT_AND_ENQUEUE (obj, sgen_obj_get_descriptor (obj), block, queue);
                } else {
                        if (sgen_los_object_is_pinned (obj))
                                return;
@@ -1318,7 +912,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 ();
                }
        }
@@ -1362,7 +956,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;
                }
@@ -1390,9 +984,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 +1001,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 +1009,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)
@@ -1441,7 +1016,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))
@@ -1457,11 +1032,10 @@ 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));
                }
        }
 }
-#endif
 
 static void
 major_copy_or_mark_object_canonical (void **ptr, SgenGrayQueue *queue)
@@ -1475,6 +1049,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)
@@ -1487,7 +1062,6 @@ major_get_and_reset_num_major_objects_marked (void)
        return 0;
 #endif
 }
-#endif
 
 #include "sgen-major-scan-object.h"
 
@@ -1510,10 +1084,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;
        }
 }
@@ -1620,7 +1196,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);
@@ -1644,9 +1220,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;
@@ -1691,8 +1265,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.
@@ -1710,20 +1282,16 @@ 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));
-#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;
                }
-       }
+       } 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];
@@ -1869,18 +1437,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);
        }
@@ -1891,7 +1454,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 +1469,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 +1618,6 @@ major_have_computer_minor_collection_allowance (void)
                ++stat_major_blocks_freed_individual;
 #endif
        }
-#endif
 }
 
 static void
@@ -2065,7 +1626,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;
 }
@@ -2117,17 +1678,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 +1703,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"
                        );
@@ -2165,10 +1712,11 @@ static void
 major_iterate_live_block_ranges (sgen_cardtable_block_callback callback)
 {
        MSBlockInfo *block;
+       gboolean has_references;
 
-       FOREACH_BLOCK (block) {
-               if (block->has_references)
-                       callback ((mword)block->block, MS_BLOCK_SIZE);
+       FOREACH_BLOCK_HAS_REFERENCES (block, has_references) {
+               if (has_references)
+                       callback ((mword)MS_BLOCK_FOR_BLOCK_INFO (block), MS_BLOCK_SIZE);
        } END_FOREACH_BLOCK;
 }
 
@@ -2232,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
@@ -2241,15 +1790,15 @@ 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;
-               block_start = block->block;
+               block_start = MS_BLOCK_FOR_BLOCK_INFO (block);
 
                if (block_obj_size >= CARD_SIZE_IN_BYTES) {
                        guint8 *cards;
@@ -2377,7 +1926,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;
                                }
@@ -2392,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) {
-               guint8 *cards = sgen_card_table_get_card_scan_address ((mword) 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;
@@ -2423,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;
@@ -2433,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
 
@@ -2445,49 +1995,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
@@ -2500,29 +2007,12 @@ 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
-#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);
@@ -2548,10 +2038,6 @@ sgen_marksweep_fixed_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);
@@ -2563,33 +2049,20 @@ sgen_marksweep_fixed_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) {
                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;
@@ -2600,9 +2073,6 @@ sgen_marksweep_fixed_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;
index 187988e7def5fe723b6af95d294d87af839817ad..c18e49f16dd46c01180d2c6ceef6f0c4fb5df9e7 100644 (file)
@@ -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)
index 7a34dfd4ac34beb07c58a61e6f423c2543a633b8..3cff269a7da3d5bc65ceedcb658fe34461b2ad57 100644 (file)
@@ -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 {    \
@@ -100,10 +45,14 @@ PARALLEL_SCAN_VTYPE (char *start, mword desc, SgenGrayQueue *queue BINARY_PROTOC
        } 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;
 
+#ifdef HEAVY_STATISTICS
+       sgen_descriptor_count_scanned_object (desc);
+#endif
+
 #define SCAN_OBJECT_PROTOCOL
 #include "sgen-scan-object.h"
 
@@ -125,8 +74,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)
index d07203db4d1fd50606d6a30e7a4708a3f7dc3717..51b00e96695475d26176387342f33ba37ae13695 100644 (file)
@@ -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;
 
index 3d422e6b7b8aac5c8d9765bb61523a105ede4e44..01d1bd1a7960cc908c2da78769993a689e53e529 100644 (file)
@@ -782,12 +782,13 @@ 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);
+                       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);
index 42a588164df379f3827988052145f1590e7ceee2..4e2ba7b84d79053c215747c8d962fc7e5ee67d9d 100644 (file)
@@ -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));
index 909b8382c81e2863355d1f1f5e4c3c50a40b032f..9918d16adc58182836069bc29449f642c598c4e1 100644 (file)
@@ -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));
                }
index d91692d42e94dee71dd2ce0463341091b44dc0e9..71a8dbefebe0999513e55b4d083fd79e7d2665c9 100644 (file)
@@ -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 */
        }
 }
 
index 46db46536cdfe21a93fe2f29239caa82aa328197..19840beb646c4d2fb0ba2b66de4c6b6a332899cd 100644 (file)
@@ -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
index c645bdd8798c1ed0967f275f2988352051765169..3c1d8fb6c61d8d036a670924fd68f6c768984acb 100644 (file)
@@ -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,18 @@ 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)
+{
+       size_t i;
+       for (i = 0; i < queue->next_slot; ++i)
+               if (queue->data [i] == ptr)
+                       return i;
+       return (size_t)-1;
+}
+
 #endif
index 031870f1285a9900d38a97fb1d8547fc2b0d88d2..d972f3cc92e235f04cb200d33622846f9ed53bd8 100644 (file)
@@ -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
index 7cbe57a6c83e82f9c59d6dc7345120d2e2bf7540..ad569dda3595206fad7a2dd294c5040688b119c1 100644 (file)
  * 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".
+ *
+ * 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):
  *
 
 {
 #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)
@@ -97,7 +93,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
index f2f7066c3015cd39600027fbf558087d69fc7636..2cfb9d3211c0ee61f761c856ab1e2cda3ddda58f 100644 (file)
@@ -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;
index 1f62d14b703ffde9313db161f868f9f80adba1d1..87cc412c672371ed8609566a362359e4d0936bf3 100644 (file)
@@ -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-tagged-pointer.h b/mono/metadata/sgen-tagged-pointer.h
new file mode 100644 (file)
index 0000000..fc065f7
--- /dev/null
@@ -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
index 59013f70124aa832120f3c0a2216964bea45e1f4..5c6525e9ec71723050687a7e8e4c0fd577d140c5 100644 (file)
@@ -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"
 }
index b3eebb02d9ce3ea0f46461b81d2b893bb9972857..2d48745762b3b7fe21b29a48c2de3226d2b8ece7 100644 (file)
@@ -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
@@ -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;
@@ -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);
@@ -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;
@@ -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 ();
index 9070623673fc268eb8db724e7f10914d615a912e..d13c460967437a25387240f4bac000aae8735ac5 100644 (file)
@@ -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);
index 0927141e7925f92d753c6579aa0905c816131f22..22b1fbbbdb49a2aed23b58776bc07811f7c39496 100644 (file)
@@ -65,5 +65,12 @@ 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;
 }
+
+void
+ves_icall_System_String_InternalSetLength (MonoString *str, gint32 new_length)
+{
+       mono_gc_set_string_length (str, new_length);
+}
+
index a0b831a1e2006411eecc26190d60ca4df45c4f27..33bcf80378b006c177992070ddac209613660b34 100644 (file)
@@ -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_ */
index 39ade54daa14f83a12c5982a15be9d014e30f289..02acb073a8538c5011955c07b5264180bfcfb683 100644 (file)
@@ -41,6 +41,7 @@
 #include <unistd.h>
 #endif
 #include <string.h>
+#include <math.h>
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
 #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 */
@@ -83,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
@@ -127,12 +127,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;
-       gint64 averages [2];
+#if DEBUG
+       volatile gint32 njobs;
+#endif
+       volatile gint32 nexecuted;
        gboolean is_io;
 } ThreadPool;
 
@@ -148,6 +146,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);
@@ -163,6 +162,11 @@ 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;
+static MonoInternalThread *monitor_internal_thread;
+
 /* Hooks */
 static MonoThreadPoolFunc tp_start_func;
 static MonoThreadPoolFunc tp_finish_func;
@@ -656,6 +660,16 @@ 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);
+
+       if (InterlockedDecrement (&monitor_njobs) == 0)
+               monitor_state = MONITOR_STATE_FALLING_ASLEEP;
+
        return exc;
 }
 
@@ -757,21 +771,105 @@ signal_handler (int signo)
 }
 #endif
 
+#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;
+       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;
+       gint8 num_waiting_iterations = 0;
+
+       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;
@@ -791,26 +889,40 @@ 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];
-                       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 (&current, &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);
                }
        }
 }
@@ -878,6 +990,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 *
@@ -1014,6 +1130,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
@@ -1043,6 +1161,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 +1183,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;
 
@@ -1067,7 +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) {
-                       mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK);
+                       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
@@ -1078,14 +1203,18 @@ 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))
                        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 +1225,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);
 }
@@ -1309,84 +1442,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) {
-               if (tp->destroy_thread == 0 && InterlockedCompareExchange (&tp->destroy_thread, 1, 0) == 0)
-                       pulse_on_new_job (tp);
-       }
-}
-
 static gboolean
 should_i_die (ThreadPool *tp)
 {
@@ -1513,8 +1568,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);
@@ -1541,8 +1594,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) {
index 6aeca4acf5eadfa05b80ac8c0fce89c155d48280..860bb5b67e96bd9270d2ef3bf91d8b89835ed168 100644 (file)
@@ -40,8 +40,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 +52,8 @@ typedef LPTHREAD_START_ROUTINE WapiThreadStart;
 typedef struct _MonoInternalThread MonoInternalThread;
 
 typedef void (*MonoThreadCleanupFunc) (MonoInternalThread* thread);
+/* 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;
 
index b558395203660335d46f65509e15d1a59f6977ed..de4917ce08d41a7f879c0bcc5c0c9b89caa6f134 100644 (file)
@@ -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 */
@@ -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);
@@ -4658,6 +4662,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);
index dfc2b62e5603bdcfefa8291710a3d6ead48574d6..70e11b7730f483f97e20093d88d33800cdbca90e 100644 (file)
@@ -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
@@ -5003,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);
@@ -8885,6 +8891,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)
@@ -9011,7 +9019,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
                res = emit_llvm_file (acfg);
                if (!res)
-                       return FALSE;
+                       return 1;
        }
 #endif
 
index 213d5b56ab26711df37e99cd5300756dab8097ed..e9b5f42668a6b634bee63d6e68043e4c050669d1 100644 (file)
@@ -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:
@@ -1492,14 +1494,17 @@ 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) {
+               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 {
                /*
@@ -2339,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;
@@ -2450,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 */
@@ -2539,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;
@@ -2551,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);
@@ -2567,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;
@@ -2583,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;
@@ -2619,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];
@@ -2656,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;
 
@@ -3280,9 +3274,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;
index 431936113c35613cc15904147fbc8904ab575fa4..b31b368ec78550d7442a76009225d42d64bf7873 100644 (file)
@@ -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:24 dest:i clob:c
 
 # 32 bit opcodes
 int_add: dest:i src1:i src2:i len:4
index 58d66c88f482b9d8c0c2507ff42bda75250b288c..63e39501fe1e4dcdb43880f2f267ccf72402d713 100644 (file)
@@ -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 : "<null>"));
index 592969a5256e9f538531bc822d46d975140a3f88..a0865b7e2b68dcfce72c596b361a61eb3be8ab17 100644 (file)
@@ -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;
@@ -1025,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;
index 841b4580a6b4f246f560530e3f1a09639e41effc..615b3f2371f3788b2d96bf8c0f280f0e9ea63ae5 100755 (executable)
@@ -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) {
 
index cdf7b36ef68c95829e188f9d135fde4a3fb1f720..f350710c76e1b04e60e407212595aa47fe84b08b 100644 (file)
@@ -913,6 +913,7 @@ class Tests
                }
        }
 
+       [Category ("GSHAREDVT")]
        static int test_0_synchronized_gshared () {
                var c = new SyncClass<string> ();
                if (c.getInstance () != typeof (string))
@@ -1088,6 +1089,36 @@ class Tests
         var s = f2 (f);
                return s == "A" ? 0 : 1;
        }
+
+    public interface ICovariant<out R>
+    {
+    }
+
+    // Deleting the `out` modifier from this line stop the problem
+    public interface IExtCovariant<out R> : ICovariant<R>
+    {
+    }
+
+    public class Sample<R> : ICovariant<R>
+    {
+    }
+
+    public interface IMyInterface
+    {
+    }
+
+       public static int test_0_variant_cast_cache () {
+               object covariant = new Sample<IMyInterface>();
+
+               var foo = (ICovariant<IMyInterface>)(covariant);
+
+               try {
+                       var extCovariant = (IExtCovariant<IMyInterface>)covariant;
+                       return 1;
+               } catch {
+                       return 0;
+               }
+       }
 }
 
 #if !MOBILE
index 4db81265757801ae92d662fa5ffc5b912be484c3..6f757ff8e97afbcdf3a99c807b4f062746c25a0c 100755 (executable)
 
 #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)
                        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<T> (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)) {        \
@@ -4063,6 +4107,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.
  */
@@ -4662,6 +4733,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;
 
@@ -4766,6 +4839,9 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        }
 #endif
 
+       if (g_list_find (cfg->dont_inline, method))
+               return FALSE;
+
        return TRUE;
 }
 
@@ -5976,9 +6052,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;
@@ -5995,7 +6076,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);
 
@@ -6071,11 +6152,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;
 
@@ -6091,6 +6173,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) {
@@ -6145,6 +6228,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 
@@ -6201,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
@@ -6623,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;
 }
 
@@ -6820,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:
  *
@@ -6827,7 +6996,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;
@@ -6857,13 +7026,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;
@@ -6992,7 +7161,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)
@@ -7920,7 +8089,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 ())
@@ -8347,8 +8516,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;
 
@@ -8360,10 +8528,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 */
@@ -9529,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);
 
@@ -9563,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);
@@ -9605,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);
 
@@ -9629,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);
@@ -9674,58 +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 &&
-                                   !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)) {
-                                       int costs;
-
-                                       if ((costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, dont_inline, FALSE))) {
-                                               cfg->real_offset += 5;
-                                               bblock = cfg->cbb;
-
-                                               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 (cmethod, TRUE) ||
-                                                        !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) {
@@ -9733,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;
@@ -9754,23 +9844,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)) {
@@ -9783,14 +9858,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];
 
@@ -9844,13 +9918,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];
 
@@ -9889,23 +9962,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)) {
@@ -9917,13 +9975,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;
@@ -10144,7 +10201,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))
@@ -10205,12 +10262,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 {
@@ -10269,9 +10325,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;
@@ -11759,7 +11814,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))
@@ -11983,7 +12038,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);
@@ -12348,9 +12403,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                }
        }
 
-       g_slist_free (class_inits);
-       dont_inline = g_list_remove (dont_inline, method);
-
        if (inline_costs < 0) {
                char *mname;
 
@@ -12359,29 +12411,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);
-               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;
@@ -12389,9 +12429,12 @@ 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;
+       if (cfg->exception_type)
+               return -1;
+       else
+               return inline_costs;
 }
 
 static int
index 8a69db7f005571acf151d909bc8a5000ac38bec5..9317394473a1c4e9ba2c5300a4c78c6e702c2102 100755 (executable)
@@ -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
@@ -8178,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))
index 2a017149f1ff3539906c114bc7fd80bd46e5a433..ebd2638727b7b5ba04c3a42807e2dece11a4558d 100755 (executable)
@@ -276,67 +276,9 @@ typedef struct {
 
 #endif /* !HOST_WIN32 && !__native_client__ */
 
-#if defined (__APPLE__)
-
-#define MONO_ARCH_NOMAP32BIT
-
-#elif 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
-
-#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
-#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
-
-/* 
- * FreeBSD does not have MAP_32BIT, so code allocated by the code manager might not have a
- * 32 bit address.
- */
-#define MONO_ARCH_NOMAP32BIT
-
-#endif /* __FreeBSD__ */
+#if !defined(__linux__)
+#define MONO_ARCH_NOMAP32BIT 1
+#endif
 
 #ifdef HOST_WIN32
 #define MONO_AMD64_ARG_REG1 AMD64_RCX
@@ -355,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
@@ -376,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
@@ -396,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
index b644d7dca7a0ab20b6d2d6150c1de81cae6c66f4..9491a442d1a6f74175524297201d62292322bda8 100644 (file)
@@ -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:
index 7c3fd9ad0412e7af3f2b956764d546c4ad87726b..f22514b61ef3e58d2d6acbc1a1e4132e1ebc76c1 100644 (file)
@@ -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)
@@ -267,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
@@ -284,6 +282,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
index 5993ddddb63364b5b9834e3ea006d7260079572e..db4a1ce4b0c98834c4fd8cad0dd4f569c90c215a 100644 (file)
@@ -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
index d419bc26c728aaa2d9f100ff610ec629b50ce66c..15bb596d41418f5d683c71c98aaa276ea72ae6dc 100644 (file)
@@ -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__ */  
index c94f7c898f36c621c9b8286e562cba50fb84db01..d8d769130c4fc049ec242d90b650e55040a17865 100644 (file)
@@ -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
@@ -280,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)
 
index c3025a712e030cc21a894ad21e9cb97c73934a03..4b39b7ac2230065934bde90bf523b94f52998571 100644 (file)
@@ -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
 
@@ -192,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)
index 50b74c51fd9de7a315072acf8d89d8c198fe984f..b40425c647861be96ad3c1c0c6d9fa5475b8b929 100644 (file)
@@ -53,8 +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_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
index 4b9477845585d9a18e0d5efa1758b2b77e0bb1be..ab8e452b70e93292e1bced3f59298445fbc75cd2 100644 (file)
@@ -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)
index 4434564ee791c374fbce341e328e96b9e66842c3..d8f1e4298e956e681b2b67aeffe75750005c678a 100644 (file)
@@ -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.
index c7931e328ff6b032e4e3e5beb1862cdc2ac4f68d..5f589b258b8b1393229f1637569741eb7ea17926 100644 (file)
@@ -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;
index 05b977c547add58e58e20f6001998a6c6c4f24ba..f6ddc930427da887278d6b004076d4d0e52e40d5 100644 (file)
@@ -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;
 
@@ -220,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
@@ -249,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
index b489216a885814fb4df537f7a1fa869a67072dd4..6b4d8bfddad4da33b1c0fa13af219415364cdec8 100755 (executable)
@@ -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;
@@ -4326,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;
@@ -4351,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) {
@@ -4370,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;
@@ -4407,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);
 
@@ -4482,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;
@@ -4511,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));
@@ -4934,7 +4917,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)
@@ -5048,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;
@@ -5281,7 +5267,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) {
@@ -7274,6 +7260,43 @@ mini_free_jit_domain_info (MonoDomain *domain)
        domain->runtime_info = NULL;
 }
 
+#ifdef ENABLE_LLVM
+static gboolean
+llvm_init_inner (void)
+{
+       if (!mono_llvm_load (NULL))
+               return FALSE;
+
+       mono_llvm_init ();
+       return TRUE;
+}
+#endif
+
+/*
+ * 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)
 {
@@ -7394,13 +7417,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 (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
index 9200a64c3a5d78610d1d56a6f1594ffd664100ab..d507b960ef644c3e9f019596b42f33f285c9d387 100755 (executable)
 #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;
@@ -1425,8 +1426,6 @@ typedef struct {
        MonoGenericSharingContext gsctx;
        MonoGenericContext *gsctx_context;
 
-       gboolean gsharedvt;
-
        MonoGSharedVtMethodInfo *gsharedvt_info;
 
        /* Points to the gsharedvt locals area at runtime */
@@ -1523,6 +1522,9 @@ typedef struct {
        guint            has_atomic_cas_i4 : 1;
        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;
@@ -1539,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;
@@ -1613,6 +1617,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;
@@ -2202,6 +2207,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;
 
@@ -2291,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;
@@ -2463,7 +2470,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;
index bb500a7c0f505c954834f36b68c97deb7a424337..f9e651093b46e07958d0068840b5361de5487998 100644 (file)
@@ -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 */
 
index 58392b04acda1cd231f9ad617c0684cfbaeaf289..6268cadb4f09ff780579368c362807dc95d479de 100644 (file)
@@ -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
index ce0d65e74189bd049872cf8b414a8529a36f3348..24caf07cc133be4aa6d8ebdee53c9b05687e52c3 100644 (file)
@@ -301,6 +301,7 @@ public class TestRunner
                        lock (monitor) {
                                foreach (Process p in processes) {
                                        Console.WriteLine (process_data [p].test);
+                                       p.Kill ();
                                }
                        }
                        return 1;
index e8a6a27cc7b635612bb4a38d69d13e448d273589..d3c41ba44dfe7f456031042397428aaff66d51e4 100644 (file)
 #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)
index 619e574e424c509728ba2d009543f18557cacea9..3b01b49f0669d5f0abcd4c6ca1f010c59c26ea4b 100755 (executable)
@@ -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 <mono/arch/arm/arm-codegen.h>
+
 typedef struct {
        mgreg_t pc;
        mgreg_t regs [16];
index 3f032f9d22c321ff8bd4627d2459557c54c5756b..1303b5b4d448498e2d6afea298f4a5599b047e8b 100644 (file)
@@ -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;
index ce0e5be87ef8dd5d4e68572540d91cd5fe313eb4..9aa70ac20b0b442511afadf97dceedaf4b1302ce 100644 (file)
@@ -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;
@@ -734,10 +734,10 @@ 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__)
+#if defined(__arm__)
        return !disable_new_interrupt;
 #endif
        return FALSE;
index 0904216278062951537d7f157fe2668001c76891..ff0b717d53ae071966ca6e2650a922d5f756ac48 100644 (file)
@@ -3,6 +3,7 @@
 /al1
 /al2
 /caspol
+/cert-sync
 /cert2spc
 /certmgr
 /cccheck
index 0c690d3a35c4213b0746b82955c88b44bbb4f0e0..b6d74e1cb41832b4768000939b1050afb14e7b50 100644 (file)
 #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 */
 
 /*
 /* #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 */