Merge pull request #2763 from esdrubal/mono-symbolicate-standalone2
authorMarcos Henrich <marcoshenrich@gmail.com>
Wed, 30 Mar 2016 07:55:15 +0000 (08:55 +0100)
committerMarcos Henrich <marcoshenrich@gmail.com>
Wed, 30 Mar 2016 07:55:15 +0000 (08:55 +0100)
Mono-symbolicate standalone

187 files changed:
README.md
acceptance-tests/SUBMODULES.json
acceptance-tests/ms-test-suite.mk
acceptance-tests/roslyn.mk
configure.ac
docs/docs.make
external/referencesource
man/mono.1
mcs/build/Makefile
mcs/build/common/AssemblyRef.cs [new file with mode: 0644]
mcs/build/common/SR.cs
mcs/build/gensources.sh
mcs/class/Makefile
mcs/class/Microsoft.Build/Microsoft.Build.Execution/BuildManager.cs
mcs/class/Microsoft.Build/Microsoft.Build.Execution/ProjectInstance.cs
mcs/class/Microsoft.Build/Microsoft.Build.Internal/BuildNodeManager.cs
mcs/class/Mono.Security/Makefile
mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsProvider.cs
mcs/class/SMDiagnostics/Assembly/AssemblyInfo.cs
mcs/class/System.Data.Entity/System.Data.Entity.dll.sources
mcs/class/System.Data/mobile_System.Data.dll.sources
mcs/class/System.Data/net_4_x_System.Data.dll.sources
mcs/class/System.IO.Compression.FileSystem/Makefile
mcs/class/System.IO.Compression/Makefile
mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs
mcs/class/System.Runtime.Remoting/Makefile
mcs/class/System.Runtime.Remoting/xammac_net_4_5_System.Runtime.Remoting.dll.sources [new file with mode: 0644]
mcs/class/System.ServiceModel.Internals/System.ServiceModel.Internals.dll.sources
mcs/class/System.ServiceModel.Internals/mobile_System.ServiceModel.Internals.dll.sources
mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddress10.cs
mcs/class/System.ServiceModel/System.ServiceModel_test.dll.sources
mcs/class/System.ServiceModel/Test/System.ServiceModel/Bug36080Test.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Handlers/AssemblyResourceLoader.cs
mcs/class/System.XML/Assembly/AssemblyInfo.cs
mcs/class/System.XML/System.Xml.dll.sources
mcs/class/System.XML/mobile_System.Xml.dll.sources
mcs/class/System/Mono.Net.Security/ChainValidationHelper.cs
mcs/class/System/Mono.Net.Security/MonoTlsStream.cs
mcs/class/System/Mono.Net.Security/SystemCertificateValidator.cs
mcs/class/System/System.Diagnostics/DefaultTraceListener.cs
mcs/class/System/System.Diagnostics/Process.cs
mcs/class/System/System.Net.Sockets/SafeSocketHandle.cs
mcs/class/System/System.Net/HttpListenerRequest.cs
mcs/class/System/System.Net/ServicePoint.cs
mcs/class/System/System.Net/WebConnection.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X500DistinguishedName.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs [new file with mode: 0644]
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs [new file with mode: 0644]
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Chain.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImpl.cs [new file with mode: 0644]
mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs [new file with mode: 0644]
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs [new file with mode: 0644]
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Store.cs
mcs/class/System/System.dll.sources
mcs/class/System/Test/System.Net/HttpListener2Test.cs
mcs/class/System/Test/System.Net/HttpListenerRequestTest.cs
mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X509Certificate2Test.cs
mcs/class/System/mobile_System.dll.sources
mcs/class/corlib/Assembly/AssemblyInfo.cs
mcs/class/corlib/System.IO/FileInfo.cs
mcs/class/corlib/System.Runtime.InteropServices/RuntimeEnvironment.cs [deleted file]
mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Certificate.cs
mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509CertificateImpl.cs
mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509CertificateImplMono.cs
mcs/class/corlib/System/Console.cs
mcs/class/corlib/Test/System.IO/FileInfoTest.cs
mcs/class/corlib/corlib.dll.sources
mcs/mcs/constant.cs
mcs/mcs/settings.cs
mcs/tests/Makefile
mcs/tests/test-nameof-05.cs
mcs/tests/ver-il-net_4_x.xml
mcs/tools/cil-stringreplacer/Makefile
mcs/tools/cil-stringreplacer/cil-stringreplacer.cs
mcs/tools/cil-stringreplacer/cil-stringreplacer.csproj [new file with mode: 0644]
mcs/tools/cil-stringreplacer/cil-stringreplacer.exe.sources
mcs/tools/compiler-tester/compiler-tester.cs
mcs/tools/corcompare/Makefile
mcs/tools/csharp/getline.cs
mcs/tools/csharp/repl.cs
mcs/tools/gacutil/driver.cs
mcs/tools/linker/Makefile
mcs/tools/sqlmetal/Makefile
mono/metadata/appdomain.c
mono/metadata/appdomain.h
mono/metadata/class-internals.h
mono/metadata/class.c
mono/metadata/cominterop.c
mono/metadata/console-unix.c
mono/metadata/domain.c
mono/metadata/exception.c
mono/metadata/handle.h
mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/image.c
mono/metadata/loader.c
mono/metadata/marshal.c
mono/metadata/metadata.c
mono/metadata/mono-basic-block.c
mono/metadata/mono-basic-block.h
mono/metadata/object-internals.h
mono/metadata/object.c
mono/metadata/object.h
mono/metadata/reflection-internals.h
mono/metadata/reflection.c
mono/metadata/reflection.h
mono/metadata/remoting.c
mono/metadata/sgen-bridge.c
mono/metadata/sgen-client-mono.h
mono/metadata/sgen-mono.c
mono/metadata/sgen-new-bridge.c
mono/metadata/sgen-old-bridge.c
mono/metadata/socket-io.c
mono/metadata/threadpool-ms-io.c
mono/metadata/threadpool-ms.c
mono/metadata/threadpool-ms.h
mono/metadata/verify.c
mono/mini/Makefile.am.in
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/debugger-agent.c
mono/mini/dwarfwriter.c
mono/mini/dwarfwriter.h
mono/mini/exceptions-amd64.c
mono/mini/exceptions-arm.c
mono/mini/exceptions-ia64.c
mono/mini/exceptions-mips.c
mono/mini/exceptions-ppc.c
mono/mini/exceptions-s390x.c
mono/mini/exceptions-sparc.c
mono/mini/exceptions-x86.c
mono/mini/genmdesc.c
mono/mini/gshared.cs
mono/mini/image-writer.c
mono/mini/jit-icalls.c
mono/mini/method-to-ir.c
mono/mini/mini-amd64.c
mono/mini/mini-arm.c
mono/mini/mini-exceptions.c
mono/mini/mini-llvm.c
mono/mini/mini-runtime.c
mono/mini/mini-trampolines.c
mono/mini/mini-windows.c
mono/mini/mini-x86.c
mono/mini/tramp-arm.c
mono/mini/unwind.c
mono/mini/xdebug.c
mono/sgen/Makefile.am
mono/sgen/sgen-array-list.c [new file with mode: 0644]
mono/sgen/sgen-array-list.h [new file with mode: 0644]
mono/sgen/sgen-cardtable.c
mono/sgen/sgen-cardtable.h
mono/sgen/sgen-client.h
mono/sgen/sgen-gc.c
mono/sgen/sgen-gc.h
mono/sgen/sgen-gchandles.c
mono/sgen/sgen-los.c
mono/sgen/sgen-marksweep-drain-gray-stack.h
mono/sgen/sgen-marksweep-scan-object-concurrent.h [deleted file]
mono/sgen/sgen-marksweep.c
mono/sgen/sgen-minor-scan-object.h
mono/sgen/sgen-pinning.c
mono/sgen/sgen-pinning.h
mono/sgen/sgen-thread-pool.c
mono/sgen/sgen-thread-pool.h
mono/sgen/sgen-workers.c
mono/sgen/sgen-workers.h
mono/tests/Makefile.am
mono/tests/appdomain-unload.cs
mono/tests/assembly-load-remap.cs
mono/tests/libtest.c
mono/tests/pinvoke3.cs
mono/tests/test-runner.cs
mono/utils/checked-build.c
mono/utils/checked-build.h
mono/utils/mono-error-internals.h
mono/utils/mono-error.c
mono/utils/mono-memory-model.h
mono/utils/mono-rand.c
mono/utils/mono-signal-handler.h
mono/utils/mono-threads-coop.c
mono/utils/mono-threads-state-machine.c
msvc/libmonoruntime.vcxproj
runtime/Makefile.am
scripts/.gitignore
scripts/Makefile.am

index 7a7f3639f28ccefebc994e5d5f03cb0ae41f2ce1..d3ff65bda20411879d323a6aa9e14d4c38efbcfa 100644 (file)
--- a/README.md
+++ b/README.md
@@ -104,6 +104,8 @@ See the man pages for mono(1), mcs(1) and monodis(1) for further details.
 Directory Roadmap
 =================
 
+* `acceptance-tests/` - Optional third party test suites used to validate Mono against a wider range of test cases.
+
 * `data/` - Configuration files installed as part of the Mono runtime.
 
 * `docs/` - Technical documents about the Mono runtime.
index 9bb324948f7574a942bc284d9c46aeecfc593445..7a9de16bc374515f3f926267bfcfc27645a232cd 100644 (file)
@@ -18,7 +18,7 @@
   {
     "name": "ms-test-suite", 
     "url": "git@github.com:xamarin/ms-test-suite.git", 
-    "rev": "1ab0d4972937bf0451fc164f39a67475776a9edf", 
+    "rev": "4a95604fdf2c0523e68eaad64a17d22eebb051b3", 
     "remote-branch": "origin/master", 
     "branch": "master", 
     "directory": "ms-test-suite"
index 05f99482a28f1634fac2c37860d06136fe33328a..c1c16199481352d873f6df2c7a077a43197dcbe3 100644 (file)
@@ -1,9 +1,10 @@
 check-ms-test-suite:
        @if $(MAKE) validate-ms-test-suite RESET_VERSIONS=1; then \
-               $(MAKE) -C $(MSTESTSUITE_PATH)/conformance build MCS="$(MCS) -t:library -warn:1 -r:nunit.framework"; \
-               $(MAKE) -C $(MSTESTSUITE_PATH)/conformance run NUNIT-CONSOLE="$(RUNTIME) $(CLASS)/nunit-console.exe -nologo -exclude=MonoBug,BadTest" NUNIT_XML_RESULT=$(abs_top_builddir)/acceptance-tests/TestResult-ms-test-suite-conformance.xml; \
-               $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup build MCS="$(MCS) -debug -warn:1"; \
-               $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup run MONO="$(RUNTIME)"; \
+               $(MAKE) -C $(MSTESTSUITE_PATH)/conformance build MCS="$(MCS) -t:library -warn:1 -r:nunit.framework" && \
+               $(MAKE) -C $(MSTESTSUITE_PATH)/conformance run NUNIT-CONSOLE="$(RUNTIME) $(CLASS)/nunit-console.exe -nologo -exclude=MonoBug,BadTest" NUNIT_XML_RESULT=$(abs_top_builddir)/acceptance-tests/TestResult-ms-test-suite-conformance.xml || EXIT_CODE=1; \
+               $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup build MCS="$(MCS) -debug -warn:1" && \
+               $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup run MONO="$(RUNTIME)" || EXIT_CODE=1; \
+               exit $$EXIT_CODE; \
        else \
                echo "*** [ms-test-suite] Getting the repository failed, you probably don't have access to this Xamarin-internal resource. Skipping."; \
        fi
\ No newline at end of file
index e20b01e4979a0c05a239578a0d5bd6cb1af5fa32..17e0e4ce67580a5f3a762dbd89ca5d8bb8ab667f 100644 (file)
@@ -19,5 +19,6 @@ check-roslyn:
        cd $(ROSLYN_PATH); \
        sed -i -e 'N; s/bootstrapArg=".*\n.*"/bootstrapArg=""/g' cibuild.sh; \
        sed -i -e 's#-xml Binaries/\$$BUILD_CONFIGURATION/xUnitResults/#-nunit $(abs_top_builddir)/acceptance-tests/TestResult-#g' cibuild.sh; \
-       ./cibuild.sh --mono-path $$PREFIX/bin; \
-       sed -i -e 's/\\4.5"/\\4.5-api"/g' $$PREFIX/lib/mono/xbuild-frameworks/.NETFramework/v4.5/RedistList/FrameworkList.xml;
+       ./cibuild.sh --mono-path $$PREFIX/bin || EXIT_CODE=1; \
+       sed -i -e 's/\\4.5"/\\4.5-api"/g' $$PREFIX/lib/mono/xbuild-frameworks/.NETFramework/v4.5/RedistList/FrameworkList.xml; \
+       exit $$EXIT_CODE
index bf0e910961bee936d8a8ccaea91b02d2472813ae..5d9bfe8244ff44f3ca0394fb766ab3b9c7fe4d75 100644 (file)
@@ -3583,35 +3583,34 @@ AC_ARG_WITH(cooperative_gc, [  --with-cooperative-gc=yes|no      Enable cooperat
        fi
 ], [with_cooperative_gc=no])
 
-AC_ARG_WITH(checked_build, [  --with-checked-build=yes|no      Enable checked build (expensive asserts)) (defaults to no)],[
-       if test x$with_checked_build != xno ; then
-               AC_DEFINE(CHECKED_BUILD,1,[Enable checked build.])
-       fi
-], [with_checked_build=no])
+AC_ARG_ENABLE(checked_build, [  --enable-checked-build=LIST      To enable checked build (expensive asserts), configure with a comma-separated LIST of checked build modules and then include that same list in the environment variable MONO_CHECK_MODE at runtime. Recognized checked build modules: all, gc, metadata, thread],[
 
-if test x$with_checked_build != xno ; then
-       DISABLED_CHECKED_BUILD_TEST=none
+       if test x$enable_checked_build != x ; then
+               AC_DEFINE(ENABLE_CHECKED_BUILD,1,[Enable checked build])
+       fi
+       for feature in `echo "$enable_checked_build" | sed -e "s/,/ /g"`; do
+               eval "mono_checked_build_test_enable_$feature='yes'"
+       done
 
-       AC_ARG_ENABLE(checked_build_test, [  --enable-checked-build-test=LIST      drop support for LIST checked build tests. LIST is a comma-separated list from: gc, metadata, thread.],
-       [
-               for feature in `echo "$enable_checked_build_test" | sed -e "s/,/ /g"`; do
-                       eval "mono_checked_build_test_disable_$feature='yes'"
-               done
-               DISABLED_CHECKED_BUILD_TEST=$enable_checked_build_test
-       ],[])
+       if test "x$mono_checked_build_test_enable_all" = "xyes"; then
+               eval "mono_checked_build_test_enable_gc='yes'"
+               eval "mono_checked_build_test_enable_metadata='yes'"
+               eval "mono_checked_build_test_enable_thread='yes'"
+       fi
 
-       if test "x$mono_checked_build_test_disable_gc" = "xyes"; then
-               AC_DEFINE(DISABLE_CHECKED_BUILD_GC, 1, [Disable GC checked build])
+       if test "x$mono_checked_build_test_enable_gc" = "xyes"; then
+               AC_DEFINE(ENABLE_CHECKED_BUILD_GC, 1, [Enable GC checked build])
        fi
 
-       if test "x$mono_checked_build_test_disable_metadata" = "xyes"; then
-               AC_DEFINE(DISABLE_CHECKED_BUILD_METADATA, 1, [Disable metadata checked build])
+       if test "x$mono_checked_build_test_enable_metadata" = "xyes"; then
+               AC_DEFINE(ENABLE_CHECKED_BUILD_METADATA, 1, [Enable metadata checked build])
        fi
 
-       if test "x$mono_checked_build_test_disable_thread" = "xyes"; then
-               AC_DEFINE(DISABLE_CHECKED_BUILD_THREAD, 1, [Disable thread checked build])
+       if test "x$mono_checked_build_test_enable_thread" = "xyes"; then
+               AC_DEFINE(ENABLE_CHECKED_BUILD_THREAD, 1, [Enable thread checked build])
        fi
-fi
+
+], [])
 
 AC_CHECK_HEADER([malloc.h], 
                [AC_DEFINE([HAVE_USR_INCLUDE_MALLOC_H], [1], 
index 4f2d964e5b93f89ff144f23bd9c4180869f9bf89..c19ba5c33758cc2e935f459b907e8b3d22736a4a 100644 (file)
@@ -13,10 +13,10 @@ ASSEMBLED_DOCS = \
        monoapi.tree monoapi.zip
 
 convert.exe: $(srcdir)/convert.cs AgilityPack.dll
-       $(CSCOMPILE) -out:$@ $< -r:AgilityPack.dll
+       $(CSCOMPILE) -r:System.Xml.dll -out:$@ $< -r:AgilityPack.dll
 
 AgilityPack.dll:
-       $(CSCOMPILE) -target:library -out:$@ $(srcdir)/HtmlAgilityPack/*.cs
+       $(CSCOMPILE) -r:System.dll -r:System.Xml.dll -target:library -out:$@ $(srcdir)/HtmlAgilityPack/*.cs
 
 monoapi.zip: monoapi.tree
        @test -f $@ || { rm -f $< && $(MAKE) $<; }
index f6109ff2bc79dcb052b61239a78870a866bcd42c..6c6e36218c4a0b6dfb85bd27fa6746467761e8a0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f6109ff2bc79dcb052b61239a78870a866bcd42c
+Subproject commit 6c6e36218c4a0b6dfb85bd27fa6746467761e8a0
index f29f4d1601ee83055ad10cd9599067f4042107ab..a3829ae79a54741d8f8d047999c82b9977c6c923 100644 (file)
@@ -1094,11 +1094,6 @@ find spots that need to be tuned for this mode of operation.   Alternatively,
 this mode can be enabled at compile time by using the --with-cooperative-gc
 flag when calling configure.
 .TP
-\fBMONO_ENABLE_SHM\fR
-Unix only: Enable support for cross-process handles.  Cross-process
-handles are used to expose process handles, thread handles, named
-mutexes, named events and named semaphores across Unix processes.
-.TP
 \fBMONO_ENV_OPTIONS\fR
 This environment variable allows you to pass command line arguments to
 a Mono process through the environment.   This is useful for example
index 8048c5fdf3beb54fe2bdcdd761616bf177795d5b..f33fcccf2d7635f498496404d5ed0dbadd8f1d56 100644 (file)
@@ -28,7 +28,8 @@ COMMON_SRCS = \
        Locale.cs                       \
        MonoTODOAttribute.cs \
        basic-profile-check.cs          \
-       SR.cs
+       SR.cs   \
+       AssemblyRef.cs
 
 DISTFILES = \
        README.makefiles                \
diff --git a/mcs/build/common/AssemblyRef.cs b/mcs/build/common/AssemblyRef.cs
new file mode 100644 (file)
index 0000000..a38d371
--- /dev/null
@@ -0,0 +1,25 @@
+static class AssemblyRef
+{
+       // FIXME
+       internal const string SystemConfiguration = "System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
+       internal const string System = "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
+
+       public const string EcmaPublicKey = "b77a5c561934e089";
+#if NET_2_1
+       public const string FrameworkPublicKeyFull = "0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9";
+       public const string FrameworkPublicKeyFull2 = "00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB";
+#else
+       public const string FrameworkPublicKeyFull = "00000000000000000400000000000000";
+       public const string FrameworkPublicKeyFull2 = "00000000000000000400000000000000";
+#endif
+       public const string MicrosoftPublicKey = "b03f5f7f11d50a3a";
+       public const string MicrosoftJScript = Consts.AssemblyMicrosoft_JScript;
+       public const string MicrosoftVSDesigner = Consts.AssemblyMicrosoft_VSDesigner;
+       public const string SystemData = Consts.AssemblySystem_Data;
+       public const string SystemDesign = Consts.AssemblySystem_Design;
+       public const string SystemDrawing = Consts.AssemblySystem_Drawing;
+       public const string SystemWeb = Consts.AssemblySystem_Web;
+       public const string SystemWebExtensions =  "System.Web.Extensions, Version=" + Consts.FxVersion + ", Culture=neutral, PublicKeyToken=31bf3856ad364e35";
+       public const string SystemWindowsForms = Consts.AssemblySystem_Windows_Forms;
+}
\ No newline at end of file
index 836910f2ecf21ac2833f2f601287dd061b5e12ca..0685edb53bca0127edb3c2ef8f5847a7dfc2498f 100644 (file)
@@ -1,31 +1,5 @@
 using System.Globalization;
 
-static class AssemblyRef
-{
-       // FIXME
-       internal const string SystemConfiguration = "System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
-       internal const string System = "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
-
-       public const string EcmaPublicKey = "b77a5c561934e089";
-#if NET_2_1
-       public const string FrameworkPublicKeyFull = "0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9";
-       public const string FrameworkPublicKeyFull2 = "00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB";
-#else
-       public const string FrameworkPublicKeyFull = "00000000000000000400000000000000";
-       public const string FrameworkPublicKeyFull2 = "00000000000000000400000000000000";
-#endif
-       public const string MicrosoftPublicKey = "b03f5f7f11d50a3a";
-       public const string MicrosoftJScript = Consts.AssemblyMicrosoft_JScript;
-       public const string MicrosoftVSDesigner = Consts.AssemblyMicrosoft_VSDesigner;
-       public const string SystemData = Consts.AssemblySystem_Data;
-       public const string SystemDesign = Consts.AssemblySystem_Design;
-       public const string SystemDrawing = Consts.AssemblySystem_Drawing;
-       public const string SystemWeb = Consts.AssemblySystem_Web;
-       public const string SystemWebExtensions =  "System.Web.Extensions, Version=" + Consts.FxVersion + ", Culture=neutral, PublicKeyToken=31bf3856ad364e35";
-       public const string SystemWindowsForms = Consts.AssemblySystem_Windows_Forms;
-}
-
 static partial class SR
 {
        internal static string GetString(string name, params object[] args)
index 2eb4995bdd80c6569867178350c70fdaad71a2b6..14a0a01db59d07b4503b9a5d1ae8882e25442524 100644 (file)
@@ -43,7 +43,7 @@ sort -u $outfile.inc > $outfile.inc_s
 rm -f $outfile.inc
 
 
-if test -n "$excfile"; then
+if test -n "$excfile" -a -f "$excfile"; then
     process_includes $excfile $outfile.exc
 fi
 
index ee6e39dcc86cb40c84c98bcbdc0d8f55beacdf35..6bf570842e7757c2ba86d3e6c1a7bbe7b90ba30d 100644 (file)
@@ -14,7 +14,9 @@ build_SUBDIRS :=  \
        System.XML \
        System Mono.Security \
        Mono.Posix \
-       System.Core
+       System.Core \
+       Mono.Cecil \
+       Mono.Cecil.Mdb
 
 pcl_facade_dirs := Facades
 
index bd3c641856d7cd133f9488a37de707a989fff58c..c295d3ba67f30a6ead7b70938f594380a009c5f6 100644 (file)
@@ -54,7 +54,8 @@ namespace Microsoft.Build.Execution
                
                public void Dispose ()
                {
-                       WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
+                       if (submissions.Count > 0)
+                               WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
                        BuildNodeManager.Stop ();
                }
 
index d4414a9b8a5da54340028545decaf7a2ce21c9b4..64cfacd9a49d4b57e4e7db27609369035deda62c 100644 (file)
@@ -427,6 +427,7 @@ namespace Microsoft.Build.Execution
                        };
                        var requestData = new BuildRequestData (this, targets ?? DefaultTargets.ToArray ());
                        var result = manager.Build (parameters, requestData);
+                       manager.Dispose ();
                        targetOutputs = result.ResultsByTarget;
                        return result.OverallResult == BuildResultCode.Success;
                }
index ebfad5ba752ff0ec11cd51eb452d64bb8a186b62..322006a4e849fadd25b24ad978fb62530d9fe27e 100644 (file)
@@ -41,7 +41,10 @@ namespace Microsoft.Build.Internal
                public BuildNodeManager (BuildManager buildManager)
                {
                        BuildManager = buildManager;
-                       new Thread (RunLoop).Start ();
+                       new Thread (RunLoop) {
+                               IsBackground = true,
+                               Name = "xbuild request handler"
+                       }.Start ();
                }
 
                ~BuildNodeManager ()
index d0e7294f80f06e2087f936e029f71a4711d9988b..8a873fa9a47f0ca2085f41ca0a1e712ce04a1b3b 100644 (file)
@@ -21,5 +21,5 @@ EXTRA_DISTFILES = Mono.Security.Interface/README.md
 
 #
 # Update this comment to trigger a build in System
-# +2
+# +3
 #
index 753cd97e5a23952166c2f74f6effd7524a407c6d..8b7c6ddecfc28a375c64139d08d003fb67f6a2ce 100644 (file)
@@ -144,7 +144,7 @@ namespace Mono.Security.Interface
                 */
                public virtual bool InvokeSystemCertificateValidator (
                        ICertificateValidator validator, string targetHost, bool serverMode,
-                       X509CertificateCollection certificates, X509Chain chain, out bool success,
+                       X509CertificateCollection certificates, ref X509Chain chain, out bool success,
                        ref MonoSslPolicyErrors errors, ref int status11)
                {
                        success = false;
index e83ceb3e1d1990375796bb3cb5ab9a33141ae120..561d2fef4b2a656d5dde288fab45d8d9ca8cdd83 100644 (file)
@@ -48,7 +48,6 @@ using System.Runtime.InteropServices;
 [assembly: ComCompatibleVersion (1, 0, 3300, 0)]
 [assembly: SecurityCritical (SecurityCriticalScope.Explicit)]
 #endif
-[assembly: InternalsVisibleTo ("System.Runtime.Serialization, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull)]
 [assembly: InternalsVisibleTo ("System.IdentityModel, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull)]
 [assembly: InternalsVisibleTo ("System.IdentityModel.Selectors, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull)]
 [assembly: InternalsVisibleTo ("System.ServiceModel, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull)]
index 13ab7daa6d13d3dc3347053fdb639b28ce4f1539..59a7f8b139e5d1501eabf69f48924799d275e4d0 100644 (file)
@@ -1,6 +1,7 @@
 Assembly/AssemblyInfo.cs
 ../../build/common/Consts.cs
 ../../build/common/SR.cs
+../../build/common/AssemblyRef.cs
 EntityRes.cs
 EntityResCategoryAttribute.cs
 EntityResDescriptionAttribute.cs
index 1315e15e184338ef0f5639d41128c7e35cf9a53b..a5b2a2f1492a695f255fbb5c8aaf165e5c297848 100644 (file)
@@ -3,6 +3,7 @@ Assembly/AssemblyInfo.cs
 ../../build/common/Locale.cs
 ../../build/common/SR.cs
 ../../build/common/MonoTODOAttribute.cs
+../../build/common/AssemblyRef.cs
 
 ReferenceSources/NativeOledbWrapper.cs
 ReferenceSources/Res.cs
index 9622fcee668d3525c1dc49fa7a44053d20c8a983..76b642b8849fda23403711d3dbc810bb48a6171a 100644 (file)
@@ -3,6 +3,7 @@ Assembly/AssemblyInfo.cs
 ../../build/common/Locale.cs
 ../../build/common/SR.cs
 ../../build/common/MonoTODOAttribute.cs
+../../build/common/AssemblyRef.cs
 
 ReferenceSources/NativeOledbWrapper.cs
 ReferenceSources/Res.cs
index d8b918ebce307242c16d0e3383b39fa948badb2c..abc4e30ee80dea672bbb6ae14cfdd90449b6d521 100644 (file)
@@ -5,6 +5,6 @@ include ../../build/rules.make
 LIBRARY = System.IO.Compression.FileSystem.dll
 LIB_REFS = System System.IO.Compression
 LIB_MCS_FLAGS =
-TEST_MCS_FLAGS = /r:System /r:System.Core /r:System.IO.Compression.dll
+TEST_MCS_FLAGS = /r:System.dll /r:System.Core.dll /r:System.IO.Compression.dll
 
 include ../../build/library.make
index 7b2bd8144fb4fe6c7e7ad159dde706049e957825..3ca6899dacde9f589312031a31c0a8622a766770 100644 (file)
@@ -5,6 +5,6 @@ include ../../build/rules.make
 LIBRARY = System.IO.Compression.dll
 LIB_REFS = System System.Core
 LIB_MCS_FLAGS = /unsafe
-TEST_MCS_FLAGS = /r:System /r:System.Core
+TEST_MCS_FLAGS = /r:System.dll /r:System.Core.dll
 
 include ../../build/library.make
index 7992ecafb20807263f94efc60b129375821c16d0..4d9265a6ac76f8e3640e82e2e75e1fa6189b8ee6 100644 (file)
@@ -152,15 +152,16 @@ namespace MonoTests.System.Net.Http
 
                const int WaitTimeout = 5000;
 
-               string port, TestHost, LocalServer;
+               string TestHost, LocalServer;
+               int port;
 
                [SetUp]
                public void SetupFixture ()
                {
                        if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
-                               port = "810";
+                               port = 810;
                        } else {
-                               port = "8810";
+                               port = 8810;
                        }
 
                        TestHost = "localhost:" + port;
@@ -996,10 +997,30 @@ namespace MonoTests.System.Net.Http
                [Category ("MobileNotWorking")] // Missing encoding
                public void GetString_Many ()
                {
-                       var client = new HttpClient ();
-                       var t1 = client.GetStringAsync ("http://example.org");
-                       var t2 = client.GetStringAsync ("http://example.org");
-                       Assert.IsTrue (Task.WaitAll (new [] { t1, t2 }, WaitTimeout));          
+                       Action<HttpListenerContext> context = (HttpListenerContext l) => {
+                               var response = l.Response;
+                               response.StatusCode = 200;
+                               response.OutputStream.WriteByte (0x68);
+                               response.OutputStream.WriteByte (0x65);
+                               response.OutputStream.WriteByte (0x6c);
+                               response.OutputStream.WriteByte (0x6c);
+                               response.OutputStream.WriteByte (0x6f);
+                       };
+
+                       var listener = CreateListener (context); // creates a default request handler
+                       AddListenerContext (listener, context);  // add another request handler for the second request
+
+                       try {
+                               var client = new HttpClient ();
+                               var t1 = client.GetStringAsync (LocalServer);
+                               var t2 = client.GetStringAsync (LocalServer);
+                               Assert.IsTrue (Task.WaitAll (new [] { t1, t2 }, WaitTimeout));
+                               Assert.AreEqual ("hello", t1.Result, "#1");
+                               Assert.AreEqual ("hello", t2.Result, "#2");
+                       } finally {
+                               listener.Abort ();
+                               listener.Close ();
+                       }
                }
 
                [Test]
@@ -1060,9 +1081,20 @@ namespace MonoTests.System.Net.Http
                                var response = l.Response;
 
                                response.StatusCode = (int)HttpStatusCode.Moved;
-                               response.RedirectLocation = "http://xamarin.com/";
+                               response.RedirectLocation = "http://localhost:8811/";
                        });
 
+                       var listener2 = CreateListener (l => {
+                               var response = l.Response;
+
+                               response.StatusCode = (int)HttpStatusCode.OK;
+                               response.OutputStream.WriteByte (0x68);
+                               response.OutputStream.WriteByte (0x65);
+                               response.OutputStream.WriteByte (0x6c);
+                               response.OutputStream.WriteByte (0x6c);
+                               response.OutputStream.WriteByte (0x6f);
+                       }, 8811);
+
                        try {
                                var chandler = new HttpClientHandler ();
                                chandler.AllowAutoRedirect = true;
@@ -1071,10 +1103,13 @@ namespace MonoTests.System.Net.Http
                                var r = client.GetAsync (LocalServer);
                                Assert.IsTrue (r.Wait (WaitTimeout), "#1");
                                var resp = r.Result;
-                               Assert.AreEqual ("http://xamarin.com/", resp.RequestMessage.RequestUri.AbsoluteUri, "#2");
+                               Assert.AreEqual ("http://localhost:8811/", resp.RequestMessage.RequestUri.AbsoluteUri, "#2");
+                               Assert.AreEqual ("hello", resp.Content.ReadAsStringAsync ().Result, "#3");
                        } finally {
                                listener.Abort ();
                                listener.Close ();
+                               listener2.Abort ();
+                               listener2.Close ();
                        }
                }
 
@@ -1131,10 +1166,22 @@ namespace MonoTests.System.Net.Http
                }
 
                HttpListener CreateListener (Action<HttpListenerContext> contextAssert)
+               {
+                       return CreateListener (contextAssert, port);
+               }
+
+               HttpListener CreateListener (Action<HttpListenerContext> contextAssert, int port)
                {
                        var l = new HttpListener ();
                        l.Prefixes.Add (string.Format ("http://+:{0}/", port));
                        l.Start ();
+                       AddListenerContext(l, contextAssert);
+
+                       return l;
+               }
+
+               HttpListener AddListenerContext (HttpListener l, Action<HttpListenerContext> contextAssert)
+               {
                        l.BeginGetContext (ar => {
                                var ctx = l.EndGetContext (ar);
 
index 344d5669236655ba19abb49663689453c3d71af9..eeb73d0894eefe4d3fa471d20c063fb544c3abad 100644 (file)
@@ -4,9 +4,13 @@ include ../../build/rules.make
 
 LIBRARY = System.Runtime.Remoting.dll
 
-LIB_REFS = System System.Web System.Xml System.Runtime.Serialization.Formatters.Soap
+LIB_REFS = System System.Xml System.Runtime.Serialization.Formatters.Soap
 LIB_MCS_FLAGS = /r:$(corlib)
 
+ifndef NO_SYSTEM_WEB_DEPENDENCY
+LIB_REFS += System.Web
+endif
+
 TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) -nowarn:618 /r:System.Runtime.Remoting.dll
 
 TEST_MONO_PATH = .
diff --git a/mcs/class/System.Runtime.Remoting/xammac_net_4_5_System.Runtime.Remoting.dll.sources b/mcs/class/System.Runtime.Remoting/xammac_net_4_5_System.Runtime.Remoting.dll.sources
new file mode 100644 (file)
index 0000000..cadd275
--- /dev/null
@@ -0,0 +1,56 @@
+Assembly/AssemblyInfo.cs
+../../build/common/Consts.cs
+../../build/common/Locale.cs
+../../build/common/MonoTODOAttribute.cs
+System.Runtime.Remoting.Channels/BinaryClientFormatterSink.cs
+System.Runtime.Remoting.Channels/BinaryClientFormatterSinkProvider.cs
+System.Runtime.Remoting.Channels/BinaryCore.cs
+System.Runtime.Remoting.Channels/BinaryServerFormatterSink.cs
+System.Runtime.Remoting.Channels/BinaryServerFormatterSinkProvider.cs
+System.Runtime.Remoting.Channels/ChannelCore.cs
+System.Runtime.Remoting.Channels/CommonTransportKeys.cs
+System.Runtime.Remoting.Channels/IAuthorizeRemotingConnection.cs
+System.Runtime.Remoting.Channels/RemotingThreadPool.cs
+System.Runtime.Remoting.Channels/SoapClientFormatterSink.cs
+System.Runtime.Remoting.Channels/SoapCore.cs
+System.Runtime.Remoting.Channels/SoapServerFormatterSink.cs
+System.Runtime.Remoting.Channels/SoapClientFormatterSinkProvider.cs
+System.Runtime.Remoting.Channels/SoapServerFormatterSinkProvider.cs
+System.Runtime.Remoting.Channels/SoapMessageFormatter.cs
+System.Runtime.Remoting.Channels/SocketCachePolicy.cs
+System.Runtime.Remoting.Channels.Ipc/IpcChannel.cs
+System.Runtime.Remoting.Channels.Ipc/IpcClientChannel.cs
+System.Runtime.Remoting.Channels.Ipc/IpcServerChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/IpcTransport.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/IpcChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/IpcChannelHelper.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/IpcClientChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/IpcServerChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeClient.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeException.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeHelper.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeListener.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeStream.cs
+System.Runtime.Remoting.Channels.Ipc.Unix/IpcChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Unix/IpcClientChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Unix/IpcServerChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Unix/UnixChannelLoader.cs
+System.Runtime.Remoting.Channels.Tcp/TcpChannel.cs
+System.Runtime.Remoting.Channels.Tcp/TcpClientChannel.cs
+System.Runtime.Remoting.Channels.Tcp/TcpMessageIO.cs
+System.Runtime.Remoting.Channels.Tcp/TcpServerChannel.cs
+System.Runtime.Remoting.Channels.Tcp/TcpServerTransportSink.cs
+System.Runtime.Remoting.Channels.Tcp/TcpClientTransportSinkProvider.cs
+System.Runtime.Remoting.Channels.Tcp/TcpClientTransportSink.cs
+System.Runtime.Remoting.Channels.Tcp/TcpConnectionPool.cs
+System.Runtime.Remoting.MetadataServices/MetaData.cs
+System.Runtime.Remoting.MetadataServices/MetaDataExporter.cs
+System.Runtime.Remoting.MetadataServices/MetaDataCodeGenerator.cs
+System.Runtime.Remoting.MetadataServices/SdlChannelSinkProvider.cs
+System.Runtime.Remoting.MetadataServices/ServiceType.cs
+System.Runtime.Remoting.MetadataServices/SUDSParserException.cs
+System.Runtime.Remoting.MetadataServices/SdlChannelSink.cs
+System.Runtime.Remoting.MetadataServices/SdlType.cs
+System.Runtime.Remoting.MetadataServices/SUDSGeneratorException.cs
+System.Runtime.Remoting.Services/RemotingClientProxy.cs
index 99b323b2ab87b039f8e4d4c379c55ff66dd9fb4d..c9371adcc7403240c954b4a66007148ccf1aeb6c 100644 (file)
@@ -1,5 +1,6 @@
 ../../build/common/Consts.cs
 ../../build/common/SR.cs
+../../build/common/AssemblyRef.cs
 EventLogEntryType.cs
 InternalSR.cs
 Assembly/AssemblyInfo.cs
index a2290a9efeaf3b0ae14f737112d1aebd49cb4be0..d788a69db7c339cf3c567efc9aec7dceb8fd62f1 100644 (file)
@@ -1,5 +1,6 @@
 ../../build/common/Consts.cs
 ../../build/common/SR.cs
+../../build/common/AssemblyRef.cs
 EventLogEntryType.cs
 InternalSR.cs
 MobileStubs.cs
index 361a049e6e6e49b5881ca613e00f9e51d5c201d3..862830b0c76eb927a2b38a78c9b321365f3b2440 100644 (file)
@@ -65,7 +65,6 @@ namespace System.ServiceModel
                        return new EndpointAddress10 (address);
                }
 
-#if !NET_2_1
                public static XmlQualifiedName GetSchema (XmlSchemaSet xmlSchemaSet)
                {
                        if (xmlSchemaSet == null)
@@ -73,7 +72,6 @@ namespace System.ServiceModel
                        xmlSchemaSet.Add (XmlSchema.Read (typeof (EndpointAddress10).Assembly.GetManifestResourceStream ("ws-addr.xsd"), null));
                        return new XmlQualifiedName ("EndpointReferenceType", AddressingVersion.WSAddressing10.Namespace);
                }
-#endif
 
                public EndpointAddress ToEndpointAddress ()
                {
index 0cde2c9bdec8b0b276078978bc3ed79db1fe8434..dd2dc7f1c70d6e37264ac1c428b2d6592f37eacf 100644 (file)
@@ -166,6 +166,7 @@ System.ServiceModel.Security/SupportingTokenParametersTest.cs
 System.ServiceModel.Security/TransportSecurityBindingElementTest.cs
 System.ServiceModel.Security/WSSecurityTokenSerializerTest.cs
 System.ServiceModel/BasicHttpBindingTest.cs
+System.ServiceModel/Bug36080Test.cs
 System.ServiceModel/CallbackBehaviorAttributeTest.cs
 System.ServiceModel/ChannelFactoryTest.cs
 System.ServiceModel/ChannelFactory_1Test.cs
diff --git a/mcs/class/System.ServiceModel/Test/System.ServiceModel/Bug36080Test.cs b/mcs/class/System.ServiceModel/Test/System.ServiceModel/Bug36080Test.cs
new file mode 100644 (file)
index 0000000..2727915
--- /dev/null
@@ -0,0 +1,585 @@
+//
+// Author:
+//       Marcos Henrich <marcos.henrich@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.ServiceModel;
+using System.ServiceModel.Description;
+using System.Threading;
+using System.ServiceModel.Channels;
+using System.Text;
+using NUnit.Framework;
+
+using MonoTests.Helpers;
+
+namespace MonoTests.System.ServiceModel
+{
+       [TestFixture]
+       public class Bug36080
+       {
+               [Test]
+               public void Bug36080Test ()
+               {
+                       int port = NetworkHelpers.FindFreePort ();
+                       var url = "http://localhost:" + port + "/HelloWorldService";
+
+                       TransportBindingElement element = new HttpTransportBindingElement { MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue };
+                       Binding binding = new CustomBinding(new BindingElement[]
+                               {
+                                       new TextMessageEncodingBindingElement (MessageVersion.Default, Encoding.UTF8),
+                                       element
+                               });
+
+#if !MOBILE
+                       // Init service
+                       ServiceHost serviceHost = new ServiceHost (typeof (HelloWorldServiceImpl), new Uri (url));
+                       serviceHost.AddServiceEndpoint (typeof (IHelloWorldService), binding, string.Empty);
+
+                       serviceHost.Open ();
+#endif
+                       // In Mobile we still run this tests without any server.
+                       // Issue reported in #36080 was occuring before the connections fails.
+                       var wait = new ManualResetEvent (false);
+
+                       Exception error = null;
+                       string result = null;
+
+                       try {
+                               var client = new HelloWorldServiceClient (binding, new EndpointAddress(url));
+                               client.SayHelloToCompleted += delegate (object o, SayHelloToCompletedEventArgs e) {
+                                       try {
+                                               error = e.Error;
+                                               result = e.Error == null ? e.Result : null;
+                                       } finally {
+                                               wait.Set ();
+                                       }
+                               };
+
+                               var str = "Xamarin";
+                               client.SayHelloToAsync(str);
+
+                               Assert.IsTrue (wait.WaitOne (TimeSpan.FromSeconds (20)), "timeout");
+#if MOBILE
+                               if (error.GetType() == typeof(EndpointNotFoundException))
+                                       return;
+#endif
+
+                               Assert.IsNull (error, "#1, inner exception: {0}", error);
+                               Assert.AreEqual (str, result, "#2");
+                       }  finally {
+#if !MOBILE
+                               serviceHost.Close ();
+#endif
+                       }
+               }
+       }
+
+       public class  HelloWorldServiceImpl : IHelloWorldService
+       {
+               Func<string, string> sayHelloToFunc = SayHelloTo;
+
+               static string SayHelloTo (string name)
+               {
+                       return name;
+               }
+
+               public IAsyncResult BeginSayHelloTo(string name, AsyncCallback callback, object asyncState)
+               {
+                       return sayHelloToFunc.BeginInvoke (name, callback, asyncState);
+               }
+               
+               public string EndSayHelloTo(IAsyncResult result) 
+               {
+                       return sayHelloToFunc.EndInvoke(result);
+               }
+               
+               public IAsyncResult BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, AsyncCallback callback, object asyncState)
+               {
+                       return null;
+               }
+
+               public TestXamarin4WCFService.HelloWorldData EndGetHelloData(IAsyncResult result)
+               {
+                       return null;
+               }
+       }
+}
+
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.18444
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+// 
+// This code was auto-generated by SlSvcUtil, version 5.0.61118.0
+// 
+namespace TestXamarin4WCFService
+{
+    using System.Runtime.Serialization;
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+    [System.Runtime.Serialization.DataContractAttribute(Name = "HelloWorldData", Namespace = "http://schemas.datacontract.org/2004/07/TestXamarin4WCFService")]
+    public partial class HelloWorldData : object
+    {
+        
+        private string NameField;
+        
+        private bool SayHelloField;
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public string Name
+        {
+            get
+            {
+                return this.NameField;
+            }
+            set
+            {
+                this.NameField = value;
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public bool SayHello
+        {
+            get
+            {
+                return this.SayHelloField;
+            }
+            set
+            {
+                this.SayHelloField = value;
+            }
+        }
+    }
+}
+
+
+[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
+[System.ServiceModel.ServiceContractAttribute(ConfigurationName="IHelloWorldService")]
+public interface IHelloWorldService
+{
+    
+    [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://tempuri.org/IHelloWorldService/SayHelloTo", ReplyAction="http://tempuri.org/IHelloWorldService/SayHelloToResponse")]
+    System.IAsyncResult BeginSayHelloTo(string name, System.AsyncCallback callback, object asyncState);
+    
+    string EndSayHelloTo(System.IAsyncResult result);
+    
+    [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://tempuri.org/IHelloWorldService/GetHelloData", ReplyAction="http://tempuri.org/IHelloWorldService/GetHelloDataResponse")]
+    System.IAsyncResult BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, System.AsyncCallback callback, object asyncState);
+
+    TestXamarin4WCFService.HelloWorldData EndGetHelloData(System.IAsyncResult result);
+}
+
+[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
+public interface IHelloWorldServiceChannel : IHelloWorldService, System.ServiceModel.IClientChannel
+{
+}
+
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
+public partial class SayHelloToCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
+{
+    
+    private object[] results;
+    
+    public SayHelloToCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : 
+            base(exception, cancelled, userState)
+    {
+        this.results = results;
+    }
+    
+    public string Result
+    {
+        get
+        {
+            base.RaiseExceptionIfNecessary();
+            return ((string)(this.results[0]));
+        }
+    }
+}
+
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
+public partial class GetHelloDataCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
+{
+    
+    private object[] results;
+    
+    public GetHelloDataCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : 
+            base(exception, cancelled, userState)
+    {
+        this.results = results;
+    }
+
+    public TestXamarin4WCFService.HelloWorldData Result
+    {
+        get
+        {
+            base.RaiseExceptionIfNecessary();
+            return ((TestXamarin4WCFService.HelloWorldData)(this.results[0]));
+        }
+    }
+}
+
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
+public partial class HelloWorldServiceClient : System.ServiceModel.ClientBase<IHelloWorldService>, IHelloWorldService
+{
+    
+    private BeginOperationDelegate onBeginSayHelloToDelegate;
+    
+    private EndOperationDelegate onEndSayHelloToDelegate;
+    
+    private System.Threading.SendOrPostCallback onSayHelloToCompletedDelegate;
+    
+    private BeginOperationDelegate onBeginGetHelloDataDelegate;
+    
+    private EndOperationDelegate onEndGetHelloDataDelegate;
+    
+    private System.Threading.SendOrPostCallback onGetHelloDataCompletedDelegate;
+    
+    private BeginOperationDelegate onBeginOpenDelegate;
+    
+    private EndOperationDelegate onEndOpenDelegate;
+    
+    private System.Threading.SendOrPostCallback onOpenCompletedDelegate;
+    
+    private BeginOperationDelegate onBeginCloseDelegate;
+    
+    private EndOperationDelegate onEndCloseDelegate;
+    
+    private System.Threading.SendOrPostCallback onCloseCompletedDelegate;
+    
+    public HelloWorldServiceClient()
+    {
+    }
+    
+    public HelloWorldServiceClient(string endpointConfigurationName) : 
+            base(endpointConfigurationName)
+    {
+    }
+    
+    public HelloWorldServiceClient(string endpointConfigurationName, string remoteAddress) : 
+            base(endpointConfigurationName, remoteAddress)
+    {
+    }
+    
+    public HelloWorldServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
+            base(endpointConfigurationName, remoteAddress)
+    {
+    }
+    
+    public HelloWorldServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
+            base(binding, remoteAddress)
+    {
+    }
+    
+    public System.Net.CookieContainer CookieContainer
+    {
+        get
+        {
+            System.ServiceModel.Channels.IHttpCookieContainerManager httpCookieContainerManager = this.InnerChannel.GetProperty<System.ServiceModel.Channels.IHttpCookieContainerManager>();
+            if ((httpCookieContainerManager != null))
+            {
+                return httpCookieContainerManager.CookieContainer;
+            }
+            else
+            {
+                return null;
+            }
+        }
+        set
+        {
+            System.ServiceModel.Channels.IHttpCookieContainerManager httpCookieContainerManager = this.InnerChannel.GetProperty<System.ServiceModel.Channels.IHttpCookieContainerManager>();
+            if ((httpCookieContainerManager != null))
+            {
+                httpCookieContainerManager.CookieContainer = value;
+            }
+            else
+            {
+                throw new System.InvalidOperationException("Unable to set the CookieContainer. Please make sure the binding contains an HttpC" +
+                        "ookieContainerBindingElement.");
+            }
+        }
+    }
+    
+    public event System.EventHandler<SayHelloToCompletedEventArgs> SayHelloToCompleted;
+    
+    public event System.EventHandler<GetHelloDataCompletedEventArgs> GetHelloDataCompleted;
+    
+    public event System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs> OpenCompleted;
+    
+    public event System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs> CloseCompleted;
+    
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    System.IAsyncResult IHelloWorldService.BeginSayHelloTo(string name, System.AsyncCallback callback, object asyncState)
+    {
+        return base.Channel.BeginSayHelloTo(name, callback, asyncState);
+    }
+    
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    string IHelloWorldService.EndSayHelloTo(System.IAsyncResult result)
+    {
+        return base.Channel.EndSayHelloTo(result);
+    }
+    
+    private System.IAsyncResult OnBeginSayHelloTo(object[] inValues, System.AsyncCallback callback, object asyncState)
+    {
+        string name = ((string)(inValues[0]));
+        return ((IHelloWorldService)(this)).BeginSayHelloTo(name, callback, asyncState);
+    }
+    
+    private object[] OnEndSayHelloTo(System.IAsyncResult result)
+    {
+        string retVal = ((IHelloWorldService)(this)).EndSayHelloTo(result);
+        return new object[] {
+                retVal};
+    }
+    
+    private void OnSayHelloToCompleted(object state)
+    {
+        if ((this.SayHelloToCompleted != null))
+        {
+            InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
+            this.SayHelloToCompleted(this, new SayHelloToCompletedEventArgs(e.Results, e.Error, e.Cancelled, e.UserState));
+        }
+    }
+    
+    public void SayHelloToAsync(string name)
+    {
+        this.SayHelloToAsync(name, null);
+    }
+    
+    public void SayHelloToAsync(string name, object userState)
+    {
+        if ((this.onBeginSayHelloToDelegate == null))
+        {
+            this.onBeginSayHelloToDelegate = new BeginOperationDelegate(this.OnBeginSayHelloTo);
+        }
+        if ((this.onEndSayHelloToDelegate == null))
+        {
+            this.onEndSayHelloToDelegate = new EndOperationDelegate(this.OnEndSayHelloTo);
+        }
+        if ((this.onSayHelloToCompletedDelegate == null))
+        {
+            this.onSayHelloToCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnSayHelloToCompleted);
+        }
+        base.InvokeAsync(this.onBeginSayHelloToDelegate, new object[] {
+                    name}, this.onEndSayHelloToDelegate, this.onSayHelloToCompletedDelegate, userState);
+    }
+    
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    System.IAsyncResult IHelloWorldService.BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, System.AsyncCallback callback, object asyncState)
+    {
+        return base.Channel.BeginGetHelloData(helloWorldData, callback, asyncState);
+    }
+    
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    TestXamarin4WCFService.HelloWorldData IHelloWorldService.EndGetHelloData(System.IAsyncResult result)
+    {
+        return base.Channel.EndGetHelloData(result);
+    }
+    
+    private System.IAsyncResult OnBeginGetHelloData(object[] inValues, System.AsyncCallback callback, object asyncState)
+    {
+        TestXamarin4WCFService.HelloWorldData helloWorldData = ((TestXamarin4WCFService.HelloWorldData)(inValues[0]));
+        return ((IHelloWorldService)(this)).BeginGetHelloData(helloWorldData, callback, asyncState);
+    }
+    
+    private object[] OnEndGetHelloData(System.IAsyncResult result)
+    {
+        TestXamarin4WCFService.HelloWorldData retVal = ((IHelloWorldService)(this)).EndGetHelloData(result);
+        return new object[] {
+                retVal};
+    }
+    
+    private void OnGetHelloDataCompleted(object state)
+    {
+        if ((this.GetHelloDataCompleted != null))
+        {
+            InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
+            this.GetHelloDataCompleted(this, new GetHelloDataCompletedEventArgs(e.Results, e.Error, e.Cancelled, e.UserState));
+        }
+    }
+
+    public void GetHelloDataAsync(TestXamarin4WCFService.HelloWorldData helloWorldData)
+    {
+        this.GetHelloDataAsync(helloWorldData, null);
+    }
+
+    public void GetHelloDataAsync(TestXamarin4WCFService.HelloWorldData helloWorldData, object userState)
+    {
+        if ((this.onBeginGetHelloDataDelegate == null))
+        {
+            this.onBeginGetHelloDataDelegate = new BeginOperationDelegate(this.OnBeginGetHelloData);
+        }
+        if ((this.onEndGetHelloDataDelegate == null))
+        {
+            this.onEndGetHelloDataDelegate = new EndOperationDelegate(this.OnEndGetHelloData);
+        }
+        if ((this.onGetHelloDataCompletedDelegate == null))
+        {
+            this.onGetHelloDataCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnGetHelloDataCompleted);
+        }
+        base.InvokeAsync(this.onBeginGetHelloDataDelegate, new object[] {
+                    helloWorldData}, this.onEndGetHelloDataDelegate, this.onGetHelloDataCompletedDelegate, userState);
+    }
+    
+    private System.IAsyncResult OnBeginOpen(object[] inValues, System.AsyncCallback callback, object asyncState)
+    {
+        return ((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(callback, asyncState);
+    }
+    
+    private object[] OnEndOpen(System.IAsyncResult result)
+    {
+        ((System.ServiceModel.ICommunicationObject)(this)).EndOpen(result);
+        return null;
+    }
+    
+    private void OnOpenCompleted(object state)
+    {
+        if ((this.OpenCompleted != null))
+        {
+            InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
+            this.OpenCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(e.Error, e.Cancelled, e.UserState));
+        }
+    }
+    
+    public void OpenAsync()
+    {
+        this.OpenAsync(null);
+    }
+    
+    public void OpenAsync(object userState)
+    {
+        if ((this.onBeginOpenDelegate == null))
+        {
+            this.onBeginOpenDelegate = new BeginOperationDelegate(this.OnBeginOpen);
+        }
+        if ((this.onEndOpenDelegate == null))
+        {
+            this.onEndOpenDelegate = new EndOperationDelegate(this.OnEndOpen);
+        }
+        if ((this.onOpenCompletedDelegate == null))
+        {
+            this.onOpenCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnOpenCompleted);
+        }
+        base.InvokeAsync(this.onBeginOpenDelegate, null, this.onEndOpenDelegate, this.onOpenCompletedDelegate, userState);
+    }
+    
+    private System.IAsyncResult OnBeginClose(object[] inValues, System.AsyncCallback callback, object asyncState)
+    {
+        return ((System.ServiceModel.ICommunicationObject)(this)).BeginClose(callback, asyncState);
+    }
+    
+    private object[] OnEndClose(System.IAsyncResult result)
+    {
+        ((System.ServiceModel.ICommunicationObject)(this)).EndClose(result);
+        return null;
+    }
+    
+    private void OnCloseCompleted(object state)
+    {
+        if ((this.CloseCompleted != null))
+        {
+            InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
+            this.CloseCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(e.Error, e.Cancelled, e.UserState));
+        }
+    }
+    
+    public void CloseAsync()
+    {
+        this.CloseAsync(null);
+    }
+    
+    public void CloseAsync(object userState)
+    {
+        if ((this.onBeginCloseDelegate == null))
+        {
+            this.onBeginCloseDelegate = new BeginOperationDelegate(this.OnBeginClose);
+        }
+        if ((this.onEndCloseDelegate == null))
+        {
+            this.onEndCloseDelegate = new EndOperationDelegate(this.OnEndClose);
+        }
+        if ((this.onCloseCompletedDelegate == null))
+        {
+            this.onCloseCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnCloseCompleted);
+        }
+        base.InvokeAsync(this.onBeginCloseDelegate, null, this.onEndCloseDelegate, this.onCloseCompletedDelegate, userState);
+    }
+    
+    protected override IHelloWorldService CreateChannel()
+    {
+        return new HelloWorldServiceClientChannel(this);
+    }
+    
+    private class HelloWorldServiceClientChannel : ChannelBase<IHelloWorldService>, IHelloWorldService
+    {
+        
+        public HelloWorldServiceClientChannel(System.ServiceModel.ClientBase<IHelloWorldService> client) : 
+                base(client)
+        {
+        }
+        
+        public System.IAsyncResult BeginSayHelloTo(string name, System.AsyncCallback callback, object asyncState)
+        {
+            object[] _args = new object[1];
+            _args[0] = name;
+            System.IAsyncResult _result = base.BeginInvoke("SayHelloTo", _args, callback, asyncState);
+            return _result;
+        }
+        
+        public string EndSayHelloTo(System.IAsyncResult result)
+        {
+            object[] _args = new object[0];
+            string _result = ((string)(base.EndInvoke("SayHelloTo", _args, result)));
+            return _result;
+        }
+
+        public System.IAsyncResult BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, System.AsyncCallback callback, object asyncState)
+        {
+            object[] _args = new object[1];
+            _args[0] = helloWorldData;
+            System.IAsyncResult _result = base.BeginInvoke("GetHelloData", _args, callback, asyncState);
+            return _result;
+        }
+
+        public TestXamarin4WCFService.HelloWorldData EndGetHelloData(System.IAsyncResult result)
+        {
+            object[] _args = new object[0];
+            TestXamarin4WCFService.HelloWorldData _result = ((TestXamarin4WCFService.HelloWorldData)(base.EndInvoke("GetHelloData", _args, result)));
+            return _result;
+        }
+    }
+}
index a8cd2f842cb2d887242b5e8292085c3e6410e5e2..7f59b52e22b47f90653406803db3f8ef8acc6c08 100644 (file)
@@ -79,7 +79,9 @@ namespace System.Web.Handlers
                                        if (!hashAlg.CanReuseTransform) {
                                                canReuseHashAlg = false;
                                                hashAlg = null;
+                                               return null;
                                        }
+                                       hashAlg.Key = MachineKeySectionUtils.GetValidationKey (mks);
                                }
 
                                if (hashAlg != null)
index 355a3941c49773033d6a5496df503c5a8a417a99..3b61fe6384ad5cb0384fd7b329d1f7ac1133b281 100644 (file)
@@ -63,12 +63,9 @@ using System.Runtime.InteropServices;
 
 #if NET_2_1
        [assembly: InternalsVisibleTo ("System.ServiceModel.Web, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")]
-       // System.Xml.Serialization (from Microsoft Silverlight 2.0 SDK) requires access to System.Xml internals
-       [assembly: InternalsVisibleTo ("System.Xml.Serialization, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull)]
 #else
        [assembly: AllowPartiallyTrustedCallers]
 #endif
-       [assembly: InternalsVisibleTo ("System.Runtime.Serialization, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull, AllInternalsVisible = false)]
        [assembly: InternalsVisibleTo ("System.Xml.Linq, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull, AllInternalsVisible = false)]
 
 [assembly: AssemblyFileVersion (Consts.FxFileVersion)]
index 267719b871e93571b74c4c277a04a15e98a32845..be7f6099f6c4f6eeaa005c179dd27b8e738ba2d8 100644 (file)
@@ -1,6 +1,7 @@
 Assembly/AssemblyInfo.cs
 ../../build/common/Consts.cs
 ../../build/common/SR.cs
+../../build/common/AssemblyRef.cs
 ReferenceSources/Res.cs
 ReferenceSources/LocalAppContextSwitches.cs
 ReferenceSources/ThisAssembly.cs
index 9306044810f02c3f1491fa556fd8b522c9813452..253beb6470688707f66711f03749fc80fb4cb3ea 100644 (file)
@@ -2,6 +2,7 @@ Assembly/AssemblyInfo.cs
 ../../build/common/Consts.cs
 ../../build/common/MonoTODOAttribute.cs
 ../../build/common/SR.cs
+../../build/common/AssemblyRef.cs
 ReferenceSources/Res.cs
 ReferenceSources/LocalAppContextSwitches.cs
 ReferenceSources/ThisAssembly.cs
index f50bddac7777f46b141185bcc3b03a4988238f7e..617fbdefd531e5d2e6686ce7cc15f85348498a34 100644 (file)
@@ -264,7 +264,7 @@ namespace Mono.Net.Security
                                leaf = certs [0];
 
                        if (tlsStream != null)
-                               request.ServicePoint.SetServerCertificate (leaf);
+                               request.ServicePoint.UpdateServerCertificate (leaf);
 
                        if (leaf == null) {
                                errors |= SslPolicyErrors.RemoteCertificateNotAvailable;
@@ -292,14 +292,12 @@ namespace Mono.Net.Security
                        if (wantsChain)
                                chain = SystemCertificateValidator.CreateX509Chain (certs);
 
-                       if (wantsChain || SystemCertificateValidator.NeedsChain (settings))
-                               SystemCertificateValidator.BuildX509Chain (certs, chain, ref errors, ref status11);
-
                        bool providerValidated = false;
                        if (provider != null && provider.HasCustomSystemCertificateValidator) {
                                var xerrors = (MonoSslPolicyErrors)errors;
                                var xchain = (XX509Chain)(object)chain;
-                               providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, xchain, out result, ref xerrors, ref status11);
+                               providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, ref xchain, out result, ref xerrors, ref status11);
+                               chain = (X509Chain)(object)xchain;
                                errors = (SslPolicyErrors)xerrors;
                        }
 
index db6e66ca283313a5d06000cd4e2c0a6039f5c1b7..96f5933dfb7ba0608ad4f5827671eb23bb390d37 100644 (file)
@@ -109,13 +109,19 @@ namespace Mono.Net.Security
                                        ServicePointManager.CheckCertificateRevocationList);
 
                                status = WebExceptionStatus.Success;
+                       } catch (Exception ex) {
+                               status = WebExceptionStatus.SecureChannelFailure;
+                               throw;
                        } finally {
                                if (CertificateValidationFailed)
                                        status = WebExceptionStatus.TrustFailure;
 
-                               request.ServicePoint.SetClientCertificate (sslStream.InternalLocalCertificate);
-                               if (status != WebExceptionStatus.Success)
+                               if (status == WebExceptionStatus.Success)
+                                       request.ServicePoint.UpdateClientCertificate (sslStream.InternalLocalCertificate);
+                               else {
+                                       request.ServicePoint.UpdateClientCertificate (null);
                                        sslStream = null;
+                               }
                        }
 
                        try {
index f0a0be39e0eb547f4e595696cd1c217aaea2b23e..8cd1ca0b6fac8de068150a1b0e18f3342ce8a7c0 100644 (file)
@@ -86,13 +86,13 @@ namespace Mono.Net.Security
                        return chain;
                }
 
-               public static bool BuildX509Chain (XX509CertificateCollection certs, X509Chain chain, ref SslPolicyErrors errors, ref int status11)
+               static bool BuildX509Chain (XX509CertificateCollection certs, X509Chain chain, ref SslPolicyErrors errors, ref int status11)
                {
 #if MOBILE
-                       return true;
+                       return false;
 #else
                        if (is_macosx)
-                               return true;
+                               return false;
 
                        var leaf = (X509Certificate2)certs [0];
 
@@ -121,7 +121,9 @@ namespace Mono.Net.Security
                static bool CheckUsage (XX509CertificateCollection certs, string host, ref SslPolicyErrors errors, ref int status11)
                {
 #if !MONOTOUCH
-                       var leaf = (X509Certificate2)certs[0];
+                       var leaf = certs[0] as X509Certificate2;
+                       if (leaf == null)
+                               leaf = new X509Certificate2 (certs[0]);
                        // for OSX and iOS we're using the native API to check for the SSL server policy and host names
                        if (!is_macosx) {
                                if (!CheckCertificateUsage (leaf)) {
@@ -130,7 +132,7 @@ namespace Mono.Net.Security
                                        return false;
                                }
 
-                               if (host != null && !CheckServerIdentity (leaf, host)) {
+                               if (!string.IsNullOrEmpty (host) && !CheckServerIdentity (leaf, host)) {
                                        errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
                                        status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F
                                        return false;
@@ -143,7 +145,7 @@ namespace Mono.Net.Security
                static bool EvaluateSystem (XX509CertificateCollection certs, XX509CertificateCollection anchors, string host, X509Chain chain, ref SslPolicyErrors errors, ref int status11)
                {
                        var leaf = certs [0];
-                       var result = false;
+                       bool result;
 
 #if MONODROID
                        result = AndroidPlatform.TrustEvaluateSsl (certs);
@@ -166,6 +168,8 @@ namespace Mono.Net.Security
                                        result = (trustResult == OSX509Certificates.SecTrustResult.Proceed ||
                                                trustResult == OSX509Certificates.SecTrustResult.Unspecified);
                                } catch {
+                                       result = false;
+                                       errors |= SslPolicyErrors.RemoteCertificateChainErrors;
                                        // Ignore
                                }
 
@@ -178,6 +182,8 @@ namespace Mono.Net.Security
                                        status11 = (int)trustResult;
                                        errors |= SslPolicyErrors.RemoteCertificateChainErrors;
                                }
+                       } else {
+                               result = BuildX509Chain (certs, chain, ref errors, ref status11);
                        }
 #endif
 
@@ -203,6 +209,8 @@ namespace Mono.Net.Security
 #if MOBILE
                        return false;
 #else
+                       if (!is_macosx)
+                               return true;
                        if (!CertificateValidationHelper.SupportsX509Chain)
                                return false;
                        if (settings != null)
index 2bf4cab23c6e5641bcf5c351a09c2c7444058b10..fb31ace627b679a46f3b9eece4154858108a0c14 100644 (file)
@@ -255,10 +255,10 @@ namespace System.Diagnostics {
                                WritePrefix ();
                        }
 
-                       WriteDebugString (message);
-
                        if (Debugger.IsLogging())
                                Debugger.Log (0, null, message);
+                       else
+                               WriteDebugString (message);
 
                        WriteLogFile (message, LogFileName);
                }
index 57b8e669160aca8d9934afb06f6d77f839158532..41cf0d8c8c455930dfc4e5c8bbd84c9fa5308d74 100644 (file)
@@ -302,7 +302,7 @@ namespace System.Diagnostics
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The session ID for this process.")]
                public int SessionId {
-                       get { throw new NotImplementedException (); }
+                       get { return 0; }
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
index e0f8569969f680c662d71a55e2019a5650015656..33f83eccec481a4768b360eb7a4552b41b38f936 100644 (file)
@@ -16,6 +16,7 @@ namespace System.Net.Sockets {
        sealed class SafeSocketHandle : SafeHandleZeroOrMinusOneIsInvalid {
 
                List<Thread> blocking_threads;
+               bool in_cleanup;
 
                const int SOCKET_CLOSED = 10004;
 
@@ -43,32 +44,36 @@ namespace System.Net.Sockets {
 #endif
 
                        if (blocking_threads != null) {
-                               int abort_attempts = 0;
-                               while (blocking_threads.Count > 0) {
-                                       if (abort_attempts++ >= ABORT_RETRIES) {
-                                               if (THROW_ON_ABORT_RETRIES)
-                                                       throw new Exception ("Could not abort registered blocking threads before closing socket.");
-
-                                               // Attempts to close the socket safely failed.
-                                               // We give up, and close the socket with pending blocking system calls.
-                                               // This should not occur, nonetheless if it does this avoids an endless loop.
-                                               break;
-                                       }
-
-                                       /*
-                                        * This method can be called by the DangerousRelease inside RegisterForBlockingSyscall
-                                        * When this happens blocking_threads contains the current thread.
-                                        * We can safely close the socket and throw SocketException in RegisterForBlockingSyscall
-                                        * before the blocking system call.
-                                        */
-                                       lock (blocking_threads) {
+                               lock (blocking_threads) {
+                                       int abort_attempts = 0;
+                                       while (blocking_threads.Count > 0) {
+                                               if (abort_attempts++ >= ABORT_RETRIES) {
+                                                       if (THROW_ON_ABORT_RETRIES)
+                                                               throw new Exception ("Could not abort registered blocking threads before closing socket.");
+
+                                                       // Attempts to close the socket safely failed.
+                                                       // We give up, and close the socket with pending blocking system calls.
+                                                       // This should not occur, nonetheless if it does this avoids an endless loop.
+                                                       break;
+                                               }
+
+                                               /*
+                                               * This method can be called by the DangerousRelease inside RegisterForBlockingSyscall
+                                               * When this happens blocking_threads contains the current thread.
+                                               * We can safely close the socket and throw SocketException in RegisterForBlockingSyscall
+                                               * before the blocking system call.
+                                               */
                                                if (blocking_threads.Count == 1 && blocking_threads[0] == Thread.CurrentThread)
                                                        break;
-                                       }
 
-                                       AbortRegisteredThreads ();
-                                       // Sleep so other threads can resume
-                                       Thread.Sleep (1);
+                                               // abort registered threads
+                                               foreach (var t in blocking_threads)
+                                                       Socket.cancel_blocking_socket_operation (t);
+
+                                               // Sleep so other threads can resume
+                                               in_cleanup = true;
+                                               Monitor.Wait (blocking_threads, 100);
+                                       }
                                }
                        }
 
@@ -105,16 +110,8 @@ namespace System.Net.Sockets {
                        //If this NRE, we're in deep problems because Register Must have
                        lock (blocking_threads) {
                                blocking_threads.Remove (Thread.CurrentThread);
-                       }
-               }
-
-               void AbortRegisteredThreads () {
-                       if (blocking_threads == null)
-                               return;
-
-                       lock (blocking_threads) {
-                               foreach (var t in blocking_threads)
-                                       Socket.cancel_blocking_socket_operation (t);
+                               if (in_cleanup && blocking_threads.Count == 0)
+                                       Monitor.Pulse (blocking_threads);
                        }
                }
        }
index 769195a2b3ec4c965278d9ed8aa7670388d5e800..f1c47802cb94bef9e16534919ff1d10aba148b8c 100644 (file)
@@ -403,7 +403,7 @@ namespace System.Net {
                }
 
                public bool IsLocal {
-                       get { return IPAddress.IsLoopback (RemoteEndPoint.Address); }
+                       get { return LocalEndPoint.Address.Equals (RemoteEndPoint.Address); }
                }
 
                public bool IsSecureConnection {
index 6ee185ac19abc5bf7ca0cb434853587558f2ba0a..13c06ec493f499c3f5636c35248940ba13b3a6cc 100644 (file)
@@ -49,8 +49,6 @@ namespace System.Net
                DateTime idleSince;
                DateTime lastDnsResolve;
                Version protocolVersion;
-               X509Certificate certificate;
-               X509Certificate clientCertificate;
                IPHostEntry host;
                bool usesProxy;
                Dictionary<string,WebConnectionGroup> groups;
@@ -92,14 +90,6 @@ namespace System.Net
                        set { endPointCallback = value; }
                }
                
-               public X509Certificate Certificate {
-                       get { return certificate; }
-               }
-               
-               public X509Certificate ClientCertificate {
-                       get { return clientCertificate; }
-               }
-
                [MonoTODO]
                public int ConnectionLeaseTimeout
                {
@@ -413,20 +403,55 @@ namespace System.Net
                        return false;
                }
 
-               internal void SetServerCertificate (X509Certificate server)
+               //
+               // Copied from the referencesource
+               //
+
+               object m_ServerCertificateOrBytes;
+               object m_ClientCertificateOrBytes;
+
+               /// <devdoc>
+               ///    <para>
+               ///       Gets the certificate received for this <see cref='System.Net.ServicePoint'/>.
+               ///    </para>
+               /// </devdoc>
+               public  X509Certificate Certificate {
+                       get {
+                               object chkCert = m_ServerCertificateOrBytes;
+                               if (chkCert != null && chkCert.GetType() == typeof(byte[]))
+                                       return (X509Certificate)(m_ServerCertificateOrBytes = new X509Certificate((byte[]) chkCert));
+                               else
+                                       return chkCert as X509Certificate;
+                       }
+               }
+               internal void UpdateServerCertificate(X509Certificate certificate)
                {
-                       var cloned = server != null ? new X509Certificate (server) : null;
-                       var old = Interlocked.Exchange (ref certificate, cloned);
-                       if (old != null)
-                               old.Dispose ();
+                       if (certificate != null)
+                               m_ServerCertificateOrBytes = certificate.GetRawCertData();
+                       else
+                               m_ServerCertificateOrBytes = null;
+               }
+
+               /// <devdoc>
+               /// <para>
+               /// Gets the Client Certificate sent by us to the Server.
+               /// </para>
+               /// </devdoc>
+               public  X509Certificate ClientCertificate {
+                       get {
+                               object chkCert = m_ClientCertificateOrBytes;
+                               if (chkCert != null && chkCert.GetType() == typeof(byte[]))
+                                       return (X509Certificate)(m_ClientCertificateOrBytes = new X509Certificate((byte[]) chkCert));
+                               else
+                                       return chkCert as X509Certificate;
+                       }
                }
-
-               internal void SetClientCertificate (X509Certificate clientCertificate)
+               internal void UpdateClientCertificate(X509Certificate certificate)
                {
-                       var cloned = clientCertificate != null ? new X509Certificate (clientCertificate) : null;
-                       var old = Interlocked.Exchange (ref clientCertificate, cloned);
-                       if (old != null)
-                               old.Dispose ();
+                       if (certificate != null)
+                               m_ClientCertificateOrBytes = certificate.GetRawCertData();
+                       else
+                               m_ClientCertificateOrBytes = null;
                }
 
                internal bool CallEndPointDelegate (Socket sock, IPEndPoint remote)
index 8c1523ad82484bb59a94c69298e2e3337a0b2c98..f4f61725fb440e500fa5b40060cf7a489f6ec3d6 100644 (file)
@@ -419,6 +419,7 @@ namespace System.Net
                                        status = tlsStream.ExceptionStatus;
                                else if (!request.Aborted)
                                        status = WebExceptionStatus.ConnectFailure;
+                               connect_exception = ex;
                                return false;
                        }
 
@@ -992,9 +993,6 @@ namespace System.Net
 
                internal bool EndWrite (HttpWebRequest request, bool throwOnError, IAsyncResult result)
                {
-                       if (request.FinishedReading)
-                               return true;
-
                        Stream s = null;
                        lock (this) {
                                if (status == WebExceptionStatus.RequestCanceled)
index 0681e9eb5d7c6c4056b0c3008d8c34104f9db8ee..795f0d04b21acfabb51a09db288cfa3ccfecd274 100644 (file)
@@ -52,6 +52,7 @@ namespace System.Security.Cryptography.X509Certificates {
                        X500DistinguishedNameFlags.UseT61Encoding | X500DistinguishedNameFlags.ForceUTF8Encoding;
 
                private string name;
+               private byte[] canonEncoding;
 
 
                public X500DistinguishedName (AsnEncodedData encodedDistinguishedName)
@@ -122,6 +123,20 @@ namespace System.Security.Cryptography.X509Certificates {
                        name = distinguishedName.name;
                }
 
+               internal X500DistinguishedName (byte[] encoded, byte[] canonEncoding, string name)
+                       : this (encoded)
+               {
+                       this.canonEncoding = canonEncoding;
+                       this.name = name;
+
+                       Oid = new Oid ();
+                       RawData = encoded;
+               }
+
+               internal byte[] CanonicalEncoding {
+                       get { return canonEncoding; }
+               }
+
 
                public string Name {
                        get { return name; }
@@ -215,6 +230,16 @@ namespace System.Security.Cryptography.X509Certificates {
                        if (name2 == null)
                                return false;
 
+                       if (name1.canonEncoding != null && name2.canonEncoding != null) {
+                               if (name1.canonEncoding.Length != name2.canonEncoding.Length)
+                                       return false;
+                               for (int i = 0; i < name1.canonEncoding.Length; i++) {
+                                       if (name1.canonEncoding[i] != name2.canonEncoding[2])
+                                               return false;
+                               }
+                               return true;
+                       }
+
                        X500DistinguishedNameFlags flags = X500DistinguishedNameFlags.UseNewLines | X500DistinguishedNameFlags.DoNotUseQuotes;
                        string[] split = new string[] { Environment.NewLine };
                        string[] parts1 = name1.Decode (flags).Split (split, StringSplitOptions.RemoveEmptyEntries);
index afb81cb1ab77e0488174477741d71bf0e3d766c3..29decab439faa252aeb371c167e754684e7f9ec9 100644 (file)
@@ -44,11 +44,13 @@ using MX = Mono.Security.X509;
 
 using System.IO;
 using System.Text;
+using System.Collections;
 
 namespace System.Security.Cryptography.X509Certificates {
 
        [Serializable]
        public class X509Certificate2 : X509Certificate {
+       
 #if !SECURITY_DEP
                // Used in Mono.Security HttpsClientStream
                public X509Certificate2 (byte[] rawData)
@@ -56,24 +58,20 @@ namespace System.Security.Cryptography.X509Certificates {
                }
 #endif
 #if SECURITY_DEP
-               private bool _archived;
-               private X509ExtensionCollection _extensions;
-               private string _name = String.Empty;
-               private string _serial;
-               private PublicKey _publicKey;
-               private X500DistinguishedName issuer_name;
-               private X500DistinguishedName subject_name;
-               private Oid signature_algorithm;
-
-               private MX.X509Certificate _cert;
+               new internal X509Certificate2Impl Impl {
+                       get {
+                               var impl2 = base.Impl as X509Certificate2Impl;
+                               X509Helper2.ThrowIfContextInvalid (impl2);
+                               return impl2;
+                       }
+               }
 
-               private static string empty_error = Locale.GetText ("Certificate instance is empty.");
+               string friendlyName = string.Empty;
 
                // constructors
 
                public X509Certificate2 ()
                {
-                       _cert = null;
                }
 
                public X509Certificate2 (byte[] rawData)
@@ -128,206 +126,88 @@ namespace System.Security.Cryptography.X509Certificates {
 
                public X509Certificate2 (IntPtr handle) : base (handle) 
                {
-                       _cert = new MX.X509Certificate (base.GetRawCertData ());
+                       throw new NotImplementedException ();
                }
 
                public X509Certificate2 (X509Certificate certificate) 
-                       : base (certificate)
+                       : base (X509Helper2.Import (certificate))
+               {
+               }
+
+               internal X509Certificate2 (X509Certificate2Impl impl)
+                       : base (impl)
                {
-                       _cert = new MX.X509Certificate (base.GetRawCertData ());
                }
 
                // properties
 
                public bool Archived {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               return _archived;
-                       }
-                       set {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               _archived = value;
-                       }
+                       get { return Impl.Archived; }
+                       set { Impl.Archived = true; }
                }
 
                public X509ExtensionCollection Extensions {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               if (_extensions == null)
-                                       _extensions = new X509ExtensionCollection (_cert);
-                               return _extensions;
-                       }
+                       get { return Impl.Extensions; }
                }
 
                public string FriendlyName {
                        get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               return _name;
+                               ThrowIfContextInvalid ();
+                               return friendlyName;
                        }
                        set {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               _name = value;
+                               ThrowIfContextInvalid ();
+                               friendlyName = value;
                        }
                }
 
-               // FIXME - Could be more efficient
                public bool HasPrivateKey {
-                       get { return PrivateKey != null; }
+                       get { return Impl.HasPrivateKey; }
                }
 
                public X500DistinguishedName IssuerName {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               if (issuer_name == null)
-                                       issuer_name = new X500DistinguishedName (_cert.GetIssuerName ().GetBytes ());
-                               return issuer_name;
-                       }
+                       get { return Impl.IssuerName; }
                } 
 
                public DateTime NotAfter {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               return _cert.ValidUntil.ToLocalTime ();
-                       }
+                       get { return Impl.GetValidUntil ().ToLocalTime (); }
                }
 
                public DateTime NotBefore {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               return _cert.ValidFrom.ToLocalTime ();
-                       }
+                       get { return Impl.GetValidFrom ().ToLocalTime (); }
                }
 
                public AsymmetricAlgorithm PrivateKey {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               try {
-                                       if (_cert.RSA != null) {
-                                               RSACryptoServiceProvider rcsp = _cert.RSA as RSACryptoServiceProvider;
-                                               if (rcsp != null)
-                                                       return rcsp.PublicOnly ? null : rcsp;
-
-                                               RSAManaged rsam = _cert.RSA as RSAManaged;
-                                               if (rsam != null)
-                                                       return rsam.PublicOnly ? null : rsam;
-
-                                               _cert.RSA.ExportParameters (true);
-                                               return _cert.RSA;
-                                       } else if (_cert.DSA != null) {
-                                               DSACryptoServiceProvider dcsp = _cert.DSA as DSACryptoServiceProvider;
-                                               if (dcsp != null)
-                                                       return dcsp.PublicOnly ? null : dcsp;
-
-                                               _cert.DSA.ExportParameters (true);
-                                               return _cert.DSA;
-                                       }
-                               }
-                               catch {
-                               }
-                               return null;
-                       }
-                       set {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               // allow NULL so we can "forget" the key associated to the certificate
-                               // e.g. in case we want to export it in another format (see bug #396620)
-                               if (value == null) {
-                                       _cert.RSA = null;
-                                       _cert.DSA = null;
-                               } else  if (value is RSA)
-                                       _cert.RSA = (RSA) value;
-                               else if (value is DSA)
-                                       _cert.DSA = (DSA) value;
-                               else
-                                       throw new NotSupportedException ();
-                       }
+                       get { return Impl.PrivateKey; }
+                       set { Impl.PrivateKey = value; }
                } 
 
                public PublicKey PublicKey {
-                       get { 
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               if (_publicKey == null) {
-                                       try {
-                                               _publicKey = new PublicKey (_cert);
-                                       }
-                                       catch (Exception e) {
-                                               string msg = Locale.GetText ("Unable to decode public key.");
-                                               throw new CryptographicException (msg, e);
-                                       }
-                               }
-                               return _publicKey;
-                       }
+                       get { return Impl.PublicKey; }
                } 
 
                public byte[] RawData {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               return base.GetRawCertData ();
-                       }
-               } 
+                       get { return GetRawCertData (); }
+               }
 
                public string SerialNumber {
-                       get { 
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               if (_serial == null) {
-                                       StringBuilder sb = new StringBuilder ();
-                                       byte[] serial = _cert.SerialNumber;
-                                       for (int i=serial.Length - 1; i >= 0; i--)
-                                               sb.Append (serial [i].ToString ("X2"));
-                                       _serial = sb.ToString ();
-                               }
-                               return _serial; 
-                       }
+                       get { return GetSerialNumberString (); }
                } 
 
                public Oid SignatureAlgorithm {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               if (signature_algorithm == null)
-                                       signature_algorithm = new Oid (_cert.SignatureAlgorithm);
-                               return signature_algorithm;
-                       }
+                       get { return Impl.SignatureAlgorithm; }
                } 
 
                public X500DistinguishedName SubjectName {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               if (subject_name == null)
-                                       subject_name = new X500DistinguishedName (_cert.GetSubjectName ().GetBytes ());
-                               return subject_name;
-                       }
+                       get { return Impl.SubjectName; }
                } 
 
                public string Thumbprint {
-                       get { return base.GetCertHashString (); }
+                       get { return GetCertHashString (); }
                } 
 
                public int Version {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               return _cert.Version;
-                       }
+                       get { return Impl.Version; }
                }
 
                // methods
@@ -335,135 +215,7 @@ namespace System.Security.Cryptography.X509Certificates {
                [MonoTODO ("always return String.Empty for UpnName, DnsFromAlternativeName and UrlName")]
                public string GetNameInfo (X509NameType nameType, bool forIssuer) 
                {
-                       switch (nameType) {
-                       case X509NameType.SimpleName:
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               // return CN= or, if missing, the first part of the DN
-                               ASN1 sn = forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ();
-                               ASN1 dn = Find (commonName, sn);
-                               if (dn != null)
-                                       return GetValueAsString (dn);
-                               if (sn.Count == 0)
-                                       return String.Empty;
-                               ASN1 last_entry = sn [sn.Count - 1];
-                               if (last_entry.Count == 0)
-                                       return String.Empty;
-                               return GetValueAsString (last_entry [0]);
-                       case X509NameType.EmailName:
-                               // return the E= part of the DN (if present)
-                               ASN1 e = Find (email, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
-                               if (e != null)
-                                       return GetValueAsString (e);
-                               return String.Empty;
-                       case X509NameType.UpnName:
-                               // FIXME - must find/create test case
-                               return String.Empty;
-                       case X509NameType.DnsName:
-                               // return the CN= part of the DN (if present)
-                               ASN1 cn = Find (commonName, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
-                               if (cn != null)
-                                       return GetValueAsString (cn);
-                               return String.Empty;
-                       case X509NameType.DnsFromAlternativeName:
-                               // FIXME - must find/create test case
-                               return String.Empty;
-                       case X509NameType.UrlName:
-                               // FIXME - must find/create test case
-                               return String.Empty;
-                       default:
-                               throw new ArgumentException ("nameType");
-                       }
-               }
-
-               static byte[] commonName = { 0x55, 0x04, 0x03 };
-               static byte[] email = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 };
-
-               private ASN1 Find (byte[] oid, ASN1 dn)
-               {
-                       if (dn.Count == 0)
-                               return null;
-
-                       // process SET
-                       for (int i = 0; i < dn.Count; i++) {
-                               ASN1 set = dn [i];
-                               for (int j = 0; j < set.Count; j++) {
-                                       ASN1 pair = set [j];
-                                       if (pair.Count != 2)
-                                               continue;
-
-                                       ASN1 poid = pair [0];
-                                       if (poid == null)
-                                               continue;
-
-                                       if (poid.CompareValue (oid))
-                                               return pair;
-                               }
-                       }
-                       return null;
-               }
-
-               private string GetValueAsString (ASN1 pair)
-               {
-                       if (pair.Count != 2)
-                               return String.Empty;
-
-                       ASN1 value = pair [1];
-                       if ((value.Value == null) || (value.Length == 0))
-                               return String.Empty;
-
-                       if (value.Tag == 0x1E) {
-                               // BMPSTRING
-                               StringBuilder sb = new StringBuilder ();
-                               for (int j = 1; j < value.Value.Length; j += 2)
-                                       sb.Append ((char)value.Value [j]);
-                               return sb.ToString ();
-                       } else {
-                               return Encoding.UTF8.GetString (value.Value);
-                       }
-               }
-
-               private MX.X509Certificate ImportPkcs12 (byte[] rawData, string password)
-               {
-                       MX.PKCS12 pfx = null;
-                       if (string.IsNullOrEmpty (password)) {
-                               try {
-                                       // Support both unencrypted PKCS#12..
-                                       pfx = new MX.PKCS12 (rawData, (string)null);
-                               } catch {
-                                       // ..and PKCS#12 encrypted with an empty password
-                                       pfx = new MX.PKCS12 (rawData, string.Empty);
-                               }
-                       } else {
-                               pfx = new MX.PKCS12 (rawData, password);
-                       }
-
-                       if (pfx.Certificates.Count == 0) {
-                               // no certificate was found
-                               return null;
-                       } else if (pfx.Keys.Count == 0) {
-                               // no key were found - pick the first certificate
-                               return pfx.Certificates [0];
-                       } else {
-                               // find the certificate that match the first key
-                               MX.X509Certificate cert = null;
-                               var keypair = (pfx.Keys [0] as AsymmetricAlgorithm);
-                               string pubkey = keypair.ToXmlString (false);
-                               foreach (var c in pfx.Certificates) {
-                                       if (((c.RSA != null) && (pubkey == c.RSA.ToXmlString (false))) ||
-                                               ((c.DSA != null) && (pubkey == c.DSA.ToXmlString (false)))) {
-                                               cert = c;
-                                               break;
-                                       }
-                               }
-                               if (cert == null) {
-                                       cert = pfx.Certificates [0]; // no match, pick first certificate without keys
-                               } else {
-                                       cert.RSA = (keypair as RSA);
-                                       cert.DSA = (keypair as DSA);
-                               }
-                               return cert;
-                       }
+                       return Impl.GetNameInfo (nameType, forIssuer);
                }
 
                public override void Import (byte[] rawData) 
@@ -474,37 +226,8 @@ namespace System.Security.Cryptography.X509Certificates {
                [MonoTODO ("missing KeyStorageFlags support")]
                public override void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
                {
-                       MX.X509Certificate cert = null;
-                       if (password == null) {
-                               try {
-                                       cert = new MX.X509Certificate (rawData);
-                               }
-                               catch (Exception e) {
-                                       try {
-                                               cert = ImportPkcs12 (rawData, null);
-                                       }
-                                       catch {
-                                               string msg = Locale.GetText ("Unable to decode certificate.");
-                                               // inner exception is the original (not second) exception
-                                               throw new CryptographicException (msg, e);
-                                       }
-                               }
-                       } else {
-                               // try PKCS#12
-                               try {
-                                       cert = ImportPkcs12 (rawData, password);
-                               }
-                               catch {
-                                       // it's possible to supply a (unrequired/unusued) password
-                                       // fix bug #79028
-                                       cert = new MX.X509Certificate (rawData);
-                               }
-                       }
-                       // we do not have to fully re-decode the certificate since X509Certificate does not deal with keys
-                       if (cert != null) {
-                               base.Import (cert.RawData, (string) null, keyStorageFlags);
-                               _cert = cert; // becuase base call will call Reset!
-                       }
+                       var impl = X509Helper2.Import (rawData, password, keyStorageFlags);
+                       ImportHandle (impl);
                }
 
                [MonoTODO ("SecureString is incomplete")]
@@ -536,64 +259,25 @@ namespace System.Security.Cryptography.X509Certificates {
                [MonoTODO ("X509ContentType.SerializedCert is not supported")]
                public override byte[] Export (X509ContentType contentType, string password)
                {
-                       if (_cert == null)
-                               throw new CryptographicException (empty_error);
-
-                       switch (contentType) {
-                       case X509ContentType.Cert:
-                               return _cert.RawData;
-                       case X509ContentType.Pfx: // this includes Pkcs12
-                               return ExportPkcs12 (password);
-                       case X509ContentType.SerializedCert:
-                               // TODO
-                               throw new NotSupportedException ();
-                       default:
-                               string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
-                               throw new CryptographicException (msg);
-                       }
-               }
-
-               byte[] ExportPkcs12 (string password)
-               {
-                       var pfx = new MX.PKCS12 ();
-                       try {
-                               if (password != null)
-                                       pfx.Password = password;
-                               pfx.AddCertificate (_cert);
-                               var privateKey = PrivateKey;
-                               if (privateKey != null)
-                                       pfx.AddPkcs8ShroudedKeyBag (privateKey);
-                               return pfx.GetBytes ();
-                       } finally {
-                               pfx.Password = null;
-                       }
+                       return Impl.Export (contentType, password);
                }
 
                public override void Reset () 
                {
-                       _cert = null;
-                       _archived = false;
-                       _extensions = null;
-                       _name = String.Empty;
-                       _serial = null;
-                       _publicKey = null;
-                       issuer_name = null;
-                       subject_name = null;
-                       signature_algorithm = null;
+                       friendlyName = string.Empty;
                        base.Reset ();
                }
 
                public override string ToString ()
                {
-                       if (_cert == null)
+                       if (!IsValid)
                                return "System.Security.Cryptography.X509Certificates.X509Certificate2";
-
                        return base.ToString (true);
                }
 
                public override string ToString (bool verbose)
                {
-                       if (_cert == null)
+                       if (!IsValid)
                                return "System.Security.Cryptography.X509Certificates.X509Certificate2";
 
                        // the non-verbose X509Certificate2 == verbose X509Certificate
@@ -643,14 +327,7 @@ namespace System.Security.Cryptography.X509Certificates {
                [MonoTODO ("by default this depends on the incomplete X509Chain")]
                public bool Verify ()
                {
-                       if (_cert == null)
-                               throw new CryptographicException (empty_error);
-
-                       X509Chain chain = X509Chain.Create ();
-                       if (!chain.Build (this))
-                               return false;
-                       // TODO - check chain and other stuff ???
-                       return true;
+                       return Impl.Verify (this);
                }
 
                // static methods
@@ -717,8 +394,14 @@ namespace System.Security.Cryptography.X509Certificates {
                // internal stuff because X509Certificate2 isn't complete enough
                // (maybe X509Certificate3 will be better?)
 
+               [Obsolete ("KILL")]
                internal MX.X509Certificate MonoCertificate {
-                       get { return _cert; }
+                       get {
+                               var monoImpl = Impl as X509Certificate2ImplMono;
+                               if (monoImpl == null)
+                                       throw new NotSupportedException ();
+                               return monoImpl.MonoCertificate;
+                       }
                }
 
 #else
diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs
new file mode 100644 (file)
index 0000000..60e256a
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// X509Certificate2Impl.cs
+//
+// Authors:
+//     Martin Baulig  <martin.baulig@xamarin.com>
+//
+// Copyright (C) 2016 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.
+//
+namespace System.Security.Cryptography.X509Certificates
+{
+       internal abstract class X509Certificate2Impl : X509CertificateImpl
+       {
+#if SECURITY_DEP
+
+               public abstract bool Archived {
+                       get; set;
+               }
+
+               public abstract X509ExtensionCollection Extensions {
+                       get;
+               }
+
+               public abstract bool HasPrivateKey {
+                       get;
+               }
+
+               public abstract X500DistinguishedName IssuerName {
+                       get;
+               }
+
+               public abstract AsymmetricAlgorithm PrivateKey {
+                       get; set;
+               }
+
+               public abstract PublicKey PublicKey {
+                       get;
+               }
+
+               public abstract Oid SignatureAlgorithm {
+                       get;
+               }
+
+               public abstract X500DistinguishedName SubjectName {
+                       get;
+               }
+
+               public abstract int Version {
+                       get;
+               }
+
+               public abstract string GetNameInfo (X509NameType nameType, bool forIssuer);
+
+               public abstract void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags);
+
+               public abstract byte[] Export (X509ContentType contentType, string password);
+
+               public abstract bool Verify (X509Certificate2 thisCertificate);
+
+               public abstract void Reset ();
+
+#endif
+       }
+}
diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs
new file mode 100644 (file)
index 0000000..87fd8a1
--- /dev/null
@@ -0,0 +1,694 @@
+//
+// X509Certificate2ImplMono
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//     Martin Baulig  <martin.baulig@xamarin.com>
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
+// Copyright (C) 2015-2016 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 SECURITY_DEP
+
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+using MonoSecurity::Mono.Security;
+using MonoSecurity::Mono.Security.Cryptography;
+using MX = MonoSecurity::Mono.Security.X509;
+#else
+using Mono.Security;
+using Mono.Security.Cryptography;
+using MX = Mono.Security.X509;
+#endif
+
+using System.IO;
+using System.Text;
+using System.Collections;
+
+namespace System.Security.Cryptography.X509Certificates
+{
+       internal class X509Certificate2ImplMono : X509Certificate2Impl
+       {
+               bool _archived;
+               X509ExtensionCollection _extensions;
+               string _serial;
+               PublicKey _publicKey;
+               X500DistinguishedName issuer_name;
+               X500DistinguishedName subject_name;
+               Oid signature_algorithm;
+
+               MX.X509Certificate _cert;
+
+               static string empty_error = Locale.GetText ("Certificate instance is empty.");
+
+               public override bool IsValid {
+                       get {
+                               return _cert != null;
+                       }
+               }
+
+               public override IntPtr Handle {
+                       get { return IntPtr.Zero; }
+               }
+
+               internal X509Certificate2ImplMono (MX.X509Certificate cert)
+               {
+                       this._cert = cert;
+               }
+
+               public override X509CertificateImpl Clone ()
+               {
+                       ThrowIfContextInvalid ();
+                       return new X509Certificate2ImplMono (_cert);
+               }
+
+               #region Implemented X509CertificateImpl members
+
+               public override string GetIssuerName (bool legacyV1Mode)
+               {
+                       ThrowIfContextInvalid ();
+                       if (legacyV1Mode)
+                               return _cert.IssuerName;
+                       else
+                               return MX.X501.ToString (_cert.GetIssuerName (), true, ", ", true);
+               }
+
+               public override string GetSubjectName (bool legacyV1Mode)
+               {
+                       ThrowIfContextInvalid ();
+                       if (legacyV1Mode)
+                               return _cert.SubjectName;
+                       else
+                               return MX.X501.ToString (_cert.GetSubjectName (), true, ", ", true);
+               }
+
+               public override byte[] GetRawCertData ()
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.RawData;
+               }
+
+               protected override byte[] GetCertHash (bool lazy)
+               {
+                       ThrowIfContextInvalid ();
+                       SHA1 sha = SHA1.Create ();
+                       return sha.ComputeHash (_cert.RawData);
+               }
+
+               public override DateTime GetValidFrom ()
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.ValidFrom;
+               }
+
+               public override DateTime GetValidUntil ()
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.ValidUntil;
+               }
+
+               public override bool Equals (X509CertificateImpl other, out bool result)
+               {
+                       // Use default implementation
+                       result = false;
+                       return false;
+               }
+
+               public override string GetKeyAlgorithm () 
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.KeyAlgorithm;
+               }
+
+               public override byte[] GetKeyAlgorithmParameters () 
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.KeyAlgorithmParameters;
+               }
+
+               public override byte[] GetPublicKey ()
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.PublicKey;
+               }
+
+               public override byte[] GetSerialNumber ()
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.SerialNumber;
+               }
+
+               public override byte[] Export (X509ContentType contentType, byte[] password)
+               {
+                       ThrowIfContextInvalid ();
+
+                       switch (contentType) {
+                       case X509ContentType.Cert:
+                               return GetRawCertData ();
+                       case X509ContentType.Pfx: // this includes Pkcs12
+                               // TODO
+                               throw new NotSupportedException ();
+                       case X509ContentType.SerializedCert:
+                               // TODO
+                               throw new NotSupportedException ();
+                       default:
+                               string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
+                               throw new CryptographicException (msg);
+                       }
+               }
+
+               #endregion
+
+               // constructors
+
+               public X509Certificate2ImplMono ()
+               {
+                       _cert = null;
+               }
+
+               // properties
+
+               public override bool Archived {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               return _archived;
+                       }
+                       set {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               _archived = value;
+                       }
+               }
+
+               public override X509ExtensionCollection Extensions {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               if (_extensions == null)
+                                       _extensions = new X509ExtensionCollection (_cert);
+                               return _extensions;
+                       }
+               }
+
+               // FIXME - Could be more efficient
+               public override bool HasPrivateKey {
+                       get { return PrivateKey != null; }
+               }
+
+               public override X500DistinguishedName IssuerName {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               if (issuer_name == null)
+                                       issuer_name = new X500DistinguishedName (_cert.GetIssuerName ().GetBytes ());
+                               return issuer_name;
+                       }
+               } 
+
+               public override AsymmetricAlgorithm PrivateKey {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               try {
+                                       if (_cert.RSA != null) {
+                                               RSACryptoServiceProvider rcsp = _cert.RSA as RSACryptoServiceProvider;
+                                               if (rcsp != null)
+                                                       return rcsp.PublicOnly ? null : rcsp;
+
+                                               RSAManaged rsam = _cert.RSA as RSAManaged;
+                                               if (rsam != null)
+                                                       return rsam.PublicOnly ? null : rsam;
+
+                                               _cert.RSA.ExportParameters (true);
+                                               return _cert.RSA;
+                                       } else if (_cert.DSA != null) {
+                                               DSACryptoServiceProvider dcsp = _cert.DSA as DSACryptoServiceProvider;
+                                               if (dcsp != null)
+                                                       return dcsp.PublicOnly ? null : dcsp;
+
+                                               _cert.DSA.ExportParameters (true);
+                                               return _cert.DSA;
+                                       }
+                               }
+                               catch {
+                               }
+                               return null;
+                       }
+                       set {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+
+                               // allow NULL so we can "forget" the key associated to the certificate
+                               // e.g. in case we want to export it in another format (see bug #396620)
+                               if (value == null) {
+                                       _cert.RSA = null;
+                                       _cert.DSA = null;
+                               } else  if (value is RSA)
+                                       _cert.RSA = (RSA) value;
+                               else if (value is DSA)
+                                       _cert.DSA = (DSA) value;
+                               else
+                                       throw new NotSupportedException ();
+                       }
+               } 
+
+               public override PublicKey PublicKey {
+                       get { 
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+
+                               if (_publicKey == null) {
+                                       try {
+                                               _publicKey = new PublicKey (_cert);
+                                       }
+                                       catch (Exception e) {
+                                               string msg = Locale.GetText ("Unable to decode public key.");
+                                               throw new CryptographicException (msg, e);
+                                       }
+                               }
+                               return _publicKey;
+                       }
+               }
+
+               public override Oid SignatureAlgorithm {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+
+                               if (signature_algorithm == null)
+                                       signature_algorithm = new Oid (_cert.SignatureAlgorithm);
+                               return signature_algorithm;
+                       }
+               } 
+
+               public override X500DistinguishedName SubjectName {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+
+                               if (subject_name == null)
+                                       subject_name = new X500DistinguishedName (_cert.GetSubjectName ().GetBytes ());
+                               return subject_name;
+                       }
+               } 
+
+               public override int Version {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               return _cert.Version;
+                       }
+               }
+
+               // methods
+
+               [MonoTODO ("always return String.Empty for UpnName, DnsFromAlternativeName and UrlName")]
+               public override string GetNameInfo (X509NameType nameType, bool forIssuer) 
+               {
+                       switch (nameType) {
+                       case X509NameType.SimpleName:
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               // return CN= or, if missing, the first part of the DN
+                               ASN1 sn = forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ();
+                               ASN1 dn = Find (commonName, sn);
+                               if (dn != null)
+                                       return GetValueAsString (dn);
+                               if (sn.Count == 0)
+                                       return String.Empty;
+                               ASN1 last_entry = sn [sn.Count - 1];
+                               if (last_entry.Count == 0)
+                                       return String.Empty;
+                               return GetValueAsString (last_entry [0]);
+                       case X509NameType.EmailName:
+                               // return the E= part of the DN (if present)
+                               ASN1 e = Find (email, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
+                               if (e != null)
+                                       return GetValueAsString (e);
+                               return String.Empty;
+                       case X509NameType.UpnName:
+                               // FIXME - must find/create test case
+                               return String.Empty;
+                       case X509NameType.DnsName:
+                               // return the CN= part of the DN (if present)
+                               ASN1 cn = Find (commonName, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
+                               if (cn != null)
+                                       return GetValueAsString (cn);
+                               return String.Empty;
+                       case X509NameType.DnsFromAlternativeName:
+                               // FIXME - must find/create test case
+                               return String.Empty;
+                       case X509NameType.UrlName:
+                               // FIXME - must find/create test case
+                               return String.Empty;
+                       default:
+                               throw new ArgumentException ("nameType");
+                       }
+               }
+
+               static byte[] commonName = { 0x55, 0x04, 0x03 };
+               static byte[] email = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 };
+
+               private ASN1 Find (byte[] oid, ASN1 dn)
+               {
+                       if (dn.Count == 0)
+                               return null;
+
+                       // process SET
+                       for (int i = 0; i < dn.Count; i++) {
+                               ASN1 set = dn [i];
+                               for (int j = 0; j < set.Count; j++) {
+                                       ASN1 pair = set [j];
+                                       if (pair.Count != 2)
+                                               continue;
+
+                                       ASN1 poid = pair [0];
+                                       if (poid == null)
+                                               continue;
+
+                                       if (poid.CompareValue (oid))
+                                               return pair;
+                               }
+                       }
+                       return null;
+               }
+
+               private string GetValueAsString (ASN1 pair)
+               {
+                       if (pair.Count != 2)
+                               return String.Empty;
+
+                       ASN1 value = pair [1];
+                       if ((value.Value == null) || (value.Length == 0))
+                               return String.Empty;
+
+                       if (value.Tag == 0x1E) {
+                               // BMPSTRING
+                               StringBuilder sb = new StringBuilder ();
+                               for (int j = 1; j < value.Value.Length; j += 2)
+                                       sb.Append ((char)value.Value [j]);
+                               return sb.ToString ();
+                       } else {
+                               return Encoding.UTF8.GetString (value.Value);
+                       }
+               }
+
+               private MX.X509Certificate ImportPkcs12 (byte[] rawData, string password)
+               {
+                       MX.PKCS12 pfx = null;
+                       if (string.IsNullOrEmpty (password)) {
+                               try {
+                                       // Support both unencrypted PKCS#12..
+                                       pfx = new MX.PKCS12 (rawData, (string)null);
+                               } catch {
+                                       // ..and PKCS#12 encrypted with an empty password
+                                       pfx = new MX.PKCS12 (rawData, string.Empty);
+                               }
+                       } else {
+                               pfx = new MX.PKCS12 (rawData, password);
+                       }
+
+                       if (pfx.Certificates.Count == 0) {
+                               // no certificate was found
+                               return null;
+                       } else if (pfx.Keys.Count == 0) {
+                               // no key were found - pick the first certificate
+                               return pfx.Certificates [0];
+                       } else {
+                               // find the certificate that match the first key
+                               MX.X509Certificate cert = null;
+                               var keypair = (pfx.Keys [0] as AsymmetricAlgorithm);
+                               string pubkey = keypair.ToXmlString (false);
+                               foreach (var c in pfx.Certificates) {
+                                       if (((c.RSA != null) && (pubkey == c.RSA.ToXmlString (false))) ||
+                                               ((c.DSA != null) && (pubkey == c.DSA.ToXmlString (false)))) {
+                                               cert = c;
+                                               break;
+                                       }
+                               }
+                               if (cert == null) {
+                                       cert = pfx.Certificates [0]; // no match, pick first certificate without keys
+                               } else {
+                                       cert.RSA = (keypair as RSA);
+                                       cert.DSA = (keypair as DSA);
+                               }
+                               return cert;
+                       }
+               }
+
+               [MonoTODO ("missing KeyStorageFlags support")]
+               public override void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
+               {
+                       MX.X509Certificate cert = null;
+                       if (password == null) {
+                               try {
+                                       cert = new MX.X509Certificate (rawData);
+                               }
+                               catch (Exception e) {
+                                       try {
+                                               cert = ImportPkcs12 (rawData, null);
+                                       }
+                                       catch {
+                                               string msg = Locale.GetText ("Unable to decode certificate.");
+                                               // inner exception is the original (not second) exception
+                                               throw new CryptographicException (msg, e);
+                                       }
+                               }
+                       } else {
+                               // try PKCS#12
+                               try {
+                                       cert = ImportPkcs12 (rawData, password);
+                               }
+                               catch {
+                                       // it's possible to supply a (unrequired/unusued) password
+                                       // fix bug #79028
+                                       cert = new MX.X509Certificate (rawData);
+                               }
+                       }
+                       _cert = cert;
+               }
+
+               [MonoTODO ("X509ContentType.SerializedCert is not supported")]
+               public override byte[] Export (X509ContentType contentType, string password)
+               {
+                       if (_cert == null)
+                               throw new CryptographicException (empty_error);
+
+                       switch (contentType) {
+                       case X509ContentType.Cert:
+                               return _cert.RawData;
+                       case X509ContentType.Pfx: // this includes Pkcs12
+                               return ExportPkcs12 (password);
+                       case X509ContentType.SerializedCert:
+                               // TODO
+                               throw new NotSupportedException ();
+                       default:
+                               string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
+                               throw new CryptographicException (msg);
+                       }
+               }
+
+               byte[] ExportPkcs12 (string password)
+               {
+                       var pfx = new MX.PKCS12 ();
+                       try {
+                               var attrs = new Hashtable ();
+                               var localKeyId = new ArrayList ();
+                               localKeyId.Add (new byte[] { 1, 0, 0, 0 });
+                               attrs.Add (MX.PKCS9.localKeyId, localKeyId);
+
+                               if (password != null)
+                                       pfx.Password = password;
+                               pfx.AddCertificate (_cert, attrs);
+                               var privateKey = PrivateKey;
+                               if (privateKey != null)
+                                       pfx.AddPkcs8ShroudedKeyBag (privateKey, attrs);
+                               return pfx.GetBytes ();
+                       } finally {
+                               pfx.Password = null;
+                       }
+               }
+
+               public override void Reset () 
+               {
+                       _cert = null;
+                       _archived = false;
+                       _extensions = null;
+                       _serial = null;
+                       _publicKey = null;
+                       issuer_name = null;
+                       subject_name = null;
+                       signature_algorithm = null;
+               }
+
+               public override string ToString ()
+               {
+                       if (_cert == null)
+                               return "System.Security.Cryptography.X509Certificates.X509Certificate2";
+
+                       return ToString (true);
+               }
+
+               public override string ToString (bool verbose)
+               {
+                       if (_cert == null)
+                               return "System.Security.Cryptography.X509Certificates.X509Certificate2";
+
+                       string nl = Environment.NewLine;
+                       StringBuilder sb = new StringBuilder ();
+
+                       // the non-verbose X509Certificate2 == verbose X509Certificate
+                       if (!verbose) {
+                               sb.AppendFormat ("[Subject]{0}  {1}{0}{0}", nl, GetSubjectName (false));
+                               sb.AppendFormat ("[Issuer]{0}  {1}{0}{0}", nl, GetIssuerName (false));
+                               sb.AppendFormat ("[Not Before]{0}  {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
+                               sb.AppendFormat ("[Not After]{0}  {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
+                               sb.AppendFormat ("[Thumbprint]{0}  {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
+                               sb.Append (nl);
+                               return sb.ToString ();
+                       }
+
+                       sb.AppendFormat ("[Version]{0}  V{1}{0}{0}", nl, Version);
+                       sb.AppendFormat ("[Subject]{0}  {1}{0}{0}", nl, GetSubjectName (false));
+                       sb.AppendFormat ("[Issuer]{0}  {1}{0}{0}", nl, GetIssuerName (false));
+                       sb.AppendFormat ("[Serial Number]{0}  {1}{0}{0}", nl, GetSerialNumber ());
+                       sb.AppendFormat ("[Not Before]{0}  {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
+                       sb.AppendFormat ("[Not After]{0}  {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
+                       sb.AppendFormat ("[Thumbprint]{0}  {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
+                       sb.AppendFormat ("[Signature Algorithm]{0}  {1}({2}){0}{0}", nl, SignatureAlgorithm.FriendlyName, 
+                               SignatureAlgorithm.Value);
+
+                       AsymmetricAlgorithm key = PublicKey.Key;
+                       sb.AppendFormat ("[Public Key]{0}  Algorithm: ", nl);
+                       if (key is RSA)
+                               sb.Append ("RSA");
+                       else if (key is DSA)
+                               sb.Append ("DSA");
+                       else
+                               sb.Append (key.ToString ());
+                       sb.AppendFormat ("{0}  Length: {1}{0}  Key Blob: ", nl, key.KeySize);
+                       AppendBuffer (sb, PublicKey.EncodedKeyValue.RawData);
+                       sb.AppendFormat ("{0}  Parameters: ", nl);
+                       AppendBuffer (sb, PublicKey.EncodedParameters.RawData);
+                       sb.Append (nl);
+
+                       return sb.ToString ();
+               }
+
+               private static void AppendBuffer (StringBuilder sb, byte[] buffer)
+               {
+                       if (buffer == null)
+                               return;
+                       for (int i=0; i < buffer.Length; i++) {
+                               sb.Append (buffer [i].ToString ("x2"));
+                               if (i < buffer.Length - 1)
+                                       sb.Append (" ");
+                       }
+               }
+
+               [MonoTODO ("by default this depends on the incomplete X509Chain")]
+               public override bool Verify (X509Certificate2 thisCertificate)
+               {
+                       if (_cert == null)
+                               throw new CryptographicException (empty_error);
+
+                       X509Chain chain = X509Chain.Create ();
+                       if (!chain.Build (thisCertificate))
+                               return false;
+                       // TODO - check chain and other stuff ???
+                       return true;
+               }
+
+               // static methods
+
+               private static byte[] signedData = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02 };
+
+               [MonoTODO ("Detection limited to Cert, Pfx, Pkcs12, Pkcs7 and Unknown")]
+               public static X509ContentType GetCertContentType (byte[] rawData)
+               {
+                       if ((rawData == null) || (rawData.Length == 0))
+                               throw new ArgumentException ("rawData");
+
+                       X509ContentType type = X509ContentType.Unknown;
+                       try {
+                               ASN1 data = new ASN1 (rawData);
+                               if (data.Tag != 0x30) {
+                                       string msg = Locale.GetText ("Unable to decode certificate.");
+                                       throw new CryptographicException (msg);
+                               }
+
+                               if (data.Count == 0)
+                                       return type;
+
+                               if (data.Count == 3) {
+                                       switch (data [0].Tag) {
+                                       case 0x30:
+                                               // SEQUENCE / SEQUENCE / BITSTRING
+                                               if ((data [1].Tag == 0x30) && (data [2].Tag == 0x03))
+                                                       type = X509ContentType.Cert;
+                                               break;
+                                       case 0x02:
+                                               // INTEGER / SEQUENCE / SEQUENCE
+                                               if ((data [1].Tag == 0x30) && (data [2].Tag == 0x30))
+                                                       type = X509ContentType.Pkcs12;
+                                               // note: Pfx == Pkcs12
+                                               break;
+                                       }
+                               }
+                               // check for PKCS#7 (count unknown but greater than 0)
+                               // SEQUENCE / OID (signedData)
+                               if ((data [0].Tag == 0x06) && data [0].CompareValue (signedData))
+                                       type = X509ContentType.Pkcs7;
+                       }
+                       catch (Exception e) {
+                               string msg = Locale.GetText ("Unable to decode certificate.");
+                               throw new CryptographicException (msg, e);
+                       }
+
+                       return type;
+               }
+
+               [MonoTODO ("Detection limited to Cert, Pfx, Pkcs12 and Unknown")]
+               public static X509ContentType GetCertContentType (string fileName)
+               {
+                       if (fileName == null)
+                               throw new ArgumentNullException ("fileName");
+                       if (fileName.Length == 0)
+                               throw new ArgumentException ("fileName");
+
+                       byte[] data = File.ReadAllBytes (fileName);
+                       return GetCertContentType (data);
+               }
+
+               // internal stuff because X509Certificate2 isn't complete enough
+               // (maybe X509Certificate3 will be better?)
+
+               internal MX.X509Certificate MonoCertificate {
+                       get { return _cert; }
+               }
+       }
+}
+
+#endif
index 9910f3982705c9187eb3a6e9415a507cd9b3e61a..a7c24d385f8fe38d227f6609085127b4bf604c6a 100644 (file)
@@ -42,23 +42,27 @@ using System.Text;
 
 namespace System.Security.Cryptography.X509Certificates {
 
-       public class X509Chain {
+       public class X509Chain : IDisposable {
 
-               private StoreLocation location;
-               private X509ChainElementCollection elements;
-               private X509ChainPolicy policy;
-               private X509ChainStatus[] status;
+               X509ChainImpl impl;
 
                static X509ChainStatus[] Empty = new X509ChainStatus [0];
 
-               // RFC3280 variables
-               private int max_path_length;
-               private X500DistinguishedName working_issuer_name;
-//             private string working_public_key_algorithm;
-               private AsymmetricAlgorithm working_public_key;
+               internal X509ChainImpl Impl {
+                       get {
+                               X509Helper2.ThrowIfContextInvalid (impl);
+                               return impl;
+                       }
+               }
 
-               // other flags
-               private X509ChainElement bce_restriction;
+               internal bool IsValid {
+                       get { return X509Helper2.IsValid (impl); }
+               }
+
+               internal void ThrowIfContextInvalid ()
+               {
+                       X509Helper2.ThrowIfContextInvalid (impl);
+               }
 
                // constructors
 
@@ -69,9 +73,13 @@ namespace System.Security.Cryptography.X509Certificates {
 
                public X509Chain (bool useMachineContext) 
                {
-                       location = useMachineContext ? StoreLocation.LocalMachine : StoreLocation.CurrentUser;
-                       elements = new X509ChainElementCollection ();
-                       policy = new X509ChainPolicy ();
+                       impl = X509Helper2.CreateChainImpl (useMachineContext);
+               }
+
+               internal X509Chain (X509ChainImpl impl)
+               {
+                       X509Helper2.ThrowIfContextInvalid (impl);
+                       this.impl = impl;
                }
 
                [MonoTODO ("Mono's X509Chain is fully managed. All handles are invalid.")]
@@ -85,153 +93,37 @@ namespace System.Security.Cryptography.X509Certificates {
 
                [MonoTODO ("Mono's X509Chain is fully managed. Always returns IntPtr.Zero.")]
                public IntPtr ChainContext {
-                       get { return IntPtr.Zero; }
+                       get {
+                               if (impl != null && impl.IsValid)
+                                       return impl.Handle;
+                               return IntPtr.Zero;
+                       }
                }
 
                public X509ChainElementCollection ChainElements {
-                       get { return elements; }
+                       get { return Impl.ChainElements; }
                }
 
                public X509ChainPolicy ChainPolicy {
-                       get { return policy; }
-                       set { policy = value; }
+                       get { return Impl.ChainPolicy; }
+                       set { Impl.ChainPolicy = value; }
                }
 
                public X509ChainStatus[] ChainStatus {
-                       get { 
-                               if (status == null)
-                                       return Empty;
-                               return status;
-                       }
-               } 
+                       get { return Impl.ChainStatus; }
+               }
 
                // methods
 
                [MonoTODO ("Not totally RFC3280 compliant, but neither is MS implementation...")]
                public bool Build (X509Certificate2 certificate)
                {
-                       if (certificate == null)
-                               throw new ArgumentException ("certificate");
-
-                       Reset ();
-                       X509ChainStatusFlags flag;
-                       try {
-                               flag = BuildChainFrom (certificate);
-                               ValidateChain (flag);
-                       }
-                       catch (CryptographicException ce) {
-                               throw new ArgumentException ("certificate", ce);
-                       }
-
-                       X509ChainStatusFlags total = X509ChainStatusFlags.NoError;
-                       ArrayList list = new ArrayList ();
-                       // build "global" ChainStatus from the ChainStatus of every ChainElements
-                       foreach (X509ChainElement ce in elements) {
-                               foreach (X509ChainStatus cs in ce.ChainElementStatus) {
-                                       // we MUST avoid duplicates in the "global" list
-                                       if ((total & cs.Status) != cs.Status) {
-                                               list.Add (cs);
-                                               total |= cs.Status;
-                                       }
-                               }
-                       }
-                       // and if required add some
-                       if (flag != X509ChainStatusFlags.NoError) {
-                               list.Insert (0, new X509ChainStatus (flag));
-                       }
-                       status = (X509ChainStatus[]) list.ToArray (typeof (X509ChainStatus));
-
-                       // (fast path) this ignore everything we have checked
-                       if ((status.Length == 0) || (ChainPolicy.VerificationFlags == X509VerificationFlags.AllFlags))
-                               return true;
-
-                       bool result = true;
-                       // now check if exclude some verification for the "end result" (boolean)
-                       foreach (X509ChainStatus cs in status) {
-                               switch (cs.Status) {
-                               case X509ChainStatusFlags.UntrustedRoot:
-                               case X509ChainStatusFlags.PartialChain:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.AllowUnknownCertificateAuthority) != 0);
-                                       break;
-                               case X509ChainStatusFlags.NotTimeValid:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeValid) != 0);
-                                       break;
-                               // FIXME - from here we needs new test cases for all cases
-                               case X509ChainStatusFlags.NotTimeNested:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeNested) != 0);
-                                       break;
-                               case X509ChainStatusFlags.InvalidBasicConstraints:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidBasicConstraints) != 0);
-                                       break;
-                               case X509ChainStatusFlags.InvalidPolicyConstraints:
-                               case X509ChainStatusFlags.NoIssuanceChainPolicy:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidPolicy) != 0);
-                                       break;
-                               case X509ChainStatusFlags.InvalidNameConstraints:
-                               case X509ChainStatusFlags.HasNotSupportedNameConstraint:
-                               case X509ChainStatusFlags.HasNotPermittedNameConstraint:
-                               case X509ChainStatusFlags.HasExcludedNameConstraint:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidName) != 0);
-                                       break;
-                               case X509ChainStatusFlags.InvalidExtension:
-                                       // not sure ?!?
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
-                                       break;
-                               //
-                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreRootRevocationUnknown) != 0)
-                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreEndRevocationUnknown) != 0)
-                               case X509ChainStatusFlags.CtlNotTimeValid:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlNotTimeValid) != 0);
-                                       break;
-                               case X509ChainStatusFlags.CtlNotSignatureValid:
-                                       // ?
-                                       break;
-                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlSignerRevocationUnknown) != 0);
-                               case X509ChainStatusFlags.CtlNotValidForUsage:
-                                       // FIXME - does IgnoreWrongUsage apply to CTL (it doesn't have Ctl in it's name like the others)
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
-                                       break;
-                               default:
-                                       result = false;
-                                       break;
-                               }
-                               // once we have one failure there's no need to check further
-                               if (!result)
-                                       return false;
-                       }
-
-                       // every "problem" was excluded
-                       return true;
+                       return Impl.Build (certificate);
                }
 
                public void Reset () 
                {
-                       // note: this call doesn't Reset the X509ChainPolicy
-                       if ((status != null) && (status.Length != 0))
-                               status = null;
-                       if (elements.Count > 0)
-                               elements.Clear ();
-                       if (user_root_store != null) {
-                               user_root_store.Close ();
-                               user_root_store = null;
-                       }
-                       if (root_store != null) {
-                               root_store.Close ();
-                               root_store = null;
-                       }
-                       if (user_ca_store != null) {
-                               user_ca_store.Close ();
-                               user_ca_store = null;
-                       }
-                       if (ca_store != null) {
-                               ca_store.Close ();
-                               ca_store = null;
-                       }
-                       roots = null;
-                       cas = null;
-                       collection = null;
-                       bce_restriction = null;
-                       working_public_key = null;
+                       Impl.Reset ();
                }
 
                // static methods
@@ -245,717 +137,23 @@ namespace System.Security.Cryptography.X509Certificates {
 #endif
                }
 
-               // private stuff
-
-               private X509Certificate2Collection roots;
-               private X509Certificate2Collection cas;
-               private X509Store root_store;
-               private X509Store ca_store;
-               private X509Store user_root_store;
-               private X509Store user_ca_store;
-
-               private X509Certificate2Collection Roots {
-                       get {
-                               if (roots == null) {
-                                       X509Certificate2Collection c = new X509Certificate2Collection ();
-                                       X509Store store = LMRootStore;
-                                       if (location == StoreLocation.CurrentUser)
-                                               c.AddRange (UserRootStore.Certificates);
-                                       c.AddRange (store.Certificates);
-                                       roots = c;
-                               }
-                               return roots;
-                       }
-               }
-
-               private X509Certificate2Collection CertificateAuthorities {
-                       get {
-                               if (cas == null) {
-                                       X509Certificate2Collection c = new X509Certificate2Collection ();
-                                       X509Store store = LMCAStore;
-                                       if (location == StoreLocation.CurrentUser)
-                                               c.AddRange (UserCAStore.Certificates);
-                                       c.AddRange (store.Certificates);
-                                       cas = c;
-                               }
-                               return cas;
-                       }
-               }
-
-               private X509Store LMRootStore {
-                       get {
-                               if (root_store == null) {
-                                       root_store = new X509Store (StoreName.Root, StoreLocation.LocalMachine);
-                                       try {
-                                               root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
-                                       } catch {
-                                       }
-                               }
-                               return root_store;
-                       }
-               }
-
-               private X509Store UserRootStore {
-                       get {
-                               if (user_root_store == null) {
-                                       user_root_store = new X509Store (StoreName.Root, StoreLocation.CurrentUser);
-                                       try {
-                                               user_root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
-                                       } catch {
-                                       }
-                               }
-                               return user_root_store;
-                       }
-               }
-
-               private X509Store LMCAStore {
-                       get {
-                               if (ca_store == null) {
-                                       ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.LocalMachine);
-                                       try {
-                                               ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
-                                       } catch {
-                                       }
-                               }
-                               return ca_store;
-                       }
-               }
-
-               private X509Store UserCAStore {
-                       get {
-                               if (user_ca_store == null) {
-                                       user_ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.CurrentUser);
-                                       try {
-                                               user_ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
-                                       } catch {
-                                       }
-                               }
-                               return user_ca_store;
-                       }
-               }
-               // *** certificate chain/path building stuff ***
-
-               private X509Certificate2Collection collection;
-
-               // we search local user (default) or machine certificate store 
-               // and in the extra certificate supplied in ChainPolicy.ExtraStore
-               private X509Certificate2Collection CertificateCollection {
-                       get {
-                               if (collection == null) {
-                                       collection = new X509Certificate2Collection (ChainPolicy.ExtraStore);
-                                       collection.AddRange (Roots);
-                                       collection.AddRange (CertificateAuthorities);
-                               }
-                               return collection;
-                       }
-               }
-
-               // This is a non-recursive chain/path building algorithm. 
-               //
-               // At this stage we only checks for PartialChain, Cyclic and UntrustedRoot errors are they
-               // affect the path building (other errors are verification errors).
-               //
-               // Note that the order match the one we need to match MS and not the one defined in RFC3280,
-               // we also include the trusted root certificate (trust anchor in RFC3280) in the list.
-               // (this isn't an issue, just keep that in mind if you look at the source and the RFC)
-               private X509ChainStatusFlags BuildChainFrom (X509Certificate2 certificate)
-               {
-                       elements.Add (certificate);
-
-                       while (!IsChainComplete (certificate)) {
-                               certificate = FindParent (certificate);
-
-                               if (certificate == null)
-                                       return X509ChainStatusFlags.PartialChain;
-
-                               if (elements.Contains (certificate))
-                                       return X509ChainStatusFlags.Cyclic;
-
-                               elements.Add (certificate);
-                       }
-
-                       // roots may be supplied (e.g. in the ExtraStore) so we need to confirm their
-                       // trustiness (what a cute word) in the trusted root collection
-                       if (!Roots.Contains (certificate))
-                               elements [elements.Count - 1].StatusFlags |= X509ChainStatusFlags.UntrustedRoot;
-
-                       return X509ChainStatusFlags.NoError;
-               }
-
-
-               private X509Certificate2 SelectBestFromCollection (X509Certificate2 child, X509Certificate2Collection c)
-               {
-                       switch (c.Count) {
-                       case 0:
-                               return null;
-                       case 1:
-                               return c [0];
-                       default:
-                               // multiple candidate, keep only the ones that are still valid
-                               X509Certificate2Collection time_valid = c.Find (X509FindType.FindByTimeValid, ChainPolicy.VerificationTime, false);
-                               switch (time_valid.Count) {
-                               case 0:
-                                       // that's too restrictive, let's revert and try another thing...
-                                       time_valid = c;
-                                       break;
-                               case 1:
-                                       return time_valid [0];
-                               default:
-                                       break;
-                               }
-
-                               // again multiple candidates, let's find the AKI that match the SKI (if we have one)
-                               string aki = GetAuthorityKeyIdentifier (child);
-                               if (String.IsNullOrEmpty (aki)) {
-                                       return time_valid [0]; // FIXME: out of luck, you get the first one
-                               }
-                               foreach (X509Certificate2 parent in time_valid) {
-                                       string ski = GetSubjectKeyIdentifier (parent);
-                                       // if both id are available then they must match
-                                       if (aki == ski)
-                                               return parent;
-                               }
-                               return time_valid [0]; // FIXME: out of luck, you get the first one
-                       }
-               }
-
-               private X509Certificate2 FindParent (X509Certificate2 certificate)
-               {
-                       X509Certificate2Collection subset = CertificateCollection.Find (X509FindType.FindBySubjectDistinguishedName, certificate.Issuer, false);
-                       string aki = GetAuthorityKeyIdentifier (certificate);
-                       if ((aki != null) && (aki.Length > 0)) {
-                               subset.AddRange (CertificateCollection.Find (X509FindType.FindBySubjectKeyIdentifier, aki, false));
-                       }
-                       X509Certificate2 parent = SelectBestFromCollection (certificate, subset);
-                       // if parent==certificate we're looping but it's not (probably) a bug and not a true cyclic (over n certs)
-                       return certificate.Equals (parent) ? null : parent;
-               }
-
-               private bool IsChainComplete (X509Certificate2 certificate)
+               public void Dispose ()
                {
-                       // the chain is complete if we have a self-signed certificate
-                       if (!IsSelfIssued (certificate))
-                               return false;
-
-                       // we're very limited to what we can do without certificate extensions
-                       if (certificate.Version < 3)
-                               return true;
-
-                       // check that Authority Key Identifier == Subject Key Identifier
-                       // e.g. it will be different if a self-signed certificate is part (not the end) of the chain
-                       string ski = GetSubjectKeyIdentifier (certificate);
-                       if (String.IsNullOrEmpty (ski))
-                               return true;
-                       string aki = GetAuthorityKeyIdentifier (certificate);
-                       if (String.IsNullOrEmpty (aki))
-                               return true;
-                       // if both id are available then they must match
-                       return (aki == ski);
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
                }
 
-               // check for "self-issued" certificate - without verifying the signature
-               // note that self-issued doesn't always mean it's a root certificate!
-               private bool IsSelfIssued (X509Certificate2 certificate)
+               protected virtual void Dispose (bool disposing)
                {
-                       return (certificate.Issuer == certificate.Subject);
-               }
-
-
-               // *** certificate chain/path validation stuff ***
-
-               // Currently a subset of RFC3280 (hopefully a full implementation someday)
-               private void ValidateChain (X509ChainStatusFlags flag)
-               {
-                       // 'n' should be the root certificate... 
-                       int n = elements.Count - 1;
-                       X509Certificate2 certificate = elements [n].Certificate;
-
-                       // ... and, if so, must be treated outside the chain... 
-                       if (((flag & X509ChainStatusFlags.PartialChain) == 0)) {
-                               Process (n);
-                               // deal with the case where the chain == the root certificate 
-                               // (which isn't for RFC3280) part of the chain
-                               if (n == 0) {
-                                       elements [0].UncompressFlags ();
-                                       return;
-                               }
-                               // skip the root certificate when processing the chain (in 6.1.3)
-                               n--;
-                       }
-                       // ... unless the chain is a partial one (then we start with that one)
-
-                       // 6.1.1 - Inputs
-                       // 6.1.1.a - a prospective certificate path of length n (i.e. elements)
-                       // 6.1.1.b - the current date/time (i.e. ChainPolicy.VerificationTime)
-                       // 6.1.1.c - user-initial-policy-set (i.e. ChainPolicy.CertificatePolicy)
-                       // 6.1.1.d - the trust anchor information (i.e. certificate, unless it's a partial chain)
-                       // 6.1.1.e - initial-policy-mapping-inhibit (NOT SUPPORTED BY THE API)
-                       // 6.1.1.f - initial-explicit-policy (NOT SUPPORTED BY THE API)
-                       // 6.1.1.g - initial-any-policy-inhibit (NOT SUPPORTED BY THE API)
-
-                       // 6.1.2 - Initialization (incomplete)
-                       // 6.1.2.a-f - policy stuff, some TODO, some not supported
-                       // 6.1.2.g - working public key algorithm
-//                     working_public_key_algorithm = certificate.PublicKey.Oid.Value;
-                       // 6.1.2.h-i - our key contains both the "working public key" and "working public key parameters" data
-                       working_public_key = certificate.PublicKey.Key;
-                       // 6.1.2.j - working issuer name
-                       working_issuer_name = certificate.IssuerName;
-                       // 6.1.2.k - this integer is initialized to n, is decremented for each non-self-issued, certificate and
-                       //           may be reduced to the value in the path length constraint field
-                       max_path_length = n;
-
-                       // 6.1.3 - Basic Certificate Processing
-                       // note: loop looks reversed (the list is) but we process this part just like RFC3280 does
-                       for (int i = n; i > 0; i--) {
-                               Process (i);
-                               // 6.1.4 - preparation for certificate i+1 (for not with i+1, or i-1 in our loop)
-                               PrepareForNextCertificate (i);
+                       if (impl != null) {
+                               impl.Dispose ();
+                               impl = null;
                        }
-                       Process (0);
-
-                       // 6.1.3.a.3 - revocation checks
-                       CheckRevocationOnChain (flag);
-
-                       // 6.1.5 - Wrap-up procedure
-                       WrapUp ();
                }
 
-               private void Process (int n)
+               ~X509Chain ()
                {
-                       X509ChainElement element = elements [n];
-                       X509Certificate2 certificate = element.Certificate;
-
-                       // pre-step: DSA certificates may inherit the parameters of their CA
-                       if ((n != elements.Count - 1) && (certificate.MonoCertificate.KeyAlgorithm == "1.2.840.10040.4.1")) {
-                               if (certificate.MonoCertificate.KeyAlgorithmParameters == null) {
-                                       X509Certificate2 parent = elements [n+1].Certificate;
-                                       certificate.MonoCertificate.KeyAlgorithmParameters = parent.MonoCertificate.KeyAlgorithmParameters;
-                               }
-                       }
-
-                       bool root = (working_public_key == null);
-                       // 6.1.3.a.1 - check signature (with special case to deal with root certificates)
-                       if (!IsSignedWith (certificate, root ? certificate.PublicKey.Key : working_public_key)) {
-                               // another special case where only an end-entity is available and can't be verified.
-                               // In this case we do not report an invalid signature (since this is unknown)
-                               if (root || (n != elements.Count - 1) || IsSelfIssued (certificate)) {
-                                       element.StatusFlags |= X509ChainStatusFlags.NotSignatureValid;
-                               }
-                       }
-
-                       // 6.1.3.a.2 - check validity period
-                       if ((ChainPolicy.VerificationTime < certificate.NotBefore) ||
-                               (ChainPolicy.VerificationTime > certificate.NotAfter)) {
-                               element.StatusFlags |= X509ChainStatusFlags.NotTimeValid;
-                       }
-                       // TODO - for X509ChainStatusFlags.NotTimeNested (needs global structure)
-
-                       // note: most of them don't apply to the root certificate
-                       if (root) {
-                               return;
-                       }
-
-                       // 6.1.3.a.3 - revocation check (we're doing at the last stage)
-                       // note: you revoke a trusted root by removing it from your trusted store (i.e. no CRL can do this job)
-
-                       // 6.1.3.a.4 - check certificate issuer name
-                       if (!X500DistinguishedName.AreEqual (certificate.IssuerName, working_issuer_name)) {
-                               // NOTE: this is not the "right" error flag, but it's the closest one defined
-                               element.StatusFlags |= X509ChainStatusFlags.InvalidNameConstraints;
-                       }
-
-                       if (!IsSelfIssued (certificate) && (n != 0)) {
-                               // TODO 6.1.3.b - subject name in the permitted_subtrees ...
-                               // TODO 6.1.3.c - subject name not within excluded_subtrees...
-
-                               // TODO - check for X509ChainStatusFlags.InvalidNameConstraint
-                               // TODO - check for X509ChainStatusFlags.HasNotSupportedNameConstraint
-                               // TODO - check for X509ChainStatusFlags.HasNotPermittedNameConstraint
-                               // TODO - check for X509ChainStatusFlags.HasExcludedNameConstraint
-                       }
-
-                       // TODO 6.1.3.d - check if certificate policies extension is present
-                       //if (false) {
-                               // TODO - for X509ChainStatusFlags.InvalidPolicyConstraints
-                               //      using X509ChainPolicy.ApplicationPolicy and X509ChainPolicy.CertificatePolicy
-
-                               // TODO - check for X509ChainStatusFlags.NoIssuanceChainPolicy
-
-                       //} else {
-                               // TODO 6.1.3.e - set valid_policy_tree to NULL
-                       //}
-
-                       // TODO 6.1.3.f - verify explict_policy > 0 if valid_policy_tree != NULL
-               }
-
-               // CTL == Certificate Trust List / NOT SUPPORTED
-               // TODO - check for X509ChainStatusFlags.CtlNotTimeValid
-               // TODO - check for X509ChainStatusFlags.CtlNotSignatureValid
-               // TODO - check for X509ChainStatusFlags.CtlNotValidForUsage
-
-               private void PrepareForNextCertificate (int n) 
-               {
-                       X509ChainElement element = elements [n];
-                       X509Certificate2 certificate = element.Certificate;
-
-                       // TODO 6.1.4.a-b
-
-                       // 6.1.4.c
-                       working_issuer_name = certificate.SubjectName;
-                       // 6.1.4.d-e - our key includes both the public key and it's parameters
-                       working_public_key = certificate.PublicKey.Key;
-                       // 6.1.4.f
-//                     working_public_key_algorithm = certificate.PublicKey.Oid.Value;
-
-                       // TODO 6.1.4.g-j
-
-                       // 6.1.4.k - Verify that the certificate is a CA certificate
-                       X509BasicConstraintsExtension bce = (certificate.Extensions["2.5.29.19"] as X509BasicConstraintsExtension);
-                       if (bce != null) {
-                               if (!bce.CertificateAuthority) {
-                                       element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
-                               }
-                       } else if (certificate.Version >= 3) {
-                               // recent (v3+) CA certificates must include BCE
-                               element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
-                       }
-
-                       // 6.1.4.l - if the certificate isn't self-issued...
-                       if (!IsSelfIssued (certificate)) {
-                               // ... verify that max_path_length > 0
-                               if (max_path_length > 0) {
-                                       max_path_length--;
-                               } else {
-                                       // to match MS the reported status must be against the certificate 
-                                       // with the BCE and not where the path is too long. It also means
-                                       // that this condition has to be reported only once
-                                       if (bce_restriction != null) {
-                                               bce_restriction.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
-                                       }
-                               }
-                       }
-
-                       // 6.1.4.m - if pathLengthConstraint is present...
-                       if ((bce != null) && (bce.HasPathLengthConstraint)) {
-                               // ... and is less that max_path_length, set max_path_length to it's value
-                               if (bce.PathLengthConstraint < max_path_length) {
-                                       max_path_length = bce.PathLengthConstraint;
-                                       bce_restriction = element;
-                               }
-                       }
-
-                       // 6.1.4.n - if key usage extension is present...
-                       X509KeyUsageExtension kue = (certificate.Extensions["2.5.29.15"] as X509KeyUsageExtension);
-                       if (kue != null) {
-                               // ... verify keyCertSign is set
-                               X509KeyUsageFlags success = X509KeyUsageFlags.KeyCertSign;
-                               if ((kue.KeyUsages & success) != success)
-                                       element.StatusFlags |= X509ChainStatusFlags.NotValidForUsage;
-                       }
-
-                       // 6.1.4.o - recognize and process other critical extension present in the certificate
-                       ProcessCertificateExtensions (element);
-               }
-
-               private void WrapUp ()
-               {
-                       X509ChainElement element = elements [0];
-                       X509Certificate2 certificate = element.Certificate;
-
-                       // 6.1.5.a - TODO if certificate n (our 0) wasn't self issued and explicit_policy != 0
-                       if (IsSelfIssued (certificate)) {
-                               // TODO... decrement explicit_policy by 1
-                       }
-
-                       // 6.1.5.b - TODO
-
-                       // 6.1.5.c,d,e - not required by the X509Chain implementation
-
-                       // 6.1.5.f - recognize and process other critical extension present in the certificate
-                       ProcessCertificateExtensions (element);
-
-                       // 6.1.5.g - TODO
-
-                       // uncompressed the flags into several elements
-                       for (int i = elements.Count - 1; i >= 0; i--) {
-                               elements [i].UncompressFlags ();
-                       }
-               }
-
-               private void ProcessCertificateExtensions (X509ChainElement element)
-               {
-                       foreach (X509Extension ext in element.Certificate.Extensions) {
-                               if (ext.Critical) {
-                                       switch (ext.Oid.Value) {
-                                       case "2.5.29.15": // X509KeyUsageExtension
-                                       case "2.5.29.19": // X509BasicConstraintsExtension
-                                               // we processed this extension
-                                               break;
-                                       default:
-                                               // note: Under Windows XP MS implementation seems to ignore 
-                                               // certificate with unknown critical extensions.
-                                               element.StatusFlags |= X509ChainStatusFlags.InvalidExtension;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-
-               private bool IsSignedWith (X509Certificate2 signed, AsymmetricAlgorithm pubkey)
-               {
-                       if (pubkey == null)
-                               return false;
-                       // Sadly X509Certificate2 doesn't expose the signature nor the tbs (to be signed) structure
-                       MX.X509Certificate mx = signed.MonoCertificate;
-                       return (mx.VerifySignature (pubkey));
-               }
-
-               private string GetSubjectKeyIdentifier (X509Certificate2 certificate)
-               {
-                       X509SubjectKeyIdentifierExtension ski = (certificate.Extensions["2.5.29.14"] as X509SubjectKeyIdentifierExtension);
-                       return (ski == null) ? String.Empty : ski.SubjectKeyIdentifier;
-               }
-
-               // System.dll v2 doesn't have a class to deal with the AuthorityKeyIdentifier extension
-               static string GetAuthorityKeyIdentifier (X509Certificate2 certificate)
-               {
-                       return GetAuthorityKeyIdentifier (certificate.MonoCertificate.Extensions ["2.5.29.35"]);
-               }
-
-               // but anyway System.dll v2 doesn't expose CRL in any way so...
-               static string GetAuthorityKeyIdentifier (MX.X509Crl crl)
-               {
-                       return GetAuthorityKeyIdentifier (crl.Extensions ["2.5.29.35"]);
-               }
-
-               static string GetAuthorityKeyIdentifier (MX.X509Extension ext)
-               {
-                       if (ext == null)
-                               return String.Empty;
-                       MX.Extensions.AuthorityKeyIdentifierExtension aki = new MX.Extensions.AuthorityKeyIdentifierExtension (ext);
-                       byte[] id = aki.Identifier;
-                       if (id == null) 
-                               return String.Empty;
-                       StringBuilder sb = new StringBuilder ();
-                       foreach (byte b in id)
-                               sb.Append (b.ToString ("X02"));
-                       return sb.ToString ();
-               }
-
-               // we check the revocation only once we have built the complete chain
-               private void CheckRevocationOnChain (X509ChainStatusFlags flag)
-               {
-                       bool partial = ((flag & X509ChainStatusFlags.PartialChain) != 0);
-                       bool online;
-
-                       switch (ChainPolicy.RevocationMode) {
-                       case X509RevocationMode.Online:
-                               // default
-                               online = true;
-                               break;
-                       case X509RevocationMode.Offline:
-                               online = false;
-                               break;
-                       case X509RevocationMode.NoCheck:
-                               return;
-                       default:
-                               throw new InvalidOperationException (Locale.GetText ("Invalid revocation mode."));
-                       }
-
-                       bool unknown = partial;
-                       // from the root down to the end-entity
-                       for (int i = elements.Count - 1; i >= 0; i--) {
-                               bool check = true;
-
-                               switch (ChainPolicy.RevocationFlag) {
-                               case X509RevocationFlag.EndCertificateOnly:
-                                       check = (i == 0);
-                                       break;
-                               case X509RevocationFlag.EntireChain:
-                                       check = true;
-                                       break;
-                               case X509RevocationFlag.ExcludeRoot:
-                                       // default
-                                       check = (i != (elements.Count - 1));
-                                       // anyway, who's gonna sign that the root is invalid ?
-                                       break;
-                               }
-
-                               X509ChainElement element = elements [i];
-
-                               // we can't assume the revocation status if the certificate is bad (e.g. invalid signature)
-                               if (!unknown)
-                                       unknown |= ((element.StatusFlags & X509ChainStatusFlags.NotSignatureValid) != 0);
-
-                               if (unknown) {
-                                       // we can skip the revocation checks as we can't be sure of them anyway
-                                       element.StatusFlags |= X509ChainStatusFlags.RevocationStatusUnknown;
-                                       element.StatusFlags |= X509ChainStatusFlags.OfflineRevocation;
-                               } else if (check && !partial && !IsSelfIssued (element.Certificate)) {
-                                       // check for revocation (except for the trusted root and self-issued certs)
-                                       element.StatusFlags |= CheckRevocation (element.Certificate, i+1, online);
-                                       // if revoked, then all others following in the chain are unknown...
-                                       unknown |= ((element.StatusFlags & X509ChainStatusFlags.Revoked) != 0);
-                               }
-                       }
-               }
-
-               // This isn't how RFC3280 (section 6.3) deals with CRL, but then we don't (yet) support DP, deltas...
-               private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, int ca, bool online)
-               {
-                       X509ChainStatusFlags result = X509ChainStatusFlags.RevocationStatusUnknown;
-                       X509ChainElement element = elements [ca];
-                       X509Certificate2 ca_cert = element.Certificate;
-
-                       // find the CRL from the "right" CA
-                       while (IsSelfIssued (ca_cert) && (ca < elements.Count - 1)) {
-                               // try with this self-issued
-                               result = CheckRevocation (certificate, ca_cert, online);
-                               if (result != X509ChainStatusFlags.RevocationStatusUnknown)
-                                       break;
-                               ca++;
-                               element = elements [ca];
-                               ca_cert = element.Certificate;
-                       }
-                       if (result == X509ChainStatusFlags.RevocationStatusUnknown)
-                               result = CheckRevocation (certificate, ca_cert, online);
-                       return result;
-               }
-
-               private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, X509Certificate2 ca_cert, bool online)
-               {
-                       // change this if/when we support OCSP
-                       X509KeyUsageExtension kue = (ca_cert.Extensions["2.5.29.15"] as X509KeyUsageExtension);
-                       if (kue != null) {
-                               // ... verify CrlSign is set
-                               X509KeyUsageFlags success = X509KeyUsageFlags.CrlSign;
-                               if ((kue.KeyUsages & success) != success) {
-                                       // FIXME - we should try to find an alternative CA that has the CrlSign bit
-                                       return X509ChainStatusFlags.RevocationStatusUnknown;
-                               }
-                       }
-
-                       MX.X509Crl crl = FindCrl (ca_cert);
-
-                       if ((crl == null) && online) {
-                               // FIXME - download and install new CRL
-                               // then you get a second chance
-                               // crl = FindCrl (ca_cert, ref valid, ref out_of_date);
-
-                               // We need to get the subjectAltName and an URI from there (or use OCSP)        
-                               // X509KeyUsageExtension subjectAltName = (ca_cert.Extensions["2.5.29.17"] as X509KeyUsageExtension);
-                       }
-
-                       if (crl != null) {
-                               // validate the digital signature on the CRL using the CA public key
-                               // note #1: we can't use X509Crl.VerifySignature(X509Certificate) because it duplicates
-                               // checks and we loose the "why" of the failure
-                               // note #2: we do this before other tests as an invalid signature could be a hacked CRL
-                               // (so anything within can't be trusted)
-                               if (!crl.VerifySignature (ca_cert.PublicKey.Key)) {
-                                       return X509ChainStatusFlags.RevocationStatusUnknown;
-                               }
-
-                               MX.X509Crl.X509CrlEntry entry = crl.GetCrlEntry (certificate.MonoCertificate);
-                               if (entry != null) {
-                                       // We have an entry for this CRL that includes an unknown CRITICAL extension
-                                       // See [X.509 7.3] NOTE 4
-                                       if (!ProcessCrlEntryExtensions (entry))
-                                               return X509ChainStatusFlags.Revoked;
-
-                                       // FIXME - a little more is involved
-                                       if (entry.RevocationDate <= ChainPolicy.VerificationTime)
-                                               return X509ChainStatusFlags.Revoked;
-                               }
-
-                               // are we overdue for a CRL update ? if so we can't be sure of any certificate status
-                               if (crl.NextUpdate < ChainPolicy.VerificationTime)
-                                       return X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation;
-
-                               // we have a CRL that includes an unknown CRITICAL extension
-                               // we put this check at the end so we do not "hide" any Revoked flags
-                               if (!ProcessCrlExtensions (crl)) {
-                                       return X509ChainStatusFlags.RevocationStatusUnknown;
-                               }
-                       } else {
-                               return X509ChainStatusFlags.RevocationStatusUnknown;
-                       }
-
-                       return X509ChainStatusFlags.NoError;
-               }
-
-               static MX.X509Crl CheckCrls (string subject, string ski, MX.X509Store store)
-               {
-                       if (store == null)
-                               return null;
-
-                       var crls = store.Crls;
-                       foreach (MX.X509Crl crl in crls) {
-                               if (crl.IssuerName == subject && (ski.Length == 0 || ski == GetAuthorityKeyIdentifier (crl)))
-                                       return crl;
-                       }
-                       return null; // No CRL found
-               }
-
-               private MX.X509Crl FindCrl (X509Certificate2 caCertificate)
-               {
-                       string subject = caCertificate.SubjectName.Decode (X500DistinguishedNameFlags.None);
-                       string ski = GetSubjectKeyIdentifier (caCertificate);
-
-                       // consider that the LocalMachine directories could not exists... and cannot be created by the user
-                       MX.X509Crl result = CheckCrls (subject, ski, LMCAStore.Store);
-                       if (result != null)
-                               return result;
-                       if (location == StoreLocation.CurrentUser) {
-                               result = CheckCrls (subject, ski, UserCAStore.Store);
-                               if (result != null)
-                                       return result;
-                       }
-
-                       // consider that the LocalMachine directories could not exists... and cannot be created by the user
-                       result = CheckCrls (subject, ski, LMRootStore.Store);
-                       if (result != null)
-                               return result;
-                       if (location == StoreLocation.CurrentUser) {
-                               result = CheckCrls (subject, ski, UserRootStore.Store);
-                               if (result != null)
-                                       return result;
-                       }
-                       return null;
-               }
-
-               private bool ProcessCrlExtensions (MX.X509Crl crl)
-               {
-                       foreach (MX.X509Extension ext in crl.Extensions) {
-                               if (ext.Critical) {
-                                       switch (ext.Oid) {
-                                       case "2.5.29.20": // cRLNumber
-                                       case "2.5.29.35": // authorityKeyIdentifier
-                                               // we processed/know about this extension
-                                               break;
-                                       default:
-                                               return false;
-                                       }
-                               }
-                       }
-                       return true;
-               }
-
-               private bool ProcessCrlEntryExtensions (MX.X509Crl.X509CrlEntry entry)
-               {
-                       foreach (MX.X509Extension ext in entry.Extensions) {
-                               if (ext.Critical) {
-                                       switch (ext.Oid) {
-                                       case "2.5.29.21": // cRLReason
-                                               // we processed/know about this extension
-                                               break;
-                                       default:
-                                               return false;
-                                       }
-                               }
-                       }
-                       return true;
+                       Dispose (false);
                }
        }
 }
diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImpl.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImpl.cs
new file mode 100644 (file)
index 0000000..2a4c9cf
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// X509ChainImpl.cs
+//
+// Authors:
+//     Martin Baulig  <martin.baulig@xamarin.com>
+//
+// Copyright (C) 2016 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 SECURITY_DEP
+
+namespace System.Security.Cryptography.X509Certificates
+{
+       internal abstract class X509ChainImpl : IDisposable
+       {
+               public abstract bool IsValid {
+                       get;
+               }
+
+               public abstract IntPtr Handle {
+                       get;
+               }
+
+               protected void ThrowIfContextInvalid ()
+               {
+                       if (!IsValid)
+                               throw X509Helper2.GetInvalidChainContextException ();
+               }
+
+               public abstract X509ChainElementCollection ChainElements {
+                       get;
+               }
+
+               public abstract X509ChainPolicy ChainPolicy {
+                       get; set;
+               }
+
+               public abstract X509ChainStatus[] ChainStatus {
+                       get;
+               }
+
+               public abstract bool Build (X509Certificate2 certificate);
+
+               public abstract void Reset ();
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+               }
+
+               ~X509ChainImpl ()
+               {
+                       Dispose (false);
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs
new file mode 100644 (file)
index 0000000..210bd8f
--- /dev/null
@@ -0,0 +1,954 @@
+//
+// System.Security.Cryptography.X509Certificates.X509ChainImplMono
+//
+// Author:
+//     Sebastien Pouliot  <sebastien@ximian.com>
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
+// Copyright (C) 2011 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 SECURITY_DEP
+
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+using MX = MonoSecurity::Mono.Security.X509;
+#else
+using MX = Mono.Security.X509;
+#endif
+
+using System.Collections;
+using System.Text;
+
+namespace System.Security.Cryptography.X509Certificates {
+
+       internal class X509ChainImplMono : X509ChainImpl
+       {
+               private StoreLocation location;
+               private X509ChainElementCollection elements;
+               private X509ChainPolicy policy;
+               private X509ChainStatus[] status;
+
+               static X509ChainStatus[] Empty = new X509ChainStatus [0];
+
+               // RFC3280 variables
+               private int max_path_length;
+               private X500DistinguishedName working_issuer_name;
+//             private string working_public_key_algorithm;
+               private AsymmetricAlgorithm working_public_key;
+
+               // other flags
+               private X509ChainElement bce_restriction;
+
+               // constructors
+
+               public X509ChainImplMono ()
+                       : this (false)
+               {
+               }
+
+               public X509ChainImplMono (bool useMachineContext) 
+               {
+                       location = useMachineContext ? StoreLocation.LocalMachine : StoreLocation.CurrentUser;
+                       elements = new X509ChainElementCollection ();
+                       policy = new X509ChainPolicy ();
+               }
+
+               [MonoTODO ("Mono's X509Chain is fully managed. All handles are invalid.")]
+               public X509ChainImplMono (IntPtr chainContext)
+               {
+                       // CryptoAPI compatibility (unmanaged handle)
+                       throw new NotSupportedException ();
+               }
+
+               public override bool IsValid {
+                       get { return true; }
+               }
+
+               public override IntPtr Handle {
+                       get { return IntPtr.Zero; }
+               }
+
+               // properties
+
+               public override X509ChainElementCollection ChainElements {
+                       get { return elements; }
+               }
+
+               public override X509ChainPolicy ChainPolicy {
+                       get { return policy; }
+                       set { policy = value; }
+               }
+
+               public override X509ChainStatus[] ChainStatus {
+                       get { 
+                               if (status == null)
+                                       return Empty;
+                               return status;
+                       }
+               } 
+
+               // methods
+
+               [MonoTODO ("Not totally RFC3280 compliant, but neither is MS implementation...")]
+               public override bool Build (X509Certificate2 certificate)
+               {
+                       if (certificate == null)
+                               throw new ArgumentException ("certificate");
+
+                       Reset ();
+                       X509ChainStatusFlags flag;
+                       try {
+                               flag = BuildChainFrom (certificate);
+                               ValidateChain (flag);
+                       }
+                       catch (CryptographicException ce) {
+                               throw new ArgumentException ("certificate", ce);
+                       }
+
+                       X509ChainStatusFlags total = X509ChainStatusFlags.NoError;
+                       ArrayList list = new ArrayList ();
+                       // build "global" ChainStatus from the ChainStatus of every ChainElements
+                       foreach (X509ChainElement ce in elements) {
+                               foreach (X509ChainStatus cs in ce.ChainElementStatus) {
+                                       // we MUST avoid duplicates in the "global" list
+                                       if ((total & cs.Status) != cs.Status) {
+                                               list.Add (cs);
+                                               total |= cs.Status;
+                                       }
+                               }
+                       }
+                       // and if required add some
+                       if (flag != X509ChainStatusFlags.NoError) {
+                               list.Insert (0, new X509ChainStatus (flag));
+                       }
+                       status = (X509ChainStatus[]) list.ToArray (typeof (X509ChainStatus));
+
+                       // (fast path) this ignore everything we have checked
+                       if ((status.Length == 0) || (ChainPolicy.VerificationFlags == X509VerificationFlags.AllFlags))
+                               return true;
+
+                       bool result = true;
+                       // now check if exclude some verification for the "end result" (boolean)
+                       foreach (X509ChainStatus cs in status) {
+                               switch (cs.Status) {
+                               case X509ChainStatusFlags.UntrustedRoot:
+                               case X509ChainStatusFlags.PartialChain:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.AllowUnknownCertificateAuthority) != 0);
+                                       break;
+                               case X509ChainStatusFlags.NotTimeValid:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeValid) != 0);
+                                       break;
+                               // FIXME - from here we needs new test cases for all cases
+                               case X509ChainStatusFlags.NotTimeNested:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeNested) != 0);
+                                       break;
+                               case X509ChainStatusFlags.InvalidBasicConstraints:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidBasicConstraints) != 0);
+                                       break;
+                               case X509ChainStatusFlags.InvalidPolicyConstraints:
+                               case X509ChainStatusFlags.NoIssuanceChainPolicy:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidPolicy) != 0);
+                                       break;
+                               case X509ChainStatusFlags.InvalidNameConstraints:
+                               case X509ChainStatusFlags.HasNotSupportedNameConstraint:
+                               case X509ChainStatusFlags.HasNotPermittedNameConstraint:
+                               case X509ChainStatusFlags.HasExcludedNameConstraint:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidName) != 0);
+                                       break;
+                               case X509ChainStatusFlags.InvalidExtension:
+                                       // not sure ?!?
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
+                                       break;
+                               //
+                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreRootRevocationUnknown) != 0)
+                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreEndRevocationUnknown) != 0)
+                               case X509ChainStatusFlags.CtlNotTimeValid:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlNotTimeValid) != 0);
+                                       break;
+                               case X509ChainStatusFlags.CtlNotSignatureValid:
+                                       // ?
+                                       break;
+                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlSignerRevocationUnknown) != 0);
+                               case X509ChainStatusFlags.CtlNotValidForUsage:
+                                       // FIXME - does IgnoreWrongUsage apply to CTL (it doesn't have Ctl in it's name like the others)
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
+                                       break;
+                               default:
+                                       result = false;
+                                       break;
+                               }
+                               // once we have one failure there's no need to check further
+                               if (!result)
+                                       return false;
+                       }
+
+                       // every "problem" was excluded
+                       return true;
+               }
+
+               public override void Reset () 
+               {
+                       // note: this call doesn't Reset the X509ChainPolicy
+                       if ((status != null) && (status.Length != 0))
+                               status = null;
+                       if (elements.Count > 0)
+                               elements.Clear ();
+                       if (user_root_store != null) {
+                               user_root_store.Close ();
+                               user_root_store = null;
+                       }
+                       if (root_store != null) {
+                               root_store.Close ();
+                               root_store = null;
+                       }
+                       if (user_ca_store != null) {
+                               user_ca_store.Close ();
+                               user_ca_store = null;
+                       }
+                       if (ca_store != null) {
+                               ca_store.Close ();
+                               ca_store = null;
+                       }
+                       roots = null;
+                       cas = null;
+                       collection = null;
+                       bce_restriction = null;
+                       working_public_key = null;
+               }
+
+               // private stuff
+
+               private X509Certificate2Collection roots;
+               private X509Certificate2Collection cas;
+               private X509Store root_store;
+               private X509Store ca_store;
+               private X509Store user_root_store;
+               private X509Store user_ca_store;
+
+               private X509Certificate2Collection Roots {
+                       get {
+                               if (roots == null) {
+                                       X509Certificate2Collection c = new X509Certificate2Collection ();
+                                       X509Store store = LMRootStore;
+                                       if (location == StoreLocation.CurrentUser)
+                                               c.AddRange (UserRootStore.Certificates);
+                                       c.AddRange (store.Certificates);
+                                       roots = c;
+                               }
+                               return roots;
+                       }
+               }
+
+               private X509Certificate2Collection CertificateAuthorities {
+                       get {
+                               if (cas == null) {
+                                       X509Certificate2Collection c = new X509Certificate2Collection ();
+                                       X509Store store = LMCAStore;
+                                       if (location == StoreLocation.CurrentUser)
+                                               c.AddRange (UserCAStore.Certificates);
+                                       c.AddRange (store.Certificates);
+                                       cas = c;
+                               }
+                               return cas;
+                       }
+               }
+
+               private X509Store LMRootStore {
+                       get {
+                               if (root_store == null) {
+                                       root_store = new X509Store (StoreName.Root, StoreLocation.LocalMachine);
+                                       try {
+                                               root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
+                                       } catch {
+                                       }
+                               }
+                               return root_store;
+                       }
+               }
+
+               private X509Store UserRootStore {
+                       get {
+                               if (user_root_store == null) {
+                                       user_root_store = new X509Store (StoreName.Root, StoreLocation.CurrentUser);
+                                       try {
+                                               user_root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
+                                       } catch {
+                                       }
+                               }
+                               return user_root_store;
+                       }
+               }
+
+               private X509Store LMCAStore {
+                       get {
+                               if (ca_store == null) {
+                                       ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.LocalMachine);
+                                       try {
+                                               ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
+                                       } catch {
+                                       }
+                               }
+                               return ca_store;
+                       }
+               }
+
+               private X509Store UserCAStore {
+                       get {
+                               if (user_ca_store == null) {
+                                       user_ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.CurrentUser);
+                                       try {
+                                               user_ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
+                                       } catch {
+                                       }
+                               }
+                               return user_ca_store;
+                       }
+               }
+               // *** certificate chain/path building stuff ***
+
+               private X509Certificate2Collection collection;
+
+               // we search local user (default) or machine certificate store 
+               // and in the extra certificate supplied in ChainPolicy.ExtraStore
+               private X509Certificate2Collection CertificateCollection {
+                       get {
+                               if (collection == null) {
+                                       collection = new X509Certificate2Collection (ChainPolicy.ExtraStore);
+                                       collection.AddRange (Roots);
+                                       collection.AddRange (CertificateAuthorities);
+                               }
+                               return collection;
+                       }
+               }
+
+               // This is a non-recursive chain/path building algorithm. 
+               //
+               // At this stage we only checks for PartialChain, Cyclic and UntrustedRoot errors are they
+               // affect the path building (other errors are verification errors).
+               //
+               // Note that the order match the one we need to match MS and not the one defined in RFC3280,
+               // we also include the trusted root certificate (trust anchor in RFC3280) in the list.
+               // (this isn't an issue, just keep that in mind if you look at the source and the RFC)
+               private X509ChainStatusFlags BuildChainFrom (X509Certificate2 certificate)
+               {
+                       elements.Add (certificate);
+
+                       while (!IsChainComplete (certificate)) {
+                               certificate = FindParent (certificate);
+
+                               if (certificate == null)
+                                       return X509ChainStatusFlags.PartialChain;
+
+                               if (elements.Contains (certificate))
+                                       return X509ChainStatusFlags.Cyclic;
+
+                               elements.Add (certificate);
+                       }
+
+                       // roots may be supplied (e.g. in the ExtraStore) so we need to confirm their
+                       // trustiness (what a cute word) in the trusted root collection
+                       if (!Roots.Contains (certificate))
+                               elements [elements.Count - 1].StatusFlags |= X509ChainStatusFlags.UntrustedRoot;
+
+                       return X509ChainStatusFlags.NoError;
+               }
+
+
+               private X509Certificate2 SelectBestFromCollection (X509Certificate2 child, X509Certificate2Collection c)
+               {
+                       switch (c.Count) {
+                       case 0:
+                               return null;
+                       case 1:
+                               return c [0];
+                       default:
+                               // multiple candidate, keep only the ones that are still valid
+                               X509Certificate2Collection time_valid = c.Find (X509FindType.FindByTimeValid, ChainPolicy.VerificationTime, false);
+                               switch (time_valid.Count) {
+                               case 0:
+                                       // that's too restrictive, let's revert and try another thing...
+                                       time_valid = c;
+                                       break;
+                               case 1:
+                                       return time_valid [0];
+                               default:
+                                       break;
+                               }
+
+                               // again multiple candidates, let's find the AKI that match the SKI (if we have one)
+                               string aki = GetAuthorityKeyIdentifier (child);
+                               if (String.IsNullOrEmpty (aki)) {
+                                       return time_valid [0]; // FIXME: out of luck, you get the first one
+                               }
+                               foreach (X509Certificate2 parent in time_valid) {
+                                       string ski = GetSubjectKeyIdentifier (parent);
+                                       // if both id are available then they must match
+                                       if (aki == ski)
+                                               return parent;
+                               }
+                               return time_valid [0]; // FIXME: out of luck, you get the first one
+                       }
+               }
+
+               private X509Certificate2 FindParent (X509Certificate2 certificate)
+               {
+                       X509Certificate2Collection subset = CertificateCollection.Find (X509FindType.FindBySubjectDistinguishedName, certificate.Issuer, false);
+                       string aki = GetAuthorityKeyIdentifier (certificate);
+                       if ((aki != null) && (aki.Length > 0)) {
+                               subset.AddRange (CertificateCollection.Find (X509FindType.FindBySubjectKeyIdentifier, aki, false));
+                       }
+                       X509Certificate2 parent = SelectBestFromCollection (certificate, subset);
+                       // if parent==certificate we're looping but it's not (probably) a bug and not a true cyclic (over n certs)
+                       return certificate.Equals (parent) ? null : parent;
+               }
+
+               private bool IsChainComplete (X509Certificate2 certificate)
+               {
+                       // the chain is complete if we have a self-signed certificate
+                       if (!IsSelfIssued (certificate))
+                               return false;
+
+                       // we're very limited to what we can do without certificate extensions
+                       if (certificate.Version < 3)
+                               return true;
+
+                       // check that Authority Key Identifier == Subject Key Identifier
+                       // e.g. it will be different if a self-signed certificate is part (not the end) of the chain
+                       string ski = GetSubjectKeyIdentifier (certificate);
+                       if (String.IsNullOrEmpty (ski))
+                               return true;
+                       string aki = GetAuthorityKeyIdentifier (certificate);
+                       if (String.IsNullOrEmpty (aki))
+                               return true;
+                       // if both id are available then they must match
+                       return (aki == ski);
+               }
+
+               // check for "self-issued" certificate - without verifying the signature
+               // note that self-issued doesn't always mean it's a root certificate!
+               private bool IsSelfIssued (X509Certificate2 certificate)
+               {
+                       return (certificate.Issuer == certificate.Subject);
+               }
+
+
+               // *** certificate chain/path validation stuff ***
+
+               // Currently a subset of RFC3280 (hopefully a full implementation someday)
+               private void ValidateChain (X509ChainStatusFlags flag)
+               {
+                       // 'n' should be the root certificate... 
+                       int n = elements.Count - 1;
+                       X509Certificate2 certificate = elements [n].Certificate;
+
+                       // ... and, if so, must be treated outside the chain... 
+                       if (((flag & X509ChainStatusFlags.PartialChain) == 0)) {
+                               Process (n);
+                               // deal with the case where the chain == the root certificate 
+                               // (which isn't for RFC3280) part of the chain
+                               if (n == 0) {
+                                       elements [0].UncompressFlags ();
+                                       return;
+                               }
+                               // skip the root certificate when processing the chain (in 6.1.3)
+                               n--;
+                       }
+                       // ... unless the chain is a partial one (then we start with that one)
+
+                       // 6.1.1 - Inputs
+                       // 6.1.1.a - a prospective certificate path of length n (i.e. elements)
+                       // 6.1.1.b - the current date/time (i.e. ChainPolicy.VerificationTime)
+                       // 6.1.1.c - user-initial-policy-set (i.e. ChainPolicy.CertificatePolicy)
+                       // 6.1.1.d - the trust anchor information (i.e. certificate, unless it's a partial chain)
+                       // 6.1.1.e - initial-policy-mapping-inhibit (NOT SUPPORTED BY THE API)
+                       // 6.1.1.f - initial-explicit-policy (NOT SUPPORTED BY THE API)
+                       // 6.1.1.g - initial-any-policy-inhibit (NOT SUPPORTED BY THE API)
+
+                       // 6.1.2 - Initialization (incomplete)
+                       // 6.1.2.a-f - policy stuff, some TODO, some not supported
+                       // 6.1.2.g - working public key algorithm
+//                     working_public_key_algorithm = certificate.PublicKey.Oid.Value;
+                       // 6.1.2.h-i - our key contains both the "working public key" and "working public key parameters" data
+                       working_public_key = certificate.PublicKey.Key;
+                       // 6.1.2.j - working issuer name
+                       working_issuer_name = certificate.IssuerName;
+                       // 6.1.2.k - this integer is initialized to n, is decremented for each non-self-issued, certificate and
+                       //           may be reduced to the value in the path length constraint field
+                       max_path_length = n;
+
+                       // 6.1.3 - Basic Certificate Processing
+                       // note: loop looks reversed (the list is) but we process this part just like RFC3280 does
+                       for (int i = n; i > 0; i--) {
+                               Process (i);
+                               // 6.1.4 - preparation for certificate i+1 (for not with i+1, or i-1 in our loop)
+                               PrepareForNextCertificate (i);
+                       }
+                       Process (0);
+
+                       // 6.1.3.a.3 - revocation checks
+                       CheckRevocationOnChain (flag);
+
+                       // 6.1.5 - Wrap-up procedure
+                       WrapUp ();
+               }
+
+               private void Process (int n)
+               {
+                       X509ChainElement element = elements [n];
+                       X509Certificate2 certificate = element.Certificate;
+
+                       // pre-step: DSA certificates may inherit the parameters of their CA
+                       if ((n != elements.Count - 1) && (certificate.MonoCertificate.KeyAlgorithm == "1.2.840.10040.4.1")) {
+                               if (certificate.MonoCertificate.KeyAlgorithmParameters == null) {
+                                       X509Certificate2 parent = elements [n+1].Certificate;
+                                       certificate.MonoCertificate.KeyAlgorithmParameters = parent.MonoCertificate.KeyAlgorithmParameters;
+                               }
+                       }
+
+                       bool root = (working_public_key == null);
+                       // 6.1.3.a.1 - check signature (with special case to deal with root certificates)
+                       if (!IsSignedWith (certificate, root ? certificate.PublicKey.Key : working_public_key)) {
+                               // another special case where only an end-entity is available and can't be verified.
+                               // In this case we do not report an invalid signature (since this is unknown)
+                               if (root || (n != elements.Count - 1) || IsSelfIssued (certificate)) {
+                                       element.StatusFlags |= X509ChainStatusFlags.NotSignatureValid;
+                               }
+                       }
+
+                       // 6.1.3.a.2 - check validity period
+                       if ((ChainPolicy.VerificationTime < certificate.NotBefore) ||
+                               (ChainPolicy.VerificationTime > certificate.NotAfter)) {
+                               element.StatusFlags |= X509ChainStatusFlags.NotTimeValid;
+                       }
+                       // TODO - for X509ChainStatusFlags.NotTimeNested (needs global structure)
+
+                       // note: most of them don't apply to the root certificate
+                       if (root) {
+                               return;
+                       }
+
+                       // 6.1.3.a.3 - revocation check (we're doing at the last stage)
+                       // note: you revoke a trusted root by removing it from your trusted store (i.e. no CRL can do this job)
+
+                       // 6.1.3.a.4 - check certificate issuer name
+                       if (!X500DistinguishedName.AreEqual (certificate.IssuerName, working_issuer_name)) {
+                               // NOTE: this is not the "right" error flag, but it's the closest one defined
+                               element.StatusFlags |= X509ChainStatusFlags.InvalidNameConstraints;
+                       }
+
+                       if (!IsSelfIssued (certificate) && (n != 0)) {
+                               // TODO 6.1.3.b - subject name in the permitted_subtrees ...
+                               // TODO 6.1.3.c - subject name not within excluded_subtrees...
+
+                               // TODO - check for X509ChainStatusFlags.InvalidNameConstraint
+                               // TODO - check for X509ChainStatusFlags.HasNotSupportedNameConstraint
+                               // TODO - check for X509ChainStatusFlags.HasNotPermittedNameConstraint
+                               // TODO - check for X509ChainStatusFlags.HasExcludedNameConstraint
+                       }
+
+                       // TODO 6.1.3.d - check if certificate policies extension is present
+                       //if (false) {
+                               // TODO - for X509ChainStatusFlags.InvalidPolicyConstraints
+                               //      using X509ChainPolicy.ApplicationPolicy and X509ChainPolicy.CertificatePolicy
+
+                               // TODO - check for X509ChainStatusFlags.NoIssuanceChainPolicy
+
+                       //} else {
+                               // TODO 6.1.3.e - set valid_policy_tree to NULL
+                       //}
+
+                       // TODO 6.1.3.f - verify explict_policy > 0 if valid_policy_tree != NULL
+               }
+
+               // CTL == Certificate Trust List / NOT SUPPORTED
+               // TODO - check for X509ChainStatusFlags.CtlNotTimeValid
+               // TODO - check for X509ChainStatusFlags.CtlNotSignatureValid
+               // TODO - check for X509ChainStatusFlags.CtlNotValidForUsage
+
+               private void PrepareForNextCertificate (int n) 
+               {
+                       X509ChainElement element = elements [n];
+                       X509Certificate2 certificate = element.Certificate;
+
+                       // TODO 6.1.4.a-b
+
+                       // 6.1.4.c
+                       working_issuer_name = certificate.SubjectName;
+                       // 6.1.4.d-e - our key includes both the public key and it's parameters
+                       working_public_key = certificate.PublicKey.Key;
+                       // 6.1.4.f
+//                     working_public_key_algorithm = certificate.PublicKey.Oid.Value;
+
+                       // TODO 6.1.4.g-j
+
+                       // 6.1.4.k - Verify that the certificate is a CA certificate
+                       X509BasicConstraintsExtension bce = (certificate.Extensions["2.5.29.19"] as X509BasicConstraintsExtension);
+                       if (bce != null) {
+                               if (!bce.CertificateAuthority) {
+                                       element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
+                               }
+                       } else if (certificate.Version >= 3) {
+                               // recent (v3+) CA certificates must include BCE
+                               element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
+                       }
+
+                       // 6.1.4.l - if the certificate isn't self-issued...
+                       if (!IsSelfIssued (certificate)) {
+                               // ... verify that max_path_length > 0
+                               if (max_path_length > 0) {
+                                       max_path_length--;
+                               } else {
+                                       // to match MS the reported status must be against the certificate 
+                                       // with the BCE and not where the path is too long. It also means
+                                       // that this condition has to be reported only once
+                                       if (bce_restriction != null) {
+                                               bce_restriction.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
+                                       }
+                               }
+                       }
+
+                       // 6.1.4.m - if pathLengthConstraint is present...
+                       if ((bce != null) && (bce.HasPathLengthConstraint)) {
+                               // ... and is less that max_path_length, set max_path_length to it's value
+                               if (bce.PathLengthConstraint < max_path_length) {
+                                       max_path_length = bce.PathLengthConstraint;
+                                       bce_restriction = element;
+                               }
+                       }
+
+                       // 6.1.4.n - if key usage extension is present...
+                       X509KeyUsageExtension kue = (certificate.Extensions["2.5.29.15"] as X509KeyUsageExtension);
+                       if (kue != null) {
+                               // ... verify keyCertSign is set
+                               X509KeyUsageFlags success = X509KeyUsageFlags.KeyCertSign;
+                               if ((kue.KeyUsages & success) != success)
+                                       element.StatusFlags |= X509ChainStatusFlags.NotValidForUsage;
+                       }
+
+                       // 6.1.4.o - recognize and process other critical extension present in the certificate
+                       ProcessCertificateExtensions (element);
+               }
+
+               private void WrapUp ()
+               {
+                       X509ChainElement element = elements [0];
+                       X509Certificate2 certificate = element.Certificate;
+
+                       // 6.1.5.a - TODO if certificate n (our 0) wasn't self issued and explicit_policy != 0
+                       if (IsSelfIssued (certificate)) {
+                               // TODO... decrement explicit_policy by 1
+                       }
+
+                       // 6.1.5.b - TODO
+
+                       // 6.1.5.c,d,e - not required by the X509Chain implementation
+
+                       // 6.1.5.f - recognize and process other critical extension present in the certificate
+                       ProcessCertificateExtensions (element);
+
+                       // 6.1.5.g - TODO
+
+                       // uncompressed the flags into several elements
+                       for (int i = elements.Count - 1; i >= 0; i--) {
+                               elements [i].UncompressFlags ();
+                       }
+               }
+
+               private void ProcessCertificateExtensions (X509ChainElement element)
+               {
+                       foreach (X509Extension ext in element.Certificate.Extensions) {
+                               if (ext.Critical) {
+                                       switch (ext.Oid.Value) {
+                                       case "2.5.29.15": // X509KeyUsageExtension
+                                       case "2.5.29.19": // X509BasicConstraintsExtension
+                                               // we processed this extension
+                                               break;
+                                       default:
+                                               // note: Under Windows XP MS implementation seems to ignore 
+                                               // certificate with unknown critical extensions.
+                                               element.StatusFlags |= X509ChainStatusFlags.InvalidExtension;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               private bool IsSignedWith (X509Certificate2 signed, AsymmetricAlgorithm pubkey)
+               {
+                       if (pubkey == null)
+                               return false;
+                       // Sadly X509Certificate2 doesn't expose the signature nor the tbs (to be signed) structure
+                       MX.X509Certificate mx = signed.MonoCertificate;
+                       return (mx.VerifySignature (pubkey));
+               }
+
+               private string GetSubjectKeyIdentifier (X509Certificate2 certificate)
+               {
+                       X509SubjectKeyIdentifierExtension ski = (certificate.Extensions["2.5.29.14"] as X509SubjectKeyIdentifierExtension);
+                       return (ski == null) ? String.Empty : ski.SubjectKeyIdentifier;
+               }
+
+               // System.dll v2 doesn't have a class to deal with the AuthorityKeyIdentifier extension
+               static string GetAuthorityKeyIdentifier (X509Certificate2 certificate)
+               {
+                       return GetAuthorityKeyIdentifier (certificate.MonoCertificate.Extensions ["2.5.29.35"]);
+               }
+
+               // but anyway System.dll v2 doesn't expose CRL in any way so...
+               static string GetAuthorityKeyIdentifier (MX.X509Crl crl)
+               {
+                       return GetAuthorityKeyIdentifier (crl.Extensions ["2.5.29.35"]);
+               }
+
+               static string GetAuthorityKeyIdentifier (MX.X509Extension ext)
+               {
+                       if (ext == null)
+                               return String.Empty;
+                       MX.Extensions.AuthorityKeyIdentifierExtension aki = new MX.Extensions.AuthorityKeyIdentifierExtension (ext);
+                       byte[] id = aki.Identifier;
+                       if (id == null) 
+                               return String.Empty;
+                       StringBuilder sb = new StringBuilder ();
+                       foreach (byte b in id)
+                               sb.Append (b.ToString ("X02"));
+                       return sb.ToString ();
+               }
+
+               // we check the revocation only once we have built the complete chain
+               private void CheckRevocationOnChain (X509ChainStatusFlags flag)
+               {
+                       bool partial = ((flag & X509ChainStatusFlags.PartialChain) != 0);
+                       bool online;
+
+                       switch (ChainPolicy.RevocationMode) {
+                       case X509RevocationMode.Online:
+                               // default
+                               online = true;
+                               break;
+                       case X509RevocationMode.Offline:
+                               online = false;
+                               break;
+                       case X509RevocationMode.NoCheck:
+                               return;
+                       default:
+                               throw new InvalidOperationException (Locale.GetText ("Invalid revocation mode."));
+                       }
+
+                       bool unknown = partial;
+                       // from the root down to the end-entity
+                       for (int i = elements.Count - 1; i >= 0; i--) {
+                               bool check = true;
+
+                               switch (ChainPolicy.RevocationFlag) {
+                               case X509RevocationFlag.EndCertificateOnly:
+                                       check = (i == 0);
+                                       break;
+                               case X509RevocationFlag.EntireChain:
+                                       check = true;
+                                       break;
+                               case X509RevocationFlag.ExcludeRoot:
+                                       // default
+                                       check = (i != (elements.Count - 1));
+                                       // anyway, who's gonna sign that the root is invalid ?
+                                       break;
+                               }
+
+                               X509ChainElement element = elements [i];
+
+                               // we can't assume the revocation status if the certificate is bad (e.g. invalid signature)
+                               if (!unknown)
+                                       unknown |= ((element.StatusFlags & X509ChainStatusFlags.NotSignatureValid) != 0);
+
+                               if (unknown) {
+                                       // we can skip the revocation checks as we can't be sure of them anyway
+                                       element.StatusFlags |= X509ChainStatusFlags.RevocationStatusUnknown;
+                                       element.StatusFlags |= X509ChainStatusFlags.OfflineRevocation;
+                               } else if (check && !partial && !IsSelfIssued (element.Certificate)) {
+                                       // check for revocation (except for the trusted root and self-issued certs)
+                                       element.StatusFlags |= CheckRevocation (element.Certificate, i+1, online);
+                                       // if revoked, then all others following in the chain are unknown...
+                                       unknown |= ((element.StatusFlags & X509ChainStatusFlags.Revoked) != 0);
+                               }
+                       }
+               }
+
+               // This isn't how RFC3280 (section 6.3) deals with CRL, but then we don't (yet) support DP, deltas...
+               private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, int ca, bool online)
+               {
+                       X509ChainStatusFlags result = X509ChainStatusFlags.RevocationStatusUnknown;
+                       X509ChainElement element = elements [ca];
+                       X509Certificate2 ca_cert = element.Certificate;
+
+                       // find the CRL from the "right" CA
+                       while (IsSelfIssued (ca_cert) && (ca < elements.Count - 1)) {
+                               // try with this self-issued
+                               result = CheckRevocation (certificate, ca_cert, online);
+                               if (result != X509ChainStatusFlags.RevocationStatusUnknown)
+                                       break;
+                               ca++;
+                               element = elements [ca];
+                               ca_cert = element.Certificate;
+                       }
+                       if (result == X509ChainStatusFlags.RevocationStatusUnknown)
+                               result = CheckRevocation (certificate, ca_cert, online);
+                       return result;
+               }
+
+               private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, X509Certificate2 ca_cert, bool online)
+               {
+                       // change this if/when we support OCSP
+                       X509KeyUsageExtension kue = (ca_cert.Extensions["2.5.29.15"] as X509KeyUsageExtension);
+                       if (kue != null) {
+                               // ... verify CrlSign is set
+                               X509KeyUsageFlags success = X509KeyUsageFlags.CrlSign;
+                               if ((kue.KeyUsages & success) != success) {
+                                       // FIXME - we should try to find an alternative CA that has the CrlSign bit
+                                       return X509ChainStatusFlags.RevocationStatusUnknown;
+                               }
+                       }
+
+                       MX.X509Crl crl = FindCrl (ca_cert);
+
+                       if ((crl == null) && online) {
+                               // FIXME - download and install new CRL
+                               // then you get a second chance
+                               // crl = FindCrl (ca_cert, ref valid, ref out_of_date);
+
+                               // We need to get the subjectAltName and an URI from there (or use OCSP)        
+                               // X509KeyUsageExtension subjectAltName = (ca_cert.Extensions["2.5.29.17"] as X509KeyUsageExtension);
+                       }
+
+                       if (crl != null) {
+                               // validate the digital signature on the CRL using the CA public key
+                               // note #1: we can't use X509Crl.VerifySignature(X509Certificate) because it duplicates
+                               // checks and we loose the "why" of the failure
+                               // note #2: we do this before other tests as an invalid signature could be a hacked CRL
+                               // (so anything within can't be trusted)
+                               if (!crl.VerifySignature (ca_cert.PublicKey.Key)) {
+                                       return X509ChainStatusFlags.RevocationStatusUnknown;
+                               }
+
+                               MX.X509Crl.X509CrlEntry entry = crl.GetCrlEntry (certificate.MonoCertificate);
+                               if (entry != null) {
+                                       // We have an entry for this CRL that includes an unknown CRITICAL extension
+                                       // See [X.509 7.3] NOTE 4
+                                       if (!ProcessCrlEntryExtensions (entry))
+                                               return X509ChainStatusFlags.Revoked;
+
+                                       // FIXME - a little more is involved
+                                       if (entry.RevocationDate <= ChainPolicy.VerificationTime)
+                                               return X509ChainStatusFlags.Revoked;
+                               }
+
+                               // are we overdue for a CRL update ? if so we can't be sure of any certificate status
+                               if (crl.NextUpdate < ChainPolicy.VerificationTime)
+                                       return X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation;
+
+                               // we have a CRL that includes an unknown CRITICAL extension
+                               // we put this check at the end so we do not "hide" any Revoked flags
+                               if (!ProcessCrlExtensions (crl)) {
+                                       return X509ChainStatusFlags.RevocationStatusUnknown;
+                               }
+                       } else {
+                               return X509ChainStatusFlags.RevocationStatusUnknown;
+                       }
+
+                       return X509ChainStatusFlags.NoError;
+               }
+
+               static MX.X509Crl CheckCrls (string subject, string ski, MX.X509Store store)
+               {
+                       if (store == null)
+                               return null;
+
+                       var crls = store.Crls;
+                       foreach (MX.X509Crl crl in crls) {
+                               if (crl.IssuerName == subject && (ski.Length == 0 || ski == GetAuthorityKeyIdentifier (crl)))
+                                       return crl;
+                       }
+                       return null; // No CRL found
+               }
+
+               private MX.X509Crl FindCrl (X509Certificate2 caCertificate)
+               {
+                       string subject = caCertificate.SubjectName.Decode (X500DistinguishedNameFlags.None);
+                       string ski = GetSubjectKeyIdentifier (caCertificate);
+
+                       // consider that the LocalMachine directories could not exists... and cannot be created by the user
+                       MX.X509Crl result = CheckCrls (subject, ski, LMCAStore.Store);
+                       if (result != null)
+                               return result;
+                       if (location == StoreLocation.CurrentUser) {
+                               result = CheckCrls (subject, ski, UserCAStore.Store);
+                               if (result != null)
+                                       return result;
+                       }
+
+                       // consider that the LocalMachine directories could not exists... and cannot be created by the user
+                       result = CheckCrls (subject, ski, LMRootStore.Store);
+                       if (result != null)
+                               return result;
+                       if (location == StoreLocation.CurrentUser) {
+                               result = CheckCrls (subject, ski, UserRootStore.Store);
+                               if (result != null)
+                                       return result;
+                       }
+                       return null;
+               }
+
+               private bool ProcessCrlExtensions (MX.X509Crl crl)
+               {
+                       foreach (MX.X509Extension ext in crl.Extensions) {
+                               if (ext.Critical) {
+                                       switch (ext.Oid) {
+                                       case "2.5.29.20": // cRLNumber
+                                       case "2.5.29.35": // authorityKeyIdentifier
+                                               // we processed/know about this extension
+                                               break;
+                                       default:
+                                               return false;
+                                       }
+                               }
+                       }
+                       return true;
+               }
+
+               private bool ProcessCrlEntryExtensions (MX.X509Crl.X509CrlEntry entry)
+               {
+                       foreach (MX.X509Extension ext in entry.Extensions) {
+                               if (ext.Critical) {
+                                       switch (ext.Oid) {
+                                       case "2.5.29.21": // cRLReason
+                                               // we processed/know about this extension
+                                               break;
+                                       default:
+                                               return false;
+                                       }
+                               }
+                       }
+                       return true;
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs
new file mode 100644 (file)
index 0000000..544f67c
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// X509Helper2.cs
+//
+// Authors:
+//     Martin Baulig  <martin.baulig@xamarin.com>
+//
+// Copyright (C) 2016 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 SECURITY_DEP
+namespace System.Security.Cryptography.X509Certificates
+{
+       internal static class X509Helper2
+       {
+               internal static void ThrowIfContextInvalid (X509CertificateImpl impl)
+               {
+                       X509Helper.ThrowIfContextInvalid (impl);
+               }
+
+               internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
+               {
+                       var impl = new X509Certificate2ImplMono ();
+                       impl.Import (rawData, password, keyStorageFlags);
+                       return impl;
+               }
+
+               internal static X509Certificate2Impl Import (X509Certificate cert)
+               {
+                       var impl2 = cert.Impl as X509Certificate2Impl;
+                       if (impl2 != null)
+                               return (X509Certificate2Impl)impl2.Clone ();
+                       return Import (cert.GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet);
+               }
+
+               internal static X509ChainImpl CreateChainImpl (bool useMachineContext)
+               {
+                       return new X509ChainImplMono (useMachineContext);
+               }
+
+               public static bool IsValid (X509ChainImpl impl)
+               {
+                       return impl != null && impl.IsValid;
+               }
+
+               internal static void ThrowIfContextInvalid (X509ChainImpl impl)
+               {
+                       if (!IsValid (impl))
+                               throw GetInvalidChainContextException ();
+               }
+
+               internal static Exception GetInvalidChainContextException ()
+               {
+                       return new CryptographicException (Locale.GetText ("Chain instance is empty."));
+               }
+       }
+}
+#endif
index 904142e3595e4737c60cddab3376e306953daa84..42b6c6e3d44dc65bdbf2d8838f498fdd51ed0c33 100644 (file)
@@ -40,7 +40,7 @@ using System.Security.Permissions;
 
 namespace System.Security.Cryptography.X509Certificates {
 
-       public sealed class X509Store : IDisposable {
+       public sealed class X509Store {
 
                private string _name;
                private StoreLocation _location;
@@ -107,10 +107,6 @@ namespace System.Security.Cryptography.X509Certificates {
                        _location = storeLocation;
                }
 
-               public void Dispose ()
-               {
-               }
-
                // properties
 
                public X509Certificate2Collection Certificates {
index e2c0718b8ab6f55f7f1581d43a55e380b5f8fe98..1d37b1294e573b833968429100e92c98aedcff57 100644 (file)
@@ -536,11 +536,15 @@ System.Security.Cryptography.X509Certificates/X509BasicConstraintsExtension.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2Collection.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2Enumerator.cs
+System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs
+System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs
 System.Security.Cryptography.X509Certificates/X509CertificateCollection.cs
 System.Security.Cryptography.X509Certificates/X509Chain.cs
 System.Security.Cryptography.X509Certificates/X509ChainElementCollection.cs
 System.Security.Cryptography.X509Certificates/X509ChainElement.cs
 System.Security.Cryptography.X509Certificates/X509ChainElementEnumerator.cs
+System.Security.Cryptography.X509Certificates/X509ChainImpl.cs
+System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs
 System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs
 System.Security.Cryptography.X509Certificates/X509ChainStatus.cs
 System.Security.Cryptography.X509Certificates/X509ChainStatusFlags.cs
@@ -550,6 +554,7 @@ System.Security.Cryptography.X509Certificates/X509Extension.cs
 System.Security.Cryptography.X509Certificates/X509ExtensionEnumerator.cs
 System.Security.Cryptography.X509Certificates/X509FindType.cs
 System.Security.Cryptography.X509Certificates/X509IncludeOption.cs
+System.Security.Cryptography.X509Certificates/X509Helper2.cs
 System.Security.Cryptography.X509Certificates/X509KeyUsageExtension.cs
 System.Security.Cryptography.X509Certificates/X509KeyUsageFlags.cs
 System.Security.Cryptography.X509Certificates/X509NameType.cs
index 45649b8ad51a173ed0a658892fbf07fd0330042f..77fb73e3f00ed1404dbe81fe1a68294f5d7068a2 100644 (file)
@@ -81,13 +81,23 @@ namespace MonoTests.System.Net {
 
                public static MyNetworkStream CreateNS (int port)
                {
-                       return CreateNS (port, 5000);
+                       return CreateNS (IPAddress.Loopback, port, 5000);
                }
 
                public static MyNetworkStream CreateNS (int port, int timeout_ms)
+               {
+                       return CreateNS (IPAddress.Loopback, port, timeout_ms);
+               }
+
+               public static MyNetworkStream CreateNS (IPAddress ip, int port)
+               {
+                       return CreateNS (ip, port, 5000);
+               }
+
+               public static MyNetworkStream CreateNS (IPAddress ip, int port, int timeout_ms)
                {
                        Socket sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-                       sock.Connect (new IPEndPoint (IPAddress.Loopback, port));
+                       sock.Connect (new IPEndPoint (ip, port));
                        sock.SendTimeout = timeout_ms;
                        sock.ReceiveTimeout = timeout_ms;
                        return new MyNetworkStream (sock);
index 06b756d387b2fae9ed04d69b2a44261ca8863c64..c088e4e14e2ddeb71509bbda356c4d7761d12c66 100644 (file)
@@ -32,6 +32,7 @@ using System.IO;
 using System.Net;
 using System.Net.Sockets;
 using System.Text;
+using System.Collections.Generic;
 
 using NUnit.Framework;
 
@@ -190,6 +191,26 @@ namespace MonoTests.System.Net
                        listener.Close ();
                }
 
+               [Test]
+               public void HttpRequestIsLocal ()
+               {
+                       var ips = new List<IPAddress> (Dns.GetHostAddresses (Dns.GetHostName ()));
+                       ips.Add (IPAddress.Loopback);
+                       foreach (var ip in ips) {
+                               if (ip.AddressFamily != AddressFamily.InterNetwork)
+                                       continue;
+
+                               HttpListener listener = HttpListener2Test.CreateAndStartListener (
+                                       "http://" + ip + ":9000/HttpRequestIsLocal/");
+                               NetworkStream ns = HttpListener2Test.CreateNS (ip, 9000);
+                               HttpListener2Test.Send (ns, "GET /HttpRequestIsLocal/ HTTP/1.0\r\n\r\n");
+                               HttpListenerContext ctx = listener.GetContext ();
+                               HttpListenerRequest request = ctx.Request;
+                               Assert.AreEqual (true, request.IsLocal, "IP " + ip + " is not local");
+                               listener.Close ();
+                       }
+               }
+
                [Test] // #29927
                public void HttpRequestUriUnescape ()
                {
index e642d688f3c59c8d62dd075b49ad48e36176f470..a7e48646d05dcf3b87af070d4ee4cb66ac045634 100644 (file)
@@ -1465,17 +1465,35 @@ WYpnKQqsKIzlSqv9wwXs7B1iA7ZdvHk3TAnSnLP1o2H7ME05UnZPKCvraONdezon
                }
 
                [Test]
-               [ExpectedException (typeof (ArgumentException))]
                public void GetNameInfo_Invalid_True ()
                {
-                       new X509Certificate2 ().GetNameInfo ((X509NameType) Int32.MinValue, true);
+                       try {
+                               // MS throws ArgumentException, Mono's new implementation throws
+                               // CryptographicException, which is consistent with other "certificate
+                               // instance is empty" situations.
+                               new X509Certificate2 ().GetNameInfo ((X509NameType) Int32.MinValue, true);
+                               Assert.Fail ("Expected exception.");
+                       } catch (ArgumentException) {
+                       } catch (CryptographicException) {
+                       } catch (Exception ex) {
+                               Assert.Fail ("Expected 'ArgumentException' or 'CryptographicException', got '{0}'", ex.GetType ());
+                       }
                }
 
                [Test]
-               [ExpectedException (typeof (ArgumentException))]
                public void GetNameInfo_Invalid_False ()
                {
-                       new X509Certificate2 ().GetNameInfo ((X509NameType) Int32.MinValue, false);
+                       try {
+                               // MS throws ArgumentException, Mono's new implementation throws
+                               // CryptographicException, which is consistent with other "certificate
+                               // instance is empty" situations.
+                               new X509Certificate2 ().GetNameInfo ((X509NameType) Int32.MinValue, false);
+                               Assert.Fail ("Expected exception.");
+                       } catch (ArgumentException) {
+                       } catch (CryptographicException) {
+                       } catch (Exception ex) {
+                               Assert.Fail ("Expected 'ArgumentException' or 'CryptographicException', got '{0}'", ex.GetType ());
+                       }
                }
 
                [Test]
@@ -1486,10 +1504,19 @@ WYpnKQqsKIzlSqv9wwXs7B1iA7ZdvHk3TAnSnLP1o2H7ME05UnZPKCvraONdezon
                }
 
                [Test]
-               [ExpectedException (typeof (NullReferenceException))]
                public void Empty_GetNameInfo_DnsName ()
                {
-                       new X509Certificate2 ().GetNameInfo (X509NameType.DnsName, true);
+                       try {
+                               // MS throws NullReferenceException, Mono's new implementation throws
+                               // CryptographicException, which is consistent with other "certificate
+                               // instance is empty" situations.
+                               new X509Certificate2 ().GetNameInfo (X509NameType.DnsName, true);
+                               Assert.Fail ("Expected exception.");
+                       } catch (NullReferenceException) {
+                       } catch (CryptographicException) {
+                       } catch (Exception ex) {
+                               Assert.Fail ("Expected 'NullReferenceException' or 'CryptographicException', got '{0}'", ex.GetType ());
+                       }
                }
 
                [Test]
index 42aae6ea158c8a8c299debefa02cc4bed9c01cd5..9fe0be90027bb9eb94769947fa80d510910e3281 100644 (file)
@@ -300,11 +300,15 @@ System.Security.Cryptography.X509Certificates/X509BasicConstraintsExtension.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2Collection.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2Enumerator.cs
+System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs
+System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs
 System.Security.Cryptography.X509Certificates/X509CertificateCollection.cs
 System.Security.Cryptography.X509Certificates/X509Chain.cs
 System.Security.Cryptography.X509Certificates/X509ChainElement.cs
 System.Security.Cryptography.X509Certificates/X509ChainElementCollection.cs
 System.Security.Cryptography.X509Certificates/X509ChainElementEnumerator.cs
+System.Security.Cryptography.X509Certificates/X509ChainImpl.cs
+System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs
 System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs
 System.Security.Cryptography.X509Certificates/X509ChainStatus.cs
 System.Security.Cryptography.X509Certificates/X509ChainStatusFlags.cs
@@ -314,6 +318,7 @@ System.Security.Cryptography.X509Certificates/X509ExtensionCollection.cs
 System.Security.Cryptography.X509Certificates/X509ExtensionEnumerator.cs
 System.Security.Cryptography.X509Certificates/X509FindType.cs
 System.Security.Cryptography.X509Certificates/X509IncludeOption.cs
+System.Security.Cryptography.X509Certificates/X509Helper2.cs
 System.Security.Cryptography.X509Certificates/X509KeyUsageExtension.cs
 System.Security.Cryptography.X509Certificates/X509KeyUsageFlags.cs
 System.Security.Cryptography.X509Certificates/X509NameType.cs
index b3284ea78796be7b38531510d7a79ffb72f7b7b2..cf95aee80ea0e92aa4eec92c3b2ce8c4a6bf8ccd 100644 (file)
@@ -73,13 +73,9 @@ using System.Runtime.InteropServices;
 [assembly: DefaultDependency (LoadHint.Always)]
 [assembly: StringFreezing]
 
-#if NET_2_1
-[assembly: InternalsVisibleTo ("System, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")]
-[assembly: InternalsVisibleTo ("System.Core, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")]
-#else
-[assembly: InternalsVisibleTo ("System, PublicKey=00000000000000000400000000000000")]
-[assembly: InternalsVisibleTo ("System.Core, PublicKey=00000000000000000400000000000000")]
-#endif
+[assembly: InternalsVisibleTo ("System, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull2)]
+[assembly: InternalsVisibleTo ("System.Core, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull2)]
+
 [assembly: InternalsVisibleTo ("System.Numerics, PublicKey=00000000000000000400000000000000")]
 
 #if MONOTOUCH
index 1e53bade58fbf5653b11b0d124bbbe31e7ead55b..69e1f32ffdd74bcf0f4b446b145468b9301769b1 100644 (file)
@@ -48,6 +48,7 @@ namespace System.IO {
        public sealed class FileInfo : FileSystemInfo
        {
                private bool exists;
+               private string displayPath;
 
                public FileInfo (string fileName)
                {
@@ -59,11 +60,14 @@ namespace System.IO {
 
                        OriginalPath = fileName;
                        FullPath = Path.GetFullPath (fileName);
+                       
+                       displayPath = OriginalPath;
                }
 
                private FileInfo (SerializationInfo info, StreamingContext context)
                        : base (info, context)
                {
+                       displayPath = OriginalPath;
                }
 
                internal override void InternalRefresh ()
@@ -241,6 +245,8 @@ namespace System.IO {
 
                        File.Move (FullPath, destFullPath);
                        this.FullPath = destFullPath;
+
+                       displayPath = destFileName;
                }
 
                public FileInfo CopyTo (string destFileName)
@@ -267,7 +273,7 @@ namespace System.IO {
 
                public override string ToString ()
                {
-                       return OriginalPath;
+                       return displayPath;
                }
 
 #if !MOBILE
diff --git a/mcs/class/corlib/System.Runtime.InteropServices/RuntimeEnvironment.cs b/mcs/class/corlib/System.Runtime.InteropServices/RuntimeEnvironment.cs
deleted file mode 100644 (file)
index d280820..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// System.Runtime.InteropServices/RuntimeEnvironment.cs
-//
-// Authors:
-//     Dominik Fretz (roboto@gmx.net)
-//     Sebastien Pouliot (sebastien@ximian.com)
-//
-// (C) 2003 Dominik Fretz
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.IO;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Security.Permissions;
-
-namespace System.Runtime.InteropServices
-{
-       [ComVisible (true)]
-       public class RuntimeEnvironment
-       {
-               public RuntimeEnvironment ()
-               {
-               }
-
-               public static string SystemConfigurationFile {
-                       get {
-                               // GetMachineConfigPath is internal and not protected by CAS
-                               string path = Environment.GetMachineConfigPath ();
-                               if (SecurityManager.SecurityEnabled) {
-                                       new FileIOPermission (FileIOPermissionAccess.PathDiscovery, path).Demand ();
-                               }
-                               return path;
-                       }
-               }
-
-               public static bool FromGlobalAccessCache (Assembly a)
-               {
-                       // yes, this will throw a NullReferenceException (just like MS, reported as ...)
-                       return a.GlobalAssemblyCache;
-               }
-       
-               public static string GetRuntimeDirectory ()
-               {
-                       return Path.GetDirectoryName (typeof (int).Assembly.Location);  
-               }
-
-               [SecuritySafeCritical]
-               public static string GetSystemVersion ()
-               {
-                       return "v" + Environment.Version.Major + "." + Environment.Version.Minor + "." + Environment.Version.Build;
-               }
-       }
-}
index 144997e573b63c0cb211a47596cdbb0e676228ac..3ff0a2adeada877f4a4a3cf241de95b182e76217 100644 (file)
@@ -109,6 +109,14 @@ namespace System.Security.Cryptography.X509Certificates {
                        impl = X509Helper.InitFromHandle (handle);
                }
 
+               internal X509Certificate (X509CertificateImpl impl)
+               {
+                       if (impl == null)
+                               throw new ArgumentNullException ("impl");
+
+                       this.impl = X509Helper.InitFromCertificate (impl);
+               }
+
                public X509Certificate (System.Security.Cryptography.X509Certificates.X509Certificate cert) 
                {
                        if (cert == null)
@@ -120,6 +128,27 @@ namespace System.Security.Cryptography.X509Certificates {
                        hideDates = false;
                }
 
+               internal void ImportHandle (X509CertificateImpl impl)
+               {
+                       Reset ();
+                       this.impl = impl;
+               }
+
+               internal X509CertificateImpl Impl {
+                       get {
+                               X509Helper.ThrowIfContextInvalid (impl);
+                               return impl;
+                       }
+               }
+
+               internal bool IsValid {
+                       get { return X509Helper.IsValid (impl); }
+               }
+
+               internal void ThrowIfContextInvalid ()
+               {
+                       X509Helper.ThrowIfContextInvalid (impl);
+               }
 
                // public methods
        
@@ -161,7 +190,7 @@ namespace System.Security.Cryptography.X509Certificates {
                                return null;
                        X509Helper.ThrowIfContextInvalid (impl);
 
-                       return impl.GetEffectiveDateString ().ToString ();
+                       return impl.GetValidFrom ().ToLocalTime ().ToString ();
                }
        
                // strangly there are no DateTime returning function
@@ -171,7 +200,7 @@ namespace System.Security.Cryptography.X509Certificates {
                                return null;
                        X509Helper.ThrowIfContextInvalid (impl);
 
-                       return impl.GetExpirationDateString ().ToString ();
+                       return impl.GetValidUntil ().ToLocalTime ().ToString ();
                }
        
                // well maybe someday there'll be support for PGP or SPKI ?
index e3dc5b36201f71a1dec2488dcea7effa4d3e8135..7178bedaa547e5ace0afd2186a5cae5d30d5483e 100644 (file)
@@ -45,17 +45,15 @@ namespace System.Security.Cryptography.X509Certificates
 
                public abstract X509CertificateImpl Clone ();
 
-               public abstract string GetSubjectSummary ();
-
                public abstract string GetIssuerName (bool legacyV1Mode);
 
                public abstract string GetSubjectName (bool legacyV1Mode);
 
                public abstract byte[] GetRawCertData ();
 
-               public abstract DateTime GetEffectiveDateString ();
+               public abstract DateTime GetValidFrom ();
 
-               public abstract DateTime GetExpirationDateString ();
+               public abstract DateTime GetValidUntil ();
 
                byte[] cachedCertificateHash;
 
index 85985c5d303cef3e3beebb05c1fb9f9c51eba7cd..056bf561ee5a31a719907724b41b6e11cf4ef5ab 100644 (file)
@@ -66,12 +66,6 @@ namespace System.Security.Cryptography.X509Certificates
                                return MX.X501.ToString (x509.GetIssuerName (), true, ", ", true);
                }
 
-               public override string GetSubjectSummary ()
-               {
-                       ThrowIfContextInvalid ();
-                       return x509.SubjectName;
-               }
-
                public override string GetSubjectName (bool legacyV1Mode)
                {
                        ThrowIfContextInvalid ();
@@ -94,16 +88,16 @@ namespace System.Security.Cryptography.X509Certificates
                        return sha.ComputeHash (x509.RawData);
                }
 
-               public override DateTime GetEffectiveDateString ()
+               public override DateTime GetValidFrom ()
                {
                        ThrowIfContextInvalid ();
-                       return x509.ValidFrom.ToLocalTime ();
+                       return x509.ValidFrom;
                }
 
-               public override DateTime GetExpirationDateString ()
+               public override DateTime GetValidUntil ()
                {
                        ThrowIfContextInvalid ();
-                       return x509.ValidUntil.ToLocalTime ();
+                       return x509.ValidUntil;
                }
 
                public override bool Equals (X509CertificateImpl other, out bool result)
@@ -164,8 +158,8 @@ namespace System.Security.Cryptography.X509Certificates
                        StringBuilder sb = new StringBuilder ();
                        sb.AppendFormat ("[Subject]{0}  {1}{0}{0}", nl, GetSubjectName (false));
                        sb.AppendFormat ("[Issuer]{0}  {1}{0}{0}", nl, GetIssuerName (false));
-                       sb.AppendFormat ("[Not Before]{0}  {1}{0}{0}", nl, GetEffectiveDateString ());
-                       sb.AppendFormat ("[Not After]{0}  {1}{0}{0}", nl, GetExpirationDateString ());
+                       sb.AppendFormat ("[Not Before]{0}  {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
+                       sb.AppendFormat ("[Not After]{0}  {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
                        sb.AppendFormat ("[Thumbprint]{0}  {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
                        sb.Append (nl);
                        return sb.ToString ();
index aee50509f8f299f121260c1a47ac362951d5d504..f75547ab13d55a425298a88f431b885aa0462a08 100644 (file)
@@ -96,11 +96,6 @@ namespace System
 
                static Console ()
                {
-#if NET_2_1
-                       Encoding inputEncoding;
-                       Encoding outputEncoding;
-#endif
-
                        if (Environment.IsRunningOnWindows) {
                                //
                                // On Windows, follow the Windows tradition
@@ -524,7 +519,6 @@ namespace System
 
 #endif
 
-#if !NET_2_1
                // FIXME: Console should use these encodings when changed
                static Encoding inputEncoding;
                static Encoding outputEncoding;
@@ -545,6 +539,7 @@ namespace System
                        }
                }
 
+#if !NET_2_1
                public static ConsoleColor BackgroundColor {
                        get { return ConsoleDriver.BackgroundColor; }
                        set { ConsoleDriver.BackgroundColor = value; }
index 0068c4643b8fdcae08e5070ee5ed340ab9d64cdf..db33ec75f0febdaa5cecfef8d4ce7b4975ba9cc8 100644 (file)
@@ -880,6 +880,29 @@ namespace MonoTests.System.IO
                        }
                }
 
+               [Test] //Covers #38796
+               public void ToStringAfterMoveTo ()
+               {
+                       string name1 = "FIT.ToStringAfterMoveTo.Test";
+                       string name2 = "FIT.ToStringAfterMoveTo.Test.Alt";
+                       string path1 = TempFolder + DSC + name1;
+                       string path2 = TempFolder + DSC + name2;
+                       DeleteFile (path1);
+                       DeleteFile (path2);
+                       
+                       try {
+                               File.Create (path1).Close ();
+                               FileInfo info = new FileInfo (path1);
+                               Assert.AreEqual (path1, info.ToString (), "#A");
+
+                               info.MoveTo (path2);
+                               Assert.AreEqual (path2, info.ToString (), "#B");
+                       } finally {
+                               DeleteFile (path1);
+                               DeleteFile (path2);
+                       }
+               }
+
 #if !MOBILE
                [Test]
                public void Replace1 ()
index f49db8501d29151ad1b7ece11e6b004540d2aea2..9a2b075df8837573163a5a1b72119eb1210281a2 100644 (file)
@@ -1,6 +1,7 @@
 Assembly/AssemblyInfo.cs
 ../../build/common/Consts.cs
 ../../build/common/Locale.cs
+../../build/common/AssemblyRef.cs
 Microsoft.Win32/IRegistryApi.cs
 Microsoft.Win32/RegistryKey.cs
 Microsoft.Win32/RegistryKeyPermissionCheck.cs
@@ -399,7 +400,6 @@ System.Runtime.InteropServices/RegistrationConnectionType.cs
 System.Runtime.InteropServices/SEHException.cs
 System.Runtime.InteropServices/STATSTG.cs
 System.Runtime.InteropServices/RegistrationServices.cs
-System.Runtime.InteropServices/RuntimeEnvironment.cs
 System.Runtime.InteropServices/SafeArrayRankMismatchException.cs
 System.Runtime.InteropServices/SafeArrayTypeMismatchException.cs
 System.Runtime.InteropServices/SafeBuffer.cs
@@ -1287,6 +1287,7 @@ ReferenceSources/SecurityContext.cs
 ../../../external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs
 
 ../../../external/referencesource/mscorlib/system/runtime/interopservices/attributes.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/runtimeenvironment.cs
 ../../../external/referencesource/mscorlib/system/runtime/interopservices/safehandle.cs
 ../../../external/referencesource/mscorlib/system/runtime/interopservices/ucomienumconnections.cs
 
index 68477b3c1ed34bf07220b57999433d23dfc004a4..a0ae78cdf518e42737b571c830e08a99adf00747 100644 (file)
@@ -2245,7 +2245,7 @@ namespace Mono.CSharp {
                                return IsLeftResolvedExpressionValid (dmb.Arguments [0].Expr);
                        }
 
-                       if (expr is ConstantExpr || expr is TypeExpr || expr is NamespaceExpression || expr is This)
+                       if (expr is ConstantExpr || expr is TypeExpr || expr is NamespaceExpression || expr is VariableReference)
                                return true;
 
                        return false;
index 16a67f4cbd9cb446147670c989887cef81f56c17..0c199017af9b1d4e3e19624afb3563ee9b7705ca 100644 (file)
@@ -1211,13 +1211,29 @@ namespace Mono.CSharp {
                                return ParseResult.Success;
 
                        // csc options that we don't support
-                       case "/utf8output":
-                       case "/subsystemversion":
+                       case "/analyzer":
+                       case "/appconfig":
+                       case "/baseaddress":
+                       case "/deterministic":
+                       case "/errorendlocation":
+                       case "/errorlog":
+                       case "/features":
                        case "/highentropyva":
                        case "/highentropyva+":
                        case "/highentropyva-":
-                       case "/win32manifest":
+                       case "/link":
+                       case "/moduleassemblyname":
                        case "/nowin32manifest":
+                       case "/pathmap":
+                       case "/pdb":
+                       case "/preferreduilang":
+                       case "/publicsign":
+                       case "/reportanalyzer":
+                       case "/ruleset":
+                       case "/sqmsessionguid":
+                       case "/subsystemversion":
+                       case "/utf8output":
+                       case "/win32manifest":
                                return ParseResult.Success;
 
                        default:
index 1b1a16ca1848ba14db594af3408f0bce0531e37e..10674f5cd9ec50902bc0db9d25355599b17fa65d 100644 (file)
@@ -50,7 +50,7 @@ TEST_PATTERN = 'v2'
 
 ifeq (net_4_x, $(PROFILE))
 TEST_PATTERN = 'v4'
-DEFINES = -compiler-options:"-d:NET_4_0;NET_4_5"
+DEFINES = -compiler-options:"-d:NET_4_0;NET_4_5 -debug"
 endif
 
 LOCAL_RUNTIME_FLAGS = --verify-all
index ea92d6af0de4bb188050d29921e7dc39cb32227d..4ad5cdf547e8c744dbad0e1b154e95d8ce16d2d0 100644 (file)
@@ -29,6 +29,11 @@ public class MainClass
        public static event Action Act = null;
        public static dynamic BBB = null;
 
+       void ParameterTest (Person ParPerson)
+       {
+               Console.WriteLine (nameof (ParPerson.MyCar.Year));
+       }
+
        public static int Main ()
        {
                string name;
@@ -61,6 +66,11 @@ public class MainClass
                if (name != "ToString")
                        return 7;
 
+               Person LocPerson = null;
+               name = nameof (LocPerson.MyCar.Year);
+               if (name != "Year")
+                       return 8;
+
                return 0;
        }
 }
index 3cc0ea315382acaa4f7e2726f79714b6d3bab297..576a15ddb738d3d6612dffbf80fa5a75ce29346a 100644 (file)
         <size>40</size>
       </method>
       <method name="Int32 Main()" attrs="150">
-        <size>213</size>
+        <size>244</size>
       </method>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
         <size>7</size>
       </method>
     </type>
+    <type name="MainClass">
+      <method name="Void ParameterTest(Person)" attrs="129">
+        <size>12</size>
+      </method>
+    </type>
   </test>
   <test name="test-null-operator-01.cs">
     <type name="S">
index e0bef6d2be8f6c2d4f76a494ae1742055ee1b59c..9b07560ab3997c9f56a23edbc71e127d02ca7a34 100644 (file)
@@ -3,7 +3,8 @@ SUBDIRS =
 include ../../build/rules.make
 
 PROGRAM = cil-stringreplacer.exe
+NO_INSTALL = yes
 
-LOCAL_MCS_FLAGS = -r:System.dll
+LOCAL_MCS_FLAGS = -r:System.dll -r:Mono.Cecil.dll
 
 include ../../build/executable.make
index f86922be2bf58e3560dcd3e318ec0d80a0d2f2a1..2414206c692ef2023b30b34d7ca16ebceebc8306 100644 (file)
@@ -100,7 +100,8 @@ public class Program
 
        static void RewriteAssembly (string assemblyLocation, Dictionary<string, string> resourcesStrings, CmdOptions options)
        {
-               var assembly = AssemblyDefinition.ReadAssembly (assemblyLocation);
+               var readerParameters = new ReaderParameters { ReadSymbols = true };
+               var assembly = AssemblyDefinition.ReadAssembly (assemblyLocation, readerParameters);
                foreach (var module in assembly.Modules) {
                        foreach (var type in module.GetTypes ()) {
                                foreach (var method in type.Methods) {
@@ -124,7 +125,8 @@ public class Program
                        }
                }
 
-               assembly.Write (assemblyLocation);
+               var writerParameters = new WriterParameters { WriteSymbols = true };
+               assembly.Write (assemblyLocation, writerParameters);
        }
 
        static bool LoadGetResourceStrings (Dictionary<string, string> resourcesStrings, CmdOptions options)
diff --git a/mcs/tools/cil-stringreplacer/cil-stringreplacer.csproj b/mcs/tools/cil-stringreplacer/cil-stringreplacer.csproj
new file mode 100644 (file)
index 0000000..230cd62
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>\r
+    <ProjectGuid>{7A08A2B6-5AC3-4268-8566-B07648B50D01}</ProjectGuid>\r
+    <OutputType>Exe</OutputType>\r
+    <RootNamespace>cilstringreplacer</RootNamespace>\r
+    <AssemblyName>cilstringreplacer</AssemblyName>\r
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <DebugType>full</DebugType>\r
+    <Optimize>false</Optimize>\r
+    <OutputPath>bin\Debug</OutputPath>\r
+    <DefineConstants>DEBUG;</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+    <ExternalConsole>false</ExternalConsole>\r
+    <PlatformTarget>x86</PlatformTarget>\r
+    <Commandlineparameters>--resourcestrings:/Users/marek/git/mono/external/referencesource/mscorlib/mscorlib.txt /Users/marek/git/mono/mcs/class/lib/net_4_x/mscorlib.dll</Commandlineparameters>\r
+    <ConsolePause>false</ConsolePause>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>bin\Release</OutputPath>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+    <ExternalConsole>true</ExternalConsole>\r
+    <PlatformTarget>x86</PlatformTarget>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="System" />\r
+    <Reference Include="Mono.Cecil">\r
+      <HintPath>..\..\class\lib\net_4_x\Mono.Cecil.dll</HintPath>\r
+    </Reference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="cil-stringreplacer.cs">\r
+      <Link>cil-stringreplacer.cs</Link>\r
+    </Compile>\r
+    <Compile Include="..\..\class\Mono.Options\Mono.Options\Options.cs">\r
+      <Link>Options.cs</Link>\r
+    </Compile>\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />\r
+</Project>
\ No newline at end of file
index 90536b886aa757b695ba77603c6a0efb5eb912b7..c16659f2b39c76efd24a0756765ea42799ef42b1 100644 (file)
@@ -1,9 +1,2 @@
 cil-stringreplacer.cs
 ../../class/Mono.Options/Mono.Options/Options.cs
-../../../external/cecil/Mono.Cecil/*.cs
-../../../external/cecil/Mono.Cecil.Cil/*.cs
-../../../external/cecil/Mono.Cecil.Metadata/*.cs
-../../../external/cecil/Mono.Cecil.PE/*.cs
-../../../external/cecil/Mono.Collections.Generic/*.cs
-../../../external/cecil/Mono/Empty.cs
-../../../external/cecil/Mono.Security.Cryptography/*.cs
index 602f6540ae4a7c8b1e4711114f9e457f83ab1433..beafdfa555778472afda9b56e0d11d2fd3d52845 100644 (file)
@@ -589,13 +589,12 @@ namespace TestRunner {
                        string[] test_args;
 
                        if (test.CompilerOptions != null) {
-                               test_args = new string[2 + test.CompilerOptions.Length];
+                               test_args = new string[1 + test.CompilerOptions.Length];
                                test.CompilerOptions.CopyTo (test_args, 0);
                        } else {
-                               test_args = new string[2];
+                               test_args = new string[1];
                        }
-                       test_args[test_args.Length - 2] = test_args[0];
-                       test_args[test_args.Length - 1] = "-debug";
+                       test_args[test_args.Length - 1] = test_args[0];
                        test_args[0] = test.FileName;
 
                        return tester.Invoke (test_args);
@@ -697,11 +696,9 @@ namespace TestRunner {
                                log_file.WriteLine (msg, rest);
                }
                
-               public void LogFileLine (string file, string msg, params object [] args)
+               public void LogFileLine (string file, string msg)
                {
-                       string s = verbose ? 
-                               string.Format (msg, args) :
-                               file + "...\t" + string.Format (msg, args); 
+                       string s = verbose ? msg : file + "...\t" + msg;
 
                        Console.WriteLine (s);
                        if (log_file != null)
@@ -871,7 +868,7 @@ namespace TestRunner {
                                        return true;
 
                                if (md.ILSize > il_size) {
-                                       checker.LogFileLine (test.FileName, "{0} (code size reduction {1} -> {2})", decl_type + ": " + m_name, md.ILSize, il_size);
+                                       checker.LogFileLine (test.FileName, string.Format ("{0} (code size reduction {1} -> {2})", decl_type + ": " + m_name, md.ILSize, il_size));
                                        md.ILSize = il_size;
                                        return true;
                                }
@@ -1442,6 +1439,7 @@ namespace TestRunner {
 
                static bool TryToMatchErrorMessage (string actual, string expected)
                {
+                       actual = actual.Replace ("\\", "/");
                        var path_mask_start = expected.IndexOf ("*PATH*");
                        if (path_mask_start > 0 && actual.Length > path_mask_start) {
                                var path_mask_continue = expected.Substring (path_mask_start + 6);
index 17d843975055ef2db7672acb490f7a395f57f953..760f9cf5045c92e217bbb7edcdb66d7e8aa86b20 100644 (file)
@@ -2,21 +2,36 @@ thisdir = tools/corcompare
 SUBDIRS =
 include ../../build/rules.make
 
-ALL_PROGRAMS = mono-api-info.exe
-
-COMMON_SOURCES = \
-       AssemblyResolver.cs     \
-       Util.cs \
-       WellFormedXmlWriter.cs
+ALL_PROGRAMS = mono-api-info.exe mono-api-html.exe
 
 PROGRAM_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)
 
 APIINFO_SOURCES = \
        mono-api-info.cs \
-       ../../class/Mono.Options/Mono.Options/Options.cs \
-       $(COMMON_SOURCES)
+       AssemblyResolver.cs     \
+       Util.cs \
+       WellFormedXmlWriter.cs \
+       ../../class/Mono.Options/Mono.Options/Options.cs
+
+APIHTML_SOURCES = \
+       mono-api-html/ApiChange.cs \
+       mono-api-html/ApiDiff.cs \
+       mono-api-html/AssemblyComparer.cs \
+       mono-api-html/ClassComparer.cs \
+       mono-api-html/Comparer.cs \
+       mono-api-html/ConstructorComparer.cs \
+       mono-api-html/EventComparer.cs \
+       mono-api-html/FieldComparer.cs \
+       mono-api-html/Helpers.cs \
+       mono-api-html/InterfaceComparer.cs \
+       mono-api-html/MemberComparer.cs \
+       mono-api-html/MethodComparer.cs \
+       mono-api-html/NamespaceComparer.cs \
+       mono-api-html/PropertyComparer.cs \
+       ../../class/Mono.Options/Mono.Options/Options.cs
 
-DISTFILES= $(COMMON_SOURCES) $(APIINFO_SOURCES)
+
+DISTFILES= $(APIINFO_SOURCES) $(APIHTML_SOURCES)
 
 all-local: $(ALL_PROGRAMS)
 
@@ -42,5 +57,8 @@ clean-local:
 
 dist-local: dist-default
 
-mono-api-info.exe: $(APIINFO_SOURCES) ../../class/Mono.Options/Mono.Options/Options.cs
+mono-api-info.exe: $(APIINFO_SOURCES)
        $(CSCOMPILE) -r:Mono.Cecil.dll -r:System.Xml.dll -r:System.Core.dll -r:System.dll -out:$@ $^
+
+mono-api-html.exe: $(APIHTML_SOURCES)
+       $(CSCOMPILE) -r:Mono.Cecil.dll -r:System.Xml.dll -r:System.Core.dll -r:System.dll -r:System.Xml.Linq.dll -out:$@ $^
index d0783dec3ecaecec317e8fda21bb63c473b7e55b..b60971e0df34eabe9d3954b6843f0f875063b41d 100644 (file)
@@ -596,6 +596,7 @@ namespace Mono.Terminal {
                                        
                        if (completions.Length == 1){
                                InsertTextAtCursor (completions [0]);
+                               HideCompletions ();
                        } else {
                                int last = -1;
 
index f16fcb9ea698d52ca8e3756fc1e89aa724a5d441..75b22b934c83c16f46c9d255ce384d5ab8b53368 100644 (file)
@@ -404,7 +404,7 @@ namespace Mono {
                static void EscapeString (TextWriter output, string s)
                {
                        foreach (var c in s){
-                               if (c > 32){
+                               if (c >= 32){
                                        output.Write (c);
                                        continue;
                                }
@@ -416,7 +416,7 @@ namespace Mono {
                                case '\b':
                                        output.Write ("\\b"); break;
                                case '\n':
-                                       output.Write ("\\n");
+                                       output.Write ("\n");
                                        break;
                                
                                case '\v':
@@ -448,7 +448,7 @@ namespace Mono {
                                output.Write ("'\\''");
                                return;
                        }
-                       if (c > 32){
+                       if (c >= 32){
                                output.Write ("'{0}'", c);
                                return;
                        }
@@ -482,7 +482,7 @@ namespace Mono {
                                break;
 
                        default:
-                               output.Write ("'\\x{0:x}", (int) c);
+                               output.Write ("'\\x{0:x}'", (int) c);
                                break;
                        }
                }
index 3446b6f74c0afdbc912a571af8cb900b089945f8..13f686e22c64ec5dadc09c136838db3ed7c74a43 100644 (file)
@@ -324,6 +324,11 @@ namespace Mono.Tools {
 
                        Copy (name, asmb_path, true);
 
+                       var name_pdb = Path.ChangeExtension (name, ".pdb");
+                       if (File.Exists (name_pdb)) {
+                               Copy (name_pdb, Path.ChangeExtension (asmb_path, ".pdb"), true);
+                       }
+
                        foreach (string ext in siblings) {
                                string sibling = String.Concat (name, ext);
                                if (File.Exists (sibling))
@@ -356,9 +361,23 @@ namespace Mono.Tools {
                                        string pkg_path = AbsoluteToRelativePath (ref_dir, pkg_path_abs);
                                        symlink (pkg_path, ref_path);
 
+                                       var pdb_pkg_path = Path.ChangeExtension (pkg_path, ".pdb");
+                                       var pdb_ref_path = Path.ChangeExtension (ref_path, ".pdb");
+
+                                       if (File.Exists (pdb_pkg_path)) {
+                                               symlink (pdb_pkg_path, pdb_ref_path);
+                                       } else {
+                                               try {
+                                                       File.Delete (pdb_ref_path);
+                                               } catch {
+                                                       // Ignore error, just delete files that should not be there.
+                                               }
+                                       }
+
                                        foreach (string ext in siblings) {
                                                string sibling = String.Concat (pkg_path, ext);
                                                string sref = String.Concat (ref_path, ext);
+
                                                if (File.Exists (sibling))
                                                        symlink (sibling, sref);
                                                else {
index b6b8fc785611d4f43ed16e58922940a3c7140535..63c5eb6adce769bff8c1b9107149ad02576bd708 100644 (file)
@@ -18,7 +18,7 @@ PROGRAM = monolinker.exe
 
 $(PROGRAM): $(RESOURCES)
 
-LOCAL_MCS_FLAGS = /r:$(CECIL) /r:System.Xml.dll -keyfile:$(PROGRAM_SNK) $(RESOURCES:%=-resource:%)
+LOCAL_MCS_FLAGS = /r:$(CECIL) /r:System.Xml.dll /r:System.Core.dll /r:System.dll $(RESOURCES:%=-resource:%)
 
 EXTRA_DISTFILES = $(RESOURCES)
 
index 45aeed2f7b85918c6ceb974934b5f088e856a0cb..7bd68482312e9491925aa0ebcd7e03e933e5e54e 100644 (file)
@@ -11,11 +11,12 @@ LOCAL_MCS_FLAGS = \
        -resource:$(dbmetal_src)/Language/EnglishWords.txt,$(ns).EnglishWords.txt \
        -resource:$(dbmetal_src)/Language/FrenchWords.txt,$(ns).FrenchWords.txt   \
        -resource:$(dbmetal_src)/Language/GermanWords.txt,$(ns).GermanWords.txt   \
-       -r:System.Configuration                                             \
-       -r:System.Core                                                      \
-       -r:System.Data                                                      \
-       -r:System.Data.Linq                                                 \
-       -r:System.Xml
+       -r:System.Configuration.dll                                             \
+       -r:System.Core.dll                                                      \
+       -r:System.Data.dll                                                      \
+       -r:System.Data.Linq.dll                                                 \
+       -r:System.Xml.dll \
+       -r:System.dll
 
 SQLMETAL_RESOURCES = \
        $(dbmetal_src)/Language/EnglishWords.txt \
index 6ffc0a3f2af47ac0276940aa3295cee7b9713751..e7a0db8eb2afaa66d4a204087fd839d4f7f49421 100644 (file)
@@ -257,7 +257,6 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT
        mono_install_assembly_postload_search_hook ((MonoAssemblySearchFunc)mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE));
        mono_install_assembly_postload_refonly_search_hook ((MonoAssemblySearchFunc)mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE));
        mono_install_assembly_load_hook (mono_domain_fire_assembly_load, NULL);
-       mono_install_lookup_dynamic_token (mono_reflection_lookup_dynamic_token);
 
        mono_thread_init (start_cb, attach_cb);
 
@@ -1766,7 +1765,7 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
        if (!mono_error_ok (&error)) {
                mono_error_cleanup (&error);
                g_free (dir_name);
-               mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Failed to create shadow copy (invalid characters in shadow directory name).");
+               mono_error_set_execution_engine (oerror, "Failed to create shadow copy (invalid characters in shadow directory name).");
                return NULL;
        }
 
@@ -1781,13 +1780,13 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
        shadow = get_shadow_assembly_location (filename, &error);
        if (!mono_error_ok (&error)) {
                mono_error_cleanup (&error);
-               mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Failed to create shadow copy (invalid characters in file name).");
+               mono_error_set_execution_engine (oerror, "Failed to create shadow copy (invalid characters in file name).");
                return NULL;
        }
 
        if (ensure_directory_exists (shadow) == FALSE) {
                g_free (shadow);
-               mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Failed to create shadow copy (ensure directory exists).");
+               mono_error_set_execution_engine (oerror, "Failed to create shadow copy (ensure directory exists).");
                return NULL;
        }       
 
@@ -1824,7 +1823,7 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
                if (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND)
                        return NULL; /* file not found, shadow copy failed */
 
-               mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Failed to create shadow copy (CopyFile).");
+               mono_error_set_execution_engine (oerror, "Failed to create shadow copy (CopyFile).");
                return NULL;
        }
 
@@ -1843,14 +1842,14 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
        
        if (copy_result == FALSE)  {
                g_free (shadow);
-               mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Failed to create shadow copy of sibling data (CopyFile).");
+               mono_error_set_execution_engine (oerror, "Failed to create shadow copy of sibling data (CopyFile).");
                return NULL;
        }
 
        /* Create a .ini file containing the original assembly location */
        if (!shadow_copy_create_ini (shadow, filename)) {
                g_free (shadow);
-               mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Failed to create shadow copy .ini file.");
+               mono_error_set_execution_engine (oerror, "Failed to create shadow copy .ini file.");
                return NULL;
        }
 
@@ -2146,10 +2145,11 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad,  MonoString *assRef,
 void
 ves_icall_System_AppDomain_InternalUnload (gint32 domain_id)
 {
+       MonoException *exc = NULL;
        MonoDomain * domain = mono_domain_get_by_id (domain_id);
 
        if (NULL == domain) {
-               MonoException *exc = mono_get_exception_execution_engine ("Failed to unload domain, domain id not found");
+               mono_get_exception_execution_engine ("Failed to unload domain, domain id not found");
                mono_set_pending_exception (exc);
                return;
        }
@@ -2169,7 +2169,9 @@ ves_icall_System_AppDomain_InternalUnload (gint32 domain_id)
        return;
 #endif
 
-       mono_domain_unload (domain);
+       mono_domain_try_unload (domain, (MonoObject**)&exc);
+       if (exc)
+               mono_set_pending_exception (exc);
 }
 
 gboolean
@@ -2516,8 +2518,6 @@ mono_domain_unload (MonoDomain *domain)
 {
        MonoObject *exc = NULL;
        mono_domain_try_unload (domain, &exc);
-       if (exc)
-               mono_raise_exception ((MonoException*)exc);
 }
 
 static guint32
index 58313a937eb4c9007f07fa78c63babf1d63d5c39..ebf94234bb21b83ac59f44a776c2bc2e5d2aff47 100644 (file)
@@ -89,6 +89,7 @@ mono_domain_set            (MonoDomain *domain, mono_bool force);
 MONO_API void
 mono_domain_set_internal   (MonoDomain *domain);
 
+MONO_RT_EXTERNAL_ONLY
 MONO_API void
 mono_domain_unload (MonoDomain *domain);
 
index d0fa87e0173bf85833ff0581dcde0b6c7b6e81e2..14e50f56b687731ef8500e319d622b32e7e3ff19 100644 (file)
@@ -517,7 +517,6 @@ struct _MonoMethodInflated {
                MonoMethod method;
                MonoMethodPInvoke pinvoke;
        } method;
-       MonoMethodHeader *header;
        MonoMethod *declaring;          /* the generic method definition. */
        MonoGenericContext context;     /* The current instantiation */
        MonoImageSet *owner; /* The image set that the inflated method belongs to. */
@@ -918,8 +917,6 @@ extern MonoStats mono_stats;
 typedef gpointer (*MonoRemotingTrampoline)       (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target);
 typedef gpointer (*MonoDelegateTrampoline)       (MonoDomain *domain, MonoClass *klass);
 
-typedef gpointer (*MonoLookupDynamicToken) (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context);
-
 typedef gboolean (*MonoGetCachedClassInfo) (MonoClass *klass, MonoCachedClassInfo *res);
 
 typedef gboolean (*MonoGetClassFromName) (MonoImage *image, const char *name_space, const char *name, MonoClass **res);
@@ -941,7 +938,7 @@ void
 mono_classes_cleanup (void);
 
 void
-mono_class_layout_fields   (MonoClass *klass);
+mono_class_layout_fields   (MonoClass *klass, int instance_size);
 
 void
 mono_class_setup_interface_offsets (MonoClass *klass);
@@ -1011,13 +1008,10 @@ void
 mono_install_delegate_trampoline (MonoDelegateTrampoline func);
 
 gpointer
-mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context);
+mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error);
 
 gpointer
-mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean check_token, MonoClass **handle_class, MonoGenericContext *context);
-
-void
-mono_install_lookup_dynamic_token (MonoLookupDynamicToken func);
+mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean check_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
 
 gpointer
 mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper);
@@ -1153,7 +1147,7 @@ typedef struct {
 #define mono_object_is_transparent_proxy(object) (FALSE)
 #else
 MonoRemoteClass*
-mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class);
+mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class, MonoError *error);
 
 void
 mono_install_remoting_trampoline (MonoRemotingTrampoline func);
index d264ea32ba65bb24b09f9e54628227e7023f5d0f..49225c652e607e7176fe01dff9b5a6f23ef255bd 100644 (file)
@@ -1480,6 +1480,7 @@ mono_class_setup_fields (MonoClass *klass)
        int i, blittable = TRUE;
        guint32 real_size = 0;
        guint32 packing_size = 0;
+       int instance_size;
        gboolean explicit_size;
        MonoClassField *field;
        MonoGenericContainer *container = NULL;
@@ -1555,7 +1556,7 @@ mono_class_setup_fields (MonoClass *klass)
                }
        }
 
-       klass->instance_size = 0;
+       instance_size = 0;
        if (!klass->rank)
                klass->sizes.class_size = 0;
 
@@ -1569,13 +1570,13 @@ mono_class_setup_fields (MonoClass *klass)
                                return;
                        }
                }
-               klass->instance_size += klass->parent->instance_size;
+               instance_size += klass->parent->instance_size;
                klass->min_align = klass->parent->min_align;
                /* we use |= since it may have been set already */
                klass->has_references |= klass->parent->has_references;
                blittable = klass->parent->blittable;
        } else {
-               klass->instance_size = sizeof (MonoObject);
+               instance_size = sizeof (MonoObject);
                klass->min_align = 1;
        }
 
@@ -1597,14 +1598,16 @@ mono_class_setup_fields (MonoClass *klass)
                        return;
                }
                klass->packing_size = packing_size;
-               real_size += klass->instance_size;
+               real_size += instance_size;
        }
 
        if (!top) {
                if (explicit_size && real_size) {
-                       klass->instance_size = MAX (real_size, klass->instance_size);
+                       instance_size = MAX (real_size, instance_size);
                }
                klass->blittable = blittable;
+               if (!klass->instance_size)
+                       klass->instance_size = instance_size;
                mono_memory_barrier ();
                klass->size_inited = 1;
                klass->fields_inited = 1;
@@ -1718,12 +1721,12 @@ mono_class_setup_fields (MonoClass *klass)
                return;
        }
        if (explicit_size && real_size) {
-               klass->instance_size = MAX (real_size, klass->instance_size);
+               instance_size = MAX (real_size, instance_size);
        }
 
        if (mono_class_has_failure (klass))
                return;
-       mono_class_layout_fields (klass);
+       mono_class_layout_fields (klass, instance_size);
 
        /*valuetypes can't be neither bigger than 1Mb or empty. */
        if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
@@ -1804,6 +1807,7 @@ type_has_references (MonoClass *klass, MonoType *ftype)
 /*
  * mono_class_layout_fields:
  * @class: a class
+ * @instance_size: base instance size
  *
  * Compute the placement of fields inside an object or struct, according to
  * the layout rules and set the following fields in @class:
@@ -1816,7 +1820,7 @@ type_has_references (MonoClass *klass, MonoType *ftype)
  * LOCKING: this is supposed to be called with the loader lock held.
  */
 void
-mono_class_layout_fields (MonoClass *klass)
+mono_class_layout_fields (MonoClass *klass, int instance_size)
 {
        int i;
        const int top = klass->field.count;
@@ -1897,7 +1901,6 @@ mono_class_layout_fields (MonoClass *klass)
        /*
         * Compute field layout and total size (not considering static fields)
         */
-
        switch (layout) {
        case TYPE_ATTRIBUTE_AUTO_LAYOUT:
        case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
@@ -1973,11 +1976,11 @@ mono_class_layout_fields (MonoClass *klass)
                                real_size = field->offset + size;
                        }
 
-                       klass->instance_size = MAX (real_size, klass->instance_size);
+                       instance_size = MAX (real_size, instance_size);
        
-                       if (klass->instance_size & (klass->min_align - 1)) {
-                               klass->instance_size += klass->min_align - 1;
-                               klass->instance_size &= ~(klass->min_align - 1);
+                       if (instance_size & (klass->min_align - 1)) {
+                               instance_size += klass->min_align - 1;
+                               instance_size &= ~(klass->min_align - 1);
                        }
                }
                break;
@@ -2062,10 +2065,10 @@ mono_class_layout_fields (MonoClass *klass)
                        g_free (ref_bitmap);
                }
 
-               klass->instance_size = MAX (real_size, klass->instance_size);
-               if (klass->instance_size & (klass->min_align - 1)) {
-                       klass->instance_size += klass->min_align - 1;
-                       klass->instance_size &= ~(klass->min_align - 1);
+               instance_size = MAX (real_size, instance_size);
+               if (instance_size & (klass->min_align - 1)) {
+                       instance_size += klass->min_align - 1;
+                       instance_size &= ~(klass->min_align - 1);
                }
                break;
        }
@@ -2081,11 +2084,17 @@ mono_class_layout_fields (MonoClass *klass)
                 * unaligned accesses otherwise. See #78990 for a testcase.
                 */
                if (mono_align_small_structs) {
-                       if (klass->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
-                               klass->min_align = MAX (klass->min_align, klass->instance_size - sizeof (MonoObject));
+                       if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
+                               klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
                }
        }
 
+       if (klass->instance_size && !klass->image->dynamic) {
+               /* Might be already set using cached info */
+               g_assert (klass->instance_size == instance_size);
+       } else {
+               klass->instance_size = instance_size;
+       }
        mono_memory_barrier ();
        klass->size_inited = 1;
 
@@ -3792,6 +3801,7 @@ mono_class_setup_vtable (MonoClass *klass)
 static void
 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
 {
+       MonoError error;
        MonoMethod **overrides;
        MonoGenericContext *context;
        guint32 type_token;
@@ -3842,7 +3852,14 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
                 * This is true since we don't do layout all over again for them, we simply inflate
                 * the layout of the parent.
                 */
-               mono_reflection_get_dynamic_overrides (klass, &overrides, &onum);
+               mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
+               if (!is_ok (&error)) {
+                       mono_loader_unlock ();
+                       g_list_remove (in_setup, klass);
+                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error)));
+                       mono_error_cleanup (&error);
+                       return;
+               }
        } else {
                /* The following call fails if there are missing methods in the type */
                /* FIXME it's probably a good idea to avoid this for generic instances. */
@@ -7440,7 +7457,7 @@ mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
                        mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
                        return NULL;
                }
-               klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
+               klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
                goto done;
        }
 
@@ -7490,8 +7507,11 @@ mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext
        mono_error_init (error);
 
        //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
-       if (image_is_dynamic (image))
-               return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
+       if (image_is_dynamic (image)) {
+               MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
+               return_val_if_nok (error, NULL);
+               return mono_class_get_type (klass);
+       }
 
        if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
                MonoClass *klass = mono_class_get_checked (image, type_token, error);
@@ -8317,6 +8337,7 @@ mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
 gboolean
 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
 {
+       MonoError error;
        /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
        if (!klass->inited)
                mono_class_init (klass);
@@ -8350,12 +8371,18 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                }
 
                /* interface_offsets might not be set for dynamic classes */
-               if (oklass->ref_info_handle && !oklass->interface_bitmap)
+               if (oklass->ref_info_handle && !oklass->interface_bitmap) {
                        /* 
                         * oklass might be a generic type parameter but they have 
                         * interface_offsets set.
                         */
-                       return mono_reflection_call_is_assignable_to (oklass, klass);
+                       gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
+                       if (!is_ok (&error)) {
+                               mono_error_cleanup (&error);
+                               return FALSE;
+                       }
+                       return result;
+               }
                if (!oklass->interface_bitmap)
                        /* Happens with generic instances of not-yet created dynamic types */
                        return FALSE;
@@ -8363,7 +8390,6 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                        return TRUE;
 
                if (mono_class_has_variant_generic_params (klass)) {
-                       MonoError error;
                        int i;
                        mono_class_setup_interfaces (oklass, &error);
                        if (!mono_error_ok (&error)) {
@@ -8760,8 +8786,9 @@ mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
 
        if (image_is_dynamic (image)) {
                MonoClass *tmp_handle_class;
-               gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
+               gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
 
+               mono_error_assert_ok (error);
                g_assert (tmp_handle_class);
                if (handle_class)
                        *handle_class = tmp_handle_class;
@@ -8841,30 +8868,18 @@ mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
        return NULL;
 }
 
-/**
- * This function might need to call runtime functions so it can't be part
- * of the metadata library.
- */
-static MonoLookupDynamicToken lookup_dynamic = NULL;
-
-void
-mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
-{
-       lookup_dynamic = func;
-}
-
 gpointer
-mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
+mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
 {
        MonoClass *handle_class;
-
-       return lookup_dynamic (image, token, TRUE, &handle_class, context);
+       mono_error_init (error);
+       return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
 }
 
 gpointer
-mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
+mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
 {
-       return lookup_dynamic (image, token, valid_token, handle_class, context);
+       return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
 }
 
 static MonoGetCachedClassInfo get_cached_class_info = NULL;
index 2adee418f37749a9f80db8f8f49a95e75d0b8640..88f1ea21b1950338417d4d9cd0f1f3b8c6b30a1c 100644 (file)
@@ -149,6 +149,10 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method);
 static gpointer
 cominterop_get_ccw (MonoObject* object, MonoClass* itf);
 
+static gpointer
+cominterop_get_ccw_checked (MonoObject *object, MonoClass *itf, MonoError *error);
+
+
 static MonoObject*
 cominterop_get_ccw_object (MonoCCWInterface* ccw_entry, gboolean verify);
 
@@ -465,7 +469,7 @@ cominterop_com_visible (MonoClass* klass)
 
 }
 
-static void cominterop_raise_hr_exception (int hr)
+static void cominterop_set_hr_error (MonoError *oerror, int hr)
 {
        static MonoMethod* throw_exception_for_hr = NULL;
        MonoError error;
@@ -476,26 +480,29 @@ static void cominterop_raise_hr_exception (int hr)
                throw_exception_for_hr = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetExceptionForHR", 1);
 
        ex = (MonoException*)mono_runtime_invoke_checked (throw_exception_for_hr, NULL, params, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_error_assert_ok (&error);
 
-       mono_raise_exception (ex);
+       mono_error_set_exception_instance (oerror, ex);
 }
 
 /**
- * cominterop_get_interface:
+ * cominterop_get_interface_checked:
  * @obj: managed wrapper object containing COM object
  * @ic: interface type to retrieve for COM object
+ * @error: set on error
  *
- * Returns: the COM interface requested
+ * Returns: the COM interface requested. On failure returns NULL and sets @error
  */
 static gpointer
-cominterop_get_interface (MonoComObject* obj, MonoClass* ic, gboolean throw_exception)
+cominterop_get_interface_checked (MonoComObject* obj, MonoClass* ic, MonoError *error)
 {
        gpointer itf = NULL;
 
        g_assert (ic);
        g_assert (MONO_CLASS_IS_INTERFACE (ic));
 
+       mono_error_init (error);
+
        mono_cominterop_lock ();
        if (obj->itf_hash)
                itf = g_hash_table_lookup (obj->itf_hash, GUINT_TO_POINTER ((guint)ic->interface_id));
@@ -507,8 +514,8 @@ cominterop_get_interface (MonoComObject* obj, MonoClass* ic, gboolean throw_exce
                int hr;
                g_assert(found);
                hr = ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (obj->iunknown, iid, &itf);
-               if (hr < 0 && throw_exception) {
-                       cominterop_raise_hr_exception (hr);     
+               if (hr < 0) {
+                       cominterop_set_hr_error (error, hr);
                }
 
                if (hr >= 0 && itf) {
@@ -520,6 +527,30 @@ cominterop_get_interface (MonoComObject* obj, MonoClass* ic, gboolean throw_exce
                }
 
        }
+       return itf;
+}
+
+/**
+ * cominterop_get_interface:
+ * @obj: managed wrapper object containing COM object
+ * @ic: interface type to retrieve for COM object
+ *
+ * Returns: the COM interface requested
+ */
+static gpointer
+cominterop_get_interface (MonoComObject *obj, MonoClass *ic, gboolean throw_exception)
+{
+       MonoError error;
+       gpointer itf = cominterop_get_interface_checked (obj, ic, &error);
+       if (!is_ok (&error)) {
+               if (throw_exception) {
+                       mono_error_set_pending_exception (&error);
+                       return NULL;
+               } else {
+                       mono_error_cleanup (&error);
+               }
+       }
+
        if (throw_exception)
                g_assert (itf);
 
@@ -544,7 +575,7 @@ cominterop_type_from_handle (MonoType *handle)
        mono_class_init (klass);
 
        ret = mono_type_get_object_checked (domain, handle, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_error_set_pending_exception (&error);
 
        return ret;
 }
@@ -1449,20 +1480,23 @@ static gboolean cominterop_can_support_dispatch (MonoClass* klass)
 }
 
 static void*
-cominterop_get_idispatch_for_object (MonoObject* object)
+cominterop_get_idispatch_for_object (MonoObject* object, MonoError *error)
 {
+       mono_error_init (error);
        if (!object)
                return NULL;
 
        if (cominterop_object_is_rcw (object)) {
-               return cominterop_get_interface (((MonoComInteropProxy*)((MonoTransparentProxy*)object)->rp)->com_object, 
-                       mono_class_get_idispatch_class (), TRUE);
+               return cominterop_get_interface_checked (((MonoComInteropProxy*)((MonoTransparentProxy*)object)->rp)->com_object,
+                                                        mono_class_get_idispatch_class (), error);
        }
        else {
                MonoClass* klass = mono_object_class (object);
-               if (!cominterop_can_support_dispatch (klass) )
-                       cominterop_raise_hr_exception (MONO_E_NOINTERFACE);
-               return cominterop_get_ccw (object, mono_class_get_idispatch_class ());
+               if (!cominterop_can_support_dispatch (klass) ) {
+                       cominterop_set_hr_error (error, MONO_E_NOINTERFACE);
+                       return NULL;
+               }
+               return cominterop_get_ccw_checked (object, mono_class_get_idispatch_class (), error);
        }
 }
 
@@ -1470,6 +1504,8 @@ void*
 ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal (MonoObject* object)
 {
 #ifndef DISABLE_COM
+       MonoError error;
+
        if (!object)
                return NULL;
 
@@ -1504,7 +1540,9 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal (M
                return ((MonoComInteropProxy*)real_proxy)->com_object->iunknown;
        }
        else {
-               return cominterop_get_ccw (object, mono_class_get_iunknown_class ());
+               void* ccw_entry = cominterop_get_ccw_checked (object, mono_class_get_iunknown_class (), &error);
+               mono_error_set_pending_exception (&error);
+               return ccw_entry;
        }
 #else
        g_assert_not_reached ();
@@ -1533,7 +1571,10 @@ void*
 ves_icall_System_Runtime_InteropServices_Marshal_GetIDispatchForObjectInternal (MonoObject* object)
 {
 #ifndef DISABLE_COM
-       return cominterop_get_idispatch_for_object (object);
+       MonoError error;
+       void* idisp = cominterop_get_idispatch_for_object (object, &error);
+       mono_error_set_pending_exception (&error);
+       return idisp;
 #else
        g_assert_not_reached ();
 #endif
@@ -1543,6 +1584,7 @@ void*
 ves_icall_System_Runtime_InteropServices_Marshal_GetCCW (MonoObject* object, MonoReflectionType* type)
 {
 #ifndef DISABLE_COM
+       MonoError error;
        MonoClass* klass = NULL;
        void* itf = NULL;
        g_assert (type);
@@ -1554,8 +1596,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetCCW (MonoObject* object, Mon
                return NULL;
        }
 
-       itf = cominterop_get_ccw (object, klass);
-       g_assert (itf);
+       itf = cominterop_get_ccw_checked (object, klass, &error);
+       mono_error_set_pending_exception (&error);
        return itf;
 #else
        g_assert_not_reached ();
@@ -1712,13 +1754,19 @@ gpointer
 ves_icall_System_ComObject_GetInterfaceInternal (MonoComObject* obj, MonoReflectionType* type, MonoBoolean throw_exception)
 {
 #ifndef DISABLE_COM
+       MonoError error;
        MonoClass *klass = mono_type_get_class (type->type);
        if (!mono_class_init (klass)) {
                mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
                return NULL;
        }
 
-       return cominterop_get_interface (obj, klass, (gboolean)throw_exception);
+       gpointer itf = cominterop_get_interface_checked (obj, klass, &error);
+       if (throw_exception)
+               mono_error_set_pending_exception (&error);
+       else
+               mono_error_cleanup (&error);
+       return itf;
 #else
        g_assert_not_reached ();
 #endif
@@ -1826,17 +1874,18 @@ cominterop_setup_marshal_context (EmitMarshalContext *m, MonoMethod *method)
 }
 
 /**
- * cominterop_get_ccw:
+ * cominterop_get_ccw_checked:
  * @object: a pointer to the object
  * @itf: interface type needed
+ * @error: set on error
  *
  * Returns: a value indicating if the object is a
- * Runtime Callable Wrapper (RCW) for a COM object
+ * Runtime Callable Wrapper (RCW) for a COM object.
+ * On failure returns NULL and sets @error.
  */
 static gpointer
-cominterop_get_ccw (MonoObject* object, MonoClass* itf)
+cominterop_get_ccw_checked (MonoObject* object, MonoClass* itf, MonoError *error)
 {
-       MonoError error;
        int i;
        MonoCCW *ccw = NULL;
        MonoCCWInterface* ccw_entry = NULL;
@@ -1851,6 +1900,8 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf)
        GList *ccw_list, *ccw_list_item;
        MonoCustomAttrInfo *cinfo = NULL;
 
+       mono_error_init (error);
+       
        if (!object)
                return NULL;
 
@@ -1908,12 +1959,12 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf)
                g_hash_table_insert (ccw_hash, GINT_TO_POINTER (mono_object_hash (object)), ccw_list);
                mono_cominterop_unlock ();
                /* register for finalization to clean up ccw */
-               mono_object_register_finalizer (object, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_object_register_finalizer (object, error);
+               return_val_if_nok (error, NULL);
        }
 
-       cinfo = mono_custom_attrs_from_class_checked (itf, &error);
-       mono_error_assert_ok (&error);
+       cinfo = mono_custom_attrs_from_class_checked (itf, error);
+       mono_error_assert_ok (error);
        if (cinfo) {
                static MonoClass* coclass_attribute = NULL;
                if (!coclass_attribute)
@@ -2056,6 +2107,23 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf)
        return ccw_entry;
 }
 
+/**
+ * cominterop_get_ccw:
+ * @object: a pointer to the object
+ * @itf: interface type needed
+ *
+ * Returns: a value indicating if the object is a
+ * Runtime Callable Wrapper (RCW) for a COM object
+ */
+static gpointer
+cominterop_get_ccw (MonoObject* object, MonoClass* itf)
+{
+       MonoError error;
+       gpointer ccw_entry = cominterop_get_ccw_checked (object, itf, &error);
+       mono_error_set_pending_exception (&error);
+       return ccw_entry;
+}
+
 static gboolean
 mono_marshal_free_ccw_entry (gpointer key, gpointer value, gpointer user_data)
 {
@@ -2334,10 +2402,12 @@ static int
 cominterop_ccw_getfreethreadedmarshaler (MonoCCW* ccw, MonoObject* object, gpointer* ppv)
 {
 #ifdef HOST_WIN32
+       MonoError error;
        if (!ccw->free_marshaler) {
                int ret = 0;
                gpointer tunk;
-               tunk = cominterop_get_ccw (object, mono_class_get_iunknown_class ());
+               tunk = cominterop_get_ccw_checked (object, mono_class_get_iunknown_class (), &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
                ret = CoCreateFreeThreadedMarshaler (tunk, (LPUNKNOWN*)&ccw->free_marshaler);
        }
                
@@ -2374,7 +2444,8 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p
 
        /* handle IUnknown special */
        if (cominterop_class_guid_equal (riid, mono_class_get_iunknown_class ())) {
-               *ppv = cominterop_get_ccw (object, mono_class_get_iunknown_class ());
+               *ppv = cominterop_get_ccw_checked (object, mono_class_get_iunknown_class (), &error);
+               mono_error_assert_ok (&error);
                /* remember to addref on QI */
                cominterop_ccw_addref ((MonoCCWInterface *)*ppv);
                return MONO_S_OK;
@@ -2385,7 +2456,8 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p
                if (!cominterop_can_support_dispatch (klass))
                        return MONO_E_NOINTERFACE;
                
-               *ppv = cominterop_get_ccw (object, mono_class_get_idispatch_class ());
+               *ppv = cominterop_get_ccw_checked (object, mono_class_get_idispatch_class (), &error);
+               mono_error_assert_ok (&error);
                /* remember to addref on QI */
                cominterop_ccw_addref ((MonoCCWInterface *)*ppv);
                return MONO_S_OK;
@@ -2419,7 +2491,11 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p
                klass_iter = klass_iter->parent;
        }
        if (itf) {
-               *ppv = cominterop_get_ccw (object, itf);
+               *ppv = cominterop_get_ccw_checked (object, itf, &error);
+               if (!is_ok (&error)) {
+                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
+                       return MONO_E_NOINTERFACE;
+               }
                /* remember to addref on QI */
                cominterop_ccw_addref ((MonoCCWInterface *)*ppv);
                return MONO_S_OK;
@@ -3060,13 +3136,15 @@ mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer *
 
                                hr = mono_marshal_safe_array_get_lbound (safearray, i+1, &lbound);
                                if (hr < 0) {
-                                       cominterop_raise_hr_exception (hr);
+                                       cominterop_set_hr_error (&error, hr);
+                                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                                }
                                if (lbound != 0)
                                        bounded = TRUE;
                                hr = mono_marshal_safe_array_get_ubound (safearray, i+1, &ubound);
                                if (hr < 0) {
-                                       cominterop_raise_hr_exception (hr);
+                                       cominterop_set_hr_error (&error, hr);
+                                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                                }
                                cursize = ubound-lbound+1;
                                sizes [i] = cursize;
@@ -3093,17 +3171,20 @@ mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer *
 static 
 gpointer mono_marshal_safearray_get_value (gpointer safearray, gpointer indices)
 {
+       MonoError error;
        gpointer result;
 #ifdef HOST_WIN32
        int hr = SafeArrayPtrOfIndex (safearray, indices, &result);
        if (hr < 0) {
-               cominterop_raise_hr_exception (hr);
+                       cominterop_set_hr_error (&error, hr);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
        }
 #else
        if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {
                int hr = safe_array_ptr_of_index_ms (safearray, (glong *)indices, &result);
                if (hr < 0) {
-                       cominterop_raise_hr_exception (hr);
+                       cominterop_set_hr_error (&error, hr);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
        } else {
                g_assert_not_reached ();
@@ -3115,6 +3196,7 @@ gpointer mono_marshal_safearray_get_value (gpointer safearray, gpointer indices)
 static 
 gboolean mono_marshal_safearray_next (gpointer safearray, gpointer indices)
 {
+       MonoError error;
        int i;
        int dim = mono_marshal_safearray_get_dim (safearray);
        gboolean ret= TRUE;
@@ -3127,7 +3209,8 @@ gboolean mono_marshal_safearray_next (gpointer safearray, gpointer indices)
 
                hr = mono_marshal_safe_array_get_ubound (safearray, i+1, &ubound);
                if (hr < 0) {
-                       cominterop_raise_hr_exception (hr);
+                       cominterop_set_hr_error (&error, hr);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
 
                if (++pIndices[i] <= ubound) {
@@ -3136,7 +3219,8 @@ gboolean mono_marshal_safearray_next (gpointer safearray, gpointer indices)
 
                hr = mono_marshal_safe_array_get_lbound (safearray, i+1, &lbound);
                if (hr < 0) {
-                       cominterop_raise_hr_exception (hr);
+                       cominterop_set_hr_error (&error, hr);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
 
                pIndices[i] = lbound;
@@ -3211,15 +3295,19 @@ mono_marshal_safearray_create (MonoArray *input, gpointer *newsafearray, gpointe
 static 
 void mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpointer value)
 {
+       MonoError error;
 #ifdef HOST_WIN32
        int hr = SafeArrayPutElement (safearray, indices, value);
-       if (hr < 0)
-               cominterop_raise_hr_exception (hr);
+       if (hr < 0) {
+               cominterop_set_hr_error (&error, hr);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+       }
 #else
        if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {
                int hr = safe_array_put_element_ms (safearray, (glong *)indices, (void **)value);
                if (hr < 0) {
-                       cominterop_raise_hr_exception (hr);
+                       cominterop_set_hr_error (&error, hr);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
        } else
                g_assert_not_reached ();
index fe59f700ea987d7a621daff20544b7808ec62acd..43c97c7cfef1a574191fb8a994edc27e90c22acc 100644 (file)
@@ -254,7 +254,11 @@ do_console_cancel_event (void)
        method = mono_class_get_method_from_name (klass, "BeginInvoke", -1);
        g_assert (method != NULL);
 
-       mono_threadpool_ms_begin_invoke (domain, (MonoObject*) load_value, method, NULL);
+       mono_threadpool_ms_begin_invoke (domain, (MonoObject*) load_value, method, NULL, &error);
+       if (!is_ok (&error)) {
+               g_warning ("Couldn't invoke System.Console cancel handler due to %s", mono_error_get_message (&error));
+               mono_error_cleanup (&error);
+       }
 }
 
 static int need_cancel = FALSE;
index 9f2d9fbd81433be9d715311d2d995efc214b61c4..ab021003394f58b85d425213a51cff84e4afa042 100644 (file)
@@ -886,8 +886,8 @@ mono_cleanup (void)
        mono_loader_cleanup ();
        mono_classes_cleanup ();
        mono_assemblies_cleanup ();
-       mono_images_cleanup ();
        mono_debug_cleanup ();
+       mono_images_cleanup ();
        mono_metadata_cleanup ();
 
        mono_native_tls_free (appdomain_thread_id);
index cdf5ea0965e97c2a795733944fb8f81d9f73ad75..e2c45aca38bbc615c7547112df6253a7475560bb 100644 (file)
@@ -966,11 +966,27 @@ mono_error_raise_exception (MonoError *target_error)
                mono_raise_exception (ex);
 }
 
-void
+/**
+ * mono_error_set_pending_exception:
+ * @error: The error
+ *
+ *
+ * If @error is set, convert it to an exception and set the pending exception for the current icall.
+ * Returns TRUE if @error was set, or FALSE otherwise, so that you can write:
+ *    if (mono_error_set_pending_exception (error)) {
+ *      { ... cleanup code ... }
+ *      return;
+ *    }
+ */
+gboolean
 mono_error_set_pending_exception (MonoError *error)
 {
        MonoException *ex = mono_error_convert_to_exception (error);
-       if (ex)
+       if (ex) {
                mono_set_pending_exception (ex);
+               return TRUE;
+       } else {
+               return FALSE;
+       }
 }
 
index b933039b0b0ed222b08aaa2df015b7f947e13b04..e5807a1796c0b6cdfc32ee5e411fede54f956a03 100644 (file)
@@ -94,7 +94,7 @@ mono_handle_elevate (MonoHandle handle)
        return mono_handle_arena_elevate (mono_handle_arena_current (), handle);
 }
 
-#ifndef CHECKED_BUILD
+#ifndef ENABLE_CHECKED_BUILD
 
 #define mono_handle_obj(handle) ((handle)->__private_obj)
 
index 3dd49f236e8000ffebae868a9ab39c1c5b5ce769..5ca728a0489c0ee158e1279b326d7646411a1c5c 100644 (file)
@@ -500,7 +500,7 @@ ICALL(ASSEMB_1, "InternalAddModule", ves_icall_System_Reflection_Emit_AssemblyBu
 ICALL(ASSEMB_2, "basic_init", mono_image_basic_init)
 
 ICALL_TYPE(CATTRB, "System.Reflection.Emit.CustomAttributeBuilder", CATTRB_1)
-ICALL(CATTRB_1, "GetBlob", mono_reflection_get_custom_attrs_blob)
+ICALL(CATTRB_1, "GetBlob", ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob)
 
 #ifndef DISABLE_REFLECTION_EMIT
 ICALL_TYPE(DERIVEDTYPE, "System.Reflection.Emit.DerivedType", DERIVEDTYPE_1)
index d5a846bf9a4afee0656a25f73c60d032596e39fc..01be8d10162465eebda5aec982653fd6c1f7bc8e 100644 (file)
@@ -138,19 +138,23 @@ mono_class_init_checked (MonoClass *klass, MonoError *error)
 ICALL_EXPORT MonoObject *
 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
 {
+       MonoError error;
        MonoClass *ac;
        gint32 esize;
        gpointer *ea;
+       MonoObject *result = NULL;
 
        ac = (MonoClass *)arr->obj.vtable->klass;
 
        esize = mono_array_element_size (ac);
        ea = (gpointer*)((char*)arr->vector + (pos * esize));
 
-       if (ac->element_class->valuetype)
-               return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
-       else
-               return (MonoObject *)*ea;
+       if (ac->element_class->valuetype) {
+               result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
+               mono_error_set_pending_exception (&error);
+       } else
+               result = (MonoObject *)*ea;
+       return result;
 }
 
 ICALL_EXPORT MonoObject *
@@ -203,6 +207,7 @@ ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
 ICALL_EXPORT void
 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
 {
+       MonoError error;
        MonoClass *ac, *vc, *ec;
        gint32 esize, vsize;
        gpointer *ea, *va;
@@ -212,6 +217,8 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
        gint64 i64 = 0;
        gdouble r64 = 0;
 
+       mono_error_init (&error);
+
        if (value)
                vc = value->vtable->klass;
        else
@@ -289,19 +296,24 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32
        }
 
        if (!ec->valuetype) {
-               if (!mono_object_isinst (value, ec))
+               gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
+               if (mono_error_set_pending_exception (&error))
+                       return;
+               if (!castOk)
                        INVALID_CAST;
                mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
                return;
        }
 
-       if (mono_object_isinst (value, ec)) {
+       if (mono_object_isinst_checked (value, ec, &error)) {
                if (ec->has_references)
                        mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
                else
                        mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
                return;
        }
+       if (mono_error_set_pending_exception (&error))
+               return;
 
        if (!vc->valuetype)
                INVALID_CAST;
@@ -1256,6 +1268,15 @@ ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflecti
        return result;
 }
 
+ICALL_EXPORT MonoArray*
+ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
+{
+       MonoError error;
+       MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
+}
+
 static gboolean
 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
 {
@@ -1617,8 +1638,13 @@ ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObje
        MonoError error;
        MonoClass *klass = mono_class_from_mono_type (type->type);
        mono_class_init_checked (klass, &error);
-       mono_error_raise_exception (&error);
-       return mono_object_isinst (obj, klass) != NULL;
+       if (!is_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return FALSE;
+       }
+       guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 ICALL_EXPORT guint32
@@ -2701,10 +2727,12 @@ ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
                types [i] = t->type;
        }
 
-       geninst = mono_reflection_bind_generic_parameters (type, count, types);
+       geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
        g_free (types);
-       if (!geninst)
+       if (!geninst) {
+               mono_error_set_pending_exception (&error);
                return NULL;
+       }
 
        klass = mono_class_from_mono_type (geninst);
 
@@ -3052,7 +3080,11 @@ ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, Mo
                }
 
                if (this_arg) {
-                       if (!mono_object_isinst (this_arg, m->klass)) {
+                       if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
+                               if (!is_ok (&error)) {
+                                       mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
+                                       return NULL;
+                               }
                                char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
                                char *target_name = mono_type_get_full_name (m->klass);
                                char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
@@ -3164,6 +3196,7 @@ ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, Mo
 ICALL_EXPORT MonoObject *
 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs) 
 {
+       MonoError error;
        MonoDomain *domain = mono_object_domain (method); 
        MonoMethod *m = method->method;
        MonoMethodSignature *sig = mono_method_signature (m);
@@ -3192,9 +3225,11 @@ ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, M
                                MonoClassField* field = mono_class_get_field_from_name (k, str);
                                if (field) {
                                        MonoClass *field_klass =  mono_class_from_mono_type (field->type);
-                                       if (field_klass->valuetype)
-                                               result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
-                                       else 
+                                       if (field_klass->valuetype) {
+                                               result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
+                                               mono_error_set_pending_exception (&error);
+                                               /* fallthru to cleanup */
+                                       } else 
                                                result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
                                
                                        out_args = mono_array_new (domain, mono_defaults.object_class, 1);
@@ -4355,8 +4390,7 @@ ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint
 
        mono_ptr_array_destroy (tmp_array);
 
-       if (!str)
-               g_free (str);
+       g_free (str);
 
        return res;
 }
@@ -5516,7 +5550,6 @@ mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **excepti
                if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
                        klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
                        mono_loader_assert_no_error (); /* Plug any leaks */
-                       mono_error_assert_ok (error);
                        
                        if (klass) {
                                rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
@@ -5792,10 +5825,13 @@ mono_memberref_is_method (MonoImage *image, guint32 token)
                mono_metadata_decode_blob_size (sig, &sig);
                return (*sig != 0x6);
        } else {
+               MonoError error;
                MonoClass *handle_class;
 
-               if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
+               if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
+                       mono_error_cleanup (&error); /* just probing, ignore error */
                        return FALSE;
+               }
 
                return mono_defaults.methodhandle_class == handle_class;
        }
@@ -5836,12 +5872,14 @@ ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 t
 
        if (image_is_dynamic (image)) {
                if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
-                       klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+                       klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+                       mono_error_cleanup (&error);
                        return klass ? &klass->byval_arg : NULL;
                }
 
                init_generic_context_from_args (&context, type_args, method_args);
-               klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
+               klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
+               mono_error_cleanup (&error);
                return klass ? &klass->byval_arg : NULL;
        }
 
@@ -5884,8 +5922,11 @@ ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32
        }
 
        if (image_is_dynamic (image)) {
-               if (table == MONO_TABLE_METHOD)
-                       return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+               if (table == MONO_TABLE_METHOD) {
+                       method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+                       mono_error_cleanup (&error);
+                       return method;
+               }
 
                if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
                        *resolve_error = ResolveTokenError_BadTable;
@@ -5893,7 +5934,9 @@ ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32
                }
 
                init_generic_context_from_args (&context, type_args, method_args);
-               return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
+               method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
+               mono_error_cleanup (&error);
+               return method;
        }
 
        if ((index <= 0) || (index > image->tables [table].rows)) {
@@ -5913,23 +5956,27 @@ ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32
 }
 
 ICALL_EXPORT MonoString*
-ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
+ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
 {
+       MonoError error;
        int index = mono_metadata_token_index (token);
 
-       *error = ResolveTokenError_Other;
+       *resolve_error = ResolveTokenError_Other;
 
        /* Validate token */
        if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
-               *error = ResolveTokenError_BadTable;
+               *resolve_error = ResolveTokenError_BadTable;
                return NULL;
        }
 
-       if (image_is_dynamic (image))
-               return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+       if (image_is_dynamic (image)) {
+               MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+               mono_error_cleanup (&error);
+               return result;
+       }
 
        if ((index <= 0) || (index >= image->heap_us.size)) {
-               *error = ResolveTokenError_OutOfRange;
+               *resolve_error = ResolveTokenError_OutOfRange;
                return NULL;
        }
 
@@ -5957,8 +6004,11 @@ ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32
        }
 
        if (image_is_dynamic (image)) {
-               if (table == MONO_TABLE_FIELD)
-                       return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+               if (table == MONO_TABLE_FIELD) {
+                       field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+                       mono_error_cleanup (&error);
+                       return field;
+               }
 
                if (mono_memberref_is_method (image, token)) {
                        *resolve_error = ResolveTokenError_BadTable;
@@ -5966,7 +6016,9 @@ ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32
                }
 
                init_generic_context_from_args (&context, type_args, method_args);
-               return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
+               field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
+               mono_error_cleanup (&error);
+               return field;
        }
 
        if ((index <= 0) || (index > image->tables [table].rows)) {
@@ -6265,7 +6317,14 @@ ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, Mon
        mono_class_init_checked (delegate_class, &error);
        mono_error_raise_exception (&error);
 
-       mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
+       if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
+               /* FIXME improve this exception message */
+               mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
+                                                __func__,
+                                                "delegate_class->parent == mono_defaults.multicastdelegate_class");
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
 
        if (mono_security_core_clr_enabled ()) {
                if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
@@ -6435,8 +6494,16 @@ ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoStri
                return NULL;
        }
 
-       tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
-       tp->remote_class = mono_remote_class (domain, class_name, klass);
+       tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
+       if (!is_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+       tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
+       if (!is_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
 
        res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
        return res;
@@ -7590,12 +7657,16 @@ mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
 ICALL_EXPORT MonoObject*
 mono_TypedReference_ToObject (MonoTypedRef* tref)
 {
+       MonoError error;
+       MonoObject *result = NULL;
        if (MONO_TYPE_IS_REFERENCE (tref->type)) {
                MonoObject** objp = (MonoObject **)tref->value;
                return *objp;
        }
 
-       return mono_value_box (mono_domain_get (), tref->klass, tref->value);
+       result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 ICALL_EXPORT MonoTypedRef
index c99de7aa04f344b980db02069a46a38a274f5bfc..b16cd7cc2e88dd4fecb216b724ad1a14793503b2 100644 (file)
@@ -509,9 +509,19 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo)
 
        i = ((MonoImageLoader*)image->loader)->load_tables (image);
        g_assert (image->heap_guid.data);
-       g_assert (image->heap_guid.size >= 16);
 
-       image->guid = mono_guid_to_string ((guint8*)image->heap_guid.data);
+       if (!image->metadata_only) {
+               g_assert (image->heap_guid.size >= 16);
+
+               image->guid = mono_guid_to_string ((guint8*)image->heap_guid.data);
+       } else {
+               /* PPDB files have no guid */
+               guint8 empty_guid [16];
+
+               memset (empty_guid, 0, sizeof (empty_guid));
+
+               image->guid = mono_guid_to_string (empty_guid);
+       }
 
        return i;
 }
@@ -1070,13 +1080,13 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
                goto done;
        }
 
-       if (image->loader == &pe_loader && !mono_verifier_verify_cli_data (image, &errors))
+       if (image->loader == &pe_loader && !image->metadata_only && !mono_verifier_verify_cli_data (image, &errors))
                goto invalid_image;
 
        if (!mono_image_load_cli_data (image))
                goto invalid_image;
 
-       if (image->loader == &pe_loader && !mono_verifier_verify_table_data (image, &errors))
+       if (image->loader == &pe_loader && !image->metadata_only && !mono_verifier_verify_table_data (image, &errors))
                goto invalid_image;
 
        mono_image_load_names (image);
index 56630da1eddbdf44b210c32f3670351a49b502e7..2195d22618f6180bcf37e2755ebdcdac3ee6dcfc 100644 (file)
@@ -563,7 +563,9 @@ mono_field_from_token_checked (MonoImage *image, guint32 token, MonoClass **retk
                MonoClass *handle_class;
 
                *retklass = NULL;
-               result = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context);
+               MonoError inner_error;
+               result = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context, &inner_error);
+               mono_error_cleanup (&inner_error);
                // This checks the memberref type as well
                if (!result || handle_class != mono_defaults.fieldhandle_class) {
                        mono_error_set_bad_image (error, image, "Bad field token 0x%08x", token);
@@ -874,27 +876,31 @@ mono_inflate_generic_signature (MonoMethodSignature *sig, MonoGenericContext *co
 static MonoMethodHeader*
 inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context, MonoError *error)
 {
-       MonoMethodHeader *res;
-       int i;
-       res = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + sizeof (gpointer) * header->num_locals);
+       size_t locals_size = sizeof (gpointer) * header->num_locals;
+       size_t clauses_size = header->num_clauses * sizeof (MonoExceptionClause);
+       size_t header_size = MONO_SIZEOF_METHOD_HEADER + locals_size + clauses_size; 
+       MonoMethodHeader *res = (MonoMethodHeader *)g_malloc0 (header_size);
+       res->num_locals = header->num_locals;
+       res->clauses = (MonoExceptionClause *) &res->locals [res->num_locals] ;
+       memcpy (res->clauses, header->clauses, clauses_size);
+
        res->code = header->code;
        res->code_size = header->code_size;
        res->max_stack = header->max_stack;
        res->num_clauses = header->num_clauses;
        res->init_locals = header->init_locals;
-       res->num_locals = header->num_locals;
-       res->clauses = header->clauses;
+
+       res->is_transient = TRUE;
 
        mono_error_init (error);
 
-       for (i = 0; i < header->num_locals; ++i) {
+       for (int i = 0; i < header->num_locals; ++i) {
                res->locals [i] = mono_class_inflate_generic_type_checked (header->locals [i], context, error);
                if (!is_ok (error))
                        goto fail;
        }
        if (res->num_clauses) {
-               res->clauses = (MonoExceptionClause *)g_memdup (header->clauses, sizeof (MonoExceptionClause) * res->num_clauses);
-               for (i = 0; i < header->num_clauses; ++i) {
+               for (int i = 0; i < header->num_clauses; ++i) {
                        MonoExceptionClause *clause = &res->clauses [i];
                        if (clause->flags != MONO_EXCEPTION_CLAUSE_NONE)
                                continue;
@@ -1873,7 +1879,8 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass,
        if (image_is_dynamic (image)) {
                MonoClass *handle_class;
 
-               result = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context);
+               result = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context, error);
+               mono_error_assert_ok (error);
                mono_loader_assert_no_error ();
 
                // This checks the memberref type as well
@@ -2827,20 +2834,7 @@ mono_method_get_header_checked (MonoMethod *method, MonoError *error)
                        return NULL;
                }
 
-               mono_image_lock (img);
-
-               if (imethod->header) {
-                       mono_metadata_free_mh (iheader);
-                       mono_image_unlock (img);
-                       return imethod->header;
-               }
-
-               mono_memory_barrier ();
-               imethod->header = iheader;
-
-               mono_image_unlock (img);
-
-               return imethod->header;
+               return iheader;
        }
 
        if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) {
index 696b97deca31c7385e56335cb44f4c2af65aa062..9b7eca1ffce41cca0086710387a74c9d10f9157c 100644 (file)
@@ -211,11 +211,11 @@ init_safe_handle ()
 }
 
 static void
-register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
+register_icall (gpointer func, const char *name, const char *sigstr, gboolean no_wrapper)
 {
        MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
 
-       mono_register_jit_icall (func, name, sig, save);
+       mono_register_jit_icall (func, name, sig, no_wrapper);
 }
 
 MonoMethodSignature*
@@ -237,6 +237,15 @@ mono_marshal_init_tls (void)
        mono_native_tls_alloc (&load_type_info_tls_id, NULL);
 }
 
+static MonoObject*
+mono_object_isinst_icall (MonoObject *obj, MonoClass *klass)
+{
+       MonoError error;
+       MonoObject *result = mono_object_isinst_checked (obj, klass, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
+}
+
 void
 mono_marshal_init (void)
 {
@@ -284,7 +293,7 @@ mono_marshal_init (void)
                register_icall (mono_string_to_byvalstr, "mono_string_to_byvalstr", "void ptr ptr int32", FALSE);
                register_icall (mono_string_to_byvalwstr, "mono_string_to_byvalwstr", "void ptr ptr int32", FALSE);
                register_icall (g_free, "g_free", "void ptr", FALSE);
-               register_icall (mono_object_isinst, "mono_object_isinst", "object object ptr", FALSE);
+               register_icall (mono_object_isinst_icall, "mono_object_isinst_icall", "object object ptr", FALSE);
                register_icall (mono_struct_delete_old, "mono_struct_delete_old", "void ptr ptr", FALSE);
                register_icall (mono_delegate_begin_invoke, "mono_delegate_begin_invoke", "object object ptr", FALSE);
                register_icall (mono_delegate_end_invoke, "mono_delegate_end_invoke", "object object ptr", FALSE);
@@ -352,7 +361,7 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate)
        if (delegate->method_is_virtual)
                method = mono_object_get_virtual_method (delegate->target, method);
 
-       if (mono_method_signature (method)->pinvoke) {
+       if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
                const char *exc_class, *exc_arg;
                gpointer ftnptr;
 
@@ -519,7 +528,11 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
 
                if (use_aot_wrappers) {
                        wrapper = mono_marshal_get_native_func_wrapper_aot (klass);
-                       this_obj = mono_value_box (mono_domain_get (), mono_defaults.int_class, &ftn);
+                       this_obj = mono_value_box_checked (mono_domain_get (), mono_defaults.int_class, &ftn, &error);
+                       if (!is_ok (&error)) {
+                               mono_error_set_pending_exception (&error);
+                               return NULL;
+                       }
                } else {
                        memset (&piinfo, 0, sizeof (piinfo));
                        parse_unmanaged_function_pointer_attr (klass, &piinfo);
@@ -1843,11 +1856,7 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
        }
                
        default: {
-               char *msg = g_strdup_printf ("marshalling conversion %d not implemented", conv);
-               MonoException *exc = mono_get_exception_not_implemented (msg);
-               g_warning ("%s", msg);
-               g_free (msg);
-               mono_raise_exception (exc);
+               g_error ("marshalling conversion %d not implemented", conv);
        }
        }
 }
@@ -2205,7 +2214,9 @@ mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
                method = mono_get_delegate_invoke (klass);
        g_assert (method);
 
-       return mono_threadpool_ms_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params);
+       MonoAsyncResult *result = mono_threadpool_ms_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 #ifndef DISABLE_JIT
@@ -8226,7 +8237,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
        EmitMarshalContext m;
 
        g_assert (method != NULL);
-       g_assert (!mono_method_signature (method)->pinvoke);
+       g_assert (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL));
 
        /* 
         * FIXME: Should cache the method+delegate type pair, since the same method
@@ -8587,7 +8598,9 @@ mono_marshal_get_castclass_with_cache (void)
 static MonoObject *
 mono_marshal_isinst_with_cache (MonoObject *obj, MonoClass *klass, uintptr_t *cache)
 {
-       MonoObject *isinst = mono_object_isinst (obj, klass);
+       MonoError error;
+       MonoObject *isinst = mono_object_isinst_checked (obj, klass, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
 #ifndef DISABLE_REMOTING
        if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
@@ -9490,7 +9503,7 @@ get_virtual_stelemref_wrapper (int kind)
                /*if (mono_object_isinst (value, aklass)) */
                mono_mb_emit_ldarg (mb, 2);
                mono_mb_emit_ldloc (mb, aklass);
-               mono_mb_emit_icall (mb, mono_object_isinst);
+               mono_mb_emit_icall (mb, mono_object_isinst_icall);
                b2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
 
                /* do_store: */
@@ -9604,7 +9617,7 @@ get_virtual_stelemref_wrapper (int kind)
                /*if (mono_object_isinst (value, aklass)) */
                mono_mb_emit_ldarg (mb, 2);
                mono_mb_emit_ldloc (mb, aklass);
-               mono_mb_emit_icall (mb, mono_object_isinst);
+               mono_mb_emit_icall (mb, mono_object_isinst_icall);
                b2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
 
                /* if (vklass->idepth < aklass->idepth) goto failue */
@@ -9930,7 +9943,7 @@ mono_marshal_get_stelemref (void)
        
        mono_mb_emit_ldarg (mb, 2);
        mono_mb_emit_ldloc (mb, aklass);
-       mono_mb_emit_icall (mb, mono_object_isinst);
+       mono_mb_emit_icall (mb, mono_object_isinst_icall);
        
        b4 = mono_mb_emit_branch (mb, CEE_BRTRUE);
        mono_mb_patch_addr (mb, b4, copy_pos - (b4 + 4));
index a96f8cee6380ae2adf0e67ff0d5f0c2cddf019ab..1ed5d5125e9b74bfad194f8ecf74242fd72120f0 100644 (file)
@@ -1837,8 +1837,11 @@ mono_metadata_parse_signature (MonoImage *image, guint32 token)
        guint32 sig;
        const char *ptr;
 
-       if (image_is_dynamic (image))
-               return (MonoMethodSignature *)mono_lookup_dynamic_token (image, token, NULL);
+       if (image_is_dynamic (image)) {
+               ret = (MonoMethodSignature *)mono_lookup_dynamic_token (image, token, NULL, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               return ret;
+       }
 
        g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
                
@@ -2772,18 +2775,6 @@ free_inflated_method (MonoMethodInflated *imethod)
        if (method->signature)
                mono_metadata_free_inflated_signature (method->signature);
 
-       if (!((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))) {
-               MonoMethodHeader *header = imethod->header;
-
-               if (header) {
-                       /* Allocated in inflate_generic_header () */
-                       for (i = 0; i < header->num_locals; ++i)
-                               mono_metadata_free_type (header->locals [i]);
-                       g_free (header->clauses);
-                       g_free (header);
-               }
-       }
-
        g_free (method);
 }
 
index d7115994b84f49a9063db8720ace9c9423c44f15..5f9aa0736f401205a52d5500a3eb9fdee31d8010 100644 (file)
@@ -514,20 +514,11 @@ mono_basic_block_free (MonoSimpleBasicBlock *bb)
  * Return the list of basic blocks of method. Return NULL on failure and set @error.
 */
 MonoSimpleBasicBlock*
-mono_basic_block_split (MonoMethod *method, MonoError *error)
+mono_basic_block_split (MonoMethod *method, MonoError *error, MonoMethodHeader *header)
 {
        MonoError inner_error;
        MonoSimpleBasicBlock *bb, *root;
        const unsigned char *start, *end;
-       MonoMethodHeader *header = mono_method_get_header_checked (method, &inner_error);
-
-       mono_error_init (error);
-
-       if (!header) {
-               mono_error_set_not_verifiable (error, method, "Could not decode header due to %s", mono_error_get_message (&inner_error));
-               mono_error_cleanup (&inner_error);
-               return NULL;
-       }
 
        start = header->code;
        end = start + header->code_size;
@@ -553,11 +544,9 @@ mono_basic_block_split (MonoMethod *method, MonoError *error)
        dump_bb_list (bb, &root, g_strdup_printf("AFTER LIVENESS %s", mono_method_full_name (method, TRUE)));
 #endif
 
-       mono_metadata_free_mh (header);
        return bb;
 
 fail:
-       mono_metadata_free_mh (header);
        mono_basic_block_free (bb);
        return NULL;
 }
index a971b36176efe2b7badb6cdf4d6f29c53d0e3aa3..a3f65187873add05800f1a59f35fb1912c01d817 100644 (file)
@@ -19,7 +19,7 @@ struct _MonoSimpleBasicBlock {
 };
 
 MonoSimpleBasicBlock*
-mono_basic_block_split (MonoMethod *method, MonoError *error);
+mono_basic_block_split (MonoMethod *method, MonoError *error, MonoMethodHeader *header);
 
 void
 mono_basic_block_free (MonoSimpleBasicBlock *bb);
index b7ab37ea690fac711a97b23898f462e9312ca9b1..4a316f33cc1da1bf8920ab2a73cb3b729bfe394a 100644 (file)
 #include "mono/utils/mono-tls.h"
 #include "mono/utils/mono-coop-mutex.h"
 
-#if 1
-#ifdef __GNUC__
-#define mono_assert(expr)                 G_STMT_START{                  \
-     if (!(expr))                                                        \
-       {                                                                 \
-               MonoException *ex;                                        \
-               char *msg = g_strdup_printf ("file %s: line %d (%s): "    \
-               "assertion failed: (%s)", __FILE__, __LINE__,             \
-               __PRETTY_FUNCTION__, #expr);                              \
-               ex = mono_get_exception_execution_engine (msg);           \
-               g_free (msg);                                             \
-               mono_raise_exception (ex);                                \
-       };                              }G_STMT_END
-
-#define mono_assert_not_reached()                G_STMT_START{           \
-     MonoException *ex;                                                          \
-     char *msg = g_strdup_printf ("file %s: line %d (%s): "              \
-     "should not be reached", __FILE__, __LINE__, __PRETTY_FUNCTION__);          \
-     ex = mono_get_exception_execution_engine (msg);                     \
-     g_free (msg);                                                       \
-     mono_raise_exception (ex);                                                  \
-}G_STMT_END
-#else /* not GNUC */
-#define mono_assert(expr)                 G_STMT_START{                  \
-     if (!(expr))                                                        \
-       {                                                                 \
-               MonoException *ex;                                        \
-               char *msg = g_strdup_printf ("file %s: line %d: "         \
-               "assertion failed: (%s)", __FILE__, __LINE__,             \
-               #expr);                                                   \
-               ex = mono_get_exception_execution_engine (msg);           \
-               g_free (msg);                                             \
-               mono_raise_exception (ex);                                \
-       };                              }G_STMT_END
-
-#define mono_assert_not_reached()                G_STMT_START{           \
-     MonoException *ex;                                                          \
-     char *msg = g_strdup_printf ("file %s: line %d): "                          \
-     "should not be reached", __FILE__, __LINE__);                       \
-     ex = mono_get_exception_execution_engine (msg);                     \
-     g_free (msg);                                                       \
-     mono_raise_exception (ex);                                                  \
-}G_STMT_END
-#endif
-#else
-#define mono_assert(expr) g_assert(expr)
-#define mono_assert_not_reached() g_assert_not_reached() 
-#endif
-
 /* Use this as MONO_CHECK_ARG_NULL (arg,expr,) in functions returning void */
 #define MONO_CHECK_ARG(arg, expr, retval)              G_STMT_START{             \
                if (G_UNLIKELY (!(expr)))                                                         \
@@ -734,17 +685,6 @@ mono_domain_get_tls_offset (void);
 
 #define IS_MONOTYPE(obj) (!(obj) || (((MonoObject*)(obj))->vtable->klass->image == mono_defaults.corlib && ((MonoReflectionType*)(obj))->type != NULL))
 
-/* 
- * Make sure the argument, which should be a System.Type is a System.MonoType object 
- * or equivalent, and not an instance of 
- * a user defined subclass of System.Type. This should be used in places were throwing
- * an exception is safe.
- */
-#define CHECK_MONOTYPE(obj) do { \
-       if (!IS_MONOTYPE (obj)) \
-               mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
-       } while (0)
-
 /* This should be used for accessing members of Type[] arrays */
 #define mono_type_array_get(arr,index) monotype_cast (mono_array_get ((arr), gpointer, (index)))
 
@@ -1411,7 +1351,7 @@ void        mono_reflection_create_generic_class  (MonoReflectionTypeBuilder *tb
 
 MonoReflectionType* mono_reflection_create_runtime_class  (MonoReflectionTypeBuilder *tb);
 
-void        mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides);
+void        mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error);
 
 void mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *m);
 void mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb);
@@ -1428,7 +1368,7 @@ MonoArray* mono_param_get_objects_internal  (MonoDomain *domain, MonoMethod *met
 MonoClass*
 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic);
 MonoType*
-mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types);
+mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error);
 MonoReflectionMethod*
 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *method, MonoArray *types);
 void
@@ -1443,10 +1383,10 @@ MonoArray  *mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelp
 MonoReflectionMarshalAsAttribute* mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass, MonoMarshalSpec *spec, MonoError *error);
 
 gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context);
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
 
 gboolean
-mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass);
+mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error);
 
 gboolean
 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token);
@@ -1514,8 +1454,11 @@ mono_get_addr_from_ftnptr (gpointer descr);
 void
 mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass);
 
+MonoObject *
+mono_value_box_checked (MonoDomain *domain, MonoClass *klass, void* val, MonoError *error);
+
 MonoObject*
-mono_nullable_box (guint8 *buf, MonoClass *klass);
+mono_nullable_box (guint8 *buf, MonoClass *klass, MonoError *error);
 
 #ifdef MONO_SMALL_CONFIG
 #define MONO_IMT_SIZE 9
@@ -1672,7 +1615,7 @@ mono_copy_value (MonoType *type, void *dest, void *value, int deref_pointer);
 void
 mono_error_raise_exception (MonoError *target_error);
 
-void
+gboolean
 mono_error_set_pending_exception (MonoError *error);
 
 MonoArray *
@@ -1693,6 +1636,12 @@ ves_icall_object_new_fast (MonoVTable *vtable);
 MonoObject *
 mono_object_clone_checked (MonoObject *obj, MonoError *error);
 
+MonoObject *
+mono_object_isinst_checked (MonoObject *obj, MonoClass *klass, MonoError *error);
+
+MonoObject *
+mono_object_isinst_mbyref_checked   (MonoObject *obj, MonoClass *klass, MonoError *error);
+
 MonoString *
 mono_string_new_size_checked (MonoDomain *domain, gint32 len, MonoError *error);
 
index ad58b37b8e51fc63a69ea02a99c899d9eba1f5d6..92a733b34bdb66ebc7420b7e075980975ab7315f 100644 (file)
@@ -2591,21 +2591,23 @@ copy_remote_class_key (MonoDomain *domain, gpointer *key)
  * mono_remote_class:
  * @domain: the application domain
  * @class_name: name of the remote class
+ * @error: set on error
  *
  * Creates and initializes a MonoRemoteClass object for a remote type. 
  *
- * Can raise an exception on failure. 
+ * On failure returns NULL and sets @error
  */
 MonoRemoteClass*
-mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
+mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoError error;
        MonoRemoteClass *rc;
        gpointer* key, *mp_key;
        char *name;
        
+       mono_error_init (error);
+
        key = create_remote_class_key (NULL, proxy_class);
        
        mono_domain_lock (domain);
@@ -2617,11 +2619,11 @@ mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_
                return rc;
        }
 
-       name = mono_string_to_utf8_mp (domain->mp, class_name, &error);
-       if (!mono_error_ok (&error)) {
+       name = mono_string_to_utf8_mp (domain->mp, class_name, error);
+       if (!is_ok (error)) {
                g_free (key);
                mono_domain_unlock (domain);
-               mono_error_raise_exception (&error);
+               return NULL;
        }
 
        mp_key = copy_remote_class_key (domain, key);
@@ -3504,7 +3506,7 @@ mono_field_get_value_object_checked (MonoDomain *domain, MonoClassField *field,
        klass = mono_class_from_mono_type (type);
 
        if (mono_class_is_nullable (klass))
-               return mono_nullable_box (mono_field_get_addr (obj, vtable, field), klass);
+               return mono_nullable_box (mono_field_get_addr (obj, vtable, field), klass, error);
 
        o = mono_object_new_checked (domain, klass, error);
        return_val_if_nok (error, NULL);
@@ -3732,17 +3734,17 @@ mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
  * mono_nullable_box:
  * @buf: The buffer representing the data to be boxed
  * @klass: the type to box it as.
+ * @error: set on oerr
  *
  * Creates a boxed vtype or NULL from the Nullable structure pointed to by
- * @buf.
+ * @buf.  On failure returns NULL and sets @error
  */
 MonoObject*
-mono_nullable_box (guint8 *buf, MonoClass *klass)
+mono_nullable_box (guint8 *buf, MonoClass *klass, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoError error;
-       
+       mono_error_init (error);
        MonoClass *param_class = klass->cast_class;
 
        mono_class_setup_fields_locking (klass);
@@ -3752,8 +3754,8 @@ mono_nullable_box (guint8 *buf, MonoClass *klass)
        g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
 
        if (*(guint8*)(buf + klass->fields [1].offset - sizeof (MonoObject))) {
-               MonoObject *o = mono_object_new_checked (mono_domain_get (), param_class, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoObject *o = mono_object_new_checked (mono_domain_get (), param_class, error);
+               return_val_if_nok (error, NULL);
                if (param_class->has_references)
                        mono_gc_wbarrier_value_copy (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), 1, param_class);
                else
@@ -4598,7 +4600,8 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                                                 * boxed object in the arg array with the copy.
                                                 */
                                                MonoObject *orig = mono_array_get (params, MonoObject*, i);
-                                               MonoObject *copy = mono_value_box (mono_domain_get (), orig->vtable->klass, mono_object_unbox (orig));
+                                               MonoObject *copy = mono_value_box_checked (mono_domain_get (), orig->vtable->klass, mono_object_unbox (orig), &error);
+                                               mono_error_raise_exception (&error); /* FIXME don't raise here */
                                                mono_array_setref (params, i, copy);
                                        }
                                                
@@ -4650,8 +4653,11 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
 
                        if (!params)
                                return NULL;
-                       else
-                               return mono_value_box (mono_domain_get (), method->klass->cast_class, pa [0]);
+                       else {
+                               MonoObject *result = mono_value_box_checked (mono_domain_get (), method->klass->cast_class, pa [0], &error);
+                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                               return result;
+                       }
                }
 
                if (!obj) {
@@ -4667,7 +4673,8 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        else
                                o = obj;
                } else if (method->klass->valuetype) {
-                       obj = mono_value_box (mono_domain_get (), method->klass, obj);
+                       obj = mono_value_box_checked (mono_domain_get (), method->klass, obj, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
 
                if (exc) {
@@ -4690,7 +4697,9 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        nullable = mono_object_new_checked (mono_domain_get (), method->klass, &error);
                        mono_error_raise_exception (&error); /* FIXME don't raise here */
 
-                       mono_nullable_init ((guint8 *)mono_object_unbox (nullable), mono_value_box (mono_domain_get (), method->klass->cast_class, obj), method->klass);
+                       MonoObject *boxed = mono_value_box_checked (mono_domain_get (), method->klass->cast_class, obj, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_nullable_init ((guint8 *)mono_object_unbox (nullable), boxed, method->klass);
                        obj = mono_object_unbox (nullable);
                }
 
@@ -4879,7 +4888,7 @@ mono_object_new_specific_checked (MonoVTable *vtable, MonoError *error)
 
                        im = mono_class_get_method_from_name (klass, "CreateProxyForType", 1);
                        if (!im) {
-                               mono_error_set_generic_error (error, "System", "NotSupportedException", "Linked away.");
+                               mono_error_set_not_supported (error, "Linked away.");
                                return NULL;
                        }
                        vtable->domain->create_proxy_for_type_method = im;
@@ -5796,23 +5805,42 @@ mono_string_new_wrapper (const char *text)
 MonoObject *
 mono_value_box (MonoDomain *domain, MonoClass *klass, gpointer value)
 {
-       MONO_REQ_GC_UNSAFE_MODE;
-
        MonoError error;
+       MonoObject *result = mono_value_box_checked (domain, klass, value, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
+/**
+ * mono_value_box_checked:
+ * @domain: the domain of the new object
+ * @class: the class of the value
+ * @value: a pointer to the unboxed data
+ * @error: set on error
+ *
+ * Returns: A newly created object which contains @value. On failure
+ * returns NULL and sets @error.
+ */
+MonoObject *
+mono_value_box_checked (MonoDomain *domain, MonoClass *klass, gpointer value, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
        MonoObject *res;
        int size;
        MonoVTable *vtable;
 
+       mono_error_init (error);
+
        g_assert (klass->valuetype);
        if (mono_class_is_nullable (klass))
-               return mono_nullable_box ((guint8 *)value, klass);
+               return mono_nullable_box ((guint8 *)value, klass, error);
 
        vtable = mono_class_vtable (domain, klass);
        if (!vtable)
                return NULL;
        size = mono_class_instance_size (klass);
-       res = mono_object_new_alloc_specific_checked (vtable, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       res = mono_object_new_alloc_specific_checked (vtable, error);
+       return_val_if_nok (error, NULL);
 
        size = size - sizeof (MonoObject);
 
@@ -5842,8 +5870,8 @@ mono_value_box (MonoDomain *domain, MonoClass *klass, gpointer value)
 #endif
 #endif
        if (klass->has_finalize) {
-               mono_object_register_finalizer (res, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_object_register_finalizer (res, error);
+               return_val_if_nok (error, NULL);
        }
        return res;
 }
@@ -5968,18 +5996,45 @@ mono_object_unbox (MonoObject *obj)
  * @obj: an object
  * @klass: a pointer to a class 
  *
- * Returns: @obj if @obj is derived from @klass
+ * Returns: @obj if @obj is derived from @klass or NULL otherwise.
  */
 MonoObject *
 mono_object_isinst (MonoObject *obj, MonoClass *klass)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+       MonoObject *result = mono_object_isinst_checked (obj, klass, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+       
+
+/**
+ * mono_object_isinst_checked:
+ * @obj: an object
+ * @klass: a pointer to a class 
+ * @error: set on error
+ *
+ * Returns: @obj if @obj is derived from @klass or NULL if it isn't.
+ * On failure returns NULL and sets @error.
+ */
+MonoObject *
+mono_object_isinst_checked (MonoObject *obj, MonoClass *klass, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       mono_error_init (error);
+       
+       MonoObject *result = NULL;
+
        if (!klass->inited)
                mono_class_init (klass);
 
-       if (mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_INTERFACE))
-               return mono_object_isinst_mbyref (obj, klass);
+       if (mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+               result = mono_object_isinst_mbyref_checked (obj, klass, error);
+               return result;
+       }
 
        if (!obj)
                return NULL;
@@ -5993,8 +6048,20 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoError error;
+       MonoObject *result = mono_object_isinst_mbyref_checked (obj, klass, &error);
+       mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
+       return result;
+}
+
+MonoObject *
+mono_object_isinst_mbyref_checked (MonoObject *obj, MonoClass *klass, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoVTable *vt;
 
+       mono_error_init (error);
+
        if (!obj)
                return NULL;
 
@@ -6033,12 +6100,12 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
                im = mono_object_get_virtual_method (rp, im);
                g_assert (im);
        
-               pa [0] = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               pa [0] = mono_type_get_object_checked (domain, &klass->byval_arg, error);
+               return_val_if_nok (error, NULL);
                pa [1] = obj;
 
-               res = mono_runtime_invoke_checked (im, rp, pa, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               res = mono_runtime_invoke_checked (im, rp, pa, error);
+               return_val_if_nok (error, NULL);
 
                if (*(MonoBoolean *) mono_object_unbox(res)) {
                        /* Update the vtable of the remote type, so it can safely cast to this new type */
@@ -6055,19 +6122,17 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
  * @obj: an object
  * @klass: a pointer to a class 
  *
- * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
+ * Returns: @obj if @obj is derived from @klass, returns NULL otherwise.
  */
 MonoObject *
 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
 {
        MONO_REQ_GC_UNSAFE_MODE;
+       MonoError error;
 
        if (!obj) return NULL;
-       if (mono_object_isinst_mbyref (obj, klass)) return obj;
-               
-       mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
-                                                       "System",
-                                                       "InvalidCastException"));
+       if (mono_object_isinst_mbyref_checked (obj, klass, &error)) return obj;
+       mono_error_cleanup (&error);
        return NULL;
 }
 
@@ -6230,9 +6295,11 @@ MonoString*
 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
 {
        MONO_REQ_GC_UNSAFE_MODE;
+       MonoError error;
 
        if (image->dynamic) {
-               MonoString *str = (MonoString *)mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL);
+               MonoString *str = (MonoString *)mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
                return str;
        } else {
                if (!mono_verifier_verify_string_signature (image, idx, NULL))
@@ -6916,7 +6983,7 @@ mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, MonoObject
        if (!im) {
                im = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "PrivateInvoke", 4);
                if (!im) {
-                       mono_error_set_generic_error (error, "System", "NotSupportedException", "Linked away.");
+                       mono_error_set_not_supported (error, "Linked away.");
                        return NULL;
                }
                real_proxy->vtable->domain->private_invoke_method = im;
@@ -7236,9 +7303,10 @@ mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *
 
                klass = mono_class_from_mono_type (sig->params [i]);
 
-               if (klass->valuetype)
-                       arg = mono_value_box (domain, klass, vpos);
-               else 
+               if (klass->valuetype) {
+                       arg = mono_value_box_checked (domain, klass, vpos, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               } else 
                        arg = *((MonoObject **)vpos);
                      
                mono_array_setref (msg->args, i, arg);
@@ -7499,9 +7567,10 @@ mono_store_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField
                        mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
        }
 
-       if (field_class->valuetype)
-               arg = mono_value_box (domain, field_class, val);
-       else 
+       if (field_class->valuetype) {
+               arg = mono_value_box_checked (domain, field_class, val, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+       } else 
                arg = *((MonoObject **)val);
                
 
index 433938694844601138a58549ed296c236e659c98..360dcd0d63188714790752d0e38c6e846496e662 100644 (file)
@@ -162,6 +162,7 @@ mono_object_hash            (MonoObject* obj);
 MONO_API MonoString *
 mono_object_to_string (MonoObject *obj, MonoObject **exc);
 
+MONO_RT_EXTERNAL_ONLY
 MONO_API MonoObject *
 mono_value_box             (MonoDomain *domain, MonoClass *klass, void* val);
 
@@ -183,12 +184,15 @@ mono_object_unbox     (MonoObject *obj);
 MONO_API MonoObject *
 mono_object_clone          (MonoObject *obj);
 
+MONO_RT_EXTERNAL_ONLY
 MONO_API MonoObject *
 mono_object_isinst         (MonoObject *obj, MonoClass *klass);
 
+MONO_RT_EXTERNAL_ONLY
 MONO_API MonoObject *
 mono_object_isinst_mbyref   (MonoObject *obj, MonoClass *klass);
 
+MONO_RT_EXTERNAL_ONLY
 MONO_API MonoObject *
 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass);
 
index af5ba0afdb0b0a6420e1f309712fb928d04cf811..04417c82b714856c00bd88020cc484a2b4b4bf55 100644 (file)
@@ -27,6 +27,9 @@ mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error
 MonoArray*
 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error);
 
+MonoArray*
+mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error);
+
 MonoCustomAttrInfo*
 mono_custom_attrs_from_index_checked    (MonoImage *image, uint32_t idx, MonoError *error);
 MonoCustomAttrInfo*
index a3ea522b1cf5e1cccdccde76bbd134070ae6fe9f..c49153f85a1615f3052355b6c3fc37086d85f0a2 100644 (file)
@@ -151,7 +151,7 @@ static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, M
 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
-static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
+static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
@@ -187,6 +187,8 @@ static gboolean is_sr_mono_property (MonoClass *klass);
 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
 
+static gboolean type_is_reference (MonoType *type);
+
 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
@@ -5533,7 +5535,7 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
        /* Check for user defined reflection objects */
        /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
        if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
-               mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
+               mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
                return 0;
        }
 
@@ -7773,7 +7775,7 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
 {
        MonoError error;
        MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
-       mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
+       mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
        return result;
 }
 
@@ -7802,7 +7804,7 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
 
        /* for compatibility with .net */
        if (method_is_dynamic (method)) {
-               mono_error_set_exception_instance (error, mono_get_exception_invalid_operation (NULL));
+               mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
                return NULL;
        }
 
@@ -7842,7 +7844,8 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
                local_var_sig_token = 0; //FIXME
 
        ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
-       return_val_if_nok (error, NULL);
+       if (!is_ok (error))
+               goto fail;
 
        ret->init_locals = header->init_locals;
        ret->max_stack = header->max_stack;
@@ -7854,10 +7857,12 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
        MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
        for (i = 0; i < header->num_locals; ++i) {
                MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
-               return_val_if_nok (error, NULL);
+               if (!is_ok (error))
+                       goto fail;
 
                rt = mono_type_get_object_checked (domain, header->locals [i], error);
-               return_val_if_nok (error, NULL);
+               if (!is_ok (error))
+                       goto fail;
 
                MONO_OBJECT_SETREF (info, local_type, rt);
 
@@ -7870,7 +7875,8 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
        MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
        for (i = 0; i < header->num_clauses; ++i) {
                MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
-               return_val_if_nok (error, NULL);
+               if (!is_ok (error))
+                       goto fail;
                MonoExceptionClause *clause = &header->clauses [i];
 
                info->flags = clause->flags;
@@ -7882,7 +7888,8 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
                        info->filter_offset = clause->data.filter_offset;
                else if (clause->data.catch_class) {
                        rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
-                       return_val_if_nok (error, NULL);
+                       if (!is_ok (error))
+                               goto fail;
 
                        MONO_OBJECT_SETREF (info, catch_type, rt);
                }
@@ -7893,6 +7900,10 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
        mono_metadata_free_mh (header);
        CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
        return ret;
+
+fail:
+       mono_metadata_free_mh (header);
+       return NULL;
 }
 
 /**
@@ -8571,7 +8582,7 @@ mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoT
                        return NULL;
 
                instance = mono_reflection_bind_generic_parameters (
-                       the_type, info->type_arguments->len, type_args);
+                       the_type, info->type_arguments->len, type_args, error);
 
                g_free (type_args);
                if (!instance)
@@ -8914,8 +8925,8 @@ mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
        } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
                token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
        } else {
-               mono_error_set_generic_error (error, "System", "NotImplementedException",
-                                             "MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
+               mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
+                                               klass->name_space, klass->name);
                return 0;
        }
 
@@ -9206,6 +9217,28 @@ handle_type:
        return NULL;
 }
 
+static MonoObject*
+load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
+{
+       mono_error_init (error);
+
+       gboolean is_ref = type_is_reference (t);
+
+       void *val = load_cattr_value (image, t, p, end, error);
+       if (!is_ok (error)) {
+               if (is_ref)
+                       g_free (val);
+               return NULL;
+       }
+
+       if (is_ref)
+               return (MonoObject*)val;
+
+       MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
+       g_free (val);
+       return boxed;
+}
+
 static MonoObject*
 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
 {
@@ -9541,21 +9574,10 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
        p += 2;
        for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
                MonoObject *obj;
-               void *val;
-
-               val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
-               if (!mono_error_ok (error)) {
-                       if (!type_is_reference (mono_method_signature (method)->params [i]))
-                               g_free (val);
-                       return;
-               }
 
-               obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
-                       val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
+               obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
+               return_if_nok (error);
                mono_array_setref (typedargs, i, obj);
-
-               if (!type_is_reference (mono_method_signature (method)->params [i]))
-                       g_free (val);
        }
 
        named = p;
@@ -9598,7 +9620,6 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
                if (named_type == 0x53) {
                        MonoObject *obj;
                        MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
-                       void *val;
 
                        if (!field) {
                                g_free (name);
@@ -9608,23 +9629,17 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
                        arginfo [j].type = field->type;
                        arginfo [j].field = field;
 
-                       val = load_cattr_value (image, field->type, named, &named, error);
-                       if (!mono_error_ok (error)) {
-                               if (!type_is_reference (field->type))
-                                       g_free (val);
+                       obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
+                       if (!is_ok (error)) {
                                g_free (name);
                                return;
                        }
-
-                       obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
                        mono_array_setref (namedargs, j, obj);
-                       if (!type_is_reference (field->type))
-                               g_free (val);
+
                } else if (named_type == 0x54) {
                        MonoObject *obj;
                        MonoType *prop_type;
                        MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
-                       void *val;
 
                        if (!prop || !prop->set) {
                                g_free (name);
@@ -9637,18 +9652,12 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
                        arginfo [j].type = prop_type;
                        arginfo [j].prop = prop;
 
-                       val = load_cattr_value (image, prop_type, named, &named, error);
-                       if (!mono_error_ok (error)) {
-                               if (!type_is_reference (prop_type))
-                                       g_free (val);
+                       obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
+                       if (!is_ok (error)) {
                                g_free (name);
                                return;
                        }
-
-                       obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
                        mono_array_setref (namedargs, j, obj);
-                       if (!type_is_reference (prop_type))
-                               g_free (val);
                }
                g_free (name);
        }
@@ -10362,7 +10371,7 @@ mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error
 #endif
                else {
                        char *type_name = mono_type_get_full_name (member_class);
-                       mono_error_set_generic_error (error, "System", "NotSupportedException",
+                       mono_error_set_not_supported (error,
                                                      "Custom attributes on a ParamInfo with member %s are not supported",
                                                      type_name);
                        g_free (type_name);
@@ -10663,7 +10672,7 @@ mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
                        }
                }
 
-               res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
+               res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
                g_free (types);
                g_assert (res);
                gclass->type.type = res;
@@ -10682,17 +10691,20 @@ mono_reflection_create_unmanaged_type (MonoReflectionType *type)
        mono_error_set_pending_exception (&error);
 }
 
-void
-mono_reflection_register_with_runtime (MonoReflectionType *type)
+static gboolean
+reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
 {
-       MonoError error;
-       MonoType *res = mono_reflection_type_get_handle (type, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
        MonoDomain *domain = mono_object_domain ((MonoObject*)type);
        MonoClass *klass;
 
-       if (!res)
-               mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
+       mono_error_init (error);
+
+       MonoType *res = mono_reflection_type_get_handle (type, error);
+
+       if (!res && is_ok (error)) {
+               mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
+       }
+       return_val_if_nok (error, FALSE);
 
        klass = mono_class_from_mono_type (res);
 
@@ -10709,25 +10721,39 @@ mono_reflection_register_with_runtime (MonoReflectionType *type)
        }
        mono_domain_unlock (domain);
        mono_loader_unlock ();
+
+       return TRUE;
+}
+
+void
+mono_reflection_register_with_runtime (MonoReflectionType *type)
+{
+       MonoError error;
+       (void) reflection_register_with_runtime (type, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 /**
  * LOCKING: Assumes the loader lock is held.
  */
 static MonoMethodSignature*
-parameters_to_signature (MonoImage *image, MonoArray *parameters) {
-       MonoError error;
+parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
        MonoMethodSignature *sig;
        int count, i;
 
+       mono_error_init (error);
+
        count = parameters? mono_array_length (parameters): 0;
 
        sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
        sig->param_count = count;
        sig->sentinelpos = -1; /* FIXME */
        for (i = 0; i < count; ++i) {
-               sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
+               if (!is_ok (error)) {
+                       image_g_free (image, sig);
+                       return NULL;
+               }
        }
        return sig;
 }
@@ -10736,10 +10762,13 @@ parameters_to_signature (MonoImage *image, MonoArray *parameters) {
  * LOCKING: Assumes the loader lock is held.
  */
 static MonoMethodSignature*
-ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
+ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
        MonoMethodSignature *sig;
 
-       sig = parameters_to_signature (image, ctor->parameters);
+       mono_error_init (error);
+
+       sig = parameters_to_signature (image, ctor->parameters, error);
+       return_val_if_nok (error, NULL);
        sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
        sig->ret = &mono_defaults.void_class->byval_arg;
        return sig;
@@ -10749,15 +10778,20 @@ ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
  * LOCKING: Assumes the loader lock is held.
  */
 static MonoMethodSignature*
-method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
-       MonoError error;
+method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
        MonoMethodSignature *sig;
 
-       sig = parameters_to_signature (image, method->parameters);
+       mono_error_init (error);
+
+       sig = parameters_to_signature (image, method->parameters, error);
+       return_val_if_nok (error, NULL);
        sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
        if (method->rtype) {
-               sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
+               if (!is_ok (error)) {
+                       image_g_free (image, sig);
+                       return NULL;
+               }
        } else {
                sig->ret = &mono_defaults.void_class->byval_arg;
        }
@@ -10766,15 +10800,20 @@ method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *meth
 }
 
 static MonoMethodSignature*
-dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
-       MonoError error;
+dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
        MonoMethodSignature *sig;
 
-       sig = parameters_to_signature (NULL, method->parameters);
+       mono_error_init (error);
+
+       sig = parameters_to_signature (NULL, method->parameters, error);
+       return_val_if_nok (error, NULL);
        sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
        if (method->rtype) {
-               sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               sig->ret = mono_reflection_type_get_handle (method->rtype, error);
+               if (!is_ok (error)) {
+                       g_free (sig);
+                       return NULL;
+               }
        } else {
                sig->ret = &mono_defaults.void_class->byval_arg;
        }
@@ -10783,15 +10822,14 @@ dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
 }
 
 static void
-get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
+get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
 {
-       MonoError error;
+       mono_error_init (error);
        MonoClass *klass = mono_object_class (prop);
        if (strcmp (klass->name, "PropertyBuilder") == 0) {
                MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
                *name = mono_string_to_utf8 (pb->name);
-               *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
        } else {
                MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
                *name = g_strdup (p->property->name);
@@ -10803,15 +10841,14 @@ get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
 }
 
 static void
-get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
+get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
 {
-       MonoError error;
+       mono_error_init (error);
        MonoClass *klass = mono_object_class (field);
        if (strcmp (klass->name, "FieldBuilder") == 0) {
                MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
                *name = mono_string_to_utf8 (fb->name);
-               *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
        } else {
                MonoReflectionField *f = (MonoReflectionField *)field;
                *name = g_strdup (mono_field_get_name (f->field));
@@ -10907,14 +10944,15 @@ mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *er
                type = mono_reflection_type_get_underlying_system_type (type, error);
                return_val_if_nok (error, NULL);
                if (is_usertype (type)) {
-                       mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
+                       mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
                        return NULL;
                }
        }
 
        return type;
 }
-/*
+/**
+ * encode_cattr_value:
  * Encode a value in a custom attribute stream of bytes.
  * The value to encode is either supplied as an object in argument val
  * (valuetypes are boxed), or as a pointer to the data in the
@@ -10925,13 +10963,14 @@ mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *er
  * @buflen contains the size of the buffer and is used to return the new buffer size
  * if this needs to be realloced.
  * @retbuffer and @retp return the start and the position of the buffer
+ * @error set on error.
  */
 static void
-encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
+encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
 {
-       MonoError error;
        MonoTypeEnum simple_type;
        
+       mono_error_init (error);
        if ((p-buffer) + 10 >= *buflen) {
                char *newbuf;
                *buflen *= 2;
@@ -11010,8 +11049,9 @@ handle_enum:
                        break;
                }
 handle_type:
-               arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
+               return_if_nok (error);
+
                str = type_get_qualified_name (arg_type, NULL);
                slen = strlen (str);
                if ((p-buffer) + 10 + slen >= *buflen) {
@@ -11054,19 +11094,22 @@ handle_type:
                        char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
                        int elsize = mono_class_array_element_size (arg_eclass);
                        for (i = 0; i < len; ++i) {
-                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
+                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
+                               return_if_nok (error);
                                elptr += elsize;
                        }
                } else if (eclass->valuetype && arg_eclass->valuetype) {
                        char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
                        int elsize = mono_class_array_element_size (eclass);
                        for (i = 0; i < len; ++i) {
-                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
+                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
+                               return_if_nok (error);
                                elptr += elsize;
                        }
                } else {
                        for (i = 0; i < len; ++i) {
-                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
+                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
+                               return_if_nok (error);
                        }
                }
                break;
@@ -11090,10 +11133,14 @@ handle_type:
                
                klass = mono_object_class (arg);
 
-               if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
+               if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
                        *p++ = 0x50;
                        goto handle_type;
-               } else if (klass->enumtype) {
+               } else {
+                       return_if_nok (error);
+               }
+
+               if (klass->enumtype) {
                        *p++ = 0x55;
                } else if (klass == mono_defaults.string_class) {
                        simple_type = MONO_TYPE_STRING;
@@ -11106,7 +11153,8 @@ handle_type:
                                *p++ = 0x51;
                        else
                                *p++ = klass->element_class->byval_arg.type;
-                       encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
+                       encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
+                       return_if_nok (error);
                        break;
                } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
                        *p++ = simple_type = klass->byval_arg.type;
@@ -11171,9 +11219,12 @@ encode_field_or_prop_type (MonoType *type, char *p, char **retp)
 
 #ifndef DISABLE_REFLECTION_EMIT
 static void
-encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
+encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
 {
        int len;
+
+       mono_error_init (error);
+
        /* Preallocate a large enough buffer */
        if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
                char *str = type_get_qualified_name (type, NULL);
@@ -11203,12 +11254,13 @@ encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char
        mono_metadata_encode_value (len, p, &p);
        memcpy (p, name, len);
        p += len;
-       encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
+       encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
+       return_if_nok (error);
        *retp = p;
        *retbuffer = buffer;
 }
 
-/*
+/**
  * mono_reflection_get_custom_attrs_blob:
  * @ctor: custom attribute constructor
  * @ctorArgs: arguments o the constructor
@@ -11224,15 +11276,44 @@ encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char
 MonoArray*
 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
 {
-       MonoArray *result;
+       MonoError error;
+       MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
+       mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
+       return result;
+}
+
+/**
+ * mono_reflection_get_custom_attrs_blob_checked:
+ * @ctor: custom attribute constructor
+ * @ctorArgs: arguments o the constructor
+ * @properties:
+ * @propValues:
+ * @fields:
+ * @fieldValues:
+ * @error: set on error
+ * 
+ * Creates the blob of data that needs to be saved in the metadata and that represents
+ * the custom attributed described by @ctor, @ctorArgs etc.
+ * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
+ */
+MonoArray*
+mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
+{
+       MonoArray *result = NULL;
        MonoMethodSignature *sig;
        MonoObject *arg;
        char *buffer, *p;
        guint32 buflen, i;
 
+       mono_error_init (error);
+
        if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
                /* sig is freed later so allocate it in the heap */
-               sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
+               sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
+               if (!is_ok (error)) {
+                       g_free (sig);
+                       return NULL;
+               }
        } else {
                sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
        }
@@ -11245,7 +11326,8 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
        *p++ = 0;
        for (i = 0; i < sig->param_count; ++i) {
                arg = mono_array_get (ctorArgs, MonoObject*, i);
-               encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
+               encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
+               if (!is_ok (error)) goto leave;
        }
        i = 0;
        if (properties)
@@ -11261,10 +11343,12 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
                        char *pname;
 
                        prop = (MonoObject *)mono_array_get (properties, gpointer, i);
-                       get_prop_name_and_type (prop, &pname, &ptype);
+                       get_prop_name_and_type (prop, &pname, &ptype, error);
+                       if (!is_ok (error)) goto leave;
                        *p++ = 0x54; /* PROPERTY signature */
-                       encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
+                       encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
                        g_free (pname);
+                       if (!is_ok (error)) goto leave;
                }
        }
 
@@ -11275,10 +11359,12 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
                        char *fname;
 
                        field = (MonoObject *)mono_array_get (fields, gpointer, i);
-                       get_field_name_and_type (field, &fname, &ftype);
+                       get_field_name_and_type (field, &fname, &ftype, error);
+                       if (!is_ok (error)) goto leave;
                        *p++ = 0x53; /* FIELD signature */
-                       encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
+                       encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
                        g_free (fname);
+                       if (!is_ok (error)) goto leave;
                }
        }
 
@@ -11287,36 +11373,40 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
        result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
        p = mono_array_addr (result, char, 0);
        memcpy (p, buffer, buflen);
+leave:
        g_free (buffer);
        if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
                g_free (sig);
        return result;
 }
 
-/*
- * mono_reflection_setup_internal_class:
+/**
+ * reflection_setup_internal_class:
  * @tb: a TypeBuilder object
+ * @error: set on error
  *
  * Creates a MonoClass that represents the TypeBuilder.
  * This is a trick that lets us simplify a lot of reflection code
  * (and will allow us to support Build and Run assemblies easier).
+ *
+ * Returns TRUE on success. On failure, returns FALSE and sets @error.
  */
-void
-mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
+static gboolean
+reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
 {
-       MonoError error;
        MonoClass *klass, *parent;
 
-       RESOLVE_TYPE (tb->parent, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_error_init (error);
+       RESOLVE_TYPE (tb->parent, error);
+       return_val_if_nok (error, FALSE);
 
        mono_loader_lock ();
 
        if (tb->parent) {
-               MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
-               if (!is_ok (&error)) {
+               MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
+               if (!is_ok (error)) {
                        mono_loader_unlock ();
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return FALSE;
                }
                /* check so we can compile corlib correctly */
                if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
@@ -11338,7 +11428,7 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
                mono_class_setup_parent (klass, parent);
                mono_class_setup_mono_type (klass);
                mono_loader_unlock ();
-               return;
+               return TRUE;
        }
 
        klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
@@ -11346,11 +11436,11 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
        klass->image = &tb->module->dynamic_image->image;
 
        klass->inited = 1; /* we lie to the runtime */
-       klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
-       if (!mono_error_ok (&error))
+       klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
+       if (!is_ok (error))
                goto failure;
-       klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
-       if (!mono_error_ok (&error))
+       klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
+       if (!is_ok (error))
                goto failure;
        klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
        klass->flags = tb->attrs;
@@ -11411,8 +11501,8 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
 
        if (tb->nesting_type) {
                g_assert (tb->nesting_type->type);
-               MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
-               if (!is_ok (&error)) goto failure;
+               MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
+               if (!is_ok (error)) goto failure;
                klass->nested_in = mono_class_from_mono_type (nesting_type);
        }
 
@@ -11421,11 +11511,29 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
        mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
        
        mono_loader_unlock ();
-       return;
+       return TRUE;
 
 failure:
        mono_loader_unlock ();
-       mono_error_raise_exception (&error);
+       return FALSE;
+}
+
+/**
+ * mono_reflection_setup_internal_class:
+ * @tb: a TypeBuilder object
+ *
+ * (icall)
+ * Creates a MonoClass that represents the TypeBuilder.
+ * This is a trick that lets us simplify a lot of reflection code
+ * (and will allow us to support Build and Run assemblies easier).
+ *
+ */
+void
+mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
+{
+       MonoError error;
+       (void) reflection_setup_internal_class (tb, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 /*
@@ -11486,18 +11594,22 @@ mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
        klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
 }
 
-/*
- * mono_reflection_create_internal_class:
+/**
+ * reflection_create_internal_class:
  * @tb: a TypeBuilder object
+ * @error: set on error
  *
  * Actually create the MonoClass that is associated with the TypeBuilder.
+ * On success returns TRUE, on failure returns FALSE and sets @error.
+ *
  */
-void
-mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
+static gboolean
+reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
 {
-       MonoError error;
+
        MonoClass *klass;
 
+       mono_error_init (error);
        klass = mono_class_from_mono_type (tb->type.type);
 
        mono_loader_lock ();
@@ -11511,20 +11623,20 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
 
                fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
 
-               MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
-               if (!is_ok (&error)) {
+               MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+               if (!is_ok (error)) {
                        mono_loader_unlock ();
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return FALSE;
                }
                if (!mono_type_is_valid_enum_basetype (field_type)) {
                        mono_loader_unlock ();
-                       return;
+                       return TRUE;
                }
 
-               enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
-               if (!is_ok (&error)) {
+               enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+               if (!is_ok (error)) {
                        mono_loader_unlock ();
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return FALSE;
                }
                klass->element_class = mono_class_from_mono_type (enum_basetype);
                if (!klass->element_class)
@@ -11544,15 +11656,32 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
                mono_class_setup_vtable_general (klass, NULL, 0, NULL);
        }
        mono_loader_unlock ();
+       return TRUE;
+}
+
+/**
+ * mono_reflection_create_internal_class:
+ * @tb: a TypeBuilder object
+ *
+ * (icall)
+ * Actually create the MonoClass that is associated with the TypeBuilder.
+ */
+void
+mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
+{
+       MonoError error;
+       (void) reflection_create_internal_class (tb, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 static MonoMarshalSpec*
 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
-                                                               MonoReflectionMarshal *minfo)
+                               MonoReflectionMarshal *minfo, MonoError *error)
 {
-       MonoError error;
        MonoMarshalSpec *res;
 
+       mono_error_init (error);
+
        res = image_g_new0 (image, MonoMarshalSpec, 1);
        res->native = (MonoMarshalNative)minfo->type;
 
@@ -11578,8 +11707,11 @@ mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
 
        case MONO_NATIVE_CUSTOM:
                if (minfo->marshaltyperef) {
-                       MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
+                       if (!is_ok (error)) {
+                               image_g_free (image, res);
+                               return NULL;
+                       }
                        res->data.custom_data.custom_name =
                                type_get_fully_qualified_name (marshaltyperef);
                }
@@ -11900,7 +12032,12 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                        if (specs == NULL)
                                                specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
                                        specs [pb->position] = 
-                                               mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
+                                               mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, &error);
+                                       if (!is_ok (&error)) {
+                                               mono_loader_unlock ();
+                                               image_g_free (image, specs);
+                                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                                       }
                                }
                        }
                }
@@ -11925,8 +12062,10 @@ ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, Mon
        MonoMethodSignature *sig;
 
        mono_loader_lock ();
-       sig = ctor_builder_to_signature (klass->image, mb);
+       g_assert (klass->image != NULL);
+       sig = ctor_builder_to_signature (klass->image, mb, error);
        mono_loader_unlock ();
+       return_val_if_nok (error, NULL);
 
        if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
                return NULL;
@@ -11952,8 +12091,10 @@ methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb,
        mono_error_init (error);
 
        mono_loader_lock ();
-       sig = method_builder_to_signature (klass->image, mb);
+       g_assert (klass->image != NULL);
+       sig = method_builder_to_signature (klass->image, mb, error);
        mono_loader_unlock ();
+       return_val_if_nok (error, NULL);
 
        if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
                return NULL;
@@ -11970,39 +12111,40 @@ methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb,
 }
 
 static MonoClassField*
-fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
+fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
 {
        MonoClassField *field;
        MonoType *custom;
-       MonoError error;
+
+       mono_error_init (error);
 
        field = g_new0 (MonoClassField, 1);
 
-       field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
-       g_assert (mono_error_ok (&error));
+       field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
+       mono_error_assert_ok (error);
        if (fb->attrs || fb->modreq || fb->modopt) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
-               if (!is_ok (&error)) {
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+               if (!is_ok (error)) {
                        g_free (field);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return NULL;
                }
                field->type = mono_metadata_type_dup (NULL, type);
                field->type->attrs = fb->attrs;
 
                g_assert (image_is_dynamic (klass->image));
-               custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, &error);
+               custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
                g_free (field->type);
-               if (!is_ok (&error)) {
+               if (!is_ok (error)) {
                        g_free (field);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return NULL;
                }
                field->type = mono_metadata_type_dup (klass->image, custom);
                g_free (custom);
        } else {
-               field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
-               if (!is_ok (&error)) {
+               field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+               if (!is_ok (error)) {
                        g_free (field);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return NULL;
                }
        }
        if (fb->offset != -1)
@@ -12016,15 +12158,26 @@ fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder*
 }
 #endif
 
+/**
+ * mono_reflection_bind_generic_parameters:
+ * @type: a managed type object (which should be some kind of generic (instance? definition?))
+ * @type_args: the number of type arguments to bind
+ * @types: array of type arguments
+ * @error: set on error
+ *
+ * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
+ * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
+ */
 MonoType*
-mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
+mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
 {
-       MonoError error;
        MonoClass *klass;
        MonoReflectionTypeBuilder *tb = NULL;
        gboolean is_dynamic = FALSE;
        MonoClass *geninst;
 
+       mono_error_init (error);
+       
        mono_loader_lock ();
 
        if (is_sre_type_builder (mono_object_class (type))) {
@@ -12045,12 +12198,16 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
        if (tb && tb->generic_container)
                mono_reflection_create_generic_class (tb);
 
-       MonoType *t = mono_reflection_type_get_handle (type, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       MonoType *t = mono_reflection_type_get_handle (type, error);
+       if (!is_ok (error)) {
+               mono_loader_unlock ();
+               return NULL;
+       }
 
        klass = mono_class_from_mono_type (t);
        if (!klass->generic_container) {
                mono_loader_unlock ();
+               mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
                return NULL;
        }
 
@@ -12259,29 +12416,30 @@ inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
 }
 
 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
-void
-mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
+static gboolean
+reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
 {
-       MonoError error;
        MonoGenericClass *gclass;
        MonoDynamicGenericClass *dgclass;
        MonoClass *klass, *gklass;
        MonoType *gtype;
        int i;
 
-       gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_error_init (error);
+
+       gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
+       return_val_if_nok (error, FALSE);
        klass = mono_class_from_mono_type (gtype);
        g_assert (gtype->type == MONO_TYPE_GENERICINST);
        gclass = gtype->data.generic_class;
 
        if (!gclass->is_dynamic)
-               return;
+               return TRUE;
 
        dgclass = (MonoDynamicGenericClass *) gclass;
 
        if (dgclass->initialized)
-               return;
+               return TRUE;
 
        gklass = gclass->container_class;
        mono_class_init (gklass);
@@ -12293,13 +12451,13 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
        dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
 
        for (i = 0; i < dgclass->count_fields; i++) {
-               MonoError error;
                MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
                MonoClassField *field, *inflated_field = NULL;
 
-               if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
-                       inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
-               else if (!strcmp (obj->vtable->klass->name, "MonoField"))
+               if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
+                       inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
+                       return_val_if_nok (error, FALSE);
+               } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
                        field = ((MonoReflectionField *) obj)->field;
                else {
                        field = NULL; /* prevent compiler warning */
@@ -12309,8 +12467,8 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
                dgclass->fields [i] = *field;
                dgclass->fields [i].parent = klass;
                dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
-                       field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
-               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+                       field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
+               mono_error_assert_ok (error); /* FIXME don't swallow the error */
                dgclass->field_generic_types [i] = field->type;
                MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
                dgclass->field_objects [i] = obj;
@@ -12323,6 +12481,15 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
        }
 
        dgclass->initialized = TRUE;
+       return TRUE;
+}
+
+void
+mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
+{
+       MonoError error;
+       (void) reflection_generic_class_initialize (type, fields, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 void
@@ -12342,21 +12509,34 @@ mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
        }
 }
 
-static void
-fix_partial_generic_class (MonoClass *klass)
+/**
+ * fix_partial_generic_class:
+ * @klass: a generic instantiation MonoClass
+ * @error: set on error
+ *
+ * Assumes that the generic container of @klass has its vtable
+ * initialized, and updates the parent class, insterfaces, methods and
+ * fields of @klass by inflating the types using the generic context.
+ *
+ * On success returns TRUE, on failure returns FALSE and sets @error.
+ *
+ */
+static gboolean
+fix_partial_generic_class (MonoClass *klass, MonoError *error)
 {
        MonoClass *gklass = klass->generic_class->container_class;
        MonoDynamicGenericClass *dgclass;
        int i;
 
+       mono_error_init (error);
+
        if (klass->wastypebuilder)
-               return;
+               return TRUE;
 
        dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
        if (klass->parent != gklass->parent) {
-               MonoError error;
-               MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
-               if (mono_error_ok (&error)) {
+               MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
+               if (mono_error_ok (error)) {
                        MonoClass *parent = mono_class_from_mono_type (parent_type);
                        mono_metadata_free_type (parent_type);
                        if (parent != klass->parent) {
@@ -12365,26 +12545,23 @@ fix_partial_generic_class (MonoClass *klass)
                                mono_class_setup_parent (klass, parent);
                        }
                } else {
-                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
-                       mono_error_cleanup (&error);
                        if (gklass->wastypebuilder)
                                klass->wastypebuilder = TRUE;
-                       return;
+                       return FALSE;
                }
        }
 
        if (!dgclass->initialized)
-               return;
+               return TRUE;
 
        if (klass->method.count != gklass->method.count) {
                klass->method.count = gklass->method.count;
                klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
 
                for (i = 0; i < klass->method.count; i++) {
-                       MonoError error;
                        klass->methods [i] = mono_class_inflate_generic_method_full_checked (
-                               gklass->methods [i], klass, mono_class_get_context (klass), &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                               gklass->methods [i], klass, mono_class_get_context (klass), error);
+                       mono_error_assert_ok (error);
                }
        }
 
@@ -12394,15 +12571,14 @@ fix_partial_generic_class (MonoClass *klass)
                klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
 
                for (i = 0; i < gklass->interface_count; ++i) {
-                       MonoError error;
-                       MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
+                       return_val_if_nok (error, FALSE);
 
                        klass->interfaces [i] = mono_class_from_mono_type (iface_type);
                        mono_metadata_free_type (iface_type);
 
-                       ensure_runtime_vtable (klass->interfaces [i], &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       if (!ensure_runtime_vtable (klass->interfaces [i], error))
+                               return FALSE;
                }
                klass->interfaces_inited = 1;
        }
@@ -12412,18 +12588,17 @@ fix_partial_generic_class (MonoClass *klass)
                klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
 
                for (i = 0; i < klass->field.count; i++) {
-                       MonoError error;
                        klass->fields [i] = gklass->fields [i];
                        klass->fields [i].parent = klass;
-                       klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
+                       return_val_if_nok (error, FALSE);
                }
        }
 
        /*We can only finish with this klass once it's parent has as well*/
        if (gklass->wastypebuilder)
                klass->wastypebuilder = TRUE;
-       return;
+       return TRUE;
 }
 
 /**
@@ -12444,9 +12619,7 @@ ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
        if (!ensure_runtime_vtable (gklass, error))
                return FALSE;
 
-       fix_partial_generic_class (klass);
-
-       return TRUE;
+       return fix_partial_generic_class (klass, error);
 }
 
 /**
@@ -12505,8 +12678,10 @@ ensure_runtime_vtable (MonoClass *klass, MonoError *error)
                        klass->interfaces_inited = 1;
                }
        } else if (klass->generic_class){
-               if (!ensure_generic_class_runtime_vtable (klass, error))
+               if (!ensure_generic_class_runtime_vtable (klass, error)) {
+                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        return FALSE;
+               }
        }
 
        if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
@@ -12537,9 +12712,9 @@ ensure_runtime_vtable (MonoClass *klass, MonoError *error)
 }
 
 static MonoMethod*
-mono_reflection_method_get_handle (MonoObject *method)
+mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
 {
-       MonoError error;
+       mono_error_init (error);
        MonoClass *klass = mono_object_class (method);
        if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
                MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
@@ -12554,11 +12729,10 @@ mono_reflection_method_get_handle (MonoObject *method)
                MonoMethod *result;
                /*FIXME move this to a proper method and unify with resolve_object*/
                if (m->method_args) {
-                       result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       result = mono_reflection_method_on_tb_inst_get_handle (m, error);
                } else {
-                       MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
+                       return_val_if_nok (error, NULL);
                        MonoClass *inflated_klass = mono_class_from_mono_type (type);
                        MonoMethod *mono_method;
 
@@ -12579,12 +12753,13 @@ mono_reflection_method_get_handle (MonoObject *method)
 }
 
 void
-mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
+mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
 {
        MonoReflectionTypeBuilder *tb;
        int i, j, onum;
        MonoReflectionMethod *m;
 
+       mono_error_init (error);
        *overrides = NULL;
        *num_overrides = 0;
 
@@ -12618,7 +12793,8 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides
                                for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
                                        m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
 
-                                       (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
+                                       (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
+                                       return_if_nok (error);
                                        (*overrides) [onum * 2 + 1] = mb->mhandle;
 
                                        g_assert (mb->mhandle);
@@ -12722,7 +12898,7 @@ typebuilder_setup_fields (MonoClass *klass, MonoError *error)
        }
 
        klass->instance_size = MAX (klass->instance_size, real_size);
-       mono_class_layout_fields (klass);
+       mono_class_layout_fields (klass, klass->instance_size);
 }
 
 static void
@@ -12775,15 +12951,19 @@ typebuilder_setup_properties (MonoClass *klass, MonoError *error)
        }
 }
 
-MonoReflectionEvent *
-mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
+static MonoReflectionEvent *
+reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
 {
-       MonoError error;
+       mono_error_init (error);
+
        MonoEvent *event = g_new0 (MonoEvent, 1);
        MonoClass *klass;
 
-       MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
+       if (!is_ok (error)) {
+               g_free (event);
+               return NULL;
+       }
        klass = mono_class_from_mono_type (type);
 
        event->parent = klass;
@@ -12809,11 +12989,26 @@ mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, Mon
        }
 #endif
 
-       MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
+       if (!is_ok (error)) {
+#ifndef MONO_SMALL_CONFIG
+               g_free (event->other);
+#endif
+               g_free (event);
+               return NULL;
+       }
        return ev_obj;
 }
 
+MonoReflectionEvent *
+mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
+{
+       MonoError error;
+       MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
+}
+
 static void
 typebuilder_setup_events (MonoClass *klass, MonoError *error)
 {
@@ -12863,16 +13058,34 @@ typebuilder_setup_events (MonoClass *klass, MonoError *error)
        }
 }
 
+struct remove_instantiations_user_data
+{
+       MonoClass *klass;
+       MonoError *error;
+};
+
 static gboolean
 remove_instantiations_of_and_ensure_contents (gpointer key,
                                                  gpointer value,
                                                  gpointer user_data)
 {
+       struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
        MonoType *type = (MonoType*)key;
-       MonoClass *klass = (MonoClass*)user_data;
+       MonoClass *klass = data->klass;
+       gboolean already_failed = !is_ok (data->error);
+       MonoError lerror;
+       MonoError *error = already_failed ? &lerror : data->error;
 
        if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
-               fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
+               MonoClass *inst_klass = mono_class_from_mono_type (type);
+               //Ensure it's safe to use it.
+               if (!fix_partial_generic_class (inst_klass, error)) {
+                       mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       // Marked the class with failure, but since some other instantiation already failed,
+                       // just report that one, and swallow the error from this one.
+                       if (already_failed)
+                               mono_error_cleanup (error);
+               }
                return TRUE;
        } else
                return FALSE;
@@ -12903,6 +13116,8 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        MonoReflectionType* res;
        int i, j;
 
+       mono_error_init (&error);
+
        domain = mono_object_domain (tb);
        klass = mono_class_from_mono_type (tb->type.type);
 
@@ -12910,22 +13125,28 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
         * Check for user defined Type subclasses.
         */
        RESOLVE_TYPE (tb->parent, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       if (!is_ok (&error))
+               goto failure_unlocked;
        check_array_for_usertypes (tb->interfaces, &error);
-       mono_error_raise_exception (&error); /*FIXME don't raise here */
+       if (!is_ok (&error))
+               goto failure_unlocked;
        if (tb->fields) {
                for (i = 0; i < mono_array_length (tb->fields); ++i) {
                        MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
                        if (fb) {
                                RESOLVE_TYPE (fb->type, &error);
-                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                check_array_for_usertypes (fb->modreq, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                check_array_for_usertypes (fb->modopt, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
                                        RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
-                                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                                       if (!is_ok (&error))
+                                               goto failure_unlocked;
                                }
                        }
                }
@@ -12935,22 +13156,28 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                        MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
                        if (mb) {
                                RESOLVE_TYPE (mb->rtype, &error);
-                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                check_array_for_usertypes (mb->return_modreq, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                check_array_for_usertypes (mb->return_modopt, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                check_array_for_usertypes (mb->parameters, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                if (mb->param_modreq)
                                        for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
                                                check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
-                                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                                               if (!is_ok (&error))
+                                                       goto failure_unlocked;
                                        }
                                if (mb->param_modopt)
                                        for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
                                                check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
-                                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                                               if (!is_ok (&error))
+                                                       goto failure_unlocked;
                                        }
                        }
                }
@@ -12960,16 +13187,19 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                        MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
                        if (mb) {
                                check_array_for_usertypes (mb->parameters, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                if (mb->param_modreq)
                                        for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
                                                check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
-                                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                                               if (!is_ok (&error))
+                                                       goto failure_unlocked;
                                        }
                                if (mb->param_modopt)
                                        for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
                                                check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
-                                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                                               if (!is_ok (&error))
+                                                       goto failure_unlocked;
                                        }
                        }
                }
@@ -12988,7 +13218,7 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                mono_loader_unlock ();
 
                res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_error_set_pending_exception (&error);
 
                return res;
        }
@@ -13016,7 +13246,7 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                        mono_domain_unlock (domain);
 
                        res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_error_set_pending_exception (&error);
 
                        return res;
                }
@@ -13077,19 +13307,28 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
         *
         * Together with this we must ensure the contents of all instances to match the created type.
         */
-       if (domain->type_hash && klass->generic_container)
-               mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
+       if (domain->type_hash && klass->generic_container) {
+               struct remove_instantiations_user_data data;
+               data.klass = klass;
+               data.error = &error;
+               mono_error_assert_ok (&error);
+               mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
+               if (!is_ok (&error))
+                       goto failure;
+       }
 
        mono_domain_unlock (domain);
        mono_loader_unlock ();
 
        if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
-               mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
+               mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
+               goto failure_unlocked;
        }
 
        res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       if (!is_ok (&error))
+               goto failure_unlocked;
 
        g_assert (res != (MonoReflectionType*)tb);
 
@@ -13100,30 +13339,32 @@ failure:
        klass->wastypebuilder = TRUE;
        mono_domain_unlock (domain);
        mono_loader_unlock ();
-       mono_error_raise_exception (&error);
+failure_unlocked:
+       mono_error_set_pending_exception (&error);
        return NULL;
 }
 
-void
-mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
+static gboolean
+reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
 {
        MonoGenericParamFull *param;
        MonoImage *image;
        MonoClass *pklass;
-       MonoError error;
+
+       mono_error_init (error);
 
        image = &gparam->tbuilder->module->dynamic_image->image;
 
        param = mono_image_new0 (image, MonoGenericParamFull, 1);
 
-       param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
-       g_assert (mono_error_ok (&error));
+       param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
+       mono_error_assert_ok (error);
        param->param.num = gparam->index;
 
        if (gparam->mbuilder) {
                if (!gparam->mbuilder->generic_container) {
-                       MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
+                       return_val_if_nok (error, FALSE);
 
                        MonoClass *klass = mono_class_from_mono_type (tb);
                        gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
@@ -13138,8 +13379,8 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
                param->param.owner = gparam->mbuilder->generic_container;
        } else if (gparam->tbuilder) {
                if (!gparam->tbuilder->generic_container) {
-                       MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
+                       return_val_if_nok (error, FALSE);
                        MonoClass *klass = mono_class_from_mono_type (tb);
                        gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
                        gparam->tbuilder->generic_container->owner.klass = klass;
@@ -13153,8 +13394,19 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
 
        mono_class_set_ref_info (pklass, gparam);
        mono_image_append_class_to_reflection_info_set (pklass);
+
+       return TRUE;
+}
+
+void
+mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
+{
+       MonoError error;
+       (void) reflection_initialize_generic_parameter (gparam, &error);
+       mono_error_set_pending_exception (&error);
 }
 
+
 MonoArray *
 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
 {
@@ -13256,10 +13508,9 @@ free_dynamic_method (void *dynamic_method)
        g_free (data);
 }
 
-void 
-mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
+static gboolean
+reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
 {
-       MonoError error;
        MonoReferenceQueue *queue;
        MonoMethod *handle;
        DynamicMethodReleaseData *release_data;
@@ -13270,8 +13521,12 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
        GSList *l;
        int i;
 
-       if (mono_runtime_is_shutting_down ())
-               mono_raise_exception (mono_get_exception_invalid_operation (""));
+       mono_error_init (error);
+
+       if (mono_runtime_is_shutting_down ()) {
+               mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
+               return FALSE;
+       }
 
        if (!(queue = dynamic_method_queue)) {
                mono_loader_lock ();
@@ -13280,7 +13535,8 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
                mono_loader_unlock ();
        }
 
-       sig = dynamic_method_to_signature (mb);
+       sig = dynamic_method_to_signature (mb, error);
+       return_val_if_nok (error, FALSE);
 
        reflection_methodbuilder_from_dynamic_method (&rmb, mb);
 
@@ -13318,7 +13574,11 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
                        handle_class = mono_defaults.methodhandle_class;
                } else {
                        MonoException *ex = NULL;
-                       ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
+                       ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
+                       if (!is_ok  (error)) {
+                               g_free (rmb.refs);
+                               return FALSE;
+                       }
                        if (!ref)
                                ex = mono_get_exception_type_load (NULL, NULL);
                        else if (mono_security_core_clr_enabled ())
@@ -13326,8 +13586,8 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 
                        if (ex) {
                                g_free (rmb.refs);
-                               mono_raise_exception (ex);
-                               return;
+                               mono_error_set_exception_instance (error, ex);
+                               return FALSE;
                        }
                }
 
@@ -13336,10 +13596,10 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
        }               
 
        if (mb->owner) {
-               MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
-               if (!is_ok (&error)) {
+               MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
+               if (!is_ok (error)) {
                        g_free (rmb.refs);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return FALSE;
                }
                klass = mono_class_from_mono_type (owner_type);
        } else {
@@ -13380,6 +13640,16 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
                domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
        g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
        mono_domain_unlock (domain);
+
+       return TRUE;
+}
+
+void
+mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
+{
+       MonoError error;
+       (void) reflection_create_dynamic_method (mb, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 #endif /* DISABLE_REFLECTION_EMIT */
@@ -13425,23 +13695,28 @@ mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32
  * LOCKING: Take the loader lock
  */
 gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
 {
        MonoDynamicImage *assembly = (MonoDynamicImage*)image;
        MonoObject *obj;
        MonoClass *klass;
 
+       mono_error_init (error);
+       
        obj = lookup_dyn_token (assembly, token);
        if (!obj) {
                if (valid_token)
                        g_error ("Could not find required dynamic token 0x%08x", token);
-               else
+               else {
+                       mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
                        return NULL;
+               }
        }
 
        if (!handle_class)
                handle_class = &klass;
-       return resolve_object (image, obj, handle_class, context);
+       gpointer result = resolve_object (image, obj, handle_class, context, error);
+       return result;
 }
 
 /*
@@ -13451,15 +13726,15 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean
  * dynamic types.
  */
 static void
-ensure_complete_type (MonoClass *klass)
+ensure_complete_type (MonoClass *klass, MonoError *error)
 {
-       MonoError error;
+       mono_error_init (error);
 
        if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
 
-               mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+               return_if_nok (error);
 
                // Asserting here could break a lot of code
                //g_assert (klass->wastypebuilder);
@@ -13470,32 +13745,36 @@ ensure_complete_type (MonoClass *klass)
                int i;
 
                for (i = 0; i < inst->type_argc; ++i) {
-                       ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
+                       ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
+                       return_if_nok (error);
                }
        }
 }
 
 static gpointer
-resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
+resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
 {
-       MonoError error;
        gpointer result = NULL;
 
+       mono_error_init (error);
+
        if (strcmp (obj->vtable->klass->name, "String") == 0) {
-               result = mono_string_intern_checked ((MonoString*)obj, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               result = mono_string_intern_checked ((MonoString*)obj, error);
+               return_val_if_nok (error, NULL);
                *handle_class = mono_defaults.string_class;
                g_assert (result);
        } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+               return_val_if_nok (error, NULL);
                MonoClass *mc = mono_class_from_mono_type (type);
-               if (!mono_class_init (mc))
-                       mono_raise_exception (mono_class_get_exception_for_failure (mc));
+               if (!mono_class_init (mc)) {
+                       mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
+                       return NULL;
+               }
 
                if (context) {
-                       MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
+                       return_val_if_nok (error, NULL);
 
                        result = mono_class_from_mono_type (inflated);
                        mono_metadata_free_type (inflated);
@@ -13510,9 +13789,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                   strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
                result = ((MonoReflectionMethod*)obj)->method;
                if (context) {
-                       MonoError error;
-                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+                       mono_error_assert_ok (error);
                }
                *handle_class = mono_defaults.methodhandle_class;
                g_assert (result);
@@ -13523,8 +13801,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                        /* Type is not yet created */
                        MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
 
-                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+                       return_val_if_nok (error, NULL);
 
                        /*
                         * Hopefully this has been filled in by calling CreateType() on the
@@ -13537,9 +13815,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                        result = mb->mhandle;
                }
                if (context) {
-                       MonoError error;
-                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+                       mono_error_assert_ok (error);
                }
                *handle_class = mono_defaults.methodhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
@@ -13549,23 +13826,24 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                if (!result) {
                        MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
 
-                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+                       return_val_if_nok (error, NULL);
                        result = cb->mhandle;
                }
                if (context) {
-                       MonoError error;
-                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+                       mono_error_assert_ok (error);
                }
                *handle_class = mono_defaults.methodhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
                MonoClassField *field = ((MonoReflectionField*)obj)->field;
 
-               ensure_complete_type (field->parent);
+               ensure_complete_type (field->parent, error);
+               return_val_if_nok (error, NULL);
+
                if (context) {
-                       MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
+                       return_val_if_nok (error, NULL);
 
                        MonoClass *klass = mono_class_from_mono_type (inflated);
                        MonoClassField *inflated_field;
@@ -13589,15 +13867,15 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                if (!result) {
                        MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
 
-                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+                       return_val_if_nok (error, NULL);
                        result = fb->handle;
                }
 
                if (fb->handle && fb->handle->parent->generic_container) {
                        MonoClass *klass = fb->handle->parent;
-                       MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
+                       return_val_if_nok (error, NULL);
 
                        MonoClass *inflated = mono_class_from_mono_type (type);
 
@@ -13608,8 +13886,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                *handle_class = mono_defaults.fieldhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
+               return_val_if_nok (error, NULL);
                MonoClass *klass;
 
                klass = type->data.klass;
@@ -13618,8 +13896,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                        result = klass;
                }
                else {
-                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+                       return_val_if_nok (error, NULL);
                        result = type->data.klass;
                        g_assert (result);
                }
@@ -13651,8 +13929,11 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                /* TODO: Copy type ? */
                sig->ret = helper->return_type->type;
                for (i = 0; i < nargs; ++i) {
-                       sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
+                       if (!is_ok (error)) {
+                               image_g_free (image, sig);
+                               return NULL;
+                       }
                }
 
                result = sig;
@@ -13664,20 +13945,20 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                result = method->mhandle;
                *handle_class = mono_defaults.methodhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
-               type = mono_class_inflate_generic_type_checked (type, context, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+               return_val_if_nok (error, NULL);
+               type = mono_class_inflate_generic_type_checked (type, context, error);
+               return_val_if_nok (error, NULL);
 
                result = mono_class_from_mono_type (type);
                *handle_class = mono_defaults.typehandle_class;
                g_assert (result);
                mono_metadata_free_type (type);
        } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
-               type = mono_class_inflate_generic_type_checked (type, context, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+               return_val_if_nok (error, NULL);
+               type = mono_class_inflate_generic_type_checked (type, context, error);
+               return_val_if_nok (error, NULL);
 
                result = mono_class_from_mono_type (type);
                *handle_class = mono_defaults.typehandle_class;
@@ -13696,24 +13977,29 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                else
                        g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
 
-               MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
-               type = mono_class_inflate_generic_type_checked (finst, context, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
+               return_val_if_nok (error, NULL);
+               type = mono_class_inflate_generic_type_checked (finst, context, error);
+               return_val_if_nok (error, NULL);
 
                inflated = mono_class_from_mono_type (type);
 
                result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
-               ensure_complete_type (field->parent);
+               ensure_complete_type (field->parent, error);
+               if (!is_ok (error)) {
+                       mono_metadata_free_type (type);
+                       return NULL;
+               }
+
                g_assert (result);
                mono_metadata_free_type (type);
                *handle_class = mono_defaults.fieldhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
                MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
-               MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
-               MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
+               return_val_if_nok (error, NULL);
+               MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
+               return_val_if_nok (error, NULL);
 
                MonoClass *inflated_klass = mono_class_from_mono_type (type);
                MonoMethod *method;
@@ -13731,17 +14017,17 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
        } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
                MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
                if (m->method_args) {
-                       result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       result = mono_reflection_method_on_tb_inst_get_handle (m, error);
+                       return_val_if_nok (error, NULL);
                        if (context) {
-                               result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
-                               mono_error_assert_ok (&error);
+                               result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+                               mono_error_assert_ok (error);
                        }
                } else {
-                       MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
-                       MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
+                       return_val_if_nok (error, NULL);
+                       MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
+                       return_val_if_nok (error, NULL);
 
                        MonoClass *inflated_klass = mono_class_from_mono_type (type);
                        MonoMethod *method;
@@ -13765,8 +14051,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                gpointer iter;
                char *name;
 
-               mtype = mono_reflection_type_get_handle (m->parent, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mtype = mono_reflection_type_get_handle (m->parent, error);
+               return_val_if_nok (error, NULL);
                klass = mono_class_from_mono_type (mtype);
 
                /* Find the method */
@@ -13789,12 +14075,12 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                                is_sre_byref (mono_object_get_class(obj)) ||
                                is_sre_pointer (mono_object_get_class(obj))) {
                MonoReflectionType *ref_type = (MonoReflectionType *)obj;
-               MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle (ref_type, error);
+               return_val_if_nok (error, NULL);
 
                if (context) {
-                       MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
+                       return_val_if_nok (error, NULL);
 
                        result = mono_class_from_mono_type (inflated);
                        mono_metadata_free_type (inflated);
@@ -13901,8 +14187,9 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
 }
 
 void
-mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
+mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
 {
+       mono_error_init (error);
        *overrides = NULL;
        *num_overrides = 0;
 }
@@ -14395,13 +14682,14 @@ mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDe
 }
 
 gboolean
-mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
+mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
 {
-       MonoError error;
        MonoObject *res, *exc;
        void *params [1];
        static MonoMethod *method = NULL;
 
+       mono_error_init (error);
+
        if (method == NULL) {
                method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
                g_assert (method);
@@ -14414,13 +14702,13 @@ mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
        g_assert (mono_class_get_ref_info (klass));
        g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
 
-       params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
+       return_val_if_nok (error, FALSE);
 
-       res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
+       res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
 
-       if (exc || !mono_error_ok (&error)) {
-               mono_error_cleanup (&error);
+       if (exc || !mono_error_ok (error)) {
+               mono_error_cleanup (error);
                return FALSE;
        } else
                return *(MonoBoolean*)mono_object_unbox (res);
index 164cc4ae87cfe996d18bbeabdea99255c6ca867c..af85ac1b3c3eb1c8423c252eed10cf9fa82f77d9 100644 (file)
@@ -77,6 +77,7 @@ MONO_API MonoArray*  mono_reflection_get_custom_attrs_by_type (MonoObject *obj,
 MONO_API MonoArray*  mono_reflection_get_custom_attrs (MonoObject *obj);
 MONO_RT_EXTERNAL_ONLY
 MONO_API MonoArray*  mono_reflection_get_custom_attrs_data (MonoObject *obj);
+MONO_RT_EXTERNAL_ONLY
 MONO_API MonoArray*  mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *porpValues, MonoArray *fields, MonoArray* fieldValues);
 
 MONO_RT_EXTERNAL_ONLY
index 9b621c92fc577f1ec9e486e9f7fe2e8db2cfd4d3..9c329f4934247bb8218f87c7f518d48cca3e006a 100644 (file)
@@ -373,9 +373,10 @@ mono_remoting_wrapper (MonoMethod *method, gpointer *params)
                                        mparams[i] = *((gpointer *)params [i]);
                                } else {
                                        /* runtime_invoke expects a boxed instance */
-                                       if (mono_class_is_nullable (mono_class_from_mono_type (sig->params [i])))
-                                               mparams[i] = mono_nullable_box ((guint8 *)params [i], klass);
-                                       else
+                                       if (mono_class_is_nullable (mono_class_from_mono_type (sig->params [i]))) {
+                                               mparams[i] = mono_nullable_box ((guint8 *)params [i], klass, &error);
+                                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                                       } else
                                                mparams[i] = params [i];
                                }
                        } else {
@@ -2009,7 +2010,10 @@ mono_marshal_xdomain_copy_value (MonoObject *val)
        case MONO_TYPE_U8:
        case MONO_TYPE_R4:
        case MONO_TYPE_R8: {
-               return mono_value_box (domain, mono_object_class (val), ((char*)val) + sizeof(MonoObject));
+               MonoObject *res = mono_value_box_checked (domain, mono_object_class (val), ((char*)val) + sizeof(MonoObject), &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               return res;
+
        }
        case MONO_TYPE_STRING: {
                MonoString *str = (MonoString *) val;
index 5e4fa165ab0efc72fd2d09482953ab52b8ee1289..93d5b0858a9f90267acaaea99ad30ca163f3e68a 100644 (file)
@@ -77,7 +77,7 @@ mono_gc_register_bridge_callbacks (MonoGCBridgeCallbacks *callbacks)
        bridge_callbacks = *callbacks;
 
        if (!bridge_processor.reset_data)
-               sgen_old_bridge_init (&bridge_processor);
+               sgen_new_bridge_init (&bridge_processor);
 }
 
 static gboolean
index fd36c3941eeee0e0f2bc1ba44f3b1acc3b8d97b2..d0eaa26e14e014df49aa86ef63fa043d644d896e 100644 (file)
@@ -731,7 +731,7 @@ extern MonoNativeTlsKey thread_info_key;
 
 #define SGEN_TV_DECLARE(name) gint64 name
 #define SGEN_TV_GETTIME(tv) tv = mono_100ns_ticks ()
-#define SGEN_TV_ELAPSED(start,end) ((long)(end-start))
+#define SGEN_TV_ELAPSED(start,end) ((gint64)(end-start))
 
 typedef MonoSemType SgenSemaphore;
 
index 8421b903ba6f967366bba0f2d7c7b337510ac1ee..efa0e892eccf3bd312a72915c482e115c8fad163 100644 (file)
@@ -37,6 +37,7 @@
 #include "metadata/handle.h"
 #include "utils/mono-memory-model.h"
 #include "utils/mono-logger-internals.h"
+#include "sgen/sgen-thread-pool.h"
 
 #ifdef HEAVY_STATISTICS
 static guint64 stat_wbarrier_set_arrayref = 0;
@@ -1591,7 +1592,7 @@ find_next_card (guint8 *card_data, guint8 *end)
 #define ARRAY_OBJ_INDEX(ptr,array,elem_size) (((char*)(ptr) - ((char*)(array) + G_STRUCT_OFFSET (MonoArray, vector))) / (elem_size))
 
 gboolean
-sgen_client_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, gboolean mod_union, ScanCopyContext ctx)
+sgen_client_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, ScanCopyContext ctx)
 {
        MonoVTable *vt = SGEN_LOAD_VTABLE (obj);
        MonoClass *klass = vt->klass;
@@ -1671,20 +1672,11 @@ LOOP_HEAD:
                                for (; elem < card_end; elem += elem_size)
                                        scan_vtype_func (obj, elem, desc, ctx.queue BINARY_PROTOCOL_ARG (elem_size));
                        } else {
-                               CopyOrMarkObjectFunc copy_func = ctx.ops->copy_or_mark_object;
+                               ScanPtrFieldFunc scan_ptr_field_func = ctx.ops->scan_ptr_field;
 
                                HEAVY_STAT (++los_array_cards);
-                               for (; elem < card_end; elem += SIZEOF_VOID_P) {
-                                       GCObject *new_;
-                                       gpointer old = *(gpointer*)elem;
-                                       if ((mod_union && old) || G_UNLIKELY (sgen_ptr_in_nursery (old))) {
-                                               HEAVY_STAT (++los_array_remsets);
-                                               copy_func ((GCObject**)elem, ctx.queue);
-                                               new_ = *(GCObject **)elem;
-                                               if (G_UNLIKELY (sgen_ptr_in_nursery (new_)))
-                                                       sgen_add_to_global_remset (elem, new_);
-                                       }
-                               }
+                               for (; elem < card_end; elem += SIZEOF_VOID_P)
+                                       scan_ptr_field_func (obj, (GCObject**)elem, ctx.queue);
                        }
 
                        binary_protocol_card_scan (first_elem, elem - first_elem);
@@ -2987,6 +2979,7 @@ mono_gc_base_init (void)
 void
 mono_gc_base_cleanup (void)
 {
+       sgen_thread_pool_shutdown ();
 }
 
 gboolean
index 20fdb460adde86c416d941f2625f335516b3e1bb..a4f05e63ac954da9942505ad65d012ef0ec6d861 100644 (file)
@@ -968,7 +968,7 @@ compare_hash_entries (const HashEntry *e1, const HashEntry *e2)
 
 DEF_QSORT_INLINE(hash_entries, HashEntry*, compare_hash_entries)
 
-static unsigned long step_1, step_2, step_3, step_4, step_5, step_6;
+static gint64 step_1, step_2, step_3, step_4, step_5, step_6;
 static int fist_pass_links, second_pass_links, sccs_links;
 static int max_sccs_links = 0;
 
index 83f991d5b867ce64bd230021fe7a96381fc09158..f8437fe4810ccb775aa0858ddc85bce4e30207ce 100644 (file)
@@ -616,7 +616,7 @@ compare_hash_entries (const HashEntry *e1, const HashEntry *e2)
 
 DEF_QSORT_INLINE(hash_entries, HashEntry*, compare_hash_entries)
 
-static unsigned long step_1, step_2, step_3, step_4, step_5, step_6;
+static gint64 step_1, step_2, step_3, step_4, step_5, step_6;
 static int fist_pass_links, second_pass_links, sccs_links;
 static int max_sccs_links = 0;
 
index 56212ac57cf8df16137f7c781167cc76919b0561..7f8c7beaa2c59019244a98d143006fac2582c76e 100644 (file)
@@ -1925,7 +1925,10 @@ ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArray **sockets, gint32
 static MonoObject*
 int_to_object (MonoDomain *domain, int val)
 {
-       return mono_value_box (domain, mono_get_int32_class (), &val);
+       MonoError error;
+       MonoObject *result = mono_value_box_checked (domain, mono_get_int32_class (), &val, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       return result;
 }
 
 void
index 11029082f8bda156b5a52d577f07c4a43e7fbbed..30e34e50a3c5bcdd5dc096fd8154953cafd9c690 100644 (file)
@@ -245,6 +245,8 @@ filter_jobs_for_domain (gpointer key, gpointer value, gpointer user_data)
 static void
 wait_callback (gint fd, gint events, gpointer user_data)
 {
+       MonoError error;
+
        if (mono_runtime_is_shutting_down ())
                return;
 
@@ -269,13 +271,18 @@ wait_callback (gint fd, gint events, gpointer user_data)
 
                if (list && (events & EVENT_IN) != 0) {
                        MonoIOSelectorJob *job = get_job_for_event (&list, EVENT_IN);
-                       if (job)
-                               mono_threadpool_ms_enqueue_work_item (((MonoObject*) job)->vtable->domain, (MonoObject*) job);
+                       if (job) {
+                               mono_threadpool_ms_enqueue_work_item (((MonoObject*) job)->vtable->domain, (MonoObject*) job, &error);
+                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       }
+
                }
                if (list && (events & EVENT_OUT) != 0) {
                        MonoIOSelectorJob *job = get_job_for_event (&list, EVENT_OUT);
-                       if (job)
-                               mono_threadpool_ms_enqueue_work_item (((MonoObject*) job)->vtable->domain, (MonoObject*) job);
+                       if (job) {
+                               mono_threadpool_ms_enqueue_work_item (((MonoObject*) job)->vtable->domain, (MonoObject*) job, &error);
+                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       }
                }
 
                remove_fd = (events & EVENT_ERR) == EVENT_ERR;
@@ -301,6 +308,7 @@ wait_callback (gint fd, gint events, gpointer user_data)
 static void
 selector_thread (gpointer data)
 {
+       MonoError error;
        MonoGHashTable *states;
 
        io_selector_running = TRUE;
@@ -368,8 +376,10 @@ selector_thread (gpointer data)
                                                        memset (update, 0, sizeof (ThreadPoolIOUpdate));
                                        }
 
-                                       for (; list; list = mono_mlist_remove_item (list, list))
-                                               mono_threadpool_ms_enqueue_work_item (mono_object_domain (mono_mlist_get_data (list)), mono_mlist_get_data (list));
+                                       for (; list; list = mono_mlist_remove_item (list, list)) {
+                                               mono_threadpool_ms_enqueue_work_item (mono_object_domain (mono_mlist_get_data (list)), mono_mlist_get_data (list), &error);
+                                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                                       }
 
                                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: del fd %3d", fd);
                                        threadpool_io->backend.remove_fd (fd);
index 1c5ac4f42f1bea25cace38a9fcb0098e6dab50bf..32d93e6e522490a4564332d022e0ddb013ca251f 100644 (file)
@@ -344,16 +344,16 @@ cleanup (void)
        mono_coop_mutex_unlock (&threadpool->active_threads_lock);
 }
 
-void
-mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item)
+gboolean
+mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item, MonoError *error)
 {
        static MonoClass *threadpool_class = NULL;
        static MonoMethod *unsafe_queue_custom_work_item_method = NULL;
-       MonoError error;
        MonoDomain *current_domain;
        MonoBoolean f;
        gpointer args [2];
 
+       mono_error_init (error);
        g_assert (work_item);
 
        if (!threadpool_class)
@@ -370,17 +370,21 @@ mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item)
 
        current_domain = mono_domain_get ();
        if (current_domain == domain) {
-               mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, error);
+               return_val_if_nok (error, FALSE);
        } else {
                mono_thread_push_appdomain_ref (domain);
                if (mono_domain_set (domain, FALSE)) {
-                       mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, error);
+                       if (!is_ok (error)) {
+                               mono_thread_pop_appdomain_ref ();
+                               return FALSE;
+                       }
                        mono_domain_set (current_domain, TRUE);
                }
                mono_thread_pop_appdomain_ref ();
        }
+       return TRUE;
 }
 
 /* LOCKING: threadpool->domains_lock must be held */
@@ -1314,10 +1318,9 @@ mono_threadpool_ms_cleanup (void)
 }
 
 MonoAsyncResult *
-mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMethod *method, gpointer *params)
+mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMethod *method, gpointer *params, MonoError *error)
 {
        static MonoClass *async_call_klass = NULL;
-       MonoError error;
        MonoMethodMessage *message;
        MonoAsyncResult *async_result;
        MonoAsyncCall *async_call;
@@ -1329,10 +1332,12 @@ mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMet
 
        mono_lazy_initialize (&status, initialize);
 
+       mono_error_init (error);
+
        message = mono_method_call_message_new (method, params, mono_get_delegate_invoke (method->klass), (params != NULL) ? (&async_callback) : NULL, (params != NULL) ? (&state) : NULL);
 
-       async_call = (MonoAsyncCall*) mono_object_new_checked (domain, async_call_klass, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       async_call = (MonoAsyncCall*) mono_object_new_checked (domain, async_call_klass, error);
+       return_val_if_nok (error, NULL);
 
        MONO_OBJECT_SETREF (async_call, msg, message);
        MONO_OBJECT_SETREF (async_call, state, state);
@@ -1345,7 +1350,8 @@ mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMet
        async_result = mono_async_result_new (domain, NULL, async_call->state, NULL, (MonoObject*) async_call);
        MONO_OBJECT_SETREF (async_result, async_delegate, target);
 
-       mono_threadpool_ms_enqueue_work_item (domain, (MonoObject*) async_result);
+       mono_threadpool_ms_enqueue_work_item (domain, (MonoObject*) async_result, error);
+       return_val_if_nok (error, NULL);
 
        return async_result;
 }
@@ -1583,7 +1589,9 @@ void
 ves_icall_System_Threading_ThreadPool_ReportThreadStatus (MonoBoolean is_working)
 {
        // TODO
-       mono_raise_exception (mono_get_exception_not_implemented (NULL));
+       MonoError error;
+       mono_error_set_not_implemented (&error, "");
+       mono_error_set_pending_exception (&error);
 }
 
 MonoBoolean
@@ -1596,7 +1604,9 @@ MonoBoolean G_GNUC_UNUSED
 ves_icall_System_Threading_ThreadPool_PostQueuedCompletionStatus (MonoNativeOverlapped *native_overlapped)
 {
        /* This copy the behavior of the current Mono implementation */
-       mono_raise_exception (mono_get_exception_not_implemented (NULL));
+       MonoError error;
+       mono_error_set_not_implemented (&error, "");
+       mono_error_set_pending_exception (&error);
        return FALSE;
 }
 
index 8aee68c4c035c10b0cfb88870a771de5ccc79d4e..9812ee57ba2a989617ac1b96f54997a3cc3c0b58 100644 (file)
@@ -15,7 +15,7 @@ void
 mono_threadpool_ms_cleanup (void);
 
 MonoAsyncResult *
-mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMethod *method, gpointer *params);
+mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMethod *method, gpointer *params, MonoError *error);
 MonoObject *
 mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, MonoObject **exc);
 
@@ -59,7 +59,7 @@ ves_icall_System_Threading_ThreadPool_IsThreadPoolHosted (void);
 
 /* Internals */
 
-void
-mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item);
+gboolean
+mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item, MonoError *error);
 
 #endif // _MONO_THREADPOOL_MICROSOFT_H_
index e52f90aca0c155d453e40a77a1fdb3db805708ed..383ced4f1bf4a5540004bfc16ceb5fa8efa207e6 100644 (file)
@@ -5016,7 +5016,7 @@ mono_method_verify (MonoMethod *method, int level)
        if (!ctx.valid)
                goto cleanup;
 
-       original_bb = bb = mono_basic_block_split (method, &error);
+       original_bb = bb = mono_basic_block_split (method, &error, ctx.header);
        if (!mono_error_ok (&error)) {
                ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid branch target: %s", mono_error_get_message (&error)));
                mono_error_cleanup (&error);
index 6d5feb04e017d390c3a279bf372d1fff13cd8e0c..f75db695f358153a26e0a0ec5c21958fec9390f4 100755 (executable)
@@ -1,6 +1,13 @@
 count=100000
 mtest=for_loop
 monodir=$(top_builddir)
+mono=$(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),mono)
+
+if HOST_WIN32
+PLATFORM_PATH_SEPARATOR=;
+else
+PLATFORM_PATH_SEPARATOR=:
+endif
 
 # This is needed for automake dependency generation
 libgc_libs=$(monodir)/libgc/libmonogc.la
@@ -39,7 +46,7 @@ CLASS=$(mcs_topdir)/class/lib/$(DEFAULT_PROFILE)
 RUNTIME_EXECUTABLE = $(if $(BOEHM),$(top_builddir)/mono/mini/mono-boehm,$(top_builddir)/runtime/mono-wrapper)
 
 MINI_RUNTIME = MONO_PATH=$(CLASS) $(RUNTIME_EXECUTABLE)
-RUNTIME_AOTCHECK = MONO_PATH=$(CLASS):. $(RUNTIME_EXECUTABLE)
+RUNTIME_AOTCHECK = MONO_PATH="$(CLASS)$(PLATFORM_PATH_SEPARATOR)." $(RUNTIME_EXECUTABLE)
 
 MCS = $(MINI_RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -unsafe -nowarn:0162
 ILASM = $(MINI_RUNTIME) $(CLASS)/ilasm.exe
@@ -715,13 +722,13 @@ FULLAOT_LIBS = \
        Mono.Simd.dll
 
 # This currently only works on amd64/arm
-fullaotcheck: mono $(fullaot_regtests)
+fullaotcheck: $(mono) $(fullaot_regtests)
        rm -rf fullaot-tmp
        mkdir fullaot-tmp
-       $(MAKE) fullaot-libs AOT_FLAGS=full GSHAREDVT=$(GSHAREDVT)
+       $(MAKE) fullaot-libs AOT_FLAGS="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" GSHAREDVT=$(GSHAREDVT)
        cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
-       MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot=full fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
-       ln -s $$PWD/mono fullaot-tmp/
+       MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
+       ln -s $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),$$PWD/mono) fullaot-tmp/
        for i in $(fullaot_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --full-aot fullaot-tmp/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done
 
 # This can run in parallel
@@ -730,7 +737,7 @@ fullaot-libs: $(patsubst %,fullaot-tmp/%.dylib,$(FULLAOT_LIBS))
 fullaot-tmp/%.dylib: $(CLASS)/%
        cp $(CLASS)/$* fullaot-tmp/
        mkdir fullaot-tmp/$*-tmp
-       MONO_PATH=fullaot-tmp/:$(CLASS) $(top_builddir)/runtime/mono-wrapper $(if $(GSHAREDVT),-O=gsharedvt) --aot=$(AOT_FLAGS),temp-path=fullaot-tmp/$*-tmp fullaot-tmp/$*
+       MONO_PATH="fullaot-tmp/$(PLATFORM_PATH_SEPARATOR)$(CLASS)" $(top_builddir)/runtime/mono-wrapper $(if $(GSHAREDVT),-O=gsharedvt) --aot=$(AOT_FLAGS),temp-path=fullaot-tmp/$*-tmp fullaot-tmp/$*
        rm -rf fullaot-tmp/$*-tmp
 
 llvmfullaotcheck:
@@ -741,7 +748,7 @@ llvmonly_regtests = $(fullaot_regtests) gshared.exe
 llvmonlycheck: mono $(llvmonly_regtests)
        rm -rf fullaot-tmp
        mkdir fullaot-tmp
-       $(MAKE) fullaot-libs AOT_FLAGS=llvmonly
+       $(MAKE) fullaot-libs AOT_FLAGS="llvmonly,$(MONO_FULLAOT_ADDITIONAL_ARGS)"
        cp $(llvmonly_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
        MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper  --aot=llvmonly fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
        ln -s $$PWD/mono fullaot-tmp/
index 70e293d123d782331054c6abf1aa31b5916be2c3..b74b1107fbfb328cc1cd69361a9c3d68449052cd 100644 (file)
@@ -4966,7 +4966,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
        GPtrArray *patches;
        MonoJumpInfo *patch_info;
        MonoDebugSourceLocation **locs = NULL;
-       gboolean skip;
+       gboolean skip, prologue_end = FALSE;
 #ifdef MONO_ARCH_AOT_SUPPORTED
        gboolean direct_call, external_call;
        guint32 got_slot;
@@ -5001,10 +5001,16 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                if (locs && locs [i]) {
                        MonoDebugSourceLocation *loc = locs [i];
                        int findex;
+                       const char *options;
 
                        findex = get_file_index (acfg, loc->source_file);
                        emit_unset_mode (acfg);
-                       fprintf (acfg->fp, ".loc %d %d 0\n", findex, loc->row);
+                       if (!prologue_end)
+                               options = " prologue_end";
+                       else
+                               options = "";
+                       prologue_end = TRUE;
+                       fprintf (acfg->fp, ".loc %d %d 0%s\n", findex, loc->row, options);
                        mono_debug_symfile_free_location (loc);
                }
 
@@ -6670,6 +6676,15 @@ wrap_path (gchar * path)
        return clean;
 }
 
+// Duplicate a char range and add it to a ptrarray, but only if it is nonempty
+static void
+ptr_array_add_range_if_nonempty(GPtrArray *args, gchar const *start, gchar const *end)
+{
+       ptrdiff_t len = end-start;
+       if (len > 0)
+               g_ptr_array_add (args, g_strndup (start, len));
+}
+
 static GPtrArray *
 mono_aot_split_options (const char *aot_options)
 {
@@ -6725,6 +6740,7 @@ mono_aot_split_options (const char *aot_options)
 
        next:
                aot_options++;
+       restart:
                // If the next character is end of string, then process the last option.
                if (*(aot_options) == '\0') {
                        end_of_string = TRUE;
@@ -6733,11 +6749,11 @@ mono_aot_split_options (const char *aot_options)
                continue;
 
        new_opt:
-               g_ptr_array_add (args, g_strndup (opt_start, aot_options - opt_start));
+               ptr_array_add_range_if_nonempty (args, opt_start, aot_options);
                opt_start = ++aot_options;
                if (end_of_string)
                        break;
-               goto next;
+               goto restart; // Check for null and continue loop
        }
 
        return args;
@@ -9544,7 +9560,6 @@ compile_asm (MonoAotCompile *acfg)
 #define AS_OPTIONS "--64"
 #elif defined(TARGET_POWERPC64)
 #define AS_OPTIONS "-a64 -mppc64"
-#define LD_OPTIONS "-m elf64ppc"
 #elif defined(sparc) && SIZEOF_VOID_P == 8
 #define AS_OPTIONS "-xarch=v9"
 #elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
@@ -9565,22 +9580,30 @@ compile_asm (MonoAotCompile *acfg)
 #define AS_NAME "as"
 #endif
 
-#ifndef LD_OPTIONS
-#define LD_OPTIONS ""
-#endif
-
 #if defined(sparc)
-#define LD_NAME "ld -shared -G"
+#define LD_NAME "ld"
+#define LD_OPTIONS "-shared -G"
 #elif defined(__ppc__) && defined(TARGET_MACH)
-#define LD_NAME "gcc -dynamiclib"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "-dynamiclib"
 #elif defined(TARGET_AMD64) && defined(TARGET_MACH)
-#define LD_NAME "clang --shared"
+#define LD_NAME "clang"
+#define LD_OPTIONS "--shared"
 #elif defined(TARGET_WIN32) && !defined(TARGET_ANDROID)
-#define LD_NAME "gcc -shared --dll"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "-shared"
 #elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
-#define LD_NAME "clang -m32 -dynamiclib"
+#define LD_NAME "clang"
+#define LD_OPTIONS "-m32 -dynamiclib"
 #elif defined(TARGET_ARM) && !defined(TARGET_ANDROID)
-#define LD_NAME "gcc --shared"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "--shared"
+#elif defined(TARGET_POWERPC64)
+#define LD_OPTIONS "-m elf64ppc"
+#endif
+
+#ifndef LD_OPTIONS
+#define LD_OPTIONS ""
 #endif
 
        if (acfg->aot_opts.asm_only) {
@@ -9656,10 +9679,11 @@ compile_asm (MonoAotCompile *acfg)
                ld_flags = g_strdup_printf ("%s %s", ld_flags, "-lstdc++");
 
 #ifdef LD_NAME
-       command = g_strdup_printf ("%s -o %s %s %s %s", LD_NAME,
+       command = g_strdup_printf ("%s%s %s -o %s %s %s %s", tool_prefix, LD_NAME, LD_OPTIONS,
                wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
                wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
 #else
+       // Default (linux)
        command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
                wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
                wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
@@ -10329,13 +10353,11 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                }
        }
 
-       if (acfg->aot_opts.dwarf_debug && acfg->aot_opts.asm_only && acfg->aot_opts.gnu_asm) {
+       if (acfg->aot_opts.dwarf_debug && acfg->aot_opts.gnu_asm) {
                /*
                 * CLANG supports GAS .file/.loc directives, so emit line number information this way
-                * FIXME: CLANG only emits line number info for .loc directives followed by assembly, not
-                * .byte directives.
                 */
-               //acfg->gas_line_numbers = TRUE;
+               acfg->gas_line_numbers = TRUE;
        }
 
        if ((!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) && acfg->has_jitted_code) {
@@ -10343,7 +10365,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        aot_printerrf (acfg, "The dwarf AOT option requires the --debug option.\n");
                        return 1;
                }
-               acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, FALSE, !acfg->gas_line_numbers);
+               acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, !acfg->gas_line_numbers);
        }
 
        if (acfg->w)
index 93756b108b33cb4402a0ca57601aa8b0bb9a25cc..4f633c190af2b0cac360db5e69a43ad7eda30728 100644 (file)
@@ -1986,7 +1986,10 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module '%s' not found: %s\n", aot_name, err);
                                g_free (err);
 
-                               aot_name = g_strdup_printf ("%s/mono/aot-cache/%s/%s%s", mono_assembly_getrootdir(), MONO_ARCHITECTURE, g_path_get_basename (assembly->image->name), MONO_SOLIB_EXT);
+                               g_free (aot_name);
+                               char *basename = g_path_get_basename (assembly->image->name);
+                               aot_name = g_strdup_printf ("%s/mono/aot-cache/%s/%s%s", mono_assembly_getrootdir(), MONO_ARCHITECTURE, basename, MONO_SOLIB_EXT);
+                               g_free (basename);
                                sofile = mono_dl_open (aot_name, MONO_DL_LAZY, &err);
                                if (!sofile) {
                                        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module '%s' not found: %s\n", aot_name, err);
@@ -3056,7 +3059,7 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
                        mono_error_cleanup (&error); /* FIXME don't swallow the error */
                }
 
-               gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
+               gi->generic_sharing_context = alloc0_jit_info_data (domain, sizeof (MonoGenericSharingContext), async);
                if (decode_value (p, &p)) {
                        /* gsharedvt */
                        MonoGenericSharingContext *gsctx = gi->generic_sharing_context;
index 4c791507cc3775777fb5e32e80d057292f1841e0..e69085073ec92c79b6f8f916477963336506168a 100644 (file)
@@ -6031,6 +6031,7 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr,
                        } else if (type == VALUE_TYPE_ID_NULL) {
                                *(MonoObject**)addr = NULL;
                        } else if (type == MONO_TYPE_VALUETYPE) {
+                               MonoError error;
                                guint8 *buf2;
                                gboolean is_enum;
                                MonoClass *klass;
@@ -6062,7 +6063,8 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr,
                                        g_free (vtype_buf);
                                        return err;
                                }
-                               *(MonoObject**)addr = mono_value_box (d, klass, vtype_buf);
+                               *(MonoObject**)addr = mono_value_box_checked (d, klass, vtype_buf, &error);
+                               mono_error_cleanup (&error);
                                g_free (vtype_buf);
                        } else {
                                char *name = mono_type_full_name (t);
@@ -6084,6 +6086,7 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr,
 static ErrorCode
 decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit)
 {
+       MonoError error;
        ErrorCode err;
        int type = decode_byte (buf, &buf, limit);
 
@@ -6108,7 +6111,12 @@ decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8
                                g_free (nullable_buf);
                                return err;
                        }
-                       mono_nullable_init (addr, mono_value_box (domain, mono_class_from_mono_type (targ), nullable_buf), mono_class_from_mono_type (t));
+                       MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (targ), nullable_buf, &error);
+                       if (!is_ok (&error)) {
+                               mono_error_cleanup (&error);
+                               return ERR_INVALID_OBJECT;
+                       }
+                       mono_nullable_init (addr, boxed, mono_class_from_mono_type (t));
                        g_free (nullable_buf);
                        *endbuf = buf;
                        return ERR_NONE;
index 596509e6b7495cfad5f1b063fca51f95784eb50a..b53661e519b4d18cdcf1534dfd45191dc0a0511e 100644 (file)
@@ -53,7 +53,7 @@ struct _MonoDwarfWriter
        GSList *cie_program;
        FILE *fp;
        const char *temp_prefix;
-       gboolean emit_line, appending, collect_line_info;
+       gboolean emit_line;
        GSList *line_info;
        int cur_file_index;
 };
@@ -70,48 +70,17 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method,
  *   Create a DWARF writer object. WRITER is the underlying image writer this 
  * writer will emit to. IL_FILE is the file where IL code will be dumped to for
  * methods which have no line number info. It can be NULL.
- * If APPENDING is TRUE, the output file will be in assembleable state after each
- * call to the _emit_ functions. This is used for XDEBUG. If APPENDING is FALSE,
- * a separate mono_dwarf_writer_close () call is needed to finish the emission of
- * debug information.
  */
 MonoDwarfWriter*
-mono_dwarf_writer_create (MonoImageWriter *writer, FILE *il_file, int il_file_start_line, gboolean appending, gboolean emit_line_numbers)
+mono_dwarf_writer_create (MonoImageWriter *writer, FILE *il_file, int il_file_start_line, gboolean emit_line_numbers)
 {
        MonoDwarfWriter *w = g_new0 (MonoDwarfWriter, 1);
-       
-       /*
-        * The appending flag is needed because we use subsections to order things in 
-        * the debug info, and:
-        * - apple's assembler doesn't support them
-        * - the binary writer has problems with subsections+alignment
-        * So instead of subsections, we use the _close () function in AOT mode,
-        * which writes out things in order.
-        */
 
        w->w = writer;
        w->il_file = il_file;
        w->il_file_line_index = il_file_start_line;
-       w->appending = appending;
-
-       if (appending)
-               g_assert (mono_img_writer_subsections_supported (w->w));
-
-       w->emit_line = TRUE;
-
-       if (appending) {
-               if (!mono_img_writer_subsections_supported (w->w))
-                       /* Can't emit line number info without subsections */
-                       w->emit_line = FALSE;
-       } else {
-               /* Collect line number info and emit it at once */
-               w->collect_line_info = TRUE;
-       }
 
-       if (!emit_line_numbers) {
-               w->emit_line = FALSE;
-               w->collect_line_info = FALSE;
-       }
+       w->emit_line = emit_line_numbers;
 
        w->fp = mono_img_writer_get_fp (w->w);
        w->temp_prefix = mono_img_writer_get_temp_label_prefix (w->w);
@@ -734,8 +703,6 @@ emit_all_line_number_info (MonoDwarfWriter *w)
        GSList *l;
        GSList *info_list;
 
-       g_assert (w->collect_line_info);
-
        add_line_number_file_name (w, "<unknown>", 0, 0);
 
        /* Collect files */
@@ -887,6 +854,12 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, const char *cu_name, GSLis
        char *s, *build_info;
        int i;
 
+       if (!w->emit_line) {
+               emit_section_change (w, ".debug_line", 0);
+               emit_label (w, ".Ldebug_line_section_start");
+               emit_label (w, ".Ldebug_line_start");
+       }
+
        w->cie_program = base_unwind_program;
 
        emit_section_change (w, ".debug_abbrev", 0);
@@ -936,14 +909,6 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, const char *cu_name, GSLis
        emit_int32 (w, 0); /* .debug_abbrev offset */
        emit_byte (w, sizeof (gpointer)); /* address size */
 
-       if (mono_img_writer_subsections_supported (w->w) && w->appending) {
-               /* Emit this into a separate section so it gets placed at the end */
-               emit_section_change (w, ".debug_info", 1);
-               emit_byte (w, 0); /* close COMPILE_UNIT */
-               emit_label (w, ".Ldebug_info_end");
-               emit_section_change (w, ".debug_info", 0);
-       }
-
        /* Compilation unit */
        emit_uleb128 (w, ABBREV_COMPILE_UNIT);
        build_info = mono_get_runtime_build_info ();
@@ -957,10 +922,7 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, const char *cu_name, GSLis
        emit_pointer_value (w, 0);
        emit_pointer_value (w, 0);
        /* offset into .debug_line section */
-       if (w->emit_line)
-               emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
-       else
-               emit_pointer_value (w, 0);
+       emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
 
        /* Base types */
        for (i = 0; i < G_N_ELEMENTS (basic_types); ++i) {
@@ -988,13 +950,11 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, const char *cu_name, GSLis
 void
 mono_dwarf_writer_close (MonoDwarfWriter *w)
 {
-       if (!w->appending) {
-               emit_section_change (w, ".debug_info", 0);
-               emit_byte (w, 0); /* close COMPILE_UNIT */
-               emit_label (w, ".Ldebug_info_end");
-       }
+       emit_section_change (w, ".debug_info", 0);
+       emit_byte (w, 0); /* close COMPILE_UNIT */
+       emit_label (w, ".Ldebug_info_end");
 
-       if (w->collect_line_info)
+       if (w->emit_line)
                emit_all_line_number_info (w);
 }
 
@@ -1714,10 +1674,7 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method,
                        if (!prev_file_name || strcmp (loc->source_file, prev_file_name) != 0) {
                                /* Add an entry to the file table */
                                /* FIXME: Avoid duplicates */
-                               if (w->collect_line_info)
-                                       file_index = get_line_number_file_name (w, loc->source_file) + 1;
-                               else
-                                       file_index = emit_line_number_file_name (w, loc->source_file, 0, 0);
+                               file_index = get_line_number_file_name (w, loc->source_file) + 1;
                                g_free (prev_file_name);
                                prev_file_name = g_strdup (loc->source_file);
 
@@ -2072,23 +2029,18 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod
                w->fde_index ++;
        }
 
-       /* Emit line number info */
+       /* Save the information needed to emit the line number info later at once */
        /* != could happen when using --regression */
        if (debug_info && (debug_info->code_start == code)) {
-               if (w->collect_line_info) {
-                       MethodLineNumberInfo *info;
-
-                       /* Save the information needed to emit the line number info later at once */
-                       info = g_new0 (MethodLineNumberInfo, 1);
-                       info->method = method;
-                       info->start_symbol = g_strdup (start_symbol);
-                       info->end_symbol = g_strdup (end_symbol);
-                       info->code = code;
-                       info->code_size = code_size;
-                       w->line_info = g_slist_prepend (w->line_info, info);
-               } else {
-                       emit_line_number_info (w, method, start_symbol, end_symbol, code, code_size, debug_info);
-               }
+               MethodLineNumberInfo *info;
+
+               info = g_new0 (MethodLineNumberInfo, 1);
+               info->method = method;
+               info->start_symbol = g_strdup (start_symbol);
+               info->end_symbol = g_strdup (end_symbol);
+               info->code = code;
+               info->code_size = code_size;
+               w->line_info = g_slist_prepend (w->line_info, info);
        }
 
        emit_line (w);
index b5a08b1e99042624b166466bdbf24c9f7a52d51b..83d6a1c16d5391e673984b8fdf4a3e5514edf5b9 100644 (file)
@@ -20,7 +20,7 @@
 
 typedef struct _MonoDwarfWriter MonoDwarfWriter;
 
-MonoDwarfWriter* mono_dwarf_writer_create (MonoImageWriter *writer, FILE *il_file, int il_file_start_line, gboolean appending, gboolean emit_line_numbers);
+MonoDwarfWriter* mono_dwarf_writer_create (MonoImageWriter *writer, FILE *il_file, int il_file_start_line, gboolean emit_line_numbers);
 
 void mono_dwarf_writer_destroy (MonoDwarfWriter *w);
 
index 1f4f63384ed3e2e93af6c0f8215c8de2a0146e44..cab03fc0f2eae39d21165e0a02250a666d7cbd79 100644 (file)
@@ -306,18 +306,20 @@ mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guin
                                                        guint64 dummy5, guint64 dummy6,
                                                        MonoContext *mctx, MonoObject *exc, gboolean rethrow)
 {
+       MonoError error;
        MonoContext ctx;
 
        /* mctx is on the caller's stack */
        memcpy (&ctx, mctx, sizeof (MonoContext));
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
 
        /* adjust eip so that it point into the call instruction */
        ctx.gregs [AMD64_RIP] --;
@@ -415,10 +417,7 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
        amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, stack_size + sizeof(mgreg_t));
        amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (AMD64_RSP * sizeof(mgreg_t)), X86_EAX, sizeof(mgreg_t));
        /* Save IP */
-       if (llvm_abs)
-               amd64_alu_reg_reg (code, X86_XOR, AMD64_RAX, AMD64_RAX);
-       else
-               amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, stack_size, sizeof(mgreg_t));
+       amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, stack_size, sizeof(mgreg_t));
        amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (AMD64_RIP * sizeof(mgreg_t)), AMD64_RAX, sizeof(mgreg_t));
        /* Set arg1 == ctx */
        amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, ctx_offset);
@@ -432,14 +431,14 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
        if (resume_unwind) {
                amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], 0, sizeof(mgreg_t));
        } else if (corlib) {
-               amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG2, sizeof(mgreg_t));
                if (llvm_abs)
-                       /* 
-                        * The caller is LLVM code which passes the absolute address not a pc offset,
-                        * so compensate by passing 0 as 'rip' and passing the negated abs address as
-                        * the pc offset.
+                       /*
+                        * The caller doesn't pass in a pc/pc offset, instead we simply use the
+                        * caller ip. Negate the pc adjustment done in mono_amd64_throw_corlib_exception ().
                         */
-                       amd64_neg_membase (code, AMD64_RSP, arg_offsets [2]);
+                       amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], 1, sizeof(mgreg_t));
+               else
+                       amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG2, sizeof(mgreg_t));
        } else {
                amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], rethrow, sizeof(mgreg_t));
        }
index b478a713bc5e108ea30e7d59ed5e4a2f8c24a9c0..4c2b5ce821db200b5cbb1765ac463eb54cde8463 100644 (file)
@@ -137,6 +137,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 void
 mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
 {
+       MonoError error;
        MonoContext ctx;
        gboolean rethrow = sp & 1;
 
@@ -152,25 +153,27 @@ mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_
        memcpy (((guint8*)&ctx.regs) + (ARMREG_R4 * sizeof (mgreg_t)), int_regs, 8 * sizeof (mgreg_t));
        memcpy (&ctx.fregs, fp_regs, sizeof (double) * 16);
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
        mono_handle_exception (&ctx, exc);
        mono_restore_context (&ctx);
        g_assert_not_reached ();
 }
 
 void
-mono_arm_throw_exception_by_token (guint32 type_token, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
+mono_arm_throw_exception_by_token (guint32 ex_token_index, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
 {
+       guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
        /* Clear thumb bit */
        pc &= ~1;
 
-       mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, type_token), pc, sp, int_regs, fp_regs);
+       mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token), pc, sp, int_regs, fp_regs);
 }
 
 void
@@ -245,9 +248,15 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm
        /* exc is already in place in r0 */
        if (corlib) {
                /* The caller ip is already in R1 */
-               if (llvm)
-                       /* Negate the ip adjustment done in mono_arm_throw_exception */
-                       ARM_ADD_REG_IMM8 (code, ARMREG_R1, ARMREG_R1, 4);
+               if (llvm) {
+                       /*
+                        * The address passed by llvm might point to before the call,
+                        * thus outside the eh range recorded by llvm. Use the return
+                        * address instead.
+                        * FIXME: Do this on more platforms.
+                        */
+                       ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
+               }
        } else {
                ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
        }
index 9d13bfbf2c59a3f485e4a2d963cda406fb4caf04..adae20f2b5f2fb83a57d67b3b08b30a77f007483 100644 (file)
@@ -236,18 +236,20 @@ static void
 throw_exception (MonoObject *exc, guint64 rethrow)
 {
        unw_context_t unw_ctx;
+       MonoError error;
        MonoContext ctx;
        MonoJitInfo *ji;
        unw_word_t ip, sp;
        int res;
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
 
        res = unw_getcontext (&unw_ctx);
        g_assert (res == 0);
index f8d9dedff2ce60e3e223f4189b57c5452a456c4d..f39ff46977a8ce5d25c8ed7e89c2b16dde67b163 100644 (file)
@@ -176,6 +176,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 static void
 throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean rethrow)
 {
+       MonoError error;
        MonoContext ctx;
 
 #ifdef DEBUG_EXCEPTIONS
@@ -194,13 +195,14 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean
        memset (&ctx.sc_fpregs, 0, sizeof (mips_freg) * MONO_SAVED_FREGS);
        MONO_CONTEXT_SET_IP (&ctx, eip);
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
        mono_handle_exception (&ctx, exc);
 #ifdef DEBUG_EXCEPTIONS
        g_print ("throw_exception: restore to pc=%p sp=%p fp=%p ctx=%p\n",
index 1088e12ea426ae53272624cb11c3a49de19e8863..80a579b05eb87e539e3b1c344edf636991b4c667 100644 (file)
@@ -318,6 +318,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 void
 mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow)
 {
+       MonoError error;
        MonoContext ctx;
 
        /* adjust eip so that it point into the call instruction */
@@ -331,13 +332,14 @@ mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp,
        memcpy (&ctx.regs, int_regs, sizeof (mgreg_t) * MONO_SAVED_GREGS);
        memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_SAVED_FREGS);
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
        mono_handle_exception (&ctx, exc);
        mono_restore_context (&ctx);
 
index 18e51bd94ee89b6743184d8aa915007f03bdd010..bfb3fabcda8713be9842fc2e1caf4abd333c894e 100644 (file)
@@ -240,6 +240,7 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp,
                 gulong *int_regs, gdouble *fp_regs, gint32 *acc_regs, 
                 guint fpc, gboolean rethrow)
 {
+       MonoError error;
        MonoContext ctx;
        int iReg;
 
@@ -261,13 +262,14 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp,
        MONO_CONTEXT_SET_BP (&ctx, sp);
        MONO_CONTEXT_SET_IP (&ctx, ip);
        
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
 //     mono_arch_handle_exception (&ctx, exc, FALSE);
        mono_handle_exception (&ctx, exc);
        mono_restore_context(&ctx);
index d9b3d9d99c658bfc396ef0e01aa21af3633d7a03..77510a7f934de0d832dd20fca39c687f19c4d1de 100644 (file)
@@ -166,6 +166,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 static void
 throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow)
 {
+       MonoError error;
        MonoContext ctx;
        static void (*restore_context) (MonoContext *);
        gpointer *window;
@@ -178,13 +179,14 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow)
        ctx.ip = ip;
        ctx.fp = (gpointer*)(MONO_SPARC_WINDOW_ADDR (sp) [sparc_i6 - 16]);
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
        mono_handle_exception (&ctx, exc);
        restore_context (&ctx);
 
index 87a67abd930f3d4ee33149018d6a2ed89ca38fb1..14e8f6111c15ce90bac97f37ab15c38b85ec27ae 100644 (file)
@@ -456,6 +456,7 @@ void
 mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, 
                                                  mgreg_t eip, gboolean rethrow)
 {
+       MonoError error;
        MonoContext ctx;
 
        ctx.esp = regs [X86_ESP];
@@ -473,13 +474,14 @@ mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc,
        g_assert ((ctx.esp % MONO_ARCH_FRAME_ALIGNMENT) == 0);
 #endif
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
 
        /* adjust eip so that it point into the call instruction */
        ctx.eip -= 1;
index b996f8f83b55a07a401a31409d4f5c437228d43c..7118e19c8cec06cd9fb7588d5e7c89f2e9564706 100644 (file)
@@ -54,6 +54,14 @@ static GHashTable *template_table;
 
 #define eat_whitespace(s) while (*(s) && isspace (*(s))) s++;
 
+// Per spec isalnum() expects input in the range 0-255
+// and can misbehave if you pass in a signed char.
+static int
+isalnum_char(char c)
+{
+       return isalnum ((unsigned char)c);
+}
+
 static int
 load_file (const char *name) {
        FILE *f;
@@ -163,7 +171,7 @@ load_file (const char *name) {
                                OpDesc *tdesc;
                                p += 9;
                                tname = p;
-                               while (*p && isalnum (*p)) ++p;
+                               while (*p && isalnum_char (*p)) ++p;
                                *p++ = 0;
                                tdesc = (OpDesc *)g_hash_table_lookup (template_table, tname);
                                if (!tdesc)
@@ -181,7 +189,7 @@ load_file (const char *name) {
                                        g_error ("Duplicated name tag in template %s at '%s' at line %d in %s\n", desc->name, p, line, name);
                                p += 5;
                                tname = p;
-                               while (*p && isalnum (*p)) ++p;
+                               while (*p && isalnum_char (*p)) ++p;
                                *p++ = 0;
                                if (g_hash_table_lookup (template_table, tname))
                                        g_error ("Duplicated template %s at line %d in %s\n", tname, line, name);
@@ -220,7 +228,7 @@ init_table (void) {
 
 static void
 output_char (FILE *f, char c) {
-       if (isalnum (c))
+       if (isalnum_char (c))
                fprintf (f, "%c", c);
        else
                fprintf (f, "\\x%x\" \"", (guint8)c);
index a8bfee03414ab95fe515d69c2dce3f7b178af86a..88f8c2ebb22b780a3c461daf2d8b62e6370f3e68 100644 (file)
@@ -1716,6 +1716,23 @@ public class Tests
                return 0;
        }
 
+       interface ISmallArg {
+               T foo<T> (string s1, string s2, string s3, string s4, string s5, string s6, string s7, string s8,
+                                 string s9, string s10, string s11, string s12, string s13, T t);
+       }
+
+       class SmallArgClass : ISmallArg {
+                       public T foo<T> (string s1, string s2, string s3, string s4, string s5, string s6, string s7, string s8,
+                                                        string s9, string s10, string s11, string s12, string s13, T t) {
+                               return t;
+                       }
+               }
+
+       public static int test_1_small_gsharedvt_stack_arg_ios () {
+               ISmallArg o = new SmallArgClass ();
+               return o.foo<int> ("", "", "", "", "", "", "", "", "", "", "", "", "", 1);
+       }
+
        // Passing vtype normal arguments on the stack
        public static int test_0_arm64_vtype_stack_args () {
                IFoo3<EmptyStruct> o = (IFoo3<EmptyStruct>)Activator.CreateInstance (typeof (Foo3<>).MakeGenericType (new Type [] { typeof (EmptyStruct) }));
index c216f3b25755f4231091b096a4f506990e4a8d2f..4992565ba0d162951515dee73e1177f56124f4f8 100644 (file)
@@ -1686,6 +1686,9 @@ bin_writer_emit_writeout (MonoImageWriter *acfg)
 static void
 asm_writer_emit_start (MonoImageWriter *acfg)
 {
+#if defined(TARGET_ASM_APPLE)
+       fprintf (acfg->fp, ".subsections_via_symbols\n");
+#endif
 }
 
 static int
@@ -1759,8 +1762,14 @@ asm_writer_emit_symbol_type (MonoImageWriter *acfg, const char *name, gboolean f
                stype = "object";
 
        asm_writer_emit_unset_mode (acfg);
+
 #if defined(TARGET_ASM_APPLE)
 
+#elif defined(TARGET_WIN32)
+       if (func)
+               fprintf (acfg->fp, "\t.def %s; .scl 2; .type 32; .endef\n", name);
+       else
+               fprintf (acfg->fp, "\t.data\n");
 #elif defined(TARGET_ARM)
        fprintf (acfg->fp, "\t.type %s,#%s\n", name, stype);
 #else
@@ -1783,7 +1792,7 @@ asm_writer_emit_local_symbol (MonoImageWriter *acfg, const char *name, const cha
 {
        asm_writer_emit_unset_mode (acfg);
 
-#ifndef TARGET_ASM_APPLE
+#if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
        fprintf (acfg->fp, "\t.local %s\n", name);
 #endif
 
@@ -1795,7 +1804,8 @@ asm_writer_emit_symbol_size (MonoImageWriter *acfg, const char *name, const char
 {
        asm_writer_emit_unset_mode (acfg);
 
-#ifndef TARGET_ASM_APPLE
+
+#if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
        fprintf (acfg->fp, "\t.size %s,%s-%s\n", name, end_label, name);
 #endif
 }
index b67cb5f1508f03a58db4225668c10980ab0da4c0..dbf89a8d517e0ea20d793f181a7c8f65487aeffb 100644 (file)
@@ -102,11 +102,14 @@ mono_ldvirtfn_gshared (MonoObject *obj, MonoMethod *method)
 void
 mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
 {
+       MonoError error;
        if (!array) {
                mono_set_pending_exception (mono_get_exception_null_reference ());
                return;
        }
-       if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class)) {
+       if (val && !mono_object_isinst_checked (val, array->obj.vtable->klass->element_class, &error)) {
+               if (mono_error_set_pending_exception (&error))
+                       return;
                mono_set_pending_exception (mono_get_exception_array_type_mismatch ());
                return;
        }
@@ -1178,6 +1181,7 @@ mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg
 MonoObject*
 mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
 {
+       MonoError error;
        MonoJitTlsData *jit_tls = NULL;
        MonoClass *oklass;
 
@@ -1192,8 +1196,10 @@ mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
        oklass = obj->vtable->klass;
        if ((klass->enumtype && oklass == klass->element_class) || (oklass->enumtype && klass == oklass->element_class))
                return obj;
-       if (mono_object_isinst (obj, klass))
+       if (mono_object_isinst_checked (obj, klass, &error))
                return obj;
+       if (mono_error_set_pending_exception (&error))
+               return NULL;
 
        if (mini_get_debug_options ()->better_cast_details) {
                jit_tls->class_cast_from = oklass;
@@ -1209,6 +1215,7 @@ mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
 MonoObject*
 mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
 {
+       MonoError error;
        MonoJitTlsData *jit_tls = NULL;
        gpointer cached_vtable, obj_vtable;
 
@@ -1226,10 +1233,12 @@ mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *c
        if (cached_vtable == obj_vtable)
                return obj;
 
-       if (mono_object_isinst (obj, klass)) {
+       if (mono_object_isinst_checked (obj, klass, &error)) {
                *cache = obj_vtable;
                return obj;
        }
+       if (mono_error_set_pending_exception (&error))
+               return NULL;
 
        if (mini_get_debug_options ()->better_cast_details) {
                jit_tls->class_cast_from = obj->vtable->klass;
@@ -1245,6 +1254,7 @@ mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *c
 MonoObject*
 mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
 {
+       MonoError error;
        size_t cached_vtable, obj_vtable;
 
        if (!obj)
@@ -1257,10 +1267,12 @@ mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cach
                return (cached_vtable & 0x1) ? NULL : obj;
        }
 
-       if (mono_object_isinst (obj, klass)) {
+       if (mono_object_isinst_checked (obj, klass, &error)) {
                *cache = (gpointer)obj_vtable;
                return obj;
        } else {
+               if (mono_error_set_pending_exception (&error))
+                       return NULL;
                /*negative cache*/
                *cache = (gpointer)(obj_vtable | 0x1);
                return NULL;
@@ -1322,7 +1334,7 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k
                /*
                 * Calling a non-vtype method with a vtype receiver, has to box.
                 */
-               *this_arg = mono_value_box (mono_domain_get (), klass, mp);
+               *this_arg = mono_value_box_checked (mono_domain_get (), klass, mp, error);
        else if (klass->valuetype)
                /*
                 * Calling a vtype method with a vtype receiver
index 3d295db2a358a479cdce82160444b1066145b036..71ed0310656e5baaf0aabe72ac577e1979ca1bdc 100644 (file)
@@ -8578,7 +8578,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
        skip_dead_blocks = !dont_verify;
        if (skip_dead_blocks) {
-               original_bb = bb = mono_basic_block_split (method, &cfg->error);
+               original_bb = bb = mono_basic_block_split (method, &cfg->error, header);
                CHECK_CFG_ERROR;
                g_assert (bb);
        }
@@ -11649,7 +11649,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                                INLINE_FAILURE ("class init");
                                                        if (!mono_runtime_class_init_full (vtable, &cfg->error)) {
                                                                mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
-                                                               g_assert_not_reached ();
                                                                goto exception_exit;
                                                        }
                                                }
index 5b386a904f0f8a97c929a2093aaf70b5109d3102..b1cdaaf8dfe52c3628d5cf17cbd099beac77bf86 100644 (file)
@@ -3926,21 +3926,6 @@ emit_setup_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset, int cfa_offse
        return code;
 }
 
-#define REAL_PRINT_REG(text,reg) \
-mono_assert (reg >= 0); \
-amd64_push_reg (code, AMD64_RAX); \
-amd64_push_reg (code, AMD64_RDX); \
-amd64_push_reg (code, AMD64_RCX); \
-amd64_push_reg (code, reg); \
-amd64_push_imm (code, reg); \
-amd64_push_imm (code, text " %d %p\n"); \
-amd64_mov_reg_imm (code, AMD64_RAX, printf); \
-amd64_call_reg (code, AMD64_RAX); \
-amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 3*4); \
-amd64_pop_reg (code, AMD64_RCX); \
-amd64_pop_reg (code, AMD64_RDX); \
-amd64_pop_reg (code, AMD64_RAX);
-
 /* benchmark and set based on cpu */
 #define LOOP_ALIGNMENT 8
 #define bb_is_loop_start(bb) ((bb)->loop_body_start && (bb)->nesting)
index 66fd8c083b302ec723f148e1f7130b0a1104c9dc..a7df6fc1c1b282990ba87401cf50423291a546f0 100644 (file)
@@ -2375,6 +2375,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                                        } else {
                                                int creg;
 
+                                               cfg->param_area = MAX (cfg->param_area, 8);
                                                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, ARMREG_SP, (cfg->param_area - 8), in->dreg);
                                                creg = mono_alloc_ireg (cfg);
                                                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, creg, ARMREG_SP, (cfg->param_area - 8));
@@ -2396,6 +2397,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                                        } else {
                                                int creg;
 
+                                               cfg->param_area = MAX (cfg->param_area, 8);
                                                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, ARMREG_SP, (cfg->param_area - 8), in->dreg);
                                                creg = mono_alloc_ireg (cfg);
                                                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, creg, ARMREG_SP, (cfg->param_area - 8));
@@ -2467,6 +2469,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
 
                                /* This should work for soft-float as well */
 
+                               cfg->param_area = MAX (cfg->param_area, 8);
                                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, ARMREG_SP, (cfg->param_area - 8), in->dreg);
                                creg = mono_alloc_ireg (cfg);
                                mono_call_inst_add_outarg_reg (cfg, call, creg, ARMREG_R3, FALSE);
@@ -6572,7 +6575,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                code = mono_arm_load_jumptable_entry_addr (code, jte, ARMREG_LR);
 #else
                ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
-               ARM_B (code, 2);
+               ARM_B (code, 1);
                *(gpointer*)code = &single_step_tramp;
                code += 4;
                *(gpointer*)code = breakpoint_tramp;
@@ -6824,7 +6827,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
                        patch_info->ip.i = code - cfg->native_code;
                        ARM_BL (code, 0);
                        cfg->thunk_area += THUNK_SIZE;
-                       *(guint32*)(gpointer)code = exc_class->type_token;
+                       *(guint32*)(gpointer)code = exc_class->type_token - MONO_TOKEN_TYPE_DEF;
                        code += 4;
 #endif
                        break;
index cde7e06bf05f165dced94e47bf0cf5f544aebee0..77d5fdcb1ebf654bd4c6e43093bca0e30b232721 100644 (file)
@@ -1348,6 +1348,7 @@ setup_stack_trace (MonoException *mono_ex, GSList *dynamic_methods, MonoArray *i
 static gboolean
 mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception)
 {
+       MonoError error;
        MonoDomain *domain = mono_domain_get ();
        MonoJitInfo *ji = NULL;
        static int (*call_filter) (MonoContext *, gpointer) = NULL;
@@ -1373,10 +1374,11 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
        mono_ex = (MonoException*)obj;
        initial_trace_ips = mono_ex->trace_ips;
 
-       if (mono_object_isinst (obj, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
                mono_ex = (MonoException*)obj;
                initial_trace_ips = mono_ex->trace_ips;
        } else {
+               mono_error_assert_ok (&error);
                mono_ex = NULL;
        }
 
@@ -1539,7 +1541,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
                                        }
                                }
 
-                               if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (ex_obj, catch_class)) {
+                               if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (ex_obj, catch_class, &error)) {
                                        setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
                                        g_slist_free (dynamic_methods);
 
@@ -1550,6 +1552,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
                                        MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
                                        return TRUE;
                                }
+                               mono_error_cleanup (&error);
                        }
                }
 
@@ -1605,7 +1608,8 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                obj = (MonoObject *)mono_get_exception_null_reference ();
        }
 
-       if (!mono_object_isinst (obj, mono_defaults.exception_class)) {
+       if (!mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
+               mono_error_assert_ok (&error);
                non_exception = obj;
                obj = (MonoObject *)mono_get_exception_runtime_wrapped_checked (obj, &error);
                mono_error_assert_ok (&error);
@@ -1619,9 +1623,10 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                        ;
        }
 
-       if (mono_object_isinst (obj, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
                mono_ex = (MonoException*)obj;
        } else {
+               mono_error_assert_ok (&error);
                mono_ex = NULL;
        }
 
@@ -1832,8 +1837,9 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                        filter_idx ++;
                                }
 
+                               mono_error_init (&error);
                                if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && 
-                                        mono_object_isinst (ex_obj, catch_class)) || filtered) {
+                                    mono_object_isinst_checked (ex_obj, catch_class, &error)) || filtered) {
                                        /*
                                         * This guards against the situation that we abort a thread that is executing a finally clause
                                         * that was called by the EH machinery. It won't have a guard trampoline installed, so we must
@@ -1884,6 +1890,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
 
                                        return 0;
                                }
+                               mono_error_cleanup (&error);
                                if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
                                        if (mono_trace_is_enabled () && mono_trace_eval (method))
                                                g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
@@ -2882,7 +2889,8 @@ throw_exception (MonoObject *ex, gboolean rethrow)
        MonoJitTlsData *jit_tls = mono_get_jit_tls ();
        MonoException *mono_ex;
 
-       if (!mono_object_isinst (ex, mono_defaults.exception_class)) {
+       if (!mono_object_isinst_checked (ex, mono_defaults.exception_class, &error)) {
+               mono_error_assert_ok (&error);
                mono_ex = mono_get_exception_runtime_wrapped_checked (ex, &error);
                mono_error_assert_ok (&error);
        }
@@ -3022,6 +3030,7 @@ mono_llvm_clear_exception (void)
 gint32
 mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj)
 {
+                       MonoError error;
        MonoJitTlsData *jit_tls = mono_get_jit_tls ();
        MonoObject *exc;
        gint32 index = -1;
@@ -3037,7 +3046,6 @@ mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 reg
 
                catch_class = ei->data.catch_class;
                if (catch_class->byval_arg.type == MONO_TYPE_VAR || catch_class->byval_arg.type == MONO_TYPE_MVAR || catch_class->byval_arg.type == MONO_TYPE_GENERICINST) {
-                       MonoError error;
                        MonoGenericContext context;
                        MonoType *inflated_type;
 
@@ -3051,10 +3059,13 @@ mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 reg
                }
 
                // FIXME: Handle edge cases handled in get_exception_catch_class
-               if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (exc, catch_class)) {
+               if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (exc, catch_class, &error)) {
                        index = ei->clause_index;
                        break;
-               } else if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+               } else
+                       mono_error_assert_ok (&error);
+               
+               if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
                        g_assert_not_reached ();
                }
        }
index 9e8596e7bf135c3a31b057172fff8588306cdbb7..f8aa239061589f9c9092ff6b246e76eecfa98591 100644 (file)
@@ -24,8 +24,6 @@
 #define __STDC_CONSTANT_MACROS
 #endif
 
-#include "llvm-c/Core.h"
-#include "llvm-c/ExecutionEngine.h"
 #include "llvm-c/BitWriter.h"
 #include "llvm-c/Analysis.h"
 
@@ -2070,6 +2068,11 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex
        MonoClass *exc_class;
        LLVMValueRef args [2];
        LLVMValueRef callee;
+       gboolean no_pc = FALSE;
+
+       if (IS_TARGET_AMD64)
+               /* Some platforms don't require the pc argument */
+               no_pc = TRUE;
        
        ex_bb = gen_bb (ctx, "EX_BB");
        if (ctx->llvm_only)
@@ -2114,7 +2117,10 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex
                LLVMTypeRef sig;
                const char *icall_name;
 
-               sig = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), LLVMPointerType (LLVMInt8Type (), 0), FALSE);
+               if (no_pc)
+                       sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
+               else
+                       sig = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), LLVMPointerType (LLVMInt8Type (), 0), FALSE);
                icall_name = "llvm_throw_corlib_exception_abs_trampoline";
 
                if (ctx->cfg->compile_aot) {
@@ -2146,17 +2152,18 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex
                }
        }
 
-       if (IS_TARGET_X86 || IS_TARGET_AMD64)
-               args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
-       else
-               args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token, FALSE);
+       args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
 
        /*
         * The LLVM mono branch contains changes so a block address can be passed as an
         * argument to a call.
         */
-       args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
-       emit_call (ctx, bb, &builder, callee, args, 2);
+       if (no_pc) {
+               emit_call (ctx, bb, &builder, callee, args, 1);
+       } else {
+               args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
+               emit_call (ctx, bb, &builder, callee, args, 2);
+       }
 
        LLVMBuildUnreachable (builder);
 
index 6a9f054864b68efb5c4915a9b234c442443ec58e..ba0aad7dce30161796170b5ec6173d927b8c9b99 100644 (file)
@@ -2007,7 +2007,9 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er
                        MonoVTable *vtable;
 
                        mono_jit_stats.methods_lookups++;
-                       vtable = mono_class_vtable (domain, method->klass);
+                       vtable = mono_class_vtable_full (domain, method->klass, error);
+                       if (!is_ok (error))
+                               return NULL;
                        g_assert (vtable);
                        if (!mono_runtime_class_init_full (vtable, error))
                                return NULL;
@@ -2500,7 +2502,7 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void
                mono_error_set_exception_instance (error, (MonoException*) *exc);
 
        if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
-               return mono_value_box (domain, info->ret_box_class, retval);
+               return mono_value_box_checked (domain, info->ret_box_class, retval, error);
        else
                return *(MonoObject**)retval;
 }
@@ -2675,7 +2677,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                mono_arch_finish_dyn_call (info->dyn_call_info, buf);
 
                if (info->ret_box_class)
-                       return mono_value_box (domain, info->ret_box_class, retval);
+                       return mono_value_box_checked (domain, info->ret_box_class, retval, error);
                else
                        return *(MonoObject**)retval;
        }
index ed844636c525ed7b50cf746cfca057e22f5c301f..346ef6d9221bb23e3d885102d6c39114c451e503 100644 (file)
@@ -1057,36 +1057,6 @@ mono_rgctx_lazy_fetch_trampoline (mgreg_t *regs, guint8 *code, gpointer data, gu
        return res;
 }
 
-/*
- * Precompute data to speed up mono_delegate_trampoline ().
- * METHOD might be NULL.
- */
-static MonoDelegateTrampInfo*
-create_delegate_trampoline_data (MonoDomain *domain, MonoClass *klass, MonoMethod *method)
-{
-       MonoDelegateTrampInfo *tramp_data;
-       MonoMethod *invoke;
-       MonoError err;
-
-       // Precompute the delegate invoke impl and pass it to the delegate trampoline
-       invoke = mono_get_delegate_invoke (klass);
-       g_assert (invoke);
-
-       tramp_data = (MonoDelegateTrampInfo *)mono_domain_alloc0 (domain, sizeof (MonoDelegateTrampInfo));
-       tramp_data->invoke = invoke;
-       tramp_data->invoke_sig = mono_method_signature (invoke);
-       tramp_data->impl_this = mono_arch_get_delegate_invoke_impl (mono_method_signature (invoke), TRUE);
-       tramp_data->impl_nothis = mono_arch_get_delegate_invoke_impl (mono_method_signature (invoke), FALSE);
-       tramp_data->method = method;
-       if (method) {
-               mono_error_init (&err);
-               tramp_data->sig = mono_method_signature_checked (method, &err);
-               tramp_data->need_rgctx_tramp = mono_method_needs_static_rgctx_invoke (method, FALSE);
-       }
-
-       return tramp_data;
-}
-
 /**
  * mono_delegate_trampoline:
  *
@@ -1576,11 +1546,13 @@ mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token)
 /*
  * mono_create_delegate_trampoline_info:
  *
- *   Create a delegate trampoline for the KLASS+METHOD pair.
+ *  Create a trampoline info structure for the KLASS+METHOD pair.
  */
 MonoDelegateTrampInfo*
 mono_create_delegate_trampoline_info (MonoDomain *domain, MonoClass *klass, MonoMethod *method)
 {
+       MonoMethod *invoke;
+       MonoError error;
        MonoDelegateTrampInfo *tramp_info;
        MonoClassMethodPair pair, *dpair;
        guint32 code_size = 0;
@@ -1593,8 +1565,20 @@ mono_create_delegate_trampoline_info (MonoDomain *domain, MonoClass *klass, Mono
        if (tramp_info)
                return tramp_info;
 
-       tramp_info = create_delegate_trampoline_data (domain, klass, method);
+       invoke = mono_get_delegate_invoke (klass);
+       g_assert (invoke);
 
+       tramp_info = (MonoDelegateTrampInfo *)mono_domain_alloc0 (domain, sizeof (MonoDelegateTrampInfo));
+       tramp_info->invoke = invoke;
+       tramp_info->invoke_sig = mono_method_signature (invoke);
+       tramp_info->impl_this = mono_arch_get_delegate_invoke_impl (mono_method_signature (invoke), TRUE);
+       tramp_info->impl_nothis = mono_arch_get_delegate_invoke_impl (mono_method_signature (invoke), FALSE);
+       tramp_info->method = method;
+       if (method) {
+               mono_error_init (&error);
+               tramp_info->sig = mono_method_signature_checked (method, &error);
+               tramp_info->need_rgctx_tramp = mono_method_needs_static_rgctx_invoke (method, FALSE);
+       }
        tramp_info->invoke_impl = mono_create_specific_trampoline (tramp_info, MONO_TRAMPOLINE_DELEGATE, domain, &code_size);
        g_assert (code_size);
 
index 4bcc19b5bfb64d86d12da04f3653159639057a1f..41f12051f906929073be867a6b0076a04b8dbf11 100644 (file)
@@ -58,12 +58,14 @@ void
 mono_runtime_install_handlers (void)
 {
 #ifndef MONO_CROSS_COMPILE
-       win32_seh_init();
-       win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
-       win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
-       win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
-       if (mini_get_debug_options ()->handle_sigint)
-               win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
+       if (!mono_aot_only) {
+               win32_seh_init();
+               win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
+               win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
+               win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
+               if (mini_get_debug_options ()->handle_sigint)
+                       win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
+       }
 #endif
 }
 
@@ -71,7 +73,9 @@ void
 mono_runtime_cleanup_handlers (void)
 {
 #ifndef MONO_CROSS_COMPILE
-       win32_seh_cleanup();
+       if (!mono_aot_only) {
+               win32_seh_cleanup();
+       }
 #endif
 }
 
index 9802e46c58f88cffa1743c6a92d41085ec439774..1ef8d4614dd92f90cad7202396f7c9894ec9d5ea 100644 (file)
@@ -2475,26 +2475,6 @@ emit_setup_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset, int cfa_offse
        return code;
 }
 
-#define REAL_PRINT_REG(text,reg) \
-mono_assert (reg >= 0); \
-x86_push_reg (code, X86_EAX); \
-x86_push_reg (code, X86_EDX); \
-x86_push_reg (code, X86_ECX); \
-x86_push_reg (code, reg); \
-x86_push_imm (code, reg); \
-x86_push_imm (code, text " %d %p\n"); \
-x86_mov_reg_imm (code, X86_EAX, printf); \
-x86_call_reg (code, X86_EAX); \
-x86_alu_reg_imm (code, X86_ADD, X86_ESP, 3*4); \
-x86_pop_reg (code, X86_ECX); \
-x86_pop_reg (code, X86_EDX); \
-x86_pop_reg (code, X86_EAX);
-
-/* REAL_PRINT_REG does not appear to be used, and was not adapted to work with Native Client. */
-#ifdef __native__client_codegen__
-#define REAL_PRINT_REG(text, reg) g_assert_not_reached()
-#endif
-
 /* benchmark and set based on cpu */
 #define LOOP_ALIGNMENT 8
 #define bb_is_loop_start(bb) ((bb)->loop_body_start && (bb)->nesting)
index 2430e2295ceda8979dab5340ee18e038b737c70b..1a83343d735dfb5fdcf8b0c808939dea88f2692b 100644 (file)
@@ -910,7 +910,7 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo
        ARM_STR_IMM (code, ARMREG_R0, ARMREG_FP, MONO_STRUCT_OFFSET (MonoContext, regs) + 4 * ARMREG_SP);
 
        /* make ctx.eip hold the address of the call. */
-       ARM_SUB_REG_IMM8 (code, ARMREG_LR, ARMREG_LR, 4);
+       //ARM_SUB_REG_IMM8 (code, ARMREG_LR, ARMREG_LR, 4);
        ARM_STR_IMM (code, ARMREG_LR, ARMREG_FP, MONO_STRUCT_OFFSET (MonoContext, pc));
 
        /* r0 now points to the MonoContext */
index 82f14d7882255940ad311339fbe8c50073075a1b..ef3c65a7f225790813dfa5ab71f9a5e11b8c8ed4 100644 (file)
@@ -652,8 +652,12 @@ mono_unwind_cleanup (void)
 
                g_free (cached);
        }
-
        g_free (cached_info);
+
+       for (GSList *cursor = cached_info_list; cursor != NULL; cursor = cursor->next)
+               g_free (cursor->data);
+
+       g_slist_free (cached_info_list);
 }
 
 /*
@@ -708,10 +712,10 @@ mono_cache_unwind_info (guint8 *unwind_info, guint32 unwind_info_len)
 
                mono_memory_barrier ();
 
-               cached_info = new_table;
-
                cached_info_list = g_slist_prepend (cached_info_list, cached_info);
 
+               cached_info = new_table;
+
                cached_info_size *= 2;
        }
 
index 0e051966e126822f7121977b87b7aed82b1a2005..bbf90a08b64aac4af029668e370ba1778036466c 100644 (file)
@@ -162,7 +162,7 @@ mono_xdebug_init (const char *options)
 
        mono_img_writer_emit_start (w);
 
-       xdebug_writer = mono_dwarf_writer_create (w, il_file, 0, TRUE, TRUE);
+       xdebug_writer = mono_dwarf_writer_create (w, il_file, 0, TRUE);
 
        /* Emit something so the file has a text segment */
        mono_img_writer_emit_section_change (w, ".text", 0);
@@ -185,7 +185,7 @@ xdebug_begin_emit (MonoImageWriter **out_w, MonoDwarfWriter **out_dw)
        if (!il_file)
                il_file = fopen ("xdb.il", "w");
 
-       dw = mono_dwarf_writer_create (w, il_file, il_file_line_index, FALSE, TRUE);
+       dw = mono_dwarf_writer_create (w, il_file, il_file_line_index, TRUE);
 
        mono_dwarf_writer_emit_base_info (dw, "JITted code", mono_unwind_get_cie_program ());
 
index 7816c06d9f962e2d37b8b94d3281168726b2e31f..6027f7839a7faebb48ac492b3b10b15966b7d38a 100644 (file)
@@ -43,7 +43,6 @@ monosgen_sources = \
        sgen-los.c \
        sgen-major-copy-object.h \
        sgen-marksweep-drain-gray-stack.h \
-       sgen-marksweep-scan-object-concurrent.h \
        sgen-marksweep.c \
        sgen-memory-governor.c \
        sgen-memory-governor.h \
@@ -55,6 +54,8 @@ monosgen_sources = \
        sgen-pinning.h \
        sgen-pointer-queue.c \
        sgen-pointer-queue.h \
+       sgen-array-list.h \
+       sgen-array-list.c \
        sgen-protocol-def.h \
        sgen-protocol.c \
        sgen-protocol.h \
diff --git a/mono/sgen/sgen-array-list.c b/mono/sgen/sgen-array-list.c
new file mode 100644 (file)
index 0000000..f84868e
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * sgen-array-list.c: A pointer array list that doesn't require reallocs
+ *
+ * Copyright (C) 2016 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.
+ */
+
+#ifdef HAVE_SGEN_GC
+
+#include <string.h>
+
+#include "mono/sgen/sgen-gc.h"
+#include "mono/sgen/sgen-array-list.h"
+
+static void
+sgen_array_list_grow (SgenArrayList *array, guint32 old_capacity)
+{
+       const guint32 new_bucket = sgen_array_list_index_bucket (old_capacity);
+       const guint32 growth = sgen_array_list_bucket_size (new_bucket);
+       const guint32 new_capacity = old_capacity + growth;
+       const guint32 new_bucket_size = sizeof (**array->entries) * growth;
+       gpointer *entries;
+       if (array->capacity >= new_capacity)
+               return;
+       if (array->mem_type != -1)
+               entries = (gpointer*) sgen_alloc_internal_dynamic (new_bucket_size, array->mem_type, TRUE);
+       else
+               entries = (gpointer*) g_malloc0 (new_bucket_size);
+       if (array->bucket_alloc_callback)
+               array->bucket_alloc_callback (entries, new_bucket_size, TRUE);
+       /*
+        * The zeroing of the newly allocated bucket must be complete before storing
+        * the new bucket pointer.
+        */
+       mono_memory_write_barrier ();
+       if (InterlockedCompareExchangePointer ((volatile gpointer *)&array->entries [new_bucket], entries, NULL) == NULL) {
+               /*
+                * It must not be the case that we succeeded in setting the bucket
+                * pointer, while someone else succeeded in changing the capacity.
+                */
+               if (InterlockedCompareExchange ((volatile gint32 *)&array->capacity, new_capacity, old_capacity) != old_capacity)
+                       g_assert_not_reached ();
+               array->slot_hint = old_capacity;
+               return;
+       }
+       /* Someone beat us to the allocation. */
+       if (array->bucket_alloc_callback)
+               array->bucket_alloc_callback (entries, new_bucket_size, FALSE);
+       if (array->mem_type != -1)
+               sgen_free_internal_dynamic (entries, new_bucket_size, array->mem_type);
+       else
+               g_free (entries);
+}
+
+static guint32
+sgen_array_list_find_unset (SgenArrayList *array, guint32 capacity)
+{
+       if (!array->is_slot_set_func) {
+               guint32 next_slot = array->next_slot;
+               /* We can't lookup empty slots, use next_slot */
+               if (next_slot < capacity)
+                       return next_slot;
+       } else {
+               guint32 slot_hint = array->slot_hint;
+               guint32 index;
+               volatile gpointer *slot;
+
+               SGEN_ARRAY_LIST_FOREACH_SLOT_RANGE(array, slot_hint, capacity, slot, index) {
+                       if (!array->is_slot_set_func (slot))
+                               return index;
+               } SGEN_ARRAY_LIST_END_FOREACH_SLOT_RANGE;
+
+               SGEN_ARRAY_LIST_FOREACH_SLOT_RANGE (array, 0, slot_hint, slot, index) {
+                       if (!array->is_slot_set_func (slot))
+                               return index;
+               } SGEN_ARRAY_LIST_END_FOREACH_SLOT_RANGE;
+       }
+
+       return -1;
+}
+
+static void
+sgen_array_list_update_next_slot (SgenArrayList *array, guint32 new_index)
+{
+       if (!array->set_slot_func) {
+               /*
+                * If we don't have a custom setter it means we don't have thread
+                * safety requirements.
+                */
+               if (new_index >= array->next_slot)
+                       array->next_slot = new_index + 1;
+       } else {
+               guint32 old_next_slot;
+               /* Thread safe update */
+               do {
+                       old_next_slot = array->next_slot;
+                       if (new_index < old_next_slot)
+                               break;
+               } while (InterlockedCompareExchange ((volatile gint32 *)&array->next_slot, new_index + 1, old_next_slot) != old_next_slot);
+       }
+}
+
+guint32
+sgen_array_list_add (SgenArrayList *array, gpointer ptr, int data, gboolean increase_size_before_set)
+{
+       guint32 index, capacity;
+       volatile gpointer *slot;
+
+       if (!array->capacity)
+               sgen_array_list_grow (array, 0);
+retry:
+       capacity = array->capacity;
+       index = sgen_array_list_find_unset (array, capacity);
+       if (index == -1) {
+               sgen_array_list_grow (array, capacity);
+               goto retry;
+       }
+       array->slot_hint = index;
+
+       if (increase_size_before_set) {
+               sgen_array_list_update_next_slot (array, index);
+               mono_memory_write_barrier ();
+       }
+
+       slot = sgen_array_list_get_slot (array, index);
+       if (array->set_slot_func) {
+               if (!array->set_slot_func (slot, ptr, data))
+                       goto retry;
+       } else {
+               *slot = ptr;
+       }
+
+       if (!increase_size_before_set) {
+               mono_memory_write_barrier ();
+               sgen_array_list_update_next_slot (array, index);
+       }
+
+       return index;
+}
+
+/*
+ * Removes all NULL pointers from the array. Not thread safe
+ */
+void
+sgen_array_list_remove_nulls (SgenArrayList *array)
+{
+       guint32 start = 0;
+       volatile gpointer *slot;
+
+       SGEN_ARRAY_LIST_FOREACH_SLOT (array, slot) {
+               if (*slot)
+                       *sgen_array_list_get_slot (array, start++) = *slot;
+       } SGEN_ARRAY_LIST_END_FOREACH_SLOT;
+
+       mono_memory_write_barrier ();
+       array->next_slot = start;
+}
+
+/*
+ * Does a linear search through the pointer array to find `ptr`.  Returns the index if
+ * found, otherwise (guint32)-1.
+ */
+guint32
+sgen_array_list_find (SgenArrayList *array, gpointer ptr)
+{
+       volatile gpointer *slot;
+
+       SGEN_ARRAY_LIST_FOREACH_SLOT (array, slot) {
+               if (*slot == ptr)
+                       return __index;
+       } SGEN_ARRAY_LIST_END_FOREACH_SLOT;
+       return (guint32)-1;
+}
+
+#endif
diff --git a/mono/sgen/sgen-array-list.h b/mono/sgen/sgen-array-list.h
new file mode 100644 (file)
index 0000000..fb37009
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * sgen-array-list.h: A pointer array that doesn't use reallocs.
+ *
+ * Copyright (C) 2016 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_ARRAY_LIST_H__
+#define __MONO_SGEN_ARRAY_LIST_H__
+
+#include <glib.h>
+
+#define SGEN_ARRAY_LIST_BUCKETS (32)
+#define SGEN_ARRAY_LIST_MIN_BUCKET_BITS (5)
+#define SGEN_ARRAY_LIST_MIN_BUCKET_SIZE (1 << SGEN_ARRAY_LIST_MIN_BUCKET_BITS)
+
+typedef void (*SgenArrayListBucketAllocCallback) (gpointer *bucket, guint32 new_bucket_size, gboolean alloc);
+typedef gboolean (*SgenArrayListIsSlotSetFunc) (volatile gpointer *slot);
+typedef gboolean (*SgenArrayListSetSlotFunc) (volatile gpointer *slot, gpointer ptr, int data);
+
+/*
+ * 'entries' is an array of pointers to buckets of increasing size. The first
+ * bucket has size 'MIN_BUCKET_SIZE', and each bucket is twice the size of the
+ * previous, i.e.:
+ *
+ *           |-------|-- MIN_BUCKET_SIZE
+ *    [0] -> xxxxxxxx
+ *    [1] -> xxxxxxxxxxxxxxxx
+ *    [2] -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ *    ...
+ *
+ * 'slot_hint' denotes the position of the last allocation, so that the
+ * whole array needn't be searched on every allocation.
+ *
+ * The size of the spine, 'SGEN_ARRAY_LIST_BUCKETS', is chosen so
+ * that the maximum number of entries is no less than G_MAXUINT32.
+ */
+
+typedef struct {
+       volatile gpointer *volatile entries [SGEN_ARRAY_LIST_BUCKETS];
+       volatile guint32 capacity;
+       volatile guint32 slot_hint;
+       volatile guint32 next_slot;
+       SgenArrayListBucketAllocCallback bucket_alloc_callback;
+       SgenArrayListIsSlotSetFunc is_slot_set_func;
+       SgenArrayListSetSlotFunc set_slot_func;
+       int mem_type; /* sgen internal mem type or -1 for malloc allocation */
+} SgenArrayList;
+
+/*
+ * Computes floor(log2(index + MIN_BUCKET_SIZE)) - 1, giving the index
+ * of the bucket containing a slot.
+ */
+static inline guint32
+sgen_array_list_index_bucket (guint32 index)
+{
+#ifdef __GNUC__
+       return CHAR_BIT * sizeof (index) - __builtin_clz (index + SGEN_ARRAY_LIST_MIN_BUCKET_SIZE) - 1 - SGEN_ARRAY_LIST_MIN_BUCKET_BITS;
+#else
+       guint count = 0;
+       index += SGEN_ARRAY_LIST_MIN_BUCKET_SIZE;
+       while (index) {
+               ++count;
+               index >>= 1;
+       }
+       return count - 1 - SGEN_ARRAY_LIST_MIN_BUCKET_BITS;
+#endif
+}
+
+static inline guint32
+sgen_array_list_bucket_size (guint32 index)
+{
+       return 1 << (index + SGEN_ARRAY_LIST_MIN_BUCKET_BITS);
+}
+
+static inline void
+sgen_array_list_bucketize (guint32 index, guint32 *bucket, guint32 *offset)
+{
+       *bucket = sgen_array_list_index_bucket (index);
+       *offset = index - sgen_array_list_bucket_size (*bucket) + SGEN_ARRAY_LIST_MIN_BUCKET_SIZE;
+}
+
+static inline volatile gpointer *
+sgen_array_list_get_slot (SgenArrayList *array, guint32 index)
+{
+       guint32 bucket, offset;
+
+       SGEN_ASSERT (0, index < array->capacity, "Why are we accessing an entry that is not allocated");
+
+       sgen_array_list_bucketize (index, &bucket, &offset);
+       return &(array->entries [bucket] [offset]);
+}
+
+#define SGEN_ARRAY_LIST_INIT(bucket_alloc_callback, is_slot_set_func, set_slot_func, mem_type) { { NULL }, 0, 0, 0, (bucket_alloc_callback), (is_slot_set_func), (set_slot_func), (mem_type) }
+
+#define SGEN_ARRAY_LIST_FOREACH_SLOT(array, slot) {                    \
+       guint32 __bucket, __offset;                                     \
+       const guint32 __max_bucket = sgen_array_list_index_bucket ((array)->capacity); \
+       guint32 __index = 0;                                            \
+       const guint32 __next_slot = (array)->next_slot;                 \
+       for (__bucket = 0; __bucket < __max_bucket; ++__bucket) {       \
+               volatile gpointer *__entries = (array)->entries [__bucket]; \
+               for (__offset = 0; __offset < sgen_array_list_bucket_size (__bucket); ++__offset, ++__index) { \
+                       if (__index >= __next_slot)                     \
+                               break;                                  \
+                       slot = &__entries [__offset];
+
+#define SGEN_ARRAY_LIST_END_FOREACH_SLOT       } } }
+
+#define SGEN_ARRAY_LIST_FOREACH_SLOT_RANGE(array, begin, end, slot, index) {   \
+       for (index = (begin); index < (end); index++) {         \
+               guint32 __bucket, __offset;                             \
+               volatile gpointer *__entries;                           \
+               sgen_array_list_bucketize (index, &__bucket, &__offset); \
+               __entries = (array)->entries [__bucket];                \
+               slot = &__entries [__offset];
+
+#define SGEN_ARRAY_LIST_END_FOREACH_SLOT_RANGE } }
+
+guint32 sgen_array_list_add (SgenArrayList *array, gpointer ptr, int data, gboolean increase_size_before_set);
+guint32 sgen_array_list_find (SgenArrayList *array, gpointer ptr);
+void sgen_array_list_remove_nulls (SgenArrayList *array);
+
+#endif
index f88b933a68e49f9d3e9fc3f81cda93d1f9e2d51a..16f4ea6a7d9ae8c7066d33d793305b6e334d32af 100644 (file)
@@ -342,6 +342,29 @@ sgen_card_table_update_mod_union (guint8 *dest, char *obj, mword obj_size, size_
                *out_num_cards = num_cards;
 }
 
+/* Preclean cards and saves the cards that need to be scanned afterwards in cards_preclean */
+void
+sgen_card_table_preclean_mod_union (guint8 *cards, guint8 *cards_preclean, size_t num_cards)
+{
+       size_t i;
+
+       memcpy (cards_preclean, cards, num_cards);
+       for (i = 0; i < num_cards; i++) {
+               if (cards_preclean [i]) {
+                       cards [i] = 0;
+               }
+       }
+       /*
+        * When precleaning we need to make sure the card cleaning
+        * takes place before the object is scanned. If we don't
+        * do this we could finish scanning the object and, before
+        * the cleaning of the card takes place, another thread
+        * could dirty the object, mark the mod_union card only for
+        * us to clean it back, without scanning the object again.
+        */
+       mono_memory_barrier ();
+}
+
 #ifdef SGEN_HAVE_OVERLAPPING_CARDS
 
 static void
@@ -426,11 +449,11 @@ sgen_card_table_scan_remsets (ScanCopyContext ctx)
        sgen_card_table_clear_cards ();
 #endif
        SGEN_TV_GETTIME (atv);
-       sgen_get_major_collector ()->scan_card_table (FALSE, ctx);
+       sgen_get_major_collector ()->scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx);
        SGEN_TV_GETTIME (btv);
        last_major_scan_time = SGEN_TV_ELAPSED (atv, btv); 
        major_card_scan_time += last_major_scan_time;
-       sgen_los_scan_card_table (FALSE, ctx);
+       sgen_los_scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx);
        SGEN_TV_GETTIME (atv);
        last_los_scan_time = SGEN_TV_ELAPSED (btv, atv);
        los_card_scan_time += last_los_scan_time;
@@ -477,11 +500,11 @@ sgen_card_table_dump_obj_card (GCObject *object, size_t size, void *dummy)
 #endif
 
 void
-sgen_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, gboolean mod_union, ScanCopyContext ctx)
+sgen_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, ScanCopyContext ctx)
 {
        HEAVY_STAT (++large_objects);
 
-       if (sgen_client_cardtable_scan_object (obj, block_obj_size, cards, mod_union, ctx))
+       if (sgen_client_cardtable_scan_object (obj, block_obj_size, cards, ctx))
                return;
 
        HEAVY_STAT (++bloby_objects);
index bda77e4e925fd5149ee09a244322af12c2c9bbaa..fde8ac11eff721cd7a961bc2d43a8d8f11ab9cd3 100644 (file)
@@ -31,7 +31,7 @@ void sgen_card_table_reset_region (mword start, mword end);
 void* sgen_card_table_align_pointer (void *ptr);
 void sgen_card_table_mark_range (mword address, mword size);
 void sgen_cardtable_scan_object (GCObject *obj, mword obj_size, guint8 *cards,
-               gboolean mod_union, ScanCopyContext ctx);
+               ScanCopyContext ctx);
 
 gboolean sgen_card_table_get_card_data (guint8 *dest, mword address, mword cards);
 
@@ -40,6 +40,7 @@ void sgen_card_table_free_mod_union (guint8 *mod_union, char *obj, mword obj_siz
 
 void sgen_card_table_update_mod_union_from_cards (guint8 *dest, guint8 *start_card, size_t num_cards);
 void sgen_card_table_update_mod_union (guint8 *dest, char *obj, mword obj_size, size_t *out_num_cards);
+void sgen_card_table_preclean_mod_union (guint8 *cards, guint8 *cards_preclean, size_t num_cards);
 
 guint8* sgen_get_card_table_configuration (int *shift_bits, gpointer *mask);
 
index edf9dde8439e1f1cd4bef151e6dde539d853caf3..a975040734d043e23ff61677d7d3d4772b4f5fc8 100644 (file)
@@ -105,7 +105,7 @@ void sgen_client_ensure_weak_gchandles_accessible (void);
  * parts of the object based on which cards are marked, do so and return TRUE.  Otherwise,
  * return FALSE.
  */
-gboolean sgen_client_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, gboolean mod_union, ScanCopyContext ctx);
+gboolean sgen_client_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, ScanCopyContext ctx);
 
 /*
  * Called after nursery objects have been pinned.  No action is necessary.
index 89af85f4387d92646edc38554aa138dd0b9dbdec..2274febcb108a57359ff380aec845c0554feb08f 100644 (file)
@@ -245,6 +245,8 @@ static gboolean do_verify_nursery = FALSE;
 static gboolean do_dump_nursery_content = FALSE;
 static gboolean enable_nursery_canaries = FALSE;
 
+static gboolean precleaning_enabled = TRUE;
+
 #ifdef HEAVY_STATISTICS
 guint64 stat_objects_alloced_degraded = 0;
 guint64 stat_bytes_alloced_degraded = 0;
@@ -1167,7 +1169,7 @@ finish_gray_stack (int generation, ScanCopyContext ctx)
        sgen_client_clear_togglerefs (start_addr, end_addr, ctx);
 
        TV_GETTIME (btv);
-       SGEN_LOG (2, "Finalize queue handling scan for %s generation: %ld usecs %d ephemeron rounds", generation_name (generation), TV_ELAPSED (atv, btv), ephemeron_rounds);
+       SGEN_LOG (2, "Finalize queue handling scan for %s generation: %lld usecs %d ephemeron rounds", generation_name (generation), TV_ELAPSED (atv, btv), ephemeron_rounds);
 
        /*
         * handle disappearing links
@@ -1392,7 +1394,7 @@ job_scan_major_mod_union_card_table (void *worker_data_untyped, SgenThreadPoolJo
        ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (job_data->ops, sgen_workers_get_job_gray_queue (worker_data));
 
        g_assert (concurrent_collection_in_progress);
-       major_collector.scan_card_table (TRUE, ctx);
+       major_collector.scan_card_table (CARDTABLE_SCAN_MOD_UNION, ctx);
 }
 
 static void
@@ -1403,7 +1405,20 @@ job_scan_los_mod_union_card_table (void *worker_data_untyped, SgenThreadPoolJob
        ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (job_data->ops, sgen_workers_get_job_gray_queue (worker_data));
 
        g_assert (concurrent_collection_in_progress);
-       sgen_los_scan_card_table (TRUE, ctx);
+       sgen_los_scan_card_table (CARDTABLE_SCAN_MOD_UNION, ctx);
+}
+
+static void
+job_mod_union_preclean (void *worker_data_untyped, SgenThreadPoolJob *job)
+{
+       WorkerData *worker_data = (WorkerData *)worker_data_untyped;
+       ScanJob *job_data = (ScanJob*)job;
+       ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (job_data->ops, sgen_workers_get_job_gray_queue (worker_data));
+
+       g_assert (concurrent_collection_in_progress);
+
+       major_collector.scan_card_table (CARDTABLE_SCAN_MOD_UNION_PRECLEAN, ctx);
+       sgen_los_scan_card_table (CARDTABLE_SCAN_MOD_UNION_PRECLEAN, ctx);
 }
 
 static void
@@ -1546,7 +1561,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark)
 
        TV_GETTIME (atv);
        time_minor_pinning += TV_ELAPSED (btv, atv);
-       SGEN_LOG (2, "Finding pinned pointers: %zd in %ld usecs", sgen_get_pinned_count (), TV_ELAPSED (btv, atv));
+       SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), TV_ELAPSED (btv, atv));
        SGEN_LOG (4, "Start scan with %zd pinned objects", sgen_get_pinned_count ());
 
        sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan remset", job_remembered_set_scan, sizeof (ScanJob));
@@ -1556,7 +1571,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark)
        /* we don't have complete write barrier yet, so we scan all the old generation sections */
        TV_GETTIME (btv);
        time_minor_scan_remsets += TV_ELAPSED (atv, btv);
-       SGEN_LOG (2, "Old generation scan: %ld usecs", TV_ELAPSED (atv, btv));
+       SGEN_LOG (2, "Old generation scan: %lld usecs", TV_ELAPSED (atv, btv));
 
        sgen_pin_stats_print_class_stats ();
 
@@ -1597,7 +1612,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark)
        sgen_client_binary_protocol_reclaim_end (GENERATION_NURSERY);
        TV_GETTIME (btv);
        time_minor_fragment_creation += TV_ELAPSED (atv, btv);
-       SGEN_LOG (2, "Fragment creation: %ld usecs, %lu bytes available", TV_ELAPSED (atv, btv), (unsigned long)fragment_total);
+       SGEN_LOG (2, "Fragment creation: %lld usecs, %lu bytes available", TV_ELAPSED (atv, btv), (unsigned long)fragment_total);
 
        if (consistency_check_at_minor_collection)
                sgen_check_major_refs ();
@@ -1709,8 +1724,20 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, CopyOrMarkFromRootsMod
        sgen_init_pinning ();
        SGEN_LOG (6, "Collecting pinned addresses");
        pin_from_roots ((void*)lowest_heap_address, (void*)highest_heap_address, ctx);
-
+       if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
+               /* Pin cemented objects that were forced */
+               sgen_pin_cemented_objects ();
+       }
        sgen_optimize_pin_queue ();
+       if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
+               /*
+                * Cemented objects that are in the pinned list will be marked. When
+                * marking concurrently we won't mark mod-union cards for these objects.
+                * Instead they will remain cemented until the next major collection,
+                * when we will recheck if they are still pinned in the roots.
+                */
+               sgen_cement_force_pinned ();
+       }
 
        sgen_client_collecting_major_1 ();
 
@@ -1762,24 +1789,19 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, CopyOrMarkFromRootsMod
 
        TV_GETTIME (btv);
        time_major_pinning += TV_ELAPSED (atv, btv);
-       SGEN_LOG (2, "Finding pinned pointers: %zd in %ld usecs", sgen_get_pinned_count (), TV_ELAPSED (atv, btv));
+       SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), TV_ELAPSED (atv, btv));
        SGEN_LOG (4, "Start scan with %zd pinned objects", sgen_get_pinned_count ());
 
        major_collector.init_to_space ();
 
-       /*
-        * The concurrent collector doesn't move objects, neither on
-        * the major heap nor in the nursery, so we can mark even
-        * before pinning has finished.  For the non-concurrent
-        * collector we start the workers after pinning.
-        */
-       if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
-               SGEN_ASSERT (0, sgen_workers_all_done (), "Why are the workers not done when we start or finish a major collection?");
-               sgen_workers_start_all_workers (object_ops);
-               gray_queue_enable_redirect (WORKERS_DISTRIBUTE_GRAY_QUEUE);
-       } else if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
+       SGEN_ASSERT (0, sgen_workers_all_done (), "Why are the workers not done when we start or finish a major collection?");
+       if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
                if (sgen_workers_have_idle_work ()) {
-                       sgen_workers_start_all_workers (object_ops);
+                       /*
+                        * We force the finish of the worker with the new object ops context
+                        * which can also do copying. We need to have finished pinning.
+                        */
+                       sgen_workers_start_all_workers (object_ops, NULL);
                        sgen_workers_join ();
                }
        }
@@ -1795,15 +1817,29 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, CopyOrMarkFromRootsMod
 
        sgen_client_collecting_major_3 (&fin_ready_queue, &critical_fin_queue);
 
-       /*
-        * FIXME: is this the right context?  It doesn't seem to contain a copy function
-        * unless we're concurrent.
-        */
-       enqueue_scan_from_roots_jobs (heap_start, heap_end, object_ops, mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT);
+       enqueue_scan_from_roots_jobs (heap_start, heap_end, object_ops, FALSE);
 
        TV_GETTIME (btv);
        time_major_scan_roots += TV_ELAPSED (atv, btv);
 
+       /*
+        * We start the concurrent worker after pinning and after we scanned the roots
+        * in order to make sure that the worker does not finish before handling all
+        * the roots.
+        */
+       if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
+               if (precleaning_enabled) {
+                       ScanJob *sj;
+                       /* Mod union preclean job */
+                       sj = (ScanJob*)sgen_thread_pool_job_alloc ("preclean mod union cardtable", job_mod_union_preclean, sizeof (ScanJob));
+                       sj->ops = object_ops;
+                       sgen_workers_start_all_workers (object_ops, &sj->job);
+               } else {
+                       sgen_workers_start_all_workers (object_ops, NULL);
+               }
+               gray_queue_enable_redirect (WORKERS_DISTRIBUTE_GRAY_QUEUE);
+       }
+
        if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
                ScanJob *sj;
 
@@ -1827,11 +1863,6 @@ static void
 major_finish_copy_or_mark (CopyOrMarkFromRootsMode mode)
 {
        if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
-               /*
-                * Prepare the pin queue for the next collection.  Since pinning runs on the worker
-                * threads we must wait for the jobs to finish before we can reset it.
-                */
-               sgen_workers_wait_for_jobs_finished ();
                sgen_finish_pinning ();
 
                sgen_pin_stats_reset ();
@@ -2931,6 +2962,15 @@ sgen_gc_init (void)
                                continue;
                        }
 
+                       if (!strcmp (opt, "precleaning")) {
+                               precleaning_enabled = TRUE;
+                               continue;
+                       }
+                       if (!strcmp (opt, "no-precleaning")) {
+                               precleaning_enabled = FALSE;
+                               continue;
+                       }
+
                        if (major_collector.handle_gc_param && major_collector.handle_gc_param (opt))
                                continue;
 
index 4b2f895d890badc5f42157ebe4009f57211ad1b4..381e24d6f451da83c8450b777fe4f706d83b1de3 100644 (file)
@@ -407,12 +407,14 @@ gboolean sgen_is_worker_thread (MonoNativeThreadId thread);
 typedef void (*CopyOrMarkObjectFunc) (GCObject**, SgenGrayQueue*);
 typedef void (*ScanObjectFunc) (GCObject *obj, SgenDescriptor desc, SgenGrayQueue*);
 typedef void (*ScanVTypeFunc) (GCObject *full_object, char *start, SgenDescriptor desc, SgenGrayQueue* BINARY_PROTOCOL_ARG (size_t size));
+typedef void (*ScanPtrFieldFunc) (GCObject *obj, GCObject **ptr, SgenGrayQueue* queue);
 typedef gboolean (*DrainGrayStackFunc) (SgenGrayQueue *queue);
 
 typedef struct {
        CopyOrMarkObjectFunc copy_or_mark_object;
        ScanObjectFunc scan_object;
        ScanVTypeFunc scan_vtype;
+       ScanPtrFieldFunc scan_ptr_field;
        /* Drain stack optimized for the above functions */
        DrainGrayStackFunc drain_gray_stack;
        /*FIXME add allocation function? */
@@ -595,6 +597,12 @@ typedef struct
        size_t num_unique_scanned_objects;
 } ScannedObjectCounts;
 
+typedef enum {
+       CARDTABLE_SCAN_GLOBAL = 0,
+       CARDTABLE_SCAN_MOD_UNION = 1,
+       CARDTABLE_SCAN_MOD_UNION_PRECLEAN = CARDTABLE_SCAN_MOD_UNION | 2,
+} CardTableScanType;
+
 typedef struct _SgenMajorCollector SgenMajorCollector;
 struct _SgenMajorCollector {
        size_t section_size;
@@ -624,7 +632,7 @@ struct _SgenMajorCollector {
        void (*free_non_pinned_object) (GCObject *obj, size_t size);
        void (*pin_objects) (SgenGrayQueue *queue);
        void (*pin_major_object) (GCObject *obj, SgenGrayQueue *queue);
-       void (*scan_card_table) (gboolean mod_union, ScanCopyContext ctx);
+       void (*scan_card_table) (CardTableScanType scan_type, ScanCopyContext ctx);
        void (*iterate_live_block_ranges) (sgen_cardtable_block_callback callback);
        void (*update_cardtable_mod_union) (void);
        void (*init_to_space) (void);
@@ -850,7 +858,7 @@ void sgen_los_sweep (void);
 gboolean sgen_ptr_is_in_los (char *ptr, char **start);
 void sgen_los_iterate_objects (IterateObjectCallbackFunc cb, void *user_data);
 void sgen_los_iterate_live_block_ranges (sgen_cardtable_block_callback callback);
-void sgen_los_scan_card_table (gboolean mod_union, ScanCopyContext ctx);
+void sgen_los_scan_card_table (CardTableScanType scan_type, ScanCopyContext ctx);
 void sgen_los_update_cardtable_mod_union (void);
 void sgen_los_count_cards (long long *num_total_cards, long long *num_marked_cards);
 gboolean sgen_los_is_valid_object (char *object);
index 9d00c397b9d6fb996f780a454aa56eb8647c65c2..68be8b5c2431cbea8b823d614f31a821b232d54d 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "mono/sgen/sgen-gc.h"
 #include "mono/sgen/sgen-client.h"
+#include "mono/sgen/sgen-array-list.h"
 #include "mono/utils/mono-membar.h"
 
 #ifdef HEAVY_STATISTICS
@@ -29,26 +30,9 @@ static volatile guint32 stat_gc_handles_allocated = 0;
 static volatile guint32 stat_gc_handles_max_allocated = 0;
 #endif
 
-#define BUCKETS (32 - MONO_GC_HANDLE_TYPE_SHIFT)
-#define MIN_BUCKET_BITS (5)
-#define MIN_BUCKET_SIZE (1 << MIN_BUCKET_BITS)
-
 /*
  * A table of GC handle data, implementing a simple lock-free bitmap allocator.
  *
- * 'entries' is an array of pointers to buckets of increasing size. The first
- * bucket has size 'MIN_BUCKET_SIZE', and each bucket is twice the size of the
- * previous, i.e.:
- *
- *           |-------|-- MIN_BUCKET_SIZE
- *    [0] -> xxxxxxxx
- *    [1] -> xxxxxxxxxxxxxxxx
- *    [2] -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- *    ...
- *
- * The size of the spine, 'BUCKETS', is chosen so that the maximum number of
- * entries is no less than the maximum index value of a GC handle.
- *
  * Each entry in a bucket is a pointer with two tag bits: if
  * 'GC_HANDLE_OCCUPIED' returns true for a slot, then the slot is occupied; if
  * so, then 'GC_HANDLE_VALID' gives whether the entry refers to a valid (1) or
@@ -56,51 +40,13 @@ static volatile guint32 stat_gc_handles_max_allocated = 0;
  * object pointer. If the reference is NULL, and 'GC_HANDLE_TYPE_IS_WEAK' is
  * true for 'type', then the pointer is a metadata pointer--this allows us to
  * retrieve the domain ID of an expired weak reference in Mono.
- *
- * Finally, 'slot_hint' denotes the position of the last allocation, so that the
- * whole array needn't be searched on every allocation.
  */
 
 typedef struct {
-       volatile gpointer *volatile entries [BUCKETS];
-       volatile guint32 capacity;
-       volatile guint32 slot_hint;
-       volatile guint32 max_index;
+       SgenArrayList entries_array;
        guint8 type;
 } HandleData;
 
-static inline guint
-bucket_size (guint index)
-{
-       return 1 << (index + MIN_BUCKET_BITS);
-}
-
-/* Computes floor(log2(index + MIN_BUCKET_SIZE)) - 1, giving the index
- * of the bucket containing a slot.
- */
-static inline guint
-index_bucket (guint index)
-{
-#ifdef __GNUC__
-       return CHAR_BIT * sizeof (index) - __builtin_clz (index + MIN_BUCKET_SIZE) - 1 - MIN_BUCKET_BITS;
-#else
-       guint count = 0;
-       index += MIN_BUCKET_SIZE;
-       while (index) {
-               ++count;
-               index >>= 1;
-       }
-       return count - 1 - MIN_BUCKET_BITS;
-#endif
-}
-
-static inline void
-bucketize (guint index, guint *bucket, guint *offset)
-{
-       *bucket = index_bucket (index);
-       *offset = index - bucket_size (*bucket) + MIN_BUCKET_SIZE;
-}
-
 static void
 protocol_gchandle_update (int handle_type, gpointer link, gpointer old_value, gpointer new_value)
 {
@@ -136,21 +82,38 @@ try_set_slot (volatile gpointer *slot, GCObject *obj, gpointer old, GCHandleType
        return NULL;
 }
 
+static inline gboolean
+is_slot_set (volatile gpointer *slot)
+{
+       gpointer entry = *slot;
+       if (MONO_GC_HANDLE_OCCUPIED (entry))
+               return TRUE;
+       return FALSE;
+}
+
 /* Try to claim a slot by setting its occupied bit. */
 static inline gboolean
-try_occupy_slot (HandleData *handles, guint bucket, guint offset, GCObject *obj, gboolean track)
+try_occupy_slot (volatile gpointer *slot, gpointer obj, int data)
 {
-       volatile gpointer *link_addr = &(handles->entries [bucket] [offset]);
-       if (MONO_GC_HANDLE_OCCUPIED (*link_addr))
+       if (is_slot_set (slot))
                return FALSE;
-       return try_set_slot (link_addr, obj, NULL, (GCHandleType)handles->type) != NULL;
+       return try_set_slot (slot, (GCObject *)obj, NULL, (GCHandleType)data) != NULL;
+}
+
+static void
+bucket_alloc_callback (gpointer *bucket, guint32 new_bucket_size, gboolean alloc)
+{
+       if (alloc)
+               sgen_register_root ((char *)bucket, new_bucket_size, SGEN_DESCRIPTOR_NULL, ROOT_TYPE_PINNED, MONO_ROOT_SOURCE_GC_HANDLE, "pinned gc handles");
+       else
+               sgen_deregister_root ((char *)bucket);
 }
 
 static HandleData gc_handles [] = {
-       { { NULL }, 0, 0, 0, (HANDLE_WEAK) },
-       { { NULL }, 0, 0, 0, (HANDLE_WEAK_TRACK) },
-       { { NULL }, 0, 0, 0, (HANDLE_NORMAL) },
-       { { NULL }, 0, 0, 0, (HANDLE_PINNED) }
+       { SGEN_ARRAY_LIST_INIT (NULL, is_slot_set, try_occupy_slot, -1), (HANDLE_WEAK) },
+       { SGEN_ARRAY_LIST_INIT (NULL, is_slot_set, try_occupy_slot, -1), (HANDLE_WEAK_TRACK) },
+       { SGEN_ARRAY_LIST_INIT (NULL, is_slot_set, try_occupy_slot, -1), (HANDLE_NORMAL) },
+       { SGEN_ARRAY_LIST_INIT (bucket_alloc_callback, is_slot_set, try_occupy_slot, -1), (HANDLE_PINNED) }
 };
 
 static HandleData *
@@ -164,102 +127,27 @@ void
 sgen_mark_normal_gc_handles (void *addr, SgenUserMarkFunc mark_func, void *gc_data)
 {
        HandleData *handles = gc_handles_for_type (HANDLE_NORMAL);
-       size_t bucket, offset;
-       const guint max_bucket = index_bucket (handles->capacity);
-       guint32 index = 0;
-       const guint32 max_index = handles->max_index;
-       for (bucket = 0; bucket < max_bucket; ++bucket) {
-               volatile gpointer *entries = handles->entries [bucket];
-               for (offset = 0; offset < bucket_size (bucket); ++offset, ++index) {
-                       volatile gpointer *entry;
-                       gpointer hidden, revealed;
-                       /* No need to iterate beyond the largest index ever allocated. */
-                       if (index > max_index)
-                               return;
-                       entry = &entries [offset];
-                       hidden = *entry;
-                       revealed = MONO_GC_REVEAL_POINTER (hidden, FALSE);
-                       if (!MONO_GC_HANDLE_IS_OBJECT_POINTER (hidden))
-                               continue;
-                       mark_func ((MonoObject **)&revealed, gc_data);
-                       g_assert (revealed);
-                       *entry = MONO_GC_HANDLE_OBJECT_POINTER (revealed, FALSE);
-               }
-       }
+       SgenArrayList *array = &handles->entries_array;
+       volatile gpointer *slot;
+       gpointer hidden, revealed;
+
+       SGEN_ARRAY_LIST_FOREACH_SLOT (array, slot) {
+               hidden = *slot;
+               revealed = MONO_GC_REVEAL_POINTER (hidden, FALSE);
+               if (!MONO_GC_HANDLE_IS_OBJECT_POINTER (hidden))
+                       continue;
+               mark_func ((MonoObject **)&revealed, gc_data);
+               g_assert (revealed);
+               *slot = MONO_GC_HANDLE_OBJECT_POINTER (revealed, FALSE);
+       } SGEN_ARRAY_LIST_END_FOREACH_SLOT;
 }
 
-static guint
-handle_data_find_unset (HandleData *handles, guint32 begin, guint32 end)
-{
-       guint index;
-       gint delta = begin < end ? +1 : -1;
-       for (index = begin; index < end; index += delta) {
-               guint bucket, offset;
-               volatile gpointer *entries;
-               bucketize (index, &bucket, &offset);
-               entries = handles->entries [bucket];
-               g_assert (entries);
-               if (!MONO_GC_HANDLE_OCCUPIED (entries [offset]))
-                       return index;
-       }
-       return -1;
-}
-
-/* Adds a bucket if necessary and possible. */
-static void
-handle_data_grow (HandleData *handles, guint32 old_capacity)
-{
-       const guint new_bucket = index_bucket (old_capacity);
-       const guint32 growth = bucket_size (new_bucket);
-       const guint32 new_capacity = old_capacity + growth;
-       gpointer *entries;
-       const size_t new_bucket_size = sizeof (**handles->entries) * growth;
-       if (handles->capacity >= new_capacity)
-               return;
-       entries = (gpointer *)g_malloc0 (new_bucket_size);
-       if (handles->type == HANDLE_PINNED)
-               sgen_register_root ((char *)entries, new_bucket_size, SGEN_DESCRIPTOR_NULL, ROOT_TYPE_PINNED, MONO_ROOT_SOURCE_GC_HANDLE, "pinned gc handles");
-       /* The zeroing of the newly allocated bucket must be complete before storing
-        * the new bucket pointer.
-        */
-       mono_memory_write_barrier ();
-       if (InterlockedCompareExchangePointer ((volatile gpointer *)&handles->entries [new_bucket], entries, NULL) == NULL) {
-               /* It must not be the case that we succeeded in setting the bucket
-                * pointer, while someone else succeeded in changing the capacity.
-                */
-               if (InterlockedCompareExchange ((volatile gint32 *)&handles->capacity, new_capacity, old_capacity) != old_capacity)
-                       g_assert_not_reached ();
-               handles->slot_hint = old_capacity;
-               return;
-       }
-       /* Someone beat us to the allocation. */
-       if (handles->type == HANDLE_PINNED)
-               sgen_deregister_root ((char *)entries);
-       g_free (entries);
-}
 
 static guint32
 alloc_handle (HandleData *handles, GCObject *obj, gboolean track)
 {
-       guint index;
-       guint32 res;
-       guint bucket, offset;
-       guint32 capacity;
-       guint32 slot_hint;
-       guint32 max_index;
-       if (!handles->capacity)
-               handle_data_grow (handles, 0);
-retry:
-       capacity = handles->capacity;
-       slot_hint = handles->slot_hint;
-       index = handle_data_find_unset (handles, slot_hint, capacity);
-       if (index == -1)
-               index = handle_data_find_unset (handles, 0, slot_hint);
-       if (index == -1) {
-               handle_data_grow (handles, capacity);
-               goto retry;
-       }
-       handles->slot_hint = index;
+       guint32 res, index;
+       SgenArrayList *array = &handles->entries_array;
 
        /*
         * If a GC happens shortly after a new bucket is allocated, the entire
@@ -267,21 +155,13 @@ retry:
         * we track the maximum index seen so far, so that we can skip the empty
         * slots.
         *
-        * Note that we update `max_index` before we even try occupying the
+        * Note that we update `next_slot` before we even try occupying the
         * slot.  If we did it the other way around and a GC happened in
         * between, the GC wouldn't know that the slot was occupied.  This is
         * not a huge deal since `obj` is on the stack and thus pinned anyway,
         * but hopefully some day it won't be anymore.
         */
-       do {
-               max_index = handles->max_index;
-               if (index <= max_index)
-                       break;
-       } while (InterlockedCompareExchange ((volatile gint32 *)&handles->max_index, index, max_index) != max_index);
-
-       bucketize (index, &bucket, &offset);
-       if (!try_occupy_slot (handles, bucket, offset, obj, track))
-               goto retry;
+       index = sgen_array_list_add (array, obj, handles->type, TRUE);
 #ifdef HEAVY_STATISTICS
        InterlockedIncrement ((volatile gint32 *)&stat_gc_handles_allocated);
        if (stat_gc_handles_allocated > stat_gc_handles_max_allocated)
@@ -308,38 +188,28 @@ void
 sgen_gchandle_iterate (GCHandleType handle_type, int max_generation, SgenGCHandleIterateCallback callback, gpointer user)
 {
        HandleData *handle_data = gc_handles_for_type (handle_type);
-       size_t bucket, offset;
-       guint max_bucket = index_bucket (handle_data->capacity);
-       guint32 index = 0;
-       guint32 max_index = handle_data->max_index;
+       SgenArrayList *array = &handle_data->entries_array;
+       gpointer hidden, result, occupied;
+       volatile gpointer *slot;
+
        /* If a new bucket has been allocated, but the capacity has not yet been
         * increased, nothing can yet have been allocated in the bucket because the
         * world is stopped, so we shouldn't miss any handles during iteration.
         */
-       for (bucket = 0; bucket < max_bucket; ++bucket) {
-               volatile gpointer *entries = handle_data->entries [bucket];
-               for (offset = 0; offset < bucket_size (bucket); ++offset, ++index) {
-                       gpointer hidden;
-                       gpointer result;
-                       /* Table must contain no garbage pointers. */
-                       gboolean occupied;
-                       /* No need to iterate beyond the largest index ever allocated. */
-                       if (index > max_index)
-                                       return;
-                       hidden = entries [offset];
-                       occupied = MONO_GC_HANDLE_OCCUPIED (hidden);
-                       g_assert (hidden ? occupied : !occupied);
-                       if (!occupied)
-                               continue;
-                       result = callback (hidden, handle_type, max_generation, user);
-                       if (result)
-                               SGEN_ASSERT (0, MONO_GC_HANDLE_OCCUPIED (result), "Why did the callback return an unoccupied entry?");
-                       else
-                               HEAVY_STAT (InterlockedDecrement ((volatile gint32 *)&stat_gc_handles_allocated));
-                       protocol_gchandle_update (handle_type, (gpointer)&entries [offset], hidden, result);
-                       entries [offset] = result;
-               }
-       }
+       SGEN_ARRAY_LIST_FOREACH_SLOT (array, slot) {
+               hidden = *slot;
+               occupied = (gpointer) MONO_GC_HANDLE_OCCUPIED (hidden);
+               g_assert (hidden ? !!occupied : !occupied);
+               if (!occupied)
+                       continue;
+               result = callback (hidden, handle_type, max_generation, user);
+               if (result)
+                       SGEN_ASSERT (0, MONO_GC_HANDLE_OCCUPIED (result), "Why did the callback return an unoccupied entry?");
+               else
+                       HEAVY_STAT (InterlockedDecrement ((volatile gint32 *)&stat_gc_handles_allocated));
+               protocol_gchandle_update (handle_type, (gpointer)slot, hidden, result);
+               *slot = result;
+       } SGEN_ARRAY_LIST_END_FOREACH_SLOT;
 }
 
 /**
@@ -453,43 +323,40 @@ mono_gchandle_get_target (guint32 gchandle)
        /* Invalid handles are possible; accessing one should produce NULL. (#34276) */
        if (!handles)
                return NULL;
-       guint bucket, offset;
-       g_assert (index < handles->capacity);
-       bucketize (index, &bucket, &offset);
-       return link_get (&handles->entries [bucket] [offset], MONO_GC_HANDLE_TYPE_IS_WEAK (type));
+       return link_get (sgen_array_list_get_slot (&handles->entries_array, index), MONO_GC_HANDLE_TYPE_IS_WEAK (type));
 }
 
 void
 sgen_gchandle_set_target (guint32 gchandle, GCObject *obj)
 {
-       guint index = MONO_GC_HANDLE_SLOT (gchandle);
+       guint32 index = MONO_GC_HANDLE_SLOT (gchandle);
        GCHandleType type = MONO_GC_HANDLE_TYPE (gchandle);
        HandleData *handles = gc_handles_for_type (type);
+       volatile gpointer *slot;
+       gpointer entry;
+
        if (!handles)
                return;
-       guint bucket, offset;
-       gpointer slot;
 
-       g_assert (index < handles->capacity);
-       bucketize (index, &bucket, &offset);
+       slot = sgen_array_list_get_slot (&handles->entries_array, index);
 
        do {
-               slot = handles->entries [bucket] [offset];
-               SGEN_ASSERT (0, MONO_GC_HANDLE_OCCUPIED (slot), "Why are we setting the target on an unoccupied slot?");
-       } while (!try_set_slot (&handles->entries [bucket] [offset], obj, slot, (GCHandleType)handles->type));
+               entry = *slot;
+               SGEN_ASSERT (0, MONO_GC_HANDLE_OCCUPIED (entry), "Why are we setting the target on an unoccupied slot?");
+       } while (!try_set_slot (slot, obj, entry, (GCHandleType)handles->type));
 }
 
 static gpointer
-mono_gchandle_slot_metadata (volatile gpointer *slot_addr, gboolean is_weak)
+mono_gchandle_slot_metadata (volatile gpointer *slot, gboolean is_weak)
 {
-       gpointer slot;
+       gpointer entry;
        gpointer metadata;
 retry:
-       slot = *slot_addr;
-       if (!MONO_GC_HANDLE_OCCUPIED (slot))
+       entry = *slot;
+       if (!MONO_GC_HANDLE_OCCUPIED (entry))
                return NULL;
-       if (MONO_GC_HANDLE_IS_OBJECT_POINTER (slot)) {
-               GCObject *obj = (GCObject *)MONO_GC_REVEAL_POINTER (slot, is_weak);
+       if (MONO_GC_HANDLE_IS_OBJECT_POINTER (entry)) {
+               GCObject *obj = (GCObject *)MONO_GC_REVEAL_POINTER (entry, is_weak);
                /* See note [dummy use]. */
                sgen_dummy_use (obj);
                /*
@@ -497,14 +364,14 @@ retry:
                 * at this point and recompute it later, in which case we would still use
                 * it.
                 */
-               if (*slot_addr != slot)
+               if (*slot != entry)
                        goto retry;
                return sgen_client_metadata_for_object (obj);
        }
-       metadata = MONO_GC_REVEAL_POINTER (slot, is_weak);
+       metadata = MONO_GC_REVEAL_POINTER (entry, is_weak);
        /* See note [dummy use]. */
        sgen_dummy_use (metadata);
-       if (*slot_addr != slot)
+       if (*slot != entry)
                goto retry;
        return metadata;
 }
@@ -512,16 +379,19 @@ retry:
 gpointer
 sgen_gchandle_get_metadata (guint32 gchandle)
 {
-       guint index = MONO_GC_HANDLE_SLOT (gchandle);
+       guint32 index = MONO_GC_HANDLE_SLOT (gchandle);
        GCHandleType type = MONO_GC_HANDLE_TYPE (gchandle);
        HandleData *handles = gc_handles_for_type (type);
+       volatile gpointer *slot;
+
        if (!handles)
                return NULL;
-       guint bucket, offset;
-       if (index >= handles->capacity)
+       if (index >= handles->entries_array.capacity)
                return NULL;
-       bucketize (index, &bucket, &offset);
-       return mono_gchandle_slot_metadata (&handles->entries [bucket] [offset], MONO_GC_HANDLE_TYPE_IS_WEAK (type));
+
+       slot = sgen_array_list_get_slot (&handles->entries_array, index);
+
+       return mono_gchandle_slot_metadata (slot, MONO_GC_HANDLE_TYPE_IS_WEAK (type));
 }
 
 /**
@@ -535,18 +405,20 @@ sgen_gchandle_get_metadata (guint32 gchandle)
 void
 mono_gchandle_free (guint32 gchandle)
 {
-       guint index = MONO_GC_HANDLE_SLOT (gchandle);
+       guint32 index = MONO_GC_HANDLE_SLOT (gchandle);
        GCHandleType type = MONO_GC_HANDLE_TYPE (gchandle);
        HandleData *handles = gc_handles_for_type (type);
+       volatile gpointer *slot;
+       gpointer entry;
        if (!handles)
                return;
-       guint bucket, offset;
-       gpointer slot;
-       bucketize (index, &bucket, &offset);
-       slot = handles->entries [bucket] [offset];
-       if (index < handles->capacity && MONO_GC_HANDLE_OCCUPIED (slot)) {
-               handles->entries [bucket] [offset] = NULL;
-               protocol_gchandle_update (handles->type, (gpointer)&handles->entries [bucket] [offset], slot, NULL);
+
+       slot = sgen_array_list_get_slot (&handles->entries_array, index);
+       entry = *slot;
+
+       if (index < handles->entries_array.capacity && MONO_GC_HANDLE_OCCUPIED (entry)) {
+               *slot = NULL;
+               protocol_gchandle_update (handles->type, (gpointer)slot, entry, NULL);
                HEAVY_STAT (InterlockedDecrement ((volatile gint32 *)&stat_gc_handles_allocated));
        } else {
                /* print a warning? */
index a89ec99fe353517580f0695f6d45e68859a18101..eb620281410ed984d4efb4aa96024afa633c28e3 100644 (file)
@@ -73,6 +73,7 @@ struct _LOSSection {
        unsigned char *free_chunk_map;
 };
 
+/* We allow read only access on the list while sweep is not running */
 LOSObject *los_object_list = NULL;
 mword los_memory_usage = 0;
 
@@ -410,6 +411,11 @@ sgen_los_alloc_large_inner (GCVTable vtable, size_t size)
        *vtslot = vtable;
        sgen_update_heap_boundaries ((mword)obj->data, (mword)obj->data + size);
        obj->next = los_object_list;
+       /*
+        * We need a memory barrier so we don't expose as head of the los object list
+        * a LOSObject that doesn't have its fields initialized.
+        */
+       mono_memory_write_barrier ();
        los_object_list = obj;
        los_memory_usage += size;
        los_num_objects++;
@@ -617,30 +623,44 @@ get_cardtable_mod_union_for_object (LOSObject *obj)
 }
 
 void
-sgen_los_scan_card_table (gboolean mod_union, ScanCopyContext ctx)
+sgen_los_scan_card_table (CardTableScanType scan_type, ScanCopyContext ctx)
 {
        LOSObject *obj;
 
-       binary_protocol_los_card_table_scan_start (sgen_timestamp (), mod_union);
+       binary_protocol_los_card_table_scan_start (sgen_timestamp (), scan_type & CARDTABLE_SCAN_MOD_UNION);
        for (obj = los_object_list; obj; obj = obj->next) {
+               mword num_cards = 0;
                guint8 *cards;
 
                if (!SGEN_OBJECT_HAS_REFERENCES (obj->data))
                        continue;
 
-               if (mod_union) {
+               if (scan_type & CARDTABLE_SCAN_MOD_UNION) {
                        if (!sgen_los_object_is_pinned (obj->data))
                                continue;
 
                        cards = get_cardtable_mod_union_for_object (obj);
                        g_assert (cards);
+                       if (scan_type == CARDTABLE_SCAN_MOD_UNION_PRECLEAN) {
+                               guint8 *cards_preclean;
+                               mword obj_size = sgen_los_object_size (obj);
+                               num_cards = sgen_card_table_number_of_cards_in_range ((mword) obj->data, obj_size);
+                               cards_preclean = (guint8 *)sgen_alloc_internal_dynamic (num_cards, INTERNAL_MEM_CARDTABLE_MOD_UNION, TRUE);
+
+                               sgen_card_table_preclean_mod_union (cards, cards_preclean, num_cards);
+
+                               cards = cards_preclean;
+                       }
                } else {
                        cards = NULL;
                }
 
-               sgen_cardtable_scan_object (obj->data, sgen_los_object_size (obj), cards, mod_union, ctx);
+               sgen_cardtable_scan_object (obj->data, sgen_los_object_size (obj), cards, ctx);
+
+               if (scan_type == CARDTABLE_SCAN_MOD_UNION_PRECLEAN)
+                       sgen_free_internal_dynamic (cards, num_cards, INTERNAL_MEM_CARDTABLE_MOD_UNION);
        }
-       binary_protocol_los_card_table_scan_end (sgen_timestamp (), mod_union);
+       binary_protocol_los_card_table_scan_end (sgen_timestamp (), scan_type & CARDTABLE_SCAN_MOD_UNION);
 }
 
 void
index 677435a0a09cba9abd3d598b18ab7b20350451b1..a0bff286fa3236e19464d2e6225f468c4b49e8f3 100644 (file)
@@ -234,7 +234,7 @@ SCAN_OBJECT_FUNCTION_NAME (GCObject *full_object, SgenDescriptor desc, SgenGrayQ
                                COPY_OR_MARK_FUNCTION_NAME ((ptr), __old, queue); \
                        }                                               \
                } else {                                                \
-                       if (G_UNLIKELY (sgen_ptr_in_nursery (__old) && !sgen_ptr_in_nursery ((ptr)))) \
+                       if (G_UNLIKELY (sgen_ptr_in_nursery (__old) && !sgen_ptr_in_nursery ((ptr)) && !sgen_cement_is_forced (__old))) \
                                mark_mod_union_card ((full_object), (void**)(ptr), __old); \
                        }                                               \
                } while (0)
@@ -246,7 +246,7 @@ SCAN_OBJECT_FUNCTION_NAME (GCObject *full_object, SgenDescriptor desc, SgenGrayQ
                        PREFETCH_READ (__old);                  \
                        COPY_OR_MARK_FUNCTION_NAME ((ptr), __old, queue); \
                } else {                                                \
-                       if (G_UNLIKELY (sgen_ptr_in_nursery (__old) && !sgen_ptr_in_nursery ((ptr)))) \
+                       if (G_UNLIKELY (sgen_ptr_in_nursery (__old) && !sgen_ptr_in_nursery ((ptr)) && !sgen_cement_is_forced (__old))) \
                                mark_mod_union_card ((full_object), (void**)(ptr), __old); \
                        }                                               \
                } while (0)
@@ -268,6 +268,37 @@ SCAN_OBJECT_FUNCTION_NAME (GCObject *full_object, SgenDescriptor desc, SgenGrayQ
 #include "sgen-scan-object.h"
 }
 
+#ifdef SCAN_VTYPE_FUNCTION_NAME 
+static void
+SCAN_VTYPE_FUNCTION_NAME (GCObject *full_object, char *start, SgenDescriptor desc, SgenGrayQueue *queue BINARY_PROTOCOL_ARG (size_t size))
+{
+       SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP;
+
+#ifdef HEAVY_STATISTICS
+       /* FIXME: We're half scanning this object.  How do we account for that? */
+       //add_scanned_object (start);
+#endif
+
+       /* The descriptors include info about the object header as well */
+       start -= SGEN_CLIENT_OBJECT_HEADER_SIZE;
+
+       /* We use the same HANDLE_PTR from the obj scan function */
+#define SCAN_OBJECT_NOVTABLE
+#define SCAN_OBJECT_PROTOCOL
+#include "sgen-scan-object.h"
+
+       SGEN_OBJECT_LAYOUT_STATISTICS_COMMIT_BITMAP;
+}
+#endif
+
+#ifdef SCAN_PTR_FIELD_FUNCTION_NAME
+static void
+SCAN_PTR_FIELD_FUNCTION_NAME (GCObject *full_object, GCObject **ptr, SgenGrayQueue *queue)
+{
+       HANDLE_PTR (ptr, NULL);
+}
+#endif
+
 static gboolean
 DRAIN_GRAY_STACK_FUNCTION_NAME (SgenGrayQueue *queue)
 {
@@ -293,5 +324,9 @@ DRAIN_GRAY_STACK_FUNCTION_NAME (SgenGrayQueue *queue)
 
 #undef COPY_OR_MARK_FUNCTION_NAME
 #undef COPY_OR_MARK_WITH_EVACUATION
+#undef COPY_OR_MARK_CONCURRENT
+#undef COPY_OR_MARK_CONCURRENT_WITH_EVACUATION
 #undef SCAN_OBJECT_FUNCTION_NAME
+#undef SCAN_VTYPE_FUNCTION_NAME
+#undef SCAN_PTR_FIELD_FUNCTION_NAME
 #undef DRAIN_GRAY_STACK_FUNCTION_NAME
diff --git a/mono/sgen/sgen-marksweep-scan-object-concurrent.h b/mono/sgen/sgen-marksweep-scan-object-concurrent.h
deleted file mode 100644 (file)
index 541a0a2..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * sgen-major-scan-object.h: Object scanning in the major collectors.
- *
- * Copyright 2001-2003 Ximian, Inc
- * Copyright 2003-2010 Novell, Inc.
- * Copyright (C) 2012 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.
- */
-
-/*
- * 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 {                                    \
-                GCObject *__old = *(ptr);                                   \
-                binary_protocol_scan_process_reference ((full_object), (ptr), __old); \
-                if (__old) {                                            \
-                        gboolean __still_in_nursery = major_copy_or_mark_object_with_evacuation ((ptr), __old, queue); \
-                        if (G_UNLIKELY (__still_in_nursery && !sgen_ptr_in_nursery ((ptr)) && !SGEN_OBJECT_IS_CEMENTED (*(ptr)))) { \
-                                GCObject *__copy = *(ptr);                  \
-                                sgen_add_to_global_remset ((ptr), __copy); \
-                        }                                              \
-                }                                                       \
-        } while (0)
-
-
-static void
-major_scan_vtype_concurrent_finish (GCObject *full_object, char *start, SgenDescriptor desc, SgenGrayQueue *queue BINARY_PROTOCOL_ARG (size_t size))
-{
-       SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP;
-
-#ifdef HEAVY_STATISTICS
-       /* FIXME: We're half scanning this object.  How do we account for that? */
-       //add_scanned_object (start);
-#endif
-
-       /* The descriptors include info about the object header as well */
-       start -= SGEN_CLIENT_OBJECT_HEADER_SIZE;
-
-#define SCAN_OBJECT_NOVTABLE
-#define SCAN_OBJECT_PROTOCOL
-#include "sgen-scan-object.h"
-
-       SGEN_OBJECT_LAYOUT_STATISTICS_COMMIT_BITMAP;
-}
index 7aaaa0221e1d900931d9f052314379a3a00271e5..b475ef3ad79ab82910792b1698028da913793f79 100644 (file)
 #include "mono/sgen/sgen-memory-governor.h"
 #include "mono/sgen/sgen-layout-stats.h"
 #include "mono/sgen/sgen-pointer-queue.h"
+#include "mono/sgen/sgen-array-list.h"
 #include "mono/sgen/sgen-pinning.h"
 #include "mono/sgen/sgen-workers.h"
 #include "mono/sgen/sgen-thread-pool.h"
 #include "mono/sgen/sgen-client.h"
-#include "mono/utils/mono-membar.h"
+#include "mono/utils/mono-memory-model.h"
 
 #if defined(ARCH_MIN_MS_BLOCK_SIZE) && defined(ARCH_MIN_MS_BLOCK_SIZE_SHIFT)
 #define MS_BLOCK_SIZE  ARCH_MIN_MS_BLOCK_SIZE
@@ -197,27 +198,25 @@ static gboolean concurrent_sweep = TRUE;
 #define BLOCK_TAG(bl)                          ((bl)->has_references ? BLOCK_TAG_HAS_REFERENCES ((bl)) : (bl))
 
 /* all allocated blocks in the system */
-static SgenPointerQueue allocated_blocks;
+static SgenArrayList allocated_blocks = SGEN_ARRAY_LIST_INIT (NULL, NULL, NULL, INTERNAL_MEM_PIN_QUEUE);
 
 /* non-allocated block free-list */
 static void *empty_blocks = NULL;
 static size_t num_empty_blocks = 0;
 
-#define FOREACH_BLOCK_NO_LOCK_CONDITION(cond,bl) {                     \
-       size_t __index;                                                 \
-       SGEN_ASSERT (0, (cond) && !sweep_in_progress (), "Can't iterate blocks while the world is running or sweep is in progress."); \
-       for (__index = 0; __index < allocated_blocks.next_slot; ++__index) { \
-               (bl) = BLOCK_UNTAG (allocated_blocks.data [__index]);
-#define FOREACH_BLOCK_NO_LOCK(bl)                                      \
-       FOREACH_BLOCK_NO_LOCK_CONDITION(sgen_is_world_stopped (), bl)
+#define FOREACH_BLOCK_NO_LOCK(bl) {                                    \
+       volatile gpointer *slot;                                                \
+       SGEN_ASSERT (0, !sweep_in_progress (), "Can't iterate blocks while sweep is in progress."); \
+       SGEN_ARRAY_LIST_FOREACH_SLOT (&allocated_blocks, slot) {        \
+               (bl) = BLOCK_UNTAG (*slot);
 #define FOREACH_BLOCK_HAS_REFERENCES_NO_LOCK(bl,hr) {                  \
-       size_t __index;                                                 \
-       SGEN_ASSERT (0, sgen_is_world_stopped () && !sweep_in_progress (), "Can't iterate blocks while the world is running or sweep is in progress."); \
-       for (__index = 0; __index < allocated_blocks.next_slot; ++__index) { \
-               (bl) = (MSBlockInfo *)allocated_blocks.data [__index];                  \
+       volatile gpointer *slot;                                                \
+       SGEN_ASSERT (0, !sweep_in_progress (), "Can't iterate blocks while sweep is in progress."); \
+       SGEN_ARRAY_LIST_FOREACH_SLOT (&allocated_blocks, slot) {        \
+               (bl) = (MSBlockInfo *) (*slot);                 \
                (hr) = BLOCK_IS_TAGGED_HAS_REFERENCES ((bl));           \
                (bl) = BLOCK_UNTAG ((bl));
-#define END_FOREACH_BLOCK_NO_LOCK      } }
+#define END_FOREACH_BLOCK_NO_LOCK      } SGEN_ARRAY_LIST_END_FOREACH_SLOT; }
 
 static volatile size_t num_major_sections = 0;
 /*
@@ -436,7 +435,7 @@ check_block_free_list (MSBlockInfo *block, int size, gboolean pinned)
                g_assert (block->free_list);
 
                /* the block must be in the allocated_blocks array */
-               g_assert (sgen_pointer_queue_find (&allocated_blocks, BLOCK_TAG (block)) != (size_t)-1);
+               g_assert (sgen_array_list_find (&allocated_blocks, BLOCK_TAG (block)) != (guint32)-1);
        }
 }
 
@@ -567,7 +566,7 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references)
        major_finish_sweep_checking ();
        mono_memory_barrier ();
 
-       sgen_pointer_queue_add (&allocated_blocks, BLOCK_TAG (info));
+       sgen_array_list_add (&allocated_blocks, BLOCK_TAG (info), 0, FALSE);
 
        SGEN_ATOMIC_ADD_P (num_major_sections, 1);
        return TRUE;
@@ -815,14 +814,14 @@ set_sweep_state (int new_, int expected)
        SGEN_ASSERT (0, success, "Could not set sweep state.");
 }
 
-static gboolean ensure_block_is_checked_for_sweeping (int block_index, gboolean wait, gboolean *have_checked);
+static gboolean ensure_block_is_checked_for_sweeping (guint32 block_index, gboolean wait, gboolean *have_checked);
 
 static SgenThreadPoolJob * volatile sweep_job;
 
 static void
 major_finish_sweep_checking (void)
 {
-       int block_index;
+       guint32 block_index;
        SgenThreadPoolJob *job;
 
  retry:
@@ -1076,7 +1075,6 @@ mark_mod_union_card (GCObject *obj, void **ptr, GCObject *value_obj)
        } else {
                sgen_los_mark_mod_union_card (obj, ptr);
        }
-
        binary_protocol_mod_union_remset (obj, ptr, value_obj, SGEN_LOAD_VTABLE (value_obj));
 }
 
@@ -1185,20 +1183,22 @@ static guint64 stat_drain_loops;
 #define COPY_OR_MARK_WITH_EVACUATION
 #define COPY_OR_MARK_FUNCTION_NAME     major_copy_or_mark_object_with_evacuation
 #define SCAN_OBJECT_FUNCTION_NAME      major_scan_object_with_evacuation
+#define SCAN_VTYPE_FUNCTION_NAME       major_scan_vtype_with_evacuation
 #define DRAIN_GRAY_STACK_FUNCTION_NAME drain_gray_stack_with_evacuation
+#define SCAN_PTR_FIELD_FUNCTION_NAME   major_scan_ptr_field_with_evacuation
 #include "sgen-marksweep-drain-gray-stack.h"
 
-#undef COPY_OR_MARK_WITH_EVACUATION
 #define COPY_OR_MARK_CONCURRENT
 #define COPY_OR_MARK_FUNCTION_NAME     major_copy_or_mark_object_concurrent_no_evacuation
 #define SCAN_OBJECT_FUNCTION_NAME      major_scan_object_concurrent_no_evacuation
 #define DRAIN_GRAY_STACK_FUNCTION_NAME drain_gray_stack_concurrent_no_evacuation
 #include "sgen-marksweep-drain-gray-stack.h"
 
-#undef COPY_OR_MARK_CONCURRENT
 #define COPY_OR_MARK_CONCURRENT_WITH_EVACUATION
 #define COPY_OR_MARK_FUNCTION_NAME     major_copy_or_mark_object_concurrent_with_evacuation
 #define SCAN_OBJECT_FUNCTION_NAME      major_scan_object_concurrent_with_evacuation
+#define SCAN_VTYPE_FUNCTION_NAME       major_scan_vtype_concurrent_with_evacuation
+#define SCAN_PTR_FIELD_FUNCTION_NAME   major_scan_ptr_field_concurrent_with_evacuation
 #define DRAIN_GRAY_STACK_FUNCTION_NAME drain_gray_stack_concurrent_with_evacuation
 #include "sgen-marksweep-drain-gray-stack.h"
 
@@ -1233,8 +1233,6 @@ drain_gray_stack_concurrent (SgenGrayQueue *queue)
                return drain_gray_stack_concurrent_no_evacuation (queue);
 }
 
-#include "sgen-marksweep-scan-object-concurrent.h"
-
 static void
 major_copy_or_mark_object_canonical (GCObject **ptr, SgenGrayQueue *queue)
 {
@@ -1449,7 +1447,7 @@ static void sweep_finish (void);
  * be correct, i.e. must not be used.
  */
 static gboolean
-ensure_block_is_checked_for_sweeping (int block_index, gboolean wait, gboolean *have_checked)
+ensure_block_is_checked_for_sweeping (guint32 block_index, gboolean wait, gboolean *have_checked)
 {
        int count;
        gboolean have_live = FALSE;
@@ -1459,6 +1457,7 @@ ensure_block_is_checked_for_sweeping (int block_index, gboolean wait, gboolean *
        int i;
        void *tagged_block;
        MSBlockInfo *block;
+       volatile gpointer *block_slot = sgen_array_list_get_slot (&allocated_blocks, block_index);
 
        SGEN_ASSERT (6, sweep_in_progress (), "Why do we call this function if there's no sweep in progress?");
 
@@ -1466,7 +1465,7 @@ ensure_block_is_checked_for_sweeping (int block_index, gboolean wait, gboolean *
                *have_checked = FALSE;
 
  retry:
-       tagged_block = *(void * volatile *)&allocated_blocks.data [block_index];
+       tagged_block = *(void * volatile *)block_slot;
        if (!tagged_block)
                return FALSE;
 
@@ -1478,7 +1477,7 @@ ensure_block_is_checked_for_sweeping (int block_index, gboolean wait, gboolean *
                goto retry;
        }
 
-       if (SGEN_CAS_PTR (&allocated_blocks.data [block_index], BLOCK_TAG_CHECKING (tagged_block), tagged_block) != tagged_block)
+       if (SGEN_CAS_PTR (block_slot, BLOCK_TAG_CHECKING (tagged_block), tagged_block) != tagged_block)
                goto retry;
 
        block = BLOCK_UNTAG (tagged_block);
@@ -1572,7 +1571,7 @@ ensure_block_is_checked_for_sweeping (int block_index, gboolean wait, gboolean *
                 * block list and freed.
                 */
                SGEN_ASSERT (6, block_index < allocated_blocks.next_slot, "How did the number of blocks shrink?");
-               SGEN_ASSERT (6, allocated_blocks.data [block_index] == BLOCK_TAG_CHECKING (tagged_block), "How did the block move?");
+               SGEN_ASSERT (6, *block_slot == BLOCK_TAG_CHECKING (tagged_block), "How did the block move?");
 
                binary_protocol_empty (MS_BLOCK_OBJ (block, 0), (char*)MS_BLOCK_OBJ (block, count) - (char*)MS_BLOCK_OBJ (block, 0));
                ms_free_block (block);
@@ -1583,15 +1582,15 @@ ensure_block_is_checked_for_sweeping (int block_index, gboolean wait, gboolean *
        }
 
  done:
-       allocated_blocks.data [block_index] = tagged_block;
+       *block_slot = tagged_block;
        return !!tagged_block;
 }
 
 static void
 sweep_job_func (void *thread_data_untyped, SgenThreadPoolJob *job)
 {
-       int block_index;
-       int num_blocks = num_major_sections_before_sweep;
+       guint32 block_index;
+       guint32 num_blocks = num_major_sections_before_sweep;
 
        SGEN_ASSERT (0, sweep_in_progress (), "Sweep thread called with wrong state");
        SGEN_ASSERT (0, num_blocks <= allocated_blocks.next_slot, "How did we lose blocks?");
@@ -1601,14 +1600,12 @@ sweep_job_func (void *thread_data_untyped, SgenThreadPoolJob *job)
         * cooperate with the sweep thread to finish sweeping, and they will traverse from
         * low to high, to avoid constantly colliding on the same blocks.
         */
-       for (block_index = num_blocks - 1; block_index >= 0; --block_index) {
-               gboolean have_checked;
-
+       for (block_index = num_blocks; block_index-- > 0;) {
                /*
                 * The block might have been freed by another thread doing some checking
                 * work.
                 */
-               if (!ensure_block_is_checked_for_sweeping (block_index, TRUE, &have_checked))
+               if (!ensure_block_is_checked_for_sweeping (block_index, TRUE, NULL))
                        ++num_major_sections_freed_in_sweep;
        }
 
@@ -1623,13 +1620,12 @@ sweep_job_func (void *thread_data_untyped, SgenThreadPoolJob *job)
 
        if (SGEN_MAX_ASSERT_LEVEL >= 6) {
                for (block_index = num_blocks; block_index < allocated_blocks.next_slot; ++block_index) {
-                       MSBlockInfo *block = BLOCK_UNTAG (allocated_blocks.data [block_index]);
+                       MSBlockInfo *block = BLOCK_UNTAG (*sgen_array_list_get_slot (&allocated_blocks, block_index));
                        SGEN_ASSERT (6, block && block->state == BLOCK_STATE_SWEPT, "How did a new block to be swept get added while swept?");
                }
        }
 
-       sgen_pointer_queue_remove_nulls (&allocated_blocks);
-       mono_memory_barrier ();
+       sgen_array_list_remove_nulls (&allocated_blocks);
 
        sweep_finish ();
 
@@ -2052,7 +2048,7 @@ major_get_used_size (void)
         */
        major_finish_sweep_checking ();
 
-       FOREACH_BLOCK_NO_LOCK_CONDITION (TRUE, block) {
+       FOREACH_BLOCK_NO_LOCK (block) {
                int count = MS_BLOCK_FREE / block->obj_size;
                void **iter;
                size += count * block->obj_size;
@@ -2186,13 +2182,14 @@ initial_skip_card (guint8 *card_data)
 #define MS_OBJ_ALLOCED_FAST(o,b)               (*(void**)(o) && (*(char**)(o) < (b) || *(char**)(o) >= (b) + MS_BLOCK_SIZE))
 
 static void
-scan_card_table_for_block (MSBlockInfo *block, gboolean mod_union, ScanCopyContext ctx)
+scan_card_table_for_block (MSBlockInfo *block, CardTableScanType scan_type, ScanCopyContext ctx)
 {
        SgenGrayQueue *queue = ctx.queue;
        ScanObjectFunc scan_func = ctx.ops->scan_object;
 #ifndef SGEN_HAVE_OVERLAPPING_CARDS
        guint8 cards_copy [CARDS_PER_BLOCK];
 #endif
+       guint8 cards_preclean [CARDS_PER_BLOCK];
        gboolean small_objects;
        int block_obj_size;
        char *block_start;
@@ -2200,6 +2197,10 @@ scan_card_table_for_block (MSBlockInfo *block, gboolean mod_union, ScanCopyConte
        guint8 *card_data_end;
        char *scan_front = NULL;
 
+       /* The concurrent mark doesn't enter evacuating blocks */
+       if (scan_type == CARDTABLE_SCAN_MOD_UNION_PRECLEAN && major_block_is_evacuating (block))
+               return;
+
        block_obj_size = block->obj_size;
        small_objects = block_obj_size < CARD_SIZE_IN_BYTES;
 
@@ -2212,7 +2213,7 @@ scan_card_table_for_block (MSBlockInfo *block, gboolean mod_union, ScanCopyConte
         * Cards aliasing happens in powers of two, so as long as major blocks are aligned to their
         * sizes, they won't overflow the cardtable overlap modulus.
         */
-       if (mod_union) {
+       if (scan_type & CARDTABLE_SCAN_MOD_UNION) {
                card_data = card_base = block->cardtable_mod_union;
                /*
                 * This happens when the nursery collection that precedes finishing
@@ -2220,6 +2221,11 @@ scan_card_table_for_block (MSBlockInfo *block, gboolean mod_union, ScanCopyConte
                 */
                if (!card_data)
                        return;
+
+               if (scan_type == CARDTABLE_SCAN_MOD_UNION_PRECLEAN) {
+                       sgen_card_table_preclean_mod_union (card_data, cards_preclean, CARDS_PER_BLOCK);
+                       card_data = card_base = cards_preclean;
+               }
        } else {
 #ifdef SGEN_HAVE_OVERLAPPING_CARDS
                card_data = card_base = sgen_card_table_get_card_scan_address ((mword)block_start);
@@ -2278,7 +2284,7 @@ scan_card_table_for_block (MSBlockInfo *block, gboolean mod_union, ScanCopyConte
                        if (obj < scan_front || !MS_OBJ_ALLOCED_FAST (obj, block_start))
                                goto next_object;
 
-                       if (mod_union) {
+                       if (scan_type & CARDTABLE_SCAN_MOD_UNION) {
                                /* FIXME: do this more efficiently */
                                int w, b;
                                MS_CALC_MARK_BIT (w, b, obj);
@@ -2293,7 +2299,7 @@ scan_card_table_for_block (MSBlockInfo *block, gboolean mod_union, ScanCopyConte
                                scan_func (object, sgen_obj_get_descriptor (object), queue);
                        } else {
                                size_t offset = sgen_card_table_get_card_offset (obj, block_start);
-                               sgen_cardtable_scan_object (object, block_obj_size, card_base + offset, mod_union, ctx);
+                               sgen_cardtable_scan_object (object, block_obj_size, card_base + offset, ctx);
                        }
                next_object:
                        obj += block_obj_size;
@@ -2311,34 +2317,36 @@ scan_card_table_for_block (MSBlockInfo *block, gboolean mod_union, ScanCopyConte
 }
 
 static void
-major_scan_card_table (gboolean mod_union, ScanCopyContext ctx)
+major_scan_card_table (CardTableScanType scan_type, ScanCopyContext ctx)
 {
        MSBlockInfo *block;
        gboolean has_references;
 
        if (!concurrent_mark)
-               g_assert (!mod_union);
+               g_assert (scan_type == CARDTABLE_SCAN_GLOBAL);
 
        major_finish_sweep_checking ();
-       binary_protocol_major_card_table_scan_start (sgen_timestamp (), mod_union);
+       binary_protocol_major_card_table_scan_start (sgen_timestamp (), scan_type & CARDTABLE_SCAN_MOD_UNION);
        FOREACH_BLOCK_HAS_REFERENCES_NO_LOCK (block, has_references) {
 #ifdef PREFETCH_CARDS
                int prefetch_index = __index + 6;
                if (prefetch_index < allocated_blocks.next_slot) {
-                       MSBlockInfo *prefetch_block = BLOCK_UNTAG (allocated_blocks.data [prefetch_index]);
-                       guint8 *prefetch_cards = sgen_card_table_get_card_scan_address ((mword)MS_BLOCK_FOR_BLOCK_INFO (prefetch_block));
+                       MSBlockInfo *prefetch_block = BLOCK_UNTAG (*sgen_array_list_get_slot (&allocated_blocks, prefetch_index));
                        PREFETCH_READ (prefetch_block);
-                       PREFETCH_WRITE (prefetch_cards);
-                       PREFETCH_WRITE (prefetch_cards + 32);
+                       if (scan_type == CARDTABLE_SCAN_GLOBAL) {
+                               guint8 *prefetch_cards = sgen_card_table_get_card_scan_address ((mword)MS_BLOCK_FOR_BLOCK_INFO (prefetch_block));
+                               PREFETCH_WRITE (prefetch_cards);
+                               PREFETCH_WRITE (prefetch_cards + 32);
+                       }
                 }
 #endif
 
                if (!has_references)
                        continue;
 
-               scan_card_table_for_block (block, mod_union, ctx);
+               scan_card_table_for_block (block, scan_type, ctx);
        } END_FOREACH_BLOCK_NO_LOCK;
-       binary_protocol_major_card_table_scan_end (sgen_timestamp (), mod_union);
+       binary_protocol_major_card_table_scan_end (sgen_timestamp (), scan_type & CARDTABLE_SCAN_MOD_UNION);
 }
 
 static void
@@ -2496,11 +2504,14 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
        if (is_concurrent) {
                collector->major_ops_concurrent_start.copy_or_mark_object = major_copy_or_mark_object_concurrent_canonical;
                collector->major_ops_concurrent_start.scan_object = major_scan_object_concurrent_with_evacuation;
+               collector->major_ops_concurrent_start.scan_vtype = major_scan_vtype_concurrent_with_evacuation;
+               collector->major_ops_concurrent_start.scan_ptr_field = major_scan_ptr_field_concurrent_with_evacuation;
                collector->major_ops_concurrent_start.drain_gray_stack = drain_gray_stack_concurrent;
 
                collector->major_ops_concurrent_finish.copy_or_mark_object = major_copy_or_mark_object_concurrent_finish_canonical;
                collector->major_ops_concurrent_finish.scan_object = major_scan_object_with_evacuation;
-               collector->major_ops_concurrent_finish.scan_vtype = major_scan_vtype_concurrent_finish;
+               collector->major_ops_concurrent_finish.scan_vtype = major_scan_vtype_with_evacuation;
+               collector->major_ops_concurrent_finish.scan_ptr_field = major_scan_ptr_field_with_evacuation;
                collector->major_ops_concurrent_finish.drain_gray_stack = drain_gray_stack;
        }
 
index b1895985dc34e340f32093abfb423f967711f44a..9b23ce4ab70e3cd2284d5babad52333158db0158 100644 (file)
@@ -80,7 +80,14 @@ SERIAL_SCAN_VTYPE (GCObject *full_object, char *start, SgenDescriptor desc, Sgen
 #include "sgen-scan-object.h"
 }
 
+static void
+SERIAL_SCAN_PTR_FIELD (GCObject *full_object, GCObject **ptr, SgenGrayQueue *queue)
+{
+       HANDLE_PTR (ptr, NULL);
+}
+
 #define FILL_MINOR_COLLECTOR_SCAN_OBJECT(collector)    do {                    \
                (collector)->serial_ops.scan_object = SERIAL_SCAN_OBJECT;       \
                (collector)->serial_ops.scan_vtype = SERIAL_SCAN_VTYPE; \
+               (collector)->serial_ops.scan_ptr_field = SERIAL_SCAN_PTR_FIELD; \
        } while (0)
index a94af9ddf4494db961697faac801a9273bece46b..4ed5d0a6b5b879bdc0788d1b0b4ac50f0a0973b6 100644 (file)
@@ -182,6 +182,7 @@ typedef struct _CementHashEntry CementHashEntry;
 struct _CementHashEntry {
        GCObject *obj;
        unsigned int count;
+       gboolean forced; /* if it should stay cemented after the finishing pause */
 };
 
 static CementHashEntry cement_hash [SGEN_CEMENT_HASH_SIZE];
@@ -197,10 +198,70 @@ sgen_cement_init (gboolean enabled)
 void
 sgen_cement_reset (void)
 {
-       memset (cement_hash, 0, sizeof (cement_hash));
+       int i;
+       for (i = 0; i < SGEN_CEMENT_HASH_SIZE; i++) {
+               if (cement_hash [i].forced) {
+                       cement_hash [i].forced = FALSE;
+               } else {
+                       cement_hash [i].obj = NULL;
+                       cement_hash [i].count = 0;
+               }
+       }
        binary_protocol_cement_reset ();
 }
 
+
+/*
+ * The pin_queue should be full and sorted, without entries from the cemented
+ * objects. We traverse the cement hash and check if each object is pinned in
+ * the pin_queue (the pin_queue contains entries between obj and obj+obj_len)
+ */
+void
+sgen_cement_force_pinned (void)
+{
+       int i;
+
+       if (!cement_enabled)
+               return;
+
+       for (i = 0; i < SGEN_CEMENT_HASH_SIZE; i++) {
+               GCObject *obj = cement_hash [i].obj;
+               size_t index;
+               if (!obj)
+                       continue;
+               if (cement_hash [i].count < SGEN_CEMENT_THRESHOLD)
+                       continue;
+               SGEN_ASSERT (0, !cement_hash [i].forced, "Why do we have a forced cemented object before forcing ?");
+
+               /* Returns the index of the target or of the first element greater than it */
+               index = sgen_pointer_queue_search (&pin_queue, obj);
+               if (index == pin_queue.next_slot)
+                       continue;
+               SGEN_ASSERT (0, pin_queue.data [index] >= (gpointer)obj, "Binary search should return a pointer greater than the search target");
+               if (pin_queue.data [index] < (gpointer)((char*)obj + sgen_safe_object_get_size (obj)))
+                       cement_hash [i].forced = TRUE;
+       }
+}
+
+gboolean
+sgen_cement_is_forced (GCObject *obj)
+{
+       guint hv = sgen_aligned_addr_hash (obj);
+       int i = SGEN_CEMENT_HASH (hv);
+
+       SGEN_ASSERT (5, sgen_ptr_in_nursery (obj), "Looking up cementing for non-nursery objects makes no sense");
+
+       if (!cement_enabled)
+               return FALSE;
+
+       if (!cement_hash [i].obj)
+               return FALSE;
+       if (cement_hash [i].obj != obj)
+               return FALSE;
+
+       return cement_hash [i].forced;
+}
+
 gboolean
 sgen_cement_lookup (GCObject *obj)
 {
index e7f1e288f81c42d41e51a565c19eaa4d80a9e38c..50d0f966ac046cba52c326989a1d77c492843f0a 100644 (file)
@@ -56,6 +56,8 @@ void sgen_pin_stats_reset (void);
 
 void sgen_cement_init (gboolean enabled);
 void sgen_cement_reset (void);
+void sgen_cement_force_pinned (void);
+gboolean sgen_cement_is_forced (GCObject *obj);
 gboolean sgen_cement_lookup (GCObject *obj);
 gboolean sgen_cement_lookup_or_register (GCObject *obj);
 void sgen_pin_cemented_objects (void);
index e9706943f847803dc38b88b633b6464aefe85c75..3371d2bfab736b19cb852957758f234d7dc0617d 100644 (file)
@@ -41,6 +41,9 @@ static SgenThreadPoolThreadInitFunc thread_init_func;
 static SgenThreadPoolIdleJobFunc idle_job_func;
 static SgenThreadPoolContinueIdleJobFunc continue_idle_job_func;
 
+static volatile gboolean threadpool_shutdown;
+static volatile gboolean thread_finished;
+
 enum {
        STATE_WAITING,
        STATE_IN_PROGRESS,
@@ -109,7 +112,7 @@ thread_func (void *thread_data)
                gboolean do_idle = continue_idle_job ();
                SgenThreadPoolJob *job = get_job_and_set_in_progress ();
 
-               if (!job && !do_idle) {
+               if (!job && !do_idle && !threadpool_shutdown) {
                        /*
                         * pthread_cond_wait() can return successfully despite the condition
                         * not being signalled, so we have to run this in a loop until we
@@ -134,8 +137,7 @@ thread_func (void *thread_data)
                         * have to broadcast.
                         */
                        mono_os_cond_signal (&done_cond);
-               } else {
-                       SGEN_ASSERT (0, do_idle, "Why did we unlock if we still have to wait for idle?");
+               } else if (do_idle) {
                        SGEN_ASSERT (0, idle_job_func, "Why do we have idle work when there's no idle job function?");
                        do {
                                idle_job_func (thread_data);
@@ -146,6 +148,13 @@ thread_func (void *thread_data)
 
                        if (!do_idle)
                                mono_os_cond_signal (&done_cond);
+               } else {
+                       SGEN_ASSERT (0, threadpool_shutdown, "Why did we unlock if no jobs and not shutting down?");
+                       mono_os_mutex_lock (&lock);
+                       thread_finished = TRUE;
+                       mono_os_cond_signal (&done_cond);
+                       mono_os_mutex_unlock (&lock);
+                       return 0;
                }
        }
 
@@ -168,6 +177,24 @@ sgen_thread_pool_init (int num_threads, SgenThreadPoolThreadInitFunc init_func,
        mono_native_thread_create (&thread, thread_func, thread_datas ? thread_datas [0] : NULL);
 }
 
+void
+sgen_thread_pool_shutdown (void)
+{
+       if (!thread)
+               return;
+
+       mono_os_mutex_lock (&lock);
+       threadpool_shutdown = TRUE;
+       mono_os_cond_signal (&work_cond);
+       while (!thread_finished)
+               mono_os_cond_wait (&done_cond, &lock);
+       mono_os_mutex_unlock (&lock);
+
+       mono_os_mutex_destroy (&lock);
+       mono_os_cond_destroy (&work_cond);
+       mono_os_cond_destroy (&done_cond);
+}
+
 SgenThreadPoolJob*
 sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size)
 {
index 4dcb3a9a14b76195c06f3ccaf396cdf67dd1e9df..6e227521a3f6a0932f8fc2ff398abc726078808c 100644 (file)
@@ -37,6 +37,8 @@ typedef gboolean (*SgenThreadPoolContinueIdleJobFunc) (void);
 
 void sgen_thread_pool_init (int num_threads, SgenThreadPoolThreadInitFunc init_func, SgenThreadPoolIdleJobFunc idle_func, SgenThreadPoolContinueIdleJobFunc continue_idle_func, void **thread_datas);
 
+void sgen_thread_pool_shutdown (void);
+
 SgenThreadPoolJob* sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size);
 /* This only needs to be called on jobs that are not enqueued. */
 void sgen_thread_pool_job_free (SgenThreadPoolJob *job);
index f1212c658c4c755954fba3d3927e62742cfe836e..33907204c8a1e60dfe691ba29ec29fb9964e8ae9 100644 (file)
@@ -64,6 +64,7 @@ typedef gint32 State;
 static volatile State workers_state;
 
 static SgenObjectOperations * volatile idle_func_object_ops;
+static SgenThreadPoolJob * volatile preclean_job;
 
 static guint64 stat_workers_num_finished;
 
@@ -230,7 +231,13 @@ marker_idle_func (void *data_untyped)
 
                sgen_drain_gray_stack (ctx);
        } else {
-               worker_try_finish ();
+               SgenThreadPoolJob *job = preclean_job;
+               if (job) {
+                       sgen_thread_pool_job_enqueue (job);
+                       preclean_job = NULL;
+               } else {
+                       worker_try_finish ();
+               }
        }
 }
 
@@ -287,6 +294,8 @@ sgen_workers_init (int num_workers)
 void
 sgen_workers_stop_all_workers (void)
 {
+       preclean_job = NULL;
+       mono_memory_write_barrier ();
        forced_stop = TRUE;
 
        sgen_thread_pool_wait_for_all_jobs ();
@@ -295,10 +304,11 @@ sgen_workers_stop_all_workers (void)
 }
 
 void
-sgen_workers_start_all_workers (SgenObjectOperations *object_ops)
+sgen_workers_start_all_workers (SgenObjectOperations *object_ops, SgenThreadPoolJob *job)
 {
        forced_stop = FALSE;
        idle_func_object_ops = object_ops;
+       preclean_job = job;
        mono_memory_write_barrier ();
 
        sgen_workers_ensure_awake ();
index 4a3703555ff19613ee1dcc291361ef0c356566ca..61538f913aafa8903df6c10a1403097cee2f6f67 100644 (file)
@@ -30,7 +30,7 @@ struct _WorkerData {
 
 void sgen_workers_init (int num_workers);
 void sgen_workers_stop_all_workers (void);
-void sgen_workers_start_all_workers (SgenObjectOperations *object_ops);
+void sgen_workers_start_all_workers (SgenObjectOperations *object_ops, SgenThreadPoolJob *finish_job);
 void sgen_workers_ensure_awake (void);
 void sgen_workers_init_distribute_gray_queue (void);
 void sgen_workers_enqueue_job (SgenThreadPoolJob *job, gboolean enqueue);
index b410d785f993dba01dbc6b3d765ed64d069dad0e..83b7d196cbd2b12005d107ba4df1eb074b2c175d 100644 (file)
@@ -709,7 +709,7 @@ EXTRA_DIST=test-driver test-runner.cs $(TEST_CS_SRC_DIST) $(TEST_IL_SRC) \
        $(ILASM) -out:$@ $<
 
 %.exe: %.cs TestDriver.dll
-       $(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll -out:$@ $<
+       $(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll -r:Mono.Posix.dll -out:$@ $<
 
 # mkbundle works on ppc, but the pkg-config POC doesn't when run with make test
 if POWERPC
index c811eec33676834d4ce737fd0434385a9ce6987e..d4673c79584328524e8f56222d4ed9d2f51597ab 100644 (file)
@@ -98,7 +98,10 @@ class CrossDomainTester : MarshalByRefObject
 public class Tests
 {
        public static int Main(string[] args) {
-               return TestDriver.RunTests (typeof (Tests), args);
+               if (args.Length == 0)
+                       return TestDriver.RunTests (typeof (Tests), new String[] { "-v" });
+               else
+                       return TestDriver.RunTests (typeof (Tests), args);
        }
 
        public static int test_0_unload () {
index f9c93d5da88f65186082c68cd3dc8b432ff2c562..566e98ce085ba7e56e40ed70c569c73233977126 100644 (file)
@@ -1,9 +1,13 @@
 using System;
 using System.IO;
 using System.Reflection;
+using System.Runtime.InteropServices;
 
 public class Tests
 {
+       [DllImport("__Internal")]
+       extern static void mono_set_assemblies_path (string path);
+
        public static void Main (string[] args)
        {
                var ver40 = new Version (4, 0, 0, 0);
@@ -17,11 +21,13 @@ public class Tests
                var frwk20 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Framework, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
                var frwk35 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
 
-               // when run as part of the test suite, we need to register the xbuild 14.0 path or v14 assembly lookup will fail 
-               if (!String.IsNullOrEmpty (Environment.GetEnvironmentVariable ("MONO_PATH"))) {
-                       var p = Path.Combine (new DirectoryInfo (Environment.GetEnvironmentVariable ("MONO_PATH")).Parent.FullName, "xbuild_14");
-                       Console.WriteLine("Adding private bin path " + p);
-                       AppDomain.CurrentDomain.AppendPrivatePath (p);
+               // when run as part of the test suite, we need to register the xbuild 14.0 path or v14 assembly lookup will fail
+               var mono_path = Environment.GetEnvironmentVariable ("MONO_PATH");
+               if (!String.IsNullOrEmpty (mono_path)) {
+                       var xbuild = Path.Combine (new DirectoryInfo (mono_path).Parent.FullName, "xbuild_14");
+                       mono_path = xbuild + Path.PathSeparator + mono_path;
+                       Console.WriteLine ("Setting Mono assemblies path to " + mono_path);
+                       mono_set_assemblies_path (mono_path);
                }
 
                var engn140 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Engine, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
index c0d094fc56f1f2a262d9a42d77ccf0e67c01fff2..dbd2e9ad1cc108d8ee2ebbb383738f9b84999af4 100644 (file)
@@ -1117,6 +1117,14 @@ mono_test_marshal_virtual_delegate (VirtualDelegate del)
        return del (42);
 }
 
+typedef char* (STDCALL *IcallDelegate) (const char *);
+LIBTEST_API int STDCALL
+mono_test_marshal_icall_delegate (IcallDelegate del)
+{
+       char *res = del ("ABC");
+       return strcmp (res, "ABC") == 0 ? 0 : 1;
+}
+
 LIBTEST_API int STDCALL  
 mono_test_marshal_stringbuilder (char *s, int n)
 {
index 376e2000187f834b4b5ce0516fa1249cb5ced8cb..29ed8ea7eee8498f00e11aaf06d54b7109a8150d 100644 (file)
@@ -194,6 +194,11 @@ public class Tests {
        [DllImport ("libtest", EntryPoint="mono_test_marshal_virtual_delegate")]
        public static extern int mono_test_marshal_virtual_delegate (VirtualDelegate del);
 
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_icall_delegate")]
+       public static extern int mono_test_marshal_icall_delegate (IcallDelegate del);
+
+       public delegate string IcallDelegate (IntPtr p);
+
        public delegate int TestDelegate (int a, ref SimpleStruct ss, int b);
 
        public delegate SimpleStruct SimpleDelegate2 (SimpleStruct ss);
@@ -1161,4 +1166,10 @@ public class Tests {
 
                return mono_test_marshal_virtual_delegate (b.get_del ());
        }
+
+       public static int test_0_icall_delegate () {
+               var m = typeof (Marshal).GetMethod ("PtrToStringAnsi", new Type[] { typeof (IntPtr) });
+
+               return mono_test_marshal_icall_delegate ((IcallDelegate)Delegate.CreateDelegate (typeof (IcallDelegate), m));
+       }
 }
index e58e009a269117778ad7472a5b7f780a33221539..358be81312cc452d0caa25fcd034069da5baa168 100644 (file)
@@ -33,6 +33,7 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.Xml;
 using System.Text.RegularExpressions;
+using Mono.Unix.Native;
 
 //
 // This is a simple test runner with support for parallel execution
@@ -268,6 +269,13 @@ public class TestRunner
                                                        timedout.Add (data);
                                                }
 
+                                               // Force the process to print a thread dump
+                                               try {
+                                                       Syscall.kill (p.Id, Signum.SIGQUIT);
+                                                       Thread.Sleep (1000);
+                                               } catch {
+                                               }
+
                                                output.Write ("timed out");
 
                                                p.Kill ();
index 624d1b88b8eb595500bcdad638d007d56f026ffe..f4ae1b54100e4550201e99c71ecf673951f815a8 100644 (file)
@@ -8,7 +8,7 @@
  */
 #include <config.h>
 
-#ifdef CHECKED_BUILD
+#ifdef ENABLE_CHECKED_BUILD
 
 #include <mono/utils/checked-build.h>
 #include <mono/utils/mono-threads.h>
 #include <execinfo.h>
 #endif
 
+// Selective-enable support
+
+// Returns true for check modes which are allowed by both the current DISABLE_ macros and the MONO_CHECK_MODE env var.
+// Argument may be a bitmask; if so, result is true if at least one specified mode is enabled.
+mono_bool
+mono_check_mode_enabled (MonoCheckMode query)
+{
+       static MonoCheckMode check_mode = MONO_CHECK_MODE_UNKNOWN;
+       if (G_UNLIKELY (check_mode == MONO_CHECK_MODE_UNKNOWN))
+       {
+               MonoCheckMode env_check_mode = MONO_CHECK_MODE_NONE;
+               const gchar *env_string = g_getenv ("MONO_CHECK_MODE");
+
+               if (env_string)
+               {
+                       gchar **env_split = g_strsplit (env_string, ",", 0);
+                       for (gchar **env_component = env_split; *env_component; env_component++)
+                       {
+                               mono_bool check_all = g_str_equal (*env_component, "all");
+#ifdef ENABLE_CHECKED_BUILD_GC
+                               if (check_all || g_str_equal (*env_component, "gc"))
+                                       env_check_mode |= MONO_CHECK_MODE_GC;
+#endif
+#ifdef ENABLE_CHECKED_BUILD_METADATA
+                               if (check_all || g_str_equal (*env_component, "metadata"))
+                                       env_check_mode |= MONO_CHECK_MODE_METADATA;
+#endif
+#ifdef ENABLE_CHECKED_BUILD_THREAD
+                               if (check_all || g_str_equal (*env_component, "thread"))
+                                       env_check_mode |= MONO_CHECK_MODE_THREAD;
+#endif
+                       }
+                       g_strfreev (env_split);
+               }
+
+               check_mode = env_check_mode;
+       }
+       return check_mode & query;
+}
+
+static int
+mono_check_transition_limit (void)
+{
+       static int transition_limit = -1;
+       if (transition_limit < 0) {
+               const gchar *env_string = g_getenv ("MONO_CHECK_THREAD_TRANSITION_HISTORY");
+               if (env_string)
+                       transition_limit = atoi (env_string);
+               else
+                       transition_limit = 3;
+       }
+       return transition_limit;
+}
+
 typedef struct {
        GPtrArray *transitions;
        guint32 in_gc_critical_region;
@@ -34,7 +88,9 @@ static MonoNativeTlsKey thread_status;
 void
 checked_build_init (void)
 {
-       mono_native_tls_alloc (&thread_status, NULL);
+       // Init state for get_state, which can be called either by gc or thread mode
+       if (mono_check_mode_enabled (MONO_CHECK_MODE_GC | MONO_CHECK_MODE_THREAD))
+               mono_native_tls_alloc (&thread_status, NULL);
 }
 
 static CheckState*
@@ -50,11 +106,11 @@ get_state (void)
        return state;
 }
 
-#if !defined(DISABLE_CHECKED_BUILD_THREAD)
+#ifdef ENABLE_CHECKED_BUILD_THREAD
 
 #define MAX_NATIVE_BT 6
 #define MAX_NATIVE_BT_PROBE (MAX_NATIVE_BT + 5)
-#define MAX_TRANSITIONS 3
+#define MAX_TRANSITIONS (mono_check_transition_limit ())
 
 #ifdef HAVE_BACKTRACE_SYMBOLS
 
@@ -124,6 +180,9 @@ free_transition (ThreadTransition *t)
 void
 checked_build_thread_transition (const char *transition, void *info, int from_state, int suspend_count, int next_state, int suspend_count_delta)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_THREAD))
+               return;
+
        MonoThreadInfo *cur = mono_thread_info_current_unchecked ();
        CheckState *state = get_state ();
        /* We currently don't record external changes as those are hard to reason about. */
@@ -143,16 +202,11 @@ checked_build_thread_transition (const char *transition, void *info, int from_st
        g_ptr_array_add (state->transitions, t);
 }
 
-#endif /* !defined(DISABLE_CHECKED_BUILD_THREAD) */
-
-#if !defined(DISABLE_CHECKED_BUILD_GC)
-
-static void
-assertion_fail (const char *msg, ...)
+void
+mono_fatal_with_history (const char *msg, ...)
 {
        int i;
        GString* err = g_string_sized_new (100);
-       CheckState *state = get_state ();
 
        g_string_append_printf (err, "Assertion failure in thread %p due to: ", mono_native_thread_id_get ());
 
@@ -161,52 +215,67 @@ assertion_fail (const char *msg, ...)
        g_string_append_vprintf (err, msg, args);
        va_end (args);
 
-       g_string_append_printf (err, "\nLast %d state transitions: (most recent first)\n", state->transitions->len);
-
-       for (i = state->transitions->len - 1; i >= 0; --i) {
-               ThreadTransition *t = state->transitions->pdata [i];
-               char *bt = translate_backtrace (t->backtrace, t->size);
-               g_string_append_printf (err, "[%s] %s -> %s (%d) %s%d at:\n%s",
-                       t->name,
-                       mono_thread_state_name (t->from_state),
-                       mono_thread_state_name (t->next_state),
-                       t->suspend_count,
-                       t->suspend_count_delta > 0 ? "+" : "", //I'd like to see this sort of values: -1, 0, +1
-                       t->suspend_count_delta,
-                       bt);
-               g_free (bt);
+       if (mono_check_mode_enabled (MONO_CHECK_MODE_THREAD))
+       {
+               CheckState *state = get_state ();
+
+               g_string_append_printf (err, "\nLast %d state transitions: (most recent first)\n", state->transitions->len);
+
+               for (i = state->transitions->len - 1; i >= 0; --i) {
+                       ThreadTransition *t = state->transitions->pdata [i];
+                       char *bt = translate_backtrace (t->backtrace, t->size);
+                       g_string_append_printf (err, "[%s] %s -> %s (%d) %s%d at:\n%s",
+                               t->name,
+                               mono_thread_state_name (t->from_state),
+                               mono_thread_state_name (t->next_state),
+                               t->suspend_count,
+                               t->suspend_count_delta > 0 ? "+" : "", //I'd like to see this sort of values: -1, 0, +1
+                               t->suspend_count_delta,
+                               bt);
+                       g_free (bt);
+               }
        }
 
        g_error (err->str);
        g_string_free (err, TRUE);
 }
 
+#endif /* defined(ENABLE_CHECKED_BUILD_THREAD) */
+
+#ifdef ENABLE_CHECKED_BUILD_GC
+
 void
 assert_gc_safe_mode (void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        MonoThreadInfo *cur = mono_thread_info_current ();
        int state;
 
        if (!cur)
-               assertion_fail ("Expected GC Safe mode but thread is not attached");
+               mono_fatal_with_history ("Expected GC Safe mode but thread is not attached");
 
        switch (state = mono_thread_info_current_state (cur)) {
        case STATE_BLOCKING:
        case STATE_BLOCKING_AND_SUSPENDED:
                break;
        default:
-               assertion_fail ("Expected GC Safe mode but was in %s state", mono_thread_state_name (state));
+               mono_fatal_with_history ("Expected GC Safe mode but was in %s state", mono_thread_state_name (state));
        }
 }
 
 void
 assert_gc_unsafe_mode (void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        MonoThreadInfo *cur = mono_thread_info_current ();
        int state;
 
        if (!cur)
-               assertion_fail ("Expected GC Unsafe mode but thread is not attached");
+               mono_fatal_with_history ("Expected GC Unsafe mode but thread is not attached");
 
        switch (state = mono_thread_info_current_state (cur)) {
        case STATE_RUNNING:
@@ -214,18 +283,21 @@ assert_gc_unsafe_mode (void)
        case STATE_SELF_SUSPEND_REQUESTED:
                break;
        default:
-               assertion_fail ("Expected GC Unsafe mode but was in %s state", mono_thread_state_name (state));
+               mono_fatal_with_history ("Expected GC Unsafe mode but was in %s state", mono_thread_state_name (state));
        }
 }
 
 void
 assert_gc_neutral_mode (void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        MonoThreadInfo *cur = mono_thread_info_current ();
        int state;
 
        if (!cur)
-               assertion_fail ("Expected GC Neutral mode but thread is not attached");
+               mono_fatal_with_history ("Expected GC Neutral mode but thread is not attached");
 
        switch (state = mono_thread_info_current_state (cur)) {
        case STATE_RUNNING:
@@ -235,13 +307,16 @@ assert_gc_neutral_mode (void)
        case STATE_BLOCKING_AND_SUSPENDED:
                break;
        default:
-               assertion_fail ("Expected GC Neutral mode but was in %s state", mono_thread_state_name (state));
+               mono_fatal_with_history ("Expected GC Neutral mode but was in %s state", mono_thread_state_name (state));
        }
 }
 
 void *
 critical_gc_region_begin(void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return NULL;
+
        CheckState *state = get_state ();
        state->in_gc_critical_region++;
        return state;
@@ -251,6 +326,9 @@ critical_gc_region_begin(void)
 void
 critical_gc_region_end(void* token)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        CheckState *state = get_state();
        g_assert (state == token);
        state->in_gc_critical_region--;
@@ -259,23 +337,29 @@ critical_gc_region_end(void* token)
 void
 assert_not_in_gc_critical_region(void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        CheckState *state = get_state();
        if (state->in_gc_critical_region > 0) {
-               assertion_fail("Expected GC Unsafe mode, but was in %s state", mono_thread_state_name (mono_thread_info_current_state (mono_thread_info_current ())));
+               mono_fatal_with_history("Expected GC Unsafe mode, but was in %s state", mono_thread_state_name (mono_thread_info_current_state (mono_thread_info_current ())));
        }
 }
 
 void
 assert_in_gc_critical_region (void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        CheckState *state = get_state();
        if (state->in_gc_critical_region == 0)
-               assertion_fail("Expected GC critical region");
+               mono_fatal_with_history("Expected GC critical region");
 }
 
-#endif /* !defined(DISABLE_CHECKED_BUILD_GC) */
+#endif /* defined(ENABLE_CHECKED_BUILD_GC) */
 
-#if !defined(DISABLE_CHECKED_BUILD_METADATA)
+#ifdef ENABLE_CHECKED_BUILD_METADATA
 
 // check_metadata_store et al: The goal of these functions is to verify that if there is a pointer from one mempool into
 // another, that the pointed-to memory is protected by the reference count mechanism for MonoImages.
@@ -543,6 +627,9 @@ mono_find_mempool_owner (void *ptr)
 static void
 check_mempool_may_reference_mempool (void *from_ptr, void *to_ptr, gboolean require_local)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_METADATA))
+               return;
+
        // Null pointers are OK
        if (!to_ptr)
                return;
@@ -610,6 +697,6 @@ check_metadata_store_local (void *from, void *to)
     check_mempool_may_reference_mempool (from, to, TRUE);
 }
 
-#endif /* !defined(DISABLE_CHECKED_BUILD_METADATA) */
+#endif /* defined(ENABLE_CHECKED_BUILD_METADATA) */
 
-#endif /* CHECKED_BUILD */
+#endif /* ENABLE_CHECKED_BUILD */
index 28932d8c630204ff83e6bae5d3cd46cb49f2c062..25e663177ef39760a804e16eae34add0147f2f7a 100644 (file)
 
 #include <config.h>
 #include <mono/utils/atomic.h>
+#include <mono/utils/mono-publib.h>
+
+typedef enum {
+       MONO_CHECK_MODE_NONE = 0,
+       MONO_CHECK_MODE_GC = 0x1,
+       MONO_CHECK_MODE_METADATA = 0x2,
+       MONO_CHECK_MODE_THREAD = 0x4,
+       MONO_CHECK_MODE_ALL = MONO_CHECK_MODE_GC | MONO_CHECK_MODE_METADATA | MONO_CHECK_MODE_THREAD,
+       MONO_CHECK_MODE_UNKNOWN = 0x8
+} MonoCheckMode;
+
+mono_bool mono_check_mode_enabled (MonoCheckMode query);
 
 // This is for metadata writes which we have chosen not to check at the current time.
 // Because in principle this should never happen, we still use a macro so that the exemptions will be easier to find, and remove, later.
 // The current reason why this is needed is for pointers to constant strings, which the checker cannot verify yet.
 #define CHECKED_METADATA_WRITE_PTR_EXEMPT(ptr, val) do { (ptr) = (val); } while (0)
 
-#if defined(CHECKED_BUILD)
+#ifdef ENABLE_CHECKED_BUILD
 
 #define g_assert_checked g_assert
 
@@ -45,10 +57,9 @@ void checked_build_init (void);
 
 #define CHECKED_MONO_INIT()
 
-#endif /* CHECKED_BUILD */
-
-#if defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_GC)
+#endif /* ENABLE_CHECKED_BUILD */
 
+#ifdef ENABLE_CHECKED_BUILD_GC
 /*
 GC runtime modes rules:
 
@@ -149,9 +160,9 @@ void assert_in_gc_critical_region (void);
 #define MONO_REQ_GC_NOT_CRITICAL
 #define MONO_REQ_GC_CRITICAL
 
-#endif /* defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_GC) */
+#endif /* defined(ENABLE_CHECKED_BUILD_GC) */
 
-#if defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_METADATA)
+#ifdef ENABLE_CHECKED_BUILD_METADATA
 
 // Use when writing a pointer from one image or imageset to another.
 #define CHECKED_METADATA_WRITE_PTR(ptr, val) do {    \
@@ -180,9 +191,9 @@ void check_metadata_store_local(void *from, void *to);
 #define CHECKED_METADATA_WRITE_PTR_LOCAL(ptr, val) do { (ptr) = (val); } while (0)
 #define CHECKED_METADATA_WRITE_PTR_ATOMIC(ptr, val) do { mono_atomic_store_release (&(ptr), (val)); } while (0)
 
-#endif /* defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_METADATA) */
+#endif /* defined(ENABLE_CHECKED_BUILD_METADATA) */
 
-#if defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_THREAD)
+#ifdef ENABLE_CHECKED_BUILD_THREAD
 
 #define CHECKED_BUILD_THREAD_TRANSITION(transition, info, from_state, suspend_count, next_state, suspend_count_delta) do {     \
        checked_build_thread_transition (transition, info, from_state, suspend_count, next_state, suspend_count_delta); \
@@ -190,10 +201,14 @@ void check_metadata_store_local(void *from, void *to);
 
 void checked_build_thread_transition(const char *transition, void *info, int from_state, int suspend_count, int next_state, int suspend_count_delta);
 
+void mono_fatal_with_history(const char *msg, ...);
+
 #else
 
 #define CHECKED_BUILD_THREAD_TRANSITION(transition, info, from_state, suspend_count, next_state, suspend_count_delta)
 
-#endif /* defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_THREAD) */
+#define mono_fatal_with_history g_error
+
+#endif /* defined(ENABLE_CHECKED_BUILD_THREAD) */
 
 #endif /* __CHECKED_BUILD_H__ */
index 8fb01856673ecca132b5ab4eee9353a299190322..559998255665b96f3296be7cada14627505ae1c1 100644 (file)
@@ -93,6 +93,15 @@ mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char
 void
 mono_error_set_generic_error (MonoError *error, const char * name_space, const char *name, const char *msg_format, ...);
 
+void
+mono_error_set_execution_engine (MonoError *error, const char *msg_format, ...);
+
+void
+mono_error_set_not_implemented (MonoError *error, const char *msg_format, ...);
+
+void
+mono_error_set_not_supported (MonoError *error, const char *msg_format, ...);
+
 void
 mono_error_set_exception_instance (MonoError *error, MonoException *exc);
 
index b6f2ee0979524b82e12815c5bd57731c7d1886a4..060402021646fad6450924f5d997524eb23afbe9 100644 (file)
 #include <mono/metadata/object.h>
 #include <mono/metadata/object-internals.h>
 
+#define set_error_messagev() do { \
+       if (!(error->full_message = g_strdup_vprintf (msg_format, args))) \
+                       error->flags |= MONO_ERROR_INCOMPLETE; \
+} while (0)
+
 #define set_error_message() do { \
        va_list args; \
        va_start (args, msg_format); \
-       if (!(error->full_message = g_strdup_vprintf (msg_format, args))) \
-                       error->flags |= MONO_ERROR_INCOMPLETE; \
+       set_error_messagev();        \
        va_end (args); \
 } while (0)
 
+static void
+mono_error_set_generic_errorv (MonoError *oerror, const char *name_space, const char *name, const char *msg_format, va_list args);
+
 static gboolean
 is_managed_exception (MonoErrorInternal *error)
 {
@@ -332,14 +339,65 @@ mono_error_set_bad_image (MonoError *oerror, MonoImage *image, const char *msg_f
 }
 
 void
-mono_error_set_generic_error (MonoError *oerror, const char * name_space, const char *name, const char *msg_format, ...)
+mono_error_set_generic_errorv (MonoError *oerror, const char *name_space, const char *name, const char *msg_format, va_list args)
 {
        MonoErrorInternal *error = (MonoErrorInternal*)oerror;
        mono_error_prepare (error);
 
        error->error_code = MONO_ERROR_GENERIC;
        mono_error_set_corlib_exception (oerror, name_space, name);
-       set_error_message ();
+       set_error_messagev ();
+}
+
+void
+mono_error_set_generic_error (MonoError *oerror, const char * name_space, const char *name, const char *msg_format, ...)
+{
+       va_list args;
+       va_start (args, msg_format);
+       mono_error_set_generic_errorv (oerror, name_space, name, msg_format, args);
+       va_end (args);
+}
+
+/**
+ * mono_error_set_not_implemented:
+ *
+ * System.NotImplementedException
+ */
+void
+mono_error_set_not_implemented (MonoError *oerror, const char *msg_format, ...)
+{
+       va_list args;
+       va_start (args, msg_format);
+       mono_error_set_generic_errorv (oerror, "System", "NotImplementedException", msg_format, args);
+       va_end (args);
+}
+
+/**
+ * mono_error_set_execution_engine:
+ *
+ * System.ExecutionEngineException
+ */
+void
+mono_error_set_execution_engine (MonoError *oerror, const char *msg_format, ...)
+{
+       va_list args;
+       va_start (args, msg_format);
+       mono_error_set_generic_errorv (oerror, "System", "ExecutionEngineException", msg_format, args);
+       va_end (args);
+}
+
+/**
+ * mono_error_set_execution_engine:
+ *
+ * System.NotSupportedException
+ */
+void
+mono_error_set_not_supported (MonoError *oerror, const char *msg_format, ...)
+{
+       va_list args;
+       va_start (args, msg_format);
+       mono_error_set_generic_errorv (oerror, "System", "NotSupportedException", msg_format, args);
+       va_end (args);
 }
 
 void
@@ -362,13 +420,13 @@ mono_error_set_from_loader_error (MonoError *oerror)
        mono_error_prepare (error);
 
        if (!loader_error) {
-               mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Runtime tried to produce a mono-error from an empty loader-error");
+               mono_error_set_execution_engine (oerror, "Runtime tried to produce a mono-error from an empty loader-error");
                return;
        }
 
        switch (loader_error->exception_type) {
        case MONO_EXCEPTION_NONE:
-               mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Runtime tried to produce a mono-error from a non-error loader-error");
+               mono_error_set_execution_engine (oerror, "Runtime tried to produce a mono-error from a non-error loader-error");
                break;
 
        case MONO_EXCEPTION_INVALID_PROGRAM:
@@ -409,7 +467,7 @@ mono_error_set_from_loader_error (MonoError *oerror)
 
        case MONO_EXCEPTION_OBJECT_SUPPLIED:
        case MONO_EXCEPTION_GENERIC_SHARING_FAILED:
-               mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Runtime tried to produce a mono-error from JIT internal error %d", loader_error->exception_type);
+               mono_error_set_execution_engine (oerror, "Runtime tried to produce a mono-error from JIT internal error %d", loader_error->exception_type);
                break;
 
        case MONO_EXCEPTION_BAD_IMAGE:
@@ -421,7 +479,7 @@ mono_error_set_from_loader_error (MonoError *oerror)
                break;
 
        default:
-               mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Runtime tried to produce an unknown loader-error %d", loader_error->exception_type);
+               mono_error_set_execution_engine (oerror, "Runtime tried to produce an unknown loader-error %d", loader_error->exception_type);
                break;
        }
 
@@ -683,7 +741,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
        }
        case MONO_ERROR_GENERIC:
                if (!error->exception_name_space || !error->exception_name)
-                       mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "MonoError with generic error but no exception name was supplied");
+                       mono_error_set_execution_engine (error_out, "MonoError with generic error but no exception name was supplied");
                else
                        exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, error->full_message);
                break;
@@ -693,7 +751,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
                break;
 
        default:
-               mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "Invalid error-code %d", error->error_code);
+               mono_error_set_execution_engine (error_out, "Invalid error-code %d", error->error_code);
        }
 
        if (!mono_error_ok (error_out))
index 9762dc5142666639ea57ad2cbeecbf334a39b680..fbb87cff574175996469db0a1ac3b10586a4fcef 100644 (file)
@@ -157,17 +157,17 @@ Acquire/release semantics macros.
 #define mono_atomic_load_release(_type,target) ({      \
        _type __tmp;    \
        LOAD_RELEASE_FENCE;     \
-       __tmp = *target;        \
+       __tmp = *(target);      \
        __tmp; })
 
 #define mono_atomic_load_acquire(var,_type,target) do {        \
-       _type __tmp = *target;  \
+       _type __tmp = *(target);        \
        LOAD_ACQUIRE_FENCE;     \
        (var) = __tmp; \
 } while (0)
 
 #define mono_atomic_store_acquire(target,value) {      \
-       *target = value;        \
+       *(target) = (value);    \
        STORE_ACQUIRE_FENCE;    \
        }
 
index 1e20760e898ebc9ef10350fe86143811b2e92cfe..d1e4bb2c496963979c87d0fbe3cffa9a006e5a9d 100644 (file)
@@ -123,7 +123,7 @@ mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gint buffer_size, Mon
                        /* exception will be thrown in managed code */
                        CryptReleaseContext (provider, 0);
                        *handle = 0;
-                       mono_error_set_generic_error (error, "System", "ExecutionEngineException", "Failed to gen random bytes (%d)", GetLastError ());
+                       mono_error_set_execution_engine (error, "Failed to gen random bytes (%d)", GetLastError ());
                        return FALSE;
                }
        }
@@ -186,7 +186,7 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr
                if (file >= 0)
                        close (file);
                g_warning ("Entropy problem! Can't create or connect to egd socket %s", path);
-               mono_error_set_generic_error (error, "System", "ExecutionEngineException", "Failed to open egd socket %s: %s", path, strerror (err));
+               mono_error_set_execution_engine (error, "Failed to open egd socket %s: %s", path, strerror (err));
                return;
        }
 
@@ -207,7 +207,7 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr
                        } else {
                                close (file);
                                g_warning ("Send egd request failed %d", err);
-                               mono_error_set_generic_error (error, "System", "ExecutionEngineException", "Failed to send request to egd socket: %s", strerror (err));
+                               mono_error_set_execution_engine (error, "Failed to send request to egd socket: %s", strerror (err));
                                return;
                        }
                }
@@ -225,7 +225,7 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr
                        } else {
                                close (file);
                                g_warning ("Receive egd request failed %d", err);
-                               mono_error_set_generic_error (error, "System", "ExecutionEngineException", "Failed to get response from egd socket: %s", strerror(err));
+                               mono_error_set_execution_engine (error, "Failed to get response from egd socket: %s", strerror(err));
                                return;
                        }
                }
@@ -295,7 +295,7 @@ mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gint buffer_size, Mon
                                        continue;
                                g_warning("Entropy error! Error in read (%s).", strerror (errno));
                                /* exception will be thrown in managed code */
-                               mono_error_set_generic_error (error, "System", "ExecutionEngineException", "Entropy error! Error in read (%s).", strerror (errno));
+                               mono_error_set_execution_engine (error, "Entropy error! Error in read (%s).", strerror (errno));
                                return FALSE;
                        }
                        count += err;
index fbe798eeb0e6321667023429bfc88b4cb65bb1ce..94335964cd08a58b4c50f791f171ef2b1ffe50fd 100644 (file)
@@ -9,10 +9,53 @@
 
 #include "config.h"
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/utils/mono-signal-handler.h"
+/*
+ * When a signal is delivered to a thread on a Krait Android device
+ * that's in the middle of skipping over an "IT" block, such as this
+ * one:
+ *
+ * 0x40184ef0 <dlfree+1308>:   ldr     r1, [r3, #0]
+ * 0x40184ef2 <dlfree+1310>:   add.w   r5, r12, r2, lsl #3
+ * 0x40184ef6 <dlfree+1314>:   lsls.w  r2, r0, r2
+ * 0x40184efa <dlfree+1318>:   tst     r2, r1
+ * ### this is the IT instruction
+ * 0x40184efc <dlfree+1320>:   itt     eq
+ * 0x40184efe <dlfree+1322>:   orreq   r2, r1
+ * ### signal arrives here
+ * 0x40184f00 <dlfree+1324>:   streq   r2, [r3, #0]
+ * 0x40184f02 <dlfree+1326>:   beq.n   0x40184f1a <dlfree+1350>
+ * 0x40184f04 <dlfree+1328>:   ldr     r2, [r5, #8]
+ * 0x40184f06 <dlfree+1330>:   ldr     r3, [r3, #16]
+ *
+ * then the first few (at most four, one would assume) instructions of
+ * the signal handler (!) might be skipped.  They happen to be the
+ * push of the frame pointer and return address, so once the signal
+ * handler has done its work, it returns into a SIGSEGV.
+ */
+
+#if defined (TARGET_ARM) && defined (HAVE_ARMV7) && defined (TARGET_ANDROID)
+#define KRAIT_IT_BUG_WORKAROUND        1
+#endif
+
+#ifdef KRAIT_IT_BUG_WORKAROUND
+#define MONO_SIGNAL_HANDLER_FUNC(access, name, arglist)                \
+       static void __krait_ ## name arglist;   \
+       __attribute__ ((naked)) access void                             \
+       name arglist                                                    \
+       {                                                               \
+               asm volatile (                                          \
+                             "mov r0, r0\n\t"                          \
+                             "mov r0, r0\n\t"                          \
+                             "mov r0, r0\n\t"                          \
+                             "mov r0, r0\n\t");                        \
+               asm volatile (                                          \
+                             "bx %0"                                   \
+                             : : "r" (__krait_ ## name));              \
+       }       \
+       static void __krait_ ## name arglist
 #endif
 
+
 /* Don't use this */
 #ifndef MONO_SIGNAL_HANDLER_FUNC
 #define MONO_SIGNAL_HANDLER_FUNC(access, name, arglist) access void name arglist
index 3b11148aafe3af5d8c7ff2d93368bb3033da1e10..20740b3dcd1d330bc943bc5ca3320b9cacd39f77 100644 (file)
@@ -25,6 +25,7 @@
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-threads-coop.h>
 #include <mono/utils/mono-threads-api.h>
+#include <mono/utils/checked-build.h>
 
 #ifdef TARGET_OSX
 #include <mono/utils/mach-support.h>
 
 volatile size_t mono_polling_required;
 
+// FIXME: This would be more efficient if instead of instantiating the stack it just pushed a simple depth counter up and down,
+// perhaps with a per-thread cookie in the high bits.
+#ifdef ENABLE_CHECKED_BUILD_GC
+// Maintains a single per-thread stack of ints, used to ensure nesting is not violated
+MonoNativeTlsKey coop_reset_count_stack_key;
+static int coop_tls_push (int v) {
+       GArray *stack = mono_native_tls_get_value (coop_reset_count_stack_key);
+       if (!stack) {
+               stack = g_array_new (FALSE,FALSE,sizeof(int));
+               mono_native_tls_set_value (coop_reset_count_stack_key, stack);
+       }
+       g_array_append_val (stack, v);
+       return stack->len;
+}
+static int coop_tls_pop (int *v) {
+       GArray *stack = mono_native_tls_get_value (coop_reset_count_stack_key);
+       if (!stack || 0 == stack->len)
+               return -1;
+       stack->len--;
+       *v = g_array_index (stack, int, stack->len);
+       int len = stack->len;
+       if (0 == len) {
+               g_array_free (stack,TRUE);
+               mono_native_tls_set_value (coop_reset_count_stack_key, NULL);
+       }
+       return len;
+}
+#endif
+
 static int coop_reset_blocking_count;
 static int coop_try_blocking_count;
 static int coop_do_blocking_count;
@@ -193,9 +223,18 @@ mono_threads_reset_blocking_start (void* stackdata)
        if (!mono_threads_is_coop_enabled ())
                return NULL;
 
+       info = mono_thread_info_current_unchecked ();
+
+#ifdef ENABLE_CHECKED_BUILD_GC
+       int reset_blocking_count = InterlockedIncrement (&coop_reset_blocking_count);
+       // In this mode, the blocking count is used as the reset cookie. We would prefer
+       // (but do not require) this to be unique across invocations and threads.
+       if (reset_blocking_count == 0) // We *do* require it be nonzero
+               reset_blocking_count = coop_reset_blocking_count = 1;
+#else
        ++coop_reset_blocking_count;
+#endif
 
-       info = mono_thread_info_current_unchecked ();
        /* If the thread is not attached, it doesn't make sense prepare for suspend. */
        if (!info || !mono_thread_info_is_live (info))
                return NULL;
@@ -211,28 +250,50 @@ mono_threads_reset_blocking_start (void* stackdata)
                return NULL;
        case AbortBlockingOk:
                info->thread_saved_state [SELF_SUSPEND_STATE_INDEX].valid = FALSE;
-               return info;
+               break;
        case AbortBlockingOkAndPool:
                mono_threads_state_poll ();
-               return info;
+               break;
        default:
                g_error ("Unknown thread state");
        }
+
+#ifdef ENABLE_CHECKED_BUILD_GC
+       if (mono_check_mode_enabled (MONO_CHECK_MODE_GC)) {
+               int level = coop_tls_push (reset_blocking_count);
+               //g_warning("Entering reset nest; level %d; cookie %d\n", level, reset_blocking_count);
+               return (void *)(intptr_t)reset_blocking_count;
+       }
+#endif
+
+       return info;
 }
 
 void
 mono_threads_reset_blocking_end (void *cookie, void* stackdata)
 {
-       MonoThreadInfo *info;
-
        if (!mono_threads_is_coop_enabled ())
                return;
 
-       info = (MonoThreadInfo *)cookie;
-       if (!info)
+       if (!cookie)
                return;
 
-       g_assert (info == mono_thread_info_current_unchecked ());
+#ifdef ENABLE_CHECKED_BUILD_GC
+       if (mono_check_mode_enabled (MONO_CHECK_MODE_GC)) {
+               int received_cookie = (int)(intptr_t)cookie;
+               int desired_cookie;
+               int level = coop_tls_pop (&desired_cookie);
+               //g_warning("Leaving reset nest; back to level %d; desired cookie %d; received cookie %d\n", level, desired_cookie, received_cookie);
+               if (level < 0)
+                       mono_fatal_with_history ("Expected cookie %d but found no stack at all\n", desired_cookie);
+               if (desired_cookie != received_cookie)
+                       mono_fatal_with_history ("Expected cookie %d but received %d\n", desired_cookie, received_cookie);
+       } else // Notice this matches the line after the endif
+#endif
+       {
+               g_assert (((MonoThreadInfo *)cookie) == mono_thread_info_current_unchecked ());
+       }
+
        mono_threads_prepare_blocking (stackdata);
 }
 
@@ -248,6 +309,10 @@ mono_threads_init_coop (void)
        mono_counters_register ("Coop Do Polling", MONO_COUNTER_GC | MONO_COUNTER_INT, &coop_do_polling_count);
        mono_counters_register ("Coop Save Count", MONO_COUNTER_GC | MONO_COUNTER_INT, &coop_save_count);
        //See the above for what's wrong here.
+
+#ifdef ENABLE_CHECKED_BUILD_GC
+       mono_native_tls_alloc (&coop_reset_count_stack_key, NULL);
+#endif
 }
 
 void
index d130a13613de89b78e4ee113cec9bc4806f74c9f..32491a4ca225229e622799504f8d7cc6012c031c 100644 (file)
@@ -113,7 +113,7 @@ retry_state_change:
                trace_state_change ("ATTACH", info, raw_state, STATE_RUNNING, 0);
                break;
        default:
-               g_error ("Cannot transition current thread from %s with ATTACH", state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition current thread from %s with ATTACH", state_name (cur_state));
        }
 }
 
@@ -148,7 +148,7 @@ STATE_BLOCKING: This is a bug in the coop code that forgot to do a finish blocki
 STATE_BLOCKING_AND_SUSPENDED: This is a bug in coop x suspend that resulted the thread in an undetachable state.
 */
        default:
-               g_error ("Cannot transition current thread %p from %s with DETACH", info, state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition current thread %p from %s with DETACH", info, state_name (cur_state));
        }
 }
 
@@ -190,7 +190,7 @@ STATE_BLOCKING_AND_SUSPENDED: Self suspension cannot be started when the thread
 If this turns to be an issue we can introduce a new suspend request state for when both have been requested.
 */
        default:
-               g_error ("Cannot transition thread %p from %s with SUSPEND_REQUEST", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with SUSPEND_REQUEST", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -252,7 +252,7 @@ The expected behavior is that the target should poll its state very soon so the
 STATE_ASYNC_SUSPEND_REQUESTED: Since there can only be one async suspend in progress and it must finish, it should not be possible to witness this.
 */
        default:
-               g_error ("Cannot transition thread %p from %s with ASYNC_SUSPEND_REQUESTED", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with ASYNC_SUSPEND_REQUESTED", mono_thread_info_get_tid (info), state_name (cur_state));
        }
        return (MonoRequestAsyncSuspendResult) FALSE;
 }
@@ -301,7 +301,7 @@ STATE_BLOCKING:
 STATE_BLOCKING_AND_SUSPENDED: Pool is a local state transition. No VM activities are allowed while in blocking mode.
 */
        default:
-               g_error ("Cannot transition thread %p from %s with STATE_POLL", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with STATE_POLL", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -401,7 +401,7 @@ If this turns to be a problem we should either implement [2] or make this an inv
 
 */
        default:
-               g_error ("Cannot transition thread %p from %s with REQUEST_RESUME", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with REQUEST_RESUME", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -437,7 +437,7 @@ STATE_SELF_SUSPEND_REQUESTED: When self suspend and async suspend happen togethe
 STATE_BLOCKING: Async suspend only begins if a transition to async suspend requested happened. Blocking would have put us into blocking with positive suspend count if it raced with async finish.
 */
        default:
-               g_error ("Cannot transition thread %p from %s with FINISH_ASYNC_SUSPEND", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with FINISH_ASYNC_SUSPEND", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -481,7 +481,7 @@ STATE_BLOCKING_AND_SUSPENDED
 STATE_SELF_SUSPEND_REQUESTED: All those are invalid end states of a sucessfull finish async suspend
 */
        default:
-               g_error ("Cannot transition thread %p from %s with COMPENSATE_FINISH_ASYNC_SUSPEND", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with COMPENSATE_FINISH_ASYNC_SUSPEND", mono_thread_info_get_tid (info), state_name (cur_state));
 
        }
 }
@@ -526,7 +526,7 @@ STATE_BLOCKING:
 STATE_BLOCKING_AND_SUSPENDED: Blocking is not nestabled
 */
        default:
-               g_error ("Cannot transition thread %p from %s with DO_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with DO_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -574,7 +574,7 @@ STATE_SELF_SUSPEND_REQUESTED: A blocking operation must not be done while trying
 STATE_BLOCKING_AND_SUSPENDED: This an exit state of done blocking
 */
        default:
-               g_error ("Cannot transition thread %p from %s with DONE_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with DONE_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -624,7 +624,7 @@ STATE_SELF_SUSPEND_REQUESTED: A blocking operation must not be done while trying
 STATE_BLOCKING_AND_SUSPENDED: This is an exit state of done blocking, can't happen here.
 */
        default:
-               g_error ("Cannot transition thread %p from %s with DONE_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with DONE_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
index 258f984d8e339e04ee1d49141e3f085ff31d6131..8bcf531528280627f8ed9d8852b4384f8ee4bf65 100644 (file)
     <ClCompile Include="..\mono\sgen\sgen-pinning-stats.c" />\r
     <ClCompile Include="..\mono\sgen\sgen-pinning.c" />\r
     <ClCompile Include="..\mono\sgen\sgen-pointer-queue.c" />\r
+    <ClCompile Include="..\mono\sgen\sgen-array-list.c" />\r
     <ClCompile Include="..\mono\sgen\sgen-protocol.c" />\r
     <ClCompile Include="..\mono\sgen\sgen-qsort.c" />\r
     <ClCompile Include="..\mono\sgen\sgen-simple-nursery.c" />\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
   <ImportGroup Label="ExtensionTargets">\r
   </ImportGroup>\r
-</Project>
\ No newline at end of file
+</Project>\r
index 7fdb42da30f9b14b6a27af1ed0953777ae946d31..223b73852dcbf3762ccd27934beb22ddf5e87687 100644 (file)
@@ -88,7 +88,7 @@ clean-local:
 
 endif BUILD_MCS
 
-TEST_SUPPORT_FILES = $(tmpinst)/bin/mono $(tmpinst)/bin/ilasm $(tmpinst)/bin/mcs $(tmpinst)/bin/dmcs $(tmpinst)/bin/al2 $(tmpinst)/bin/al
+TEST_SUPPORT_FILES = $(tmpinst)/bin/mono $(tmpinst)/bin/ilasm $(tmpinst)/bin/mcs $(tmpinst)/bin/al
 
 mcs-do-test-profiles:
        cd $(mcs_topdir) && $(MAKE) NO_DIR_CHECK=1 PROFILES='$(test_profiles)' test-profiles
@@ -168,24 +168,12 @@ $(tmpinst)/bin/mcs: $(tmpinst)/bin/mono Makefile
        echo 'exec "'"$$r/$(tmpinst)/bin/mono"'" "'"$$m/class/lib/build/mcs.exe"'" "$$@"' >> $@ ; \
        chmod +x $@
 
-$(tmpinst)/bin/dmcs: $(tmpinst)/bin/mono Makefile
-       echo '#! /bin/sh' > $@ ; \
-       r=`pwd`; m=`cd $(mcs_topdir) && pwd`; \
-       echo 'exec "'"$$r/$(tmpinst)/bin/mono"'" "'"$$m/class/lib/build/mcs.exe -sdk:4"'" "$$@"' >> $@ ; \
-       chmod +x $@
-
 $(tmpinst)/bin/ilasm: $(tmpinst)/bin/mono Makefile
        echo '#! /bin/sh' > $@ ; \
        r=`pwd`; m=`cd $(mcs_topdir) && pwd`; \
        echo 'exec "'"$$r/$(tmpinst)/bin/mono"'" "'"$$m/ilasm/ilasm.exe"'" "$$@"' >> $@ ; \
        chmod +x $@
 
-$(tmpinst)/bin/al2: $(tmpinst)/bin/mono Makefile
-       echo '#! /bin/sh' > $@ ; \
-       r=`pwd`; m=`cd $(mcs_topdir) && pwd`; \
-       echo 'exec "'"$$r/$(tmpinst)/bin/mono"'" "'"$$m/class/lib/net_2_0/al.exe"'" "$$@"' >> $@ ; \
-       chmod +x $@
-
 $(tmpinst)/bin/al: $(tmpinst)/bin/mono Makefile
        echo '#! /bin/sh' > $@ ; \
        r=`pwd`; m=`cd $(mcs_topdir) && pwd`; \
index ff7bc4bfdadb8ed3536d91b0887d16f9a6a2e0d4..a036cf1f8dbc283329b0c3c07ec21baf97d9f750 100644 (file)
@@ -50,6 +50,7 @@
 /mono-abi-info
 /mono-api-diff
 /mono-api-info
+/mono-api-html
 /mono-api-info1
 /mono-api-info2
 /mono-cil-strip
index d23bb676601ade72453fbacac11f8fba9996f1a7..be4d6b164a009018668e73beac1c186eb1666e03 100644 (file)
@@ -84,6 +84,7 @@ scripts_4_0 = \
        mod$(SCRIPT_SUFFIX)                     \
        monolinker$(SCRIPT_SUFFIX)              \
        mono-api-info$(SCRIPT_SUFFIX)           \
+       mono-api-html$(SCRIPT_SUFFIX)           \
        mono-shlib-cop$(SCRIPT_SUFFIX)          \
        mozroots$(SCRIPT_SUFFIX)                \
        permview$(SCRIPT_SUFFIX)                \