Merge pull request #2816 from xmcclure/profile-clean-0
authormonojenkins <jo.shields+jenkins@xamarin.com>
Thu, 31 Mar 2016 19:05:17 +0000 (20:05 +0100)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Thu, 31 Mar 2016 19:05:17 +0000 (20:05 +0100)
Various cleanups on profiler

3 commits:

Assist on profiler module loading

- Add a MONO_PROFILER_LIB_DIR from which profiler modules are
  dynamically loading, in case it is not the normal library path
- Add information about profiler loading to mono_trace

Comments and clarity in proflog.c

- Add comments on structures
- Rename 'data' and 'data_end' to 'cursor' and 'buf_end' in LogBuffer/StatsBuffer as the old names were confusing
- Add new assert when processing samples

Improve a safety check when writing data into StatBuffer

- The safety check should occur such that if the new value for
StatBuffer::cursor is beyond the bounds of the StatBuffer, the cursor
is not updated.

492 files changed:
CONTRIBUTING.md
COPYING.LIB
LICENSE
PATENTS.TXT [new file with mode: 0644]
README.md
acceptance-tests/SUBMODULES.json
acceptance-tests/ms-test-suite.mk
acceptance-tests/roslyn.mk
configure.ac
external/referencesource
man/mono.1
mcs/COPYING.LIB [deleted file]
mcs/LICENSE [deleted file]
mcs/LICENSE.CC [deleted file]
mcs/LICENSE.GPL [deleted file]
mcs/LICENSE.LGPL [deleted file]
mcs/LICENSE.MPL [deleted file]
mcs/LICENSE.MSPL [deleted file]
mcs/MIT.X11 [deleted file]
mcs/Makefile
mcs/README
mcs/build/Makefile
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/Mono.Security/monotouch_Mono.Security.dll.sources
mcs/class/Mono.Security/monotouch_opt_Mono.Security.dll.sources [deleted file]
mcs/class/Mono.Security/xammac_Mono.Security.dll.sources
mcs/class/Mono.Security/xammac_opt_Mono.Security.dll.sources [deleted file]
mcs/class/Mono.WebBrowser/tools/xpidl2cs/xpidl2cs.pl
mcs/class/System.Core/monotouch_System.Core.dll.sources
mcs/class/System.Core/xammac_System.Core.dll.sources
mcs/class/System.IO.Compression.FileSystem/Makefile
mcs/class/System.IO.Compression/Makefile
mcs/class/System.Net.Http/System.Net.Http/HttpClient.mac.cs [new file with mode: 0644]
mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs
mcs/class/System.Net.Http/xammac_System.Net.Http.dll.sources
mcs/class/System.Net.Http/xammac_net_4_5_System.Net.Http.dll.sources
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.Runtime.Serialization/ReferenceSources/XmlFormatWriterGenerator_static.cs
mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/DataContractSerializerTest.cs
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/Assembly/AssemblyInfoEx.cs [new file with mode: 0644]
mcs/class/System/Mono.Net.Security/ChainValidationHelper.cs
mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.MonoTouch.opt.cs [deleted file]
mcs/class/System/Mono.Net.Security/MonoTlsProviderFactoryExt.cs [new file with mode: 0644]
mcs/class/System/Mono.Net.Security/SystemCertificateValidator.cs
mcs/class/System/Mono.Security.Interface/MonoTlsProviderFactoryExt.cs [new file with mode: 0644]
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.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/System/monotouch_System.dll.sources
mcs/class/System/monotouch_opt_System.dll.sources [deleted file]
mcs/class/System/monotouch_runtime_opt_System.dll.sources [deleted file]
mcs/class/System/monotouch_tv_opt_System.dll.sources [deleted file]
mcs/class/System/monotouch_tv_runtime_opt_System.dll.sources [deleted file]
mcs/class/System/monotouch_watch_opt_System.dll.sources [deleted file]
mcs/class/System/monotouch_watch_runtime_opt_System.dll.sources [deleted file]
mcs/class/System/xammac_System.dll.sources
mcs/class/System/xammac_net_4_5_System.dll.sources
mcs/class/System/xammac_net_4_5_opt_System.dll.sources [deleted file]
mcs/class/System/xammac_opt_System.dll.sources [deleted file]
mcs/class/corlib/CommonCrypto/.gitignore [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/CommonCrypto.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/CommonCryptorGenerator.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/CommonDigestGenerator.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/CorlibExtras.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/CryptorTransform.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/FastCryptorTransform.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/Makefile.include [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/RC4CommonCrypto.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/RijndaelManaged.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/SecRandom.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/generator.cs [new file with mode: 0644]
mcs/class/corlib/CoreFoundation/CFHelpers.cs [new file with mode: 0644]
mcs/class/corlib/Makefile
mcs/class/corlib/System.Diagnostics/StackFrame.cs
mcs/class/corlib/System.Diagnostics/StackTrace.cs
mcs/class/corlib/System.Diagnostics/StackTraceHelper.cs [new file with mode: 0644]
mcs/class/corlib/System.IO/FileInfo.cs
mcs/class/corlib/System.Runtime.InteropServices/GCHandle.cs
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/X509CertificateImplApple.cs [new file with mode: 0644]
mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509CertificateImplMono.cs
mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs [new file with mode: 0644]
mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Helper.MonoTouch.opt.cs [deleted file]
mcs/class/corlib/System.Text/EncodingHelper.MonoTouch.cs [new file with mode: 0644]
mcs/class/corlib/System.Text/EncodingHelper.MonoTouch.opt.cs [deleted file]
mcs/class/corlib/System/Console.cs
mcs/class/corlib/System/Environment.MonoTouch.opt.cs [deleted file]
mcs/class/corlib/System/Environment.iOS.cs [new file with mode: 0644]
mcs/class/corlib/System/Guid.MonoTouch.cs [new file with mode: 0644]
mcs/class/corlib/System/Guid.MonoTouch.opt.cs [deleted file]
mcs/class/corlib/System/NotSupportedException.iOS.cs [new file with mode: 0644]
mcs/class/corlib/Test/System.IO/FileInfoTest.cs
mcs/class/corlib/corlib.dll.sources
mcs/class/corlib/monotouch_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_corlib.dll.sources
mcs/class/corlib/monotouch_opt_corlib.dll.sources [deleted file]
mcs/class/corlib/monotouch_runtime_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_runtime_corlib.dll.sources
mcs/class/corlib/monotouch_runtime_opt_corlib.dll.sources [deleted file]
mcs/class/corlib/monotouch_tv_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_tv_corlib.dll.sources
mcs/class/corlib/monotouch_tv_opt_corlib.dll.sources [deleted file]
mcs/class/corlib/monotouch_tv_runtime_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_tv_runtime_opt_corlib.dll.sources [deleted file]
mcs/class/corlib/monotouch_watch_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_watch_corlib.dll.sources
mcs/class/corlib/monotouch_watch_opt_corlib.dll.sources [deleted file]
mcs/class/corlib/monotouch_watch_runtime_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_watch_runtime_opt_corlib.dll.sources [deleted file]
mcs/class/corlib/xammac_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/xammac_corlib.dll.sources
mcs/class/corlib/xammac_opt_corlib.dll.sources [deleted file]
mcs/mcs/constant.cs
mcs/mcs/settings.cs
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/corcompare/Makefile
mcs/tools/gacutil/driver.cs
mcs/tools/mkbundle/mkbundle.cs
mcs/tools/mono-symbolicate/LocationProvider.cs
mcs/tools/mono-symbolicate/SeqPointInfo.cs [new file with mode: 0644]
mcs/tools/mono-symbolicate/mono-symbolicate.exe.sources
mono/arch/amd64/amd64-codegen.h
mono/arch/arm/arm-codegen.h
mono/arch/arm/arm-vfp-codegen.h
mono/arch/arm/arm-wmmx.h
mono/arch/arm64/arm64-codegen.h
mono/arch/mips/mips-codegen.h
mono/arch/ppc/ppc-codegen.h
mono/arch/s390x/s390x-codegen.h
mono/arch/x86/x86-codegen.h
mono/dis/declsec.c
mono/dis/declsec.h
mono/dis/get.c
mono/dis/main.c
mono/io-layer/handles.c
mono/io-layer/io-portability.c
mono/io-layer/io-portability.h
mono/io-layer/io-private.h
mono/io-layer/io-trace.h
mono/io-layer/io.c
mono/io-layer/locking.c
mono/io-layer/posix.c
mono/io-layer/processes.c
mono/io-layer/wthreads.c
mono/metadata/abi-details.h
mono/metadata/appdomain.c
mono/metadata/appdomain.h
mono/metadata/assembly.c
mono/metadata/attach.c
mono/metadata/boehm-gc.c
mono/metadata/class-internals.h
mono/metadata/class.c
mono/metadata/cominterop.c
mono/metadata/console-io.h
mono/metadata/console-null.c
mono/metadata/console-unix.c
mono/metadata/console-win32.c
mono/metadata/coree.c
mono/metadata/coree.h
mono/metadata/debug-helpers.c
mono/metadata/debug-mono-ppdb.c
mono/metadata/debug-mono-ppdb.h
mono/metadata/debug-mono-symfile.c
mono/metadata/debug-mono-symfile.h
mono/metadata/domain-internals.h
mono/metadata/domain.c
mono/metadata/environment.c
mono/metadata/exception.c
mono/metadata/file-io.c
mono/metadata/file-io.h
mono/metadata/file-mmap-posix.c
mono/metadata/file-mmap-windows.c
mono/metadata/file-mmap.h
mono/metadata/filewatcher.c
mono/metadata/gc-internals.h
mono/metadata/gc-stats.c
mono/metadata/gc.c
mono/metadata/handle.c
mono/metadata/handle.h
mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/image-internals.h
mono/metadata/image.c
mono/metadata/jit-info.c
mono/metadata/loader.c
mono/metadata/locales.c
mono/metadata/marshal.c
mono/metadata/mempool.c
mono/metadata/metadata-cross-helpers.c
mono/metadata/metadata-verify.c
mono/metadata/metadata.c
mono/metadata/method-builder.c
mono/metadata/monitor.c
mono/metadata/mono-basic-block.c
mono/metadata/mono-basic-block.h
mono/metadata/mono-config-dirs.c
mono/metadata/mono-config.c
mono/metadata/mono-debug.c
mono/metadata/mono-endian.c
mono/metadata/mono-hash.h
mono/metadata/mono-mlist.c
mono/metadata/mono-perfcounters.c
mono/metadata/mono-security.c
mono/metadata/null-gc.c
mono/metadata/number-ms.c
mono/metadata/object-internals.h
mono/metadata/object-offsets.h
mono/metadata/object.c
mono/metadata/object.h
mono/metadata/opcodes.c
mono/metadata/pedump.c
mono/metadata/process.c
mono/metadata/profiler.c
mono/metadata/rand.c
mono/metadata/rand.h
mono/metadata/reflection-internals.h
mono/metadata/reflection.c
mono/metadata/reflection.h
mono/metadata/remoting.c
mono/metadata/runtime.c
mono/metadata/security-core-clr.c
mono/metadata/security-core-clr.h
mono/metadata/security-manager.c
mono/metadata/security-manager.h
mono/metadata/seq-points-data.h
mono/metadata/sgen-bridge-internals.h
mono/metadata/sgen-bridge.c
mono/metadata/sgen-bridge.h
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/sgen-os-coop.c
mono/metadata/sgen-os-mach.c
mono/metadata/sgen-os-posix.c
mono/metadata/sgen-stw.c
mono/metadata/sgen-tarjan-bridge.c
mono/metadata/sgen-toggleref.c
mono/metadata/sgen-toggleref.h
mono/metadata/socket-io.c
mono/metadata/string-icalls.c
mono/metadata/sysmath.c
mono/metadata/sysmath.h
mono/metadata/threadpool-ms-io.c
mono/metadata/threadpool-ms.c
mono/metadata/threadpool-ms.h
mono/metadata/threads-types.h
mono/metadata/threads.c
mono/metadata/verify.c
mono/mini/Makefile.am.in
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/arch-stubs.c
mono/mini/bench.cs
mono/mini/branch-opts.c
mono/mini/cpu-arm.md
mono/mini/cpu-arm64.md
mono/mini/debugger-agent.c
mono/mini/decompose.c
mono/mini/dominators.c
mono/mini/driver.c
mono/mini/dwarfwriter.c
mono/mini/dwarfwriter.h
mono/mini/exceptions-amd64.c
mono/mini/exceptions-arm.c
mono/mini/exceptions-arm64.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/gshared.cs
mono/mini/image-writer.c
mono/mini/jit-icalls.c
mono/mini/liveness.c
mono/mini/llvm-jit.cpp
mono/mini/local-propagation.c
mono/mini/method-to-ir.c
mono/mini/mini-amd64-gsharedvt.c [new file with mode: 0644]
mono/mini/mini-amd64-gsharedvt.h [new file with mode: 0644]
mono/mini/mini-amd64.c
mono/mini/mini-amd64.h
mono/mini/mini-arm-gsharedvt.c [new file with mode: 0644]
mono/mini/mini-arm-tls.S
mono/mini/mini-arm.c
mono/mini/mini-arm.h
mono/mini/mini-arm64-gsharedvt.c [new file with mode: 0644]
mono/mini/mini-arm64-gsharedvt.h [new file with mode: 0644]
mono/mini/mini-arm64.c
mono/mini/mini-arm64.h
mono/mini/mini-cross-helpers.c
mono/mini/mini-darwin.c
mono/mini/mini-exceptions-native-unwinder.c [new file with mode: 0644]
mono/mini/mini-exceptions.c
mono/mini/mini-gc.c
mono/mini/mini-generic-sharing.c
mono/mini/mini-llvm-cpp.cpp
mono/mini/mini-llvm.c
mono/mini/mini-native-types.c
mono/mini/mini-ops.h
mono/mini/mini-posix.c
mono/mini/mini-runtime.c
mono/mini/mini-trampolines.c
mono/mini/mini-windows.c
mono/mini/mini-x86-gsharedvt.c [new file with mode: 0644]
mono/mini/mini-x86.c
mono/mini/mini-x86.h
mono/mini/mini.c
mono/mini/mini.h
mono/mini/seq-points.c
mono/mini/seq-points.h
mono/mini/ssa.c
mono/mini/trace.c
mono/mini/tramp-amd64-gsharedvt.c [new file with mode: 0644]
mono/mini/tramp-amd64.c
mono/mini/tramp-arm-gsharedvt.c [new file with mode: 0644]
mono/mini/tramp-arm.c
mono/mini/tramp-arm64-gsharedvt.c [new file with mode: 0644]
mono/mini/tramp-arm64.c
mono/mini/tramp-s390x.c
mono/mini/tramp-x86-gsharedvt.c [new file with mode: 0644]
mono/mini/tramp-x86.c
mono/mini/unwind.c
mono/mini/xdebug.c
mono/profiler/decode.c
mono/profiler/mono-profiler-aot.c
mono/profiler/mono-profiler-iomap.c
mono/profiler/proflog.c
mono/profiler/utils.c
mono/sgen/Makefile.am
mono/sgen/gc-internal-agnostic.h
mono/sgen/sgen-alloc.c
mono/sgen/sgen-archdep.h
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-conf.h
mono/sgen/sgen-copy-object.h
mono/sgen/sgen-debug.c
mono/sgen/sgen-descriptor.c
mono/sgen/sgen-descriptor.h
mono/sgen/sgen-fin-weak-hash.c
mono/sgen/sgen-gc.c
mono/sgen/sgen-gc.h
mono/sgen/sgen-gchandles.c
mono/sgen/sgen-gray.c
mono/sgen/sgen-gray.h
mono/sgen/sgen-internal.c
mono/sgen/sgen-layout-stats.c
mono/sgen/sgen-layout-stats.h
mono/sgen/sgen-los.c
mono/sgen/sgen-major-copy-object.h
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-memory-governor.c
mono/sgen/sgen-memory-governor.h
mono/sgen/sgen-minor-copy-object.h
mono/sgen/sgen-minor-scan-object.h
mono/sgen/sgen-nursery-allocator.c
mono/sgen/sgen-pinning-stats.c
mono/sgen/sgen-pinning.c
mono/sgen/sgen-pinning.h
mono/sgen/sgen-pointer-queue.c
mono/sgen/sgen-pointer-queue.h
mono/sgen/sgen-protocol.c
mono/sgen/sgen-protocol.h
mono/sgen/sgen-qsort.c
mono/sgen/sgen-qsort.h
mono/sgen/sgen-scan-object.h
mono/sgen/sgen-simple-nursery.c
mono/sgen/sgen-split-nursery.c
mono/sgen/sgen-tagged-pointer.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/libtest.c
mono/tests/pinvoke2.cs
mono/tests/pinvoke3.cs
mono/tests/pinvoke_ppcc.cs
mono/tests/pinvoke_ppcd.cs
mono/tests/pinvoke_ppcf.cs
mono/tests/pinvoke_ppci.cs
mono/tests/pinvoke_ppcs.cs
mono/tests/test-runner.cs
mono/tests/verifier/AssemblyRunner.cs
mono/tests/verifier/BatchCompiler.cs
mono/tests/verifier/COPYING.LIB [deleted file]
mono/unit-tests/test-conc-hashtable.c
mono/unit-tests/test-memfuncs.c
mono/unit-tests/test-mono-handle.c
mono/unit-tests/test-sgen-qsort.c
mono/utils/atomic.c
mono/utils/atomic.h
mono/utils/checked-build.c
mono/utils/checked-build.h
mono/utils/dlmalloc.h
mono/utils/gc_wrapper.h
mono/utils/hazard-pointer.c
mono/utils/hazard-pointer.h
mono/utils/json.c
mono/utils/json.h
mono/utils/lock-free-alloc.c
mono/utils/lock-free-array-queue.c
mono/utils/lock-free-array-queue.h
mono/utils/lock-free-queue.c
mono/utils/memfuncs.c
mono/utils/memfuncs.h
mono/utils/mono-complex.h
mono/utils/mono-conc-hashtable.c
mono/utils/mono-context.c
mono/utils/mono-context.h
mono/utils/mono-counters.c
mono/utils/mono-dl-darwin.c
mono/utils/mono-dl-posix.c
mono/utils/mono-dl-windows.c
mono/utils/mono-dl.c
mono/utils/mono-embed.c
mono/utils/mono-error-internals.h
mono/utils/mono-error.c
mono/utils/mono-filemap.c
mono/utils/mono-hwcap-arm.c
mono/utils/mono-hwcap-arm64.c
mono/utils/mono-hwcap-ia64.c
mono/utils/mono-hwcap-mips.c
mono/utils/mono-hwcap-ppc.c
mono/utils/mono-hwcap-s390x.c
mono/utils/mono-hwcap-sparc.c
mono/utils/mono-hwcap-x86.c
mono/utils/mono-hwcap.c
mono/utils/mono-lazy-init.h
mono/utils/mono-linked-list-set.c
mono/utils/mono-linked-list-set.h
mono/utils/mono-machine.h
mono/utils/mono-memory-model.h
mono/utils/mono-mmap-internals.h
mono/utils/mono-mmap.c
mono/utils/mono-os-mutex.h
mono/utils/mono-proclib.c
mono/utils/mono-rand.c
mono/utils/mono-signal-handler.h
mono/utils/mono-stack-unwinding.h
mono/utils/mono-threads-android.c
mono/utils/mono-threads-coop.c
mono/utils/mono-threads-state-machine.c
mono/utils/mono-threads.c
mono/utils/mono-time.c
mono/utils/mono-tls.h
mono/utils/parse.c
mono/utils/parse.h
msvc/libmonoruntime.vcxproj
runtime/Makefile.am
scripts/.gitignore
scripts/Makefile.am

index 230a4505f08c0bbb000f5582184eee1e8111f0f9..ed8d6fe7cc5ac74d975dfc69afdd0d3de2abf69b 100644 (file)
@@ -21,29 +21,18 @@ investigate bugs, regressions and problems.
 License
 =======
 
-The Mono project uses the MIT X11, GNU LGPL version 2 and the Apache
-License 2.0.  We also imported some Microsoft code licensed under the
-open source Microsoft Public License.
+The Mono runtime, compilers, and tools and most of the class libraries
+are licensed under the MIT license. But include some bits of code
+licensed under different licenses. The exact list is [available here] (https://github.com/mono/mono/blob/master/LICENSE).
 
 Different parts of Mono use different licenses.  The actual details of
 which licenses are used for which parts are detailed on the LICENSE
 file in this directory.
 
-When contributing code, make sure that your contribution falls under
-the appropriate license.  For example, contributions to code licensed
-under MIT/X11 code, should be MIT/X11 code.
-
-The runtime (`mono/...`) is a special case.  The code is dual-licensed
-by Xamarin under both the GNU LGPL v2 license and is also available
-under commercial terms.  For the runtime, you should either sign an
-agreement that grants Xamarin the rights to relicense your code under
-other licenses other than the LGPL v2 or your contribution must be
-made as an MIT/X11 license which grants us the same rights, but
-involves no paperwork.  For the latter case, please specify on your
-commit(s) that you are licensing the changes under MIT/X11.
-
-For other parts of the project that are dual-licensed, please state
-on your commit(s) what license you are contributing the changes under.
+CLA
+=======
+
+Contributions are now taken under the [.NET Foundation CLA] (https://cla2.dotnetfoundation.org/). 
 
 Testing
 =======
index 2f3b220f877d4c7c050be2602426412a691fdc0f..5fefc97aa295a4fd4d66c56ca365e9f323479fac 100644 (file)
@@ -1,501 +1 @@
-
-The Mono runtime is licensed under the terms of the GNU 
-Library General Public License, version 2.
-
-The eglib directory is licensed under the terms of the MIT
-X11 license and is a drop-in replacement for Mono's use of
-glib 2.0 (which was LGPL).
-
-The Boehm licensing information is in the libgc directory
-
-The SGen Garbage Collector is under the terms of the MIT X11
-license
-
-The class libraries under mono/mcs are unless otherwise stated
-under the MIT X11 license.
-
-Open source Microsoft code is licensed under the original terms
-which is either MS-PL for older components, or dual licensed
-MS-PL/Apache2 licensed.
-               GNU LIBRARY GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
-                    675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-\f
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-\f
-                 GNU LIBRARY GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-\f
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-\f
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-\f
-  6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    c) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    d) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-\f
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-\f
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-\f
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-                           NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-\f
-     Appendix: How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    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 along with this library; if not, write to the Free
-    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
+See LICENSE file in the project root for full license information.
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index ad5cbb429ff8967d651bee84d1d13edfb8439474..71bfc9eb4ce92efb3aaefacf0a417e558faf3901 100644 (file)
--- a/LICENSE
+++ b/LICENSE
 
-Mono is made up of many pieces of code, all of them open source, but
-different pieces of Mono use different licensing terms.
+In general, the runtime and its class libraries are licensed under the
+terms of the MIT license, and some third party code is licensed under
+the 3-clause BSD license.  See the file "PATENTS.TXT" for Microsoft's
+patent grant on the Mono codebase.
 
-For comments, corrections and updates, please contact mono@xamarin.com
+The Mono distribution does include a handful of pieces of code that
+are used during the build system and are covered under different
+licenses, those include:
 
-* Dual Licensing
+Build Time Code
+===============
 
-       Parts of Mono are dual licensed, they are available to the
-       public in GPL or LGPL forms, but we also offer those pieces
-       under commercial terms from Xamarin for the cases where the
-       GPL and the LGPL are not suitable.
+This is code that is used at build time, or during the maintenance of
+Mono itself, and does not end up in the redistributable part of Mono:
 
-       We have tried to pick the licenses that will maximize adoption
-       of Mono, so we tend to use the MIT X11 or LGPL liceses.
+* gettext
 
-       Contributions to dual-licensed module require that the author
-       contributes the code under the terms of the MIT X11 code, or
-       to sign an agreement that allows Novell to redistribute the
-       code under other licenses.
+  m4 source files used to probe features at build time: GPL
 
-       Contributions for other modules should be under the same license
-       terms as the rest of the module, or under MIT X11 terms. 
+* Benchmark Source Files
 
-       For the actual license links in the Mono distribution see the
-       bottom of this file.
+  Logic.cs and zipmark.cs are GPL source files.
 
-       If you need further information, please contact mono@xamarin.com
+* mono/docs/HtmlAgilityPack
 
-* The Modules
+  MS-PL licensed
 
-** mono/mono: the Mono VM
+* mcs/jay: 4-clause BSD licensed
 
-       This code is dual licensed under the LGPL or commercial licenses. 
+* mcs/nunit24: MS-PL
 
-       The LGPL ensures that Mono can be used in most scenarios, but
-       gives Xamarin the flexibility to relicense the code for
-       embedded systems, static linking or commercial settings where
-       the LGPL can not be used.
+* mcs/class/I18N/mklist.sh, tools/cvt.sh: GNU GPLv2
 
-       We consider non-LGPL use instances where you use this on an
-       embedded system where the end user is not able to upgrade the
-       Mono VM or Moonlight installation or distribution that is part
-       of your product (Section 6 and 7), you would have to obtain a
-       commercial license from Xamarin (consider software burned into
-       a ROM, systems where end users would not be able to upgrade,
-       an embedded console, a game console that imposes limitations
-       on the distribution and access to the code, a phone platform
-       that prevents end users from upgrading Moonlight).
-       
-       Contact mono@xamarin.com for details on obtaining the Mono
-       runtime under other terms.
+Runtime Code
+============
 
-** mono/support: MonoPosixHelper and support code
+The following code is linked with the final Mono runtime, the libmono
+embeddable runtime:
 
-       This code is dual licensed under the LGPL or commercial licenses, with
-       the same guidelines as mono/mono code.
+* support/minizip: BSD license.
 
-       The ZLib files are included under a "new BSD"-style license.
+* mono/utils/memcheck.h: BSD license, used on debug builds that use Valgrind.
 
-** mono/eglib: Mono's X11 glib implementation
+* mono/utils/freebsd-dwarf.h, freebsd-elf_common.h, freebsd-elf64.h freebsd-elf32.h: BSD license.
 
-       This is a minimal subset of glib that is to be licensed under
-       the terms of the MIT X11, this means that this code can be
-       used for any purposes by anyone.
+* mono/utils/bsearch.c: BSD license.
 
-** mono/arch/*/XXX-codegen.h
+* mono/io-layer/wapi_glob.h, wapi_glob.c: BSD license
 
-       This are C macros that are useful when generating native
-       code on various platforms.   This code is MIT X11 licensed.
+Class Library code
+==================
 
-** mcs/mcs, mcs/gmcs
+These are class libraries that can be loaded by your process:
 
-       The C# Compilers (1.0 and 2.0)
+* mcs/class/RabbitMQ.Client: dual licensed in Apache v2, and Mozilla Public License 1.1
 
-       These compilers are dual licensed under the GPL and MIT X11
-       license terms.
+* mcs/class/Compat.ICSharpCode.SharpZipLib and
+  mcs/class/ICSharpCode.SharpZipLib are GPL with class-path exception.
+  Originates with the SharpDevelop project.
 
-** tests
+* mcs/class/System.Core/System/TimeZoneInfo.Android.cs
 
-       Unless explicitly stated, the tests are under the MIT X11 license.
+  This is a port of Apache 2.0-licensed Android code, and thus is
+  licensed under the Apache 2.0 license
 
-** mcs/class
+           http://www.apache.org/licenses/LICENSE-2.0
 
-       The class libraries developed by the Mono team are licensed
-       under the MIT X11 terms.
+API Documentation
+=================
 
-       In addition to the class libraries developed by the Mono team,
-       there are a number of class libraries that we bundle as part
-       of the distribution that were integrated from third-parties or
-       that contain code that was originally licensed under different
-       terms, these are:
+The API documentation is licensed under the terms of the Creative
+Commons Attribution 4.0 International Public License
 
-           ByteFX.Data: LGPL
 
-           Npgsql: LGPL
+The Licenses
+============
 
-           FirebirdSql.Data.Firebird: Firebird public license.
-               See: mcs/class/FirebirdSql.Data.Firebird/license.txt
+       These are the licenses used in Mono, the files are located:
 
-            ICSharpCode.SharpZipLib, GPL with exceptions.
-               See: mcs/class/ICSharpCode.SharpZipLib/README
+### MIT X11 License
 
-** mcs/class/System.Core/System/TimeZoneInfo.Android.cs
+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:
 
-       This is a port of Apache 2.0-licensed Android code, and thus is
-       licensed under the Apache 2.0 license:
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
 
-           http://www.apache.org/licenses/LICENSE-2.0
+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.
 
-            
-** mcs/tools
 
-       These are licensed under the MIT X11 license, except where the
-       GPL is explicitly used. 
+### Mozilla.MPL
 
-** mcs/jay
+                          MOZILLA PUBLIC LICENSE
+                                Version 1.1
 
-       This is a port of Berkeley yacc, so it is available under the BSD
-       license.   See the license in the individual C files for details.
+                              ---------------
 
-** mono/man
+1. Definitions.
 
-       Manual pages and Mono documentation are covered by the MIT X11 license. 
+     1.0.1. "Commercial Use" means distribution or otherwise making the
+     Covered Code available to a third party.
 
-* samples
+     1.1. "Contributor" means each entity that creates or contributes to
+     the creation of Modifications.
 
-       The code in the "samples" directory is released under the MIT X11 license.
+     1.2. "Contributor Version" means the combination of the Original
+     Code, prior Modifications used by a Contributor, and the Modifications
+     made by that particular Contributor.
 
-* The Licenses
+     1.3. "Covered Code" means the Original Code or Modifications or the
+     combination of the Original Code and Modifications, in each case
+     including portions thereof.
 
-       These are the licenses used in Mono, the files are located:
+     1.4. "Electronic Distribution Mechanism" means a mechanism generally
+     accepted in the software development community for the electronic
+     transfer of data.
+
+     1.5. "Executable" means Covered Code in any form other than Source
+     Code.
+
+     1.6. "Initial Developer" means the individual or entity identified
+     as the Initial Developer in the Source Code notice required by Exhibit
+     A.
+
+     1.7. "Larger Work" means a work which combines Covered Code or
+     portions thereof with code not governed by the terms of this License.
+
+     1.8. "License" means this document.
+
+     1.8.1. "Licensable" means having the right to grant, to the maximum
+     extent possible, whether at the time of the initial grant or
+     subsequently acquired, any and all of the rights conveyed herein.
+
+     1.9. "Modifications" means any addition to or deletion from the
+     substance or structure of either the Original Code or any previous
+     Modifications. When Covered Code is released as a series of files, a
+     Modification is:
+          A. Any addition to or deletion from the contents of a file
+          containing Original Code or previous Modifications.
+
+          B. Any new file that contains any part of the Original Code or
+          previous Modifications.
+
+     1.10. "Original Code" means Source Code of computer software code
+     which is described in the Source Code notice required by Exhibit A as
+     Original Code, and which, at the time of its release under this
+     License is not already Covered Code governed by this License.
+
+     1.10.1. "Patent Claims" means any patent claim(s), now owned or
+     hereafter acquired, including without limitation,  method, process,
+     and apparatus claims, in any patent Licensable by grantor.
+
+     1.11. "Source Code" means the preferred form of the Covered Code for
+     making modifications to it, including all modules it contains, plus
+     any associated interface definition files, scripts used to control
+     compilation and installation of an Executable, or source code
+     differential comparisons against either the Original Code or another
+     well known, available Covered Code of the Contributor's choice. The
+     Source Code can be in a compressed or archival form, provided the
+     appropriate decompression or de-archiving software is widely available
+     for no charge.
+
+     1.12. "You" (or "Your")  means an individual or a legal entity
+     exercising rights under, and complying with all of the terms of, this
+     License or a future version of this License issued under Section 6.1.
+     For legal entities, "You" includes any entity which controls, is
+     controlled by, or is under common control with You. For purposes of
+     this definition, "control" means (a) the power, direct or indirect,
+     to cause the direction or management of such entity, whether by
+     contract or otherwise, or (b) ownership of more than fifty percent
+     (50%) of the outstanding shares or beneficial ownership of such
+     entity.
+
+2. Source Code License.
+
+     2.1. The Initial Developer Grant.
+     The Initial Developer hereby grants You a world-wide, royalty-free,
+     non-exclusive license, subject to third party intellectual property
+     claims:
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Initial Developer to use, reproduce,
+          modify, display, perform, sublicense and distribute the Original
+          Code (or portions thereof) with or without Modifications, and/or
+          as part of a Larger Work; and
+
+          (b) under Patents Claims infringed by the making, using or
+          selling of Original Code, to make, have made, use, practice,
+          sell, and offer for sale, and/or otherwise dispose of the
+          Original Code (or portions thereof).
+
+          (c) the licenses granted in this Section 2.1(a) and (b) are
+          effective on the date Initial Developer first distributes
+          Original Code under the terms of this License.
+
+          (d) Notwithstanding Section 2.1(b) above, no patent license is
+          granted: 1) for code that You delete from the Original Code; 2)
+          separate from the Original Code;  or 3) for infringements caused
+          by: i) the modification of the Original Code or ii) the
+          combination of the Original Code with other software or devices.
+
+     2.2. Contributor Grant.
+     Subject to third party intellectual property claims, each Contributor
+     hereby grants You a world-wide, royalty-free, non-exclusive license
+
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Contributor, to use, reproduce, modify,
+          display, perform, sublicense and distribute the Modifications
+          created by such Contributor (or portions thereof) either on an
+          unmodified basis, with other Modifications, as Covered Code
+          and/or as part of a Larger Work; and
+
+          (b) under Patent Claims infringed by the making, using, or
+          selling of  Modifications made by that Contributor either alone
+          and/or in combination with its Contributor Version (or portions
+          of such combination), to make, use, sell, offer for sale, have
+          made, and/or otherwise dispose of: 1) Modifications made by that
+          Contributor (or portions thereof); and 2) the combination of
+          Modifications made by that Contributor with its Contributor
+          Version (or portions of such combination).
+
+          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+          effective on the date Contributor first makes Commercial Use of
+          the Covered Code.
+
+          (d)    Notwithstanding Section 2.2(b) above, no patent license is
+          granted: 1) for any code that Contributor has deleted from the
+          Contributor Version; 2)  separate from the Contributor Version;
+          3)  for infringements caused by: i) third party modifications of
+          Contributor Version or ii)  the combination of Modifications made
+          by that Contributor with other software  (except as part of the
+          Contributor Version) or other devices; or 4) under Patent Claims
+          infringed by Covered Code in the absence of Modifications made by
+          that Contributor.
+
+3. Distribution Obligations.
+
+     3.1. Application of License.
+     The Modifications which You create or to which You contribute are
+     governed by the terms of this License, including without limitation
+     Section 2.2. The Source Code version of Covered Code may be
+     distributed only under the terms of this License or a future version
+     of this License released under Section 6.1, and You must include a
+     copy of this License with every copy of the Source Code You
+     distribute. You may not offer or impose any terms on any Source Code
+     version that alters or restricts the applicable version of this
+     License or the recipients' rights hereunder. However, You may include
+     an additional document offering the additional rights described in
+     Section 3.5.
+
+     3.2. Availability of Source Code.
+     Any Modification which You create or to which You contribute must be
+     made available in Source Code form under the terms of this License
+     either on the same media as an Executable version or via an accepted
+     Electronic Distribution Mechanism to anyone to whom you made an
+     Executable version available; and if made available via Electronic
+     Distribution Mechanism, must remain available for at least twelve (12)
+     months after the date it initially became available, or at least six
+     (6) months after a subsequent version of that particular Modification
+     has been made available to such recipients. You are responsible for
+     ensuring that the Source Code version remains available even if the
+     Electronic Distribution Mechanism is maintained by a third party.
+
+     3.3. Description of Modifications.
+     You must cause all Covered Code to which You contribute to contain a
+     file documenting the changes You made to create that Covered Code and
+     the date of any change. You must include a prominent statement that
+     the Modification is derived, directly or indirectly, from Original
+     Code provided by the Initial Developer and including the name of the
+     Initial Developer in (a) the Source Code, and (b) in any notice in an
+     Executable version or related documentation in which You describe the
+     origin or ownership of the Covered Code.
+
+     3.4. Intellectual Property Matters
+          (a) Third Party Claims.
+          If Contributor has knowledge that a license under a third party's
+          intellectual property rights is required to exercise the rights
+          granted by such Contributor under Sections 2.1 or 2.2,
+          Contributor must include a text file with the Source Code
+          distribution titled "LEGAL" which describes the claim and the
+          party making the claim in sufficient detail that a recipient will
+          know whom to contact. If Contributor obtains such knowledge after
+          the Modification is made available as described in Section 3.2,
+          Contributor shall promptly modify the LEGAL file in all copies
+          Contributor makes available thereafter and shall take other steps
+          (such as notifying appropriate mailing lists or newsgroups)
+          reasonably calculated to inform those who received the Covered
+          Code that new knowledge has been obtained.
+
+          (b) Contributor APIs.
+          If Contributor's Modifications include an application programming
+          interface and Contributor has knowledge of patent licenses which
+          are reasonably necessary to implement that API, Contributor must
+          also include this information in the LEGAL file.
+
+               (c)    Representations.
+          Contributor represents that, except as disclosed pursuant to
+          Section 3.4(a) above, Contributor believes that Contributor's
+          Modifications are Contributor's original creation(s) and/or
+          Contributor has sufficient rights to grant the rights conveyed by
+          this License.
+
+     3.5. Required Notices.
+     You must duplicate the notice in Exhibit A in each file of the Source
+     Code.  If it is not possible to put such notice in a particular Source
+     Code file due to its structure, then You must include such notice in a
+     location (such as a relevant directory) where a user would be likely
+     to look for such a notice.  If You created one or more Modification(s)
+     You may add your name as a Contributor to the notice described in
+     Exhibit A.  You must also duplicate this License in any documentation
+     for the Source Code where You describe recipients' rights or ownership
+     rights relating to Covered Code.  You may choose to offer, and to
+     charge a fee for, warranty, support, indemnity or liability
+     obligations to one or more recipients of Covered Code. However, You
+     may do so only on Your own behalf, and not on behalf of the Initial
+     Developer or any Contributor. You must make it absolutely clear than
+     any such warranty, support, indemnity or liability obligation is
+     offered by You alone, and You hereby agree to indemnify the Initial
+     Developer and every Contributor for any liability incurred by the
+     Initial Developer or such Contributor as a result of warranty,
+     support, indemnity or liability terms You offer.
+
+     3.6. Distribution of Executable Versions.
+     You may distribute Covered Code in Executable form only if the
+     requirements of Section 3.1-3.5 have been met for that Covered Code,
+     and if You include a notice stating that the Source Code version of
+     the Covered Code is available under the terms of this License,
+     including a description of how and where You have fulfilled the
+     obligations of Section 3.2. The notice must be conspicuously included
+     in any notice in an Executable version, related documentation or
+     collateral in which You describe recipients' rights relating to the
+     Covered Code. You may distribute the Executable version of Covered
+     Code or ownership rights under a license of Your choice, which may
+     contain terms different from this License, provided that You are in
+     compliance with the terms of this License and that the license for the
+     Executable version does not attempt to limit or alter the recipient's
+     rights in the Source Code version from the rights set forth in this
+     License. If You distribute the Executable version under a different
+     license You must make it absolutely clear that any terms which differ
+     from this License are offered by You alone, not by the Initial
+     Developer or any Contributor. You hereby agree to indemnify the
+     Initial Developer and every Contributor for any liability incurred by
+     the Initial Developer or such Contributor as a result of any such
+     terms You offer.
+
+     3.7. Larger Works.
+     You may create a Larger Work by combining Covered Code with other code
+     not governed by the terms of this License and distribute the Larger
+     Work as a single product. In such a case, You must make sure the
+     requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+     If it is impossible for You to comply with any of the terms of this
+     License with respect to some or all of the Covered Code due to
+     statute, judicial order, or regulation then You must: (a) comply with
+     the terms of this License to the maximum extent possible; and (b)
+     describe the limitations and the code they affect. Such description
+     must be included in the LEGAL file described in Section 3.4 and must
+     be included with all distributions of the Source Code. Except to the
+     extent prohibited by statute or regulation, such description must be
+     sufficiently detailed for a recipient of ordinary skill to be able to
+     understand it.
+
+5. Application of this License.
+
+     This License applies to code to which the Initial Developer has
+     attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+     6.1. New Versions.
+     Netscape Communications Corporation ("Netscape") may publish revised
+     and/or new versions of the License from time to time. Each version
+     will be given a distinguishing version number.
+
+     6.2. Effect of New Versions.
+     Once Covered Code has been published under a particular version of the
+     License, You may always continue to use it under the terms of that
+     version. You may also choose to use such Covered Code under the terms
+     of any subsequent version of the License published by Netscape. No one
+     other than Netscape has the right to modify the terms applicable to
+     Covered Code created under this License.
+
+     6.3. Derivative Works.
+     If You create or use a modified version of this License (which you may
+     only do in order to apply it to code which is not already Covered Code
+     governed by this License), You must (a) rename Your license so that
+     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+     "MPL", "NPL" or any confusingly similar phrase do not appear in your
+     license (except to note that your license differs from this License)
+     and (b) otherwise make it clear that Your version of the license
+     contains terms which differ from the Mozilla Public License and
+     Netscape Public License. (Filling in the name of the Initial
+     Developer, Original Code or Contributor in the notice described in
+     Exhibit A shall not of themselves be deemed to be modifications of
+     this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+     8.1.  This License and the rights granted hereunder will terminate
+     automatically if You fail to comply with terms herein and fail to cure
+     such breach within 30 days of becoming aware of the breach. All
+     sublicenses to the Covered Code which are properly granted shall
+     survive any termination of this License. Provisions which, by their
+     nature, must remain in effect beyond the termination of this License
+     shall survive.
+
+     8.2.  If You initiate litigation by asserting a patent infringement
+     claim (excluding declatory judgment actions) against Initial Developer
+     or a Contributor (the Initial Developer or Contributor against whom
+     You file such action is referred to as "Participant")  alleging that:
+
+     (a)  such Participant's Contributor Version directly or indirectly
+     infringes any patent, then any and all rights granted by such
+     Participant to You under Sections 2.1 and/or 2.2 of this License
+     shall, upon 60 days notice from Participant terminate prospectively,
+     unless if within 60 days after receipt of notice You either: (i)
+     agree in writing to pay Participant a mutually agreeable reasonable
+     royalty for Your past and future use of Modifications made by such
+     Participant, or (ii) withdraw Your litigation claim with respect to
+     the Contributor Version against such Participant.  If within 60 days
+     of notice, a reasonable royalty and payment arrangement are not
+     mutually agreed upon in writing by the parties or the litigation claim
+     is not withdrawn, the rights granted by Participant to You under
+     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+     the 60 day notice period specified above.
+
+     (b)  any software, hardware, or device, other than such Participant's
+     Contributor Version, directly or indirectly infringes any patent, then
+     any rights granted to You by such Participant under Sections 2.1(b)
+     and 2.2(b) are revoked effective as of the date You first made, used,
+     sold, distributed, or had made, Modifications made by that
+     Participant.
+
+     8.3.  If You assert a patent infringement claim against Participant
+     alleging that such Participant's Contributor Version directly or
+     indirectly infringes any patent where such claim is resolved (such as
+     by license or settlement) prior to the initiation of patent
+     infringement litigation, then the reasonable value of the licenses
+     granted by such Participant under Sections 2.1 or 2.2 shall be taken
+     into account in determining the amount or value of any payment or
+     license.
+
+     8.4.  In the event of termination under Sections 8.1 or 8.2 above,
+     all end user license agreements (excluding distributors and resellers)
+     which have been validly granted by You or any distributor hereunder
+     prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+     The Covered Code is a "commercial item," as that term is defined in
+     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+     software" and "commercial computer software documentation," as such
+     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+     all U.S. Government End Users acquire Covered Code with only those
+     rights set forth herein.
+
+11. MISCELLANEOUS.
+
+     This License represents the complete agreement concerning subject
+     matter hereof. If any provision of this License is held to be
+     unenforceable, such provision shall be reformed only to the extent
+     necessary to make it enforceable. This License shall be governed by
+     California law provisions (except to the extent applicable law, if
+     any, provides otherwise), excluding its conflict-of-law provisions.
+     With respect to disputes in which at least one party is a citizen of,
+     or an entity chartered or registered to do business in the United
+     States of America, any litigation relating to this License shall be
+     subject to the jurisdiction of the Federal Courts of the Northern
+     District of California, with venue lying in Santa Clara County,
+     California, with the losing party responsible for costs, including
+     without limitation, court costs and reasonable attorneys' fees and
+     expenses. The application of the United Nations Convention on
+     Contracts for the International Sale of Goods is expressly excluded.
+     Any law or regulation which provides that the language of a contract
+     shall be construed against the drafter shall not apply to this
+     License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+     As between Initial Developer and the Contributors, each party is
+     responsible for claims and damages arising, directly or indirectly,
+     out of its utilization of rights under this License and You agree to
+     work with Initial Developer and Contributors to distribute such
+     responsibility on an equitable basis. Nothing herein is intended or
+     shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+     Initial Developer may designate portions of the Covered Code as
+     "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
+     Developer permits you to utilize portions of the Covered Code under
+     Your choice of the NPL or the alternative licenses, if any, specified
+     by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+     ``The contents of this file are subject to the Mozilla Public License
+     Version 1.1 (the "License"); you may not use this file except in
+     compliance with the License. You may obtain a copy of the License at
+     http://www.mozilla.org/MPL/
+
+     Software distributed under the License is distributed on an "AS IS"
+     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+     License for the specific language governing rights and limitations
+     under the License.
+
+     The Original Code is ______________________________________.
+
+     The Initial Developer of the Original Code is ________________________.
+     Portions created by ______________________ are Copyright (C) ______
+     _______________________. All Rights Reserved.
+
+     Contributor(s): ______________________________________.
+
+     Alternatively, the contents of this file may be used under the terms
+     of the _____ license (the  "[___] License"), in which case the
+     provisions of [______] License are applicable instead of those
+     above.  If you wish to allow use of your version of this file only
+     under the terms of the [____] License and not to allow others to use
+     your version of this file under the MPL, indicate your decision by
+     deleting  the provisions above and replace  them with the notice and
+     other provisions required by the [___] License.  If you do not delete
+     the provisions above, a recipient may use your version of this file
+     under either the MPL or the [___] License."
+
+     [NOTE: The text of this Exhibit A may differ slightly from the text of
+     the notices in the Source Code files of the Original Code. You should
+     use the text of this Exhibit A rather than the text found in the
+     Original Code Source Code for Your Modifications.]
+
+### Microsoft Public License
+
+Microsoft Permissive License (Ms-PL)
+       This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
+1. Definitions
+
+       The terms \93reproduce,\94 \93reproduction,\94 \93derivative works,\94 and \93distribution\94 have the same meaning here as under U.S. copyright law.
+       A \93contribution\94 is the original software, or any additions or changes to the software.
+       A \93contributor\94 is any person that distributes its contribution under this license.
+        \93Licensed patents\94 are a contributor\92s patent claims that read directly on its contribution.
+2. Grant of Rights
+
+       (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
+       (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
+3. Conditions and Limitations
+
+       (A) No Trademark License- This license does not grant you rights to use any contributors\92 name, logo, or trademarks.
+       (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
+       (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
+       (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
+       (E) The software is licensed \93as-is.\94 You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
+       (F) If you distribute the software or derivative works with programs you develop, you agree to indemnify, defend, and hold harmless all contributors from any claims, including attorneys\92 fees, related to the distribution or use of your programs.  For clarity, you have no such obligations to a contributor for any claims based solely on the unmodified contributions of that contributor.
+       (G) If you make any additions or changes to the original software, you may only distribute them under a new namespace.  In addition, you will clearly identify your changes or additions as your own.
+
+### Infozip BSD
+
+This is version 2009-Jan-02 of the Info-ZIP license. The definitive
+version of this document should be available at
+ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and a
+copy at http://www.info-zip.org/pub/infozip/license.html.
+
+Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
+
+For the purposes of this copyright and license, "Info-ZIP" is defined
+as the following set of individuals: Mark Adler, John Bush, Karl
+Davis, Harald Denker, Jean-Michel Dubois, Jean-loup Gailly, Hunter
+Goatley, Ed Gordon, Ian Gorman, Chris Herborth, Dirk Haase, Greg
+Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, David
+Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, Steve
+P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,
+Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,
+Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,
+Rich Wales, Mike White.
+
+This software is provided "as is," without warranty of any kind,
+express or implied. In no event shall Info-ZIP or its contributors be
+held liable for any direct, indirect, incidental, special or
+consequential damages arising out of the use of or inability to use
+this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the above disclaimer and the following
+restrictions:
+
+Redistributions of source code (in whole or in part) must retain the
+above copyright notice, definition, disclaimer, and this list of
+conditions.
+
+Redistributions in binary form (compiled executables and libraries)
+must reproduce the above copyright notice, definition, disclaimer, and
+this list of conditions in documentation and/or other materials
+provided with the distribution. Additional documentation is not needed
+for executables where a command line license option provides these and
+a note regarding this option is in the executable's startup
+banner. The sole exception to this condition is redistribution of a
+standard UnZipSFX binary (including SFXWiz) as part of a
+self-extracting archive; that is permitted without inclusion of this
+license, as long as the normal SFX banner has not been removed from
+the binary or disabled.
+
+Altered versions--including, but not limited to, ports to new
+operating systems, existing ports with new graphical interfaces,
+versions with modified or added functionality, and dynamic, shared, or
+static library versions not from Info-ZIP--must be plainly marked as
+such and must not be misrepresented as being the original source or,
+if binaries, compiled from the original source. Such altered versions
+also must not be misrepresented as being Info-ZIP releases--including,
+but not limited to, labeling of the altered versions with the names
+"Info-ZIP" (or any variation thereof, including, but not limited to,
+different capitalizations), "Pocket UnZip," "WiZ" or "MacZip" without
+the explicit permission of Info-ZIP. Such altered versions are further
+prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP
+e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP
+will provide support for the altered versions.
+
+Info-ZIP retains the right to use the names "Info-ZIP," "Zip,"
+"UnZip," "UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip"
+for its own source and binary releases.
+
+### License Creative Commons 2.5
+
+// Copyright 2006 James Newton-King
+// http://www.newtonsoft.com
+//
+// This work is licensed under the Creative Commons Attribution 2.5 License
+// http://creativecommons.org/licenses/by/2.5/
+//
+// You are free:
+//    * to copy, distribute, display, and perform the work
+//    * to make derivative works
+//    * to make commercial use of the work
+//
+// Under the following conditions:
+//    * For any reuse or distribution, you must make clear to others the license terms of this work.
+//    * Any of these conditions can be waived if you get permission from the copyright holder.
+
+From: james.newtonking@gmail.com [mailto:james.newtonking@gmail.com] On Behalf Of James Newton-King
+Sent: Tuesday, June 05, 2007 6:36 AM
+To: Konstantin Triger
+Subject: Re: Support request by Konstantin Triger for Json.NET
+
+Hey Kosta
+
+I think it would be awesome to use Json.NET in Mono for System.Web.Extensions.
+
+The CC license has the following clause: Any of the above conditions can be waived if you get permission from the copyright holder.
+
+I can waive that statement for you and Mono. Would that be acceptable?
+
+
+Regards,
+James
+
+### Creative Commons Attribution 4.0 International Public License
+
+Attribution 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+     Considerations for licensors: Our public licenses are
+     intended for use by those authorized to give the public
+     permission to use material in ways otherwise restricted by
+     copyright and certain other rights. Our licenses are
+     irrevocable. Licensors should read and understand the terms
+     and conditions of the license they choose before applying it.
+     Licensors should also secure all rights necessary before
+     applying our licenses so that the public can reuse the
+     material as expected. Licensors should clearly mark any
+     material not subject to the license. This includes other CC-
+     licensed material, or material used under an exception or
+     limitation to copyright. More considerations for licensors:
+       wiki.creativecommons.org/Considerations_for_licensors
+
+     Considerations for the public: By using one of our public
+     licenses, a licensor grants the public permission to use the
+     licensed material under specified terms and conditions. If
+     the licensor's permission is not necessary for any reason--for
+     example, because of any applicable exception or limitation to
+     copyright--then that use is not regulated by the license. Our
+     licenses grant only permissions under copyright and certain
+     other rights that a licensor has authority to grant. Use of
+     the licensed material may still be restricted for other
+     reasons, including because others have copyright or other
+     rights in the material. A licensor may make special requests,
+     such as asking that all changes be marked or described.
+     Although not required by our licenses, you are encouraged to
+     respect those requests where reasonable. More_considerations
+     for the public: 
+       wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution 4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution 4.0 International Public License ("Public License"). To the
+extent this Public License may be interpreted as a contract, You are
+granted the Licensed Rights in consideration of Your acceptance of
+these terms and conditions, and the Licensor grants You such rights in
+consideration of benefits the Licensor receives from making the
+Licensed Material available under these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+  a. Adapted Material means material subject to Copyright and Similar
+     Rights that is derived from or based upon the Licensed Material
+     and in which the Licensed Material is translated, altered,
+     arranged, transformed, or otherwise modified in a manner requiring
+     permission under the Copyright and Similar Rights held by the
+     Licensor. For purposes of this Public License, where the Licensed
+     Material is a musical work, performance, or sound recording,
+     Adapted Material is always produced where the Licensed Material is
+     synched in timed relation with a moving image.
+
+  b. Adapter's License means the license You apply to Your Copyright
+     and Similar Rights in Your contributions to Adapted Material in
+     accordance with the terms and conditions of this Public License.
+
+  c. Copyright and Similar Rights means copyright and/or similar rights
+     closely related to copyright including, without limitation,
+     performance, broadcast, sound recording, and Sui Generis Database
+     Rights, without regard to how the rights are labeled or
+     categorized. For purposes of this Public License, the rights
+     specified in Section 2(b)(1)-(2) are not Copyright and Similar
+     Rights.
+
+  d. Effective Technological Measures means those measures that, in the
+     absence of proper authority, may not be circumvented under laws
+     fulfilling obligations under Article 11 of the WIPO Copyright
+     Treaty adopted on December 20, 1996, and/or similar international
+     agreements.
+
+  e. Exceptions and Limitations means fair use, fair dealing, and/or
+     any other exception or limitation to Copyright and Similar Rights
+     that applies to Your use of the Licensed Material.
+
+  f. Licensed Material means the artistic or literary work, database,
+     or other material to which the Licensor applied this Public
+     License.
+
+  g. Licensed Rights means the rights granted to You subject to the
+     terms and conditions of this Public License, which are limited to
+     all Copyright and Similar Rights that apply to Your use of the
+     Licensed Material and that the Licensor has authority to license.
+
+  h. Licensor means the individual(s) or entity(ies) granting rights
+     under this Public License.
+
+  i. Share means to provide material to the public by any means or
+     process that requires permission under the Licensed Rights, such
+     as reproduction, public display, public performance, distribution,
+     dissemination, communication, or importation, and to make material
+     available to the public including in ways that members of the
+     public may access the material from a place and at a time
+     individually chosen by them.
+
+  j. Sui Generis Database Rights means rights other than copyright
+     resulting from Directive 96/9/EC of the European Parliament and of
+     the Council of 11 March 1996 on the legal protection of databases,
+     as amended and/or succeeded, as well as other essentially
+     equivalent rights anywhere in the world.
+
+  k. You means the individual or entity exercising the Licensed Rights
+     under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+  a. License grant.
+
+       1. Subject to the terms and conditions of this Public License,
+          the Licensor hereby grants You a worldwide, royalty-free,
+          non-sublicensable, non-exclusive, irrevocable license to
+          exercise the Licensed Rights in the Licensed Material to:
+
+            a. reproduce and Share the Licensed Material, in whole or
+               in part; and
+
+            b. produce, reproduce, and Share Adapted Material.
+
+       2. Exceptions and Limitations. For the avoidance of doubt, where
+          Exceptions and Limitations apply to Your use, this Public
+          License does not apply, and You do not need to comply with
+          its terms and conditions.
+
+       3. Term. The term of this Public License is specified in Section
+          6(a).
+
+       4. Media and formats; technical modifications allowed. The
+          Licensor authorizes You to exercise the Licensed Rights in
+          all media and formats whether now known or hereafter created,
+          and to make technical modifications necessary to do so. The
+          Licensor waives and/or agrees not to assert any right or
+          authority to forbid You from making technical modifications
+          necessary to exercise the Licensed Rights, including
+          technical modifications necessary to circumvent Effective
+          Technological Measures. For purposes of this Public License,
+          simply making modifications authorized by this Section 2(a)
+          (4) never produces Adapted Material.
+
+       5. Downstream recipients.
+
+            a. Offer from the Licensor -- Licensed Material. Every
+               recipient of the Licensed Material automatically
+               receives an offer from the Licensor to exercise the
+               Licensed Rights under the terms and conditions of this
+               Public License.
+
+            b. No downstream restrictions. You may not offer or impose
+               any additional or different terms or conditions on, or
+               apply any Effective Technological Measures to, the
+               Licensed Material if doing so restricts exercise of the
+               Licensed Rights by any recipient of the Licensed
+               Material.
+
+       6. No endorsement. Nothing in this Public License constitutes or
+          may be construed as permission to assert or imply that You
+          are, or that Your use of the Licensed Material is, connected
+          with, or sponsored, endorsed, or granted official status by,
+          the Licensor or others designated to receive attribution as
+          provided in Section 3(a)(1)(A)(i).
+
+  b. Other rights.
+
+       1. Moral rights, such as the right of integrity, are not
+          licensed under this Public License, nor are publicity,
+          privacy, and/or other similar personality rights; however, to
+          the extent possible, the Licensor waives and/or agrees not to
+          assert any such rights held by the Licensor to the limited
+          extent necessary to allow You to exercise the Licensed
+          Rights, but not otherwise.
+
+       2. Patent and trademark rights are not licensed under this
+          Public License.
+
+       3. To the extent possible, the Licensor waives any right to
+          collect royalties from You for the exercise of the Licensed
+          Rights, whether directly or through a collecting society
+          under any voluntary or waivable statutory or compulsory
+          licensing scheme. In all other cases the Licensor expressly
+          reserves any right to collect such royalties.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+  a. Attribution.
+
+       1. If You Share the Licensed Material (including in modified
+          form), You must:
+
+            a. retain the following if it is supplied by the Licensor
+               with the Licensed Material:
+
+                 i. identification of the creator(s) of the Licensed
+                    Material and any others designated to receive
+                    attribution, in any reasonable manner requested by
+                    the Licensor (including by pseudonym if
+                    designated);
+
+                ii. a copyright notice;
+
+               iii. a notice that refers to this Public License;
+
+                iv. a notice that refers to the disclaimer of
+                    warranties;
+
+                 v. a URI or hyperlink to the Licensed Material to the
+                    extent reasonably practicable;
+
+            b. indicate if You modified the Licensed Material and
+               retain an indication of any previous modifications; and
+
+            c. indicate the Licensed Material is licensed under this
+               Public License, and include the text of, or the URI or
+               hyperlink to, this Public License.
+
+       2. You may satisfy the conditions in Section 3(a)(1) in any
+          reasonable manner based on the medium, means, and context in
+          which You Share the Licensed Material. For example, it may be
+          reasonable to satisfy the conditions by providing a URI or
+          hyperlink to a resource that includes the required
+          information.
+
+       3. If requested by the Licensor, You must remove any of the
+          information required by Section 3(a)(1)(A) to the extent
+          reasonably practicable.
+
+       4. If You Share Adapted Material You produce, the Adapter's
+          License You apply must not prevent recipients of the Adapted
+          Material from complying with this Public License.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+  a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+     to extract, reuse, reproduce, and Share all or a substantial
+     portion of the contents of the database;
+
+  b. if You include all or a substantial portion of the database
+     contents in a database in which You have Sui Generis Database
+     Rights, then the database in which You have Sui Generis Database
+     Rights (but not its individual contents) is Adapted Material; and
+
+  c. You must comply with the conditions in Section 3(a) if You Share
+     all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+  c. The disclaimer of warranties and limitation of liability provided
+     above shall be interpreted in a manner that, to the extent
+     possible, most closely approximates an absolute disclaimer and
+     waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+  a. This Public License applies for the term of the Copyright and
+     Similar Rights licensed here. However, if You fail to comply with
+     this Public License, then Your rights under this Public License
+     terminate automatically.
+
+  b. Where Your right to use the Licensed Material has terminated under
+     Section 6(a), it reinstates:
+
+       1. automatically as of the date the violation is cured, provided
+          it is cured within 30 days of Your discovery of the
+          violation; or
+
+       2. upon express reinstatement by the Licensor.
+
+     For the avoidance of doubt, this Section 6(b) does not affect any
+     right the Licensor may have to seek remedies for Your violations
+     of this Public License.
+
+  c. For the avoidance of doubt, the Licensor may also offer the
+     Licensed Material under separate terms or conditions or stop
+     distributing the Licensed Material at any time; however, doing so
+     will not terminate this Public License.
+
+  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+     License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+  a. The Licensor shall not be bound by any additional or different
+     terms or conditions communicated by You unless expressly agreed.
+
+  b. Any arrangements, understandings, or agreements regarding the
+     Licensed Material not stated herein are separate from and
+     independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+  a. For the avoidance of doubt, this Public License does not, and
+     shall not be interpreted to, reduce, limit, restrict, or impose
+     conditions on any use of the Licensed Material that could lawfully
+     be made without permission under this Public License.
+
+  b. To the extent possible, if any provision of this Public License is
+     deemed unenforceable, it shall be automatically reformed to the
+     minimum extent necessary to make it enforceable. If the provision
+     cannot be reformed, it shall be severed from this Public License
+     without affecting the enforceability of the remaining terms and
+     conditions.
+
+  c. No term or condition of this Public License will be waived and no
+     failure to comply consented to unless expressly agreed to by the
+     Licensor.
+
+  d. Nothing in this Public License constitutes or may be interpreted
+     as a limitation upon, or waiver of, any privileges and immunities
+     that apply to the Licensor or You, including from the legal
+     processes of any jurisdiction or authority.
+
+
+=======================================================================
+
+Creative Commons is not a party to its public
+licenses. Notwithstanding, Creative Commons may elect to apply one of
+its public licenses to material it publishes and in those instances
+will be considered the “Licensor.” The text of the Creative Commons
+public licenses is dedicated to the public domain under the CC0 Public
+Domain Dedication. Except for the limited purpose of indicating that
+material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the
+public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
+
+### GPL version 2
+
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
 
-        GNU GPL: details avaliable in the file mcs/LICENSE.GPL
-        GNU LGPL: details available in the file mcs/LICENSE.LGPL
-        MIT X11: text available in the file mcs/MIT.X11
-        MPL: text available in the file mcs/LICENSE.MPL
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
 
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/PATENTS.TXT b/PATENTS.TXT
new file mode 100644 (file)
index 0000000..a868428
--- /dev/null
@@ -0,0 +1,44 @@
+Microsoft Patent Promise for Mono
+
+Microsoft Corporation and its affiliates (“Microsoft”) promise not to
+assert any Applicable Patents against you for making, using, selling,
+offering for sale, importing, or distributing Mono.
+
+If you file, maintain, or voluntarily participate in any claim in a
+lawsuit alleging direct or contributory patent infringement by Mono,
+or inducement of patent infringement by Mono, then your rights under
+this promise will automatically terminate.
+
+This promise is not an assurance that (i) any Applicable Patents are
+valid or enforceable or (ii) Mono does not infringe patents or other
+intellectual property rights of any third party. No rights except
+those expressly stated in this promise are granted, waived or received
+by Microsoft, whether by implication, exhaustion, estoppel or
+otherwise. This is a personal promise directly from Microsoft to you,
+and you agree as a condition of benefitting from it that no Microsoft
+rights are received from suppliers, distributors, or otherwise in
+connection with this promise.
+
+Definitions:
+
+“Mono” means those portions of the software development technology, as
+originally distributed by Xamarin, Inc. or the .NET Foundation under
+the name “Mono,” that implement .NET Framework Functionality, provided
+that such portions at a minimum implement all of the required parts of
+the mandatory provisions of Standard ECMA-335 – Common Language
+Infrastructure (CLI).
+
+“.NET Framework Functionality” means any functionality in Microsoft’s
+.NET Framework as described in Microsoft’s API documentation on
+Microsoft’s MSDN website, including the functionality in
+Windowsbase.dll, but excluding all other functionality in the Windows
+Presentation Foundation component of .NET Framework.
+
+“Applicable Patents” are those patent claims, currently owned by
+Microsoft and acquired in the future, that are necessarily infringed
+by Mono. For clarity, Applicable Patents do not include any patent
+claims that are infringed (x) by any underlying or enabling technology
+that may be used, combined, or distributed in connection with Mono
+(such as hardware, operating systems, or applications that run on
+Mono), (y) only as a consequence of modification of Mono, or (z) only
+by the combination of Mono with third party code.
index 7a7f3639f28ccefebc994e5d5f03cb0ae41f2ce1..5aad9440a06112eb34bb89a82f8bd46fb2910640 100644 (file)
--- a/README.md
+++ b/README.md
@@ -3,6 +3,8 @@ create cross platform applications.  It is an open source
 implementation of Microsoft's .NET Framework based on the ECMA
 standards for C# and the Common Language Runtime.
 
+The Mono project is part of the [.NET Foundation](http://www.dotnetfoundation.org/)
+
 [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mono/mono?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 
 1. [Compilation and Installation](#compilation-and-installation)
@@ -104,6 +106,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.
@@ -505,3 +509,15 @@ to do at all), first edit `.gitmodules` to point to the new location, then:
 The desired output diff is a change in `.gitmodules` to reflect the
 change in the remote URL, and a change in /<submodule> where you see
 the desired change in the commit hash.
+
+License
+=======
+
+See the LICENSE file for licensing information, and the PATENTS.TXT
+file for information about Microsoft's patent grant.
+
+Mono Trademark Use Policy
+=======
+
+The use of trademarks and logos for Mono can be found [here] (http://www.dotnetfoundation.org/legal/mono-tm). 
+
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..12ed84fb8431368f42b8760dd8216a919921ccd6 100644 (file)
@@ -929,15 +929,8 @@ if test x$has_extension_module != xno ; then
        AC_MSG_NOTICE([Enabling mono extension module.])
 fi
 
-AC_ARG_ENABLE(gsharedvt, [  --enable-gsharedvt Enable generic valuetype sharing], enable_gsharedvt=$enableval, enable_gsharedvt=no)
-if test x$enable_gsharedvt = xyes; then
-       AC_DEFINE(ENABLE_GSHAREDVT,1,[Gsharedvt])
-fi
-
-AC_ARG_ENABLE(native-types, [  --enable-native-types Enable native types], enable_native_types=$enableval, enable_native_types=no)
-if test x$enable_native_types = xyes; then
-       AC_DEFINE(MONO_NATIVE_TYPES,1,[native types])
-fi
+# Deprecated
+AC_ARG_ENABLE(gsharedvt, [  --enable-gsharedvt Enable generic valuetype sharing (Deprecated)], enable_gsharedvt=$enableval, enable_gsharedvt=no)
 
 AC_MSG_CHECKING(for visibility __attribute__)
 AC_COMPILE_IFELSE([
@@ -3319,6 +3312,12 @@ AC_ARG_WITH([libgdiplus],
 
 # default install location
 libgdiplus_install_loc=libgdiplus${libsuffix}
+case "$host" in
+    *-*-*linux*)
+    libgdiplus_install_loc=libgdiplus${libsuffix}.0
+    ;;
+esac
+
 case $with_libgdiplus in
     no|installed)
     libgdiplus_loc=
@@ -3583,35 +3582,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], 
@@ -4064,10 +4062,6 @@ fi
     if test x$has_extension_module != xno; then
         echo "EXTENSION_MODULE = 1" >> $srcdir/$mcsdir/build/config.make
     fi
-
-    if test x$enable_gsharedvt = xno; then
-        echo "MONO_DISABLE_GSHAREDVT = 1" >> $srcdir/$mcsdir/build/config.make
-    fi
     
     echo "DEFAULT_PROFILE = $default_profile" >> $srcdir/$mcsdir/build/config.make
     
index 35b7594b5498e9712522e0556ec290415691dddd..6c6e36218c4a0b6dfb85bd27fa6746467761e8a0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 35b7594b5498e9712522e0556ec290415691dddd
+Subproject commit 6c6e36218c4a0b6dfb85bd27fa6746467761e8a0
index 99d49e6f9299c891e85917532d9fc3d601e41dc6..7eb8055fb4f56fdda2452b660572569c7b195c32 100644 (file)
@@ -1095,11 +1095,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
diff --git a/mcs/COPYING.LIB b/mcs/COPYING.LIB
deleted file mode 100644 (file)
index 5bc8fb2..0000000
+++ /dev/null
@@ -1,481 +0,0 @@
-                  GNU LIBRARY GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-\f
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-\f
-                  GNU LIBRARY GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-\f
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-\f
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-\f
-  6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    c) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    d) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-\f
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-\f
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-\f
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-                            NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-\f
-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    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 along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
diff --git a/mcs/LICENSE b/mcs/LICENSE
deleted file mode 100644 (file)
index ed2d1fc..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-
-The Mono code under the mcs/ directory is licensed under various
-different licenses:
-
-       GNU GPL: details avaliable in the file LICENSE.GPL
-       GNU LGPL: details available in the file LICENSE.LGPL
-       MIT X11: text available in the file MIT.X11
-       MPL: text available in the file LICENSE.MPL
-
-       For your convenience copies of the GNU GPL and GNU LGPL are
-       located in the file COPYING and COPYING.LIB.
-
-       * Class Libraries:
-
-               All of the core classes licensed under the terms of
-               the MIT X11 license.
-
-               Third party libraries that we distribute for
-               convenience reasons are distributed under their own
-               terms (all of them allow development of proprietary
-               applications with them).
-
-               Third party libraries include: ByteFX.Data,
-               ICSharpCode.SharpZipLib, Npgsql, MicrosoftAjaxLibrary.
-
-               The Microsoft.JScript assembly is covered by the
-               MIT X11 and the Mozilla MPL license as it contains
-               ported pieces of code from Rhino, the Mozilla JavaScript
-               implementations
-
-       * Mono C# compiler: Dual licensed MIT X11 and GNU GPL.
-
-       * Mono Basic compiler: GNU GPL.
-
-       * Various tools in the `tools' directory: GNU GPL.
-
diff --git a/mcs/LICENSE.CC b/mcs/LICENSE.CC
deleted file mode 100644 (file)
index 6114753..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2006 James Newton-King
-// http://www.newtonsoft.com
-//
-// This work is licensed under the Creative Commons Attribution 2.5 License
-// http://creativecommons.org/licenses/by/2.5/
-//
-// You are free:
-//    * to copy, distribute, display, and perform the work
-//    * to make derivative works
-//    * to make commercial use of the work
-//
-// Under the following conditions:
-//    * For any reuse or distribution, you must make clear to others the license terms of this work.
-//    * Any of these conditions can be waived if you get permission from the copyright holder.
-
-From: james.newtonking@gmail.com [mailto:james.newtonking@gmail.com] On Behalf Of James Newton-King
-Sent: Tuesday, June 05, 2007 6:36 AM
-To: Konstantin Triger
-Subject: Re: Support request by Konstantin Triger for Json.NET
-
-Hey Kosta
-
-I think it would be awesome to use Json.NET in Mono for System.Web.Extensions.
-
-The CC license has the following clause: Any of the above conditions can be waived if you get permission from the copyright holder.
-
-I can waive that statement for you and Mono. Would that be acceptable? 
-
-
-Regards,
-James
diff --git a/mcs/LICENSE.GPL b/mcs/LICENSE.GPL
deleted file mode 100644 (file)
index b236c56..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-    Mono compilers and tools.
-    Copyright (C) 2001, 2002, 2003, Ximian and contributors.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; 
-
-    This program 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 General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
diff --git a/mcs/LICENSE.LGPL b/mcs/LICENSE.LGPL
deleted file mode 100644 (file)
index 7447504..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-    Mono class libraries
-    Copyright (C) Mono project (authors listed in individual ChangeLog entries)
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License 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 along with this library; if not, write to the Free
-    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
diff --git a/mcs/LICENSE.MPL b/mcs/LICENSE.MPL
deleted file mode 100644 (file)
index 7714141..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-                          MOZILLA PUBLIC LICENSE
-                                Version 1.1
-
-                              ---------------
-
-1. Definitions.
-
-     1.0.1. "Commercial Use" means distribution or otherwise making the
-     Covered Code available to a third party.
-
-     1.1. "Contributor" means each entity that creates or contributes to
-     the creation of Modifications.
-
-     1.2. "Contributor Version" means the combination of the Original
-     Code, prior Modifications used by a Contributor, and the Modifications
-     made by that particular Contributor.
-
-     1.3. "Covered Code" means the Original Code or Modifications or the
-     combination of the Original Code and Modifications, in each case
-     including portions thereof.
-
-     1.4. "Electronic Distribution Mechanism" means a mechanism generally
-     accepted in the software development community for the electronic
-     transfer of data.
-
-     1.5. "Executable" means Covered Code in any form other than Source
-     Code.
-
-     1.6. "Initial Developer" means the individual or entity identified
-     as the Initial Developer in the Source Code notice required by Exhibit
-     A.
-
-     1.7. "Larger Work" means a work which combines Covered Code or
-     portions thereof with code not governed by the terms of this License.
-
-     1.8. "License" means this document.
-
-     1.8.1. "Licensable" means having the right to grant, to the maximum
-     extent possible, whether at the time of the initial grant or
-     subsequently acquired, any and all of the rights conveyed herein.
-
-     1.9. "Modifications" means any addition to or deletion from the
-     substance or structure of either the Original Code or any previous
-     Modifications. When Covered Code is released as a series of files, a
-     Modification is:
-          A. Any addition to or deletion from the contents of a file
-          containing Original Code or previous Modifications.
-
-          B. Any new file that contains any part of the Original Code or
-          previous Modifications.
-
-     1.10. "Original Code" means Source Code of computer software code
-     which is described in the Source Code notice required by Exhibit A as
-     Original Code, and which, at the time of its release under this
-     License is not already Covered Code governed by this License.
-
-     1.10.1. "Patent Claims" means any patent claim(s), now owned or
-     hereafter acquired, including without limitation,  method, process,
-     and apparatus claims, in any patent Licensable by grantor.
-
-     1.11. "Source Code" means the preferred form of the Covered Code for
-     making modifications to it, including all modules it contains, plus
-     any associated interface definition files, scripts used to control
-     compilation and installation of an Executable, or source code
-     differential comparisons against either the Original Code or another
-     well known, available Covered Code of the Contributor's choice. The
-     Source Code can be in a compressed or archival form, provided the
-     appropriate decompression or de-archiving software is widely available
-     for no charge.
-
-     1.12. "You" (or "Your")  means an individual or a legal entity
-     exercising rights under, and complying with all of the terms of, this
-     License or a future version of this License issued under Section 6.1.
-     For legal entities, "You" includes any entity which controls, is
-     controlled by, or is under common control with You. For purposes of
-     this definition, "control" means (a) the power, direct or indirect,
-     to cause the direction or management of such entity, whether by
-     contract or otherwise, or (b) ownership of more than fifty percent
-     (50%) of the outstanding shares or beneficial ownership of such
-     entity.
-
-2. Source Code License.
-
-     2.1. The Initial Developer Grant.
-     The Initial Developer hereby grants You a world-wide, royalty-free,
-     non-exclusive license, subject to third party intellectual property
-     claims:
-          (a)  under intellectual property rights (other than patent or
-          trademark) Licensable by Initial Developer to use, reproduce,
-          modify, display, perform, sublicense and distribute the Original
-          Code (or portions thereof) with or without Modifications, and/or
-          as part of a Larger Work; and
-
-          (b) under Patents Claims infringed by the making, using or
-          selling of Original Code, to make, have made, use, practice,
-          sell, and offer for sale, and/or otherwise dispose of the
-          Original Code (or portions thereof).
-
-          (c) the licenses granted in this Section 2.1(a) and (b) are
-          effective on the date Initial Developer first distributes
-          Original Code under the terms of this License.
-
-          (d) Notwithstanding Section 2.1(b) above, no patent license is
-          granted: 1) for code that You delete from the Original Code; 2)
-          separate from the Original Code;  or 3) for infringements caused
-          by: i) the modification of the Original Code or ii) the
-          combination of the Original Code with other software or devices.
-
-     2.2. Contributor Grant.
-     Subject to third party intellectual property claims, each Contributor
-     hereby grants You a world-wide, royalty-free, non-exclusive license
-
-          (a)  under intellectual property rights (other than patent or
-          trademark) Licensable by Contributor, to use, reproduce, modify,
-          display, perform, sublicense and distribute the Modifications
-          created by such Contributor (or portions thereof) either on an
-          unmodified basis, with other Modifications, as Covered Code
-          and/or as part of a Larger Work; and
-
-          (b) under Patent Claims infringed by the making, using, or
-          selling of  Modifications made by that Contributor either alone
-          and/or in combination with its Contributor Version (or portions
-          of such combination), to make, use, sell, offer for sale, have
-          made, and/or otherwise dispose of: 1) Modifications made by that
-          Contributor (or portions thereof); and 2) the combination of
-          Modifications made by that Contributor with its Contributor
-          Version (or portions of such combination).
-
-          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
-          effective on the date Contributor first makes Commercial Use of
-          the Covered Code.
-
-          (d)    Notwithstanding Section 2.2(b) above, no patent license is
-          granted: 1) for any code that Contributor has deleted from the
-          Contributor Version; 2)  separate from the Contributor Version;
-          3)  for infringements caused by: i) third party modifications of
-          Contributor Version or ii)  the combination of Modifications made
-          by that Contributor with other software  (except as part of the
-          Contributor Version) or other devices; or 4) under Patent Claims
-          infringed by Covered Code in the absence of Modifications made by
-          that Contributor.
-
-3. Distribution Obligations.
-
-     3.1. Application of License.
-     The Modifications which You create or to which You contribute are
-     governed by the terms of this License, including without limitation
-     Section 2.2. The Source Code version of Covered Code may be
-     distributed only under the terms of this License or a future version
-     of this License released under Section 6.1, and You must include a
-     copy of this License with every copy of the Source Code You
-     distribute. You may not offer or impose any terms on any Source Code
-     version that alters or restricts the applicable version of this
-     License or the recipients' rights hereunder. However, You may include
-     an additional document offering the additional rights described in
-     Section 3.5.
-
-     3.2. Availability of Source Code.
-     Any Modification which You create or to which You contribute must be
-     made available in Source Code form under the terms of this License
-     either on the same media as an Executable version or via an accepted
-     Electronic Distribution Mechanism to anyone to whom you made an
-     Executable version available; and if made available via Electronic
-     Distribution Mechanism, must remain available for at least twelve (12)
-     months after the date it initially became available, or at least six
-     (6) months after a subsequent version of that particular Modification
-     has been made available to such recipients. You are responsible for
-     ensuring that the Source Code version remains available even if the
-     Electronic Distribution Mechanism is maintained by a third party.
-
-     3.3. Description of Modifications.
-     You must cause all Covered Code to which You contribute to contain a
-     file documenting the changes You made to create that Covered Code and
-     the date of any change. You must include a prominent statement that
-     the Modification is derived, directly or indirectly, from Original
-     Code provided by the Initial Developer and including the name of the
-     Initial Developer in (a) the Source Code, and (b) in any notice in an
-     Executable version or related documentation in which You describe the
-     origin or ownership of the Covered Code.
-
-     3.4. Intellectual Property Matters
-          (a) Third Party Claims.
-          If Contributor has knowledge that a license under a third party's
-          intellectual property rights is required to exercise the rights
-          granted by such Contributor under Sections 2.1 or 2.2,
-          Contributor must include a text file with the Source Code
-          distribution titled "LEGAL" which describes the claim and the
-          party making the claim in sufficient detail that a recipient will
-          know whom to contact. If Contributor obtains such knowledge after
-          the Modification is made available as described in Section 3.2,
-          Contributor shall promptly modify the LEGAL file in all copies
-          Contributor makes available thereafter and shall take other steps
-          (such as notifying appropriate mailing lists or newsgroups)
-          reasonably calculated to inform those who received the Covered
-          Code that new knowledge has been obtained.
-
-          (b) Contributor APIs.
-          If Contributor's Modifications include an application programming
-          interface and Contributor has knowledge of patent licenses which
-          are reasonably necessary to implement that API, Contributor must
-          also include this information in the LEGAL file.
-
-               (c)    Representations.
-          Contributor represents that, except as disclosed pursuant to
-          Section 3.4(a) above, Contributor believes that Contributor's
-          Modifications are Contributor's original creation(s) and/or
-          Contributor has sufficient rights to grant the rights conveyed by
-          this License.
-
-     3.5. Required Notices.
-     You must duplicate the notice in Exhibit A in each file of the Source
-     Code.  If it is not possible to put such notice in a particular Source
-     Code file due to its structure, then You must include such notice in a
-     location (such as a relevant directory) where a user would be likely
-     to look for such a notice.  If You created one or more Modification(s)
-     You may add your name as a Contributor to the notice described in
-     Exhibit A.  You must also duplicate this License in any documentation
-     for the Source Code where You describe recipients' rights or ownership
-     rights relating to Covered Code.  You may choose to offer, and to
-     charge a fee for, warranty, support, indemnity or liability
-     obligations to one or more recipients of Covered Code. However, You
-     may do so only on Your own behalf, and not on behalf of the Initial
-     Developer or any Contributor. You must make it absolutely clear than
-     any such warranty, support, indemnity or liability obligation is
-     offered by You alone, and You hereby agree to indemnify the Initial
-     Developer and every Contributor for any liability incurred by the
-     Initial Developer or such Contributor as a result of warranty,
-     support, indemnity or liability terms You offer.
-
-     3.6. Distribution of Executable Versions.
-     You may distribute Covered Code in Executable form only if the
-     requirements of Section 3.1-3.5 have been met for that Covered Code,
-     and if You include a notice stating that the Source Code version of
-     the Covered Code is available under the terms of this License,
-     including a description of how and where You have fulfilled the
-     obligations of Section 3.2. The notice must be conspicuously included
-     in any notice in an Executable version, related documentation or
-     collateral in which You describe recipients' rights relating to the
-     Covered Code. You may distribute the Executable version of Covered
-     Code or ownership rights under a license of Your choice, which may
-     contain terms different from this License, provided that You are in
-     compliance with the terms of this License and that the license for the
-     Executable version does not attempt to limit or alter the recipient's
-     rights in the Source Code version from the rights set forth in this
-     License. If You distribute the Executable version under a different
-     license You must make it absolutely clear that any terms which differ
-     from this License are offered by You alone, not by the Initial
-     Developer or any Contributor. You hereby agree to indemnify the
-     Initial Developer and every Contributor for any liability incurred by
-     the Initial Developer or such Contributor as a result of any such
-     terms You offer.
-
-     3.7. Larger Works.
-     You may create a Larger Work by combining Covered Code with other code
-     not governed by the terms of this License and distribute the Larger
-     Work as a single product. In such a case, You must make sure the
-     requirements of this License are fulfilled for the Covered Code.
-
-4. Inability to Comply Due to Statute or Regulation.
-
-     If it is impossible for You to comply with any of the terms of this
-     License with respect to some or all of the Covered Code due to
-     statute, judicial order, or regulation then You must: (a) comply with
-     the terms of this License to the maximum extent possible; and (b)
-     describe the limitations and the code they affect. Such description
-     must be included in the LEGAL file described in Section 3.4 and must
-     be included with all distributions of the Source Code. Except to the
-     extent prohibited by statute or regulation, such description must be
-     sufficiently detailed for a recipient of ordinary skill to be able to
-     understand it.
-
-5. Application of this License.
-
-     This License applies to code to which the Initial Developer has
-     attached the notice in Exhibit A and to related Covered Code.
-
-6. Versions of the License.
-
-     6.1. New Versions.
-     Netscape Communications Corporation ("Netscape") may publish revised
-     and/or new versions of the License from time to time. Each version
-     will be given a distinguishing version number.
-
-     6.2. Effect of New Versions.
-     Once Covered Code has been published under a particular version of the
-     License, You may always continue to use it under the terms of that
-     version. You may also choose to use such Covered Code under the terms
-     of any subsequent version of the License published by Netscape. No one
-     other than Netscape has the right to modify the terms applicable to
-     Covered Code created under this License.
-
-     6.3. Derivative Works.
-     If You create or use a modified version of this License (which you may
-     only do in order to apply it to code which is not already Covered Code
-     governed by this License), You must (a) rename Your license so that
-     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
-     "MPL", "NPL" or any confusingly similar phrase do not appear in your
-     license (except to note that your license differs from this License)
-     and (b) otherwise make it clear that Your version of the license
-     contains terms which differ from the Mozilla Public License and
-     Netscape Public License. (Filling in the name of the Initial
-     Developer, Original Code or Contributor in the notice described in
-     Exhibit A shall not of themselves be deemed to be modifications of
-     this License.)
-
-7. DISCLAIMER OF WARRANTY.
-
-     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
-     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
-     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
-     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
-     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
-     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
-     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
-     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
-     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
-     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
-
-8. TERMINATION.
-
-     8.1.  This License and the rights granted hereunder will terminate
-     automatically if You fail to comply with terms herein and fail to cure
-     such breach within 30 days of becoming aware of the breach. All
-     sublicenses to the Covered Code which are properly granted shall
-     survive any termination of this License. Provisions which, by their
-     nature, must remain in effect beyond the termination of this License
-     shall survive.
-
-     8.2.  If You initiate litigation by asserting a patent infringement
-     claim (excluding declatory judgment actions) against Initial Developer
-     or a Contributor (the Initial Developer or Contributor against whom
-     You file such action is referred to as "Participant")  alleging that:
-
-     (a)  such Participant's Contributor Version directly or indirectly
-     infringes any patent, then any and all rights granted by such
-     Participant to You under Sections 2.1 and/or 2.2 of this License
-     shall, upon 60 days notice from Participant terminate prospectively,
-     unless if within 60 days after receipt of notice You either: (i)
-     agree in writing to pay Participant a mutually agreeable reasonable
-     royalty for Your past and future use of Modifications made by such
-     Participant, or (ii) withdraw Your litigation claim with respect to
-     the Contributor Version against such Participant.  If within 60 days
-     of notice, a reasonable royalty and payment arrangement are not
-     mutually agreed upon in writing by the parties or the litigation claim
-     is not withdrawn, the rights granted by Participant to You under
-     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
-     the 60 day notice period specified above.
-
-     (b)  any software, hardware, or device, other than such Participant's
-     Contributor Version, directly or indirectly infringes any patent, then
-     any rights granted to You by such Participant under Sections 2.1(b)
-     and 2.2(b) are revoked effective as of the date You first made, used,
-     sold, distributed, or had made, Modifications made by that
-     Participant.
-
-     8.3.  If You assert a patent infringement claim against Participant
-     alleging that such Participant's Contributor Version directly or
-     indirectly infringes any patent where such claim is resolved (such as
-     by license or settlement) prior to the initiation of patent
-     infringement litigation, then the reasonable value of the licenses
-     granted by such Participant under Sections 2.1 or 2.2 shall be taken
-     into account in determining the amount or value of any payment or
-     license.
-
-     8.4.  In the event of termination under Sections 8.1 or 8.2 above,
-     all end user license agreements (excluding distributors and resellers)
-     which have been validly granted by You or any distributor hereunder
-     prior to termination shall survive termination.
-
-9. LIMITATION OF LIABILITY.
-
-     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
-     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
-     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
-     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
-     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
-     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
-     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
-     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
-     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
-     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
-     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
-     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
-     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
-     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
-
-10. U.S. GOVERNMENT END USERS.
-
-     The Covered Code is a "commercial item," as that term is defined in
-     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
-     software" and "commercial computer software documentation," as such
-     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
-     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
-     all U.S. Government End Users acquire Covered Code with only those
-     rights set forth herein.
-
-11. MISCELLANEOUS.
-
-     This License represents the complete agreement concerning subject
-     matter hereof. If any provision of this License is held to be
-     unenforceable, such provision shall be reformed only to the extent
-     necessary to make it enforceable. This License shall be governed by
-     California law provisions (except to the extent applicable law, if
-     any, provides otherwise), excluding its conflict-of-law provisions.
-     With respect to disputes in which at least one party is a citizen of,
-     or an entity chartered or registered to do business in the United
-     States of America, any litigation relating to this License shall be
-     subject to the jurisdiction of the Federal Courts of the Northern
-     District of California, with venue lying in Santa Clara County,
-     California, with the losing party responsible for costs, including
-     without limitation, court costs and reasonable attorneys' fees and
-     expenses. The application of the United Nations Convention on
-     Contracts for the International Sale of Goods is expressly excluded.
-     Any law or regulation which provides that the language of a contract
-     shall be construed against the drafter shall not apply to this
-     License.
-
-12. RESPONSIBILITY FOR CLAIMS.
-
-     As between Initial Developer and the Contributors, each party is
-     responsible for claims and damages arising, directly or indirectly,
-     out of its utilization of rights under this License and You agree to
-     work with Initial Developer and Contributors to distribute such
-     responsibility on an equitable basis. Nothing herein is intended or
-     shall be deemed to constitute any admission of liability.
-
-13. MULTIPLE-LICENSED CODE.
-
-     Initial Developer may designate portions of the Covered Code as
-     "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
-     Developer permits you to utilize portions of the Covered Code under
-     Your choice of the NPL or the alternative licenses, if any, specified
-     by the Initial Developer in the file described in Exhibit A.
-
-EXHIBIT A -Mozilla Public License.
-
-     ``The contents of this file are subject to the Mozilla Public License
-     Version 1.1 (the "License"); you may not use this file except in
-     compliance with the License. You may obtain a copy of the License at
-     http://www.mozilla.org/MPL/
-
-     Software distributed under the License is distributed on an "AS IS"
-     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-     License for the specific language governing rights and limitations
-     under the License.
-
-     The Original Code is ______________________________________.
-
-     The Initial Developer of the Original Code is ________________________.
-     Portions created by ______________________ are Copyright (C) ______
-     _______________________. All Rights Reserved.
-
-     Contributor(s): ______________________________________.
-
-     Alternatively, the contents of this file may be used under the terms
-     of the _____ license (the  "[___] License"), in which case the
-     provisions of [______] License are applicable instead of those
-     above.  If you wish to allow use of your version of this file only
-     under the terms of the [____] License and not to allow others to use
-     your version of this file under the MPL, indicate your decision by
-     deleting  the provisions above and replace  them with the notice and
-     other provisions required by the [___] License.  If you do not delete
-     the provisions above, a recipient may use your version of this file
-     under either the MPL or the [___] License."
-
-     [NOTE: The text of this Exhibit A may differ slightly from the text of
-     the notices in the Source Code files of the Original Code. You should
-     use the text of this Exhibit A rather than the text found in the
-     Original Code Source Code for Your Modifications.]
-
diff --git a/mcs/LICENSE.MSPL b/mcs/LICENSE.MSPL
deleted file mode 100644 (file)
index 79629b2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-Microsoft Permissive License (Ms-PL)\r
\r
-       This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.\r
\r
-1. Definitions\r
-\r
-       The terms \93reproduce,\94 \93reproduction,\94 \93derivative works,\94 and \93distribution\94 have the same meaning here as under U.S. copyright law.\r
-       A \93contribution\94 is the original software, or any additions or changes to the software.\r
-       A \93contributor\94 is any person that distributes its contribution under this license.\r
-        \93Licensed patents\94 are a contributor\92s patent claims that read directly on its contribution.\r
\r
-2. Grant of Rights\r
-\r
-       (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.\r
-       (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.\r
\r
-3. Conditions and Limitations\r
-\r
-       (A) No Trademark License- This license does not grant you rights to use any contributors\92 name, logo, or trademarks.\r
-       (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.\r
-       (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.\r
-       (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.\r
-       (E) The software is licensed \93as-is.\94 You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.\r
-       (F) If you distribute the software or derivative works with programs you develop, you agree to indemnify, defend, and hold harmless all contributors from any claims, including attorneys\92 fees, related to the distribution or use of your programs.  For clarity, you have no such obligations to a contributor for any claims based solely on the unmodified contributions of that contributor.\r
-       (G) If you make any additions or changes to the original software, you may only distribute them under a new namespace.  In addition, you will clearly identify your changes or additions as your own.\r
-\r
-\r
diff --git a/mcs/MIT.X11 b/mcs/MIT.X11
deleted file mode 100644 (file)
index cb4a84d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-Copyright (c) 2001, 2002, 2003 Ximian, Inc and the individuals listed
-on the ChangeLog entries.
-
-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.
index e31193319f10b19b532b58db560ea1bfce425177..1f4566b61c75f38eb221f66a923fb57de932d930 100644 (file)
@@ -88,10 +88,6 @@ DISTFILES = \
        COPYING                 \
        COPYING.LIB             \
        INSTALL.txt             \
-       LICENSE                 \
-       LICENSE.GPL             \
-       LICENSE.LGPL            \
-       LICENSE.MPL             \
        Makefile                \
        mkinstalldirs           \
        MIT.X11                 \
index 2a64e0f6ef65989c43185a511fdc9bf9e6b74332..f23a12d69bfe078c688a21ac954522a7a7fe3ece 100644 (file)
@@ -85,46 +85,3 @@ If you want to only run the tests in a single fixture (say
 Thanks a lot to Sergey Chaban for his help during the development of
 the C# compiler.
 
-* LICENSE
-=========
-
-The mcs C# compiler and monoresgen are licensed to you under the GPL, version 2.
-The complete text of the GPL is in the 'COPYING' file.
-
-    Copyright (C) 2001-2002  Ximian, Inc.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of version 2 of the GNU General Public License as 
-    published by the Free Software Foundation.
-
-    This program 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 General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-The class libraries are licensed according to the following license:
-
-    Copyright (C) 2001-2002  Ximian, 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.
-
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                \
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 513dc61bd4fdea8fdd3c87a8df120f01c13ccd9d..17f56e3c4054885b5f5cf4477cef4bed1ff63c44 100644 (file)
@@ -1 +1,6 @@
 #include mobile_Mono.Security.dll.sources
+../corlib/CommonCrypto/CommonCrypto.cs
+../corlib/CommonCrypto/RC4CommonCrypto.cs
+../corlib/CommonCrypto/MD2Managed.g.cs
+../corlib/CommonCrypto/MD4Managed.g.cs
+../corlib/CommonCrypto/SHA224Managed.g.cs
diff --git a/mcs/class/Mono.Security/monotouch_opt_Mono.Security.dll.sources b/mcs/class/Mono.Security/monotouch_opt_Mono.Security.dll.sources
deleted file mode 100644 (file)
index e8464be..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-./Mono.Security.Cryptography/ARC4Managed.cs
-./Mono.Security.Cryptography/MD2Managed.cs
-./Mono.Security.Cryptography/MD4Managed.cs
-./Mono.Security.Cryptography/SHA224Managed.cs
index 1379fa79d8038df905a3a62f2e9bf124b648466d..6c1b4dbef6fda25d7d76612c984ad0776f33ee7f 100644 (file)
@@ -1,2 +1,7 @@
 #include monotouch_Mono.Security.dll.sources
+../corlib/CommonCrypto/CommonCrypto.cs
+../corlib/CommonCrypto/RC4CommonCrypto.cs
+../corlib/CommonCrypto/MD2Managed.g.cs
+../corlib/CommonCrypto/MD4Managed.g.cs
+../corlib/CommonCrypto/SHA224Managed.g.cs
 
diff --git a/mcs/class/Mono.Security/xammac_opt_Mono.Security.dll.sources b/mcs/class/Mono.Security/xammac_opt_Mono.Security.dll.sources
deleted file mode 100644 (file)
index e8464be..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-./Mono.Security.Cryptography/ARC4Managed.cs
-./Mono.Security.Cryptography/MD2Managed.cs
-./Mono.Security.Cryptography/MD4Managed.cs
-./Mono.Security.Cryptography/SHA224Managed.cs
index 8aabd350f40cef794cef17ee3bcfe2c8b01fd9a1..0e2a01190908f45ca20d357485ac7db8c67c57d8 100755 (executable)
@@ -6,20 +6,7 @@
 #
 # Copyright (c) 2007 Novell, Inc.
 #
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of version 2 of the GNU General Public
-# License as published by the Free Software Foundation.
-#
-# This program 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
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public
-# License along with this program; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-##############################################################
+# Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
 
 
index 7d32d44a88bd84c6036228fd2caebd01a9efbf7b..6b6d96c25a26397c17d3d29deeb327f14a235814 100644 (file)
@@ -1,2 +1,4 @@
 #include common_System.Core.dll.sources
 #include interpreter_System.Core.dll.sources
+../corlib/CommonCrypto/AesManaged.g.cs
+../corlib/CommonCrypto/AesCryptoServiceProvider.g.cs
index 882476b4b5e7308adf7bb8013f2c75a43f6c2d46..6ab44f0f8c2cb558e83d94f40731fe88409b4703 100644 (file)
@@ -1,4 +1,5 @@
 #include common_System.Core.dll.sources
 
 #include dynamic_System.Core.dll.sources
-
+../corlib/CommonCrypto/AesManaged.g.cs
+../corlib/CommonCrypto/AesCryptoServiceProvider.g.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
diff --git a/mcs/class/System.Net.Http/System.Net.Http/HttpClient.mac.cs b/mcs/class/System.Net.Http/System.Net.Http/HttpClient.mac.cs
new file mode 100644 (file)
index 0000000..42f664c
--- /dev/null
@@ -0,0 +1,23 @@
+using System;
+using System.Reflection;
+
+[assembly:System.Runtime.CompilerServices.InternalsVisibleTo ("Xamarin.Mac, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
+
+namespace System.Net.Http {
+       public partial class HttpClient {
+
+               public HttpClient ()
+                       : this (GetDefaultHandler (), true)
+               {
+               }
+
+               // note: the linker will re-write ObjCRuntime.RuntimeOptions.GetHttpMessageHandler to return the correct type
+               // unlike, XI where this method itself gets rewritten during linking
+               static HttpMessageHandler GetDefaultHandler ()
+               {
+                       Type type = Type.GetType("ObjCRuntime.RuntimeOptions, Xamarin.Mac");
+                       var method = type.GetMethod ("GetHttpMessageHandler", BindingFlags.Static | BindingFlags.NonPublic);
+                       return (HttpMessageHandler)method.Invoke (null, null);
+               }
+       }
+}
index 52a64788971e226d362bf1cf43a8a090ed8a9204..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;
@@ -1080,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;
@@ -1091,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 ();
                        }
                }
 
@@ -1151,6 +1166,11 @@ 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));
index fbffe9e7634bb2e8d42c512f49453edf60a03b1e..216e48da9cdbcb384ba0ecc8b3c4aa814c2f4ce5 100644 (file)
@@ -1 +1,2 @@
 #include System.Net.Http.dll.sources
+System.Net.Http/HttpClient.mac.cs
index fbffe9e7634bb2e8d42c512f49453edf60a03b1e..216e48da9cdbcb384ba0ecc8b3c4aa814c2f4ce5 100644 (file)
@@ -1 +1,2 @@
 #include System.Net.Http.dll.sources
+System.Net.Http/HttpClient.mac.cs
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 fdbcc77c5ba9a9dd2165481724d0e3d2285a8745..f0b6d8d669a1ad8d38cbc385a3bb10d92bf16376 100644 (file)
@@ -507,11 +507,15 @@ namespace System.Runtime.Serialization
                                                } else {
                                                        var typeHandleValue = Type.GetTypeHandle (memberValue);
                                                        var isDeclaredType = typeHandleValue.Equals (CodeInterpreter.ConvertValue (memberValue, memberType, Globals.TypeOfObject));
-                                                       if (isNullableOfT)
+                                                       if (isNullableOfT) {
                                                                ctx.InternalSerialize (writer, memberValue, isDeclaredType, writeXsiType, DataContract.GetId (memberType.TypeHandle), memberType.TypeHandle);
-                                                       else
-                                                               ctx.InternalSerializeReference (writer, memberValue, isDeclaredType, writeXsiType, DataContract.GetId (memberType.TypeHandle), memberType.TypeHandle);                                                          
-                                                       //InternalSerialize((isNullableOfT ? XmlFormatGeneratorStatics.InternalSerializeMethod : XmlFormatGeneratorStatics.InternalSerializeReferenceMethod), () => memberValue, memberType, writeXsiType);
+                                                       } else if (memberType == Globals.TypeOfObject) {
+                                                               var dataContract = DataContract.GetDataContract (memberValue.GetType());
+                                                               writer.WriteAttributeQualifiedName (Globals.XsiPrefix, DictionaryGlobals.XsiTypeLocalName, DictionaryGlobals.SchemaInstanceNamespace, dataContract.Name, dataContract.Namespace);
+                                                               ctx.InternalSerializeReference (writer, memberValue, false, false, -1, typeHandleValue);
+                                                       } else {
+                                                               ctx.InternalSerializeReference (writer, memberValue, isDeclaredType, writeXsiType, DataContract.GetId (memberType.TypeHandle), memberType.TypeHandle);
+                                                       }
                                                }
                                        }
                                }
index ada461fe2b8610290a5e9ef17a4170552cfd21e9..89c0bef1b557867cea18843de713a736cb4fd0e5 100644 (file)
@@ -122,5 +122,17 @@ namespace MonoTests.System.Runtime.Serialization
                                Assert.IsTrue (s.Contains ("<Flags>All</Flags>"));
                        }
                }
+
+               // Bug #37116
+               [Test]
+               public void KeyPairOfAny ()
+               {
+                       var dict = new Dictionary<string, object> ();
+                       dict.Add ("test", new List<string> () { "test entry" });
+
+                       var dcs = new DataContractSerializer (typeof(Dictionary<string, object>));
+                       dcs.WriteObject (new MemoryStream (), dict);
+                       // Should not throw exception.
+               }
        }
 }
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)
diff --git a/mcs/class/System/Assembly/AssemblyInfoEx.cs b/mcs/class/System/Assembly/AssemblyInfoEx.cs
new file mode 100644 (file)
index 0000000..22e5bca
--- /dev/null
@@ -0,0 +1,7 @@
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo ("monotouch, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
+[assembly: InternalsVisibleTo ("Xamarin.iOS, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
+[assembly: InternalsVisibleTo ("Xamarin.Mac, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
+[assembly: InternalsVisibleTo ("Xamarin.WatchOS, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
+[assembly: InternalsVisibleTo ("Xamarin.TVOS, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
index 63a781dbdf5a7d37628af8efb85473e6692d486e..617fbdefd531e5d2e6686ce7cc15f85348498a34 100644 (file)
@@ -296,7 +296,8 @@ namespace Mono.Net.Security
                        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;
                        }
 
diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.MonoTouch.opt.cs b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.MonoTouch.opt.cs
deleted file mode 100644 (file)
index b8c5d6d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#if MONOTOUCH || XAMMAC
-
-// this file is a shim to enable compiling monotouch profiles without mono-extensions
-namespace Mono.Net.Security
-{
-       static partial class MonoTlsProviderFactory
-       {
-               static IMonoTlsProvider CreateDefaultProvider ()
-               {
-                       throw new System.NotSupportedException ();
-               }
-       }
-}
-
-#endif
diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactoryExt.cs b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactoryExt.cs
new file mode 100644 (file)
index 0000000..f9f939b
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 Xamarin Inc. All rights reserved.
+
+using System;
+using MSI = Mono.Security.Interface;
+
+namespace Mono.Net.Security
+{
+       static partial class MonoTlsProviderFactory
+       {
+               static IMonoTlsProvider CreateDefaultProvider ()
+               {
+                       #if SECURITY_DEP
+                       MSI.MonoTlsProvider provider = null;
+                       if (MSI.MonoTlsProviderFactory._PrivateFactoryDelegate != null)
+                               provider = MSI.MonoTlsProviderFactory._PrivateFactoryDelegate ();
+                       if (provider != null)
+                               return new Private.MonoTlsProviderWrapper (provider);
+                       #endif
+                       return null;
+               }
+       }
+}
index dd67b660bef8f9212278f53c7bf6fecb62210068..8cd1ca0b6fac8de068150a1b0e18f3342ce8a7c0 100644 (file)
@@ -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)) {
diff --git a/mcs/class/System/Mono.Security.Interface/MonoTlsProviderFactoryExt.cs b/mcs/class/System/Mono.Security.Interface/MonoTlsProviderFactoryExt.cs
new file mode 100644 (file)
index 0000000..e902c80
--- /dev/null
@@ -0,0 +1,9 @@
+namespace Mono.Security.Interface
+{
+       public delegate MonoTlsProvider MonoTlsProviderFactoryDelegate ();
+
+       static partial class MonoTlsProviderFactory
+       {
+               public static MonoTlsProviderFactoryDelegate _PrivateFactoryDelegate;
+       }
+}
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 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 8dce31d234c5b119f6502c1b4dbf3c9b3baf94c0..8f3de2eff5d4afd0a8048ca3c1460423b79e1ec6 100644 (file)
@@ -1,2 +1,5 @@
 #include mobile_System.dll.sources
 MonoTouch/MonoPInvokeCallbackAttribute.cs
+Assembly/AssemblyInfoEx.cs
+Mono.Net.Security/MonoTlsProviderFactoryExt.cs
+Mono.Security.Interface/MonoTlsProviderFactoryExt.cs
diff --git a/mcs/class/System/monotouch_opt_System.dll.sources b/mcs/class/System/monotouch_opt_System.dll.sources
deleted file mode 100644 (file)
index 6877457..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Mono.Net.Security/MonoTlsProviderFactory.MonoTouch.opt.cs
diff --git a/mcs/class/System/monotouch_runtime_opt_System.dll.sources b/mcs/class/System/monotouch_runtime_opt_System.dll.sources
deleted file mode 100644 (file)
index 54025c5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_opt_System.dll.sources
diff --git a/mcs/class/System/monotouch_tv_opt_System.dll.sources b/mcs/class/System/monotouch_tv_opt_System.dll.sources
deleted file mode 100644 (file)
index 54025c5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_opt_System.dll.sources
diff --git a/mcs/class/System/monotouch_tv_runtime_opt_System.dll.sources b/mcs/class/System/monotouch_tv_runtime_opt_System.dll.sources
deleted file mode 100644 (file)
index 54025c5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_opt_System.dll.sources
diff --git a/mcs/class/System/monotouch_watch_opt_System.dll.sources b/mcs/class/System/monotouch_watch_opt_System.dll.sources
deleted file mode 100644 (file)
index 54025c5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_opt_System.dll.sources
diff --git a/mcs/class/System/monotouch_watch_runtime_opt_System.dll.sources b/mcs/class/System/monotouch_watch_runtime_opt_System.dll.sources
deleted file mode 100644 (file)
index 54025c5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_opt_System.dll.sources
index 70a77a6dbff401e4d973b5d5f8ce11321a969f9a..330f5106870020aee431722048cc1f9f8e8a4ba5 100644 (file)
@@ -1 +1,4 @@
 #include mobile_System.dll.sources
+Assembly/AssemblyInfoEx.cs
+Mono.Net.Security/MonoTlsProviderFactoryExt.cs
+Mono.Security.Interface/MonoTlsProviderFactoryExt.cs
index 3ff0aad1cfbd9e7ccb83c6ef390899c0cf041fe2..7e48f7ecc9d76cd28f42010171c2275d41b2d00f 100644 (file)
@@ -1 +1,2 @@
 #include System.dll.sources
+Assembly/AssemblyInfoEx.cs
diff --git a/mcs/class/System/xammac_net_4_5_opt_System.dll.sources b/mcs/class/System/xammac_net_4_5_opt_System.dll.sources
deleted file mode 100644 (file)
index 86ff246..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include xammac_opt_System.dll.sources
diff --git a/mcs/class/System/xammac_opt_System.dll.sources b/mcs/class/System/xammac_opt_System.dll.sources
deleted file mode 100644 (file)
index 6877457..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Mono.Net.Security/MonoTlsProviderFactory.MonoTouch.opt.cs
diff --git a/mcs/class/corlib/CommonCrypto/.gitignore b/mcs/class/corlib/CommonCrypto/.gitignore
new file mode 100644 (file)
index 0000000..1252b93
--- /dev/null
@@ -0,0 +1,2 @@
+*.g.cs
+generator.exe
diff --git a/mcs/class/corlib/CommonCrypto/CommonCrypto.cs b/mcs/class/corlib/CommonCrypto/CommonCrypto.cs
new file mode 100644 (file)
index 0000000..c765b95
--- /dev/null
@@ -0,0 +1,130 @@
+// CommonCrypto bindings for MonoMac and MonoTouch
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012-2014 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+using System.Runtime.InteropServices;
+
+namespace Crimson.CommonCrypto {
+
+       // int32_t -> CommonCryptor.h
+       enum CCCryptorStatus {
+           Success                     = 0,
+       ParamError              = -4300,
+           BufferTooSmall      = -4301,
+       MemoryFailure   = -4302,
+       AlignmentError  = -4303,
+       DecodeError             = -4304,
+       Unimplemented   = -4305
+       }
+       
+       // uint32_t -> CommonCryptor.h
+       // note: not exposed publicly so it can stay signed
+       enum CCOperation {
+               Encrypt = 0, 
+               Decrypt,     
+       }
+
+       // uint32_t -> CommonCryptor.h
+       // note: not exposed publicly so it can stay signed
+       enum CCAlgorithm {
+               AES128 = 0,
+               DES,        
+               TripleDES,       
+               CAST,       
+               RC4,
+               RC2,   
+               Blowfish    
+       }
+       
+       // uint32_t -> CommonCryptor.h
+       // note: not exposed publicly so it can stay signed
+       [Flags]
+       enum CCOptions {
+               None                    = 0,
+               PKCS7Padding    = 1,
+               ECBMode                 = 2
+       }
+       
+       static class Cryptor {
+               
+               const string libSystem = "/usr/lib/libSystem.dylib";
+               
+               // size_t was changed to IntPtr for 32/64 bits size difference - even if mono is (moslty) used in 32bits only on OSX today
+               // not using `nint` to be able to resue this outside (if needed)
+               
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorCreate (CCOperation op, CCAlgorithm alg, CCOptions options, /* const void* */ byte[] key, /* size_t */ IntPtr keyLength, /* const void* */ byte[] iv, /* CCCryptorRef* */ ref IntPtr cryptorRef);
+
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorRelease (/* CCCryptorRef */ IntPtr cryptorRef);
+
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorUpdate (/* CCCryptorRef */ IntPtr cryptorRef, /* const void* */ byte[] dataIn, /* size_t */ IntPtr dataInLength, /* void* */ byte[] dataOut, /* size_t */ IntPtr dataOutAvailable, /* size_t* */ ref IntPtr dataOutMoved);
+
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorUpdate (/* CCCryptorRef */ IntPtr cryptorRef, /* const void* */ IntPtr dataIn, /* size_t */ IntPtr dataInLength, /* void* */ IntPtr dataOut, /* size_t */ IntPtr dataOutAvailable, /* size_t* */ ref IntPtr dataOutMoved);
+
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorFinal (/* CCCryptorRef */ IntPtr cryptorRef, /* void* */ byte[] dataOut, /* size_t */ IntPtr dataOutAvailable, /* size_t* */ ref IntPtr dataOutMoved);
+
+               [DllImport (libSystem)]
+               extern internal static int CCCryptorGetOutputLength (/* CCCryptorRef */ IntPtr cryptorRef, /* size_t */ IntPtr inputLength, bool final);
+
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorReset (/* CCCryptorRef */ IntPtr cryptorRef, /* const void* */ IntPtr iv);
+               
+               // helper method to reduce the amount of generate code for each cipher algorithm
+               static internal IntPtr Create (CCOperation operation, CCAlgorithm algorithm, CCOptions options, byte[] key, byte[] iv)
+               {
+                       if (key == null)
+                               throw new CryptographicException ("A null key was provided");
+                       
+                       // unlike the .NET framework CommonCrypto does not support two-keys triple-des (128 bits) ref: #6967
+                       if ((algorithm == CCAlgorithm.TripleDES) && (key.Length == 16)) {
+                               byte[] key3 = new byte [24];
+                               Buffer.BlockCopy (key, 0, key3, 0, 16);
+                               Buffer.BlockCopy (key, 0, key3, 16, 8);
+                               key = key3;
+                       }
+                       
+                       IntPtr cryptor = IntPtr.Zero;
+                       CCCryptorStatus status = Cryptor.CCCryptorCreate (operation, algorithm, options, key, (IntPtr) key.Length, iv, ref cryptor);
+                       if (status != CCCryptorStatus.Success)
+                               throw new CryptographicUnexpectedOperationException ();
+                       return cryptor;
+               }
+
+               // size_t was changed to IntPtr for 32/64 bits size difference - even if mono is (moslty) used in 32bits only on OSX today
+               [DllImport ("/System/Library/Frameworks/Security.framework/Security")]
+               extern internal static /* int */ int SecRandomCopyBytes (/* SecRandomRef */ IntPtr rnd, /* size_t */ IntPtr count, /* uint8_t* */ byte[] bytes);
+               
+               static internal void GetRandom (byte[] buffer)
+               {
+                       if (SecRandomCopyBytes (IntPtr.Zero, (IntPtr) buffer.Length, buffer) != 0)
+                               throw new CryptographicException (Marshal.GetLastWin32Error ()); // errno
+               }
+       }
+       
+#if !MONOTOUCH && !XAMMAC
+       static class KeyBuilder {
+               static public byte[] Key (int size) 
+               {
+                       byte[] buffer = new byte [size];
+                       Cryptor.GetRandom (buffer);
+                       return buffer;
+               }
+       
+               static public byte[] IV (int size) 
+               {
+                       byte[] buffer = new byte [size];
+                       Cryptor.GetRandom (buffer);
+                       return buffer;
+               }
+       }
+#endif
+}
diff --git a/mcs/class/corlib/CommonCrypto/CommonCryptorGenerator.cs b/mcs/class/corlib/CommonCrypto/CommonCryptorGenerator.cs
new file mode 100644 (file)
index 0000000..f177c17
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// CommonCrypto code generator for symmetric block cipher algorithms
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012 Xamarin Inc.
+//
+
+using System;
+using System.IO;
+
+namespace Xamarin {
+
+       public static class CommonCryptor {
+               
+               static public void Generate (string namespaceName, string typeName, string baseTypeName, string ccAlgorithmName, string feedbackSize = "8", string ctorInitializers = null)
+               {
+                       string template = @"// Generated file to bind CommonCrypto cipher algorithms - DO NOT EDIT
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012-2014 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+
+using Mono.Security.Cryptography;
+using Crimson.CommonCrypto;
+
+namespace %NAMESPACE% {
+
+       public sealed partial class %TYPE% : %BASE% {
+               
+               public %TYPE% ()
+               {
+                       FeedbackSizeValue = %FEEDBACKSIZE%;
+                       %CTOR_INIT%
+               }
+               
+               public override void GenerateIV ()
+               {
+                       IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
+               }
+               
+               public override void GenerateKey ()
+               {
+                       KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
+               }
+               
+               public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       IntPtr decryptor = IntPtr.Zero;
+                       switch (Mode) {
+                       case CipherMode.CBC:
+                               decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.None, rgbKey, rgbIV);
+                               return new FastCryptorTransform (decryptor, this, false, rgbIV);
+                       case CipherMode.ECB:
+                               decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.ECBMode, rgbKey, rgbIV);
+                               return new FastCryptorTransform (decryptor, this, false, rgbIV);
+                       case CipherMode.CFB:
+#if MONOTOUCH || XAMMAC
+                               IntPtr encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.ECBMode, rgbKey, rgbIV);
+                               decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.ECBMode, rgbKey, rgbIV);
+                               return new CryptorTransform (decryptor, encryptor, this, false, rgbIV);
+#else
+                               throw new CryptographicException (""CFB is not supported by Crimson.CommonCrypto"");
+#endif
+                       default:
+                               throw new CryptographicException (String.Format (""{0} is not supported by the .NET framework"", Mode));
+                       }
+               }
+               
+               public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       IntPtr encryptor = IntPtr.Zero;
+                       switch (Mode) {
+                       case CipherMode.CBC:
+                               encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.None, rgbKey, rgbIV);
+                               return new FastCryptorTransform (encryptor, this, true, rgbIV);
+                       case CipherMode.ECB:
+                               encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.ECBMode, rgbKey, rgbIV);
+                               return new FastCryptorTransform (encryptor, this, true, rgbIV);
+                       case CipherMode.CFB:
+#if MONOTOUCH || XAMMAC
+                               encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.ECBMode, rgbKey, rgbIV);
+                               return new CryptorTransform (encryptor, IntPtr.Zero, this, true, rgbIV);
+#else
+                               throw new CryptographicException (""CFB is not supported by Crimson.CommonCrypto"");
+#endif
+                       default:
+                               throw new CryptographicException (String.Format (""{0} is not supported by the .NET framework"", Mode));
+                       }
+               }
+       }
+}";
+                       
+                       File.WriteAllText (typeName + ".g.cs", template.Replace ("%NAMESPACE%", namespaceName).
+                               Replace ("%TYPE%", typeName).Replace ("%BASE%", baseTypeName).Replace("%FEEDBACKSIZE%", feedbackSize).Replace ("%CTOR_INIT%", ctorInitializers).
+                               Replace ("%CCALGORITHM%", ccAlgorithmName.ToString ()));
+               }
+       }
+}
diff --git a/mcs/class/corlib/CommonCrypto/CommonDigestGenerator.cs b/mcs/class/corlib/CommonCrypto/CommonDigestGenerator.cs
new file mode 100644 (file)
index 0000000..1b729e3
--- /dev/null
@@ -0,0 +1,167 @@
+//
+// CommonCrypto code generator for digest algorithms
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012-2014 Xamarin Inc.
+//
+
+using System;
+using System.IO;
+
+namespace Xamarin {
+
+       public static class CommonDigest {
+               
+#if !MONOTOUCH && !XAMMAC
+               // we do not add anything in MonoTouch, just replacing, so this is not needed
+               // however we can avoid a dependency on Mono.Security for Crimson.CommonCrypto.dll by including the base classes
+               static public void GenerateBaseClass (string namespaceName, string typeName, string baseTypeName, int hashSize,
+                       string visibilityStart = "", string visibilityEnd = "")
+               {
+                       string template = @"// Generated file to bind CommonCrypto/CommonDigest - DO NOT EDIT
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012-2014 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+using System.Runtime.InteropServices;
+
+namespace %NAMESPACE% {
+
+%VISIBILITY_START%
+       public
+%VISIBILITY_END%
+       abstract class %BASE% : HashAlgorithm {
+
+               protected %BASE% () 
+               {
+                       HashSizeValue = %HASHSIZE%; 
+               }
+
+               public static new %BASE% Create ()
+               {
+                       return Create (""%BASE%"");
+               }
+
+               public static new %BASE% Create (string hashName)
+               {
+                       object o = CryptoConfig.CreateFromName (hashName);
+                       return (%BASE%) o ?? new %TYPE% ();
+               }
+       }
+}";
+                       
+                       File.WriteAllText (baseTypeName + ".g.cs", template.Replace ("%NAMESPACE%", namespaceName).
+                               Replace ("%TYPE%", typeName).Replace ("%BASE%", baseTypeName).
+                               Replace ("%VISIBILITY_START%", visibilityStart).Replace ("%VISIBILITY_END%", visibilityEnd).
+                               Replace ("%HASHSIZE%", hashSize.ToString ()));
+               }
+#endif
+               static public void Generate (string namespaceName, string typeName, string baseTypeName, int contextSize,
+                       string visibilityStart = "", string visibilityEnd = "")
+               {
+                       string template = @"// Generated file to bind CommonCrypto/CommonDigest - DO NOT EDIT
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2011-2014 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+using System.Runtime.InteropServices;
+
+using Mono.Security.Cryptography;
+
+namespace %NAMESPACE% {
+
+%VISIBILITY_START%
+       public
+%VISIBILITY_END%
+       sealed class %TYPE% : %BASE% {
+
+               IntPtr ctx;
+
+               [DllImport (""/usr/lib/libSystem.dylib"", EntryPoint=""CC_%BASE%_Init"")]
+               static extern int Init (/* CC_%BASE%_CTX */ IntPtr c);
+
+               [DllImport (""/usr/lib/libSystem.dylib"", EntryPoint=""CC_%BASE%_Update"")]
+               static extern int Update (/* CC_%BASE%_CTX */ IntPtr c, /* const void * */ IntPtr data, /* uint32_t */ uint len);
+
+               [DllImport (""/usr/lib/libSystem.dylib"", EntryPoint=""CC_%BASE%_Final"")]
+               static extern int Final (/* unsigned char * */ byte [] md, /* CC_%BASE%_CTX */ IntPtr c);
+
+               public %TYPE% ()
+               {
+                       ctx = IntPtr.Zero;
+               }
+
+               ~%TYPE% ()
+               {
+                       Dispose (false);
+               }
+
+               protected override void Dispose (bool disposing)
+               {
+                       if (ctx != IntPtr.Zero) {
+                               Marshal.FreeHGlobal (ctx);
+                               ctx = IntPtr.Zero;
+                       }
+                       base.Dispose (disposing);
+                       GC.SuppressFinalize (this);
+               }
+
+               public override void Initialize ()
+               {
+                       if (ctx == IntPtr.Zero)
+                               ctx = Marshal.AllocHGlobal (%CTX_SIZE%);
+                       
+                       int hr = Init (ctx);
+                       if (hr != 1)
+                               throw new CryptographicException (hr);
+               }
+
+               protected override void HashCore (byte[] data, int start, int length) 
+               {
+                       if (ctx == IntPtr.Zero)
+                               Initialize ();
+
+                       if (data.Length == 0)
+                               return;
+
+                       unsafe {
+                               fixed (byte* p = &data [0]) {
+                                       int hr = Update (ctx, (IntPtr) (p + start), (uint) length);
+                                       if (hr != 1)
+                                               throw new CryptographicException (hr);
+                               }
+                       }
+               }
+
+               protected override byte[] HashFinal () 
+               {
+                       if (ctx == IntPtr.Zero)
+                               Initialize ();
+                       
+                       byte[] data = new byte [HashSize >> 3];
+                       int hr = Final (data, ctx);
+                       if (hr != 1)
+                               throw new CryptographicException (hr);
+
+                       return data;
+               }
+       }
+}";
+                       
+                       File.WriteAllText (typeName + ".g.cs", template.Replace ("%NAMESPACE%", namespaceName).
+                               Replace ("%TYPE%", typeName).Replace ("%BASE%", baseTypeName).
+                               Replace ("%VISIBILITY_START%", visibilityStart).Replace ("%VISIBILITY_END%", visibilityEnd).
+                               Replace ("%CTX_SIZE%", contextSize.ToString ()));
+               }
+       }
+}
diff --git a/mcs/class/corlib/CommonCrypto/CorlibExtras.cs b/mcs/class/corlib/CommonCrypto/CorlibExtras.cs
new file mode 100644 (file)
index 0000000..5bdc69a
--- /dev/null
@@ -0,0 +1,24 @@
+//
+// CorlibExtras.cs: additional stuff not provided by autogenerated code
+//
+// Authors:
+//     Sebastien Pouliot (sebastien@xamarun.com)
+//
+// Copyright (C) 2012 Xamarin Inc. All rights reserved.
+//
+
+namespace System.Security.Cryptography {
+       
+       // required to ensure compatibility with MS implementation
+       public sealed partial class RC2CryptoServiceProvider : RC2 {
+               
+               public override int EffectiveKeySize {
+                       get { return base.EffectiveKeySize; }
+                       set {
+                               if (value != KeySizeValue)
+                                       throw new CryptographicUnexpectedOperationException ("Effective key size must match key size for compatibility");
+                               base.EffectiveKeySize = value; 
+                       }
+               }
+       }
+}
diff --git a/mcs/class/corlib/CommonCrypto/CryptorTransform.cs b/mcs/class/corlib/CommonCrypto/CryptorTransform.cs
new file mode 100644 (file)
index 0000000..10ca6fa
--- /dev/null
@@ -0,0 +1,60 @@
+// ICryptoTransform implementation on top of CommonCrypto and SymmetricTransform
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+
+using Mono.Security.Cryptography;
+
+namespace Crimson.CommonCrypto {
+
+       class CryptorTransform : SymmetricTransform {
+               
+               IntPtr handle;
+               IntPtr handle_e;
+               bool encryption;
+               
+               public CryptorTransform (IntPtr cryptor, IntPtr special, SymmetricAlgorithm algo, bool encryption, byte[] iv)
+                       : base (algo, encryption, iv)
+               {
+                       handle = cryptor;
+                       // for CFB we need to encrypt data while decrypting
+                       handle_e = special;
+                       this.encryption = encryption;
+               }
+               
+               ~CryptorTransform ()
+               {
+                       Dispose (false);
+               }
+               
+               // PRO: doing this ensure all cipher modes and padding modes supported by .NET will be available with CommonCrypto (drop-in replacements)
+               // CON: doing this will only process one block at the time, so it's not ideal for performance, but still a lot better than managed
+               protected override void ECB (byte[] input, byte[] output)
+               {
+                       IntPtr len = IntPtr.Zero;
+                       CCCryptorStatus s = Cryptor.CCCryptorUpdate ((encrypt == encryption) ? handle : handle_e, 
+                               input, (IntPtr) input.Length, output, (IntPtr) output.Length, ref len);
+                       if (((int) len != output.Length) || (s != CCCryptorStatus.Success))
+                               throw new CryptographicUnexpectedOperationException (s.ToString ());
+               }
+               
+               protected override void Dispose (bool disposing)
+               {
+                       if (handle != IntPtr.Zero) {
+                               Cryptor.CCCryptorRelease (handle);
+                               handle = IntPtr.Zero;
+                       }
+                       if (handle_e != IntPtr.Zero) {
+                               Cryptor.CCCryptorRelease (handle_e);
+                               handle_e = IntPtr.Zero;
+                       }
+                       base.Dispose (disposing);
+                       GC.SuppressFinalize (this);
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CommonCrypto/FastCryptorTransform.cs b/mcs/class/corlib/CommonCrypto/FastCryptorTransform.cs
new file mode 100644 (file)
index 0000000..9ff7a5a
--- /dev/null
@@ -0,0 +1,348 @@
+// Fast, multi-block, ICryptoTransform implementation on top of CommonCrypto
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+
+using Mono.Security.Cryptography;
+
+namespace Crimson.CommonCrypto {
+
+       unsafe class FastCryptorTransform : ICryptoTransform {
+               
+               IntPtr handle;
+               bool encrypt;
+               int BlockSizeByte;
+               byte[] workBuff;
+               bool lastBlock;
+               PaddingMode padding;
+               
+               public FastCryptorTransform (IntPtr cryptor, SymmetricAlgorithm algo, bool encryption, byte[] iv)
+               {
+                       BlockSizeByte = (algo.BlockSize >> 3);
+                       
+                       if (iv == null) {
+                               iv = KeyBuilder.IV (BlockSizeByte);
+                       } else if (iv.Length < BlockSizeByte) {
+                               string msg = String.Format ("IV is too small ({0} bytes), it should be {1} bytes long.",
+                                       iv.Length, BlockSizeByte);
+                               throw new CryptographicException (msg);
+                       }
+                       
+                       handle = cryptor;
+                       encrypt = encryption;
+                       padding = algo.Padding;
+                       // transform buffer
+                       workBuff = new byte [BlockSizeByte];
+               }
+               
+               ~FastCryptorTransform ()
+               {
+                       Dispose (false);
+               }
+               
+               public void Dispose ()
+               {
+                       Dispose (true);
+               }
+               
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (handle != IntPtr.Zero) {
+                               Cryptor.CCCryptorRelease (handle);
+                               handle = IntPtr.Zero;
+                       }
+                       GC.SuppressFinalize (this);
+               }
+
+               public virtual bool CanTransformMultipleBlocks {
+                       get { return true; }
+               }
+
+               public virtual bool CanReuseTransform {
+                       get { return false; }
+               }
+
+               public virtual int InputBlockSize {
+                       get { return BlockSizeByte; }
+               }
+
+               public virtual int OutputBlockSize {
+                       get { return BlockSizeByte; }
+               }
+
+               int Transform (byte[] input, int inputOffset, byte[] output, int outputOffset, int length)
+               {
+                       IntPtr len = IntPtr.Zero;
+                       IntPtr in_len = (IntPtr) length;
+                       IntPtr out_len = (IntPtr) (output.Length - outputOffset);
+                       fixed (byte* inputBuffer = &input [0])
+                       fixed (byte* outputBuffer = &output [0]) {
+                               CCCryptorStatus s = Cryptor.CCCryptorUpdate (handle, (IntPtr) (inputBuffer + inputOffset), in_len, (IntPtr) (outputBuffer + outputOffset), out_len, ref len);
+                               if (s != CCCryptorStatus.Success)
+                                       throw new CryptographicException (s.ToString ());
+                       }
+                       return (int) len;
+               }
+
+               private void CheckInput (byte[] inputBuffer, int inputOffset, int inputCount)
+               {
+                       if (inputBuffer == null)
+                               throw new ArgumentNullException ("inputBuffer");
+                       if (inputOffset < 0)
+                               throw new ArgumentOutOfRangeException ("inputOffset", "< 0");
+                       if (inputCount < 0)
+                               throw new ArgumentOutOfRangeException ("inputCount", "< 0");
+                       // ordered to avoid possible integer overflow
+                       if (inputOffset > inputBuffer.Length - inputCount)
+                               throw new ArgumentException ("inputBuffer", "Overflow");
+               }
+
+               // this method may get called MANY times so this is the one to optimize
+               public virtual int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) 
+               {
+                       CheckInput (inputBuffer, inputOffset, inputCount);
+                       // check output parameters
+                       if (outputBuffer == null)
+                               throw new ArgumentNullException ("outputBuffer");
+                       if (outputOffset < 0)
+                               throw new ArgumentOutOfRangeException ("outputOffset", "< 0");
+
+                       // ordered to avoid possible integer overflow
+                       int len = outputBuffer.Length - inputCount - outputOffset;
+                       if (!encrypt && (0 > len) && ((padding == PaddingMode.None) || (padding == PaddingMode.Zeros))) {
+                               throw new CryptographicException ("outputBuffer", "Overflow");
+                       } else if (KeepLastBlock) {
+                               if (0 > len + BlockSizeByte) {
+                                       throw new CryptographicException ("outputBuffer", "Overflow");
+                               }
+                       } else {
+                               if (0 > len) {
+                                       // there's a special case if this is the end of the decryption process
+                                       if (inputBuffer.Length - inputOffset - outputBuffer.Length == BlockSizeByte)
+                                               inputCount = outputBuffer.Length - outputOffset;
+                                       else
+                                               throw new CryptographicException ("outputBuffer", "Overflow");
+                               }
+                       }
+                       return InternalTransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+               }
+
+               private bool KeepLastBlock {
+                       get {
+                               return ((!encrypt) && (padding != PaddingMode.None) && (padding != PaddingMode.Zeros));
+                       }
+               }
+
+               private int InternalTransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) 
+               {
+                       int offs = inputOffset;
+                       int full;
+
+                       // this way we don't do a modulo every time we're called
+                       // and we may save a division
+                       if (inputCount != BlockSizeByte) {
+                               if ((inputCount % BlockSizeByte) != 0)
+                                       throw new CryptographicException ("Invalid input block size.");
+
+                               full = inputCount / BlockSizeByte;
+                       } else
+                               full = 1;
+
+                       if (KeepLastBlock)
+                               full--;
+
+                       int total = 0;
+
+                       if (lastBlock) {
+                               Transform (workBuff, 0, outputBuffer, outputOffset, BlockSizeByte);
+                               outputOffset += BlockSizeByte;
+                               total += BlockSizeByte;
+                               lastBlock = false;
+                       }
+
+                       if (full > 0) {
+                               int length = full * BlockSizeByte;
+                               Transform (inputBuffer, offs, outputBuffer, outputOffset, length);
+                               offs += length;
+                               outputOffset += length;
+                               total += length;
+                       }
+
+                       if (KeepLastBlock) {
+                               Buffer.BlockCopy (inputBuffer, offs, workBuff, 0, BlockSizeByte);
+                               lastBlock = true;
+                       }
+
+                       return total;
+               }
+
+               private void Random (byte[] buffer, int start, int length)
+               {
+                       byte[] random = new byte [length];
+                       Cryptor.GetRandom (random);
+                       Buffer.BlockCopy (random, 0, buffer, start, length);
+               }
+
+               private void ThrowBadPaddingException (PaddingMode padding, int length, int position)
+               {
+                       string msg = String.Format ("Bad {0} padding.", padding);
+                       if (length >= 0)
+                               msg += String.Format (" Invalid length {0}.", length);
+                       if (position >= 0)
+                               msg += String.Format (" Error found at position {0}.", position);
+                       throw new CryptographicException (msg);
+               }
+
+               private byte[] FinalEncrypt (byte[] inputBuffer, int inputOffset, int inputCount) 
+               {
+                       // are there still full block to process ?
+                       int full = (inputCount / BlockSizeByte) * BlockSizeByte;
+                       int rem = inputCount - full;
+                       int total = full;
+
+                       switch (padding) {
+                       case PaddingMode.ANSIX923:
+                       case PaddingMode.ISO10126:
+                       case PaddingMode.PKCS7:
+                               // we need to add an extra block for padding
+                               total += BlockSizeByte;
+                               break;
+                       default:
+                               if (inputCount == 0)
+                                       return new byte [0];
+                               if (rem != 0) {
+                                       if (padding == PaddingMode.None)
+                                               throw new CryptographicException ("invalid block length");
+                                       // zero padding the input (by adding a block for the partial data)
+                                       byte[] paddedInput = new byte [full + BlockSizeByte];
+                                       Buffer.BlockCopy (inputBuffer, inputOffset, paddedInput, 0, inputCount);
+                                       inputBuffer = paddedInput;
+                                       inputOffset = 0;
+                                       inputCount = paddedInput.Length;
+                                       total = inputCount;
+                               }
+                               break;
+                       }
+
+                       byte[] res = new byte [total];
+                       int outputOffset = 0;
+
+                       // process all blocks except the last (final) block
+                       if (total > BlockSizeByte) {
+                               outputOffset = InternalTransformBlock (inputBuffer, inputOffset, total - BlockSizeByte, res, 0);
+                               inputOffset += outputOffset;
+                       }
+
+                       // now we only have a single last block to encrypt
+                       byte pad = (byte) (BlockSizeByte - rem);
+                       switch (padding) {
+                       case PaddingMode.ANSIX923:
+                               // XX 00 00 00 00 00 00 07 (zero + padding length)
+                               res [res.Length - 1] = pad;
+                               Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
+                               // the last padded block will be transformed in-place
+                               InternalTransformBlock (res, full, BlockSizeByte, res, full);
+                               break;
+                       case PaddingMode.ISO10126:
+                               // XX 3F 52 2A 81 AB F7 07 (random + padding length)
+                               Random (res, res.Length - pad, pad - 1);
+                               res [res.Length - 1] = pad;
+                               Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
+                               // the last padded block will be transformed in-place
+                               InternalTransformBlock (res, full, BlockSizeByte, res, full);
+                               break;
+                       case PaddingMode.PKCS7:
+                               // XX 07 07 07 07 07 07 07 (padding length)
+                               for (int i = res.Length; --i >= (res.Length - pad);) 
+                                       res [i] = pad;
+                               Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
+                               // the last padded block will be transformed in-place
+                               InternalTransformBlock (res, full, BlockSizeByte, res, full);
+                               break;
+                       default:
+                               InternalTransformBlock (inputBuffer, inputOffset, BlockSizeByte, res, outputOffset);
+                               break;
+                       }
+                       return res;
+               }
+
+               private byte[] FinalDecrypt (byte[] inputBuffer, int inputOffset, int inputCount) 
+               {
+                       if ((inputCount % BlockSizeByte) > 0)
+                               throw new CryptographicException ("Invalid input block size.");
+
+                       int total = inputCount;
+                       if (lastBlock)
+                               total += BlockSizeByte;
+
+                       byte[] res = new byte [total];
+                       int outputOffset = 0;
+
+                       if (inputCount > 0)
+                               outputOffset = InternalTransformBlock (inputBuffer, inputOffset, inputCount, res, 0);
+
+                       if (lastBlock) {
+                               Transform (workBuff, 0, res, outputOffset, BlockSizeByte);
+                               outputOffset += BlockSizeByte;
+                               lastBlock = false;
+                       }
+
+                       // total may be 0 (e.g. PaddingMode.None)
+                       byte pad = ((total > 0) ? res [total - 1] : (byte) 0);
+                       switch (padding) {
+                       case PaddingMode.ANSIX923:
+                               if ((pad == 0) || (pad > BlockSizeByte))
+                                       ThrowBadPaddingException (padding, pad, -1);
+                               for (int i = pad - 1; i > 0; i--) {
+                                       if (res [total - 1 - i] != 0x00)
+                                               ThrowBadPaddingException (padding, -1, i);
+                               }
+                               total -= pad;
+                               break;
+                       case PaddingMode.ISO10126:
+                               if ((pad == 0) || (pad > BlockSizeByte))
+                                       ThrowBadPaddingException (padding, pad, -1);
+                               total -= pad;
+                               break;
+                       case PaddingMode.PKCS7:
+                               if ((pad == 0) || (pad > BlockSizeByte))
+                                       ThrowBadPaddingException (padding, pad, -1);
+                               for (int i = pad - 1; i > 0; i--) {
+                                       if (res [total - 1 - i] != pad)
+                                               ThrowBadPaddingException (padding, -1, i);
+                               }
+                               total -= pad;
+                               break;
+                       case PaddingMode.None:  // nothing to do - it's a multiple of block size
+                       case PaddingMode.Zeros: // nothing to do - user must unpad himself
+                               break;
+                       }
+
+                       // return output without padding
+                       if (total > 0) {
+                               byte[] data = new byte [total];
+                               Buffer.BlockCopy (res, 0, data, 0, total);
+                               // zeroize decrypted data (copy with padding)
+                               Array.Clear (res, 0, res.Length);
+                               return data;
+                       }
+                       else
+                               return new byte [0];
+               }
+
+               public virtual byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) 
+               {
+                       CheckInput (inputBuffer, inputOffset, inputCount);
+
+                       if (encrypt)
+                               return FinalEncrypt (inputBuffer, inputOffset, inputCount);
+                       else
+                               return FinalDecrypt (inputBuffer, inputOffset, inputCount);
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CommonCrypto/Makefile.include b/mcs/class/corlib/CommonCrypto/Makefile.include
new file mode 100644 (file)
index 0000000..25e1379
--- /dev/null
@@ -0,0 +1,5 @@
+CommonCrypto/%.g.cs: CommonCrypto/generator.exe
+       cd CommonCrypto && mono --debug generator.exe
+
+CommonCrypto/generator.exe: CommonCrypto/generator.cs CommonCrypto/CommonDigestGenerator.cs CommonCrypto/CommonCryptorGenerator.cs
+       mcs CommonCrypto/generator.cs CommonCrypto/CommonDigestGenerator.cs CommonCrypto/CommonCryptorGenerator.cs -o $@
diff --git a/mcs/class/corlib/CommonCrypto/RC4CommonCrypto.cs b/mcs/class/corlib/CommonCrypto/RC4CommonCrypto.cs
new file mode 100644 (file)
index 0000000..1e5c4e2
--- /dev/null
@@ -0,0 +1,212 @@
+// A CommonCrypto-based implementation of RC4(tm)
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright 2012-2014 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+
+using Crimson.CommonCrypto;
+
+#if MONOTOUCH || XAMMAC
+using Mono.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+#if !INSIDE_CORLIB
+       public
+#endif
+       sealed partial class ARC4Managed : RC4, ICryptoTransform {
+               
+               IntPtr handle;
+               
+               public ARC4Managed ()
+               {
+               }
+               
+               ~ARC4Managed ()
+               {
+                       Dispose (false);
+               }
+#else
+namespace Crimson.Security.Cryptography {
+
+       public abstract class RC4 : SymmetricAlgorithm {
+
+               private static KeySizes[] s_legalBlockSizes = {
+                       new KeySizes (64, 64, 0)
+               };
+
+               private static KeySizes[] s_legalKeySizes = {
+                       new KeySizes (40, 512, 8)  
+               };
+       
+               public RC4 () 
+               {
+                       KeySizeValue = 128;
+                       BlockSizeValue = 64;
+                       FeedbackSizeValue = BlockSizeValue;
+                       LegalBlockSizesValue = s_legalBlockSizes;
+                       LegalKeySizesValue = s_legalKeySizes;
+               }
+
+               // required for compatibility with .NET 2.0
+               public override byte[] IV {
+                       get { return new byte [0]; }
+                       set { ; }
+               }
+
+               new static public RC4 Create() 
+               {
+                       return Create ("RC4");
+               }
+
+               new static public RC4 Create (string algName) 
+               {
+                       object o = CryptoConfig.CreateFromName (algName);
+                       return (RC4) o ?? new RC4CommonCrypto ();
+               }
+       }
+
+       public sealed class RC4CommonCrypto : RC4, ICryptoTransform {
+               
+               IntPtr handle;
+               
+               public RC4CommonCrypto ()
+               {
+               }
+               
+               ~RC4CommonCrypto ()
+               {
+                       Dispose (false);
+               }
+#endif
+               
+               public bool CanReuseTransform {
+                       get { return false; }
+               }
+
+               public bool CanTransformMultipleBlocks {
+                       get { return true; }
+               }
+               
+               public int InputBlockSize {
+                       get { return 1; }
+               }
+
+               public int OutputBlockSize {
+                       get { return 1; }
+               }
+               
+               public override byte[] Key {
+                       get {
+                               return base.Key;
+                       }
+                       set {
+                               if (value == null)
+                                       throw new ArgumentNullException ("Key");
+
+                               int length = (value.Length << 3);
+                               KeySizeValue = length;
+                               KeyValue = (byte[]) value.Clone ();
+                       }
+               }
+               
+               protected override void Dispose (bool disposing)
+               {
+                       if (handle != IntPtr.Zero) {
+                               Cryptor.CCCryptorRelease (handle);
+                               handle = IntPtr.Zero;
+                       }
+                       base.Dispose (disposing);
+                       GC.SuppressFinalize (this);
+               }
+               
+               public override void GenerateIV ()
+               {
+                       // not used for a stream cipher
+                       IVValue = new byte [0];
+               }
+               
+               public override void GenerateKey ()
+               {
+                       KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
+               }
+               
+               public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       KeyValue = rgbKey;
+                       IVValue = rgbIV;
+                       return this;
+               }
+               
+               public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       KeyValue = rgbKey;
+                       IVValue = rgbIV;
+                       return this;
+               }
+
+               private void CheckInput (byte[] inputBuffer, int inputOffset, int inputCount)
+               {
+                       if (inputBuffer == null)
+                               throw new ArgumentNullException ("inputBuffer");
+                       if (inputOffset < 0)
+                               throw new ArgumentOutOfRangeException ("inputOffset", "< 0");
+                       if (inputCount < 0)
+                               throw new ArgumentOutOfRangeException ("inputCount", "< 0");
+                       // ordered to avoid possible integer overflow
+                       if (inputOffset > inputBuffer.Length - inputCount)
+                               throw new ArgumentException ("inputBuffer", "Overflow");
+               }
+
+               public unsafe int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) 
+               {
+                       CheckInput (inputBuffer, inputOffset, inputCount);
+                       if (inputCount == 0)
+                               return 0;
+
+                       // check output parameters
+                       if (outputBuffer == null)
+                               throw new ArgumentNullException ("outputBuffer");
+                       if (outputOffset < 0)
+                               throw new ArgumentOutOfRangeException ("outputOffset", "< 0");
+                       // ordered to avoid possible integer overflow
+                       if (outputOffset > outputBuffer.Length - inputCount)
+                               throw new ArgumentException ("outputBuffer", "Overflow");
+                       if (outputBuffer.Length == 0)
+                               throw new CryptographicException ("output buffer too small");
+                       
+                       if (handle == IntPtr.Zero)
+                               handle = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.RC4, CCOptions.None, KeyValue, IVValue);
+
+                       IntPtr len = IntPtr.Zero;
+                       IntPtr in_len = (IntPtr) (inputBuffer.Length - inputOffset);
+                       IntPtr out_len = (IntPtr) (outputBuffer.Length - outputOffset);
+                       fixed (byte* input = &inputBuffer [0])
+                       fixed (byte* output = &outputBuffer [0]) {
+                               CCCryptorStatus s = Cryptor.CCCryptorUpdate (handle, (IntPtr) (input + inputOffset), in_len, (IntPtr) (output + outputOffset), out_len, ref len);
+                               if ((len != out_len) || (s != CCCryptorStatus.Success))
+                                       throw new CryptographicUnexpectedOperationException (s.ToString ());
+                       }
+                       return (int) out_len;
+               }
+               
+               public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
+               {
+                       CheckInput (inputBuffer, inputOffset, inputCount);
+                       try {
+                               byte[] output = new byte [inputCount];
+                               TransformBlock (inputBuffer, inputOffset, inputCount, output, 0);
+                               return output;
+                       }
+                       finally {
+                               Cryptor.CCCryptorRelease (handle);
+                               handle = IntPtr.Zero;
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CommonCrypto/RijndaelManaged.cs b/mcs/class/corlib/CommonCrypto/RijndaelManaged.cs
new file mode 100644 (file)
index 0000000..3d528d3
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// RijndaelManaged.cs: Use CommonCrypto AES when possible, 
+//     fallback on RijndaelManagedTransform otherwise
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012 Xamarin Inc.
+//
+
+using System;
+using System.Security.Cryptography;
+
+using Mono.Security.Cryptography;
+using Crimson.CommonCrypto;
+
+namespace System.Security.Cryptography {
+       
+       public sealed class RijndaelManaged : Rijndael {
+               
+               public RijndaelManaged ()
+               {
+               }
+               
+               public override void GenerateIV ()
+               {
+                       IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
+               }
+               
+               public override void GenerateKey ()
+               {
+                       KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
+               }
+               
+               public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       // AES is Rijndael with a 128 bits block size, so we can use CommonCrypto in this case
+                       if (BlockSize == 128) {
+                               IntPtr decryptor = IntPtr.Zero;
+                               switch (Mode) {
+                               case CipherMode.CBC:
+                                       decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.AES128, CCOptions.None, rgbKey, rgbIV);
+                                       return new FastCryptorTransform (decryptor, this, false, rgbIV);
+                               case CipherMode.ECB:
+                                       decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.AES128, CCOptions.ECBMode, rgbKey, rgbIV);
+                                       return new FastCryptorTransform (decryptor, this, false, rgbIV);
+                               default:
+                                       // CFB cipher mode is not supported by the (old) API we used (for compatibility) so we fallback for them
+                                       // FIXME: benchmark if we're better with RijndaelManagedTransform or CryptorTransform for CFB mode
+                                       break;
+                               }
+                       }
+
+            return NewEncryptor(rgbKey,
+                                ModeValue,
+                                rgbIV,
+                                FeedbackSizeValue,
+                                RijndaelManagedTransformMode.Decrypt);
+               }
+               
+               public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       if (BlockSize == 128) {
+                               IntPtr encryptor = IntPtr.Zero;
+                               switch (Mode) {
+                               case CipherMode.CBC:
+                                       encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.AES128, CCOptions.None, rgbKey, rgbIV);
+                                       return new FastCryptorTransform (encryptor, this, true, rgbIV);
+                               case CipherMode.ECB:
+                                       encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.AES128, CCOptions.ECBMode, rgbKey, rgbIV);
+                                       return new FastCryptorTransform (encryptor, this, true, rgbIV);
+                               default:
+                                       // CFB cipher mode is not supported by the (old) API we used (for compatibility) so we fallback for them
+                                       // FIXME: benchmark if we're better with RijndaelManagedTransform or CryptorTransform for CFB mode
+                                       break;
+                               }
+                       }
+
+            return NewEncryptor(rgbKey,
+                                ModeValue,
+                                rgbIV,
+                                FeedbackSizeValue,
+                                RijndaelManagedTransformMode.Encrypt);
+        }
+
+
+        private ICryptoTransform NewEncryptor (byte[] rgbKey,
+                                               CipherMode mode,
+                                               byte[] rgbIV,
+                                               int feedbackSize,
+                                               RijndaelManagedTransformMode encryptMode) {
+            // Build the key if one does not already exist
+            if (rgbKey == null) {
+                rgbKey = Utils.GenerateRandom(KeySizeValue / 8);
+            }
+
+            // If not ECB mode, make sure we have an IV. In CoreCLR we do not support ECB, so we must have
+            // an IV in all cases.
+#if !FEATURE_CRYPTO
+            if (mode != CipherMode.ECB) {
+#endif // !FEATURE_CRYPTO
+                if (rgbIV == null) {
+                    rgbIV = Utils.GenerateRandom(BlockSizeValue / 8);
+                }
+#if !FEATURE_CRYPTO
+            }
+#endif // !FEATURE_CRYPTO
+
+            // Create the encryptor/decryptor object
+            return new RijndaelManagedTransform (rgbKey,
+                                                 mode,
+                                                 rgbIV,
+                                                 BlockSizeValue,
+                                                 feedbackSize,
+                                                 PaddingValue,
+                                                 encryptMode);
+        }                            
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CommonCrypto/SecRandom.cs b/mcs/class/corlib/CommonCrypto/SecRandom.cs
new file mode 100644 (file)
index 0000000..a112faf
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// SecRandom.cs: based on Mono's System.Security.Cryptography.RNGCryptoServiceProvider
+//
+// Authors:
+//     Mark Crichton (crichton@gimp.org)
+//     Sebastien Pouliot (sebastien@xamarun.com)
+//
+// (C) 2002
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2012-2014 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 Crimson.CommonCrypto;
+
+// http://developer.apple.com/library/ios/#DOCUMENTATION/Security/Reference/RandomizationReference/Reference/reference.html
+#if MONOTOUCH || XAMMAC
+namespace System.Security.Cryptography {
+       public class RNGCryptoServiceProvider : RandomNumberGenerator {
+               public RNGCryptoServiceProvider ()
+               {
+               }
+               
+               ~RNGCryptoServiceProvider () 
+               {
+               }
+#else
+using System;
+using System.Security.Cryptography;
+
+namespace Crimson.Security.Cryptography {
+                       
+       public class SecRandom : RandomNumberGenerator {
+#endif
+               
+               public override void GetBytes (byte[] data) 
+               {
+                       if (data == null)
+                               throw new ArgumentNullException ("data");
+                                       
+                       Cryptor.GetRandom (data);
+               }
+               
+               public override void GetNonZeroBytes (byte[] data) 
+               {
+                       if (data == null)
+                               throw new ArgumentNullException ("data");
+
+                       byte[] random = new byte [data.Length * 2];
+                       int i = 0;
+                       // one pass should be enough but hey this is random ;-)
+                       while (i < data.Length) {
+                               Cryptor.GetRandom (random);
+                               for (int j=0; j < random.Length; j++) {
+                                       if (i == data.Length)
+                                               break;
+                                       if (random [j] != 0)
+                                               data [i++] = random [j];
+                               }
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CommonCrypto/generator.cs b/mcs/class/corlib/CommonCrypto/generator.cs
new file mode 100644 (file)
index 0000000..a7d13c8
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// CommonCrypto Code Generator
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012 Xamarin Inc.
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Xamarin {
+       
+       class Program {
+               static void Main (string [] args)
+               {
+                       // mscorlib replacements
+                       CommonDigest.Generate ("System.Security.Cryptography", "MD5CryptoServiceProvider", "MD5", 1000);
+                       CommonDigest.Generate ("System.Security.Cryptography", "SHA1CryptoServiceProvider", "SHA1", 1000);
+                       CommonDigest.Generate ("System.Security.Cryptography", "SHA1Managed", "SHA1", 1000);
+                       CommonDigest.Generate ("System.Security.Cryptography", "SHA256Managed", "SHA256", 1000);
+                       CommonDigest.Generate ("System.Security.Cryptography", "SHA384Managed", "SHA384", 1000);
+                       CommonDigest.Generate ("System.Security.Cryptography", "SHA512Managed", "SHA512", 1000);
+                       
+                       // System.Core replacements - not yet in MT profile (4.0 - functional dupes anyway)
+                       //CommonDigest.Generate ("System.Security.Cryptography", "MD5Cng", "MD5", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA256Cng", "SHA256", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA384Cng", "SHA384", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA512Cng", "SHA512", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA256CryptoServiceProvider", "SHA256", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA384CryptoServiceProvider", "SHA384", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA512CryptoServiceProvider", "SHA512", 1000);
+                       
+                       // Mono.Security replacements
+                       CommonDigest.Generate ("Mono.Security.Cryptography", "MD2Managed", "MD2", 1000, "#if !INSIDE_CORLIB", "#endif");
+                       CommonDigest.Generate ("Mono.Security.Cryptography", "MD4Managed", "MD4", 1000, "#if !INSIDE_CORLIB", "#endif");
+                       CommonDigest.Generate ("Mono.Security.Cryptography", "SHA224Managed", "SHA224", 1000);
+
+                       // mscorlib replacements
+                       CommonCryptor.Generate ("System.Security.Cryptography", "DESCryptoServiceProvider", "DES", "DES");
+                       CommonCryptor.Generate ("System.Security.Cryptography", "TripleDESCryptoServiceProvider", "TripleDES", "TripleDES");
+                       CommonCryptor.Generate ("System.Security.Cryptography", "RC2CryptoServiceProvider", "RC2", "RC2", ctorInitializers: "LegalKeySizesValue = new[] { new KeySizes(40, 128, 8) };");
+                       // Rijndael supports block sizes that are not available in AES - as such it does not use the same generated code
+                       // but has it's own version, using AES (128 bits block size) and falling back to managed (192/256 bits block size)
+
+                       // System.Core replacements
+                       CommonCryptor.Generate ("System.Security.Cryptography", "AesManaged", "Aes", "AES128", "128");
+                       CommonCryptor.Generate ("System.Security.Cryptography", "AesCryptoServiceProvider", "Aes", "AES128");
+
+                       // Mono.Security replacements
+                       // RC4 is a stream (not a block) cipher so it can not reuse the generated code
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CoreFoundation/CFHelpers.cs b/mcs/class/corlib/CoreFoundation/CFHelpers.cs
new file mode 100644 (file)
index 0000000..7a765d3
--- /dev/null
@@ -0,0 +1,110 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace XamMac.CoreFoundation
+{
+       internal static class CFHelpers
+       {
+               internal const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
+               internal const string SecurityLibrary = "/System/Library/Frameworks/Security.framework/Security";
+
+               [DllImport (CoreFoundationLibrary)]
+               internal extern static void CFRelease (IntPtr obj);
+
+               [DllImport (CoreFoundationLibrary)]
+               internal extern static IntPtr CFRetain (IntPtr obj);
+
+               [StructLayout (LayoutKind.Sequential)]
+               struct CFRange {
+                       public IntPtr loc;
+                       public IntPtr len;
+
+                       public CFRange (int loc, int len)
+                               : this ((long) loc, (long) len)
+                       {
+                       }
+
+                       public CFRange (long l, long len)
+                       {
+                               this.loc = (IntPtr) l;
+                               this.len = (IntPtr) len;
+                       }
+               }
+
+               [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
+               extern static IntPtr CFStringCreateWithCharacters (IntPtr allocator, string str, IntPtr count);
+
+               [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
+               extern static IntPtr CFStringGetLength (IntPtr handle);
+
+               [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
+               extern static IntPtr CFStringGetCharactersPtr (IntPtr handle);
+
+               [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
+               extern static IntPtr CFStringGetCharacters (IntPtr handle, CFRange range, IntPtr buffer);
+
+               internal static string FetchString (IntPtr handle)
+               {
+                       if (handle == IntPtr.Zero)
+                               return null;
+
+                       string str;
+
+                       int l = (int)CFStringGetLength (handle);
+                       IntPtr u = CFStringGetCharactersPtr (handle);
+                       IntPtr buffer = IntPtr.Zero;
+                       if (u == IntPtr.Zero){
+                               CFRange r = new CFRange (0, l);
+                               buffer = Marshal.AllocCoTaskMem (l * 2);
+                               CFStringGetCharacters (handle, r, buffer);
+                               u = buffer;
+                       }
+                       unsafe {
+                               str = new string ((char *) u, 0, l);
+                       }
+
+                       if (buffer != IntPtr.Zero)
+                               Marshal.FreeCoTaskMem (buffer);
+
+                       return str;
+               }
+
+               [DllImport (CoreFoundationLibrary)]
+               extern static IntPtr CFDataGetLength (IntPtr handle);
+
+               [DllImport (CoreFoundationLibrary)]
+               extern static IntPtr CFDataGetBytePtr (IntPtr handle);
+
+               internal static byte[] FetchDataBuffer (IntPtr handle)
+               {
+                       var length = (int)CFDataGetLength (handle);
+                       var buffer = new byte [length];
+                       var ptr = CFDataGetBytePtr (handle);
+                       Marshal.Copy (ptr, buffer, 0, buffer.Length);
+                       return buffer;
+               }
+
+               [DllImport (CoreFoundationLibrary)]
+               extern static IntPtr CFDataCreateWithBytesNoCopy (IntPtr allocator, IntPtr bytes, IntPtr length, IntPtr bytesDeallocator);
+
+               [DllImport (CoreFoundationLibrary)]
+               extern static IntPtr CFDataCreate (IntPtr allocator, IntPtr bytes, IntPtr length);
+
+               [DllImport (SecurityLibrary)]
+               extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr cfData);
+
+               unsafe internal static IntPtr CreateCertificateFromData (byte[] data)
+               {
+                       fixed (void *ptr = data) {
+                               var cfdata = CFDataCreate (IntPtr.Zero, (IntPtr)ptr, new IntPtr (data.Length));
+                               if (cfdata == IntPtr.Zero)
+                                       return IntPtr.Zero;
+
+                               var certificate = SecCertificateCreateWithData (IntPtr.Zero, cfdata);
+                               if (cfdata != IntPtr.Zero)
+                                       CFRelease (cfdata);
+                               return certificate;
+                       }
+               }
+       }
+}
index 2540e23603143f4999cba59f4c9b11cdc42d6a09..aff30966f5a5a3555c898dfa1bf8223a3202559f 100644 (file)
@@ -1,6 +1,7 @@
 thisdir = class/corlib
 SUBDIRS =
 include ../../build/rules.make
+include CommonCrypto/Makefile.include
 export __SECURITY_BOOTSTRAP_DB=$(topdir)/class/corlib
 
 LIBRARY = corlib.dll
index 2593f96c68d372382cf6f37764c29f9966fe58bf..702cd540d976d92e34dbce66fc2e116a679f2603 100644 (file)
@@ -60,9 +60,6 @@ namespace System.Diagnostics {
                #pragma warning restore 649
                #endregion
 
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               extern static int GetILOffsetFromFile (string path, int methodToken, uint methodIndex, int nativeOffset);
-
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern static bool get_frame_info (int skip, bool needFileInfo, out MethodBase method,
                                                   out int iloffset, out int native_offset,
index 4c322cd107fc95a732c4763db1ffb5bd675d57c9..afa470dd5c3dbd1c4e500fec031ee5805e549959 100644 (file)
@@ -201,7 +201,7 @@ namespace System.Diagnostics {
                                        else
                                                sb.AppendFormat ("<0x{0:x5} + 0x{1:x5}> {2}", frame.GetMethodAddress (), frame.GetNativeOffset (), unknown);
                                } else {
-                                       GetFullNameForStackTrace (sb, frame.GetMethod ());
+                                       StackTraceHelper.GetFullNameForStackTrace (sb, frame.GetMethod ());
 
                                        if (frame.GetILOffset () == -1) {
                                                sb.AppendFormat (" <0x{0:x5} + 0x{1:x5}>", frame.GetMethodAddress (), frame.GetNativeOffset ());
@@ -219,64 +219,6 @@ namespace System.Diagnostics {
                        return i != 0;
                }
 
-               // This method is also used with reflection by mono-symbolicate tool.
-               // mono-symbolicate tool uses this method to check which method matches
-               // the stack frame method signature.
-               static void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
-               {
-                       var declaringType = mi.DeclaringType;
-                       if (declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition)
-                               declaringType = declaringType.GetGenericTypeDefinition ();
-
-                       // Get generic definition
-                       var bindingflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
-                       foreach (var m in declaringType.GetMethods (bindingflags)) {
-                               if (m.MetadataToken == mi.MetadataToken) {
-                                       mi = m;
-                                       break;
-                               }
-                       }
-
-                       sb.Append (declaringType.ToString ());
-
-                       sb.Append (".");
-                       sb.Append (mi.Name);
-
-                       if (mi.IsGenericMethod) {
-                               Type[] gen_params = mi.GetGenericArguments ();
-                               sb.Append ("[");
-                               for (int j = 0; j < gen_params.Length; j++) {
-                                       if (j > 0)
-                                               sb.Append (",");
-                                       sb.Append (gen_params [j].Name);
-                               }
-                               sb.Append ("]");
-                       }
-
-                       ParameterInfo[] p = mi.GetParametersInternal ();
-
-                       sb.Append (" (");
-                       for (int i = 0; i < p.Length; ++i) {
-                               if (i > 0)
-                                       sb.Append (", ");
-
-                               Type pt = p[i].ParameterType;
-                               if (pt.IsGenericType && ! pt.IsGenericTypeDefinition)
-                                       pt = pt.GetGenericTypeDefinition ();
-
-                               if (pt.IsClass && !String.IsNullOrEmpty (pt.Namespace)) {
-                                       sb.Append (pt.Namespace);
-                                       sb.Append (".");
-                               }
-                               sb.Append (pt.Name);
-                               if (p [i].Name != null) {
-                                       sb.Append (" ");
-                                       sb.Append (p [i].Name);
-                               }
-                       }
-                       sb.Append (")");
-               }
-
                public override string ToString ()
                {
                        StringBuilder sb = new StringBuilder ();
diff --git a/mcs/class/corlib/System.Diagnostics/StackTraceHelper.cs b/mcs/class/corlib/System.Diagnostics/StackTraceHelper.cs
new file mode 100644 (file)
index 0000000..3bf9995
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// System.Diagnostics.StackTraceHelper.cs
+//
+// Author:
+//      Marcos Henrich (marcos.henrich@xamarin.com)
+//
+// Copyright (C) Xamarin, Inc (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Text;
+using System.Reflection;
+
+namespace System.Diagnostics {
+
+       // This class exists so tools such as mono-symbolicate can use it directly.
+       class StackTraceHelper {
+               
+               public static void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
+               {
+                       var declaringType = mi.DeclaringType;
+                       if (declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition)
+                               declaringType = declaringType.GetGenericTypeDefinition ();
+
+                       // Get generic definition
+                       var bindingflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+                       foreach (var m in declaringType.GetMethods (bindingflags)) {
+                               if (m.MetadataToken == mi.MetadataToken) {
+                                       mi = m;
+                                       break;
+                               }
+                       }
+
+                       sb.Append (declaringType.ToString ());
+
+                       sb.Append (".");
+                       sb.Append (mi.Name);
+
+                       if (mi.IsGenericMethod) {
+                               Type[] gen_params = mi.GetGenericArguments ();
+                               sb.Append ("[");
+                               for (int j = 0; j < gen_params.Length; j++) {
+                                       if (j > 0)
+                                               sb.Append (",");
+                                       sb.Append (gen_params [j].Name);
+                               }
+                               sb.Append ("]");
+                       }
+
+                       ParameterInfo[] p = mi.GetParameters ();
+
+                       sb.Append (" (");
+                       for (int i = 0; i < p.Length; ++i) {
+                               if (i > 0)
+                                       sb.Append (", ");
+
+                               Type pt = p[i].ParameterType;
+                               if (pt.IsGenericType && ! pt.IsGenericTypeDefinition)
+                                       pt = pt.GetGenericTypeDefinition ();
+
+                               if (pt.IsClass && !String.IsNullOrEmpty (pt.Namespace)) {
+                                       sb.Append (pt.Namespace);
+                                       sb.Append (".");
+                               }
+                               sb.Append (pt.Name);
+                               if (p [i].Name != null) {
+                                       sb.Append (" ");
+                                       sb.Append (p [i].Name);
+                               }
+                       }
+                       sb.Append (")");
+               }
+       }
+}
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
index 2256ebde0eab496d2dbbb03aaa04d723d1a1bdf7..ec83a3e0756b6f79737d2acb38b87f4ea11ba02b 100644 (file)
@@ -30,6 +30,7 @@
 //
 
 using System;
+using System.Threading;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
@@ -108,8 +109,17 @@ namespace System.Runtime.InteropServices
 
                public void Free()
                {
-                       FreeHandle(handle);
-                       handle = 0;
+                       // Copy the handle instance member to a local variable. This is required to prevent
+                       // race conditions releasing the handle.
+                       int local_handle = handle;
+
+                       // Free the handle if it hasn't already been freed.
+                       if (local_handle != 0 && Interlocked.CompareExchange (ref handle, 0, local_handle) == local_handle) {
+                               FreeHandle (local_handle);
+                       }
+                       else {
+                               throw new InvalidOperationException ("Handle is not initialized.");
+                       }
                }
                
                public static explicit operator IntPtr (GCHandle value)
@@ -120,7 +130,7 @@ namespace System.Runtime.InteropServices
                public static explicit operator GCHandle(IntPtr value)
                {
                        if (value == IntPtr.Zero)
-                               throw new ArgumentException ("GCHandle value cannot be zero");
+                               throw new InvalidOperationException ("GCHandle value cannot be zero");
                        if (!CheckCurrentDomain ((int)value))
                                throw new ArgumentException ("GCHandle value belongs to a different domain");
                        return new GCHandle (value);
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;
 
diff --git a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
new file mode 100644 (file)
index 0000000..bca5160
--- /dev/null
@@ -0,0 +1,193 @@
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+using XamMac.CoreFoundation;
+using MX = Mono.Security.X509;
+
+namespace System.Security.Cryptography.X509Certificates
+{
+       class X509CertificateImplApple : X509CertificateImpl
+       {
+               IntPtr handle;
+               X509CertificateImpl fallback;
+
+               public X509CertificateImplApple (IntPtr handle, bool owns)
+               {
+                       this.handle = handle;
+                       if (!owns)
+                               CFHelpers.CFRetain (handle);
+               }
+
+               public override bool IsValid {
+                       get { return handle != IntPtr.Zero; }
+               }
+
+               public override IntPtr Handle {
+                       get { return handle; }
+               }
+
+               public override X509CertificateImpl Clone ()
+               {
+                       ThrowIfContextInvalid ();
+                       return new X509CertificateImplApple (handle, false);
+               }
+
+               [DllImport (CFHelpers.SecurityLibrary)]
+               extern static IntPtr SecCertificateCopySubjectSummary (IntPtr cert);
+
+               [DllImport (CFHelpers.SecurityLibrary)]
+               extern static IntPtr SecCertificateCopyData (IntPtr cert);
+
+               public override byte[] GetRawCertData ()
+               {
+                       ThrowIfContextInvalid ();
+                       var data = SecCertificateCopyData (handle);
+                       if (data == IntPtr.Zero)
+                               throw new ArgumentException ("Not a valid certificate");
+
+                       try {
+                               return CFHelpers.FetchDataBuffer (data);
+                       } finally {
+                               CFHelpers.CFRelease (data);
+                       }
+               }
+
+               public override string GetSubjectSummary ()
+               {
+                       ThrowIfContextInvalid ();
+                       IntPtr cfstr = SecCertificateCopySubjectSummary (handle);
+                       string ret = CFHelpers.FetchString (cfstr);
+                       CFHelpers.CFRelease (cfstr);
+                       return ret;
+               }
+
+               protected override byte[] GetCertHash (bool lazy)
+               {
+                       // FIXME: might just return 'null' when 'lazy' is true.
+                       ThrowIfContextInvalid ();
+                       SHA1 sha = SHA1.Create ();
+                       return sha.ComputeHash (GetRawCertData ());
+               }
+
+               public override bool Equals (X509CertificateImpl other, out bool result)
+               {
+                       var otherAppleImpl = other as X509CertificateImplApple;
+                       if (otherAppleImpl != null && otherAppleImpl.handle == handle) {
+                               result = true;
+                               return true;
+                       }
+
+                       result = false;
+                       return false;
+               }
+
+               void MustFallback ()
+               {
+                       ThrowIfContextInvalid ();
+                       if (fallback != null)
+                               return;
+                       var mxCert = new MX.X509Certificate (GetRawCertData ());
+                       fallback = new X509CertificateImplMono (mxCert);
+               }
+
+               public X509CertificateImpl FallbackImpl {
+                       get {
+                               MustFallback ();
+                               return fallback;
+                       }
+               }
+
+               public override string GetSubjectName (bool legacyV1Mode)
+               {
+                       return FallbackImpl.GetSubjectName (legacyV1Mode);
+               }
+
+               public override string GetIssuerName (bool legacyV1Mode)
+               {
+                       return FallbackImpl.GetIssuerName (legacyV1Mode);
+               }
+
+               public override DateTime GetEffectiveDateString ()
+               {
+                       return FallbackImpl.GetEffectiveDateString ();
+               }
+
+               public override DateTime GetExpirationDateString ()
+               {
+                       return FallbackImpl.GetExpirationDateString ();
+               }
+
+               public override string GetKeyAlgorithm ()
+               {
+                       return FallbackImpl.GetKeyAlgorithm ();
+               }
+
+               public override byte[] GetKeyAlgorithmParameters ()
+               {
+                       return FallbackImpl.GetKeyAlgorithmParameters ();
+               }
+
+               public override byte[] GetPublicKey ()
+               {
+                       return FallbackImpl.GetPublicKey ();
+               }
+
+               public override byte[] GetSerialNumber ()
+               {
+                       return FallbackImpl.GetSerialNumber ();
+               }
+
+               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);
+                       }
+               }
+
+               public override string ToString (bool full)
+               {
+                       ThrowIfContextInvalid ();
+
+                       if (!full || fallback == null) {
+                               var summary = GetSubjectSummary ();
+                               return string.Format ("[X509Certificate: {0}]", summary);
+                       }
+
+                       string nl = Environment.NewLine;
+                       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 ("[Thumbprint]{0}  {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
+
+                       sb.Append (nl);
+                       return sb.ToString ();
+               }
+
+               protected override void Dispose (bool disposing)
+               {
+                       if (handle != IntPtr.Zero){
+                               CFHelpers.CFRelease (handle);
+                               handle = IntPtr.Zero;
+                       }
+                       if (fallback != null) {
+                               fallback.Dispose ();
+                               fallback = null;
+                       }
+               }
+       }
+}
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 ();
diff --git a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
new file mode 100644 (file)
index 0000000..7068882
--- /dev/null
@@ -0,0 +1,50 @@
+using System;
+using System.Runtime.InteropServices;
+using MX = Mono.Security.X509;
+using XamMac.CoreFoundation;
+
+namespace System.Security.Cryptography.X509Certificates
+{
+       static partial class X509Helper
+       {
+               public static X509CertificateImpl InitFromHandle (IntPtr handle)
+               {
+                       return new X509CertificateImplApple (handle, false);
+               }
+
+               public static X509CertificateImpl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
+               {
+                       MX.X509Certificate x509;
+                       IntPtr handle;
+                       if (password == null) {
+                               handle = CFHelpers.CreateCertificateFromData (rawData);
+                               if (handle != IntPtr.Zero)
+                                       return new X509CertificateImplApple (handle, true);
+
+                               try {
+                                       x509 = new MX.X509Certificate (rawData);
+                               } catch (Exception e) {
+                                       try {
+                                               x509 = X509Helper.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 {
+                                       x509 = X509Helper.ImportPkcs12 (rawData, password);
+                               }
+                               catch {
+                                       // it's possible to supply a (unrequired/unusued) password
+                                       // fix bug #79028
+                                       x509 = new MX.X509Certificate (rawData);
+                               }
+                       }
+
+                       return new X509CertificateImplMono (x509);
+               }
+       }
+}
diff --git a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Helper.MonoTouch.opt.cs b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Helper.MonoTouch.opt.cs
deleted file mode 100644 (file)
index 19f1c4e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#if MONOTOUCH || XAMMAC
-
-// this file is a shim to enable compiling monotouch profiles without mono-extensions
-namespace System.Security.Cryptography.X509Certificates
-{
-       static partial class X509Helper
-       {
-               public static X509CertificateImpl InitFromHandle (IntPtr handle)
-               {
-                       throw new NotSupportedException ();
-               }
-
-               public static X509CertificateImpl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
-               {
-                       throw new NotSupportedException ();
-               }
-       }
-}
-
-#endif
diff --git a/mcs/class/corlib/System.Text/EncodingHelper.MonoTouch.cs b/mcs/class/corlib/System.Text/EncodingHelper.MonoTouch.cs
new file mode 100644 (file)
index 0000000..554b206
--- /dev/null
@@ -0,0 +1,30 @@
+using System;
+
+namespace System.Text {
+
+       internal static partial class EncodingHelper {
+
+               static volatile Encoding utf8Encoding;
+
+               internal static Encoding UTF8 {
+                       get {
+                               if (utf8Encoding == null) {
+                                       lock (lockobj){
+                                               if (utf8Encoding == null){
+                                                       utf8Encoding = new UTF8Encoding (true, false);
+                                                       utf8Encoding.setReadOnly ();
+                                               }
+                                       }
+                               }
+
+                               return utf8Encoding;
+                       }
+               }
+
+               // The mobile profile has been default'ing to UTF8 since it's creation
+               internal static Encoding GetDefaultEncoding ()
+               {
+                       return UTF8;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/System.Text/EncodingHelper.MonoTouch.opt.cs b/mcs/class/corlib/System.Text/EncodingHelper.MonoTouch.opt.cs
deleted file mode 100644 (file)
index 9aba0f6..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#if MONOTOUCH
-
-// this file is a shim to enable compiling monotouch profiles without mono-extensions
-namespace System.Text
-{
-       internal static partial class EncodingHelper
-       {
-               internal static Encoding GetDefaultEncoding ()
-               {
-                       throw new NotSupportedException ();
-               }
-       }
-}
-
-#endif
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; }
diff --git a/mcs/class/corlib/System/Environment.MonoTouch.opt.cs b/mcs/class/corlib/System/Environment.MonoTouch.opt.cs
deleted file mode 100644 (file)
index d45de30..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#if MONOTOUCH
-
-// this file is a shim to enable compiling monotouch profiles without mono-extensions
-namespace System
-{
-       public static partial class Environment
-       {
-               public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option)
-               {
-                       throw new NotSupportedException ();
-               }
-
-               internal static string UnixGetFolderPath (SpecialFolder folder, SpecialFolderOption option)
-               {
-                       throw new NotSupportedException ();
-               }
-       }
-}
-
-#endif
diff --git a/mcs/class/corlib/System/Environment.iOS.cs b/mcs/class/corlib/System/Environment.iOS.cs
new file mode 100644 (file)
index 0000000..04ad76d
--- /dev/null
@@ -0,0 +1,148 @@
+// Copyright 2014 Xamarin Inc.
+
+// note: or older hack to give the Documents (or Library) directories 
+
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace System {
+
+       public static partial class Environment {
+
+               static string ns_document;
+               static string ns_library;
+
+               [DllImport ("__Internal")]
+               extern static string xamarin_GetFolderPath (int folder);
+
+               static string NSDocumentDirectory {
+                       get {
+                               if (ns_document == null) {
+#if MONOTOUCH_TV
+                                       // The "normal" NSDocumentDirectory is a read-only directory on tvOS
+                                       // and that breaks a lot of assumptions in the runtime and the BCL
+                                       // to avoid this we relocate the Documents directory under Caches
+                                       ns_document = Path.Combine (NSLibraryDirectory, "Caches", "Documents");
+                                       if (!Directory.Exists (ns_document))
+                                               Directory.CreateDirectory (ns_document);
+#else
+                                       ns_document = xamarin_GetFolderPath (/* NSDocumentDirectory */ 9);
+#endif
+                               }
+                               return ns_document;
+                       }
+               }
+
+               // Various user-visible documentation, support, and configuration files
+               static string NSLibraryDirectory {
+                       get {
+                               if (ns_library == null)
+                                       ns_library = xamarin_GetFolderPath (/* NSLibraryDirectory */ 5);
+                               return ns_library;
+                       }
+               }
+
+               public static string GetFolderPath (SpecialFolder folder, SpecialFolderOption option)
+               {
+                       return UnixGetFolderPath (folder, option);
+               }
+
+               // needed by our BCL, e.g. IsolatedStorageFile.cs
+               internal static string UnixGetFolderPath (SpecialFolder folder, SpecialFolderOption option)
+               {
+                       var dir = iOSGetFolderPath (folder);
+                       if ((option == SpecialFolderOption.Create) && !Directory.Exists (dir))
+                               Directory.CreateDirectory (dir);
+                       return dir;
+               }
+
+               internal static string iOSGetFolderPath (SpecialFolder folder)
+               {
+                       switch (folder) {
+                       case SpecialFolder.MyComputer:
+                       case SpecialFolder.Programs:
+                       case SpecialFolder.SendTo:
+                       case SpecialFolder.StartMenu:
+                       case SpecialFolder.Startup:
+                       case SpecialFolder.Cookies:
+                       case SpecialFolder.History:
+                       case SpecialFolder.Recent:
+                       case SpecialFolder.CommonProgramFiles:
+                       case SpecialFolder.System:
+                       case SpecialFolder.NetworkShortcuts:
+                       case SpecialFolder.CommonStartMenu:
+                       case SpecialFolder.CommonPrograms:
+                       case SpecialFolder.CommonStartup:
+                       case SpecialFolder.CommonDesktopDirectory:
+                       case SpecialFolder.PrinterShortcuts:
+                       case SpecialFolder.Windows:
+                       case SpecialFolder.SystemX86:
+                       case SpecialFolder.ProgramFilesX86:
+                       case SpecialFolder.CommonProgramFilesX86:
+                       case SpecialFolder.CommonDocuments:
+                       case SpecialFolder.CommonAdminTools:
+                       case SpecialFolder.AdminTools:
+                       case SpecialFolder.CommonMusic:
+                       case SpecialFolder.CommonPictures:
+                       case SpecialFolder.CommonVideos:
+                       case SpecialFolder.LocalizedResources:
+                       case SpecialFolder.CommonOemLinks:
+                       case SpecialFolder.CDBurning:
+                               return String.Empty;
+                       
+                       // personal == ~
+                       case SpecialFolder.Personal:
+                       case SpecialFolder.LocalApplicationData:
+                               return NSDocumentDirectory;
+
+                       case SpecialFolder.ApplicationData:
+                               // note: at first glance that looked like a good place to return NSLibraryDirectory 
+                               // but it would break isolated storage for existing applications
+                               return Path.Combine (NSDocumentDirectory, ".config");
+
+                       case SpecialFolder.Resources:
+                               return NSLibraryDirectory; // older (8.2 and previous) would return String.Empty
+
+                       case SpecialFolder.Desktop:
+                       case SpecialFolder.DesktopDirectory:
+                               return Path.Combine (NSDocumentDirectory, "Desktop");
+
+                       case SpecialFolder.MyMusic:
+                               return Path.Combine (NSDocumentDirectory, "Music");
+
+                       case SpecialFolder.MyPictures:
+                               return Path.Combine (NSDocumentDirectory, "Pictures");
+
+                       case SpecialFolder.Templates:
+                               return Path.Combine (NSDocumentDirectory, "Templates");
+
+                       case SpecialFolder.MyVideos:
+                               return Path.Combine (NSDocumentDirectory, "Videos");
+
+                       case SpecialFolder.CommonTemplates:
+                               return "/usr/share/templates";
+
+                       case SpecialFolder.Fonts:
+                               return Path.Combine (NSDocumentDirectory, ".fonts");
+
+                       case SpecialFolder.Favorites:
+                               return Path.Combine (NSLibraryDirectory, "Favorites");
+
+                       case SpecialFolder.ProgramFiles:
+                               return "/Applications";
+
+                       case SpecialFolder.InternetCache:
+                               return Path.Combine (NSLibraryDirectory, "Caches");
+
+                       case SpecialFolder.UserProfile:
+                               return internalGetHome ();
+
+                       case SpecialFolder.CommonApplicationData:
+                               return "/usr/share";
+
+                       default:
+                               throw new ArgumentException ("Invalid SpecialFolder");
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/System/Guid.MonoTouch.cs b/mcs/class/corlib/System/Guid.MonoTouch.cs
new file mode 100644 (file)
index 0000000..714bdb6
--- /dev/null
@@ -0,0 +1,25 @@
+#if MONOTOUCH && FULL_AOT_RUNTIME
+
+using Crimson.CommonCrypto;
+
+namespace System
+{
+       partial struct Guid
+       {
+               public static Guid NewGuid ()
+               {
+                       byte[] b = new byte [16];
+                       Cryptor.GetRandom (b);
+
+                       Guid res = new Guid (b);
+                       // Mask in Variant 1-0 in Bit[7..6]
+                       res._d = (byte) ((res._d & 0x3fu) | 0x80u);
+                       // Mask in Version 4 (random based Guid) in Bits[15..13]
+                       res._c = (short) ((res._c & 0x0fffu) | 0x4000u);
+
+                       return res;
+               }
+       }
+}
+
+#endif
\ No newline at end of file
diff --git a/mcs/class/corlib/System/Guid.MonoTouch.opt.cs b/mcs/class/corlib/System/Guid.MonoTouch.opt.cs
deleted file mode 100644 (file)
index beb6a3a..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#if MONOTOUCH && FULL_AOT_RUNTIME
-
-// this file is a shim to enable compiling monotouch profiles without mono-extensions
-namespace System
-{
-       partial struct Guid
-       {
-               public static Guid NewGuid ()
-               {
-                       throw new NotSupportedException ();
-               }
-       }
-}
-
-#endif
diff --git a/mcs/class/corlib/System/NotSupportedException.iOS.cs b/mcs/class/corlib/System/NotSupportedException.iOS.cs
new file mode 100644 (file)
index 0000000..c18b3d6
--- /dev/null
@@ -0,0 +1,13 @@
+namespace System {
+
+       public partial class NotSupportedException {
+
+               // Avoid having the linker generate this method for every linked build
+               // It also fix #30075 where --linkskip=mscorlib means that method could not be added
+               // but still referenced from other assemblies
+               internal static Exception LinkedAway ()
+               {
+                       return new NotSupportedException ("Linked Away");
+               }
+       }
+}
\ No newline at end of file
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 35ed33617c26884fa55a28c2d058cfb533a30179..9a2b075df8837573163a5a1b72119eb1210281a2 100644 (file)
@@ -161,6 +161,7 @@ System.Deployment.Internal/InternalApplicationIdentityHelper.cs
 System.Diagnostics/Debugger.cs
 System.Diagnostics/StackFrame.cs
 System.Diagnostics/StackTrace.cs
+System.Diagnostics/StackTraceHelper.cs
 System.Diagnostics.Tracing/EventAttribute.cs
 System.Diagnostics.Tracing/EventCommand.cs
 System.Diagnostics.Tracing/EventSource.cs
diff --git a/mcs/class/corlib/monotouch_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..7287193
--- /dev/null
@@ -0,0 +1,15 @@
+System.Security.Cryptography/MD5CryptoServiceProvider.cs
+System.Security.Cryptography/SHA1CryptoServiceProvider.cs
+System.Security.Cryptography/SHA1CryptoServiceProvider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/descryptoserviceprovider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/rc2cryptoserviceprovider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/rijndaelmanaged.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha1managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha256managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha384managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha512managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/tripledescryptoserviceprovider.cs
+System.Security.Cryptography/RNGCryptoServiceProvider.cs
+../Mono.Security/Mono.Security.Cryptography/ARC4Managed.cs
+../Mono.Security/Mono.Security.Cryptography/MD2Managed.cs
+../Mono.Security/Mono.Security.Cryptography/MD4Managed.cs
index da77893bcc50c66f173571e43a57595448b44e27..e802a034dd64f2aa7f7a9a97dd76b0aaf3ed4294 100644 (file)
@@ -1 +1,27 @@
 #include corlib.dll.sources
+CommonCrypto/CommonCrypto.cs
+CommonCrypto/CryptorTransform.cs
+CommonCrypto/FastCryptorTransform.cs
+CommonCrypto/CorlibExtras.cs
+CommonCrypto/MD5CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1Managed.g.cs
+CommonCrypto/SHA256Managed.g.cs
+CommonCrypto/SHA384Managed.g.cs
+CommonCrypto/SHA512Managed.g.cs
+CommonCrypto/TripleDESCryptoServiceProvider.g.cs
+CommonCrypto/DESCryptoServiceProvider.g.cs
+CommonCrypto/RC2CryptoServiceProvider.g.cs
+CommonCrypto/RijndaelManaged.cs
+CommonCrypto/SecRandom.cs
+CommonCrypto/RC4CommonCrypto.cs
+CommonCrypto/MD2Managed.g.cs
+CommonCrypto/MD4Managed.g.cs
+System/Environment.iOS.cs
+System/Guid.MonoTouch.cs
+System/NotSupportedException.iOS.cs
+CoreFoundation/CFHelpers.cs
+System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
+System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
+System.Text/EncodingHelper.MonoTouch.cs
diff --git a/mcs/class/corlib/monotouch_opt_corlib.dll.sources b/mcs/class/corlib/monotouch_opt_corlib.dll.sources
deleted file mode 100644 (file)
index be231ef..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-System/Environment.MonoTouch.opt.cs
-System/Guid.MonoTouch.opt.cs
-System.Text/EncodingHelper.MonoTouch.opt.cs
-System.Security.Cryptography.X509Certificates/X509Helper.MonoTouch.opt.cs
diff --git a/mcs/class/corlib/monotouch_runtime_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_runtime_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..53efeac
--- /dev/null
@@ -0,0 +1 @@
+#include monotouch_corlib.dll.exclude.sources
index da77893bcc50c66f173571e43a57595448b44e27..e802a034dd64f2aa7f7a9a97dd76b0aaf3ed4294 100644 (file)
@@ -1 +1,27 @@
 #include corlib.dll.sources
+CommonCrypto/CommonCrypto.cs
+CommonCrypto/CryptorTransform.cs
+CommonCrypto/FastCryptorTransform.cs
+CommonCrypto/CorlibExtras.cs
+CommonCrypto/MD5CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1Managed.g.cs
+CommonCrypto/SHA256Managed.g.cs
+CommonCrypto/SHA384Managed.g.cs
+CommonCrypto/SHA512Managed.g.cs
+CommonCrypto/TripleDESCryptoServiceProvider.g.cs
+CommonCrypto/DESCryptoServiceProvider.g.cs
+CommonCrypto/RC2CryptoServiceProvider.g.cs
+CommonCrypto/RijndaelManaged.cs
+CommonCrypto/SecRandom.cs
+CommonCrypto/RC4CommonCrypto.cs
+CommonCrypto/MD2Managed.g.cs
+CommonCrypto/MD4Managed.g.cs
+System/Environment.iOS.cs
+System/Guid.MonoTouch.cs
+System/NotSupportedException.iOS.cs
+CoreFoundation/CFHelpers.cs
+System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
+System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
+System.Text/EncodingHelper.MonoTouch.cs
diff --git a/mcs/class/corlib/monotouch_runtime_opt_corlib.dll.sources b/mcs/class/corlib/monotouch_runtime_opt_corlib.dll.sources
deleted file mode 100644 (file)
index d32b506..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_opt_corlib.dll.sources
diff --git a/mcs/class/corlib/monotouch_tv_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_tv_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..53efeac
--- /dev/null
@@ -0,0 +1 @@
+#include monotouch_corlib.dll.exclude.sources
index da77893bcc50c66f173571e43a57595448b44e27..e802a034dd64f2aa7f7a9a97dd76b0aaf3ed4294 100644 (file)
@@ -1 +1,27 @@
 #include corlib.dll.sources
+CommonCrypto/CommonCrypto.cs
+CommonCrypto/CryptorTransform.cs
+CommonCrypto/FastCryptorTransform.cs
+CommonCrypto/CorlibExtras.cs
+CommonCrypto/MD5CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1Managed.g.cs
+CommonCrypto/SHA256Managed.g.cs
+CommonCrypto/SHA384Managed.g.cs
+CommonCrypto/SHA512Managed.g.cs
+CommonCrypto/TripleDESCryptoServiceProvider.g.cs
+CommonCrypto/DESCryptoServiceProvider.g.cs
+CommonCrypto/RC2CryptoServiceProvider.g.cs
+CommonCrypto/RijndaelManaged.cs
+CommonCrypto/SecRandom.cs
+CommonCrypto/RC4CommonCrypto.cs
+CommonCrypto/MD2Managed.g.cs
+CommonCrypto/MD4Managed.g.cs
+System/Environment.iOS.cs
+System/Guid.MonoTouch.cs
+System/NotSupportedException.iOS.cs
+CoreFoundation/CFHelpers.cs
+System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
+System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
+System.Text/EncodingHelper.MonoTouch.cs
diff --git a/mcs/class/corlib/monotouch_tv_opt_corlib.dll.sources b/mcs/class/corlib/monotouch_tv_opt_corlib.dll.sources
deleted file mode 100644 (file)
index d32b506..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_opt_corlib.dll.sources
diff --git a/mcs/class/corlib/monotouch_tv_runtime_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_tv_runtime_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..53efeac
--- /dev/null
@@ -0,0 +1 @@
+#include monotouch_corlib.dll.exclude.sources
diff --git a/mcs/class/corlib/monotouch_tv_runtime_opt_corlib.dll.sources b/mcs/class/corlib/monotouch_tv_runtime_opt_corlib.dll.sources
deleted file mode 100644 (file)
index d32b506..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_opt_corlib.dll.sources
diff --git a/mcs/class/corlib/monotouch_watch_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_watch_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..53efeac
--- /dev/null
@@ -0,0 +1 @@
+#include monotouch_corlib.dll.exclude.sources
index da77893bcc50c66f173571e43a57595448b44e27..e802a034dd64f2aa7f7a9a97dd76b0aaf3ed4294 100644 (file)
@@ -1 +1,27 @@
 #include corlib.dll.sources
+CommonCrypto/CommonCrypto.cs
+CommonCrypto/CryptorTransform.cs
+CommonCrypto/FastCryptorTransform.cs
+CommonCrypto/CorlibExtras.cs
+CommonCrypto/MD5CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1Managed.g.cs
+CommonCrypto/SHA256Managed.g.cs
+CommonCrypto/SHA384Managed.g.cs
+CommonCrypto/SHA512Managed.g.cs
+CommonCrypto/TripleDESCryptoServiceProvider.g.cs
+CommonCrypto/DESCryptoServiceProvider.g.cs
+CommonCrypto/RC2CryptoServiceProvider.g.cs
+CommonCrypto/RijndaelManaged.cs
+CommonCrypto/SecRandom.cs
+CommonCrypto/RC4CommonCrypto.cs
+CommonCrypto/MD2Managed.g.cs
+CommonCrypto/MD4Managed.g.cs
+System/Environment.iOS.cs
+System/Guid.MonoTouch.cs
+System/NotSupportedException.iOS.cs
+CoreFoundation/CFHelpers.cs
+System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
+System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
+System.Text/EncodingHelper.MonoTouch.cs
diff --git a/mcs/class/corlib/monotouch_watch_opt_corlib.dll.sources b/mcs/class/corlib/monotouch_watch_opt_corlib.dll.sources
deleted file mode 100644 (file)
index d32b506..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_opt_corlib.dll.sources
diff --git a/mcs/class/corlib/monotouch_watch_runtime_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_watch_runtime_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..53efeac
--- /dev/null
@@ -0,0 +1 @@
+#include monotouch_corlib.dll.exclude.sources
diff --git a/mcs/class/corlib/monotouch_watch_runtime_opt_corlib.dll.sources b/mcs/class/corlib/monotouch_watch_runtime_opt_corlib.dll.sources
deleted file mode 100644 (file)
index d32b506..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_opt_corlib.dll.sources
diff --git a/mcs/class/corlib/xammac_corlib.dll.exclude.sources b/mcs/class/corlib/xammac_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..86bb404
--- /dev/null
@@ -0,0 +1,14 @@
+System.Security.Cryptography/MD5CryptoServiceProvider.cs
+System.Security.Cryptography/SHA1CryptoServiceProvider.cs
+System.Security.Cryptography/SHA1CryptoServiceProvider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/descryptoserviceprovider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/rc2cryptoserviceprovider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/rijndaelmanaged.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha1managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha256managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha384managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha512managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/tripledescryptoserviceprovider.cs
+../Mono.Security/Mono.Security.Cryptography/ARC4Managed.cs
+../Mono.Security/Mono.Security.Cryptography/MD2Managed.cs
+../Mono.Security/Mono.Security.Cryptography/MD4Managed.cs
index da77893bcc50c66f173571e43a57595448b44e27..0dbb5163c7042ef38fd2f08e6f1fc01a3611dd6f 100644 (file)
@@ -1 +1,22 @@
 #include corlib.dll.sources
+CommonCrypto/CommonCrypto.cs
+CommonCrypto/CryptorTransform.cs
+CommonCrypto/FastCryptorTransform.cs
+CommonCrypto/CorlibExtras.cs
+CommonCrypto/MD5CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1Managed.g.cs
+CommonCrypto/SHA256Managed.g.cs
+CommonCrypto/SHA384Managed.g.cs
+CommonCrypto/SHA512Managed.g.cs
+CommonCrypto/TripleDESCryptoServiceProvider.g.cs
+CommonCrypto/DESCryptoServiceProvider.g.cs
+CommonCrypto/RC2CryptoServiceProvider.g.cs
+CommonCrypto/RijndaelManaged.cs
+CommonCrypto/RC4CommonCrypto.cs
+CommonCrypto/MD2Managed.g.cs
+CommonCrypto/MD4Managed.g.cs
+CoreFoundation/CFHelpers.cs
+System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
+System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
diff --git a/mcs/class/corlib/xammac_opt_corlib.dll.sources b/mcs/class/corlib/xammac_opt_corlib.dll.sources
deleted file mode 100644 (file)
index 449e252..0000000
+++ /dev/null
@@ -1 +0,0 @@
-System.Security.Cryptography.X509Certificates/X509Helper.MonoTouch.opt.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 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 93153cb19b9dbcd34613f62ff8565663e92e37e8..9b07560ab3997c9f56a23edbc71e127d02ca7a34 100644 (file)
@@ -5,6 +5,6 @@ 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 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 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 46c63cd9dfeff02e3431f06c12e0317b3b25f3be..57bae7e4c1d96d7e934ae63c25872c9e9dcfab5a 100755 (executable)
@@ -97,10 +97,6 @@ class MakeBundle {
                                break;
                        case "--static":
                                static_link = true;
-                               if (!quiet) {
-                                       Console.WriteLine ("Note that statically linking the LGPL Mono runtime has more licensing restrictions than dynamically linking.");
-                                       Console.WriteLine ("See http://www.mono-project.com/Licensing for details on licensing.");
-                               }
                                break;
                        case "--config":
                                if (i+1 == top) {
index 2fc8018c7b492d35bf26e46193ca5acadfc1d5b7..0580eeb9615db86aba1c056ff7e1256b528423e6 100644 (file)
@@ -7,6 +7,7 @@ using System.Diagnostics;
 using System.Collections.Generic;
 using Mono.Cecil;
 using Mono.CompilerServices.SymbolWriter;
+using System.Runtime.InteropServices;
 
 namespace Symbolicate
 {
@@ -57,33 +58,20 @@ namespace Symbolicate
                                return true;
                        }
 
-                       static MethodInfo methodGetIL;
+                       SeqPointInfo seqPointInfo;
                        private int GetILOffsetFromFile (int methodToken, uint methodIndex, int nativeOffset)
                        {
-                               if (string.IsNullOrEmpty (seqPointDataPath))
-                                       return -1;
+                               if (seqPointInfo == null)
+                                       seqPointInfo = SeqPointInfo.Read (seqPointDataPath);
 
-                               if (methodGetIL == null)
-                                       methodGetIL = typeof (StackFrame).GetMethod ("GetILOffsetFromFile", BindingFlags.NonPublic | BindingFlags.Static);
-
-                               if (methodGetIL == null)
-                                       throw new Exception ("System.Diagnostics.StackFrame.GetILOffsetFromFile could not be found, make sure you have an updated mono installed.");
-
-                               return (int) methodGetIL.Invoke (null, new object[] {seqPointDataPath, methodToken, methodIndex, nativeOffset});
+                               return seqPointInfo.GetILOffset (methodToken, methodIndex, nativeOffset);
                        }
 
-                       static MethodInfo methodGetMethodFullName;
                        private string GetMethodFullName (MethodBase m)
                        {
-
-                               if (methodGetMethodFullName == null)
-                                       methodGetMethodFullName = typeof (StackTrace).GetMethod ("GetFullNameForStackTrace", BindingFlags.NonPublic | BindingFlags.Static);
-
-                               if (methodGetMethodFullName == null)
-                                       throw new Exception ("System.Exception.GetFullNameForStackTrace could not be found, make sure you have an updated mono installed.");
-
                                StringBuilder sb = new StringBuilder ();
-                               methodGetMethodFullName.Invoke (null, new object[] {sb, m});
+
+                               StackTraceHelper.GetFullNameForStackTrace (sb, m);
 
                                return sb.ToString ();
                        }
@@ -106,7 +94,7 @@ namespace Symbolicate
                        if (!File.Exists (assemblyPath))
                                throw new ArgumentException ("assemblyPath does not exist: "+ assemblyPath);
 
-                       var assembly = Assembly.LoadFrom (assemblyPath);
+                       var assembly = Assembly.ReflectionOnlyLoadFrom (assemblyPath);
                        MonoSymbolFile symbolFile = null;
 
                        var symbolPath = assemblyPath + ".mdb";
diff --git a/mcs/tools/mono-symbolicate/SeqPointInfo.cs b/mcs/tools/mono-symbolicate/SeqPointInfo.cs
new file mode 100644 (file)
index 0000000..606e4fb
--- /dev/null
@@ -0,0 +1,156 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+
+namespace Symbolicate
+{
+       static class BinaryReaderExtensions
+       {
+               public static int ReadVariableInt (this BinaryReader reader)
+               {
+                       int val = 0;
+                       for (var i = 0; i < 4; i++) {
+                               var b = reader.ReadByte ();
+                               val |= (b & 0x7f) << (7 * i);
+                               if ((b & 0x80) == 0)
+                                       return val;
+                       }
+
+                       throw new Exception ("Invalid variable int");
+               }
+
+               public static int ReadVariableZigZagInt (this BinaryReader reader)
+               {
+                       int enc = ReadVariableInt (reader);
+                       int val = enc >> 1;
+                       return ((enc & 1) == 0)? val : -val;
+               }
+       }
+
+       class SeqPointInfo
+       {
+               class MethodData
+               {
+                       List<SeqPoint> seqPoints;
+
+                       public static MethodData Read (BinaryReader reader)
+                       {
+                               var hasDebugData = reader.ReadVariableInt () != 0;
+                               var dataSize = reader.ReadVariableInt ();
+                               var dataEnd = reader.BaseStream.Position + dataSize;
+
+                               var seqPoints = new List<SeqPoint> ();
+                               SeqPoint prev = null;
+                               while (reader.BaseStream.Position < dataEnd) {
+                                       var seqPoint = SeqPoint.Read (reader, prev, hasDebugData);
+                                       seqPoints.Add (seqPoint);
+                                       prev = seqPoint;
+                               }
+
+                               if (reader.BaseStream.Position != dataEnd)
+                                       throw new Exception ("Read more seq point than expected.");
+
+                               return new MethodData () { seqPoints = seqPoints };
+                       }
+
+                       public bool TryGetILOffset (int nativeOffset, out int ilOffset)
+                       {
+                               ilOffset = 0;
+                               SeqPoint prev = null;
+                               foreach (var seqPoint in seqPoints) {
+                                       if (seqPoint.NativeOffset > nativeOffset)
+                                               break;
+                                       prev = seqPoint;
+                               }
+
+                               if (prev == null)
+                                       return false;
+
+                               ilOffset = prev.ILOffset;
+                               return true;
+                       }
+               }
+
+               class SeqPoint
+               {
+                       public readonly int ILOffset;
+                       public readonly int NativeOffset;
+
+                       public SeqPoint (int ilOffset, int nativeOffset)
+                       {
+                               ILOffset = ilOffset;
+                               NativeOffset = nativeOffset;
+                       }
+
+                       public static SeqPoint Read (BinaryReader reader, SeqPoint prev, bool hasDebug)
+                       {
+                               var ilOffset = reader.ReadVariableZigZagInt ();
+                               var nativeOffset = reader.ReadVariableZigZagInt ();
+
+                               // Respect delta encoding
+                               if (prev != null) {
+                                       ilOffset += prev.ILOffset;
+                                       nativeOffset += prev.NativeOffset;
+                               }
+
+                               //Read everything to ensure the buffer position is at the end of the seq point data.
+                               if (hasDebug) {
+                                       reader.ReadVariableInt (); // flags
+
+                                       var next_length = reader.ReadVariableInt ();
+                                       for (var i = 0; i < next_length; ++i)
+                                               reader.ReadVariableInt ();
+                               }
+
+                               return new SeqPoint (ilOffset, nativeOffset);
+                       }
+               };
+
+               Dictionary<Tuple<int,int>, MethodData> dataByIds;
+               Dictionary<int, MethodData> dataByTokens;
+
+               public static SeqPointInfo Read (string path)
+               {
+                       using (var reader = new BinaryReader (File.Open (path, FileMode.Open)))
+                       {
+                               var dataByIds = new Dictionary<Tuple<int,int>, MethodData> ();
+                               var dataByTokens = new Dictionary<int, MethodData> ();
+
+                               var methodCount = reader.ReadVariableInt ();
+
+                               for (var i = 0; i < methodCount; ++i) {
+                                       var methodToken = reader.ReadVariableInt ();
+                                       var methodIndex = reader.ReadVariableInt ();
+                                       var methodId = new Tuple<int, int> (methodToken, methodIndex);
+
+                                       var methodData = MethodData.Read (reader);
+
+                                       dataByIds.Add (methodId, methodData);
+                                       if (!dataByTokens.ContainsKey (methodToken))
+                                               dataByTokens.Add (methodToken, methodData);
+                               }
+
+                               return new SeqPointInfo { dataByIds  = dataByIds, dataByTokens = dataByTokens };
+                       }
+               }
+
+               public int GetILOffset (int methodToken, uint methodIndex, int nativeOffset)
+               {
+                       MethodData methodData;
+                       if (methodIndex == 0xffffff) {
+                          if (!dataByTokens.TryGetValue (methodToken, out methodData))
+                                       throw new Exception (string.Format ("Could not find data for method token {0:X}", methodToken));
+                       } else {
+                               var methodId = new Tuple<int, int> (methodToken, (int)methodIndex);
+                               if (!dataByIds.TryGetValue (methodId, out methodData))
+                                       throw new Exception (string.Format ("Could not find data for method token {0:X} with index {1:X}", methodToken, methodIndex));
+                       }
+
+                       int ilOffset;
+                       if (!methodData.TryGetILOffset (nativeOffset, out ilOffset))
+                               throw new Exception ("Could not retrieve IL offset");
+
+                       return ilOffset;
+               }
+       }
+}
index 968d028d0e95a50ac0f9a060963714a545036a7b..7f50e887c2032b2fde8f5f62f689241af91c5237 100644 (file)
@@ -1,2 +1,4 @@
 symbolicate.cs
-LocationProvider.cs
\ No newline at end of file
+LocationProvider.cs
+SeqPointInfo.cs
+../../class/corlib/System.Diagnostics/StackTraceHelper.cs
index 181913f5751c9b68b459919dc5c911dc96f1a0da..fcdf30adbfd92170b52dcd45318abe2f4ec26bed 100644 (file)
@@ -11,6 +11,7 @@
  * 
  * Copyright (C)  2000 Intel Corporation.  All rights reserved.
  * Copyright (C)  2001, 2002 Ximian, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef AMD64_H
index 3ee083f8010ffdf7bad83cc527f8d32e078e6b00..1af30c6b21bb516a2466cc6d4f5bc72118884228 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (c) 2002-2003 Sergey Chaban <serge@wildwestsoftware.com>
  * Copyright 2005-2011 Novell Inc
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 
index 8b56b00dbbee462d56c19c9089a64aae9687403a..edf558da2995f17b8e5663b0a4656bfc76576ec9 100644 (file)
@@ -1,6 +1,7 @@
 //
 // Copyright 2011 Xamarin Inc
 //
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
 #ifndef __MONO_ARM_VFP_CODEGEN_H__
 #define __MONO_ARM_VFP_CODEGEN_H__
index 427c4fc9f6066e5670172dc81c3dac0dafc52747..e43ac7763f36a4873ede1048ece176a9d8dbc0e8 100644 (file)
@@ -2,6 +2,7 @@
  * ARM CodeGen\r
  * XScale WirelessMMX extensions\r
  * Copyright 2002 Wild West Software\r
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.\r
  */\r
 \r
 #ifndef __WMMX_H__\r
index 259ff9674072a36c39df092a39a1b3a8eca25148..6ca4da6d88127686f16fe2ac70c759a8839a6f4e 100644 (file)
@@ -1,3 +1,852 @@
-#include "../../../../mono-extensions/mono/arch/arm64/arm64-codegen.h"
+/*
+ * arm64-codegen.h: ARM64 code generation macros
+ *
+ * Author:
+ *   Zoltan Varga (vargaz@gmail.com)
+ *
+ * Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
 
+#ifndef __ARM64_CODEGEN_H__
+#define __ARM64_CODEGEN_H__
 
+#include <glib.h>
+
+enum {
+       ARMREG_R0 = 0,
+       ARMREG_R1 = 1,
+       ARMREG_R2 = 2,
+       ARMREG_R3 = 3,
+       ARMREG_R4 = 4,
+       ARMREG_R5 = 5,
+       ARMREG_R6 = 6,
+       ARMREG_R7 = 7,
+       ARMREG_R8 = 8,
+       ARMREG_R9 = 9,
+       ARMREG_R10 = 10,
+       ARMREG_R11 = 11,
+       ARMREG_R12 = 12,
+       ARMREG_R13 = 13,
+       ARMREG_R14 = 14,
+       ARMREG_R15 = 15,
+       ARMREG_R16 = 16,
+       ARMREG_R17 = 17,
+       ARMREG_R18 = 18,
+       ARMREG_R19 = 19,
+       ARMREG_R20 = 20,
+       ARMREG_R21 = 21,
+       ARMREG_R22 = 22,
+       ARMREG_R23 = 23,
+       ARMREG_R24 = 24,
+       ARMREG_R25 = 25,
+       ARMREG_R26 = 26,
+       ARMREG_R27 = 27,
+       ARMREG_R28 = 28,
+       ARMREG_R29 = 29,
+       ARMREG_R30 = 30,
+       ARMREG_SP = 31,
+       ARMREG_RZR = 31,
+
+       ARMREG_IP0 = ARMREG_R16,
+       ARMREG_IP1 = ARMREG_R17,
+       ARMREG_FP = ARMREG_R29,
+       ARMREG_LR = ARMREG_R30
+};
+
+enum {
+       ARMREG_D0 = 0,
+       ARMREG_D1 = 1,
+       ARMREG_D2 = 2,
+       ARMREG_D3 = 3,
+       ARMREG_D4 = 4,
+       ARMREG_D5 = 5,
+       ARMREG_D6 = 6,
+       ARMREG_D7 = 7,
+       ARMREG_D8 = 8,
+       ARMREG_D9 = 9,
+       ARMREG_D10 = 10,
+       ARMREG_D11 = 11,
+       ARMREG_D12 = 12,
+       ARMREG_D13 = 13,
+       ARMREG_D14 = 14,
+       ARMREG_D15 = 15,
+       ARMREG_D16 = 16,
+       ARMREG_D17 = 17,
+       ARMREG_D18 = 18,
+       ARMREG_D19 = 19,
+       ARMREG_D20 = 20,
+       ARMREG_D21 = 21,
+       ARMREG_D22 = 22,
+       ARMREG_D23 = 23,
+       ARMREG_D24 = 24,
+       ARMREG_D25 = 25,
+       ARMREG_D26 = 26,
+       ARMREG_D27 = 27,
+       ARMREG_D28 = 28,
+       ARMREG_D29 = 29,
+       ARMREG_D30 = 30,
+       ARMREG_D31 = 31
+};
+
+typedef enum {
+       ARMCOND_EQ = 0x0,          /* Equal; Z = 1 */
+       ARMCOND_NE = 0x1,          /* Not equal, or unordered; Z = 0 */
+       ARMCOND_CS = 0x2,          /* Carry set; C = 1 */
+       ARMCOND_HS = ARMCOND_CS,   /* Unsigned higher or same; */
+       ARMCOND_CC = 0x3,          /* Carry clear; C = 0 */
+       ARMCOND_LO = ARMCOND_CC,   /* Unsigned lower */
+       ARMCOND_MI = 0x4,          /* Negative; N = 1 */
+       ARMCOND_PL = 0x5,          /* Positive or zero; N = 0 */
+       ARMCOND_VS = 0x6,          /* Overflow; V = 1 */
+       ARMCOND_VC = 0x7,          /* No overflow; V = 0 */
+       ARMCOND_HI = 0x8,          /* Unsigned higher; C = 1 && Z = 0 */
+       ARMCOND_LS = 0x9,          /* Unsigned lower or same; C = 0 || Z = 1 */
+       ARMCOND_GE = 0xA,          /* Signed greater than or equal; N = V */
+       ARMCOND_LT = 0xB,          /* Signed less than; N != V */
+       ARMCOND_GT = 0xC,          /* Signed greater than; Z = 0 && N = V */
+       ARMCOND_LE = 0xD,          /* Signed less than or equal; Z = 1 || N != V */
+       ARMCOND_AL = 0xE,          /* Always */
+       ARMCOND_NV = 0xF,          /* Never */
+} ARMCond;
+
+typedef enum {
+       ARMSHIFT_LSL = 0x0,
+       ARMSHIFT_LSR = 0x1,
+       ARMSHIFT_ASR = 0x2
+} ARMShift;
+
+typedef enum {
+       ARMSIZE_B = 0x0,
+       ARMSIZE_H = 0x1,
+       ARMSIZE_W = 0x2,
+       ARMSIZE_X = 0x3
+} ARMSize;
+
+#define arm_emit(p, ins) do { *(guint32*)(p) = (ins); (p) += 4; } while (0)
+
+/* Overwrite bits [offset,offset+nbits] with value */
+static G_GNUC_UNUSED inline void
+arm_set_ins_bits (void *p, int offset, int nbits, guint32 value)
+{
+       *(guint32*)p = (*(guint32*)p & ~(((1 << nbits) - 1) << offset)) | (value << offset);
+}
+
+/*
+ * Naming conventions for codegen macros:
+ * - 64 bit opcodes have an 'X' suffix
+ * - 32 bit opcodes have a 'W' suffix
+ * - the order of operands is the same as in assembly
+ */
+
+/*
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0487a/index.html
+ */
+
+/* Uncoditional branch (register) */
+
+// 0b1101011 == 0x6b
+#define arm_format_breg(p, opc, op2, op3, op4, rn) arm_emit ((p), (0x6b << 25) | ((opc) << 21) | ((op2) << 16) | ((op3) << 10) | ((rn) << 5) | ((op4) << 0))
+
+// 0b0000 == 0x0, 0b11111 == 0x1f
+#define arm_brx(p, reg) arm_format_breg ((p), 0x0, 0x1f, 0x0, 0x0, (reg))
+
+// 0b0001 == 0x1
+#define arm_blrx(p, reg) arm_format_breg ((p), 0x1, 0x1f, 0x0, 0x0, (reg))
+
+//0b0010 == 0x2
+#define arm_retx(p, reg) arm_format_breg ((p), 0x2, 0x1f, 0x0, 0x0, (reg))
+
+/* Unconditional branch (immeditate) */
+
+static G_GNUC_UNUSED inline gboolean
+arm_is_bl_disp (void *code, void *target)
+{
+       gint64 disp = ((char*)(target) - (char*)(code)) / 4;
+
+       return (disp > -(1 << 25)) && (disp < (1 << 25));
+}
+
+static G_GNUC_UNUSED inline unsigned int
+arm_get_disp (void *p, void *target)
+{
+       unsigned int disp = ((char*)target - (char*)p) / 4;
+
+       if (target)
+               g_assert (arm_is_bl_disp (p, target));
+
+       return (disp & 0x3ffffff);
+}
+
+// 0b00101 == 0x5
+#define arm_b(p, target) arm_emit (p, (0x0 << 31) | (0x5 << 26) | ((arm_get_disp ((p), (target)) << 0)))
+
+#define arm_bl(p, target) arm_emit (p, (0x1 << 31) | (0x5 << 26) | ((arm_get_disp ((p), (target)) << 0)))
+
+/* Conditional branch */
+
+static G_GNUC_UNUSED inline gboolean
+arm_is_disp19 (void *code, void *target)
+{
+       gint64 disp = ((char*)(target) - (char*)(code)) / 4;
+
+       return (disp > -(1 << 18)) && (disp < (1 << 18));
+}
+
+static G_GNUC_UNUSED inline unsigned int
+arm_get_disp19 (void *p, void *target)
+{
+       unsigned int disp = ((char*)target - (char*)p) / 4;
+
+       if (target)
+               g_assert (arm_is_disp19 (p, target));
+
+       return (disp & 0x7ffff);
+}
+
+// 0b0101010 == 0x2a
+#define arm_format_condbr(p, o1, o0, cond, disp) arm_emit ((p), (0x2a << 25) | ((o1) << 24) | ((disp) << 5) | ((o0) << 4) | ((cond) << 0))
+#define arm_get_bcc_cond(p) ((*(guint32*)p) & 0xf)
+
+#define arm_bcc(p, cond, target) arm_format_condbr ((p), 0x0, 0x0, (cond), arm_get_disp19 ((p), (target)))
+
+// 0b011010 == 0x1a
+#define arm_format_cmpbr(p, sf, op, rt, target) arm_emit ((p), ((sf) << 31) | (0x1a << 25) | ((op) << 24) | (arm_get_disp19 ((p), (target)) << 5) | ((rt) << 0))
+
+#define arm_set_cbz_target(p, target) arm_set_ins_bits (p, 5, 19, arm_get_disp19 ((p), (target)))
+
+#define arm_cbzx(p, rt, target) arm_format_cmpbr ((p), 0x1, 0x0, (rt), (target))
+#define arm_cbzw(p, rt, target) arm_format_cmpbr ((p), 0x0, 0x0, (rt), (target))
+
+#define arm_cbnzx(p, rt, target) arm_format_cmpbr ((p), 0x1, 0x1, (rt), (target))
+#define arm_cbnzw(p, rt, target) arm_format_cmpbr ((p), 0x0, 0x1, (rt), (target))
+
+static G_GNUC_UNUSED inline unsigned int
+arm_get_disp15 (void *p, void *target)
+{
+       unsigned int disp = ((char*)target - (char*)p) / 4;
+       return (disp & 0x7fff);
+}
+
+// 0b011011 == 0x1b
+#define arm_format_tbimm(p, op, rt, bit, target) arm_emit ((p), ((((bit) >> 5) & 1) << 31) | (0x1b << 25) | ((op) << 24) | (((bit) & 0x1f) << 19) | (arm_get_disp15 ((p), (target)) << 5) | ((rt) << 0))
+
+#define arm_tbz(p, rt, bit, target) arm_format_tbimm ((p), 0x0, (rt), (bit), (target))
+#define arm_tbnz(p, rt, bit, target) arm_format_tbimm ((p), 0x1, (rt), (bit), (target))
+
+/* Memory access */
+
+#define arm_is_pimm12_scaled(pimm,size) ((pimm) >= 0 && (pimm) / (size) <= 0xfff && ((pimm) % (size)) == 0)
+
+static G_GNUC_UNUSED unsigned int
+arm_encode_pimm12 (int pimm, int size)
+{
+       g_assert (arm_is_pimm12_scaled (pimm, size));
+       return ((unsigned int)(pimm / size)) & 0xfff;
+}
+
+#define arm_is_strb_imm(pimm) arm_is_pimm12_scaled((pimm), 1)
+#define arm_is_strh_imm(pimm) arm_is_pimm12_scaled((pimm), 2)
+#define arm_is_strw_imm(pimm) arm_is_pimm12_scaled((pimm), 4)
+#define arm_is_strx_imm(pimm) arm_is_pimm12_scaled((pimm), 8)
+
+/* Load/Store register + scaled immediate */
+/* No pre-index/post-index yet */
+#define arm_format_mem_imm(p, size, opc, rt, rn, pimm, scale) arm_emit ((p), ((size) << 30) | (0x39 << 24) | ((opc) << 22) | (arm_encode_pimm12 ((pimm), (scale)) << 10) | ((rn) << 5) | ((rt) << 0))
+
+/* C5.6.83 LDR (immediate) */
+#define arm_ldrx(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_X, 0x1, (rt), (rn), (pimm), 8)
+#define arm_ldrw(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_W, 0x1, (rt), (rn), (pimm), 4)
+/* C5.6.86 LDRB (immediate) */
+#define arm_ldrb(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_B, 0x1, (rt), (rn), (pimm), 1)
+/* C5.6.88 LDRH (immediate) */
+#define arm_ldrh(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_H, 0x1, (rt), (rn), (pimm), 2)
+/* C5.6.90 LDRSB (immediate) */
+#define arm_ldrsbx(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_B, 0x2, (rt), (rn), (pimm), 1)
+#define arm_ldrsbw(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_B, 0x3, (rt), (rn), (pimm), 1)
+/* C5.6.92 LDRSH (immediate) */
+#define arm_ldrshx(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_H, 0x2, (rt), (rn), (pimm), 2)
+#define arm_ldrshw(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_H, 0x3, (rt), (rn), (pimm), 2)
+/* C5.6.94 LDRSW (immediate) */
+#define arm_ldrswx(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_W, 0x2, (rt), (rn), (pimm), 4)
+
+/* C5.6.178 STR (immediate) */
+#define arm_strx(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_X, 0x0, (rt), (rn), (pimm), 8)
+#define arm_strw(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_W, 0x0, (rt), (rn), (pimm), 4)
+/* C5.6.182 STR (immediate) */
+#define arm_strh(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_H, 0x0, (rt), (rn), (pimm), 2)
+#define arm_strb(p, rt, rn, pimm) arm_format_mem_imm (p, ARMSIZE_B, 0x0, (rt), (rn), (pimm), 1)
+
+/* C3.3.9 Load/store register (immediate post-indexed) */
+static G_GNUC_UNUSED unsigned int
+arm_encode_simm9 (int simm)
+{
+       g_assert (simm >= -256 && simm <= 255);
+       return ((unsigned int)simm) & 0x1ff;
+}
+
+#define arm_format_mem_imm_post(p, size, V, opc, rt, rn, simm) arm_emit ((p), ((size) << 30) | (0x7 << 27) | ((V) << 26) | (0x0 << 24) | ((opc) << 22) | (arm_encode_simm9 ((simm)) << 12) | (0x1 << 10) | ((rn) << 5) | ((rt) << 0))
+
+#define arm_ldrx_post(p, rt, rn, simm) arm_format_mem_imm_post (p, ARMSIZE_X, 0x0, 0x1, (rt), (rn), (simm))
+#define arm_ldrw_post(p, rt, rn, simm) arm_format_mem_imm_post (p, ARMSIZE_W, 0x0, 0x1, (rt), (rn), (simm))
+
+#define arm_strx_post(p, rt, rn, simm) arm_format_mem_imm_post (p, ARMSIZE_X, 0x0, 0x0, (rt), (rn), (simm))
+#define arm_strw_post(p, rt, rn, simm) arm_format_mem_imm_post (p, ARMSIZE_W, 0x0, 0x0, (rt), (rn), (simm))
+
+/* C3.3.9 Load/store register (immediate pre-indexed) */
+#define arm_format_mem_imm_pre(p, size, V, opc, rt, rn, simm) arm_emit ((p), ((size) << 30) | (0x7 << 27) | ((V) << 26) | (0x0 << 24) | ((opc) << 22) | (arm_encode_simm9 ((simm)) << 12) | (0x3 << 10) | ((rn) << 5) | ((rt) << 0))
+
+#define arm_ldrx_pre(p, rt, rn, simm) arm_format_mem_imm_pre (p, ARMSIZE_X, 0x0, 0x1, (rt), (rn), (simm))
+#define arm_ldrw_pre(p, rt, rn, simm) arm_format_mem_imm_pre (p, ARMSIZE_W, 0x0, 0x1, (rt), (rn), (simm))
+
+#define arm_strx_pre(p, rt, rn, simm) arm_format_mem_imm_pre (p, ARMSIZE_X, 0x0, 0x0, (rt), (rn), (simm))
+#define arm_strw_pre(p, rt, rn, simm) arm_format_mem_imm_pre (p, ARMSIZE_W, 0x0, 0x0, (rt), (rn), (simm))
+
+/* Load/Store register + register */
+/* No extend/scale yet */
+#define arm_format_mem_reg(p, size, opc, rt, rn, rm) arm_emit ((p), ((size) << 30) | (0x38 << 24) | ((opc) << 22) | (0x1 << 21) | ((rm) << 16) | (0x3 << 13) | (0 << 12) | (0x2 << 10) | ((rn) << 5) | ((rt) << 0))
+
+/* C5.6.85 LDR (register) */
+#define arm_ldrx_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_X, 0x1, (rt), (rn), (rm))
+#define arm_ldrw_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_W, 0x1, (rt), (rn), (rm))
+/* C5.6.87 LDRB (register) */
+#define arm_ldrb_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_B, 0x1, (rt), (rn), (rm))
+/* C5.6.88 LDRH (register) */
+#define arm_ldrh_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_H, 0x1, (rt), (rn), (rm))
+/* C5.6.91 LDRSB (register) */
+#define arm_ldrsbx_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_B, 0x2, (rt), (rn), (rm))
+#define arm_ldrsbw_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_B, 0x3, (rt), (rn), (rm))
+/* C5.6.93 LDRSH (register) */
+#define arm_ldrshx_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_H, 0x2, (rt), (rn), (rm))
+#define arm_ldrshw_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_H, 0x3, (rt), (rn), (rm))
+/* C5.6.96 LDRSW (register) */
+#define arm_ldrswx_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_W, 0x2, (rt), (rn), (rm))
+
+/* C5.6.179 STR (register) */
+#define arm_strx_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_X, 0x0, (rt), (rn), (rm))
+#define arm_strw_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_W, 0x0, (rt), (rn), (rm))
+/* C5.6.181 STRB (register) */
+#define arm_strb_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_B, 0x0, (rt), (rn), (rm))
+/* C5.6.183 STRH (register) */
+#define arm_strh_reg(p, rt, rn, rm) arm_format_mem_reg ((p), ARMSIZE_H, 0x0, (rt), (rn), (rm))
+
+/* PC relative */
+
+/* C5.6.84 LDR (literal) */
+
+#define arm_get_ldr_lit_reg(p) (*(guint32*)(p) & 0x1f)
+
+#define arm_ldrx_lit(p, rt, target) arm_emit ((p), (0x01 << 30) | (0x18 << 24) | (arm_get_disp19 ((p), (target)) << 5) | ((rt) << 0))
+#define arm_ldrw_lit(p, rt, target) arm_emit ((p), (0x00 << 30) | (0x18 << 24) | (arm_get_disp19 ((p), (target)) << 5) | ((rt) << 0))
+#define arm_ldrswx_lit(p, rt, target) arm_emit ((p), (0x2 << 30) | (0x18 << 24) | (arm_get_disp19 ((p), (target)) << 5) | ((rt) << 0))
+
+/* Unscaled offset */
+/* FIXME: Not yet */
+
+/* Load/Store Pair */
+
+static G_GNUC_UNUSED unsigned int
+arm_encode_imm7 (int imm, int size)
+{
+       g_assert (imm / size >= -64 && imm / size <= 63 && (imm % size) == 0);
+       return ((unsigned int)(imm / size)) & 0x7f;
+}
+
+#define arm_is_imm7_scaled(imm, size) ((imm) / (size) >= -64 && (imm) / (size) <= 63 && ((imm) % (size)) == 0)
+
+#define arm_is_ldpx_imm(imm) arm_is_imm7_scaled ((imm), 8)
+
+/* C3.3.14 */
+#define arm_format_mem_p(p, size, opc, L, rt1, rt2, rn, imm) arm_emit ((p), (opc << 30) | (0x52 << 23) | ((L) << 22) | (arm_encode_imm7 (imm, size) << 15) | ((rt2) << 10) | ((rn) << 5) | ((rt1) << 0))
+
+#define arm_ldpx(p, rt1, rt2, rn, imm) arm_format_mem_p ((p), 8, 0x2, 1, (rt1), (rt2), (rn), (imm))
+#define arm_ldpw(p, rt1, rt2, rn, imm) arm_format_mem_p ((p), 4, 0x0, 1, (rt1), (rt2), (rn), (imm))
+#define arm_ldpsw(p, rt1, rt2, rn, imm) arm_format_mem_p ((p), 4, 0x1, 1, (rt1), (rt2), (rn), (imm))
+#define arm_stpx(p, rt1, rt2, rn, imm) arm_format_mem_p ((p), 8, 0x2, 0, (rt1), (rt2), (rn), (imm))
+#define arm_stpw(p, rt1, rt2, rn, imm) arm_format_mem_p ((p), 4, 0x0, 0, (rt1), (rt2), (rn), (imm))
+
+/* Load/Store Pair (Pre-indexed) */
+/* C3.3.16 */
+#define arm_format_mem_p_pre(p, size, opc, L, rt1, rt2, rn, imm) arm_emit ((p), (opc << 30) | (0x53 << 23) | ((L) << 22) | (arm_encode_imm7 (imm, size) << 15) | ((rt2) << 10) | ((rn) << 5) | ((rt1) << 0))
+
+#define arm_ldpx_pre(p, rt1, rt2, rn, imm) arm_format_mem_p_pre ((p), 8, 0x2, 1, (rt1), (rt2), (rn), (imm))
+#define arm_ldpw_pre(p, rt1, rt2, rn, imm) arm_format_mem_p_pre ((p), 4, 0x0, 1, (rt1), (rt2), (rn), (imm))
+#define arm_ldpsw_pre(p, rt1, rt2, rn, imm) arm_format_mem_p_pre ((p), 4, 0x1, 1, (rt1), (rt2), (rn), (imm))
+#define arm_stpx_pre(p, rt1, rt2, rn, imm) arm_format_mem_p_pre ((p), 8, 0x2, 0, (rt1), (rt2), (rn), (imm))
+#define arm_stpw_pre(p, rt1, rt2, rn, imm) arm_format_mem_p_pre ((p), 4, 0x0, 0, (rt1), (rt2), (rn), (imm))
+
+/* Not an official alias */
+#define arm_pushpx (p, rt1, rt2) arm_LDPX_pre (p, rt1, rt2, ARMREG_RSP, -8)
+
+/* Load/Store Pair (Post-indexed) */
+/* C3.3.15 */
+#define arm_format_mem_p_post(p, size, opc, L, rt1, rt2, rn, imm) arm_emit ((p), (opc << 30) | (0x51 << 23) | ((L) << 22) | (arm_encode_imm7 (imm, size) << 15) | ((rt2) << 10) | ((rn) << 5) | ((rt1) << 0))
+
+#define arm_ldpx_post(p, rt1, rt2, rn, imm) arm_format_mem_p_post ((p), 8, 0x2, 1, (rt1), (rt2), (rn), (imm))
+#define arm_ldpw_post(p, rt1, rt2, rn, imm) arm_format_mem_p_post ((p), 4, 0x0, 1, (rt1), (rt2), (rn), (imm))
+#define arm_ldpsw_post(p, rt1, rt2, rn, imm) arm_format_mem_p_post ((p), 4, 0x1, 1, (rt1), (rt2), (rn), (imm))
+#define arm_stpx_post(p, rt1, rt2, rn, imm) arm_format_mem_p_post ((p), 8, 0x2, 0, (rt1), (rt2), (rn), (imm))
+#define arm_stpw_post(p, rt1, rt2, rn, imm) arm_format_mem_p_post ((p), 4, 0x0, 0, (rt1), (rt2), (rn), (imm))
+
+/* Not an official alias */
+#define arm_poppx (p, rt1, rt2) arm_ldpx_post (p, rt1, rt2, ARMREG_RSP, 8)
+
+/* Load/Store Exclusive */
+#define arm_format_ldxr(p, size, rt, rn) arm_emit ((p), ((size) << 30) | (0x8 << 24) | (0x0 << 23) | (0x1 << 22) | (0x0 << 21) | (0x1f << 16) | (0x0 << 15) | (0x1f << 10) | ((rn) << 5) | ((rt) << 0))
+#define arm_format_ldxp(p, size, rt1, rt2, rn) arm_emit ((p), ((size) << 30) | (0x8 << 24) | (0x0 << 23) | (0x1 << 22) | (0x1 << 21) | (0x1f << 16) | (0x0 << 15) | ((rt2) << 10)| ((rn) << 5) | ((rt1) << 0))
+#define arm_format_stxr(p, size, rs, rt, rn) arm_emit ((p), ((size) << 30) | (0x8 << 24) | (0x0 << 23) | (0x0 << 22) | (0x0 << 21) | ((rs) << 16) | (0x0 << 15) | (0x1f << 10) | ((rn) << 5) | ((rt) << 0))
+#define arm_format_stxp(p, size, rs, rt1, rt2, rn) arm_emit ((p), ((size) << 30) | (0x8 << 24) | (0x0 << 23) | (0x0 << 22) | (0x1 << 21) | ((rs) << 16) | (0x0 << 15) | ((rt2) << 10)| ((rn) << 5) | ((rt1) << 0))
+
+#define arm_ldxrx(p, rt, rn) arm_format_ldxr ((p), ARMSIZE_X, (rt), (rn))
+#define arm_ldxrw(p, rt, rn) arm_format_ldxr ((p), ARMSIZE_W, (rt), (rn))
+#define arm_ldxrh(p, rt, rn) arm_format_ldxr ((p), ARMSIZE_H, (rt), (rn))
+#define arm_ldxrb(p, rt, rn) arm_format_ldxr ((p), ARMSIZE_B, (rt), (rn))
+#define arm_ldxpx(p, rt1, rt2, rn) arm_format_ldxp ((p), ARMSIZE_X, (rt1), (rt2), (rn))
+#define arm_ldxpw(p, rt1, rt2, rn) arm_format_ldxp ((p), ARMSIZE_W, (rt1), (rt2), (rn))
+#define arm_stxrx(p, rs, rt, rn) arm_format_stxr ((p), ARMSIZE_X, (rs), (rt), (rn))
+#define arm_stxrw(p, rs, rt, rn) arm_format_stxr ((p), ARMSIZE_W, (rs), (rt), (rn))
+#define arm_stxrh(p, rs, rt, rn) arm_format_stxr ((p), ARMSIZE_H, (rs), (rt), (rn))
+#define arm_stxrb(p, rs, rt, rn) arm_format_stxr ((p), ARMSIZE_B, (rs), (rt), (rn))
+#define arm_stxpx(p, rs, rt1, rt2, rn) arm_format_stxp ((p), ARMSIZE_X, (rs), (rt1), (rt2), (rn))
+#define arm_stxpw(p, rs, rt1, rt2, rn) arm_format_stxp ((p), ARMSIZE_W, (rs), (rt1), (rt2), (rn))
+
+/* C5.6.73 LDAR: Load-Acquire Register */
+
+#define arm_format_ldar(p, size, rt, rn) arm_emit ((p), ((size) << 30) | (0x8 << 24) | (0x1 << 23) | (0x1 << 22) | (0x0 << 21) | (0x1f << 16) | (0x1 << 15) | (0x1f << 10) | ((rn) << 5) | ((rt) << 0))
+
+#define arm_ldarx(p, rt, rn) arm_format_ldar ((p), ARMSIZE_X, (rt), (rn))
+#define arm_ldarw(p, rt, rn) arm_format_ldar ((p), ARMSIZE_W, (rt), (rn))
+#define arm_ldarh(p, rt, rn) arm_format_ldar ((p), ARMSIZE_H, (rt), (rn))
+#define arm_ldarb(p, rt, rn) arm_format_ldar ((p), ARMSIZE_B, (rt), (rn))
+
+/* C5.6.169 STLR: Store-Release Register */
+
+#define arm_format_stlr(p, size, rt, rn) arm_emit ((p), ((size) << 30) | (0x8 << 24) | (0x1 << 23) | (0x0 << 22) | (0x0 << 21) | (0x1f << 16) | (0x1 << 15) | (0x1f << 10) | ((rn) << 5) | ((rt) << 0))
+
+#define arm_stlrx(p, rn, rt) arm_format_stlr ((p), ARMSIZE_X, (rt), (rn))
+#define arm_stlrw(p, rn, rt) arm_format_stlr ((p), ARMSIZE_W, (rt), (rn))
+#define arm_stlrh(p, rn, rt) arm_format_stlr ((p), ARMSIZE_H, (rt), (rn))
+#define arm_stlrb(p, rn, rt) arm_format_stlr ((p), ARMSIZE_B, (rt), (rn))
+
+/* C5.6.77 LDAXR */
+#define arm_format_ldaxr(p, size, rn, rt) arm_emit ((p), ((size) << 30) | (0x8 << 24) | (0x0 << 23) | (0x1 << 22) | (0x0 << 21) | (0x1f << 16) | (0x1 << 15) | (0x1f << 10) | ((rn) << 5) | ((rt) << 0))
+
+#define arm_ldaxrx(p, rt, rn) arm_format_ldaxr ((p), 0x3, (rn), (rt))
+#define arm_ldaxrw(p, rt, rn) arm_format_ldaxr ((p), 0x2, (rn), (rt))
+
+/* C5.6.173 STLXR */
+#define arm_format_stlxr(p, size, rs, rn, rt) arm_emit ((p), ((size) << 30) | (0x8 << 24) | (0x0 << 23) | (0x0 << 22) | (0x0 << 21) | ((rs) << 16) | (0x1 << 15) | (0x1f << 10) | ((rn) << 5) | ((rt) << 0))
+
+#define arm_stlxrx(p, rs, rt, rn) arm_format_stlxr ((p), 0x3, (rs), (rn), (rt))
+#define arm_stlxrw(p, rs, rt, rn) arm_format_stlxr ((p), 0x2, (rs), (rn), (rt))
+
+/* Load/Store SIMD&FP */
+
+/* C6.3.285 STR (immediate, SIMD&FP) */
+#define arm_format_strfp_imm(p, size, opc, rt, rn, pimm, scale) arm_emit ((p), ((size) << 30) | (0xf << 26) | (0x1 << 24) | ((opc) << 22) | (arm_encode_pimm12 ((pimm), (scale)) << 10) | ((rn) << 5) | ((rt) << 0))
+
+/* Store double */
+#define arm_strfpx(p, dt, xn, simm) arm_format_strfp_imm ((p), ARMSIZE_X, 0x0, (dt), (xn), (simm), 8)
+/* Store single */
+#define arm_strfpw(p, st, xn, simm) arm_format_strfp_imm ((p), ARMSIZE_W, 0x0, (st), (xn), (simm), 4)
+
+/* C6.3.166 LDR (immediate, SIMD&FP) */
+#define arm_format_ldrfp_imm(p, size, opc, rt, rn, pimm, scale) arm_emit ((p), ((size) << 30) | (0xf << 26) | (0x1 << 24) | ((opc) << 22) | (arm_encode_pimm12 ((pimm), (scale)) << 10) | ((rn) << 5) | ((rt) << 0))
+
+/* Load double */
+#define arm_ldrfpx(p, dt, xn, simm) arm_format_ldrfp_imm ((p), ARMSIZE_X, 0x1, dt, xn, simm, 8)
+/* Load single */
+#define arm_ldrfpw(p, dt, xn, simm) arm_format_ldrfp_imm ((p), ARMSIZE_W, 0x1, dt, xn, simm, 4)
+
+/* Arithmetic (immediate) */
+static G_GNUC_UNUSED inline guint32
+arm_encode_arith_imm (int imm, guint32 *shift)
+{
+       // FIXME:
+       g_assert ((imm >= 0) && (imm < 0xfff));
+       *shift = 0;
+       return (guint32)imm;
+}
+
+// FIXME:
+#define arm_is_arith_imm(imm)  (((imm) >= 0) && ((imm) < 0xfff))
+
+#define arm_format_alu_imm(p, sf, op, S, rd, rn, imm) do { \
+       guint32 _imm12, _shift; \
+       _imm12 = arm_encode_arith_imm ((imm), &_shift); arm_emit ((p), ((sf) << 31) | ((op) << 30) | ((S) << 29) | (0x11 << 24) | ((_shift) << 22) | ((_imm12) << 10) | ((rn) << 5) | ((rd) << 0)); \
+} while (0)
+
+/* rd/rn can be SP for addx/subx */
+#define arm_addx_imm(p, rd, rn, imm) arm_format_alu_imm ((p), 0x1, 0x0, 0x0, (rd), (rn), (imm))
+#define arm_addw_imm(p, rd, rn, imm) arm_format_alu_imm ((p), 0x0, 0x0, 0x0, (rd), (rn), (imm))
+#define arm_addsx_imm(p, rd, rn, imm) arm_format_alu_imm ((p), 0x1, 0x0, 0x1, (rd), (rn), (imm))
+#define arm_addsw_imm(p, rd, rn, imm) arm_format_alu_imm ((p), 0x0, 0x0, 0x1, (rd), (rn), (imm))
+#define arm_subx_imm(p, rd, rn, imm) arm_format_alu_imm ((p), 0x1, 0x1, 0x0, (rd), (rn), (imm))
+#define arm_subw_imm(p, rd, rn, imm) arm_format_alu_imm ((p), 0x0, 0x1, 0x0, (rd), (rn), (imm))
+#define arm_subsx_imm(p, rd, rn, imm) arm_format_alu_imm ((p), 0x1, 0x1, 0x1, (rd), (rn), (imm))
+#define arm_subsw_imm(p, rd, rn, imm) arm_format_alu_imm ((p), 0x0, 0x1, 0x1, (rd), (rn), (imm))
+
+#define arm_cmpx_imm(p, rn, imm) arm_subsx_imm ((p), ARMREG_RZR, (rn), (imm))
+#define arm_cmpw_imm(p, rn, imm) arm_subsw_imm ((p), ARMREG_RZR, (rn), (imm))
+#define arm_cmnx_imm(p, rn, imm) arm_addsx_imm ((p), ARMREG_RZR, (rn), (imm))
+#define arm_cmnw_imm(p, rn, imm) arm_addsw_imm ((p), ARMREG_RZR, (rn), (imm))
+
+/* Logical (immediate) */
+
+// FIXME: imm
+#if 0
+#define arm_format_and(p, sf, opc, rd, rn, imm) arm_emit ((p), ((sf) << 31) | ((opc) << 29) | (0x24 << 23) | ((0) << 22) | ((imm) << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_andx_imm(p, rd, rn, imm) arm_format_and ((p), 0x1, 0x0, (rd), (rn), (imm))
+#define arm_andw_imm(p, rd, rn, imm) arm_format_and ((p), 0x0, 0x0, (rd), (rn), (imm))
+#define arm_andsx_imm(p, rd, rn, imm) arm_format_and ((p), 0x1, 0x3, (rd), (rn), (imm))
+#define arm_andsw_imm(p, rd, rn, imm) arm_format_and ((p), 0x0, 0x3, (rd), (rn), (imm))
+#define arm_eorx_imm(p, rd, rn, imm) arm_format_and ((p), 0x1, 0x2, (rd), (rn), (imm))
+#define arm_eorw_imm(p, rd, rn, imm) arm_format_and ((p), 0x0, 0x2, (rd), (rn), (imm))
+#define arm_orrx_imm(p, rd, rn, imm) arm_format_and ((p), 0x1, 0x1, (rd), (rn), (imm))
+#define arm_orrw_imm(p, rd, rn, imm) arm_format_and ((p), 0x0, 0x1, (rd), (rn), (imm))
+
+#define arm_tstx_imm(p, rn, imm) arm_andsx_imm ((p), ARMREG_RZR, (rn), (imm))
+#define arm_tstw_imm(p, rn, imm) arm_andsw_imm ((p), ARMREG_RZR, (rn), (imm))
+#endif
+
+/* Move (wide immediate) */
+#define arm_format_mov(p, sf, opc, hw, rd, imm16) arm_emit ((p), ((sf) << 31) | ((opc) << 29) | (0x25 << 23) | ((hw) << 21) | (((guint32)(imm16) & 0xffff) << 5) | ((rd) << 0))
+
+#define arm_get_movzx_rd(p) ((*(guint32*)p) & 0x1f)
+
+#define arm_movzx(p, rd, imm, shift) do { g_assert ((shift) % 16 == 0); arm_format_mov ((p), 0x1, 0x2, (shift) / 16, (rd), (imm)); } while (0)
+#define arm_movzw(p, rd, imm, shift) do { g_assert ((shift) % 16 == 0); arm_format_mov ((p), 0x0, 0x2, (shift) / 16, (rd), (imm)); } while (0)
+#define arm_movnx(p, rd, imm, shift) do { g_assert ((shift) % 16 == 0); arm_format_mov ((p), 0x1, 0x0, (shift) / 16, (rd), (imm)); } while (0)
+#define arm_movnw(p, rd, imm, shift) do { g_assert ((shift) % 16 == 0); arm_format_mov ((p), 0x0, 0x0, (shift) / 16, (rd), (imm)); } while (0)
+#define arm_movkx(p, rd, imm, shift) do { g_assert ((shift) % 16 == 0); arm_format_mov ((p), 0x1, 0x3, (shift) / 16, (rd), (imm)); } while (0)
+#define arm_movkw(p, rd, imm, shift) do { g_assert ((shift) % 16 == 0); arm_format_mov ((p), 0x0, 0x3, (shift) / 16, (rd), (imm)); } while (0)
+
+/* PC-relative address calculation */
+#define arm_format_adrp(p, op, rd, target) do { guint64 imm1 = (guint64)(target); guint64 imm2 = (guint64)(p); int _imm = imm1 - imm2; arm_emit ((p), ((op) << 31) | (((_imm) & 0x3) << 29) | (0x10 << 24) | (((_imm >> 2) & 0x7ffff) << 5) | ((rd) << 0)); } while (0)
+
+#define arm_adrpx(p, rd, target) arm_format_adrp ((p), 0x1, (rd), (target))
+#define arm_adrx(p, rd, target) arm_format_adrp ((p), 0x0, (rd), (target))
+
+/* Bitfield move */
+#define arm_format_bfm(p, sf, opc, N, immr, imms, rn, rd) arm_emit ((p), ((sf) << 31) | ((opc) << 29) | (0x26 << 23) | ((N) << 22) | ((N) << 22) | ((immr) << 16) | ((imms) << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_bfmx(p, rd, rn, immr, imms) arm_format_bfm ((p), 0x1, 0x1, 0x1, (immr), (imms), (rn), (rd))
+#define arm_bfmw(p, rd, rn, immr, imms) arm_format_bfm ((p), 0x0, 0x1, 0x0, (immr), (imms), (rn), (rd))
+#define arm_sbfmx(p, rd, rn, immr, imms) arm_format_bfm ((p), 0x1, 0x0, 0x1, (immr), (imms), (rn), (rd))
+#define arm_sbfmw(p, rd, rn, immr, imms) arm_format_bfm ((p), 0x0, 0x0, 0x0, (immr), (imms), (rn), (rd))
+#define arm_ubfmx(p, rd, rn, immr, imms) arm_format_bfm ((p), 0x1, 0x2, 0x1, (immr), (imms), (rn), (rd))
+#define arm_ubfmw(p, rd, rn, immr, imms) arm_format_bfm ((p), 0x0, 0x2, 0x0, (immr), (imms), (rn), (rd))
+
+/* Sign extend and Zero-extend */
+#define arm_sxtbx(p, rd, rn) arm_sbfmx ((p), (rd), (rn), 0, 7)
+#define arm_sxtbw(p, rd, rn) arm_sbfmw ((p), (rd), (rn), 0, 7)
+#define arm_sxthx(p, rd, rn) arm_sbfmx ((p), (rd), (rn), 0, 15)
+#define arm_sxthw(p, rd, rn) arm_sbfmw ((p), (rd), (rn), 0, 15)
+#define arm_sxtwx(p, rd, rn) arm_sbfmx ((p), (rd), (rn), 0, 31)
+#define arm_uxtbx(p, rd, rn) arm_ubfmx ((p), (rd), (rn), 0, 7)
+#define arm_uxtbw(p, rd, rn) arm_ubfmw ((p), (rd), (rn), 0, 7)
+#define arm_uxthx(p, rd, rn) arm_ubfmx ((p), (rd), (rn), 0, 15)
+#define arm_uxthw(p, rd, rn) arm_ubfmw ((p), (rd), (rn), 0, 15)
+
+/* Extract register */
+#define arm_format_extr(p, sf, N, rd, rn, rm, imms) arm_emit ((p), ((sf) << 31) | (0x27 << 23) | ((N) << 22) | (0x0 << 21) | ((rm) << 16) | ((imms) << 10) | ((rn) << 5) | ((rd) << 0))
+#define arm_extrx(p, rd, rn, rm, lsb) arm_format_extr ((p), 0x1, 0x1, (rd), (rn), (rm), (lsb))
+#define arm_extrw(p, rd, rn, rm, lsb) arm_format_extr ((p), 0x0, 0x0, (rd), (rn), (rm), (lsb))
+
+/* Shift (immediate) */
+#define arm_asrx(p, rd, rn, shift) arm_sbfmx ((p), (rd), (rn), (shift), 63)
+#define arm_asrw(p, rd, rn, shift) arm_sbfmw ((p), (rd), (rn), (shift), 31)
+#define arm_lslx(p, rd, rn, shift) arm_ubfmx ((p), (rd), (rn), 64 - ((shift) % 64), 63 - ((shift) % 64))
+#define arm_lslw(p, rd, rn, shift) arm_ubfmw ((p), (rd), (rn), 32 - ((shift) % 32), 31 - ((shift) % 32))
+#define arm_lsrx(p, rd, rn, shift) arm_ubfmx ((p), (rd), (rn), shift, 63)
+#define arm_lsrw(p, rd, rn, shift) arm_ubfmw ((p), (rd), (rn), shift, 31)
+#define arm_rorx(p, rd, rs, shift) arm_extrx ((p), (rd), (rs), (rs), (shift))
+#define arm_rorw(p, rd, rs, shift) arm_extrw ((p), (rd), (rs), (rs), (shift))
+
+/* Arithmetic (shifted register) */
+#define arm_format_alu_shift(p, sf, op, S, rd, rn, rm, shift, imm6) arm_emit ((p), ((sf) << 31) | ((op) << 30) | ((S) << 29) | (0xb << 24) | ((shift) << 22) | (0x0 << 21) | ((rm) << 16) | ((imm6) << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_addx_shift(p, rd, rn, rm, shift_type, amount) arm_format_alu_shift ((p), 0x1, 0x0, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_addw_shift(p, rd, rn, rm, shift_type, amount) arm_format_alu_shift ((p), 0x0, 0x0, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_addsx_shift(p, rd, rn, rm, shift_type, amount) arm_format_alu_shift ((p), 0x1, 0x0, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_addsw_shift(p, rd, rn, rm, shift_type, amount) arm_format_alu_shift ((p), 0x0, 0x0, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_subx_shift(p, rd, rn, rm, shift_type, amount) arm_format_alu_shift ((p), 0x1, 0x1, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_subw_shift(p, rd, rn, rm, shift_type, amount) arm_format_alu_shift ((p), 0x0, 0x1, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_subsx_shift(p, rd, rn, rm, shift_type, amount) arm_format_alu_shift ((p), 0x1, 0x1, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_subsw_shift(p, rd, rn, rm, shift_type, amount) arm_format_alu_shift ((p), 0x0, 0x1, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_cmnx_shift(p, rn, rm, shift_type, amount) arm_addsx_shift ((p), ARMREG_RZR, (rn), (rm), (shift_type), (amount))
+#define arm_cmnw_shift(p, rn, rm, shift_type, amount) arm_addsw_shift ((p), ARMREG_RZR, (rn), (rm), (shift_type), (amount))
+#define arm_cmpx_shift(p, rn, rm, shift_type, amount) arm_subsx_shift ((p), ARMREG_RZR, (rn), (rm), (shift_type), (amount))
+#define arm_cmpw_shift(p, rn, rm, shift_type, amount) arm_subsw_shift ((p), ARMREG_RZR, (rn), (rm), (shift_type), (amount))
+#define arm_negx_shift(p, rd, rm, shift_type, amount) arm_subx_shift ((p), (rd), ARMREG_RZR, (rm), (shift_type), (amount))
+#define arm_negw_shift(p, rd, rm, shift_type, amount) arm_subw_shift ((p), (rd), ARMREG_RZR, (rm), (shift_type), (amount))
+#define arm_negsx_shift(p, rd, rm, shift_type, amount) arm_subsx_shift ((p), (rd), ARMREG_RZR, (rm), (shift_type), (amount))
+#define arm_negsw_shift(p, rd, rm, shift_type, amount) arm_subsw_shift ((p), (rd), ARMREG_RZR, (rm), (shift_type), (amount))
+
+#define arm_addx(p, rd, rn, rm) arm_addx_shift ((p), (rd), (rn), (rm), 0, 0)
+#define arm_addw(p, rd, rn, rm) arm_addw_shift ((p), (rd), (rn), (rm), 0, 0)
+#define arm_subx(p, rd, rn, rm) arm_subx_shift ((p), (rd), (rn), (rm), 0, 0)
+#define arm_subw(p, rd, rn, rm) arm_subw_shift ((p), (rd), (rn), (rm), 0, 0)
+#define arm_addsx(p, rd, rn, rm) arm_addsx_shift ((p), (rd), (rn), (rm), 0, 0)
+#define arm_addsw(p, rd, rn, rm) arm_addsw_shift ((p), (rd), (rn), (rm), 0, 0)
+#define arm_subsx(p, rd, rn, rm) arm_subsx_shift ((p), (rd), (rn), (rm), 0, 0)
+#define arm_subsw(p, rd, rn, rm) arm_subsw_shift ((p), (rd), (rn), (rm), 0, 0)
+#define arm_cmpx(p, rd, rn) arm_cmpx_shift ((p), (rd), (rn), 0, 0)
+#define arm_cmpw(p, rd, rn) arm_cmpw_shift ((p), (rd), (rn), 0, 0)
+#define arm_negx(p, rd, rn) arm_negx_shift ((p), (rd), (rn), 0, 0)
+#define arm_negw(p, rd, rn) arm_negw_shift ((p), (rd), (rn), 0, 0)
+
+/* Arithmetic with carry */
+#define arm_format_adc(p, sf, op, S, rd, rn, rm) arm_emit ((p), ((sf) << 31) | ((op) << 30) | ((S) << 29) | (0xd0 << 21) | ((rm) << 16) | (0x0 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_adcx(p, rd, rn, rm) arm_format_adc ((p), 0x1, 0x0, 0x0, (rd), (rn), (rm))
+#define arm_adcw(p, rd, rn, rm) arm_format_adc ((p), 0x0, 0x0, 0x0, (rd), (rn), (rm))
+#define arm_adcsx(p, rd, rn, rm) arm_format_adc ((p), 0x1, 0x0, 0x1, (rd), (rn), (rm))
+#define arm_adcsw(p, rd, rn, rm) arm_format_adc ((p), 0x0, 0x0, 0x1, (rd), (rn), (rm))
+#define arm_sbcx(p, rd, rn, rm) arm_format_adc ((p), 0x1, 0x1, 0x0, (rd), (rn), (rm))
+#define arm_sbcw(p, rd, rn, rm) arm_format_adc ((p), 0x0, 0x1, 0x0, (rd), (rn), (rm))
+#define arm_sbcsx(p, rd, rn, rm) arm_format_adc ((p), 0x1, 0x1, 0x1, (rd), (rn), (rm))
+#define arm_sbcsw(p, rd, rn, rm) arm_format_adc ((p), 0x0, 0x1, 0x1, (rd), (rn), (rm))
+#define arm_ngcx(p, rd, rm) arm_sbcx ((p), (rd), ARMREG_RZR, (rm))
+#define arm_ngcw(p, rd, rm) arm_sbcw ((p), (rd), ARMREG_RZR, (rm))
+#define arm_ngcsx(p, rd, rm) arm_sbcsx ((p), (rd), ARMREG_RZR, (rm))
+#define arm_ngcsw(p, rd, rm) arm_sbcsw ((p), (rd), ARMREG_RZR, (rm))
+
+/* Logical (shifted register) */
+#define arm_format_logical_shift(p, sf, op, N, rd, rn, rm, shift, imm6) arm_emit ((p), ((sf) << 31) | ((op) << 29) | (0xa << 24) | ((shift) << 22) | ((N) << 21) | ((rm) << 16) | ((imm6) << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_andx_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x1, 0x0, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_andw_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x0, 0x0, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_andsx_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x1, 0x3, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_andsw_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x0, 0x3, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_bicx_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x1, 0x0, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_bicw_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x0, 0x0, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_bicsx_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x1, 0x3, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_bicsw_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x0, 0x3, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_eonx_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x1, 0x2, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_eonw_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x0, 0x2, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_eorx_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x1, 0x2, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_eorw_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x0, 0x2, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_orrx_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x1, 0x1, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_orrw_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x0, 0x1, 0x0, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_ornx_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x1, 0x1, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_ornw_shift(p, rd, rn, rm, shift_type, amount) arm_format_logical_shift ((p), 0x0, 0x1, 0x1, (rd), (rn), (rm), (shift_type), (amount))
+#define arm_mvnx_shift(p, rd, rm, shift_type, amount) arm_ornx_shift ((p), (rd), ARMREG_RZR, (rm), (shift_type), (amount))
+#define arm_mvnw_shift(p, rd, rm, shift_type, amount) arm_ornw_shift ((p), (rd), ARMREG_RZR, (rm), (shift_type), (amount))
+#define arm_tstx_shift(p, rn, rm, shift_type, amount) arm_andsx_shift ((p), ARMREG_RZR, (rn), (rm), (shift_type), (amount))
+#define arm_tstw_shift(p, rn, rm, shift_type, amount) arm_andsw_shift ((p), ARMREG_RZR, (rn), (rm), (shift_type), (amount))
+/* Aliases */
+#define arm_andx(p, rd, rn, rm) arm_andx_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_andw(p, rd, rn, rm) arm_andw_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_andsx(p, rd, rn, rm) arm_andsx_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_andsw(p, rd, rn, rm) arm_andsw_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_bixx(p, rd, rn, rm) arm_bixx_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_bixw(p, rd, rn, rm) arm_bixw_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_bixsx(p, rd, rn, rm) arm_bixsx_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_bixsw(p, rd, rn, rm) arm_bixsw_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_eonx(p, rd, rn, rm) arm_eonx_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_eonw(p, rd, rn, rm) arm_eonw_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_eorx(p, rd, rn, rm) arm_eorx_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_eorw(p, rd, rn, rm) arm_eorw_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_orrx(p, rd, rn, rm) arm_orrx_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_orrw(p, rd, rn, rm) arm_orrw_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_ornx(p, rd, rn, rm) arm_ornx_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_ornw(p, rd, rn, rm) arm_ornw_shift(p, rd, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_mvnx(p, rd, rm) arm_mvnx_shift(p, rd, rm, ARMSHIFT_LSL, 0)
+#define arm_mvnw(p, rd, rm) arm_mvnw_shift(p, rd, rm, ARMSHIFT_LSL, 0)
+#define arm_tstx(p, rn, rm) arm_tstx_shift(p, rn, rm, ARMSHIFT_LSL, 0)
+#define arm_tstw(p, rn, rm) arm_tstw_shift(p, rn, rm, ARMSHIFT_LSL, 0)
+
+/* Move (register) */
+#define arm_movx(p, rn, rm) arm_orrx_shift ((p), (rn), ARMREG_RZR, (rm), ARMSHIFT_LSL, 0)
+#define arm_movw(p, rn, rm) arm_orrw_shift ((p), (rn), ARMREG_RZR, (rm), ARMSHIFT_LSL, 0)
+
+/* Not an official alias */
+#define arm_movspx(p, rn, rm) arm_addx_imm ((p), (rn), (rm), 0)
+
+/* Shift (register) */
+#define arm_format_shift_reg(p, sf, op2, rd, rn, rm) arm_emit ((p), ((sf) << 31) | (0xd6 << 21) | ((rm) << 16) | (0x2 << 12) | ((op2) << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_asrvx(p, rd, rn, rm) arm_format_shift_reg ((p), 0x1, 0x2, (rd), (rn), (rm))
+#define arm_asrvw(p, rd, rn, rm) arm_format_shift_reg ((p), 0x0, 0x2, (rd), (rn), (rm))
+#define arm_lslvx(p, rd, rn, rm) arm_format_shift_reg ((p), 0x1, 0x0, (rd), (rn), (rm))
+#define arm_lslvw(p, rd, rn, rm) arm_format_shift_reg ((p), 0x0, 0x0, (rd), (rn), (rm))
+#define arm_lsrvx(p, rd, rn, rm) arm_format_shift_reg ((p), 0x1, 0x1, (rd), (rn), (rm))
+#define arm_lsrvw(p, rd, rn, rm) arm_format_shift_reg ((p), 0x0, 0x1, (rd), (rn), (rm))
+#define arm_rorvx(p, rd, rn, rm) arm_format_shift_reg ((p), 0x1, 0x3, (rd), (rn), (rm))
+#define arm_rorvw(p, rd, rn, rm) arm_format_shift_reg ((p), 0x0, 0x3, (rd), (rn), (rm))
+
+/* Multiply */
+#define arm_format_mul(p, sf, o0, rd, rn, rm, ra) arm_emit ((p), ((sf) << 31) | (0x0 << 29) | (0x1b << 24) | (0x0 << 21) | ((rm) << 16) | ((o0) << 15) | ((ra) << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_maddx(p, rd, rn, rm, ra) arm_format_mul((p), 0x1, 0x0, (rd), (rn), (rm), (ra))
+#define arm_maddw(p, rd, rn, rm, ra) arm_format_mul((p), 0x0, 0x0, (rd), (rn), (rm), (ra))
+#define arm_msubx(p, rd, rn, rm, ra) arm_format_mul((p), 0x1, 0x1, (rd), (rn), (rm), (ra))
+#define arm_msubw(p, rd, rn, rm, ra) arm_format_mul((p), 0x0, 0x1, (rd), (rn), (rm), (ra))
+#define arm_mnegx(p, rd, rn, rm) arm_msubx ((p), (rd), (rn), (rm), ARMREG_RZR)
+#define arm_mnegw(p, rd, rn, rm) arm_msubw ((p), (rd), (rn), (rm), ARMREG_RZR)
+#define arm_mulx(p, rd, rn, rm) arm_maddx ((p), (rd), (rn), (rm), ARMREG_RZR)
+#define arm_mulw(p, rd, rn, rm) arm_maddw ((p), (rd), (rn), (rm), ARMREG_RZR)
+
+/* FIXME: Missing multiple opcodes */
+
+/* Division */
+#define arm_format_div(p, sf, o1, rd, rn, rm) arm_emit ((p), ((sf) << 31) | (0xd6 << 21) | ((rm) << 16) | (0x1 << 11) | ((o1) << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_sdivx(p, rd, rn, rm) arm_format_div ((p), 0x1, 0x1, (rd), (rn), (rm))
+#define arm_sdivw(p, rd, rn, rm) arm_format_div ((p), 0x0, 0x1, (rd), (rn), (rm))
+#define arm_udivx(p, rd, rn, rm) arm_format_div ((p), 0x1, 0x0, (rd), (rn), (rm))
+#define arm_udivw(p, rd, rn, rm) arm_format_div ((p), 0x0, 0x0, (rd), (rn), (rm))
+
+/* Conditional select */
+#define arm_format_csel(p, sf, op, op2, cond, rd, rn, rm) arm_emit ((p), ((sf) << 31) | ((op) << 30) | (0xd4 << 21) | ((rm) << 16) | ((cond) << 12) | ((op2) << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_cselx(p, cond, rd, rn, rm) arm_format_csel ((p), 0x1, 0x0, 0x0, (cond), (rd), (rn), (rm))
+#define arm_cselw(p, cond, rd, rn, rm) arm_format_csel ((p), 0x0, 0x0, 0x0, (cond), (rd), (rn), (rm))
+#define arm_csincx(p, cond, rd, rn, rm) arm_format_csel ((p), 0x1, 0x0, 0x1, (cond), (rd), (rn), (rm))
+#define arm_csincw(p, cond, rd, rn, rm) arm_format_csel ((p), 0x0, 0x0, 0x1, (cond), (rd), (rn), (rm))
+#define arm_csinvx(p, cond, rd, rn, rm) arm_format_csel ((p), 0x1, 0x1, 0x0, (cond), (rd), (rn), (rm))
+#define arm_csinvw(p, cond, rd, rn, rm) arm_format_csel ((p), 0x0, 0x1, 0x0, (cond), (rd), (rn), (rm))
+#define arm_csnegx(p, cond, rd, rn, rm) arm_format_csel ((p), 0x1, 0x1, 0x1, (cond), (rd), (rn), (rm))
+#define arm_csnegw(p, cond, rd, rn, rm) arm_format_csel ((p), 0x0, 0x1, 0x1, (cond), (rd), (rn), (rm))
+
+#define arm_cset(p, cond, rd) arm_csincx ((p), ((cond) ^ 0x1), (rd), ARMREG_RZR, ARMREG_RZR)
+
+/* C5.6.68 (HINT) */
+#define arm_hint(p, imm) arm_emit ((p), (0xd5032 << 12) | ((imm) << 5) | (0x1f << 0))
+#define arm_nop(p) arm_hint ((p), 0x0)
+
+/* C5.6.29 BRK */
+#define arm_brk(p, imm) arm_emit ((p), (0xd4 << 24) | (0x1 << 21) | ((imm) << 5))
+
+/* C6.3.114 FMOV (General) */
+#define arm_format_fmov_gr(p, sf, type, rmode, opcode, rn, rd) arm_emit ((p), ((sf) << 31) | (0x1e << 24) | ((type) << 22) | (0x1 << 21) | ((rmode) << 19) | ((opcode) << 16) | ((rn) << 5) | ((rd) << 0))
+
+/* Move gr->vfp */
+#define arm_fmov_rx_to_double(p, dd, xn) arm_format_fmov_gr ((p), 0x1, 0x1, 0x0, 0x7, (xn), (dd))
+
+/* Move vfp->gr */
+#define arm_fmov_double_to_rx(p, xd, dn) arm_format_fmov_gr ((p), 0x1, 0x1, 0x0, 0x6, (dn), (xd))
+
+/* C6.3.113 FMOV (register) */
+#define arm_format_fmov(p, type, rn, rd) arm_emit ((p), (0x1e << 24) | ((type) << 22) | (0x1 << 21) | (0x10 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_fmovd(p, dd, dn) arm_format_fmov ((p), 0x1, (dn), (dd))
+#define arm_fmovs(p, dd, dn) arm_format_fmov ((p), 0x0, (dn), (dd))
+
+/* C6.3.54 FCMP */
+#define arm_format_fcmp(p, type, opc, rn, rm) arm_emit ((p), (0x1e << 24) | ((type) << 22) | (0x1 << 21) | ((rm) << 16) | (0x8 << 10) | ((rn) << 5) | ((opc) << 3))
+
+#define arm_fcmpd(p, dn, dm) arm_format_fcmp (p, 0x1, 0x0, (dn), (dm))
+#define arm_fcmps(p, dn, dm) arm_format_fcmp (p, 0x0, 0x0, (dn), (dm))
+
+/* Float precision */
+#define arm_format_fcvt(p, type, opc, rn, rd) arm_emit ((p), (0x1e << 24) | ((type) << 22) | (0x1 << 21) | (0x1 << 17) | ((opc) << 15) | (0x10 << 10) | ((rn) << 5) | ((rd) << 0))
+
+/* C6.3.57 FCVT */
+/* single->double */
+#define arm_fcvt_sd(p, dd, sn) arm_format_fcvt ((p), 0x0, 0x1, (sn), (dd))
+/* double->single */
+#define arm_fcvt_ds(p, sd, dn) arm_format_fcvt ((p), 0x1, 0x0, (dn), (sd))
+
+/* Float conversion to integer conversion */
+#define arm_format_fcvtz(p, sf, type, rmode, opcode, rn, rd) arm_emit ((p), ((sf) << 31) | (0x1e << 24) | ((type) << 22) | (0x1 << 21) | ((rmode) << 19) | ((opcode) << 16) | ((rn) << 5) | ((rd) << 0))
+
+/* C6.3.80 FCVTZS (scalar, integer) */
+#define arm_fcvtzs_dw(p, rd, rn) arm_format_fcvtz ((p), 0x0, 0x1, 0x3, 0x0, (rn), (rd))
+#define arm_fcvtzs_dx(p, rd, rn) arm_format_fcvtz ((p), 0x1, 0x1, 0x3, 0x0, (rn), (rd))
+#define arm_fcvtzs_sw(p, rd, rn) arm_format_fcvtz ((p), 0x0, 0x0, 0x3, 0x0, (rn), (rd))
+#define arm_fcvtzs_sx(p, rd, rn) arm_format_fcvtz ((p), 0x1, 0x0, 0x3, 0x0, (rn), (rd))
+
+/* C6.3.84 FCVTZU (scalar, integer) */
+#define arm_fcvtzu_dw(p, rd, rn) arm_format_fcvtz ((p), 0x0, 0x1, 0x3, 0x1, (rn), (rd))
+#define arm_fcvtzu_dx(p, rd, rn) arm_format_fcvtz ((p), 0x1, 0x1, 0x3, 0x1, (rn), (rd))
+#define arm_fcvtzu_sw(p, rd, rn) arm_format_fcvtz ((p), 0x0, 0x0, 0x3, 0x1, (rn), (rd))
+#define arm_fcvtzu_sx(p, rd, rn) arm_format_fcvtz ((p), 0x1, 0x0, 0x3, 0x1, (rn), (rd))
+
+/* C6.3.208 SCVTF (vector, integer) */
+#define arm_format_scvtf_vector(p, sz, rn, rd) arm_emit ((p), (0x1 << 30) | (0x0 << 29) | (0x1e << 24) | ((sz) << 22) | (0x10 << 17) | (0x1d << 12) | (0x2 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_scvtf_d(p, dd, dn) arm_format_scvtf_vector ((p), 0x1, (dn), (dd))
+#define arm_scvtf_s(p, sd, sn) arm_format_scvtf_vector ((p), 0x0, (sn), (sd))
+
+/* C6.3.210 SCVTF (scalar, integer) */
+#define arm_format_scvtf_scalar(p, sf, type, rn, rd) arm_emit ((p), ((sf) << 31) | (0x1e << 24) | ((type) << 22) | (0x1 << 21) | (0x2 << 16) | (0x0 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_scvtf_rx_to_d(p, dd, rn) arm_format_scvtf_scalar ((p), 0x1, 0x1, rn, dd)
+#define arm_scvtf_rw_to_d(p, dd, rn) arm_format_scvtf_scalar ((p), 0x0, 0x1, rn, dd)
+#define arm_scvtf_rx_to_s(p, dd, rn) arm_format_scvtf_scalar ((p), 0x1, 0x0, rn, dd)
+#define arm_scvtf_rw_to_s(p, dd, rn) arm_format_scvtf_scalar ((p), 0x0, 0x0, rn, dd)
+
+/* C6.3.306 UCVTF (vector, integer) */
+#define arm_format_ucvtf_vector(p, sz, rn, rd) arm_emit ((p), (0x1 << 30) | (0x1 << 29) | (0x1e << 24) | ((sz) << 22) | (0x10 << 17) | (0x1d << 12) | (0x2 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_ucvtf_d(p, dd, dn) arm_format_ucvtf_vector ((p), 0x1, (dn), (dd))
+#define arm_ucvtf_s(p, sd, sn) arm_format_ucvtf_vector ((p), 0x0, (sn), (sd))
+
+/* C6.3.308 UCVTF (scalar, integer) */
+#define arm_format_ucvtf_scalar(p, sf, type, rn, rd) arm_emit ((p), ((sf) << 31) | (0x1e << 24) | ((type) << 22) | (0x1 << 21) | (0x3 << 16) | (0x0 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_ucvtf_rx_to_d(p, dd, rn) arm_format_ucvtf_scalar ((p), 0x1, 0x1, rn, dd)
+#define arm_ucvtf_rw_to_d(p, dd, rn) arm_format_ucvtf_scalar ((p), 0x0, 0x1, rn, dd)
+
+/* C6.3.41 FADD (scalar) */
+#define arm_format_fadd_scalar(p, type, rd, rn, rm) arm_emit ((p), (0x1e << 24) | ((type) << 22) | (0x1 << 21) | ((rm) << 16) | (0x1 << 13) | (0x2 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_fadd_d(p, rd, rn, rm) arm_format_fadd_scalar ((p), 0x1, (rd), (rn), (rm))
+#define arm_fadd_s(p, rd, rn, rm) arm_format_fadd_scalar ((p), 0x0, (rd), (rn), (rm))
+
+/* C6.3.149 FSUB (scalar) */
+#define arm_format_fsub_scalar(p, type, rd, rn, rm) arm_emit ((p), (0x1e << 24) | ((type) << 22) | (0x1 << 21) | ((rm) << 16) | (0x1 << 13) | (0x1 << 12) | (0x2 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_fsub_d(p, rd, rn, rm) arm_format_fsub_scalar ((p), 0x1, (rd), (rn), (rm))
+#define arm_fsub_s(p, rd, rn, rm) arm_format_fsub_scalar ((p), 0x0, (rd), (rn), (rm))
+
+/* C6.3.119 FMUL (scalar) */
+#define arm_format_fmul_scalar(p, type, rd, rn, rm) arm_emit ((p), (0x1e << 24) | ((type) << 22) | (0x1 << 21) | ((rm) << 16) | (0x2 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_fmul_d(p, rd, rn, rm) arm_format_fmul_scalar ((p), 0x1, (rd), (rn), (rm))
+#define arm_fmul_s(p, rd, rn, rm) arm_format_fmul_scalar ((p), 0x0, (rd), (rn), (rm))
+
+/* C6.3.86 FDIV (scalar) */
+#define arm_format_fdiv_scalar(p, type, rd, rn, rm) arm_emit ((p), (0x1e << 24) | ((type) << 22) | (0x1 << 21) | ((rm) << 16) | (0x1 << 12) | (0x2 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_fdiv_d(p, rd, rn, rm) arm_format_fdiv_scalar ((p), 0x1, (rd), (rn), (rm))
+#define arm_fdiv_s(p, rd, rn, rm) arm_format_fdiv_scalar ((p), 0x0, (rd), (rn), (rm))
+
+/* C6.3.116 FMSUB */
+#define arm_format_fmsub(p, type, rd, rn, rm, ra) arm_emit ((p), (0x1f << 24) | ((type) << 22) | (0x0 << 21) | ((rm) << 16) | (0x1 << 15) | ((ra) << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_fmsub_d(p, rd, rn, rm, ra) arm_format_fmsub ((p), 0x1, (rd), (rn), (rm), (ra))
+
+/* C6.3.123 FNEG */
+#define arm_format_fneg(p, type, rd, rn) arm_emit ((p), (0x1e << 24) | ((type) << 22) | (0x1 << 21) | (0x2 << 15) | (0x10 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_fneg_d(p, rd, rn) arm_format_fneg ((p), 0x1, (rd), (rn))
+#define arm_fneg_s(p, rd, rn) arm_format_fneg ((p), 0x0, (rd), (rn))
+
+/* C6.3.37 FABS (scalar) */
+#define arm_format_fabs(p, type, opc, rd, rn) arm_emit ((p), (0x1e << 24) | ((type) << 22) | (0x1 << 21) | ((opc) << 15) | (0x10 << 10) | ((rn) << 5) | ((rd) << 0))
+
+#define arm_fabs_d(p, rd, rn) arm_format_fabs ((p), 0x1, 0x1, (rd), (rn))
+
+/* C5.6.60 DMB */
+#define arm_format_dmb(p, opc, CRm) arm_emit ((p), (0x354 << 22) | (0x3 << 16) | (0x3 << 12) | ((CRm) << 8) | (0x1 << 7) | ((opc) << 5) | (0x1f << 0))
+
+#define ARM_DMB_LD 0x1
+#define ARM_DMB_ST 0x2
+#define ARM_DMB_ALL 0x3
+#define ARM_DMB_SY 0xc
+
+#define arm_dmb(p, imm) arm_format_dmb ((p), 0x1, (imm))
+
+/* C5.6.129 MRS */
+
+#define ARM_MRS_REG_TPIDR_EL0 0x5e82
+
+#define arm_format_mrs(p, sysreg, rt) arm_emit ((p), (0x354 << 22) | (0x1 << 21) | (0x1 << 20) | ((sysreg) << 5) | ((rt) << 0))
+
+#define arm_mrs(p, rt, sysreg) arm_format_mrs ((p), (sysreg), (rt))
+
+#endif /* __arm_CODEGEN_H__ */
index 1dbd1c6e279d40613c8d7ccf9eb3ea0664528993..c579c88a9b3a990a26afc0edaeac0c2da8693417 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2004 Novell, Inc
  * Author: Paolo Molaro (lupus@ximian.com)
  *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /* registers */
index d4d25a254f980587bae505a5fd4deefa6d6a4749..869365b4bccd9b3d93d99dd1184dfbc049253d8f 100644 (file)
@@ -8,6 +8,7 @@
    Copyright (C)  2007-2008 Andreas Faerber
 
    for testing do the following: ./test | as -o test.o
+   Licensed under the MIT license. See LICENSE file in the project root for full license information.
 */
 
 #ifndef __MONO_PPC_CODEGEN_H__
index 4c3cd243520ea41e3330a8f5bb811b8bd03ff736..97db6ce6eb9a711c5a3da86e2c7c668630d85594 100644 (file)
@@ -1,5 +1,6 @@
 /*
    Copyright (C)  2001 Radek Doulik
+   * Licensed under the MIT license. See LICENSE file in the project root for full license information.
 */
 
 #ifndef S390X_H
index ff3fe325a791983f0d28784154b7149543e877bd..6c9d63f37e991fc8cbaeedf8ce4fd635695253c3 100644 (file)
@@ -10,6 +10,7 @@
  * 
  * Copyright (C)  2000 Intel Corporation.  All rights reserved.
  * Copyright (C)  2001, 2002 Ximian, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef X86_H
index 3d6cd252366431fc9f6cb255f0aba34499c556c0..eb0f168850aefc9a73ace127cef519640ae8c284 100755 (executable)
@@ -6,6 +6,7 @@
  *     Sebastien Pouliot  <sebastien@ximian.com>
  *
  * Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <glib.h>
index fd9a5cb36155c7108d6c49e6aed09948e711ff3c..a0e621f7cb0b47e6adfb71e310cd19b1fecd8295 100644 (file)
@@ -6,6 +6,7 @@
  *     Sebastien Pouliot  <sebastien@ximian.com>
  *
  * Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONODIS_DECLSEC_H__
index 24df084d6e39865c3f8aaafcbd5a3467fd9cadae..f3724e4384debca76a5eae810a91e4dc8333e278 100755 (executable)
@@ -6,6 +6,7 @@
  *
  * (C) 2001 Ximian, Inc.
  * Copyright 2012 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <stdio.h>
index d8f6f8558fa8d30927b50760ab82e6715e09d60c..d1b85c5509abb7c864ff51ac4b92202f38dc5475 100644 (file)
@@ -11,6 +11,7 @@
  *   Structs are not being labeled as `valuetype' classes
  *   
  *   How are fields with literals mapped to constants?
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <stdio.h>
index 3cb0a73d5785d8941318152625124b807ee374c8..f31d6cbfb4e1d984b52e866c5c3b5970c370d112 100644 (file)
@@ -6,6 +6,7 @@
  *
  * (C) 2002-2011 Novell, Inc.
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 8838c304e9c35577a0eaed9f9bf4f12c79adcdab..282cbe93a29b8e6f60923db0fafba329529ac924 100644 (file)
@@ -6,6 +6,7 @@
  *     Dick Porter (dick@ximian.com)
  *
  * Copyright (c) 2006 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 8beb367f2e638097cd9f3c6d1c5817b49f1fadc7..d7e9dba666dcfe3bfdb97774be8a0a9d5e994c21 100644 (file)
@@ -6,6 +6,7 @@
  *     Dick Porter (dick@ximian.com)
  *
  * Copyright (C) 2006 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef _WAPI_IO_PORTABILITY_H_
index fad582754fda1e8d96a76f40d0718df6a1fc91f4..9af4b1f0a11f0c4d65152b1b5ab7eccdc75b3168 100644 (file)
@@ -6,6 +6,7 @@
  *
  * (C) 2002 Ximian, Inc.
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef _WAPI_IO_PRIVATE_H_
index 51f60f453343b5bb14bd6848ba3580ec1f533cf4..f67ff65f842d42f6ab847bf40d867d4f49dce97c 100644 (file)
@@ -5,6 +5,7 @@
  *  Marek Habersack <grendel@twistedcode.net>
  *
  * Copyright 2016 Xamarin, Inc (http://xamarin.com/)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __IO_TRACE_H
index b751134d7045aa6a2cae4e3fc3ba186fedbd66c1..11b5f8f2fbbe28fe37584da260d8c405f8b7953a 100644 (file)
@@ -7,6 +7,7 @@
  * (C) 2002 Ximian, Inc.
  * Copyright (c) 2002-2006 Novell, Inc.
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 305c0ab48527cb7fd053c050a04041e7c1d7b10c..c014a2d3dc4f983c19f4b70dcb878fa47ef0f751 100644 (file)
@@ -6,6 +6,7 @@
  *
  * (C) 2002 Ximian, Inc.
  * Copyright (c) 2002-2009 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <stdio.h>
index 3cd41f67fe33d045e7d9ede7e033f40b35b407f9..2856d4fcd615cf7dbb973f27830bc391c66255df 100644 (file)
@@ -7,6 +7,7 @@
  * (C) 2002 Ximian, Inc.
  * Copyright (c) 2002-2009 Novell, Inc.
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index d54f84bd3242abb26c69473631f355fb4d1f5512..7e46c31ba3e1564a9323022f9a0e3542b5f71fca 100644 (file)
@@ -6,6 +6,7 @@
  *
  * (C) 2002-2011 Novell, Inc.
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index bb65b5f799cd44f8279b4419777e5a16210f6aa9..304fd35adf807e349c77529ee2813686d0e6553a 100644 (file)
@@ -7,6 +7,7 @@
  * (C) 2002-2006 Ximian, Inc.
  * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index cb0fb34bf953e559f4d66acea259b39b407cfc1a..3f61191b3146cbdf38a3cac5aabd935bc63152ae 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2014 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_METADATA_ABI_DETAILS_H__
 #define __MONO_METADATA_ABI_DETAILS_H__
index 6ffc0a3f2af47ac0276940aa3295cee7b9713751..93169cda59d4ba1ac7fb1a526b6a1b9a352bd489 100644 (file)
@@ -9,6 +9,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2012 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #undef ASSEMBLY_LOAD_DEBUG
 #include <config.h>
@@ -257,7 +258,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 +1766,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 +1781,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 +1824,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 +1843,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 +2146,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 +2170,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 +2519,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 275bcbb234309c1498d30ac3a283022c84b8a951..9bc8b09e27056ca7c5aeb23a0dc1453cb15c3db0 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <stdio.h>
index 45c3da535940aa408e9d54d699273f3e94370fbf..9e54462633cf92da422cb9e8d06a9783b4dae022 100644 (file)
@@ -5,6 +5,7 @@
  *   Zoltan Varga (vargaz@gmail.com)
  *
  * Copyright 2007-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 4834da608e17f422aecf9019bbda97c569fc1bcb..43844ad98304cfed42194dc622df44a161fe27ab 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index c8323fbe935a51f5649a502b17580f71472f8934..b86e7eda40ec5240dd839081662c19c752f968e6 100644 (file)
@@ -1,5 +1,6 @@
 /* 
  * Copyright 2012 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_METADATA_CLASS_INTERNALS_H__
 #define __MONO_METADATA_CLASS_INTERNALS_H__
@@ -517,7 +518,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 +918,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 +939,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 +1009,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);
index d264ea32ba65bb24b09f9e54628227e7023f5d0f..f7b36279f4af17942f00dd9af24aea8a7ba2e9b3 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #ifdef HAVE_ALLOCA_H
@@ -1480,6 +1481,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 +1557,7 @@ mono_class_setup_fields (MonoClass *klass)
                }
        }
 
-       klass->instance_size = 0;
+       instance_size = 0;
        if (!klass->rank)
                klass->sizes.class_size = 0;
 
@@ -1569,13 +1571,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 +1599,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 +1722,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 +1808,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 +1821,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 +1902,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 +1977,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 +2066,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 +2085,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 +3802,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 +3853,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 +7458,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 +7508,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 +8338,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 +8372,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 +8391,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 +8787,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 +8869,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 fdca4871eebf02a17fed1a5501040909cdd56a28..54ee88204637c491d83ec9e7207404bba1aab863 100644 (file)
@@ -5,6 +5,7 @@
  *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
  *
  * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef _MONO_METADATA_CONSOLEIO_H
index 7c778bfacd14e66a927884e720d07a7d9bcd315f..b8367e888f7b851970cb4f7a2668558db116b90c 100644 (file)
@@ -5,6 +5,7 @@
  *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
  *
  * Copyright (C) 2005-2009 Novell, Inc. (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <mono/metadata/appdomain.h>
index fe59f700ea987d7a621daff20544b7808ec62acd..5c46a85a9419339be30cb6df72122ac618d40ecc 100644 (file)
@@ -5,6 +5,7 @@
  *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
  *
  * Copyright (C) 2005-2009 Novell, Inc. (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #if defined(__native_client__)
 #include "console-null.c"
@@ -254,7 +255,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 ff703808c3d9587a3cb6e7ed4a19b919e4cd1139..c7c8c49017b6182ee292e7d2d9fc373621384b22 100644 (file)
@@ -5,6 +5,7 @@
  *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
  *
  * Copyright (C) 2005-2009 Novell, Inc. (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index c2e47b9ca7b479a3a076a8db7c2f1694b2ac5212..326251cc140c53a575ff7e227abcdeea92bc2782 100644 (file)
@@ -5,6 +5,7 @@
  *   Kornel Pal <http://www.kornelpal.hu/>
  *
  * Copyright (C) 2008 Kornel Pal
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index a9c6a7cb76a750902db71952d766bb7a42aa15f8..ade821af5e316c1830aabb6e9096bf58a6179682 100644 (file)
@@ -5,6 +5,7 @@
  *   Kornel Pal <http://www.kornelpal.hu/>
  *
  * Copyright (C) 2008 Kornel Pal
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_COREE_H__
index 2553361c14db27d1af028b583ffbf1848b13c6a6..baf79f6be9709502aa442df5fe76f9570e73719a 100644 (file)
@@ -5,6 +5,7 @@
  *     Mono Project (http://www.mono-project.com)
  *
  * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <string.h>
index fcbfd9d817f06daf4acc5c25b57d23c1923237e6..e6d9cc95e2f578977f80362f5ce971b5ef15c42e 100644 (file)
@@ -7,6 +7,7 @@
  *     Mono Project (http://www.mono-project.com)
  *
  * Copyright 2015 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index e23b279cd94007bf047878082857aaa09e0da49c..decf5e8d04bdf27eff3b5d5f887f9f8644b049f6 100644 (file)
@@ -7,6 +7,7 @@
  *     Mono Project (http://www.mono-project.com)
  *
  * Copyright 2015 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_METADATA_DEBUG_MONO_PPDB_H__
index 8df4c0f902606edc04b31b5b97cb1350b851482d..f418b2078cee4af6f2da49eb191d887c99d458bb 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 684168994b43e3f6952476f075fa02a230fea3f7..3b3459f32587e13e2589a4d0d1f3d7dbe12aa99a 100644 (file)
@@ -2,6 +2,7 @@
  * This header is only installed for use by the debugger:
  * the structures and the API declared here are not supported.
  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_DEBUG_MONO_SYMFILE_H__
index dfd65e48a211a1b8e8094a7340dce36921618cb5..5e3adb36a48537df661e036429f35b7b745af26a 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Appdomain-related internal data structures and functions.
  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_METADATA_DOMAIN_INTERNALS_H__
 #define __MONO_METADATA_DOMAIN_INTERNALS_H__
index 9f2d9fbd81433be9d715311d2d995efc214b61c4..da3b6930aafef0036aee4ecf3e6091fbc60dc6ca 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -886,8 +887,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 e0d1970f61279e87374354b4bc734610cd344c9d..4726f9ba703db888ea33078bd842e31ccb88e294 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index cdf5ea0965e97c2a795733944fb8f81d9f73ad75..332ac557d1ee77e5e5eb86213eb59ae6e47beda5 100644 (file)
@@ -9,6 +9,7 @@
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <glib.h>
@@ -966,11 +967,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 71a956679d11c43faf1cc86b7264b1dbacfb09ef..c0d0f1c11e32f01631f4ab9228bbfbd3aee26d0b 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 2974bd49949ecdd27de60df557c33ee102df61e4..ab10f929173b4413ac188294374ce56a9447406d 100644 (file)
@@ -7,6 +7,7 @@
  *
  * (C) 2001 Ximian, Inc.
  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef _MONO_METADATA_FILEIO_H_
index aca3e7fb49c6fab2a7f25c8b89aeca79d801763e..efa5547f6e485fa3a5f81522dc9fddc2153194c9 100644 (file)
@@ -5,6 +5,7 @@
  *     Rodrigo Kumpera
  *
  * Copyright 2014 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 56d598ee7f21523345f5187b5f8e09cf00eab753..dba37472c34741355a3f5e1e954f4c54a86801ad 100644 (file)
@@ -5,6 +5,7 @@
  *     Rodrigo Kumpera
  *
  * Copyright 2014 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 0e391ff1d4016bbbafdb0be16c3c67616aa8bddd..cef862e3bea755408ad986fcafb3f19d87b99cd4 100644 (file)
@@ -5,6 +5,7 @@
  *     Rodrigo Kumpera
  *
  * Copyright 2014 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef _MONO_METADATA_FILE_MMAP_H_
index def11d9856d8be929b37c1fc92f0c48651ca4dd4..eb1827a0c6055f863341ad2c12cdcf55b11ec600 100644 (file)
@@ -5,6 +5,7 @@
  *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
  *
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifdef HAVE_CONFIG_H
index bc13b1ea2694af528adf30c07927aaea3481d01b..52d950d8cca7b8469db99a3f95dcd751d6a24f4b 100644 (file)
@@ -5,6 +5,7 @@
  *
  * (C) 2002 Ximian, Inc.
  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_METADATA_GC_INTERNAL_H__
index ff442e43f6a7faf3484ec2848e7d0bc01d0f6438..ef232a93e5e98a27911de3bb57996cdb9a5b683f 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/sgen/gc-internal-agnostic.h"
index 3e56e77a821782527dfb4c03ba07f5076dc0ffb2..148bbedee6444a74666934c4a37d4b5377e69b2e 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -39,6 +40,7 @@
 #include <mono/utils/mono-threads.h>
 #include <mono/utils/atomic.h>
 #include <mono/utils/mono-coop-semaphore.h>
+#include <mono/utils/hazard-pointer.h>
 
 #ifndef HOST_WIN32
 #include <pthread.h>
@@ -638,6 +640,41 @@ mono_gc_finalize_notify (void)
        mono_coop_sem_post (&finalizer_sem);
 }
 
+/*
+This is the number of entries allowed in the hazard free queue before
+we explicitly cycle the finalizer thread to trigger pumping the queue.
+
+It was picked empirically by running the corlib test suite in a stress
+scenario where all hazard entries are queued.
+
+In this extreme scenario we double the number of times we cycle the finalizer
+thread compared to just GC calls.
+
+Entries are usually in the order of 100's of bytes each, so we're limiting
+floating garbage to be in the order of a dozen kb.
+*/
+static gboolean finalizer_thread_pulsed;
+#define HAZARD_QUEUE_OVERFLOW_SIZE 20
+
+static void
+hazard_free_queue_is_too_big (size_t size)
+{
+       if (size < HAZARD_QUEUE_OVERFLOW_SIZE)
+               return;
+
+       if (finalizer_thread_pulsed || InterlockedCompareExchange (&finalizer_thread_pulsed, TRUE, FALSE))
+               return;
+
+       mono_gc_finalize_notify ();
+}
+
+static void
+hazard_free_queue_pump (void)
+{
+       mono_thread_hazardous_try_free_all ();
+       finalizer_thread_pulsed = FALSE;
+}
+
 #ifdef HAVE_BOEHM_GC
 
 static void
@@ -713,6 +750,9 @@ finalizer_thread (gpointer unused)
 {
        gboolean wait = TRUE;
 
+       /* Register a hazard free queue pump callback */
+       mono_hazard_pointer_install_free_queue_size_callback (hazard_free_queue_is_too_big);
+
        while (!finished) {
                /* Wait to be notified that there's at least one
                 * finaliser to run
@@ -757,6 +797,8 @@ finalizer_thread (gpointer unused)
 
                reference_queue_proccess_all ();
 
+               hazard_free_queue_pump ();
+
                /* Avoid posting the pending done event until there are pending finalizers */
                if (mono_coop_sem_timedwait (&finalizer_sem, 0, MONO_SEM_FLAGS_NONE) == 0) {
                        /* Don't wait again at the start of the loop */
index c962bda7c7fb59bdc0d8c25b7b2dec5bdf82cc78..6c266259508ae6f251856794587f9967db5fd7b1 100644 (file)
@@ -5,6 +5,7 @@
  *  - Ludovic Henry <ludovic@xamarin.com>
  *
  * Copyright 2015 Xamarin, Inc. (www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index b933039b0b0ed222b08aaa2df015b7f947e13b04..99a0428290355f98fad465166ced168e0b8f1c84 100644 (file)
@@ -5,6 +5,7 @@
  *  - Ludovic Henry <ludovic@xamarin.com>
  *
  * Copyright 2015 Xamarin, Inc. (www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_HANDLE_H__
@@ -94,7 +95,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 68702706b533ca9d878797a0012d0705ea485595..5ca728a0489c0ee158e1279b326d7646411a1c5c 100644 (file)
@@ -210,9 +210,6 @@ ICALL(PROCESS_10, "ProcessName_internal(intptr)", ves_icall_System_Diagnostics_P
 ICALL(PROCESS_13, "ShellExecuteEx_internal(System.Diagnostics.ProcessStartInfo,System.Diagnostics.Process/ProcInfo&)", ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal)
 #endif /* !DISABLE_PROCESS_HANDLING */
 
-ICALL_TYPE(SFRAME, "System.Diagnostics.StackFrame", SFRAME_1)
-ICALL(SFRAME_1, "GetILOffsetFromFile", ves_icall_System_StackFrame_GetILOffsetFromFile)
-
 ICALL_TYPE(STOPWATCH, "System.Diagnostics.Stopwatch", STOPWATCH_1)
 ICALL(STOPWATCH_1, "GetTimestamp", mono_100ns_ticks)
 
@@ -503,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 4f4a90e6684a35207c236b580fd804addd1136b4..cea8809e84fe18aeeb18f6eb2a16a58168c93fbc 100644 (file)
@@ -11,6 +11,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -138,19 +139,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 +208,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 +218,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 +297,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 +1269,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 +1639,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
@@ -1843,8 +1870,11 @@ ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *ob
                return NULL;
        }
 
-       if (mono_security_core_clr_enabled ())
-               mono_security_core_clr_ensure_reflection_access_field (cf);
+       if (mono_security_core_clr_enabled () &&
+           !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
 
        MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
        mono_error_set_pending_exception (&error);
@@ -1865,8 +1895,11 @@ ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *ob
                return;
        }
 
-       if (mono_security_core_clr_enabled ())
-               mono_security_core_clr_ensure_reflection_access_field (cf);
+       if (mono_security_core_clr_enabled () &&
+           !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
+               mono_error_set_pending_exception (&error);
+               return;
+       }
 
        type = mono_field_get_type_checked (cf, &error);
        if (!mono_error_ok (&error)) {
@@ -2701,10 +2734,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);
 
@@ -3041,8 +3076,11 @@ ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, Mo
 
        *exc = NULL;
 
-       if (mono_security_core_clr_enabled ())
-               mono_security_core_clr_ensure_reflection_access_method (m);
+       if (mono_security_core_clr_enabled () &&
+           !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
 
        if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
                if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
@@ -3052,7 +3090,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 +3206,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 +3235,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 +4400,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 +5560,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 +5835,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 +5882,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 +5932,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 +5944,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 +5966,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 +6014,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 +6026,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,11 +6327,23 @@ 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))
+               if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
+                       if (throwOnBindFailure)
+                               mono_error_set_pending_exception (&error);
+                       else
+                               mono_error_cleanup (&error);
                        return NULL;
+               }
        }
 
        delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
@@ -6435,7 +6509,11 @@ 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->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);
@@ -7594,12 +7672,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
@@ -7955,20 +8037,6 @@ ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
        return message;
 }
 
-ICALL_EXPORT int
-ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
-{
-       guint32 il_offset;
-       char *path_str = mono_string_to_utf8 (path);
-
-       if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
-               il_offset = -1;
-
-       g_free (path_str);
-
-       return il_offset;
-}
-
 ICALL_EXPORT gpointer
 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
 {
index e5211176d8eeb390d84f797d0f4d036759316d82..959575f6a0a4a8c8996720693fd4a39d412b0c4a 100644 (file)
@@ -1,5 +1,6 @@
 /* 
  * Copyright 2015 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_METADATA_IMAGE_INTERNALS_H__
 #define __MONO_METADATA_IMAGE_INTERNALS_H__
index c99de7aa04f344b980db02069a46a38a274f5bfc..7b1b4278315a2eddd8463dd5b6e86039efa3ed65 100644 (file)
@@ -9,6 +9,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <stdio.h>
@@ -509,9 +510,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 +1081,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 2f4be6663ff503b84ec0f3f1983d4587fca2d875..e94b73d590cfe85fd055d00b341fc8d84198c924 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -613,7 +614,7 @@ jit_info_table_add (MonoDomain *domain, MonoJitInfoTable *volatile *table_ptr, M
                *table_ptr = new_table;
                mono_memory_barrier ();
                domain->num_jit_info_tables++;
-               mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)mono_jit_info_table_free, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
+               mono_thread_hazardous_try_free (table, (MonoHazardousFreeFunc)mono_jit_info_table_free);
                table = new_table;
 
                goto restart;
@@ -691,7 +692,7 @@ mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
        if (domain->num_jit_info_tables <= 1) {
                /* Can it actually happen that we only have one table
                   but ji is still hazardous? */
-               mono_thread_hazardous_free_or_queue (ji, g_free, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
+               mono_thread_hazardous_try_free (ji, g_free);
        } else {
                domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
        }
index 56630da1eddbdf44b210c32f3670351a49b502e7..56992b3612738bd5ea800a0a50edc2817068c202 100644 (file)
@@ -17,6 +17,7 @@
  * TODO:
  *   This should keep track of the assembly versions that we are loading.
  *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <glib.h>
@@ -563,7 +564,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 +877,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 +1880,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 +2835,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 18b52ae2b82d58b68edd3419d411539592f567f9..2adadc6ed6ea52e638f47b2e74e0a03fabf3ae3f 100644 (file)
@@ -10,6 +10,7 @@
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * (C) 2003 PT Cakram Datalingga Duaribu  http://www.cdl2000.com
  * Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 696b97deca31c7385e56335cb44f4c2af65aa062..18f93d260e3897cc70f53bbfde9b45a0229526fb 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -211,11 +212,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 +238,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 +294,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 +362,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 +529,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 +1857,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 +2215,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 +8238,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 +8599,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 +9504,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 +9618,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 +9944,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 abbdbdbace3b167545217577638bccda303b010a..60d36ae2ad1765d76cbf450dbb8feb9b616bf479 100644 (file)
@@ -10,6 +10,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc. (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 595369140103af94a4b1bb62e68a69eb0252712e..90a4d332bd129c818bebd54cb74b4e90ddd481f6 100644 (file)
@@ -1,6 +1,137 @@
+#include <stdio.h>
+
 #include "config.h"
+#include <mono/metadata/abi-details.h>
+
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/monitor.h>
+#ifdef HAVE_SGEN_GC
+#include <mono/sgen/sgen-gc.h>
+#endif
+
+static int
+dump_arch (void)
+{
+#if defined (TARGET_X86)
+       g_print ("#ifdef TARGET_X86\n");
+#elif defined (TARGET_AMD64)
+       g_print ("#ifdef TARGET_AMD64\n");
+#elif defined (TARGET_ARM)
+       g_print ("#ifdef TARGET_ARM\n");
+#elif defined (TARGET_ARM64)
+       g_print ("#ifdef TARGET_ARM64\n");
+#else
+       return 0;
+#endif
+       return 1;
+}
+
+static int
+dump_os (void)
+{
+#if defined (PLATFORM_WIN32)
+       g_print ("#ifdef TARGET_WIN32\n");
+#elif defined (PLATFORM_ANDROID)
+       g_print ("#ifdef TARGET_ANDROID\n");
+#elif defined (PLATFORM_MACOSX)
+       g_print ("#ifdef TARGET_OSX\n");
+#elif defined (PLATFORM_IOS)
+       g_print ("#ifdef TARGET_IOS\n");
+#else
+       return 0;
+#endif
+       return 1;
+}
+
+void
+mono_dump_metadata_offsets (void);
+
+void
+mono_dump_metadata_offsets (void)
+{
+#ifdef USED_CROSS_COMPILER_OFFSETS
+       g_print ("not using native offsets\n");
+#else
+       g_print ("#ifndef USED_CROSS_COMPILER_OFFSETS\n");
+
+       if (!dump_arch ()) {
+               g_print ("#error failed to figure out the current arch\n");
+               return;
+       }
+
+       if (!dump_os ()) {
+               g_print ("#error failed to figure out the current OS\n");
+               return;
+       }
+
+#ifdef HAVE_SGEN_GC
+       g_print ("#ifndef HAVE_BOEHM_GC\n");
+#elif HAVE_BOEHM_GC
+       g_print ("#ifndef HAVE_SGEN_GC\n");
+#else
+       g_print ("#error no gc conf not supported\n");
+       return;
+#endif
+
+       g_print ("#define HAS_CROSS_COMPILER_OFFSETS\n");
+       g_print ("#if defined (USE_CROSS_COMPILE_OFFSETS) || defined (MONO_CROSS_COMPILE)\n");
+       g_print ("#if !defined (DISABLE_METADATA_OFFSETS)\n");
+       g_print ("#define USED_CROSS_COMPILER_OFFSETS\n");
+
+#define DISABLE_JIT_OFFSETS
+#define DECL_OFFSET2(struct,field,offset) this_should_not_happen
+#define DECL_ALIGN2(type,size) this_should_not_happen
+
+#define DECL_OFFSET(struct,field) g_print ("DECL_OFFSET2(%s,%s,%d)\n", #struct, #field, (int)MONO_STRUCT_OFFSET (struct, field));
+#define DECL_ALIGN(type) g_print ("DECL_ALIGN2(%s,%d)\n", #type, (int)MONO_ABI_ALIGNOF (type));
+#define DECL_SIZE(type) g_print ("DECL_SIZE2(%s,%d)\n", #type, (int)MONO_ABI_SIZEOF (type));
+#include <mono/metadata/object-offsets.h>
+
+       g_print ("#endif //disable metadata check\n");
+       g_print ("#endif //gc check\n");
+#endif
+}
+
+void
+mono_metadata_cross_helpers_run (void);
+
+void
+mono_metadata_cross_helpers_run (void)
+{
+#if defined (HAS_CROSS_COMPILER_OFFSETS) && !defined (MONO_CROSS_COMPILE)
+       gboolean is_broken = FALSE;
+
+#define DISABLE_JIT_OFFSETS
+#define USE_CROSS_COMPILE_OFFSETS
+#define DECL_OFFSET(struct,field) this_should_not_happen_for_cross_fields
+#define DECL_OFFSET2(struct,field,offset) \
+        if ((int)G_STRUCT_OFFSET (struct, field) != offset) { \
+               g_print (#struct ":" #field " invalid struct offset %d (expected %d)\n",        \
+                       offset, \
+                       (int)G_STRUCT_OFFSET (struct, field));  \
+               is_broken = TRUE;       \
+       }
+#define DECL_ALIGN(type) this_should_not_happen_for_cross_align
+#define DECL_ALIGN2(name,size) \
+        if (MONO_ALIGN_ ## name != size) { \
+               g_print (#name ": invalid alignment %d (expected %d)\n",        \
+               size,   \
+               MONO_ALIGN_ ## name);   \
+               is_broken = TRUE;       \
+       }
+#define DECL_SIZE(type) this_should_not_happen_for_cross_size
+#define DECL_SIZE2(name,size) \
+        if (MONO_SIZEOF_ ## name != size) { \
+               g_print (#name ": invalid size %d (expected %d)\n",     \
+               size,   \
+               MONO_SIZEOF_ ## name);  \
+               is_broken = TRUE;       \
+       }
+
+#include <mono/metadata/object-offsets.h>
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/metadata/metadata-cross-helpers.c"
+       g_assert (!is_broken);
 #endif
+}
 
index 753e5269e921bdb9dec91aa0fdac4faf9f4f817b..287c68fbfb79d3413a3767ca63c0a9a0e3e66b35 100644 (file)
@@ -5,6 +5,7 @@
  *     Mono Project (http://www.mono-project.com)
  *
  * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/verify.h>
index a96f8cee6380ae2adf0e67ff0d5f0c2cddf019ab..5a19ef2d17dcb302805159d6e6508e9795d3eded 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -1837,8 +1838,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);
                
@@ -2766,24 +2770,11 @@ mono_metadata_clean_for_image (MonoImage *image)
 static void
 free_inflated_method (MonoMethodInflated *imethod)
 {
-       int i;
        MonoMethod *method = (MonoMethod*)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);
 }
 
@@ -3385,6 +3376,10 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                        return FALSE;
 
                type->data.klass = mono_class_from_mono_type (etype);
+
+               if (transient)
+                       mono_metadata_free_type (etype);
+
                g_assert (type->data.klass); //This was previously a check for NULL, but mcfmt should never fail. It can return a borken MonoClass, but should return at least something.
                break;
        }
index 3b04c246494af2d77121e5cbbb55fbade2bb2d3b..98431f7d64a8daa71bb9589f2f189c69f033b0d8 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index b068745dff68636300170c8abe8a48aa487fbc71..45c13be4e0f780ed511c327c5c9925ff97626e36 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index d7115994b84f49a9063db8720ace9c9423c44f15..564c83a6151db8cba9ce666d90a3b85ccef6cc2d 100644 (file)
@@ -5,6 +5,7 @@
  *   Rodrigo Kumpera (rkumpera@novell.com)
  *
  * Copyright 2010 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -514,20 +515,10 @@ 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 01e2773a9b81ea9b3868e1c1104d6f3b5d0793ac..ece67d1286cd4fef23ca0b3389e7af6b58171f82 100644 (file)
@@ -2,6 +2,7 @@
  * mono-config-dirs.c:
  *
  * Copyright 2015 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /*
index 2eba9e86d4bc38ba7efe34478ea6630b2e6889ac..80261f2b62e9a3d74741b48af5aff8fb135903b9 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "config.h"
 #include <glib.h>
index 09c55b3bcc8486be2385d9e3ea800cd4f954af0c..b88b20e03819cb0383c8b5af48622205cd8f7524 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 23b6fe7b3caffab9839fab0fd6ef704492a24b4f..a4c48f1413dda3adef0ed9064d111854343a075e 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include "mono-endian.h"
index e07f8fadb838dcd599922996f8b077333134d56d..60c3328a238782269a18de0e1c9bf04ddef6aa52 100644 (file)
@@ -5,6 +5,7 @@
  *   Paolo Molaro (lupus@xamarin.com)
  *
  * Copyright 2013 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_G_HASH_H__
index 7e90b652dd5901714b31f60bfb95725fd85a8404..657800afbe35e70255efb0f3588a9a41f7ef0225 100644 (file)
@@ -5,6 +5,7 @@
  *   Paolo Molaro (lupus@ximian.com)
  *
  * Copyright 2006-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/metadata/mono-mlist.h"
index 267f87d47350f6da4ff85b3c4f966a2d6c63e8e6..445df5c8334ef7931c3c373c82a5168d71d8842b 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright 2008-2009 Novell, Inc (http://www.novell.com)
  * 2011 Xamarin, Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index b9293154ab106bb781a6e1f8d6ed776c878fd003..d59d624782a8d781bacbf49472ca26a457a185b8 100644 (file)
@@ -5,6 +5,7 @@
  *     Sebastien Pouliot  <sebastien@ximian.com>
  *
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifdef HAVE_CONFIG_H
index f933e11276f1d54d4e2e3662dcc2d5eafe3e0f6e..7f904f3dec7b08970d31c3b3f6161c8489aed3b7 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index b296ca2e37d7f86340bebed513b1dbb548a3552a..48084d143eb540991da6643180b4e23853536676 100644 (file)
@@ -5,6 +5,7 @@
  *     Ludovic Henry (ludovic@xamarin.com)
  *
  * Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 //
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 a79e3508e0f74967146ae3c0006d437f669a64a8..36763dd311c3bf922c7171a261af3c9ca121bf9f 100644 (file)
@@ -17,17 +17,22 @@ Output defines:
 
 HAS_CROSS_COMPILER_OFFSETS - if set, it means we found some cross offsets, it doesnt mean we'll use it.
 USED_CROSS_COMPILER_OFFSETS - if set, it means we used the cross offsets
+
+Environment defines (from config.h and CFLAGS):
+
+MONO_GENERATING_OFFSETS - Set by an offsets generating tool to disable the usage of any (possibly non-existing) generated header.
+MONO_OFFSETS_FILE - Name of the header file containing the offsets to be used.
+
 */
 
 
 #undef HAS_CROSS_COMPILER_OFFSETS
 #undef USED_CROSS_COMPILER_OFFSETS
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/metadata/object-offsets.h"
+#if !defined (MONO_GENERATING_OFFSETS) && defined (MONO_OFFSETS_FILE)
+#include MONO_OFFSETS_FILE
 #endif
 
-
 #ifndef USED_CROSS_COMPILER_OFFSETS
 
 DECL_ALIGN(gint8)
@@ -225,6 +230,18 @@ DECL_OFFSET(DynCallArgs, res2)
 
 #if defined(TARGET_ARM)
 DECL_OFFSET(MonoLMF, method)
+DECL_OFFSET(GSharedVtCallInfo, stack_usage)
+DECL_OFFSET(GSharedVtCallInfo, vret_arg_reg)
+DECL_OFFSET(GSharedVtCallInfo, ret_marshal)
+DECL_OFFSET(GSharedVtCallInfo, vret_slot)
+DECL_OFFSET(GSharedVtCallInfo, gsharedvt_in)
+#endif
+
+#if defined(TARGET_ARM64)
+DECL_OFFSET(GSharedVtCallInfo, stack_usage)
+DECL_OFFSET(GSharedVtCallInfo, gsharedvt_in)
+DECL_OFFSET(GSharedVtCallInfo, ret_marshal)
+DECL_OFFSET(GSharedVtCallInfo, vret_slot)
 #endif
 
 #if defined(TARGET_AMD64) || defined(TARGET_ARM64)
index 81589594b6fa8b0c7c0cf43438c5e0fb9e2bfb1d..dc20b4e83212449db9ba9826eb4a0be57d796369 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2001 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #ifdef HAVE_ALLOCA_H
@@ -3506,7 +3507,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);
@@ -3734,17 +3735,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);
@@ -3754,8 +3755,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
@@ -4600,7 +4601,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);
                                        }
                                                
@@ -4652,8 +4654,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) {
@@ -4669,7 +4674,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) {
@@ -4692,7 +4698,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);
                }
 
@@ -4881,7 +4889,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;
@@ -5798,23 +5806,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);
 
@@ -5844,8 +5871,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;
 }
@@ -5970,18 +5997,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;
@@ -5995,8 +6049,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;
 
@@ -6035,12 +6101,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 */
@@ -6057,19 +6123,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;
 }
 
@@ -6232,9 +6296,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))
@@ -6918,7 +6984,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;
@@ -7238,9 +7304,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);
@@ -7501,9 +7568,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 6cfbe5cbcce2fe85df1a6912fbcb024ad8401d8e..838142e253f01761818863eade191b0f48381df4 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <mono/metadata/opcodes.h>
 #include <stddef.h> /* for NULL */
index 19ebb958b24d3e2a1a4981bac8eef93b7674f298..3af4153a867419f66b11691e5e18896d3034c1ab 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <stdio.h>
index dd4ac82ee77f6dd8bb4a9207103b69333f19a6ca..3cd38789d3cfd897fd521d25a6443f718d4f32e4 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2002 Ximian, Inc.
  * Copyright 2002-2006 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 28f7a2983125fa1f2e58ddf0a8466b67da05afe8..d74a273d085bf0825656642a845a683722b5ea89 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 422bda1d1bc991994ec5012c02c00a1ddeae4580..87d2d104790dceb6272299c34f19911ceb362615 100644 (file)
@@ -8,6 +8,7 @@
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <glib.h>
index 15af782fdc65b1b86409c61c56a9c401cc47126b..563b374835969d1375f8562b19057528e8bb4860 100644 (file)
@@ -7,6 +7,7 @@
  *
  * (C) 2001 Ximian, Inc.
  * Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef _MONO_METADATA_RAND_H_
index af5ba0afdb0b0a6420e1f309712fb928d04cf811..600f2c6d268906ab4c360248e961b5b394b6188e 100644 (file)
@@ -1,5 +1,6 @@
 /* 
  * Copyright 2014 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_METADATA_REFLECTION_INTERNALS_H__
 #define __MONO_METADATA_REFLECTION_INTERNALS_H__
@@ -27,6 +28,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..200c41e5f804fa015801317184020629b1c46501 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Rodrigo Kumpera
  *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include "mono/utils/mono-digest.h"
@@ -151,7 +152,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 +188,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 +5536,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 +7776,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 +7805,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 +7845,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 +7858,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 +7876,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 +7889,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 +7901,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 +8583,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 +8926,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 +9218,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 +9575,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 +9621,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 +9630,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 +9653,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 +10372,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 +10673,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 +10692,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 +10722,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 +10763,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 +10779,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 +10801,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 +10823,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 +10842,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 +10945,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 +10964,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 +11050,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 +11095,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 +11134,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 +11154,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 +11220,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 +11255,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 +11277,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 +11327,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 +11344,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 +11360,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 +11374,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 +11429,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 +11437,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 +11502,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 +11512,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 +11595,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 +11624,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 +11657,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 +11708,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 +12033,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 +12063,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 +12092,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 +12112,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 +12159,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 +12199,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 +12417,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 +12452,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 +12468,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 +12482,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 +12510,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 +12546,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 +12572,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 +12589,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 +12620,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 +12679,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 +12713,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 +12730,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 +12754,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 +12794,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 +12899,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 +12952,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 +12990,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 +13059,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 +13117,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 +13126,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 +13157,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 +13188,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 +13219,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 +13247,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 +13308,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 +13340,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 +13380,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 +13395,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 +13509,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 +13522,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 +13536,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 +13575,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 +13587,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 +13597,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 +13641,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 +13696,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 +13727,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 +13746,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 +13790,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 +13802,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 +13816,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 +13827,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 +13868,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 +13887,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 +13897,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 +13930,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 +13946,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 +13978,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 +14018,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 +14052,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 +14076,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 +14188,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 +14683,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 +14703,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..6555cdec7a0d49f1e7da05a0cd841ca99bf47139 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011-2014 Xamarin, Inc (http://www.xamarin.com)
  *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -373,9 +374,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 +2011,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 fcd8782387635f0b44c57b60da57e779ab257c4c..1c41c797db4fa2c235cd84398bf04cdf7f45541b 100644 (file)
@@ -5,6 +5,7 @@
  *  Jonathan Pryor 
  *
  * Copyright 2010 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index fc2169f9131cbb25ad67e5c214c1863b997d8787..f874043e15b6e58f423ea2752fdcc12795a4fbe6 100644 (file)
@@ -6,6 +6,7 @@
  *     Sebastien Pouliot  <sebastien@ximian.com>
  *
  * Copyright 2007-2010 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <mono/metadata/class-internals.h>
@@ -624,34 +625,38 @@ get_method_access_exception (const char *format, MonoMethod *caller, MonoMethod
  *     Transparent code cannot access to Critical fields and can only use
  *     them if they are visible from it's point of view.
  *
- *     A FieldAccessException is thrown if the field is cannot be accessed.
+ *     Returns TRUE if acess is allowed.  Otherwise returns FALSE and sets @error to a FieldAccessException if the field is cannot be accessed.
  */
-void
-mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field)
+gboolean
+mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field, MonoError *error)
 {
+       mono_error_init (error);
        MonoMethod *caller = get_reflection_caller ();
        /* CoreCLR restrictions applies to Transparent code/caller */
        if (mono_security_core_clr_method_level (caller, TRUE) != MONO_SECURITY_CORE_CLR_TRANSPARENT)
-               return;
+               return TRUE;
 
        if (mono_security_core_clr_get_options () & MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_REFLECTION) {
                if (!mono_security_core_clr_is_platform_image (mono_field_get_parent(field)->image))
-                       return;
+                       return TRUE;
        }
 
        /* Transparent code cannot [get|set]value on Critical fields */
        if (mono_security_core_clr_class_level (mono_field_get_parent (field)) == MONO_SECURITY_CORE_CLR_CRITICAL) {
-               mono_raise_exception (get_field_access_exception (
+               mono_error_set_exception_instance (error, get_field_access_exception (
                        "Transparent method %s cannot get or set Critical field %s.", 
                        caller, field));
+               return FALSE;
        }
 
        /* also it cannot access a fields that is not visible from it's (caller) point of view */
        if (!check_field_access (caller, field)) {
-               mono_raise_exception (get_field_access_exception (
+               mono_error_set_exception_instance (error, get_field_access_exception (
                        "Transparent method %s cannot get or set private/internal field %s.", 
                        caller, field));
+               return FALSE;
        }
+       return TRUE;
 }
 
 /*
@@ -661,34 +666,38 @@ mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field)
  *     Transparent code cannot call Critical methods and can only call them
  *     if they are visible from it's point of view.
  *
- *     A MethodAccessException is thrown if the field is cannot be accessed.
+ *     If access is allowed returns TRUE.  Returns FALSE and sets @error to a MethodAccessException if the field is cannot be accessed.
  */
-void
-mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method)
+gboolean
+mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method, MonoError *error)
 {
+       mono_error_init (error);
        MonoMethod *caller = get_reflection_caller ();
        /* CoreCLR restrictions applies to Transparent code/caller */
        if (mono_security_core_clr_method_level (caller, TRUE) != MONO_SECURITY_CORE_CLR_TRANSPARENT)
-               return;
+               return TRUE;
 
        if (mono_security_core_clr_get_options () & MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_REFLECTION) {
                if (!mono_security_core_clr_is_platform_image (method->klass->image))
-                       return;
+                       return TRUE;
        }
 
        /* Transparent code cannot invoke, even using reflection, Critical code */
        if (mono_security_core_clr_method_level (method, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL) {
-               mono_raise_exception (get_method_access_exception (
+               mono_error_set_exception_instance (error, get_method_access_exception (
                        "Transparent method %s cannot invoke Critical method %s.", 
                        caller, method));
+               return FALSE;
        }
 
        /* also it cannot invoke a method that is not visible from it's (caller) point of view */
        if (!check_method_access (caller, method)) {
-               mono_raise_exception (get_method_access_exception (
+               mono_error_set_exception_instance (error, get_method_access_exception (
                        "Transparent method %s cannot invoke private/internal method %s.", 
                        caller, method));
+               return FALSE;
        }
+       return TRUE;
 }
 
 /*
@@ -726,19 +735,20 @@ can_avoid_corlib_reflection_delegate_optimization (MonoMethod *method)
 /*
  * mono_security_core_clr_ensure_delegate_creation:
  *
- *     Return TRUE if a delegate can be created on the specified method. 
- *     CoreCLR also affect the binding, so throwOnBindFailure must be 
- *     FALSE to let this function return (FALSE) normally, otherwise (if
- *     throwOnBindFailure is TRUE) it will throw an ArgumentException.
+ *     Return TRUE if a delegate can be created on the specified
+ *     method.  CoreCLR can also affect the binding, this function may
+ *     return (FALSE) and set @error to an ArgumentException.
  *
- *     A MethodAccessException is thrown if the specified method is not
+ *     @error is set to a MethodAccessException if the specified method is not
  *     visible from the caller point of view.
  */
 gboolean
-mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, gboolean throwOnBindFailure)
+mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, MonoError *error)
 {
        MonoMethod *caller;
 
+       mono_error_init (error);
+
        /* note: mscorlib creates delegates to avoid reflection (optimization), we ignore those cases */
        if (can_avoid_corlib_reflection_delegate_optimization (method))
                return TRUE;
@@ -750,13 +760,10 @@ mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, gboolean th
 
        /* otherwise it (as a Transparent caller) cannot create a delegate on a Critical method... */
        if (mono_security_core_clr_method_level (method, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL) {
-               /* but this throws only if 'throwOnBindFailure' is TRUE */
-               if (!throwOnBindFailure)
-                       return FALSE;
-
-               mono_raise_exception (get_argument_exception (
+               mono_error_set_exception_instance (error, get_argument_exception (
                        "Transparent method %s cannot create a delegate on Critical method %s.", 
                        caller, method));
+               return FALSE;
        }
 
        if (mono_security_core_clr_get_options () & MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_DELEGATE) {
@@ -766,9 +773,10 @@ mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, gboolean th
 
        /* also it cannot create the delegate on a method that is not visible from it's (caller) point of view */
        if (!check_method_access (caller, method)) {
-               mono_raise_exception (get_method_access_exception (
+               mono_error_set_exception_instance (error, get_method_access_exception (
                        "Transparent method %s cannot create a delegate on private/internal method %s.", 
                        caller, method));
+               return FALSE;
        }
 
        return TRUE;
@@ -1049,19 +1057,24 @@ mono_security_core_clr_require_elevated_permissions (void)
        return FALSE;
 }
 
-void
-mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field)
+gboolean
+mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field, MonoError *error)
 {
+       mono_error_init (error);
+       return TRUE;
 }
 
 void
-mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method)
+mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method, MonoError *error)
 {
+       mono_error_init (error);
+       return TRUE;
 }
 
 gboolean
-mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, gboolean throwOnBindFailure)
+mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, MonoError *error)
 {
+       mono_error_init (error);
        return TRUE;
 }
 
index ec2ab01ee264bf77f4e957bae389ab924783831e..51fdb8c1239eedc47904a1389ce8c3e92b69daaf 100644 (file)
@@ -42,9 +42,11 @@ extern gboolean mono_security_core_clr_test;
 extern void mono_security_core_clr_check_inheritance (MonoClass *klass);
 extern void mono_security_core_clr_check_override (MonoClass *klass, MonoMethod *override, MonoMethod *base);
 
-extern void mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field);
-extern void mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method);
-extern gboolean mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, gboolean throwOnBindFailure);
+extern gboolean
+mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field, MonoError *error);
+extern gboolean
+mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method, MonoError *error);
+extern gboolean mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, MonoError *error);
 extern MonoException* mono_security_core_clr_ensure_dynamic_method_resolved_object (gpointer ref, MonoClass *handle_class);
 
 extern gboolean mono_security_core_clr_can_access_internals (MonoImage *accessing, MonoImage* accessed);
index e3c3cbc82d57a033d5ba8ba57de299dd7468fdbc..0dfb927bc29eeae095980873a14a68a4990dc9e3 100644 (file)
@@ -5,6 +5,7 @@
  *     Sebastien Pouliot  <sebastien@ximian.com>
  *
  * Copyright 2005-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "security-manager.h"
index 98fbbfd652169b5931dfcab650b008671f5c00f2..19ac3e8f82c496521b73ac37eb4d8cfab999adea 100644 (file)
@@ -5,6 +5,7 @@
  *     Sebastien Pouliot  <sebastien@ximian.com>
  *
  * Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef _MONO_METADATA_SECURITY_MANAGER_H_
index 3f72f3f338a59069bf0323c4d7f47e035d394e4c..afd19549824a4461ac9241fda71ede99d159b97b 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2015 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
  
 #ifndef __MONO_SEQ_POINTS_DATA_H__
index ac7dfb975998a1f290d9ab82d0923a253b8f4b58..df6a4bb8cdee7513673b29f6cd08b8ed3e3ae84b 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_SGENBRIDGEINTERNAL_H__
index 5e4fa165ab0efc72fd2d09482953ab52b8ee1289..3b0487c9243afe496a0f5d842a592cdf5e7dd459 100644 (file)
@@ -3,38 +3,10 @@
  *
  * Copyright 2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
- *
- * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
- * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
- *
- * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- *
- *
  * Copyright 2001-2003 Ximian, Inc
  * Copyright 2003-2010 Novell, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -77,7 +49,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 28bf2caf759969be762332c9d9cc4eea504022fd..38dc44637cc05c1fea162908aec0bb741cfb0d8d 100644 (file)
@@ -1,24 +1,7 @@
 /*
  * Copyright 2011 Novell, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /*
index fd36c3941eeee0e0f2bc1ba44f3b1acc3b8d97b2..54630c6ee033853a8ac63065b70eb7cfa1f3a100 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2014 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifdef SGEN_DEFINE_OBJECT_VTABLE
@@ -731,7 +720,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..2956d95420a1460145c6ab4a3c8e688ef5ce00f4 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2014 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -37,6 +26,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 +1581,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 +1661,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 +2968,7 @@ mono_gc_base_init (void)
 void
 mono_gc_base_cleanup (void)
 {
+       sgen_thread_pool_shutdown ();
 }
 
 gboolean
index 20fdb460adde86c416d941f2625f335516b3e1bb..462680a63fe5c2f59b379cf4147da2e02f8e8f15 100644 (file)
@@ -3,38 +3,10 @@
  *
  * Copyright 2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
- *
- * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
- * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
- *
- * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- *
- *
  * Copyright 2001-2003 Ximian, Inc
  * Copyright 2003-2010 Novell, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -968,7 +940,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..a93cc7734ade79befcc811e6a8a4bf05047531a8 100644 (file)
@@ -3,38 +3,9 @@
  *
  * Copyright 2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
- *
- * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
- * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
- *
- * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- *
- *
  * Copyright 2001-2003 Ximian, Inc
  * Copyright 2003-2010 Novell, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -616,7 +587,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 fb6fc13bc451cb9dd60a04445ac6e0a37a75f377..90c8266b341f7749da66d0ae7d3fab1a6ebbffcc 100644 (file)
@@ -5,18 +5,7 @@
  *     João Matos (joao.matos@xamarin.com)
  * Copyright (C) 2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -78,4 +67,4 @@ mono_gc_get_restart_signal (void)
 }
 
 #endif
-#endif
\ No newline at end of file
+#endif
index 666ef3ce8cfb3103bd06720529a1a44424430e58..10ac567111ec81b022d058662e3dbde0ec612375 100644 (file)
@@ -9,18 +9,7 @@
  * Copyright 2010 Novell, Inc (http://www.novell.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 37979a497d40939f04fe9a03de7d307f564efbb2..dc9d29ff1395ad81be62b1a63edde30f691135dc 100644 (file)
@@ -9,18 +9,7 @@
  * Copyright 2010 Novell, Inc (http://www.novell.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 15eb283ee1343486e706ebcee4f25738d122d518..4185ce07b8ad67d96965485b9516dcf02fb70a59 100644 (file)
  * Copyright 2011 Xamarin, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index e6bd1f17aa7082cdddc7f8a486aabed036c08946..764d9d72626db8df7ac104204980b8e3fb0abd45 100644 (file)
@@ -4,37 +4,11 @@
  * Copyright 2011 Novell, Inc (http://www.novell.com)
  * Copyright 2014 Xamarin Inc (http://www.xamarin.com)
  *
- * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
- * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
- *
- * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- *
  *
  * Copyright 2001-2003 Ximian, Inc
  * Copyright 2003-2010 Novell, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index d9afbfa868dc9efe8a6a2eb0a31c151bb82215e2..5ca66e738af696bcbd0efcab0000a4c7bd32c9ec 100644 (file)
@@ -7,18 +7,7 @@
  * Copyright 2011 Xamarin, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index e7c4b91b7400f4e56eefd965a847c020447c9c15..917323c575af0d6f5f20122bd086e1c0c1005232 100644 (file)
@@ -7,24 +7,7 @@
  * Author:
  *  Rodrigo Kumpera (kumpera@gmail.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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef _MONO_SGEN_TOGGLEREF_H_
index 56212ac57cf8df16137f7c781167cc76919b0561..4bf721f9a06faeaeaa5d90fb7fef7093106b78a1 100644 (file)
@@ -10,6 +10,7 @@
  *
  * This file has been re-licensed under the MIT License:
  * http://opensource.org/licenses/MIT
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -1925,7 +1926,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 1594cc52bfcdaceb0c82b6660eac85296430446a..be330aa413a76fb8e08c626c6851795937d005ce 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <stdlib.h>
index eadb052ccd16c46a72927fb13c0b8fe0dccda8cc..8d55a552f84dbc86d35b01deea7793039e7b007d 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2015 Xamarin, Inc (https://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 //
index bb3cf92bfd5d1906d1a53e04f4c59a0cdacc5e87..85d3234dfdb45f6c3adc7fe987a00a8387c78d10 100644 (file)
@@ -7,6 +7,7 @@
  *
  * (C) Ximian, Inc. 2002
  * Copyright 2015 Xamarin, Inc (https://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __METADATA_SYSMATH_H__
index 11029082f8bda156b5a52d577f07c4a43e7fbbed..5f4f36a193f92ec0ee314160d9c1ea6db52dfc75 100644 (file)
@@ -5,6 +5,7 @@
  *     Ludovic Henry (ludovic.henry@xamarin.com)
  *
  * Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -245,6 +246,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 +272,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 +309,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 +377,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..62fc34aef3f2b11e470b7a8912c819bbf68a6db1 100644 (file)
@@ -5,6 +5,7 @@
  *     Ludovic Henry (ludovic.henry@xamarin.com)
  *
  * Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 //
@@ -344,16 +345,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 +371,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 */
@@ -524,7 +529,7 @@ worker_park (void)
                if (interrupted)
                        goto done;
 
-               if (mono_coop_cond_timedwait (&threadpool->parked_threads_cond, &threadpool->active_threads_lock, rand_next ((void **)rand_handle, 5 * 1000, 60 * 1000)) != 0)
+               if (mono_coop_cond_timedwait (&threadpool->parked_threads_cond, &threadpool->active_threads_lock, rand_next (&rand_handle, 5 * 1000, 60 * 1000)) != 0)
                        timeout = TRUE;
 
                mono_thread_info_uninstall_interrupt (&interrupted);
@@ -1314,10 +1319,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 +1333,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 +1351,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 +1590,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 +1605,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 b097a377fe6a957221c7fe24a493ba2717b65e87..b970e96e038a2fd0944ccb0c01295aa048b4e7f7 100644 (file)
@@ -7,6 +7,7 @@
  *
  * (C) 2001 Ximian, Inc
  * (C) Copyright 2002-2006 Novell, Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef _MONO_METADATA_THREADS_TYPES_H_
index 68c4b9025c0a8812e183ceb1ee2611e8f41c3bb3..5884d0270e58ee9ce7dd577fc37d3d16a8a4fced 100644 (file)
@@ -9,6 +9,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index e52f90aca0c155d453e40a77a1fdb3db805708ed..1d291ddb459d2d26df9f940b10ba05548fd50630 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Rodrigo Kumpera
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 
@@ -5016,7 +5017,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 f75db695f358153a26e0a0ec5c21958fec9390f4..8fc453350cd2eb87f7cabfeefe778b0a69265c65 100755 (executable)
@@ -304,13 +304,18 @@ x86_sources = \
        mini-x86.c              \
        mini-x86.h              \
        exceptions-x86.c        \
-       tramp-x86.c
+       tramp-x86.c     \
+       mini-x86-gsharedvt.c    \
+       tramp-x86-gsharedvt.c
 
 amd64_sources = \
        mini-amd64.c            \
        mini-amd64.h            \
        exceptions-amd64.c      \
-       tramp-amd64.c
+       tramp-amd64.c   \
+       mini-amd64-gsharedvt.c  \
+       mini-amd64-gsharedvt.h  \
+       tramp-amd64-gsharedvt.c
 
 ppc_sources = \
        mini-ppc.c              \
@@ -324,13 +329,17 @@ arm_sources = \
        mini-arm.h              \
        mini-arm-tls.h          \
        exceptions-arm.c        \
-       tramp-arm.c
+       tramp-arm.c     \
+       mini-arm-gsharedvt.c    \
+       tramp-arm-gsharedvt.c
 
 arm64_sources = \
        mini-arm64.c            \
        mini-arm64.h            \
        exceptions-arm64.c      \
-       tramp-arm64.c
+       tramp-arm64.c   \
+       mini-arm64-gsharedvt.c  \
+       tramp-arm64-gsharedvt.c
 
 mips_sources = \
        mini-mips.c             \
@@ -425,6 +434,7 @@ common_sources = \
        graph.c                 \
        mini-codegen.c          \
        mini-exceptions.c       \
+       mini-exceptions-native-unwinder.c       \
        mini-trampolines.c      \
        branch-opts.c           \
        mini-generic-sharing.c  \
index 2e4bd331a5616fc0823bd08f09215cad938a7e14..dd2780edac9e524123b6483fca0e54cb4e5ff95b 100644 (file)
@@ -8,6 +8,7 @@
  * (C) 2002 Ximian, Inc.
  * Copyright 2003-2011 Novell, Inc 
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -857,7 +858,331 @@ arch_init (MonoAotCompile *acfg)
 
 #ifdef TARGET_ARM64
 
-#include "../../../mono-extensions/mono/mini/aot-compiler-arm64.c"
+
+/* Load the contents of GOT_SLOT into dreg, clobbering ip0 */
+static void
+arm64_emit_load_got_slot (MonoAotCompile *acfg, int dreg, int got_slot)
+{
+       int offset;
+
+       g_assert (acfg->fp);
+       emit_unset_mode (acfg);
+       /* r16==ip0 */
+       offset = (int)(got_slot * sizeof (gpointer));
+#ifdef TARGET_MACH
+       /* clang's integrated assembler */
+       fprintf (acfg->fp, "adrp x16, %s@PAGE+%d\n", acfg->got_symbol, offset & 0xfffff000);
+       fprintf (acfg->fp, "add x16, x16, %s@PAGEOFF\n", acfg->got_symbol);
+       fprintf (acfg->fp, "ldr x%d, [x16, #%d]\n", dreg, offset & 0xfff);
+#else
+       /* Linux GAS */
+       fprintf (acfg->fp, "adrp x16, %s+%d\n", acfg->got_symbol, offset & 0xfffff000);
+       fprintf (acfg->fp, "add x16, x16, :lo12:%s\n", acfg->got_symbol);
+       fprintf (acfg->fp, "ldr x%d, [x16, %d]\n", dreg, offset & 0xfff);
+#endif
+}
+
+static void
+arm64_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int *code_size)
+{
+       int reg;
+
+       g_assert (acfg->fp);
+       emit_unset_mode (acfg);
+
+       /* ldr rt, target */
+       reg = arm_get_ldr_lit_reg (code);
+
+       fprintf (acfg->fp, "adrp x%d, L_OBJC_SELECTOR_REFERENCES_%d@PAGE\n", reg, index);
+       fprintf (acfg->fp, "add x%d, x%d, L_OBJC_SELECTOR_REFERENCES_%d@PAGEOFF\n", reg, reg, index);
+       fprintf (acfg->fp, "ldr x%d, [x%d]\n", reg, reg);
+
+       *code_size = 12;
+}
+
+static void
+arm64_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, gboolean thumb, MonoJumpInfo *ji, int *call_size)
+{
+       g_assert (acfg->fp);
+       emit_unset_mode (acfg);
+       if (ji && ji->relocation == MONO_R_ARM64_B) {
+               fprintf (acfg->fp, "b %s\n", target);
+       } else {
+               if (ji)
+                       g_assert (ji->relocation == MONO_R_ARM64_BL);
+               fprintf (acfg->fp, "bl %s\n", target);
+       }
+       *call_size = 4;
+}
+
+static void
+arm64_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *code_size)
+{
+       int reg;
+
+       /* ldr rt, target */
+       reg = arm_get_ldr_lit_reg (code);
+       arm64_emit_load_got_slot (acfg, reg, got_slot);
+       *code_size = 12;
+}
+
+static void
+arm64_emit_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, int info_offset)
+{
+       arm64_emit_load_got_slot (acfg, ARMREG_R16, offset / sizeof (gpointer));
+       fprintf (acfg->fp, "br x16\n");
+       /* Used by mono_aot_get_plt_info_offset () */
+       fprintf (acfg->fp, "%s %d\n", acfg->inst_directive, info_offset);
+}
+
+static void
+arm64_emit_tramp_page_common_code (MonoAotCompile *acfg, int pagesize, int arg_reg, int *size)
+{
+       guint8 buf [256];
+       guint8 *code;
+       int imm;
+
+       /* The common code */
+       code = buf;
+       imm = pagesize;
+       /* The trampoline address is in IP0 */
+       arm_movzx (code, ARMREG_IP1, imm & 0xffff, 0);
+       arm_movkx (code, ARMREG_IP1, (imm >> 16) & 0xffff, 16);
+       /* Compute the data slot address */
+       arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
+       /* Trampoline argument */
+       arm_ldrx (code, arg_reg, ARMREG_IP0, 0);
+       /* Address */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 8);
+       arm_brx (code, ARMREG_IP0);
+
+       /* Emit it */
+       emit_code_bytes (acfg, buf, code - buf);
+
+       *size = code - buf;
+}
+
+static void
+arm64_emit_tramp_page_specific_code (MonoAotCompile *acfg, int pagesize, int common_tramp_size, int specific_tramp_size)
+{
+       guint8 buf [256];
+       guint8 *code;
+       int i, count;
+
+       count = (pagesize - common_tramp_size) / specific_tramp_size;
+       for (i = 0; i < count; ++i) {
+               code = buf;
+               arm_adrx (code, ARMREG_IP0, code);
+               /* Branch to the generic code */
+               arm_b (code, code - 4 - (i * specific_tramp_size) - common_tramp_size);
+               /* This has to be 2 pointers long */
+               arm_nop (code);
+               arm_nop (code);
+               g_assert (code - buf == specific_tramp_size);
+               emit_code_bytes (acfg, buf, code - buf);
+       }
+}
+
+static void
+arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
+{
+       guint8 buf [128];
+       guint8 *code;
+       guint8 *labels [16];
+       int common_tramp_size;
+       int specific_tramp_size = 2 * 8;
+       int imm, pagesize;
+       char symbol [128];
+
+       if (!acfg->aot_opts.use_trampolines_page)
+               return;
+
+#ifdef TARGET_MACH
+       /* Have to match the target pagesize */
+       pagesize = 16384;
+#else
+       pagesize = mono_pagesize ();
+#endif
+       acfg->tramp_page_size = pagesize;
+
+       /* The specific trampolines */
+       sprintf (symbol, "%sspecific_trampolines_page", acfg->user_symbol_prefix);
+       emit_alignment (acfg, pagesize);
+       emit_global (acfg, symbol, TRUE);
+       emit_label (acfg, symbol);
+
+       /* The common code */
+       arm64_emit_tramp_page_common_code (acfg, pagesize, ARMREG_IP1, &common_tramp_size);
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = common_tramp_size;
+
+       arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
+
+       /* The rgctx trampolines */
+       /* These are the same as the specific trampolines, but they load the argument into MONO_ARCH_RGCTX_REG */
+       sprintf (symbol, "%srgctx_trampolines_page", acfg->user_symbol_prefix);
+       emit_alignment (acfg, pagesize);
+       emit_global (acfg, symbol, TRUE);
+       emit_label (acfg, symbol);
+
+       /* The common code */
+       arm64_emit_tramp_page_common_code (acfg, pagesize, MONO_ARCH_RGCTX_REG, &common_tramp_size);
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = common_tramp_size;
+
+       arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
+
+       /* The gsharedvt arg trampolines */
+       /* These are the same as the specific trampolines */
+       sprintf (symbol, "%sgsharedvt_arg_trampolines_page", acfg->user_symbol_prefix);
+       emit_alignment (acfg, pagesize);
+       emit_global (acfg, symbol, TRUE);
+       emit_label (acfg, symbol);
+
+       arm64_emit_tramp_page_common_code (acfg, pagesize, ARMREG_IP1, &common_tramp_size);
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = common_tramp_size;
+
+       arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
+
+       /* The IMT trampolines */
+       sprintf (symbol, "%simt_trampolines_page", acfg->user_symbol_prefix);
+       emit_alignment (acfg, pagesize);
+       emit_global (acfg, symbol, TRUE);
+       emit_label (acfg, symbol);
+
+       code = buf;
+       imm = pagesize;
+       /* The trampoline address is in IP0 */
+       arm_movzx (code, ARMREG_IP1, imm & 0xffff, 0);
+       arm_movkx (code, ARMREG_IP1, (imm >> 16) & 0xffff, 16);
+       /* Compute the data slot address */
+       arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
+       /* Trampoline argument */
+       arm_ldrx (code, ARMREG_IP1, ARMREG_IP0, 0);
+
+       /* Same as arch_emit_imt_thunk () */
+       labels [0] = code;
+       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0);
+       arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
+       labels [1] = code;
+       arm_bcc (code, ARMCOND_EQ, 0);
+
+       /* End-of-loop check */
+       labels [2] = code;
+       arm_cbzx (code, ARMREG_IP0, 0);
+
+       /* Loop footer */
+       arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 2 * 8);
+       arm_b (code, labels [0]);
+
+       /* Match */
+       mono_arm_patch (labels [1], code, MONO_R_ARM64_BCC);
+       /* Load vtable slot addr */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
+       /* Load vtable slot */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0);
+       arm_brx (code, ARMREG_IP0);
+
+       /* No match */
+       mono_arm_patch (labels [2], code, MONO_R_ARM64_CBZ);
+       /* Load fail addr */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
+       arm_brx (code, ARMREG_IP0);
+
+       emit_code_bytes (acfg, buf, code - buf);
+
+       common_tramp_size = code - buf;
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = common_tramp_size;
+
+       arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
+}
+
+static void
+arm64_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
+{
+       /* Load argument from second GOT slot */
+       arm64_emit_load_got_slot (acfg, ARMREG_R17, offset + 1);
+       /* Load generic trampoline address from first GOT slot */
+       arm64_emit_load_got_slot (acfg, ARMREG_R16, offset);
+       fprintf (acfg->fp, "br x16\n");
+       *tramp_size = 7 * 4;
+}
+
+static void
+arm64_emit_unbox_trampoline (MonoAotCompile *acfg, MonoCompile *cfg, MonoMethod *method, const char *call_target)
+{
+       emit_unset_mode (acfg);
+       fprintf (acfg->fp, "add x0, x0, %d\n", (int)(sizeof (MonoObject)));
+       fprintf (acfg->fp, "b %s\n", call_target);
+}
+
+static void
+arm64_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
+{
+       /* Similar to the specific trampolines, but use the rgctx reg instead of ip1 */
+
+       /* Load argument from first GOT slot */
+       g_assert (MONO_ARCH_RGCTX_REG == 27);
+       arm64_emit_load_got_slot (acfg, ARMREG_R27, offset);
+       /* Load generic trampoline address from second GOT slot */
+       arm64_emit_load_got_slot (acfg, ARMREG_R16, offset + 1);
+       fprintf (acfg->fp, "br x16\n");
+       *tramp_size = 7 * 4;
+}
+
+static void
+arm64_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
+{
+       guint8 buf [128];
+       guint8 *code, *labels [16];
+
+       /* Load parameter from GOT slot into ip1 */
+       arm64_emit_load_got_slot (acfg, ARMREG_R17, offset);
+
+       code = buf;
+       labels [0] = code;
+       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0);
+       arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
+       labels [1] = code;
+       arm_bcc (code, ARMCOND_EQ, 0);
+
+       /* End-of-loop check */
+       labels [2] = code;
+       arm_cbzx (code, ARMREG_IP0, 0);
+
+       /* Loop footer */
+       arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 2 * 8);
+       arm_b (code, labels [0]);
+
+       /* Match */
+       mono_arm_patch (labels [1], code, MONO_R_ARM64_BCC);
+       /* Load vtable slot addr */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
+       /* Load vtable slot */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0);
+       arm_brx (code, ARMREG_IP0);
+
+       /* No match */
+       mono_arm_patch (labels [2], code, MONO_R_ARM64_CBZ);
+       /* Load fail addr */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
+       arm_brx (code, ARMREG_IP0);
+
+       emit_code_bytes (acfg, buf, code - buf);
+
+       *tramp_size = code - buf + (3 * 4);
+}
+
+static void
+arm64_emit_gsharedvt_arg_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
+{
+       /* Similar to the specific trampolines, but the address is in the second slot */
+       /* Load argument from first GOT slot */
+       arm64_emit_load_got_slot (acfg, ARMREG_R17, offset);
+       /* Load generic trampoline address from second GOT slot */
+       arm64_emit_load_got_slot (acfg, ARMREG_R16, offset + 1);
+       fprintf (acfg->fp, "br x16\n");
+       *tramp_size = 7 * 4;
+}
+
 
 #endif
 
@@ -4966,7 +5291,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 +5326,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);
                }
 
@@ -10110,7 +10441,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        //acfg->aot_opts.print_skipped_methods = TRUE;
 
-#if !defined(ENABLE_GSHAREDVT)
+#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
        if (opts & MONO_OPT_GSHAREDVT) {
                aot_printerrf (acfg, "-O=gsharedvt not supported on this platform.\n");
                return 1;
@@ -10125,13 +10456,13 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 #endif
 
        if (acfg->aot_opts.llvm_only) {
-#ifndef ENABLE_GSHAREDVT
-               aot_printerrf (acfg, "--aot=llvmonly requires a runtime compiled with --enable-gsharedvt.\n");
+#ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
+               aot_printerrf (acfg, "--aot=llvmonly requires a runtime that supports gsharedvt.\n");
                return 1;
 #endif
        }
 
-#if defined(ENABLE_GSHAREDVT) && defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
+#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
        acfg->opts |= MONO_OPT_GSHAREDVT;
        opts |= MONO_OPT_GSHAREDVT;
 #endif
@@ -10347,13 +10678,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) {
@@ -10361,7 +10690,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..2d789a2f1767d43ecfcbce86822b9ad78132ea56 100644 (file)
@@ -8,6 +8,7 @@
  * (C) 2002 Ximian, Inc.
  * Copyright 2003-2011 Novell, Inc.
  * Copyright 2011 Xamarin, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -1986,7 +1987,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 +3060,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 a75bab23586eab4d4d92fadbde33c865897c48b0..cad20a06b24c5662be9729fd1cc30f83d87b6a1f 100644 (file)
@@ -33,23 +33,6 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
 
 #endif
 
-#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(ENABLE_GSHAREDVT)
-
-gboolean
-mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)
-{
-       return FALSE;
-}
-
-gpointer
-mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
-{
-       NOT_IMPLEMENTED;
-       return NULL;
-}
-
-#endif
-
 #ifndef MONO_ARCH_HAVE_DECOMPOSE_OPTS
 void
 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
index c6a23620c5676565fe57615b1b48f56beb2a8e2e..15cd67d60c69901a2fbee50eb36f1f13ed91911e 100644 (file)
@@ -2,6 +2,7 @@ using System;
 using System.Reflection;
 
 /*
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  * Regression tests for the mono JIT.
  *
  * Each test needs to be of the form:
index 1a4ea53fe1f9ecfa48455f4961f6e1c8f1283639..7b2bedd56470c901f27cba63a015a2309c382c16 100644 (file)
@@ -6,6 +6,7 @@
  *
  * (C) 2005 Ximian, Inc.  http://www.ximian.com
  * Copyright 2011 Xamarin Inc.  http://www.xamarin.com
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
  #include "mini.h"
 
index cd51ad72c94a6965fee19bda4aaad8c0cedc9951..24694376aacce167ba9e25b15709d8863268d232 100644 (file)
@@ -1,5 +1,6 @@
 # Copyright 2003-2011 Novell, Inc (http://www.novell.com)
 # Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+# Licensed under the MIT license. See LICENSE file in the project root for full license information.
 # arm cpu description file
 # this file is read by genmdesc to pruduce a table with all the relevant information
 # about the cpu instructions that may be used by the regsiter allocator, the scheduler
index 440e6a69e14b46711625758d458e12955ddc9f5a..a8eea0965d54bb34f9263672de5063974c378e48 100644 (file)
@@ -1,5 +1,6 @@
 # Copyright 2011-2013 Xamarin, Inc (http://www.xamarin.com)
 # Copyright 2003-2011 Novell, Inc (http://www.novell.com)
+# Licensed under the MIT license. See LICENSE file in the project root for full license information.
 # arm64 cpu description file
 # this file is read by genmdesc to pruduce a table with all the relevant information
 # about the cpu instructions that may be used by the regsiter allocator, the scheduler
index 4c791507cc3775777fb5e32e80d057292f1841e0..b2712b486eb1dcea61a4dcc220c2550953f907ca 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2009-2010 Novell, Inc.
  * Copyright 2011 Xamarin Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -6031,6 +6032,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 +6064,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 +6087,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 +6112,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 10c8c75e134d359dd829d023521131246a1f8f67..10a5bdfd5b40a943f3a0b627cd4cb91265ff7121 100644 (file)
@@ -6,6 +6,7 @@
  *
  * (C) 2002 Ximian, Inc.
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mini.h"
index ab3ba6333cce8f5c11d47acd8c0b7759ce421275..b4c8dc39056147e947786a6c25efdbeb80096296 100644 (file)
@@ -7,6 +7,7 @@
  *
  * (C) 2003 Ximian, Inc.
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <string.h>
 #include <mono/metadata/debug-helpers.h>
index 5b717fcd5e04dbd5f0ac006d916de79bdb802e9a..a84cd2f6ab049bf3bde009f94c6c947ece646446 100644 (file)
@@ -7,6 +7,7 @@
  *
  * (C) 2002-2003 Ximian, Inc.
  * (C) 2003-2006 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
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..06c0fd710fc830a14454225d2867b41b8823f999 100644 (file)
@@ -6,6 +6,7 @@
  *
  * (C) 2001 Ximian, Inc.
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -306,18 +307,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 +418,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 +432,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 333fd13b75420df017b11a5be0d7c2f41d32e56b..717443c9a67dcfa6056ba65dc63f468457059ead 100644 (file)
@@ -1 +1,597 @@
-#include "../../../mono-extensions/mono/mini/exceptions-arm64.c"
+/*
+ * exceptions-arm64.c: exception support for ARM64
+ *
+ * Copyright 2013 Xamarin Inc
+ *
+ * Based on exceptions-arm.c:
+ *
+ * Authors:
+ *   Dietmar Maurer (dietmar@ximian.com)
+ *   Paolo Molaro (lupus@ximian.com)
+ *
+ * (C) 2001 Ximian, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "mini.h"
+
+#include <mono/arch/arm64/arm64-codegen.h>
+#include <mono/metadata/abi-details.h>
+
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+#ifndef DISABLE_JIT
+
+gpointer
+mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *start, *code;
+       MonoJumpInfo *ji = NULL;
+       GSList *unwind_ops = NULL;
+       int i, ctx_reg, size;
+
+       size = 256;
+       code = start = mono_global_codeman_reserve (size);
+
+       arm_movx (code, ARMREG_IP0, ARMREG_R0);
+       ctx_reg = ARMREG_IP0;
+       /* Restore fregs */
+       for (i = 0; i < 32; ++i)
+               arm_ldrfpx (code, i, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, fregs) + (i * 8));
+       /* Restore gregs */
+       // FIXME: Restore less registers
+       // FIXME: fp should be restored later
+       code = mono_arm_emit_load_regarray (code, 0xffffffff & ~(1 << ctx_reg) & ~(1 << ARMREG_SP), ctx_reg, MONO_STRUCT_OFFSET (MonoContext, regs));
+       /* ip0/ip1 doesn't need to be restored */
+       /* ip1 = pc */
+       arm_ldrx (code, ARMREG_IP1, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, pc));
+       /* ip0 = sp */
+       arm_ldrx (code, ARMREG_IP0, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, regs) + (ARMREG_SP * 8));
+       /* Restore sp, ctx is no longer valid */
+       arm_movspx (code, ARMREG_SP, ARMREG_IP0); 
+       /* Branch to pc */
+       arm_brx (code, ARMREG_IP1);
+       /* Not reached */
+       arm_brk (code, 0);
+
+       g_assert ((code - start) < size);
+       mono_arch_flush_icache (start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
+       if (info)
+               *info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
+
+       return start;
+}
+
+gpointer
+mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *code;
+       guint8* start;
+       int size, offset, gregs_offset, fregs_offset, ctx_offset, num_fregs, frame_size;
+       MonoJumpInfo *ji = NULL;
+       GSList *unwind_ops = NULL;
+
+       size = 512;
+       start = code = mono_global_codeman_reserve (size);
+
+       /* Compute stack frame size and offsets */
+       offset = 0;
+       /* frame block */
+       offset += 2 * 8;
+       /* gregs */
+       gregs_offset = offset;
+       offset += 32 * 8;
+       /* fregs */
+       num_fregs = 8;
+       fregs_offset = offset;
+       offset += num_fregs * 8;
+       ctx_offset = offset;
+       ctx_offset += 8;
+       frame_size = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
+
+       /*
+        * We are being called from C code, ctx is in r0, the address to call is in r1.
+        * We need to save state, restore ctx, make the call, then restore the previous state,
+        * returning the value returned by the call.
+        */
+
+       /* Setup a frame */
+       arm_stpx_pre (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, -frame_size);
+       arm_movspx (code, ARMREG_FP, ARMREG_SP);
+
+       /* Save ctx */
+       arm_strx (code, ARMREG_R0, ARMREG_FP, ctx_offset);
+       /* Save gregs */
+       code = mono_arm_emit_store_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS | (1 << ARMREG_FP), ARMREG_FP, gregs_offset);
+       /* No need to save/restore fregs, since we don't currently use them */
+
+       /* Load regs from ctx */
+       code = mono_arm_emit_load_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, regs));
+       /* Load fp */
+       arm_ldrx (code, ARMREG_FP, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, regs) + (ARMREG_FP * 8));
+
+       /* Make the call */
+       arm_blrx (code, ARMREG_R1);
+       /* For filters, the result is in R0 */
+
+       /* Restore fp */
+       arm_ldrx (code, ARMREG_FP, ARMREG_SP, gregs_offset + (ARMREG_FP * 8));
+       /* Load ctx */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_FP, ctx_offset);
+       /* Save registers back to ctx */
+       /* This isn't strictly neccessary since we don't allocate variables used in eh clauses to registers */
+       code = mono_arm_emit_store_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoContext, regs));
+
+       /* Restore regs */
+       code = mono_arm_emit_load_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS, ARMREG_FP, gregs_offset);
+       /* Destroy frame */
+       code = mono_arm_emit_destroy_frame (code, frame_size, (1 << ARMREG_IP0));
+       arm_retx (code, ARMREG_LR);
+
+       g_assert ((code - start) < size);
+       mono_arch_flush_icache (start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
+       if (info)
+               *info = mono_tramp_info_create ("call_filter", start, code - start, ji, unwind_ops);
+
+       return start;
+}
+
+static gpointer 
+get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *start, *code;
+       MonoJumpInfo *ji = NULL;
+       GSList *unwind_ops = NULL;
+       int i, offset, gregs_offset, fregs_offset, frame_size, num_fregs;
+
+       code = start = mono_global_codeman_reserve (size);
+
+       /* We are being called by JITted code, the exception object/type token is in R0 */
+
+       /* Compute stack frame size and offsets */
+       offset = 0;
+       /* frame block */
+       offset += 2 * 8;
+       /* gregs */
+       gregs_offset = offset;
+       offset += 32 * 8;
+       /* fregs */
+       num_fregs = 8;
+       fregs_offset = offset;
+       offset += num_fregs * 8;
+       frame_size = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
+
+       /* Setup a frame */
+       arm_stpx_pre (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, -frame_size);
+       arm_movspx (code, ARMREG_FP, ARMREG_SP);
+
+       /* Save gregs */
+       code = mono_arm_emit_store_regarray (code, 0xffffffff, ARMREG_FP, gregs_offset);
+       if (corlib && !llvm)
+               /* The real LR is in R1 */
+               arm_strx (code, ARMREG_R1, ARMREG_FP, gregs_offset + (ARMREG_LR * 8));
+       /* Save fp/sp */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_FP, 0);
+       arm_strx (code, ARMREG_IP0, ARMREG_FP, gregs_offset + (ARMREG_FP * 8));
+       arm_addx_imm (code, ARMREG_IP0, ARMREG_FP, frame_size);
+       arm_strx (code, ARMREG_IP0, ARMREG_FP, gregs_offset + (ARMREG_SP * 8)); 
+       /* Save fregs */
+       for (i = 0; i < num_fregs; ++i)
+               arm_strfpx (code, ARMREG_D8 + i, ARMREG_FP, fregs_offset + (i * 8));
+
+       /* Call the C trampoline function */
+       /* Arg1 =  exception object/type token */
+       arm_movx (code, ARMREG_R0, ARMREG_R0);
+       /* Arg2 = caller ip */
+       if (corlib) {
+               if (llvm)
+                       arm_ldrx (code, ARMREG_R1, ARMREG_FP, gregs_offset + (ARMREG_LR * 8));
+               else
+                       arm_movx (code, ARMREG_R1, ARMREG_R1);
+       } else {
+               arm_ldrx (code, ARMREG_R1, ARMREG_FP, 8);
+       }
+       /* Arg 3 = gregs */
+       arm_addx_imm (code, ARMREG_R2, ARMREG_FP, gregs_offset);
+       /* Arg 4 = fregs */
+       arm_addx_imm (code, ARMREG_R3, ARMREG_FP, fregs_offset);
+       /* Arg 5 = corlib */
+       arm_movzx (code, ARMREG_R4, corlib ? 1 : 0, 0);
+       /* Arg 6 = rethrow */
+       arm_movzx (code, ARMREG_R5, rethrow ? 1 : 0, 0);
+       /* Call the function */
+       if (aot) {
+               const char *icall_name;
+
+               if (resume_unwind)
+                       icall_name = "mono_arm_resume_unwind";
+               else
+                       icall_name = "mono_arm_throw_exception";
+
+               code = mono_arm_emit_aotconst (&ji, code, start, ARMREG_LR, MONO_PATCH_INFO_JIT_ICALL_ADDR, icall_name);
+       } else {
+               gpointer icall_func;
+
+               if (resume_unwind)
+                       icall_func = mono_arm_resume_unwind;
+               else
+                       icall_func = mono_arm_throw_exception;
+
+               code = mono_arm_emit_imm64 (code, ARMREG_LR, (guint64)icall_func);
+       }
+       arm_blrx (code, ARMREG_LR);
+       /* This shouldn't return */
+       arm_brk (code, 0x0);
+
+       g_assert ((code - start) < size);
+       mono_arch_flush_icache (start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
+       if (info)
+               *info = mono_tramp_info_create (tramp_name, start, code - start, ji, unwind_ops);
+
+       return start;
+}
+
+gpointer 
+mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
+{
+       return get_throw_trampoline (256, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot);
+}
+
+gpointer
+mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
+{
+       return get_throw_trampoline (256, FALSE, TRUE, FALSE, FALSE, "rethrow_exception", info, aot);
+}
+
+gpointer 
+mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
+{
+       return get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot);
+}
+
+GSList*
+mono_arm_get_exception_trampolines (gboolean aot)
+{
+       MonoTrampInfo *info;
+       GSList *tramps = NULL;
+
+       /* LLVM uses the normal trampolines, but with a different name */
+       get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", &info, aot);
+       tramps = g_slist_prepend (tramps, info);
+       
+       get_throw_trampoline (256, TRUE, FALSE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", &info, aot);
+       tramps = g_slist_prepend (tramps, info);
+
+       get_throw_trampoline (256, FALSE, FALSE, FALSE, TRUE, "llvm_resume_unwind_trampoline", &info, aot);
+       tramps = g_slist_prepend (tramps, info);
+
+       return tramps;
+}
+
+#else /* DISABLE_JIT */
+
+gpointer
+mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer 
+mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer 
+mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}      
+
+GSList*
+mono_arm_get_exception_trampolines (gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+#endif /* !DISABLE_JIT */
+
+void
+mono_arch_exceptions_init (void)
+{
+       guint8 *tramp;
+       GSList *tramps, *l;
+
+       if (mono_aot_only) {
+               tramp = mono_aot_get_trampoline ("llvm_throw_corlib_exception_trampoline");
+               mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_trampoline", NULL, TRUE);
+               tramp = mono_aot_get_trampoline ("llvm_throw_corlib_exception_abs_trampoline");
+               mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_abs_trampoline", NULL, TRUE);
+               tramp = mono_aot_get_trampoline ("llvm_resume_unwind_trampoline");
+               mono_register_jit_icall (tramp, "llvm_resume_unwind_trampoline", NULL, TRUE);
+       } else {
+               tramps = mono_arm_get_exception_trampolines (FALSE);
+               for (l = tramps; l; l = l->next) {
+                       MonoTrampInfo *info = l->data;
+
+                       mono_register_jit_icall (info->code, g_strdup (info->name), NULL, TRUE);
+                       mono_tramp_info_register (info, NULL);
+               }
+               g_slist_free (tramps);
+       }
+}
+
+/*
+ * mono_arm_throw_exception:
+ *
+ *   This function is called by the exception trampolines.
+ * FP_REGS points to the 8 callee saved fp regs.
+ */
+void
+mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow)
+{
+       MonoError error;
+       MonoContext ctx;
+       MonoObject *exc = NULL;
+       guint32 ex_token_index, ex_token;
+
+       if (!corlib)
+               exc = arg;
+       else {
+               ex_token_index = (guint64)arg;
+               ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
+               exc = (MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token);
+       }
+
+       /* Adjust pc so it points into the call instruction */
+       pc -= 4;
+
+       /* Initialize a ctx based on the arguments */
+       memset (&ctx, 0, sizeof (MonoContext));
+       memcpy (&(ctx.regs [0]), int_regs, sizeof (mgreg_t) * 32);
+       memcpy (&(ctx.fregs [ARMREG_D8]), fp_regs, sizeof (double) * 8);
+       ctx.pc = pc;
+
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
+               MonoException *mono_ex = (MonoException*)exc;
+               if (!rethrow)
+                       mono_ex->stack_trace = NULL;
+       }
+       mono_error_assert_ok (&error);
+
+       mono_handle_exception (&ctx, exc);
+
+       mono_restore_context (&ctx);
+}
+
+void
+mono_arm_resume_unwind (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow)
+{
+       MonoContext ctx;
+
+       /* Adjust pc so it points into the call instruction */
+       pc -= 4;
+
+       /* Initialize a ctx based on the arguments */
+       memset (&ctx, 0, sizeof (MonoContext));
+       memcpy (&(ctx.regs [0]), int_regs, sizeof (mgreg_t) * 32);
+       memcpy (&(ctx.fregs [ARMREG_D8]), fp_regs, sizeof (double) * 8);
+       ctx.pc = pc;
+
+       mono_resume_unwind (&ctx);
+}
+
+/* 
+ * mono_arch_unwind_frame:
+ *
+ * See exceptions-amd64.c for docs;
+ */
+gboolean
+mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls, 
+                                                        MonoJitInfo *ji, MonoContext *ctx, 
+                                                        MonoContext *new_ctx, MonoLMF **lmf,
+                                                        mgreg_t **save_locations,
+                                                        StackFrameInfo *frame)
+{
+       gpointer ip = MONO_CONTEXT_GET_IP (ctx);
+
+       memset (frame, 0, sizeof (StackFrameInfo));
+       frame->ji = ji;
+
+       *new_ctx = *ctx;
+
+       if (ji != NULL) {
+               mgreg_t regs [MONO_MAX_IREGS + 8 + 1];
+               guint8 *cfa;
+               guint32 unwind_info_len;
+               guint8 *unwind_info;
+
+               frame->type = FRAME_TYPE_MANAGED;
+
+               unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
+
+               memcpy (regs, &new_ctx->regs, sizeof (mgreg_t) * 32);
+               /* v8..v15 are callee saved */
+               memcpy (regs + MONO_MAX_IREGS, &(new_ctx->fregs [8]), sizeof (mgreg_t) * 8);
+
+               mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, 
+                                                  (guint8*)ji->code_start + ji->code_size,
+                                                  ip, NULL, regs, MONO_MAX_IREGS + 8,
+                                                  save_locations, MONO_MAX_IREGS, &cfa);
+
+               memcpy (&new_ctx->regs, regs, sizeof (mgreg_t) * 32);
+               memcpy (&(new_ctx->fregs [8]), regs + MONO_MAX_IREGS, sizeof (mgreg_t) * 8);
+
+               new_ctx->pc = regs [ARMREG_LR];
+               new_ctx->regs [ARMREG_SP] = (mgreg_t)cfa;
+
+               if (*lmf && (*lmf)->gregs [MONO_ARCH_LMF_REG_SP] && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->gregs [MONO_ARCH_LMF_REG_SP])) {
+                       /* remove any unused lmf */
+                       *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3);
+               }
+
+               /* we substract 1, so that the IP points into the call instruction */
+               new_ctx->pc--;
+
+               return TRUE;
+       } else if (*lmf) {
+               if (((gsize)(*lmf)->previous_lmf) & 2) {
+                       /* 
+                        * This LMF entry is created by the soft debug code to mark transitions to
+                        * managed code done during invokes.
+                        */
+                       MonoLMFExt *ext = (MonoLMFExt*)(*lmf);
+
+                       g_assert (ext->debugger_invoke);
+
+                       memcpy (new_ctx, &ext->ctx, sizeof (MonoContext));
+
+                       *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3);
+
+                       frame->type = FRAME_TYPE_DEBUGGER_INVOKE;
+
+                       return TRUE;
+               }
+
+               frame->type = FRAME_TYPE_MANAGED_TO_NATIVE;
+
+               ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->pc, NULL);
+               if (!ji)
+                       return FALSE;
+
+               g_assert (MONO_ARCH_LMF_REGS == ((0x3ff << 19) | (1 << ARMREG_FP) | (1 << ARMREG_SP)));
+               memcpy (&new_ctx->regs [ARMREG_R19], &(*lmf)->gregs [0], sizeof (mgreg_t) * 10);
+               new_ctx->regs [ARMREG_FP] = (*lmf)->gregs [MONO_ARCH_LMF_REG_FP];
+               new_ctx->regs [ARMREG_SP] = (*lmf)->gregs [MONO_ARCH_LMF_REG_SP];
+               new_ctx->pc = (*lmf)->pc;
+
+               /* we substract 1, so that the IP points into the call instruction */
+               new_ctx->pc--;
+
+               *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3);
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+void
+mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
+{
+       mono_sigctx_to_monoctx (sigctx, mctx);
+}
+
+void
+mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
+{
+       mono_monoctx_to_sigctx (mctx, sigctx);
+}
+
+/*
+ * handle_exception:
+ *
+ *   Called by resuming from a signal handler.
+ */
+static void
+handle_signal_exception (gpointer obj)
+{
+       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       MonoContext ctx;
+
+       memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
+
+       mono_handle_exception (&ctx, obj);
+
+       mono_restore_context (&ctx);
+}
+
+/*
+ * This is the function called from the signal handler
+ */
+gboolean
+mono_arch_handle_exception (void *ctx, gpointer obj)
+{
+#if defined(MONO_CROSS_COMPILE)
+       g_assert_not_reached ();
+#else
+       MonoJitTlsData *jit_tls;
+       void *sigctx = ctx;
+
+       /*
+        * Resume into the normal stack and handle the exception there.
+        */
+       jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+
+       /* Pass the ctx parameter in TLS */
+       mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
+       /* The others in registers */
+       UCONTEXT_REG_R0 (sigctx) = (gsize)obj;
+
+       UCONTEXT_REG_PC (sigctx) = (gsize)handle_signal_exception;
+       UCONTEXT_REG_SP (sigctx) = UCONTEXT_REG_SP (sigctx) - MONO_ARCH_REDZONE_SIZE;
+#endif
+
+       return TRUE;
+}
+
+gpointer
+mono_arch_ip_from_context (void *sigctx)
+{
+#ifdef MONO_CROSS_COMPILE
+       g_assert_not_reached ();
+       return NULL;
+#else
+       return (gpointer)UCONTEXT_REG_PC (sigctx);
+#endif
+}
+
+void
+mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
+{
+       mgreg_t sp = (mgreg_t)MONO_CONTEXT_GET_SP (ctx);
+
+       // FIXME:
+       g_assert (!user_data);
+
+       /* Allocate a stack frame */
+       sp -= 32;
+       MONO_CONTEXT_SET_SP (ctx, sp);
+
+       mono_arch_setup_resume_sighandler_ctx (ctx, async_cb);
+}
+
+/*
+ * mono_arch_setup_resume_sighandler_ctx:
+ *
+ *   Setup CTX so execution continues at FUNC.
+ */
+void
+mono_arch_setup_resume_sighandler_ctx (MonoContext *ctx, gpointer func)
+{
+       MONO_CONTEXT_SET_IP (ctx,func);
+}
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..fc2390d0b8596511ce63b68edea34504b213e227 100644 (file)
@@ -13,6 +13,7 @@
 /*              Dietmar Maurer (dietmar@ximian.com)                */
 /*                                                                 */
 /* Copyright   - 2001 Ximian, Inc.                                 */
+/* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
 /*                                                                 */
 /*------------------------------------------------------------------*/
 
@@ -240,6 +241,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 +263,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 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 92fd95a88cca55c1416778806b20316a84820bbe..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
index b67cb5f1508f03a58db4225668c10980ab0da4c0..6d87c74e92d01e1fb087a6f8c19e57dc65084c08 100644 (file)
@@ -8,6 +8,7 @@
  * (C) 2002 Ximian, Inc.
  * Copyright 2003-2011 Novell Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <math.h>
@@ -102,11 +103,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 +1182,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 +1197,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 +1216,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 +1234,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 +1255,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 +1268,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 +1335,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 f26d6597bb52b970dcdef31455f800478e39cd59..c897893074057b178071b619e5420ae7a36b5b6e 100644 (file)
@@ -6,6 +6,7 @@
  *
  * (C) 2002 Ximian, Inc.
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 6a7c49c0629f85bca6005c0976241ffd6cb06830..7fef6b85cb9741b955d701ae1082822fea5cca66 100644 (file)
@@ -4,7 +4,7 @@
 // (C) 2009-2011 Novell, Inc.
 // Copyright 2011-2015 Xamarin, Inc (http://www.xamarin.com)
 //
-
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 //
 // Mono's internal header files are not C++ clean, so avoid including them if 
 // possible
index 2120fa08728e6c39a3863b4ab80ce95dc3c5b499..f23c5ff3bb9e5c1278220b19656c554e6f85d527 100644 (file)
@@ -10,6 +10,7 @@
  *
  * (C) 2006 Novell, Inc.  http://www.novell.com
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 3d295db2a358a479cdce82160444b1066145b036..aed8309edf6ef795d06aca1840712df51809916c 100644 (file)
@@ -8,6 +8,7 @@
  * (C) 2002 Ximian, Inc.
  * Copyright 2003-2010 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -8578,7 +8579,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 +11650,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;
                                                        }
                                                }
diff --git a/mono/mini/mini-amd64-gsharedvt.c b/mono/mini/mini-amd64-gsharedvt.c
new file mode 100644 (file)
index 0000000..c3e2e99
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * mini-amd64-gsharedvt.c: libcorkscrew-based native unwinder
+ *
+ * Authors:
+ *   Zoltan Varga <vargaz@gmail.com>
+ *   Rodrigo Kumpera <kumpera@gmail.com>
+ *   Andi McClure <andi.mcclure@xamarin.com>
+ *
+ * Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <config.h>
+#include <glib.h>
+
+#include <mono/metadata/abi-details.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/marshal.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/mono-debug-debugger.h>
+#include <mono/metadata/profiler-private.h>
+#include <mono/metadata/gc-internals.h>
+#include <mono/arch/amd64/amd64-codegen.h>
+
+#include <mono/utils/memcheck.h>
+
+#include "mini.h"
+#include "mini-amd64.h"
+#include "mini-amd64-gsharedvt.h"
+#include "debugger-agent.h"
+
+#if defined (MONO_ARCH_GSHAREDVT_SUPPORTED)
+
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+gboolean
+mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)
+{
+       return FALSE;
+}
+
+static const char*
+storage_name (ArgStorage st)
+{
+       switch (st) {
+       case ArgInIReg: return "ArgInIReg";
+       case ArgInFloatSSEReg: return "ArgInFloatSSEReg";
+       case ArgInDoubleSSEReg: return "ArgInDoubleSSEReg";
+       case ArgOnStack: return "ArgOnStack";
+       case ArgValuetypeInReg: return "ArgValuetypeInReg";
+       case ArgValuetypeAddrInIReg: return "ArgValuetypeAddrInIReg";
+       case ArgGSharedVtInReg: return "ArgGSharedVtInReg";
+       case ArgGSharedVtOnStack: return "ArgGSharedVtOnStack";
+       case ArgNone: return "ArgNone";
+       default: return "unknown";
+       }
+}
+
+static char *
+arg_info_desc (ArgInfo *info)
+{
+       GString *str = g_string_new ("");
+
+       g_string_append_printf (str, "offset %d reg %s storage %s nregs %d", info->offset, mono_arch_regname (info->reg), storage_name (info->storage), info->nregs);
+       if (info->storage == ArgValuetypeInReg)
+               g_string_append_printf (str, " {(%s %s), (%s %s)", 
+                       storage_name (info->pair_storage [0]),
+                       mono_arch_regname (info->pair_regs [0]),
+                       storage_name (info->pair_storage [1]),
+                       mono_arch_regname (info->pair_regs [1]));
+
+       return g_string_free (str, FALSE);
+}
+
+static inline void
+add_to_map (GPtrArray *map, int src, int dst)
+{
+       g_ptr_array_add (map, GUINT_TO_POINTER (src));
+       g_ptr_array_add (map, GUINT_TO_POINTER (dst));
+}
+
+/*
+ * Slot mapping:
+ * 0..5  - rdi, rsi, rdx, rcx, r8, r9
+ * 6..13 - xmm0..xmm7
+ * 14..  - stack slots
+ */
+static inline int
+map_reg (int reg)
+{
+       int i = 0;
+       for (i = 0; i < PARAM_REGS; ++i) {
+               if (param_regs [i] == reg)
+                       return i;
+       }
+       g_error ("Invalid argument register number %d", reg);
+       return -1;
+}
+
+static inline int
+map_freg (int reg)
+{
+       return reg + PARAM_REGS;
+}
+
+static inline int
+map_stack_slot (int slot)
+{
+       return slot + PARAM_REGS + FLOAT_PARAM_REGS;
+}
+
+/*
+Format for the source descriptor:
+
+
+Format for the destination descriptor:
+       bits 0:15  - source register
+       bits 16:23 - return marshal
+       bits 24:32 - slot count
+*/
+#define SRC_DESCRIPTOR_MARSHAL_SHIFT 16
+#define SRC_DESCRIPTOR_MARSHAL_MASK 0x0Ff
+
+#define SLOT_COUNT_SHIFT 24
+#define SLOT_COUNT_MASK 0xff
+#define SLOT_BYTE_SIZE 8
+
+static int
+get_arg_slots (ArgInfo *ainfo, int **out_slots, gboolean is_source_argument)
+{
+       int sreg = ainfo->reg;
+       int sslot = ainfo->offset / 8;
+       int *src = NULL;
+       int i, nsrc;
+
+       switch (ainfo->storage) {
+       case ArgInIReg:
+               nsrc = 1;
+               src = g_malloc (nsrc * sizeof (int));
+               src [0] = map_reg (sreg);
+               break;
+       case ArgValuetypeInReg:
+               nsrc = ainfo->nregs;
+               src = g_malloc (nsrc * sizeof (int));
+               for (i = 0; i < ainfo->nregs; ++i)
+                       src [i] = map_reg (ainfo->pair_regs [i]);
+               break;
+       case ArgOnStack:
+               nsrc = ainfo->arg_size / SLOT_BYTE_SIZE;
+               src = g_malloc (nsrc * sizeof (int));
+               // is_source_argument adds 2 because we're skipping over the old BBP and the return address
+               // XXX this is a very fragile setup as changes in alignment for the caller reg array can cause the magic number be 3
+               for (i = 0; i < nsrc; ++i)
+                       src [i] = map_stack_slot (sslot + i + (is_source_argument ? 2 : 0));
+               break;
+       case ArgInDoubleSSEReg:
+       case ArgInFloatSSEReg:
+               nsrc = 1;
+               src = g_malloc (nsrc * sizeof (int));
+               src [0] = map_freg (sreg);
+               break;
+       default:
+               NOT_IMPLEMENTED;
+               break;
+       }
+
+       *out_slots = src;
+       return nsrc;
+}
+
+// Once src is known, operate on the dst
+static void
+handle_marshal_when_src_gsharedvt (ArgInfo *dst_info, int *arg_marshal, int *arg_slots)
+{
+       switch (dst_info->storage) {
+               case ArgInIReg:
+               case ArgInDoubleSSEReg:
+               case ArgInFloatSSEReg:
+                       *arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL;
+                       *arg_slots = 1;
+                       break;
+               case ArgOnStack:
+                       *arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL;
+                       g_assert (dst_info->arg_size % SLOT_BYTE_SIZE == 0); // Assert quadword aligned
+                       *arg_slots = dst_info->arg_size / SLOT_BYTE_SIZE;
+                       break;
+               case ArgValuetypeInReg:
+                       *arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL;
+                       *arg_slots = dst_info->nregs;
+                       break;
+               default:
+                       NOT_IMPLEMENTED; // Inappropriate value: if dst and src are gsharedvt at once, we shouldn't be here
+                       break;
+       }
+}
+
+// Once dst is known, operate on the src
+static void
+handle_marshal_when_dst_gsharedvt (ArgInfo *src_info, int *arg_marshal)
+{
+       switch (src_info->storage) {
+               case ArgInIReg:
+               case ArgInDoubleSSEReg:
+               case ArgInFloatSSEReg:
+               case ArgValuetypeInReg:
+               case ArgOnStack:
+                       *arg_marshal = GSHAREDVT_ARG_BYVAL_TO_BYREF;
+                       break;
+               default:
+                       NOT_IMPLEMENTED; // See above
+                       break;
+       }
+}
+
+static void
+handle_map_when_gsharedvt_in_reg (ArgInfo *reg_info, int *n, int **map)
+{
+       *n = 1;
+       *map = g_new0 (int, 1);
+       (*map) [0] = map_reg (reg_info->reg);
+}
+
+static void
+handle_map_when_gsharedvt_on_stack (ArgInfo *reg_info, int *n, int **map, gboolean is_source_argument)
+{
+       *n = 1;
+       *map = g_new0 (int, 1);
+       int sslot = reg_info->offset / SLOT_BYTE_SIZE;
+       (*map) [0] = map_stack_slot (sslot + (is_source_argument ? 2 : 0)); // see get_arg_slots
+}
+
+gpointer
+mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
+{
+       GSharedVtCallInfo *info;
+       CallInfo *caller_cinfo, *callee_cinfo;
+       MonoMethodSignature *caller_sig, *callee_sig;
+       int aindex, i;
+       gboolean var_ret = FALSE;
+       CallInfo *cinfo, *gcinfo;
+       MonoMethodSignature *sig, *gsig;
+       GPtrArray *map;
+
+       if (gsharedvt_in) {
+               caller_sig = normal_sig;
+               callee_sig = gsharedvt_sig;
+               caller_cinfo = mono_arch_get_call_info (NULL, caller_sig);
+               callee_cinfo = mono_arch_get_call_info (NULL, callee_sig);
+       } else {
+               callee_sig = normal_sig;
+               caller_sig = gsharedvt_sig;
+               callee_cinfo = mono_arch_get_call_info (NULL, callee_sig);
+               caller_cinfo = mono_arch_get_call_info (NULL, caller_sig);
+       }
+
+       /*
+        * If GSHAREDVT_IN is true, this means we are transitioning from normal to gsharedvt code. The caller uses the
+        * normal call signature, while the callee uses the gsharedvt signature.
+        * If GSHAREDVT_IN is false, its the other way around.
+        */
+
+       /* sig/cinfo describes the normal call, while gsig/gcinfo describes the gsharedvt call */
+       if (gsharedvt_in) {
+               sig = caller_sig;
+               gsig = callee_sig;
+               cinfo = caller_cinfo;
+               gcinfo = callee_cinfo;
+       } else {
+               sig = callee_sig;
+               gsig = caller_sig;
+               cinfo = callee_cinfo;
+               gcinfo = caller_cinfo;
+       }
+
+       DEBUG_AMD64_GSHAREDVT_PRINT ("source sig: (%s) return (%s)\n", mono_signature_get_desc (caller_sig, FALSE), mono_type_full_name (mono_signature_get_return_type (caller_sig))); // Leak
+       DEBUG_AMD64_GSHAREDVT_PRINT ("dest sig: (%s) return (%s)\n", mono_signature_get_desc (callee_sig, FALSE), mono_type_full_name (mono_signature_get_return_type (callee_sig)));
+
+       if (gcinfo->ret.is_gsharedvt_return_value) {
+               /*
+                * The return type is gsharedvt
+                */
+               var_ret = TRUE;
+       }
+
+       /*
+        * The stack looks like this:
+        * <arguments>
+        * <trampoline frame>
+        * <call area>
+        * We have to map the stack slots in <arguments> to the stack slots in <call area>.
+        */
+       map = g_ptr_array_new ();
+
+       for (aindex = 0; aindex < cinfo->nargs; ++aindex) {
+               ArgInfo *src_info = &caller_cinfo->args [aindex];
+               ArgInfo *dst_info = &callee_cinfo->args [aindex];
+               int *src = NULL, *dst = NULL;
+               int nsrc = -1, ndst = -1, nslots = 0;
+
+               int arg_marshal = GSHAREDVT_ARG_NONE;
+               int arg_slots = 0; // Size in quadwords
+               DEBUG_AMD64_GSHAREDVT_PRINT ("-- arg %d in (%s) out (%s)\n", aindex, arg_info_desc (src_info), arg_info_desc (dst_info));
+
+               switch (src_info->storage) {
+               case ArgInIReg:
+               case ArgInDoubleSSEReg:
+               case ArgInFloatSSEReg:
+               case ArgValuetypeInReg:
+               case ArgOnStack:
+                       nsrc = get_arg_slots (src_info, &src, TRUE);
+                       break;
+               case ArgGSharedVtInReg:
+                       handle_marshal_when_src_gsharedvt (dst_info, &arg_marshal, &arg_slots);
+                       handle_map_when_gsharedvt_in_reg (src_info, &nsrc, &src);
+                       break;
+               case ArgGSharedVtOnStack:
+                       handle_marshal_when_src_gsharedvt (dst_info, &arg_marshal, &arg_slots);
+                       handle_map_when_gsharedvt_on_stack (src_info, &nsrc, &src, TRUE);
+                       break;
+               default:
+                       g_error ("Gsharedvt can't handle source arg type %d", (int)src_info->storage); // Inappropriate value: ArgValuetypeAddrInIReg is for returns only
+               }
+
+               switch (dst_info->storage) {
+               case ArgInIReg:
+               case ArgInDoubleSSEReg:
+               case ArgInFloatSSEReg:
+               case ArgOnStack:
+               case ArgValuetypeInReg:
+                       ndst = get_arg_slots (dst_info, &dst, FALSE);
+                       break;
+               case ArgGSharedVtInReg:
+                       handle_marshal_when_dst_gsharedvt (src_info, &arg_marshal);
+                       handle_map_when_gsharedvt_in_reg (dst_info, &ndst, &dst);
+                       break;
+               case ArgGSharedVtOnStack:
+                       handle_marshal_when_dst_gsharedvt (src_info, &arg_marshal);
+                       handle_map_when_gsharedvt_on_stack (dst_info, &ndst, &dst, FALSE);
+                       break;
+               default:
+                       g_error ("Gsharedvt can't handle dest arg type %d", (int)dst_info->storage); // See above
+               }
+               if (nsrc)
+                       src [0] |= (arg_marshal << SRC_DESCRIPTOR_MARSHAL_SHIFT) | (arg_slots << SLOT_COUNT_SHIFT);
+
+               /* Merge and add to the global list*/
+               nslots = MIN (nsrc, ndst);
+               DEBUG_AMD64_GSHAREDVT_PRINT ("nsrc %d ndst %d\n", nsrc, ndst);
+
+               for (i = 0; i < nslots; ++i)
+                       add_to_map (map, src [i], dst [i]);
+
+               g_free (src);
+               g_free (dst);
+       }
+
+       DEBUG_AMD64_GSHAREDVT_PRINT ("-- return in (%s) out (%s) var_ret %d\n", arg_info_desc (&caller_cinfo->ret),  arg_info_desc (&callee_cinfo->ret), var_ret);
+
+       if (cinfo->ret.storage == ArgValuetypeAddrInIReg) {
+               /* Both the caller and the callee pass the vtype ret address in r8 */
+               g_assert (cinfo->ret.storage == gcinfo->ret.storage);
+               add_to_map (map, map_reg (cinfo->ret.reg), map_reg (cinfo->ret.reg));
+       }
+
+       info = mono_domain_alloc0 (mono_domain_get (), sizeof (GSharedVtCallInfo) + (map->len * sizeof (int)));
+       info->addr = addr;
+       info->stack_usage = callee_cinfo->stack_usage;
+       info->ret_marshal = GSHAREDVT_RET_NONE;
+       info->gsharedvt_in = gsharedvt_in ? 1 : 0;
+       info->vret_slot = -1;
+       info->calli = calli;
+
+       if (var_ret) {
+               g_assert (gcinfo->ret.is_gsharedvt_return_value);
+               info->vret_arg_reg = map_reg (gcinfo->ret.reg);
+               DEBUG_AMD64_GSHAREDVT_PRINT ("mapping vreg_arg_reg to %d in reg %s\n", info->vret_arg_reg, mono_arch_regname (gcinfo->ret.reg));
+       } else {
+               info->vret_arg_reg = -1;
+       }
+
+#ifdef DEBUG_AMD64_GSHAREDVT
+       printf ("final map:\n");
+       for (i = 0; i < map->len; i += 2) {
+               printf ("\t[%d] src %x dst %x\n ", 
+                       i / 2,
+                       GPOINTER_TO_UINT (g_ptr_array_index (map, i)),
+                       GPOINTER_TO_UINT (g_ptr_array_index (map, i + 1)));
+       }
+#endif
+
+       info->vcall_offset = vcall_offset;
+       info->map_count = map->len / 2;
+       for (i = 0; i < map->len; ++i)
+               info->map [i] = GPOINTER_TO_UINT (g_ptr_array_index (map, i));
+       g_ptr_array_free (map, TRUE);
+
+       /* Compute return value marshalling */
+       if (var_ret) {
+               /* Compute return value marshalling */
+               switch (cinfo->ret.storage) {
+               case ArgInIReg:
+                       if (!gsharedvt_in || sig->ret->byref) {
+                               info->ret_marshal = GSHAREDVT_RET_IREGS_1;
+                       } else {
+                               MonoType *ret = sig->ret;
+
+                               // Unwrap enums
+                               if (ret->type == MONO_TYPE_VALUETYPE)
+                                       ret = mini_type_get_underlying_type (ret);
+
+                               switch (ret->type) {
+                               case MONO_TYPE_I1:
+                                       info->ret_marshal = GSHAREDVT_RET_I1;
+                                       break;
+                               case MONO_TYPE_BOOLEAN:
+                               case MONO_TYPE_U1:
+                                       info->ret_marshal = GSHAREDVT_RET_U1;
+                                       break;
+                               case MONO_TYPE_I2:
+                                       info->ret_marshal = GSHAREDVT_RET_I2;
+                                       break;
+                               case MONO_TYPE_CHAR:
+                               case MONO_TYPE_U2:
+                                       info->ret_marshal = GSHAREDVT_RET_U2;
+                                       break;
+                               case MONO_TYPE_I4:
+                                       info->ret_marshal = GSHAREDVT_RET_I4;
+                                       break;
+                               case MONO_TYPE_U4:
+                                       info->ret_marshal = GSHAREDVT_RET_U4;
+                                       break;
+                               case MONO_TYPE_I:
+                               case MONO_TYPE_U:
+                               case MONO_TYPE_PTR:
+                               case MONO_TYPE_FNPTR:
+                               case MONO_TYPE_CLASS:
+                               case MONO_TYPE_OBJECT:
+                               case MONO_TYPE_SZARRAY:
+                               case MONO_TYPE_ARRAY:
+                               case MONO_TYPE_STRING:
+                               case MONO_TYPE_U8:
+                               case MONO_TYPE_I8:
+                                       info->ret_marshal = GSHAREDVT_RET_I8;
+                                       break;
+
+                               default:
+                                       g_error ("Gsharedvt can't handle dst type [%d]", (int)sig->ret->type);
+                               }
+                       }
+                       break;
+               case ArgValuetypeInReg:
+                       info->ret_marshal = GSHAREDVT_RET_IREGS_1 - 1 + cinfo->ret.nregs;
+                       g_assert (cinfo->ret.nregs == 1); // ABI supports 2-register return but we do not implement this.
+                       break;
+               case ArgInDoubleSSEReg:
+               case ArgInFloatSSEReg:
+                       info->ret_marshal = GSHAREDVT_RET_R8;
+                       break;
+               case ArgValuetypeAddrInIReg:
+                       break;
+               default:
+                       g_error ("Can't marshal return of storage [%d] %s", (int)cinfo->ret.storage, storage_name (cinfo->ret.storage));
+               }
+
+               if (gsharedvt_in && cinfo->ret.storage != ArgValuetypeAddrInIReg) {
+                       /* Allocate stack space for the return value */
+                       info->vret_slot = map_stack_slot (info->stack_usage / sizeof (gpointer));
+                       info->stack_usage += mono_type_stack_size_internal (normal_sig->ret, NULL, FALSE) + sizeof (gpointer);
+               }
+               DEBUG_AMD64_GSHAREDVT_PRINT ("RET marshal is %s\n", ret_marshal_name [info->ret_marshal]);
+       }
+
+       info->stack_usage = ALIGN_TO (info->stack_usage, MONO_ARCH_FRAME_ALIGNMENT);
+
+       DEBUG_AMD64_GSHAREDVT_PRINT ("allocated an info at %p stack usage %d\n", info, info->stack_usage);
+       return info;
+}
+
+#endif
\ No newline at end of file
diff --git a/mono/mini/mini-amd64-gsharedvt.h b/mono/mini/mini-amd64-gsharedvt.h
new file mode 100644 (file)
index 0000000..3e3d56c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * mini-exceptions-native-unwinder.c: libcorkscrew-based native unwinder
+ *
+ * Authors:
+ *   Zoltan Varga <vargaz@gmail.com>
+ *   Rodrigo Kumpera <kumpera@gmail.com>
+ *   Andi McClure <andi.mcclure@xamarin.com>
+ *
+ * Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef MINI_AMD64_GSHAREDVT_H
+#define MINI_AMD64_GSHAREDVT_H
+
+typedef enum {
+       GSHAREDVT_ARG_NONE = 0,
+       GSHAREDVT_ARG_BYVAL_TO_BYREF,
+       GSHAREDVT_ARG_BYREF_TO_BYVAL,
+} GSharedVtArgMarshal;
+
+typedef enum {
+       GSHAREDVT_RET_NONE = 0,
+       GSHAREDVT_RET_I1,      // 1 byte integer
+       GSHAREDVT_RET_U1,      // 1 byte unsigned
+       GSHAREDVT_RET_I2,      // 2 byte integer
+       GSHAREDVT_RET_U2,      // 2 byte unsigned
+       GSHAREDVT_RET_I4,      // 4 byte integer
+       GSHAREDVT_RET_U4,      // 4 byte unsigned
+       GSHAREDVT_RET_I8,      // 8 byte integer
+       GSHAREDVT_RET_IREGS_1, // Load in first return register
+       GSHAREDVT_RET_R8,     // Double
+       GSHAREDVT_RET_NUM,
+} GSharedVtRetMarshal;
+
+static const char* ret_marshal_name[] = {
+       "GSHAREDVT_RET_NONE",
+       "GSHAREDVT_RET_I1",
+       "GSHAREDVT_RET_U1",
+       "GSHAREDVT_RET_I2",
+       "GSHAREDVT_RET_U2",
+       "GSHAREDVT_RET_I4",
+       "GSHAREDVT_RET_U4",
+       "GSHAREDVT_RET_I8",
+       "GSHAREDVT_RET_IREGS_1",
+       "GSHAREDVT_RET_R8",
+       "GSHAREDVT_RET_NUM",
+};
+
+#ifdef DEBUG_AMD64_GSHAREDVT
+#define DEBUG_AMD64_GSHAREDVT_PRINT printf
+#else
+#define DEBUG_AMD64_GSHAREDVT_PRINT(...)
+#endif
+
+#endif /* MINI_AMD64_GSHAREDVT_H */
\ No newline at end of file
index 5b386a904f0f8a97c929a2093aaf70b5109d3102..18e48283d95cf103e25714f8d4478a8276a654f8 100644 (file)
@@ -12,6 +12,7 @@
  * (C) 2003 Ximian, Inc.
  * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "mini.h"
 #include <string.h>
@@ -479,48 +480,6 @@ mono_amd64_patch (unsigned char* code, gpointer target)
        amd64_patch (code, target);
 }
 
-typedef enum {
-       ArgInIReg,
-       ArgInFloatSSEReg,
-       ArgInDoubleSSEReg,
-       ArgOnStack,
-       ArgValuetypeInReg,
-       ArgValuetypeAddrInIReg,
-       /* gsharedvt argument passed by addr */
-       ArgGSharedVtInReg,
-       ArgGSharedVtOnStack,
-       ArgNone /* only in pair_storage */
-} ArgStorage;
-
-typedef struct {
-       gint16 offset;
-       gint8  reg;
-       ArgStorage storage : 8;
-       gboolean is_gsharedvt_return_value : 1;
-
-       /* Only if storage == ArgValuetypeInReg */
-       ArgStorage pair_storage [2];
-       gint8 pair_regs [2];
-       /* The size of each pair (bytes) */
-       int pair_size [2];
-       int nregs;
-       /* Only if storage == ArgOnStack */
-       int arg_size; // Bytes, will always be rounded up/aligned to 8 byte boundary
-} ArgInfo;
-
-typedef struct {
-       int nargs;
-       guint32 stack_usage;
-       guint32 reg_usage;
-       guint32 freg_usage;
-       gboolean need_stack_align;
-       /* The index of the vret arg in the argument list */
-       int vret_arg_index;
-       ArgInfo ret;
-       ArgInfo sig_cookie;
-       ArgInfo args [1];
-} CallInfo;
-
 #define DEBUG(a) if (cfg->verbose_level > 1) a
 
 static void inline
@@ -1465,7 +1424,7 @@ mono_arch_init (void)
        mono_aot_register_jit_icall ("mono_amd64_throw_corlib_exception", mono_amd64_throw_corlib_exception);
        mono_aot_register_jit_icall ("mono_amd64_resume_unwind", mono_amd64_resume_unwind);
        mono_aot_register_jit_icall ("mono_amd64_get_original_ip", mono_amd64_get_original_ip);
-#if defined(ENABLE_GSHAREDVT)
+#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
        mono_aot_register_jit_icall ("mono_amd64_start_gsharedvt_call", mono_amd64_start_gsharedvt_call);
 #endif
 
@@ -3926,21 +3885,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)
@@ -8860,8 +8804,8 @@ mono_arch_opcode_supported (int opcode)
        }
 }
 
-#if defined(ENABLE_GSHAREDVT) && defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
-
-#include "../../../mono-extensions/mono/mini/mini-amd64-gsharedvt.c"
-
-#endif /* !ENABLE_GSHAREDVT */
+CallInfo*
+mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
+{
+       return get_call_info (mp, sig);
+}
index 343a42f8d99133d552f91face897c30d6e91dadf..c22c9be0fd0007b3969fc7beec42ac686e66e0d9 100644 (file)
@@ -265,6 +265,49 @@ typedef struct {
        guint8 buffer [256];
 } DynCallArgs;
 
+typedef enum {
+       ArgInIReg,
+       ArgInFloatSSEReg,
+       ArgInDoubleSSEReg,
+       ArgOnStack,
+       ArgValuetypeInReg,
+       ArgValuetypeAddrInIReg,
+       /* gsharedvt argument passed by addr */
+       ArgGSharedVtInReg,
+       ArgGSharedVtOnStack,
+       ArgNone /* only in pair_storage */
+} ArgStorage;
+
+typedef struct {
+       gint16 offset;
+       gint8  reg;
+       ArgStorage storage : 8;
+       gboolean is_gsharedvt_return_value : 1;
+
+       /* Only if storage == ArgValuetypeInReg */
+       ArgStorage pair_storage [2];
+       gint8 pair_regs [2];
+       /* The size of each pair (bytes) */
+       int pair_size [2];
+       int nregs;
+       /* Only if storage == ArgOnStack */
+       int arg_size; // Bytes, will always be rounded up/aligned to 8 byte boundary
+} ArgInfo;
+
+typedef struct {
+       int nargs;
+       guint32 stack_usage;
+       guint32 reg_usage;
+       guint32 freg_usage;
+       gboolean need_stack_align;
+       /* The index of the vret arg in the argument list */
+       int vret_arg_index;
+       ArgInfo ret;
+       ArgInfo sig_cookie;
+       ArgInfo args [1];
+} CallInfo;
+
+
 #define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->gregs [AMD64_RAX] = (gsize)exc; } while (0)
 #define MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG(ctx, sel) do { (ctx)->gregs [AMD64_RDX] = (gsize)(sel); } while (0)
 
@@ -379,7 +422,6 @@ typedef struct {
 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1
 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1
 #define MONO_ARCH_HAVE_CREATE_LLVM_NATIVE_THUNK 1
-#define MONO_ARCH_GSHAREDVT_SUPPORTED 1
 #define MONO_ARCH_HAVE_OP_TAIL_CALL 1
 #define MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET 1
 #define MONO_ARCH_HAVE_DUMMY_INIT 1
@@ -395,6 +437,11 @@ typedef struct {
 #define MONO_ARCH_HAVE_TLS_GET_REG 1
 #endif
 
+#if !defined (TARGET_WIN32)
+#define MONO_ARCH_GSHAREDVT_SUPPORTED 1
+#endif
+
+
 #if defined(TARGET_APPLETVOS)
 /* No signals */
 #define MONO_ARCH_NEED_DIV_CHECK 1
@@ -460,5 +507,7 @@ void mono_arch_unwindinfo_install_unwind_info (gpointer* monoui, gpointer code,
 #define MONO_ARCH_HAVE_UNWIND_TABLE 1
 #endif
 
+CallInfo* mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig);
+
 #endif /* __MONO_MINI_AMD64_H__ */  
 
diff --git a/mono/mini/mini-arm-gsharedvt.c b/mono/mini/mini-arm-gsharedvt.c
new file mode 100644 (file)
index 0000000..aef522b
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * mini-arm-gsharedvt.c: gsharedvt support code for arm
+ *
+ * Authors:
+ *   Zoltan Varga <vargaz@gmail.com>
+ *
+ * Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <config.h>
+#include <glib.h>
+
+#include <mono/metadata/abi-details.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/marshal.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/profiler-private.h>
+#include <mono/arch/arm/arm-codegen.h>
+#include <mono/arch/arm/arm-vfp-codegen.h>
+
+#include "mini.h"
+#include "mini-arm.h"
+
+#ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
+
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+/*
+ * GSHAREDVT
+ */
+
+gboolean
+mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)
+{
+       /*
+       if (sig->ret && is_variable_size (sig->ret))
+               return FALSE;
+       */
+       return TRUE;
+}
+
+static inline void
+add_to_map (GPtrArray *map, int src, int dst)
+{
+       g_ptr_array_add (map, GUINT_TO_POINTER (src));
+       g_ptr_array_add (map, GUINT_TO_POINTER (dst));
+}
+
+static inline int
+map_reg (int reg)
+{
+       return reg;
+}
+
+static inline int
+map_stack_slot (int slot)
+{
+       return slot + 4;
+}
+
+static int
+get_arg_slots (ArgInfo *ainfo, int **out_slots)
+{
+       int sreg = ainfo->reg;
+       int sslot = ainfo->offset / 4;
+       int *src = NULL;
+       int i, nsrc;
+
+       switch (ainfo->storage) {
+       case RegTypeGeneral:
+               nsrc = 1;
+               src = g_malloc (nsrc * sizeof (int));
+               src [0] = map_reg (sreg);
+               break;
+       case RegTypeIRegPair:
+               nsrc = 2;
+               src = g_malloc (nsrc * sizeof (int));
+               src [0] = map_reg (sreg);
+               src [1] = map_reg (sreg + 1);
+               break;
+       case RegTypeStructByVal:
+               nsrc = ainfo->struct_size / 4;
+               src = g_malloc (nsrc * sizeof (int));
+               g_assert (ainfo->size <= nsrc);
+               for (i = 0; i < ainfo->size; ++i)
+                       src [i] = map_reg (sreg + i);
+               for (i = ainfo->size; i < nsrc; ++i)
+                       src [i] = map_stack_slot (sslot + (i - ainfo->size));
+               break;
+       case RegTypeBase:
+               nsrc = ainfo->size / 4;
+               src = g_malloc (nsrc * sizeof (int));
+               for (i = 0; i < nsrc; ++i)
+                       src [i] = map_stack_slot (sslot + i);
+               break;
+       case RegTypeBaseGen:
+               nsrc = 2;
+               src = g_malloc (nsrc * sizeof (int));
+               src [0] = map_reg (ARMREG_R3);
+               src [1] = map_stack_slot (sslot);
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+
+       *out_slots = src;
+       return nsrc;
+}
+
+/*
+ * mono_arch_get_gsharedvt_call_info:
+ *
+ *   See mini-x86.c for documentation.
+ */
+gpointer
+mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
+{
+       GSharedVtCallInfo *info;
+       CallInfo *caller_cinfo, *callee_cinfo;
+       MonoMethodSignature *caller_sig, *callee_sig;
+       int aindex, i;
+       gboolean var_ret = FALSE;
+       CallInfo *cinfo, *gcinfo;
+       MonoMethodSignature *sig, *gsig;
+       GPtrArray *map;
+
+       if (gsharedvt_in) {
+               caller_sig = normal_sig;
+               callee_sig = gsharedvt_sig;
+               caller_cinfo = mono_arch_get_call_info (NULL, caller_sig);
+               callee_cinfo = mono_arch_get_call_info (NULL, callee_sig);
+       } else {
+               callee_sig = normal_sig;
+               callee_cinfo = mono_arch_get_call_info (NULL, callee_sig);
+               caller_sig = gsharedvt_sig;
+               caller_cinfo = mono_arch_get_call_info (NULL, caller_sig);
+       }
+
+       /*
+        * If GSHAREDVT_IN is true, this means we are transitioning from normal to gsharedvt code. The caller uses the
+        * normal call signature, while the callee uses the gsharedvt signature.
+        * If GSHAREDVT_IN is false, its the other way around.
+        */
+
+       /* sig/cinfo describes the normal call, while gsig/gcinfo describes the gsharedvt call */
+       if (gsharedvt_in) {
+               sig = caller_sig;
+               gsig = callee_sig;
+               cinfo = caller_cinfo;
+               gcinfo = callee_cinfo;
+       } else {
+               sig = callee_sig;
+               gsig = caller_sig;
+               cinfo = callee_cinfo;
+               gcinfo = caller_cinfo;
+       }
+
+       if (gcinfo->ret.storage == RegTypeStructByAddr && gsig->ret && mini_is_gsharedvt_type (gsig->ret)) {
+               /*
+                * The return type is gsharedvt
+                */
+               var_ret = TRUE;
+       }
+
+       /*
+        * The stack looks like this:
+        * <arguments>
+        * <ret addr>
+        * <saved ebp>
+        * <call area>
+        * We have to map the stack slots in <arguments> to the stack slots in <call area>.
+        * The argument registers are mapped to slot 0..3, stack slot 0 is mapped to slot 4, etc.
+        */
+       map = g_ptr_array_new ();
+
+       if (cinfo->ret.storage == RegTypeStructByAddr) {
+               /*
+                * Map ret arg.
+                * This handles the case when the method returns a normal vtype, and when it returns a type arg, and its instantiated
+                * with a vtype.
+                */
+               g_assert (caller_cinfo->ret.storage == RegTypeStructByAddr);
+               g_assert (callee_cinfo->ret.storage == RegTypeStructByAddr);
+               add_to_map (map, map_reg (caller_cinfo->ret.reg), map_reg (callee_cinfo->ret.reg));
+       }
+
+       for (aindex = 0; aindex < cinfo->nargs; ++aindex) {
+               ArgInfo *ainfo = &caller_cinfo->args [aindex];
+               ArgInfo *ainfo2 = &callee_cinfo->args [aindex];
+               int *src = NULL, *dst = NULL;
+               int nsrc, ndst, nslots, src_slot, arg_marshal;
+
+               /*
+                * The src descriptor looks like this:
+                * - 4 bits src slot
+                * - 12 bits number of slots
+                * - 8 bits marshal type (GSHAREDVT_ARG_...)
+                */
+
+               arg_marshal = GSHAREDVT_ARG_NONE;
+
+               if (ainfo->storage == RegTypeGSharedVtInReg || ainfo->storage == RegTypeGSharedVtOnStack) {
+                       /* Pass the value whose address is received in a reg by value */
+                       g_assert (ainfo2->storage != RegTypeGSharedVtInReg);
+                       ndst = get_arg_slots (ainfo2, &dst);
+                       nsrc = 1;
+                       src = g_new0 (int, 1);
+                       if (ainfo->storage == RegTypeGSharedVtInReg)
+                               src_slot = map_reg (ainfo->reg);
+                       else
+                               src_slot = map_stack_slot (ainfo->offset / 4);
+                       g_assert (ndst < 256);
+                       g_assert (src_slot < 16);
+                       src [0] = (ndst << 4) | src_slot;
+
+                       if (ainfo2->storage == RegTypeGeneral && ainfo2->size != 0 && ainfo2->size != 4) {
+                               /* Have to load less than 4 bytes */
+                               // FIXME: Signed types
+                               switch (ainfo2->size) {
+                               case 1:
+                                       arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL_U1;
+                                       break;
+                               case 2:
+                                       arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL_U2;
+                                       break;
+                               default:
+                                       g_assert_not_reached ();
+                                       break;
+                               }
+                       } else {
+                               arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL;
+                       }
+               } else {
+                       nsrc = get_arg_slots (ainfo, &src);
+               }
+               if (ainfo2->storage == RegTypeGSharedVtInReg) {
+                       /* Pass the address of the first src slot in a reg */
+                       arg_marshal = GSHAREDVT_ARG_BYVAL_TO_BYREF;
+                       ndst = 1;
+                       dst = g_new0 (int, 1);
+                       dst [0] = map_reg (ainfo2->reg);
+               } else if (ainfo2->storage == RegTypeGSharedVtOnStack) {
+                       /* Pass the address of the first src slot in a stack slot */
+                       arg_marshal = GSHAREDVT_ARG_BYVAL_TO_BYREF;
+                       ndst = 1;
+                       dst = g_new0 (int, 1);
+                       dst [0] = map_stack_slot (ainfo2->offset / 4);
+               } else {
+                       ndst = get_arg_slots (ainfo2, &dst);
+               }
+               if (nsrc)
+                       src [0] |= (arg_marshal << 16);
+               nslots = MIN (nsrc, ndst);
+
+               for (i = 0; i < nslots; ++i)
+                       add_to_map (map, src [i], dst [i]);
+
+               g_free (src);
+               g_free (dst);
+       }
+
+       info = mono_domain_alloc0 (mono_domain_get (), sizeof (GSharedVtCallInfo) + (map->len * sizeof (int)));
+       info->addr = addr;
+       info->stack_usage = callee_cinfo->stack_usage;
+       info->ret_marshal = GSHAREDVT_RET_NONE;
+       info->gsharedvt_in = gsharedvt_in ? 1 : 0;
+       info->vret_slot = -1;
+       info->calli = calli;
+       if (var_ret) {
+               g_assert (gcinfo->ret.storage == RegTypeStructByAddr);
+               info->vret_arg_reg = gcinfo->ret.reg;
+       } else {
+               info->vret_arg_reg = -1;
+       }
+       info->vcall_offset = vcall_offset;
+       info->map_count = map->len / 2;
+       for (i = 0; i < map->len; ++i)
+               info->map [i] = GPOINTER_TO_UINT (g_ptr_array_index (map, i));
+       g_ptr_array_free (map, TRUE);
+
+       /* Compute return value marshalling */
+       if (var_ret) {
+               switch (cinfo->ret.storage) {
+               case RegTypeGeneral:
+                       if (gsharedvt_in && !sig->ret->byref && sig->ret->type == MONO_TYPE_I1)
+                               info->ret_marshal = GSHAREDVT_RET_I1;
+                       else if (gsharedvt_in && !sig->ret->byref && (sig->ret->type == MONO_TYPE_U1 || sig->ret->type == MONO_TYPE_BOOLEAN))
+                               info->ret_marshal = GSHAREDVT_RET_U1;
+                       else if (gsharedvt_in && !sig->ret->byref && sig->ret->type == MONO_TYPE_I2)
+                               info->ret_marshal = GSHAREDVT_RET_I2;
+                       else if (gsharedvt_in && !sig->ret->byref && (sig->ret->type == MONO_TYPE_U2 || sig->ret->type == MONO_TYPE_CHAR))
+                               info->ret_marshal = GSHAREDVT_RET_U2;
+                       else
+                               info->ret_marshal = GSHAREDVT_RET_IREG;
+                       break;
+               case RegTypeIRegPair:
+                       info->ret_marshal = GSHAREDVT_RET_IREGS;
+                       break;
+               case RegTypeFP:
+                       // FIXME: VFP
+                       if (cinfo->ret.size == 4)
+                               info->ret_marshal = GSHAREDVT_RET_IREG;
+                       else
+                               info->ret_marshal = GSHAREDVT_RET_IREGS;
+                       break;
+               case RegTypeStructByAddr:
+                       info->ret_marshal = GSHAREDVT_RET_NONE;
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+       }
+
+       if (gsharedvt_in && var_ret && caller_cinfo->ret.storage != RegTypeStructByAddr) {
+               /* Allocate stack space for the return value */
+               info->vret_slot = map_stack_slot (info->stack_usage / sizeof (gpointer));
+               info->stack_usage += mono_type_stack_size_internal (normal_sig->ret, NULL, FALSE) + sizeof (gpointer);
+       }
+
+       info->stack_usage = ALIGN_TO (info->stack_usage, MONO_ARCH_FRAME_ALIGNMENT);
+
+       g_free (caller_cinfo);
+       g_free (callee_cinfo);
+
+       return info;
+}
+
+#endif
\ No newline at end of file
index 63096e7439f6f435a68f47d3a0d7f3cc2c9c6fe5..47a6dbb5ba2fda5c38e2923c67edefd4f4f5635c 100644 (file)
@@ -2,6 +2,7 @@
  * mini-arm-tls.S: tls getters and setters for arm platforms
  *
  * Copyright 2015 Xamarin, Inc.
+        * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 66fd8c083b302ec723f148e1f7130b0a1104c9dc..86d4e123919cb97908c28153de6b512f1bc5d644 100644 (file)
@@ -8,6 +8,7 @@
  * (C) 2003 Ximian, Inc.
  * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "mini.h"
 #include <string.h>
@@ -903,7 +904,7 @@ mono_arch_init (void)
        mono_aot_register_jit_icall ("mono_arm_throw_exception", mono_arm_throw_exception);
        mono_aot_register_jit_icall ("mono_arm_throw_exception_by_token", mono_arm_throw_exception_by_token);
        mono_aot_register_jit_icall ("mono_arm_resume_unwind", mono_arm_resume_unwind);
-#if defined(ENABLE_GSHAREDVT)
+#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
        mono_aot_register_jit_icall ("mono_arm_start_gsharedvt_call", mono_arm_start_gsharedvt_call);
 #endif
        mono_aot_register_jit_icall ("mono_arm_unaligned_stack", mono_arm_unaligned_stack);
@@ -1159,50 +1160,6 @@ mono_arch_flush_icache (guint8 *code, gint size)
 #endif
 }
 
-typedef enum {
-       RegTypeNone,
-       /* Passed/returned in an ireg */
-       RegTypeGeneral,
-       /* Passed/returned in a pair of iregs */
-       RegTypeIRegPair,
-       /* Passed on the stack */
-       RegTypeBase,
-       /* First word in r3, second word on the stack */
-       RegTypeBaseGen,
-       /* FP value passed in either an ireg or a vfp reg */
-       RegTypeFP,
-       RegTypeStructByVal,
-       RegTypeStructByAddr,
-       /* gsharedvt argument passed by addr in greg */
-       RegTypeGSharedVtInReg,
-       /* gsharedvt argument passed by addr on stack */
-       RegTypeGSharedVtOnStack,
-       RegTypeHFA
-} ArgStorage;
-
-typedef struct {
-       gint32  offset;
-       guint16 vtsize; /* in param area */
-       /* RegTypeHFA */
-       int esize;
-       /* RegTypeHFA */
-       int nregs;
-       guint8  reg;
-       ArgStorage  storage;
-       gint32  struct_size;
-       guint8  size    : 4; /* 1, 2, 4, 8, or regs used by RegTypeStructByVal */
-} ArgInfo;
-
-typedef struct {
-       int nargs;
-       guint32 stack_usage;
-       /* The index of the vret arg in the argument list for RegTypeStructByAddr */
-       int vret_arg_index;
-       ArgInfo ret;
-       ArgInfo sig_cookie;
-       ArgInfo args [1];
-} CallInfo;
-
 #define DEBUG(a)
 
 static void inline
@@ -2375,6 +2332,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 +2354,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 +2426,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 +6532,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 +6784,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;
@@ -7661,8 +7621,8 @@ mono_arch_opcode_supported (int opcode)
        }
 }
 
-#if defined(ENABLE_GSHAREDVT)
-
-#include "../../../mono-extensions/mono/mini/mini-arm-gsharedvt.c"
-
-#endif /* !MONOTOUCH */
+CallInfo*
+mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
+{
+       return get_call_info (mp, sig);
+}
index b09db53452a1993fc7f13f51d056a678d1ef3a03..bcd922f522b628fac0f0fd7f0f91e13341022577 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_MINI_ARM_H__
@@ -174,6 +175,51 @@ typedef struct {
        int map [MONO_ZERO_LEN_ARRAY];
 } GSharedVtCallInfo;
 
+
+typedef enum {
+       RegTypeNone,
+       /* Passed/returned in an ireg */
+       RegTypeGeneral,
+       /* Passed/returned in a pair of iregs */
+       RegTypeIRegPair,
+       /* Passed on the stack */
+       RegTypeBase,
+       /* First word in r3, second word on the stack */
+       RegTypeBaseGen,
+       /* FP value passed in either an ireg or a vfp reg */
+       RegTypeFP,
+       RegTypeStructByVal,
+       RegTypeStructByAddr,
+       /* gsharedvt argument passed by addr in greg */
+       RegTypeGSharedVtInReg,
+       /* gsharedvt argument passed by addr on stack */
+       RegTypeGSharedVtOnStack,
+       RegTypeHFA
+} ArgStorage;
+
+typedef struct {
+       gint32  offset;
+       guint16 vtsize; /* in param area */
+       /* RegTypeHFA */
+       int esize;
+       /* RegTypeHFA */
+       int nregs;
+       guint8  reg;
+       ArgStorage  storage;
+       gint32  struct_size;
+       guint8  size    : 4; /* 1, 2, 4, 8, or regs used by RegTypeStructByVal */
+} ArgInfo;
+
+typedef struct {
+       int nargs;
+       guint32 stack_usage;
+       /* The index of the vret arg in the argument list for RegTypeStructByAddr */
+       int vret_arg_index;
+       ArgInfo ret;
+       ArgInfo sig_cookie;
+       ArgInfo args [1];
+} CallInfo;
+
 /* Structure used by the sequence points in AOTed code */
 typedef struct {
        gpointer ss_trigger_page;
@@ -366,4 +412,7 @@ mono_arm_have_tls_get (void);
 void
 mono_arm_unaligned_stack (MonoMethod *method);
 
+CallInfo*
+mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig);
+
 #endif /* __MONO_MINI_ARM_H__ */
diff --git a/mono/mini/mini-arm64-gsharedvt.c b/mono/mini/mini-arm64-gsharedvt.c
new file mode 100644 (file)
index 0000000..3d9664b
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * mini-arm64-gsharedvt.c: gsharedvt support code for arm64
+ *
+ * Authors:
+ *   Zoltan Varga <vargaz@gmail.com>
+ *
+ * Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include "mini.h"
+#include "mini-arm64.h"
+#include "mini-arm64-gsharedvt.h"
+
+/*
+ * GSHAREDVT
+ */
+#ifdef MONO_ARCH_GSHARED_SUPPORTED
+
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+void
+mono_arm_gsharedvt_init (void)
+{
+       mono_aot_register_jit_icall ("mono_arm_start_gsharedvt_call", mono_arm_start_gsharedvt_call);
+}
+
+gboolean
+mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)
+{
+       /*
+       if (sig->ret && is_variable_size (sig->ret))
+               return FALSE;
+       */
+       return TRUE;
+}
+
+static inline void
+add_to_map (GPtrArray *map, int src, int dst)
+{
+       g_ptr_array_add (map, GUINT_TO_POINTER (src));
+       g_ptr_array_add (map, GUINT_TO_POINTER (dst));
+}
+
+/*
+ * Slot mapping:
+ * 0..8  - r0..r8
+ * 9..16 - d0..d7
+ * 17..  - stack slots
+ */
+
+static inline int
+map_reg (int reg)
+{
+       return reg;
+}
+
+static inline int
+map_freg (int reg)
+{
+       return reg + NUM_GSHAREDVT_ARG_GREGS;
+}
+
+static inline int
+map_stack_slot (int slot)
+{
+       return slot + NUM_GSHAREDVT_ARG_GREGS + NUM_GSHAREDVT_ARG_FREGS;
+}
+
+static int
+get_arg_slots (ArgInfo *ainfo, int **out_slots)
+{
+       int sreg = ainfo->reg;
+       int sslot = ainfo->offset / 8;
+       int *src = NULL;
+       int i, nsrc;
+
+       switch (ainfo->storage) {
+       case ArgInIReg:
+       case ArgVtypeByRef:
+               nsrc = 1;
+               src = g_malloc (nsrc * sizeof (int));
+               src [0] = map_reg (sreg);
+               break;
+       case ArgVtypeByRefOnStack:
+               nsrc = 1;
+               src = g_malloc (nsrc * sizeof (int));
+               src [0] = map_stack_slot (sslot);
+               break;
+       case ArgInFReg:
+       case ArgInFRegR4:
+               nsrc = 1;
+               src = g_malloc (nsrc * sizeof (int));
+               src [0] = map_freg (sreg);
+               break;
+       case ArgHFA:
+               nsrc = ainfo->nregs;
+               src = g_malloc (nsrc * sizeof (int));
+               for (i = 0; i < ainfo->nregs; ++i)
+                       src [i] = map_freg (sreg + i);
+               break;
+       case ArgVtypeInIRegs:
+               nsrc = ainfo->nregs;
+               src = g_malloc (nsrc * sizeof (int));
+               for (i = 0; i < ainfo->nregs; ++i)
+                       src [i] = map_reg (sreg + i);
+               break;
+       case ArgOnStack:
+               nsrc = 1;
+               src = g_malloc (nsrc * sizeof (int));
+               src [0] = map_stack_slot (sslot);
+               break;
+       case ArgVtypeOnStack:
+               nsrc = ainfo->size / 8;
+               src = g_malloc (nsrc * sizeof (int));
+               for (i = 0; i < nsrc; ++i)
+                       src [i] = map_stack_slot (sslot + i);
+               break;
+       default:
+               NOT_IMPLEMENTED;
+               break;
+       }
+
+       *out_slots = src;
+       return nsrc;
+}
+
+/*
+ * mono_arch_get_gsharedvt_call_info:
+ *
+ *   See mini-x86.c for documentation.
+ */
+gpointer
+mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
+{
+       GSharedVtCallInfo *info;
+       CallInfo *caller_cinfo, *callee_cinfo;
+       MonoMethodSignature *caller_sig, *callee_sig;
+       int aindex, i;
+       gboolean var_ret = FALSE;
+       CallInfo *cinfo, *gcinfo;
+       MonoMethodSignature *sig, *gsig;
+       GPtrArray *map;
+
+       if (gsharedvt_in) {
+               caller_sig = normal_sig;
+               callee_sig = gsharedvt_sig;
+               caller_cinfo = mono_arch_get_call_info (NULL, caller_sig);
+               callee_cinfo = mono_arch_get_call_info (NULL, callee_sig);
+       } else {
+               callee_sig = normal_sig;
+               caller_sig = gsharedvt_sig;
+               callee_cinfo = mono_arch_get_call_info (NULL, callee_sig);
+               caller_cinfo = mono_arch_get_call_info (NULL, caller_sig);
+       }
+
+       /*
+        * If GSHAREDVT_IN is true, this means we are transitioning from normal to gsharedvt code. The caller uses the
+        * normal call signature, while the callee uses the gsharedvt signature.
+        * If GSHAREDVT_IN is false, its the other way around.
+        */
+
+       /* sig/cinfo describes the normal call, while gsig/gcinfo describes the gsharedvt call */
+       if (gsharedvt_in) {
+               sig = caller_sig;
+               gsig = callee_sig;
+               cinfo = caller_cinfo;
+               gcinfo = callee_cinfo;
+       } else {
+               sig = callee_sig;
+               gsig = caller_sig;
+               cinfo = callee_cinfo;
+               gcinfo = caller_cinfo;
+       }
+
+       if (gcinfo->ret.gsharedvt) {
+               /*
+                * The return type is gsharedvt
+                */
+               var_ret = TRUE;
+       }
+
+       /*
+        * The stack looks like this:
+        * <arguments>
+        * <trampoline frame>
+        * <call area>
+        * We have to map the stack slots in <arguments> to the stack slots in <call area>.
+        */
+       map = g_ptr_array_new ();
+
+       for (aindex = 0; aindex < cinfo->nargs; ++aindex) {
+               ArgInfo *ainfo = &caller_cinfo->args [aindex];
+               ArgInfo *ainfo2 = &callee_cinfo->args [aindex];
+               int *src = NULL, *dst = NULL;
+               int nsrc, ndst, nslots, src_slot, arg_marshal;
+
+               /*
+                * The src descriptor looks like this:
+                * - 6 bits src slot
+                * - 12 bits number of slots
+                * - 4 bits marshal type (GSHAREDVT_ARG_...)
+                * - 4 bits size/sign descriptor (GSHAREDVT_ARG_SIZE)
+                * - 4 bits offset inside stack slots
+                */
+               arg_marshal = GSHAREDVT_ARG_NONE;
+
+               if (ainfo->gsharedvt) {
+                       /* Pass the value whose address is received in a reg by value */
+                       g_assert (!ainfo2->gsharedvt);
+                       ndst = get_arg_slots (ainfo2, &dst);
+                       nsrc = 1;
+                       src = g_new0 (int, 1);
+                       if (ainfo->storage == ArgVtypeByRef)
+                               src_slot = map_reg (ainfo->reg);
+                       else
+                               src_slot = map_stack_slot (ainfo->offset / 8);
+                       g_assert (ndst < 256);
+                       g_assert (src_slot < 64);
+                       src [0] = (ndst << 6) | src_slot;
+                       if (ainfo2->storage == ArgHFA && ainfo2->esize == 4)
+                               arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL_HFAR4;
+                       else if (ainfo2->storage == ArgVtypeByRef || ainfo2->storage == ArgVtypeByRefOnStack)
+                               arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYREF;
+                       else
+                               arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL;
+               } else {
+                       nsrc = get_arg_slots (ainfo, &src);
+               }
+               if (ainfo2->storage == ArgVtypeByRef && ainfo2->gsharedvt) {
+                       /* Pass the address of the first src slot in a reg */
+                       if (ainfo->storage != ArgVtypeByRef) {
+                               if (ainfo->storage == ArgHFA && ainfo->esize == 4) {
+                                       arg_marshal = GSHAREDVT_ARG_BYVAL_TO_BYREF_HFAR4;
+                                       g_assert (src [0] < 64);
+                                       g_assert (nsrc < 256);
+                                       src [0] |= (nsrc << 6);
+                               } else {
+                                       arg_marshal = GSHAREDVT_ARG_BYVAL_TO_BYREF;
+                               }
+                       }
+                       ndst = 1;
+                       dst = g_new0 (int, 1);
+                       dst [0] = map_reg (ainfo2->reg);
+               } else if (ainfo2->storage == ArgVtypeByRefOnStack && ainfo2->gsharedvt) {
+                       /* Pass the address of the first src slot in a stack slot */
+                       if (ainfo->storage != ArgVtypeByRef)
+                               arg_marshal = GSHAREDVT_ARG_BYVAL_TO_BYREF;
+                       ndst = 1;
+                       dst = g_new0 (int, 1);
+                       dst [0] = map_stack_slot (ainfo2->offset / 8);
+               } else {
+                       ndst = get_arg_slots (ainfo2, &dst);
+               }
+               if (nsrc)
+                       src [0] |= (arg_marshal << 18);
+               if (ainfo->storage == ArgOnStack && ainfo->slot_size != 8) {
+                       GSharedVtArgSize arg_size = GSHAREDVT_ARG_SIZE_NONE;
+
+                       /*
+                        * On IOS, stack arguments smaller than 8 bytes can
+                        * share a stack slot. Encode this information into
+                        * the descriptor.
+                        */
+                       switch (ainfo->slot_size) {
+                       case 1:
+                               arg_size = ainfo->sign ? GSHAREDVT_ARG_SIZE_I1 : GSHAREDVT_ARG_SIZE_U1;
+                               break;
+                       case 2:
+                               arg_size = ainfo->sign ? GSHAREDVT_ARG_SIZE_I2 : GSHAREDVT_ARG_SIZE_U2;
+                               break;
+                       case 4:
+                               arg_size = ainfo->sign ? GSHAREDVT_ARG_SIZE_I4 : GSHAREDVT_ARG_SIZE_U4;
+                               break;
+                       default:
+                               NOT_IMPLEMENTED;
+                               break;
+                       }
+                       /* Encode the size/sign */
+                       src [0] |= (arg_size << 22);
+                       /* Encode the offset inside the stack slot */
+                       src [0] |= ((ainfo->offset % 8) << 26);
+                       if (ainfo2->storage == ArgOnStack)
+                               dst [0] |= ((ainfo2->offset % 8) << 26);
+               } else if (ainfo2->storage == ArgOnStack && ainfo2->slot_size != 8) {
+                       /* The caller passes in an address, need to store it into a stack slot */
+
+                       GSharedVtArgSize arg_size = GSHAREDVT_ARG_SIZE_NONE;
+                       switch (ainfo2->slot_size) {
+                       case 1:
+                               arg_size = ainfo2->sign ? GSHAREDVT_ARG_SIZE_I1 : GSHAREDVT_ARG_SIZE_U1;
+                               break;
+                       case 2:
+                               arg_size = ainfo2->sign ? GSHAREDVT_ARG_SIZE_I2 : GSHAREDVT_ARG_SIZE_U2;
+                               break;
+                       case 4:
+                               arg_size = ainfo2->sign ? GSHAREDVT_ARG_SIZE_I4 : GSHAREDVT_ARG_SIZE_U4;
+                               break;
+                       default:
+                               NOT_IMPLEMENTED;
+                               break;
+                       }
+                       /* Encode the size/sign */
+                       src [0] |= (arg_size << 22);
+                       /* Encode the offset inside the stack slot */
+                       dst [0] |= ((ainfo2->offset % 8) << 26);
+               }
+               nslots = MIN (nsrc, ndst);
+
+               for (i = 0; i < nslots; ++i)
+                       add_to_map (map, src [i], dst [i]);
+
+               g_free (src);
+               g_free (dst);
+       }
+
+       if (cinfo->ret.storage == ArgVtypeByRef) {
+               /* Both the caller and the callee pass the vtype ret address in r8 */
+               g_assert (cinfo->ret.storage == gcinfo->ret.storage);
+               add_to_map (map, map_reg (ARMREG_R8), map_reg (ARMREG_R8));
+       }
+
+       info = mono_domain_alloc0 (mono_domain_get (), sizeof (GSharedVtCallInfo) + (map->len * sizeof (int)));
+       info->addr = addr;
+       info->stack_usage = callee_cinfo->stack_usage;
+       info->ret_marshal = GSHAREDVT_RET_NONE;
+       info->gsharedvt_in = gsharedvt_in ? 1 : 0;
+       info->vret_slot = -1;
+       info->calli = calli;
+
+       if (var_ret) {
+               g_assert (gcinfo->ret.gsharedvt);
+               info->vret_arg_reg = map_reg (ARMREG_R8);
+       } else {
+               info->vret_arg_reg = -1;
+       }
+
+       info->vcall_offset = vcall_offset;
+       info->map_count = map->len / 2;
+       for (i = 0; i < map->len; ++i)
+               info->map [i] = GPOINTER_TO_UINT (g_ptr_array_index (map, i));
+       g_ptr_array_free (map, TRUE);
+
+       /* Compute return value marshalling */
+       if (var_ret) {
+               switch (cinfo->ret.storage) {
+               case ArgInIReg:
+                       if (!gsharedvt_in || sig->ret->byref) {
+                               info->ret_marshal = GSHAREDVT_RET_I8;
+                       } else {
+                               switch (sig->ret->type) {
+                               case MONO_TYPE_I1:
+                                       info->ret_marshal = GSHAREDVT_RET_I1;
+                                       break;
+                               case MONO_TYPE_U1:
+                               case MONO_TYPE_BOOLEAN:
+                                       info->ret_marshal = GSHAREDVT_RET_U1;
+                                       break;
+                               case MONO_TYPE_I2:
+                                       info->ret_marshal = GSHAREDVT_RET_I2;
+                                       break;
+                               case MONO_TYPE_U2:
+                               case MONO_TYPE_CHAR:
+                                       info->ret_marshal = GSHAREDVT_RET_U2;
+                                       break;
+                               case MONO_TYPE_I4:
+                                       info->ret_marshal = GSHAREDVT_RET_I4;
+                                       break;
+                               case MONO_TYPE_U4:
+                                       info->ret_marshal = GSHAREDVT_RET_U4;
+                                       break;
+                               default:
+                                       info->ret_marshal = GSHAREDVT_RET_I8;
+                                       break;
+                               }
+                       }
+                       break;
+               case ArgInFReg:
+                       info->ret_marshal = GSHAREDVT_RET_R8;
+                       break;
+               case ArgInFRegR4:
+                       info->ret_marshal = GSHAREDVT_RET_R4;
+                       break;
+               case ArgVtypeInIRegs:
+                       info->ret_marshal = GSHAREDVT_RET_IREGS_1 - 1 + cinfo->ret.nregs;
+                       break;
+               case ArgHFA:
+                       if (cinfo->ret.esize == 4)
+                               info->ret_marshal = GSHAREDVT_RET_HFAR4_1 - 1 + cinfo->ret.nregs;
+                       else
+                               info->ret_marshal = GSHAREDVT_RET_HFAR8_1 - 1 + cinfo->ret.nregs;
+                       break;
+               case ArgVtypeByRef:
+                       /* No conversion needed */
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+       }
+
+       if (gsharedvt_in && var_ret && cinfo->ret.storage != ArgVtypeByRef) {
+               /* Allocate stack space for the return value */
+               info->vret_slot = map_stack_slot (info->stack_usage / sizeof (gpointer));
+               info->stack_usage += mono_type_stack_size_internal (normal_sig->ret, NULL, FALSE) + sizeof (gpointer);
+       }
+
+       info->stack_usage = ALIGN_TO (info->stack_usage, MONO_ARCH_FRAME_ALIGNMENT);
+
+       return info;
+}
+
+#else
+
+void
+mono_arm_gsharedvt_init (void)
+{
+}
+
+#endif /* MONO_ARCH_GSHARED_SUPPORTED */
\ No newline at end of file
diff --git a/mono/mini/mini-arm64-gsharedvt.h b/mono/mini/mini-arm64-gsharedvt.h
new file mode 100644 (file)
index 0000000..b828218
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef __MINI_ARM64_GSHAREDVT_H__
+#define __MINI_ARM64_GSHAREDVT_H__
+
+/* Argument marshallings for calls between gsharedvt and normal code */
+typedef enum {
+       GSHAREDVT_ARG_NONE = 0,
+       GSHAREDVT_ARG_BYVAL_TO_BYREF = 1,
+       GSHAREDVT_ARG_BYVAL_TO_BYREF_HFAR4 = 2,
+       GSHAREDVT_ARG_BYREF_TO_BYVAL = 3,
+       GSHAREDVT_ARG_BYREF_TO_BYVAL_HFAR4 = 4,
+       GSHAREDVT_ARG_BYREF_TO_BYREF = 5
+} GSharedVtArgMarshal;
+
+/* For arguments passed on the stack on ios */
+typedef enum {
+       GSHAREDVT_ARG_SIZE_NONE = 0,
+       GSHAREDVT_ARG_SIZE_I1 = 1,
+       GSHAREDVT_ARG_SIZE_U1 = 2,
+       GSHAREDVT_ARG_SIZE_I2 = 3,
+       GSHAREDVT_ARG_SIZE_U2 = 4,
+       GSHAREDVT_ARG_SIZE_I4 = 5,
+       GSHAREDVT_ARG_SIZE_U4 = 6,
+} GSharedVtArgSize;
+
+/* Return value marshalling for calls between gsharedvt and normal code */
+typedef enum {
+       GSHAREDVT_RET_NONE = 0,
+       GSHAREDVT_RET_I8 = 1,
+       GSHAREDVT_RET_I1 = 2,
+       GSHAREDVT_RET_U1 = 3,
+       GSHAREDVT_RET_I2 = 4,
+       GSHAREDVT_RET_U2 = 5,
+       GSHAREDVT_RET_I4 = 6,
+       GSHAREDVT_RET_U4 = 7,
+       GSHAREDVT_RET_R8 = 8,
+       GSHAREDVT_RET_R4 = 9,
+       GSHAREDVT_RET_IREGS_1 = 10,
+       GSHAREDVT_RET_IREGS_2 = 11,
+       GSHAREDVT_RET_IREGS_3 = 12,
+       GSHAREDVT_RET_IREGS_4 = 13,
+       GSHAREDVT_RET_IREGS_5 = 14,
+       GSHAREDVT_RET_IREGS_6 = 15,
+       GSHAREDVT_RET_IREGS_7 = 16,
+       GSHAREDVT_RET_IREGS_8 = 17,
+       GSHAREDVT_RET_HFAR8_1 = 18,
+       GSHAREDVT_RET_HFAR8_2 = 19,
+       GSHAREDVT_RET_HFAR8_3 = 20,
+       GSHAREDVT_RET_HFAR8_4 = 21,
+       GSHAREDVT_RET_HFAR4_1 = 22,
+       GSHAREDVT_RET_HFAR4_2 = 23,
+       GSHAREDVT_RET_HFAR4_3 = 24,
+       GSHAREDVT_RET_HFAR4_4 = 25,
+       GSHAREDVT_RET_NUM = 26
+} GSharedVtRetMarshal;
+
+typedef struct {
+       /* Method address to call */
+       gpointer addr;
+       /* The trampoline reads this, so keep the size explicit */
+       int ret_marshal;
+       /* If ret_marshal != NONE, this is the reg of the vret arg, else -1 */
+       /* Equivalent of vret_arg_slot in x86 implementation. */
+       int vret_arg_reg;
+       /* The stack slot where the return value will be stored */
+       int vret_slot;
+       int stack_usage, map_count;
+       /* If not -1, then make a virtual call using this vtable offset */
+       int vcall_offset;
+       /* If 1, make an indirect call to the address in the rgctx reg */
+       int calli;
+       /* Whenever this is a in or an out call */
+       int gsharedvt_in;
+       /* Maps stack slots/registers in the caller to the stack slots/registers in the callee */
+       int map [MONO_ZERO_LEN_ARRAY];
+} GSharedVtCallInfo;
+
+/* Number of argument registers (r0..r8) */
+#define NUM_GSHAREDVT_ARG_GREGS 9
+#define NUM_GSHAREDVT_ARG_FREGS 8
+
+gpointer
+mono_arm_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg);
+
+#endif /* __MINI_ARM64_GSHAREDVT_H__ */
index 517f6c68a9dd5b3ff95373c721f84ecd57f1f994..83fe015daa57455a7eebb8a748e4ce0060bfe7ab 100644 (file)
@@ -1 +1,5217 @@
-#include "../../../mono-extensions/mono/mini/mini-arm64.c"
+/*
+ * mini-arm64.c: ARM64 backend for the Mono code generator
+ *
+ * Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
+ * 
+ * Based on mini-arm.c:
+ *
+ * Authors:
+ *   Paolo Molaro (lupus@ximian.com)
+ *   Dietmar Maurer (dietmar@ximian.com)
+ *
+ * (C) 2003 Ximian, Inc.
+ * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "mini.h"
+#include "cpu-arm64.h"
+#include "ir-emit.h"
+
+#include <mono/arch/arm64/arm64-codegen.h>
+#include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-memory-model.h>
+#include <mono/metadata/abi-details.h>
+
+/*
+ * Documentation:
+ *
+ * - ARM(R) Architecture Reference Manual, ARMv8, for ARMv8-A architecture profile (DDI0487A_a_armv8_arm.pdf)
+ * - Procedure Call Standard for the ARM 64-bit Architecture (AArch64) (IHI0055B_aapcs64.pdf)
+ * - ELF for the ARM 64-bit Architecture (IHI0056B_aaelf64.pdf)
+ *
+ * Register usage:
+ * - ip0/ip1/lr are used as temporary registers
+ * - r27 is used as the rgctx/imt register
+ * - r28 is used to access arguments passed on the stack
+ * - d15/d16 are used as fp temporary registers
+ */
+
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+#define FP_TEMP_REG ARMREG_D16
+#define FP_TEMP_REG2 ARMREG_D17
+
+#define THUNK_SIZE (4 * 4)
+
+/* The single step trampoline */
+static gpointer ss_trampoline;
+
+/* The breakpoint trampoline */
+static gpointer bp_trampoline;
+
+static gboolean ios_abi;
+
+static __attribute__((warn_unused_result)) guint8* emit_load_regset (guint8 *code, guint64 regs, int basereg, int offset);
+
+const char*
+mono_arch_regname (int reg)
+{
+       static const char * rnames[] = {
+               "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+               "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
+               "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "fp",
+               "lr", "sp"
+       };
+       if (reg >= 0 && reg < 32)
+               return rnames [reg];
+       return "unknown";
+}
+
+const char*
+mono_arch_fregname (int reg)
+{
+       static const char * rnames[] = {
+               "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
+               "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
+               "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
+               "d30", "d31"
+       };
+       if (reg >= 0 && reg < 32)
+               return rnames [reg];
+       return "unknown fp";
+}
+
+int
+mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
+{
+       NOT_IMPLEMENTED;
+       return 0;
+}
+
+#define MAX_ARCH_DELEGATE_PARAMS 7
+
+static gpointer
+get_delegate_invoke_impl (gboolean has_target, gboolean param_count, guint32 *code_size)
+{
+       guint8 *code, *start;
+
+       if (has_target) {
+               start = code = mono_global_codeman_reserve (12);
+
+               /* Replace the this argument with the target */
+               arm_ldrx (code, ARMREG_IP0, ARMREG_R0, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
+               arm_ldrx (code, ARMREG_R0, ARMREG_R0, MONO_STRUCT_OFFSET (MonoDelegate, target));
+               arm_brx (code, ARMREG_IP0);
+
+               g_assert ((code - start) <= 12);
+
+               mono_arch_flush_icache (start, 12);
+       } else {
+               int size, i;
+
+               size = 8 + param_count * 4;
+               start = code = mono_global_codeman_reserve (size);
+
+               arm_ldrx (code, ARMREG_IP0, ARMREG_R0, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
+               /* slide down the arguments */
+               for (i = 0; i < param_count; ++i)
+                       arm_movx (code, i, i + 1);
+               arm_brx (code, ARMREG_IP0);
+
+               g_assert ((code - start) <= size);
+
+               mono_arch_flush_icache (start, size);
+       }
+
+       if (code_size)
+               *code_size = code - start;
+
+       return start;
+}
+
+/*
+ * mono_arch_get_delegate_invoke_impls:
+ *
+ *   Return a list of MonoAotTrampInfo structures for the delegate invoke impl
+ * trampolines.
+ */
+GSList*
+mono_arch_get_delegate_invoke_impls (void)
+{
+       GSList *res = NULL;
+       guint8 *code;
+       guint32 code_len;
+       int i;
+       char *tramp_name;
+
+       code = get_delegate_invoke_impl (TRUE, 0, &code_len);
+       res = g_slist_prepend (res, mono_tramp_info_create ("delegate_invoke_impl_has_target", code, code_len, NULL, NULL));
+
+       for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
+               code = get_delegate_invoke_impl (FALSE, i, &code_len);
+               tramp_name = g_strdup_printf ("delegate_invoke_impl_target_%d", i);
+               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
+               g_free (tramp_name);
+       }
+
+       return res;
+}
+
+gpointer
+mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
+{
+       guint8 *code, *start;
+
+       /*
+        * vtypes are returned in registers, or using the dedicated r8 register, so
+        * they can be supported by delegate invokes.
+        */
+
+       if (has_target) {
+               static guint8* cached = NULL;
+
+               if (cached)
+                       return cached;
+
+               if (mono_aot_only)
+                       start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
+               else
+                       start = get_delegate_invoke_impl (TRUE, 0, NULL);
+               mono_memory_barrier ();
+               cached = start;
+               return cached;
+       } else {
+               static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
+               int i;
+
+               if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
+                       return NULL;
+               for (i = 0; i < sig->param_count; ++i)
+                       if (!mono_is_regsize_var (sig->params [i]))
+                               return NULL;
+
+               code = cache [sig->param_count];
+               if (code)
+                       return code;
+
+               if (mono_aot_only) {
+                       char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
+                       start = mono_aot_get_trampoline (name);
+                       g_free (name);
+               } else {
+                       start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL);
+               }
+               mono_memory_barrier ();
+               cache [sig->param_count] = start;
+               return start;
+       }
+
+       return NULL;
+}
+
+gpointer
+mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
+{
+       return NULL;
+}
+
+gpointer
+mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
+{
+       return (gpointer)regs [ARMREG_R0];
+}
+
+void
+mono_arch_cpu_init (void)
+{
+}
+
+void
+mono_arch_init (void)
+{
+       mono_aot_register_jit_icall ("mono_arm_throw_exception", mono_arm_throw_exception);
+       mono_aot_register_jit_icall ("mono_arm_resume_unwind", mono_arm_resume_unwind);
+
+       if (!mono_aot_only)
+               bp_trampoline = mini_get_breakpoint_trampoline ();
+
+       mono_arm_gsharedvt_init ();
+
+#if defined(TARGET_IOS)
+       ios_abi = TRUE;
+#endif
+}
+
+void
+mono_arch_cleanup (void)
+{
+}
+
+guint32
+mono_arch_cpu_optimizations (guint32 *exclude_mask)
+{
+       *exclude_mask = 0;
+       return 0;
+}
+
+guint32
+mono_arch_cpu_enumerate_simd_versions (void)
+{
+       return 0;
+}
+
+void
+mono_arch_register_lowlevel_calls (void)
+{
+}
+
+void
+mono_arch_finish_init (void)
+{
+}
+
+/* The maximum length is 2 instructions */
+static guint8*
+emit_imm (guint8 *code, int dreg, int imm)
+{
+       // FIXME: Optimize this
+       if (imm < 0) {
+               gint64 limm = imm;
+               arm_movnx (code, dreg, (~limm) & 0xffff, 0);
+               arm_movkx (code, dreg, (limm >> 16) & 0xffff, 16);
+       } else {
+               arm_movzx (code, dreg, imm & 0xffff, 0);
+               if (imm >> 16)
+                       arm_movkx (code, dreg, (imm >> 16) & 0xffff, 16);
+       }
+
+       return code;
+}
+
+/* The maximum length is 4 instructions */
+static guint8*
+emit_imm64 (guint8 *code, int dreg, guint64 imm)
+{
+       // FIXME: Optimize this
+       arm_movzx (code, dreg, imm & 0xffff, 0);
+       if ((imm >> 16) & 0xffff)
+               arm_movkx (code, dreg, (imm >> 16) & 0xffff, 16);
+       if ((imm >> 32) & 0xffff)
+               arm_movkx (code, dreg, (imm >> 32) & 0xffff, 32);
+       if ((imm >> 48) & 0xffff)
+               arm_movkx (code, dreg, (imm >> 48) & 0xffff, 48);
+
+       return code;
+}
+
+guint8*
+mono_arm_emit_imm64 (guint8 *code, int dreg, gint64 imm)
+{
+       return emit_imm64 (code, dreg, imm);
+}
+
+/*
+ * emit_imm_template:
+ *
+ *   Emit a patchable code sequence for constructing a 64 bit immediate.
+ */
+static guint8*
+emit_imm64_template (guint8 *code, int dreg)
+{
+       arm_movzx (code, dreg, 0, 0);
+       arm_movkx (code, dreg, 0, 16);
+       arm_movkx (code, dreg, 0, 32);
+       arm_movkx (code, dreg, 0, 48);
+
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_addw_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+       if (!arm_is_arith_imm (imm)) {
+               code = emit_imm (code, ARMREG_LR, imm);
+               arm_addw (code, dreg, sreg, ARMREG_LR);
+       } else {
+               arm_addw_imm (code, dreg, sreg, imm);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_addx_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+       if (!arm_is_arith_imm (imm)) {
+               code = emit_imm (code, ARMREG_LR, imm);
+               arm_addx (code, dreg, sreg, ARMREG_LR);
+       } else {
+               arm_addx_imm (code, dreg, sreg, imm);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_subw_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+       if (!arm_is_arith_imm (imm)) {
+               code = emit_imm (code, ARMREG_LR, imm);
+               arm_subw (code, dreg, sreg, ARMREG_LR);
+       } else {
+               arm_subw_imm (code, dreg, sreg, imm);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_subx_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+       if (!arm_is_arith_imm (imm)) {
+               code = emit_imm (code, ARMREG_LR, imm);
+               arm_subx (code, dreg, sreg, ARMREG_LR);
+       } else {
+               arm_subx_imm (code, dreg, sreg, imm);
+       }
+       return code;
+}
+
+/* Emit sp+=imm. Clobbers ip0/ip1 */
+static inline __attribute__((warn_unused_result)) guint8*
+emit_addx_sp_imm (guint8 *code, int imm)
+{
+       code = emit_imm (code, ARMREG_IP0, imm);
+       arm_movspx (code, ARMREG_IP1, ARMREG_SP);
+       arm_addx (code, ARMREG_IP1, ARMREG_IP1, ARMREG_IP0);
+       arm_movspx (code, ARMREG_SP, ARMREG_IP1);
+       return code;
+}
+
+/* Emit sp-=imm. Clobbers ip0/ip1 */
+static inline __attribute__((warn_unused_result)) guint8*
+emit_subx_sp_imm (guint8 *code, int imm)
+{
+       code = emit_imm (code, ARMREG_IP0, imm);
+       arm_movspx (code, ARMREG_IP1, ARMREG_SP);
+       arm_subx (code, ARMREG_IP1, ARMREG_IP1, ARMREG_IP0);
+       arm_movspx (code, ARMREG_SP, ARMREG_IP1);
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_andw_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+       // FIXME:
+       code = emit_imm (code, ARMREG_LR, imm);
+       arm_andw (code, dreg, sreg, ARMREG_LR);
+
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_andx_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+       // FIXME:
+       code = emit_imm (code, ARMREG_LR, imm);
+       arm_andx (code, dreg, sreg, ARMREG_LR);
+
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_orrw_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+       // FIXME:
+       code = emit_imm (code, ARMREG_LR, imm);
+       arm_orrw (code, dreg, sreg, ARMREG_LR);
+
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_orrx_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+       // FIXME:
+       code = emit_imm (code, ARMREG_LR, imm);
+       arm_orrx (code, dreg, sreg, ARMREG_LR);
+
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_eorw_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+       // FIXME:
+       code = emit_imm (code, ARMREG_LR, imm);
+       arm_eorw (code, dreg, sreg, ARMREG_LR);
+
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_eorx_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+       // FIXME:
+       code = emit_imm (code, ARMREG_LR, imm);
+       arm_eorx (code, dreg, sreg, ARMREG_LR);
+
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_cmpw_imm (guint8 *code, int sreg, int imm)
+{
+       if (imm == 0) {
+               arm_cmpw (code, sreg, ARMREG_RZR);
+       } else {
+               // FIXME:
+               code = emit_imm (code, ARMREG_LR, imm);
+               arm_cmpw (code, sreg, ARMREG_LR);
+       }
+
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_cmpx_imm (guint8 *code, int sreg, int imm)
+{
+       if (imm == 0) {
+               arm_cmpx (code, sreg, ARMREG_RZR);
+       } else {
+               // FIXME:
+               code = emit_imm (code, ARMREG_LR, imm);
+               arm_cmpx (code, sreg, ARMREG_LR);
+       }
+
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_strb (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_strb_imm (imm)) {
+               arm_strb (code, rt, rn, imm);
+       } else {
+               g_assert (rt != ARMREG_IP0);
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_strb_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_strh (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_strh_imm (imm)) {
+               arm_strh (code, rt, rn, imm);
+       } else {
+               g_assert (rt != ARMREG_IP0);
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_strh_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_strw (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_strw_imm (imm)) {
+               arm_strw (code, rt, rn, imm);
+       } else {
+               g_assert (rt != ARMREG_IP0);
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_strw_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_strfpw (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_strw_imm (imm)) {
+               arm_strfpw (code, rt, rn, imm);
+       } else {
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_addx (code, ARMREG_IP0, rn, ARMREG_IP0);
+               arm_strfpw (code, rt, ARMREG_IP0, 0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_strfpx (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_strx_imm (imm)) {
+               arm_strfpx (code, rt, rn, imm);
+       } else {
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_addx (code, ARMREG_IP0, rn, ARMREG_IP0);
+               arm_strfpx (code, rt, ARMREG_IP0, 0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_strx (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_strx_imm (imm)) {
+               arm_strx (code, rt, rn, imm);
+       } else {
+               g_assert (rt != ARMREG_IP0);
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_strx_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_ldrb (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_pimm12_scaled (imm, 1)) {
+               arm_ldrb (code, rt, rn, imm);
+       } else {
+               g_assert (rt != ARMREG_IP0);
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_ldrb_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_ldrsbx (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_pimm12_scaled (imm, 1)) {
+               arm_ldrsbx (code, rt, rn, imm);
+       } else {
+               g_assert (rt != ARMREG_IP0);
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_ldrsbx_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_ldrh (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_pimm12_scaled (imm, 2)) {
+               arm_ldrh (code, rt, rn, imm);
+       } else {
+               g_assert (rt != ARMREG_IP0);
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_ldrh_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_ldrshx (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_pimm12_scaled (imm, 2)) {
+               arm_ldrshx (code, rt, rn, imm);
+       } else {
+               g_assert (rt != ARMREG_IP0);
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_ldrshx_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_ldrswx (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_pimm12_scaled (imm, 4)) {
+               arm_ldrswx (code, rt, rn, imm);
+       } else {
+               g_assert (rt != ARMREG_IP0);
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_ldrswx_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_ldrw (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_pimm12_scaled (imm, 4)) {
+               arm_ldrw (code, rt, rn, imm);
+       } else {
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_ldrw_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_ldrx (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_pimm12_scaled (imm, 8)) {
+               arm_ldrx (code, rt, rn, imm);
+       } else {
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_ldrx_reg (code, rt, rn, ARMREG_IP0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_ldrfpw (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_pimm12_scaled (imm, 4)) {
+               arm_ldrfpw (code, rt, rn, imm);
+       } else {
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_addx (code, ARMREG_IP0, rn, ARMREG_IP0);
+               arm_ldrfpw (code, rt, ARMREG_IP0, 0);
+       }
+       return code;
+}
+
+static inline __attribute__((warn_unused_result)) guint8*
+emit_ldrfpx (guint8 *code, int rt, int rn, int imm)
+{
+       if (arm_is_pimm12_scaled (imm, 8)) {
+               arm_ldrfpx (code, rt, rn, imm);
+       } else {
+               g_assert (rn != ARMREG_IP0);
+               code = emit_imm (code, ARMREG_IP0, imm);
+               arm_addx (code, ARMREG_IP0, rn, ARMREG_IP0);
+               arm_ldrfpx (code, rt, ARMREG_IP0, 0);
+       }
+       return code;
+}
+
+guint8*
+mono_arm_emit_ldrx (guint8 *code, int rt, int rn, int imm)
+{
+       return emit_ldrx (code, rt, rn, imm);
+}
+
+static guint8*
+emit_call (MonoCompile *cfg, guint8* code, guint32 patch_type, gconstpointer data)
+{
+       /*
+       mono_add_patch_info_rel (cfg, code - cfg->native_code, patch_type, data, MONO_R_ARM64_IMM);
+       code = emit_imm64_template (code, ARMREG_LR);
+       arm_blrx (code, ARMREG_LR);
+       */
+       mono_add_patch_info_rel (cfg, code - cfg->native_code, patch_type, data, MONO_R_ARM64_BL);
+       arm_bl (code, code);
+       cfg->thunk_area += THUNK_SIZE;
+       return code;
+}
+
+static guint8*
+emit_aotconst_full (MonoCompile *cfg, MonoJumpInfo **ji, guint8 *code, guint8 *start, int dreg, guint32 patch_type, gconstpointer data)
+{
+       if (cfg)
+               mono_add_patch_info (cfg, code - cfg->native_code, patch_type, data);
+       else
+               *ji = mono_patch_info_list_prepend (*ji, code - start, patch_type, data);
+       /* See arch_emit_got_access () in aot-compiler.c */
+       arm_ldrx_lit (code, dreg, 0);
+       arm_nop (code);
+       arm_nop (code);
+       return code;
+}
+
+static guint8*
+emit_aotconst (MonoCompile *cfg, guint8 *code, int dreg, guint32 patch_type, gconstpointer data)
+{
+       return emit_aotconst_full (cfg, NULL, code, NULL, dreg, patch_type, data);
+}
+
+/*
+ * mono_arm_emit_aotconst:
+ *
+ *   Emit code to load an AOT constant into DREG. Usable from trampolines.
+ */
+guint8*
+mono_arm_emit_aotconst (gpointer ji, guint8 *code, guint8 *code_start, int dreg, guint32 patch_type, gconstpointer data)
+{
+       return emit_aotconst_full (NULL, (MonoJumpInfo**)ji, code, code_start, dreg, patch_type, data);
+}
+
+static guint8*
+emit_tls_get (guint8 *code, int dreg, int tls_offset)
+{
+       arm_mrs (code, dreg, ARM_MRS_REG_TPIDR_EL0);
+       if (tls_offset < 256) {
+               arm_ldrx (code, dreg, dreg, tls_offset);
+       } else {
+               code = emit_addx_imm (code, dreg, dreg, tls_offset);
+               arm_ldrx (code, dreg, dreg, 0);
+       }
+       return code;
+}
+
+static guint8*
+emit_tls_get_reg (guint8 *code, int dreg, int offset_reg)
+{
+       g_assert (offset_reg != ARMREG_IP0);
+       arm_mrs (code, ARMREG_IP0, ARM_MRS_REG_TPIDR_EL0);
+       arm_ldrx_reg (code, dreg, ARMREG_IP0, offset_reg);
+       return code;
+}
+
+static guint8*
+emit_tls_set (guint8 *code, int sreg, int tls_offset)
+{
+       int tmpreg = ARMREG_IP0;
+
+       g_assert (sreg != tmpreg);
+       arm_mrs (code, tmpreg, ARM_MRS_REG_TPIDR_EL0);
+       if (tls_offset < 256) {
+               arm_strx (code, sreg, tmpreg, tls_offset);
+       } else {
+               code = emit_addx_imm (code, tmpreg, tmpreg, tls_offset);
+               arm_strx (code, sreg, tmpreg, 0);
+       }
+       return code;
+}
+
+
+static guint8*
+emit_tls_set_reg (guint8 *code, int sreg, int offset_reg)
+{
+       int tmpreg = ARMREG_IP0;
+
+       g_assert (sreg != tmpreg);
+       arm_mrs (code, tmpreg, ARM_MRS_REG_TPIDR_EL0);
+       arm_strx_reg (code, sreg, tmpreg, offset_reg);
+       return code;
+}
+
+/*
+ * Emits
+ * - mov sp, fp
+ * - ldrp [fp, lr], [sp], !stack_offfset
+ * Clobbers TEMP_REGS.
+ */
+__attribute__((warn_unused_result)) guint8*
+mono_arm_emit_destroy_frame (guint8 *code, int stack_offset, guint64 temp_regs)
+{
+       arm_movspx (code, ARMREG_SP, ARMREG_FP);
+
+       if (arm_is_ldpx_imm (stack_offset)) {
+               arm_ldpx_post (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, stack_offset);
+       } else {
+               arm_ldpx (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, 0);
+               /* sp += stack_offset */
+               g_assert (temp_regs & (1 << ARMREG_IP0));
+               if (temp_regs & (1 << ARMREG_IP1)) {
+                       code = emit_addx_sp_imm (code, stack_offset);
+               } else {
+                       int imm = stack_offset;
+
+                       /* Can't use addx_sp_imm () since we can't clobber ip0/ip1 */
+                       arm_addx_imm (code, ARMREG_IP0, ARMREG_SP, 0);
+                       while (imm > 256) {
+                               arm_addx_imm (code, ARMREG_IP0, ARMREG_IP0, 256);
+                               imm -= 256;
+                       }
+                       arm_addx_imm (code, ARMREG_SP, ARMREG_IP0, imm);
+               }
+       }
+       return code;
+}
+
+#define is_call_imm(diff) ((gint)(diff) >= -33554432 && (gint)(diff) <= 33554431)
+
+static guint8*
+emit_thunk (guint8 *code, gconstpointer target)
+{
+       guint8 *p = code;
+
+       arm_ldrx_lit (code, ARMREG_IP0, code + 8);
+       arm_brx (code, ARMREG_IP0);
+       *(guint64*)code = (guint64)target;
+
+       mono_arch_flush_icache (p, code - p);
+       return code;
+}
+
+static gpointer
+create_thunk (MonoCompile *cfg, MonoDomain *domain, guchar *code, const guchar *target)
+{
+       MonoJitInfo *ji;
+       MonoThunkJitInfo *info;
+       guint8 *thunks, *p;
+       int thunks_size;
+       guint8 *orig_target;
+       guint8 *target_thunk;
+
+       if (!domain)
+               domain = mono_domain_get ();
+
+       if (cfg) {
+               /*
+                * This can be called multiple times during JITting,
+                * save the current position in cfg->arch to avoid
+                * doing a O(n^2) search.
+                */
+               if (!cfg->arch.thunks) {
+                       cfg->arch.thunks = cfg->thunks;
+                       cfg->arch.thunks_size = cfg->thunk_area;
+               }
+               thunks = cfg->arch.thunks;
+               thunks_size = cfg->arch.thunks_size;
+               if (!thunks_size) {
+                       g_print ("thunk failed %p->%p, thunk space=%d method %s", code, target, thunks_size, mono_method_full_name (cfg->method, TRUE));
+                       g_assert_not_reached ();
+               }
+
+               g_assert (*(guint32*)thunks == 0);
+               emit_thunk (thunks, target);
+
+               cfg->arch.thunks += THUNK_SIZE;
+               cfg->arch.thunks_size -= THUNK_SIZE;
+
+               return thunks;
+       } else {
+               ji = mini_jit_info_table_find (domain, (char*)code, NULL);
+               g_assert (ji);
+               info = mono_jit_info_get_thunk_info (ji);
+               g_assert (info);
+
+               thunks = (guint8*)ji->code_start + info->thunks_offset;
+               thunks_size = info->thunks_size;
+
+               orig_target = mono_arch_get_call_target (code + 4);
+
+               mono_domain_lock (domain);
+
+               target_thunk = NULL;
+               if (orig_target >= thunks && orig_target < thunks + thunks_size) {
+                       /* The call already points to a thunk, because of trampolines etc. */
+                       target_thunk = orig_target;
+               } else {
+                       for (p = thunks; p < thunks + thunks_size; p += THUNK_SIZE) {
+                               if (((guint32*)p) [0] == 0) {
+                                       /* Free entry */
+                                       target_thunk = p;
+                                       break;
+                               } else if (((guint64*)p) [1] == (guint64)target) {
+                                       /* Thunk already points to target */
+                                       target_thunk = p;
+                                       break;
+                               }
+                       }
+               }
+
+               //printf ("THUNK: %p %p %p\n", code, target, target_thunk);
+
+               if (!target_thunk) {
+                       mono_domain_unlock (domain);
+                       g_print ("thunk failed %p->%p, thunk space=%d method %s", code, target, thunks_size, cfg ? mono_method_full_name (cfg->method, TRUE) : mono_method_full_name (jinfo_get_method (ji), TRUE));
+                       g_assert_not_reached ();
+               }
+
+               emit_thunk (target_thunk, target);
+
+               mono_domain_unlock (domain);
+
+               return target_thunk;
+       }
+}
+
+static void
+arm_patch_full (MonoCompile *cfg, MonoDomain *domain, guint8 *code, guint8 *target, int relocation)
+{
+       switch (relocation) {
+       case MONO_R_ARM64_B:
+               arm_b (code, target);
+               break;
+       case MONO_R_ARM64_BCC: {
+               int cond;
+
+               cond = arm_get_bcc_cond (code);
+               arm_bcc (code, cond, target);
+               break;
+       }
+       case MONO_R_ARM64_CBZ:
+               arm_set_cbz_target (code, target);
+               break;
+       case MONO_R_ARM64_IMM: {
+               guint64 imm = (guint64)target;
+               int dreg;
+
+               /* emit_imm64_template () */
+               dreg = arm_get_movzx_rd (code);
+               arm_movzx (code, dreg, imm & 0xffff, 0);
+               arm_movkx (code, dreg, (imm >> 16) & 0xffff, 16);
+               arm_movkx (code, dreg, (imm >> 32) & 0xffff, 32);
+               arm_movkx (code, dreg, (imm >> 48) & 0xffff, 48);
+               break;
+       }
+       case MONO_R_ARM64_BL:
+               if (arm_is_bl_disp (code, target)) {
+                       arm_bl (code, target);
+               } else {
+                       gpointer thunk;
+
+                       thunk = create_thunk (cfg, domain, code, target);
+                       g_assert (arm_is_bl_disp (code, thunk));
+                       arm_bl (code, thunk);                   
+               }
+               break;
+       default:
+               g_assert_not_reached ();
+       }
+}
+
+static void
+arm_patch_rel (guint8 *code, guint8 *target, int relocation)
+{
+       arm_patch_full (NULL, NULL, code, target, relocation);
+}
+
+void
+mono_arm_patch (guint8 *code, guint8 *target, int relocation)
+{
+       arm_patch_rel (code, target, relocation);
+}
+
+void
+mono_arch_patch_code_new (MonoCompile *cfg, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gpointer target)
+{
+       guint8 *ip;
+
+       ip = ji->ip.i + code;
+
+       switch (ji->type) {
+       case MONO_PATCH_INFO_METHOD_JUMP:
+               /* ji->relocation is not set by the caller */
+               arm_patch_rel (ip, (guint8*)target, MONO_R_ARM64_B);
+               break;
+       default:
+               arm_patch_full (cfg, domain, ip, (guint8*)target, ji->relocation);
+               break;
+       }
+}
+
+void
+mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
+{
+}
+
+void
+mono_arch_flush_register_windows (void)
+{
+}
+
+MonoMethod*
+mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
+{
+       return (gpointer)regs [MONO_ARCH_RGCTX_REG];
+}
+
+MonoVTable*
+mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
+{
+       return (gpointer)regs [MONO_ARCH_RGCTX_REG];
+}
+
+mgreg_t
+mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
+{
+       return ctx->regs [reg];
+}
+
+void
+mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
+{
+       ctx->regs [reg] = val;
+}
+
+/*
+ * mono_arch_set_target:
+ *
+ *   Set the target architecture the JIT backend should generate code for, in the form
+ * of a GNU target triplet. Only used in AOT mode.
+ */
+void
+mono_arch_set_target (char *mtriple)
+{
+       if (strstr (mtriple, "darwin") || strstr (mtriple, "ios")) {
+               ios_abi = TRUE;
+       }
+}
+
+static void
+add_general (CallInfo *cinfo, ArgInfo *ainfo, int size, gboolean sign)
+{
+       if (cinfo->gr >= PARAM_REGS) {
+               ainfo->storage = ArgOnStack;
+               if (ios_abi) {
+                       /* Assume size == align */
+                       cinfo->stack_usage = ALIGN_TO (cinfo->stack_usage, size);
+                       ainfo->offset = cinfo->stack_usage;
+                       ainfo->slot_size = size;
+                       ainfo->sign = sign;
+                       cinfo->stack_usage += size;
+               } else {
+                       ainfo->offset = cinfo->stack_usage;
+                       ainfo->slot_size = 8;
+                       ainfo->sign = FALSE;
+                       /* Put arguments into 8 byte aligned stack slots */
+                       cinfo->stack_usage += 8;
+               }
+       } else {
+               ainfo->storage = ArgInIReg;
+               ainfo->reg = cinfo->gr;
+               cinfo->gr ++;
+       }
+}
+
+static void
+add_fp (CallInfo *cinfo, ArgInfo *ainfo, gboolean single)
+{
+       int size = single ? 4 : 8;
+
+       if (cinfo->fr >= FP_PARAM_REGS) {
+               ainfo->storage = single ? ArgOnStackR4 : ArgOnStackR8;
+               if (ios_abi) {
+                       cinfo->stack_usage = ALIGN_TO (cinfo->stack_usage, size);
+                       ainfo->offset = cinfo->stack_usage;
+                       ainfo->slot_size = size;
+                       cinfo->stack_usage += size;
+               } else {
+                       ainfo->offset = cinfo->stack_usage;
+                       ainfo->slot_size = 8;
+                       /* Put arguments into 8 byte aligned stack slots */
+                       cinfo->stack_usage += 8;
+               }
+       } else {
+               if (single)
+                       ainfo->storage = ArgInFRegR4;
+               else
+                       ainfo->storage = ArgInFReg;
+               ainfo->reg = cinfo->fr;
+               cinfo->fr ++;
+       }
+}
+
+static gboolean
+is_hfa (MonoType *t, int *out_nfields, int *out_esize, int *field_offsets)
+{
+       MonoClass *klass;
+       gpointer iter;
+       MonoClassField *field;
+       MonoType *ftype, *prev_ftype = NULL;
+       int i, nfields = 0;
+
+       klass = mono_class_from_mono_type (t);
+       iter = NULL;
+       while ((field = mono_class_get_fields (klass, &iter))) {
+               if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+                       continue;
+               ftype = mono_field_get_type (field);
+               ftype = mini_get_underlying_type (ftype);
+
+               if (MONO_TYPE_ISSTRUCT (ftype)) {
+                       int nested_nfields, nested_esize;
+                       int nested_field_offsets [16];
+
+                       if (!is_hfa (ftype, &nested_nfields, &nested_esize, nested_field_offsets))
+                               return FALSE;
+                       if (nested_esize == 4)
+                               ftype = &mono_defaults.single_class->byval_arg;
+                       else
+                               ftype = &mono_defaults.double_class->byval_arg;
+                       if (prev_ftype && prev_ftype->type != ftype->type)
+                               return FALSE;
+                       prev_ftype = ftype;
+                       for (i = 0; i < nested_nfields; ++i) {
+                               if (nfields + i < 4)
+                                       field_offsets [nfields + i] = field->offset - sizeof (MonoObject) + nested_field_offsets [i];
+                       }
+                       nfields += nested_nfields;
+               } else {
+                       if (!(!ftype->byref && (ftype->type == MONO_TYPE_R4 || ftype->type == MONO_TYPE_R8)))
+                               return FALSE;
+                       if (prev_ftype && prev_ftype->type != ftype->type)
+                               return FALSE;
+                       prev_ftype = ftype;
+                       if (nfields < 4)
+                               field_offsets [nfields] = field->offset - sizeof (MonoObject);
+                       nfields ++;
+               }
+       }
+       if (nfields == 0 || nfields > 4)
+               return FALSE;
+       *out_nfields = nfields;
+       *out_esize = prev_ftype->type == MONO_TYPE_R4 ? 4 : 8;
+       return TRUE;
+}
+
+static void
+add_valuetype (CallInfo *cinfo, ArgInfo *ainfo, MonoType *t)
+{
+       int i, size, align_size, nregs, nfields, esize;
+       int field_offsets [16];
+       guint32 align;
+
+       size = mini_type_stack_size_full (t, &align, FALSE);
+       align_size = ALIGN_TO (size, 8);
+
+       nregs = size / 8;
+       if (is_hfa (t, &nfields, &esize, field_offsets)) {
+               /*
+                * The struct might include nested float structs aligned at 8,
+                * so need to keep track of the offsets of the individual fields.
+                */
+               if (cinfo->fr + nfields <= FP_PARAM_REGS) {
+                       ainfo->storage = ArgHFA;
+                       ainfo->reg = cinfo->fr;
+                       ainfo->nregs = nfields;
+                       ainfo->size = size;
+                       ainfo->esize = esize;
+                       for (i = 0; i < nfields; ++i)
+                               ainfo->foffsets [i] = field_offsets [i];
+                       cinfo->fr += ainfo->nregs;
+               } else {
+                       ainfo->nfregs_to_skip = FP_PARAM_REGS > cinfo->fr ? FP_PARAM_REGS - cinfo->fr : 0;
+                       cinfo->fr = FP_PARAM_REGS;
+                       size = ALIGN_TO (size, 8);
+                       ainfo->storage = ArgVtypeOnStack;
+                       ainfo->offset = cinfo->stack_usage;
+                       ainfo->size = size;
+                       ainfo->hfa = TRUE;
+                       ainfo->nregs = nfields;
+                       ainfo->esize = esize;
+                       cinfo->stack_usage += size;
+               }
+               return;
+       }
+
+       if (align_size > 16) {
+               ainfo->storage = ArgVtypeByRef;
+               ainfo->size = size;
+               return;
+       }
+
+       if (cinfo->gr + nregs > PARAM_REGS) {
+               size = ALIGN_TO (size, 8);
+               ainfo->storage = ArgVtypeOnStack;
+               ainfo->offset = cinfo->stack_usage;
+               ainfo->size = size;
+               cinfo->stack_usage += size;
+               cinfo->gr = PARAM_REGS;
+       } else {
+               ainfo->storage = ArgVtypeInIRegs;
+               ainfo->reg = cinfo->gr;
+               ainfo->nregs = nregs;
+               ainfo->size = size;
+               cinfo->gr += nregs;
+       }
+}
+
+static void
+add_param (CallInfo *cinfo, ArgInfo *ainfo, MonoType *t)
+{
+       MonoType *ptype;
+
+       ptype = mini_get_underlying_type (t);
+       switch (ptype->type) {
+       case MONO_TYPE_I1:
+               add_general (cinfo, ainfo, 1, TRUE);
+               break;
+       case MONO_TYPE_BOOLEAN:
+       case MONO_TYPE_U1:
+               add_general (cinfo, ainfo, 1, FALSE);
+               break;
+       case MONO_TYPE_I2:
+               add_general (cinfo, ainfo, 2, TRUE);
+               break;
+       case MONO_TYPE_U2:
+       case MONO_TYPE_CHAR:
+               add_general (cinfo, ainfo, 2, FALSE);
+               break;
+       case MONO_TYPE_I4:
+               add_general (cinfo, ainfo, 4, TRUE);
+               break;
+       case MONO_TYPE_U4:
+               add_general (cinfo, ainfo, 4, FALSE);
+               break;
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+       case MONO_TYPE_PTR:
+       case MONO_TYPE_FNPTR:
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_ARRAY:
+       case MONO_TYPE_STRING:
+       case MONO_TYPE_U8:
+       case MONO_TYPE_I8:
+               add_general (cinfo, ainfo, 8, FALSE);
+               break;
+       case MONO_TYPE_R8:
+               add_fp (cinfo, ainfo, FALSE);
+               break;
+       case MONO_TYPE_R4:
+               add_fp (cinfo, ainfo, TRUE);
+               break;
+       case MONO_TYPE_VALUETYPE:
+       case MONO_TYPE_TYPEDBYREF:
+               add_valuetype (cinfo, ainfo, ptype);
+               break;
+       case MONO_TYPE_VOID:
+               ainfo->storage = ArgNone;
+               break;
+       case MONO_TYPE_GENERICINST:
+               if (!mono_type_generic_inst_is_valuetype (ptype)) {
+                       add_general (cinfo, ainfo, 8, FALSE);
+               } else if (mini_is_gsharedvt_variable_type (ptype)) {
+                       /*
+                        * Treat gsharedvt arguments as large vtypes
+                        */
+                       ainfo->storage = ArgVtypeByRef;
+                       ainfo->gsharedvt = TRUE;
+               } else {
+                       add_valuetype (cinfo, ainfo, ptype);
+               }
+               break;
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
+               g_assert (mini_is_gsharedvt_type (ptype));
+               ainfo->storage = ArgVtypeByRef;
+               ainfo->gsharedvt = TRUE;
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+}
+
+/*
+ * get_call_info:
+ *
+ *  Obtain information about a call according to the calling convention.
+ */
+static CallInfo*
+get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
+{
+       CallInfo *cinfo;
+       ArgInfo *ainfo;
+       int n, pstart, pindex;
+
+       n = sig->hasthis + sig->param_count;
+
+       if (mp)
+               cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + (sizeof (ArgInfo) * n));
+       else
+               cinfo = g_malloc0 (sizeof (CallInfo) + (sizeof (ArgInfo) * n));
+
+       cinfo->nargs = n;
+
+       /* Return value */
+       add_param (cinfo, &cinfo->ret, sig->ret);
+       if (cinfo->ret.storage == ArgVtypeByRef)
+               cinfo->ret.reg = ARMREG_R8;
+       /* Reset state */
+       cinfo->gr = 0;
+       cinfo->fr = 0;
+       cinfo->stack_usage = 0;
+
+       /* Parameters */
+       if (sig->hasthis)
+               add_general (cinfo, cinfo->args + 0, 8, FALSE);
+       pstart = 0;
+       for (pindex = pstart; pindex < sig->param_count; ++pindex) {
+               ainfo = cinfo->args + sig->hasthis + pindex;
+
+               if ((sig->call_convention == MONO_CALL_VARARG) && (pindex == sig->sentinelpos)) {
+                       /* Prevent implicit arguments and sig_cookie from
+                          being passed in registers */
+                       cinfo->gr = PARAM_REGS;
+                       cinfo->fr = FP_PARAM_REGS;
+                       /* Emit the signature cookie just before the implicit arguments */
+                       add_param (cinfo, &cinfo->sig_cookie, &mono_defaults.int_class->byval_arg);
+               }
+
+               add_param (cinfo, ainfo, sig->params [pindex]);
+               if (ainfo->storage == ArgVtypeByRef) {
+                       /* Pass the argument address in the next register */
+                       if (cinfo->gr >= PARAM_REGS) {
+                               ainfo->storage = ArgVtypeByRefOnStack;
+                               ainfo->offset = cinfo->stack_usage;
+                               cinfo->stack_usage += 8;
+                       } else {
+                               ainfo->reg = cinfo->gr;
+                               cinfo->gr ++;
+                       }
+               }
+       }
+
+       /* Handle the case where there are no implicit arguments */
+       if ((sig->call_convention == MONO_CALL_VARARG) && (pindex == sig->sentinelpos)) {
+               /* Prevent implicit arguments and sig_cookie from
+                  being passed in registers */
+               cinfo->gr = PARAM_REGS;
+               cinfo->fr = FP_PARAM_REGS;
+               /* Emit the signature cookie just before the implicit arguments */
+               add_param (cinfo, &cinfo->sig_cookie, &mono_defaults.int_class->byval_arg);
+       }
+
+       cinfo->stack_usage = ALIGN_TO (cinfo->stack_usage, MONO_ARCH_FRAME_ALIGNMENT);
+
+       return cinfo;
+}
+
+typedef struct {
+       MonoMethodSignature *sig;
+       CallInfo *cinfo;
+       MonoType *rtype;
+       MonoType **param_types;
+       int n_fpargs, n_fpret;
+} ArchDynCallInfo;
+
+static gboolean
+dyn_call_supported (CallInfo *cinfo, MonoMethodSignature *sig)
+{
+       int i;
+
+       if (sig->hasthis + sig->param_count > PARAM_REGS + DYN_CALL_STACK_ARGS)
+               return FALSE;
+
+       // FIXME: Add more cases
+       switch (cinfo->ret.storage) {
+       case ArgNone:
+       case ArgInIReg:
+       case ArgInFReg:
+       case ArgInFRegR4:
+       case ArgVtypeByRef:
+               break;
+       case ArgVtypeInIRegs:
+               if (cinfo->ret.nregs > 2)
+                       return FALSE;
+               break;
+       case ArgHFA:
+               break;
+       default:
+               return FALSE;
+       }
+
+       for (i = 0; i < cinfo->nargs; ++i) {
+               ArgInfo *ainfo = &cinfo->args [i];
+
+               switch (ainfo->storage) {
+               case ArgInIReg:
+               case ArgVtypeInIRegs:
+               case ArgInFReg:
+               case ArgInFRegR4:
+               case ArgHFA:
+               case ArgVtypeByRef:
+                       break;
+               case ArgOnStack:
+                       if (ainfo->offset >= DYN_CALL_STACK_ARGS * sizeof (mgreg_t))
+                               return FALSE;
+                       break;
+               default:
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+MonoDynCallInfo*
+mono_arch_dyn_call_prepare (MonoMethodSignature *sig)
+{
+       ArchDynCallInfo *info;
+       CallInfo *cinfo;
+       int i;
+
+       cinfo = get_call_info (NULL, sig);
+
+       if (!dyn_call_supported (cinfo, sig)) {
+               g_free (cinfo);
+               return NULL;
+       }
+
+       info = g_new0 (ArchDynCallInfo, 1);
+       // FIXME: Preprocess the info to speed up start_dyn_call ()
+       info->sig = sig;
+       info->cinfo = cinfo;
+       info->rtype = mini_get_underlying_type (sig->ret);
+       info->param_types = g_new0 (MonoType*, sig->param_count);
+       for (i = 0; i < sig->param_count; ++i)
+               info->param_types [i] = mini_get_underlying_type (sig->params [i]);
+
+       switch (cinfo->ret.storage) {
+       case ArgInFReg:
+       case ArgInFRegR4:
+               info->n_fpret = 1;
+               break;
+       case ArgHFA:
+               info->n_fpret = cinfo->ret.nregs;
+               break;
+       default:
+               break;
+       }
+       
+       return (MonoDynCallInfo*)info;
+}
+
+void
+mono_arch_dyn_call_free (MonoDynCallInfo *info)
+{
+       ArchDynCallInfo *ainfo = (ArchDynCallInfo*)info;
+
+       g_free (ainfo->cinfo);
+       g_free (ainfo->param_types);
+       g_free (ainfo);
+}
+
+static double
+bitcast_r4_to_r8 (float f)
+{
+       float *p = &f;
+
+       return *(double*)p;
+}
+
+static float
+bitcast_r8_to_r4 (double f)
+{
+       double *p = &f;
+
+       return *(float*)p;
+}
+
+void
+mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, guint8 *buf, int buf_len)
+{
+       ArchDynCallInfo *dinfo = (ArchDynCallInfo*)info;
+       DynCallArgs *p = (DynCallArgs*)buf;
+       int aindex, arg_index, greg, i, pindex;
+       MonoMethodSignature *sig = dinfo->sig;
+       CallInfo *cinfo = dinfo->cinfo;
+       int buffer_offset = 0;
+
+       g_assert (buf_len >= sizeof (DynCallArgs));
+
+       p->res = 0;
+       p->ret = ret;
+       p->n_fpargs = dinfo->n_fpargs;
+       p->n_fpret = dinfo->n_fpret;
+
+       arg_index = 0;
+       greg = 0;
+       pindex = 0;
+
+       if (sig->hasthis)
+               p->regs [greg ++] = (mgreg_t)*(args [arg_index ++]);
+
+       if (cinfo->ret.storage == ArgVtypeByRef)
+               p->regs [ARMREG_R8] = (mgreg_t)ret;
+
+       for (aindex = pindex; aindex < sig->param_count; aindex++) {
+               MonoType *t = dinfo->param_types [aindex];
+               gpointer *arg = args [arg_index ++];
+               ArgInfo *ainfo = &cinfo->args [aindex + sig->hasthis];
+               int slot = -1;
+
+               if (ainfo->storage == ArgOnStack) {
+                       slot = PARAM_REGS + 1 + (ainfo->offset / sizeof (mgreg_t));
+               } else {
+                       slot = ainfo->reg;
+               }
+
+               if (t->byref) {
+                       p->regs [slot] = (mgreg_t)*arg;
+                       continue;
+               }
+
+               if (ios_abi && ainfo->storage == ArgOnStack) {
+                       guint8 *stack_arg = (guint8*)&(p->regs [PARAM_REGS + 1]) + ainfo->offset;
+                       gboolean handled = TRUE;
+
+                       /* Special case arguments smaller than 1 machine word */
+                       switch (t->type) {
+                       case MONO_TYPE_BOOLEAN:
+                       case MONO_TYPE_U1:
+                               *(guint8*)stack_arg = *(guint8*)arg;
+                               break;
+                       case MONO_TYPE_I1:
+                               *(gint8*)stack_arg = *(gint8*)arg;
+                               break;
+                       case MONO_TYPE_U2:
+                       case MONO_TYPE_CHAR:
+                               *(guint16*)stack_arg = *(guint16*)arg;
+                               break;
+                       case MONO_TYPE_I2:
+                               *(gint16*)stack_arg = *(gint16*)arg;
+                               break;
+                       case MONO_TYPE_I4:
+                               *(gint32*)stack_arg = *(gint32*)arg;
+                               break;
+                       case MONO_TYPE_U4:
+                               *(guint32*)stack_arg = *(guint32*)arg;
+                               break;
+                       default:
+                               handled = FALSE;
+                               break;
+                       }
+                       if (handled)
+                               continue;
+               }
+
+               switch (t->type) {
+               case MONO_TYPE_STRING:
+               case MONO_TYPE_CLASS:
+               case MONO_TYPE_ARRAY:
+               case MONO_TYPE_SZARRAY:
+               case MONO_TYPE_OBJECT:
+               case MONO_TYPE_PTR:
+               case MONO_TYPE_I:
+               case MONO_TYPE_U:
+               case MONO_TYPE_I8:
+               case MONO_TYPE_U8:
+                       p->regs [slot] = (mgreg_t)*arg;
+                       break;
+               case MONO_TYPE_BOOLEAN:
+               case MONO_TYPE_U1:
+                       p->regs [slot] = *(guint8*)arg;
+                       break;
+               case MONO_TYPE_I1:
+                       p->regs [slot] = *(gint8*)arg;
+                       break;
+               case MONO_TYPE_I2:
+                       p->regs [slot] = *(gint16*)arg;
+                       break;
+               case MONO_TYPE_U2:
+               case MONO_TYPE_CHAR:
+                       p->regs [slot] = *(guint16*)arg;
+                       break;
+               case MONO_TYPE_I4:
+                       p->regs [slot] = *(gint32*)arg;
+                       break;
+               case MONO_TYPE_U4:
+                       p->regs [slot] = *(guint32*)arg;
+                       break;
+               case MONO_TYPE_R4:
+                       p->fpregs [ainfo->reg] = bitcast_r4_to_r8 (*(float*)arg);
+                       p->n_fpargs ++;
+                       break;
+               case MONO_TYPE_R8:
+                       p->fpregs [ainfo->reg] = *(double*)arg;
+                       p->n_fpargs ++;
+                       break;
+               case MONO_TYPE_GENERICINST:
+                       if (MONO_TYPE_IS_REFERENCE (t)) {
+                               p->regs [slot] = (mgreg_t)*arg;
+                               break;
+                       } else {
+                               if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
+                                       MonoClass *klass = mono_class_from_mono_type (t);
+                                       guint8 *nullable_buf;
+                                       int size;
+
+                                       /*
+                                        * Use p->buffer as a temporary buffer since the data needs to be available after this call
+                                        * if the nullable param is passed by ref.
+                                        */
+                                       size = mono_class_value_size (klass, NULL);
+                                       nullable_buf = p->buffer + buffer_offset;
+                                       buffer_offset += size;
+                                       g_assert (buffer_offset <= 256);
+
+                                       /* The argument pointed to by arg is either a boxed vtype or null */
+                                       mono_nullable_init (nullable_buf, (MonoObject*)arg, klass);
+
+                                       arg = (gpointer*)nullable_buf;
+                                       /* Fall though */
+                               } else {
+                                       /* Fall though */
+                               }
+                       }
+               case MONO_TYPE_VALUETYPE:
+                       switch (ainfo->storage) {
+                       case ArgVtypeInIRegs:
+                               for (i = 0; i < ainfo->nregs; ++i)
+                                       p->regs [slot ++] = ((mgreg_t*)arg) [i];
+                               break;
+                       case ArgHFA:
+                               if (ainfo->esize == 4) {
+                                       for (i = 0; i < ainfo->nregs; ++i)
+                                               p->fpregs [ainfo->reg + i] = bitcast_r4_to_r8 (((float*)arg) [ainfo->foffsets [i] / 4]);
+                               } else {
+                                       for (i = 0; i < ainfo->nregs; ++i)
+                                               p->fpregs [ainfo->reg + i] = ((double*)arg) [ainfo->foffsets [i] / 8];
+                               }
+                               p->n_fpargs += ainfo->nregs;
+                               break;
+                       case ArgVtypeByRef:
+                               p->regs [slot] = (mgreg_t)arg;
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                               break;
+                       }
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+       }
+}
+
+void
+mono_arch_finish_dyn_call (MonoDynCallInfo *info, guint8 *buf)
+{
+       ArchDynCallInfo *ainfo = (ArchDynCallInfo*)info;
+       CallInfo *cinfo = ainfo->cinfo;
+       DynCallArgs *args = (DynCallArgs*)buf;
+       MonoType *ptype = ainfo->rtype;
+       guint8 *ret = args->ret;
+       mgreg_t res = args->res;
+       mgreg_t res2 = args->res2;
+       int i;
+
+       if (cinfo->ret.storage == ArgVtypeByRef)
+               return;
+
+       switch (ptype->type) {
+       case MONO_TYPE_VOID:
+               *(gpointer*)ret = NULL;
+               break;
+       case MONO_TYPE_STRING:
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_ARRAY:
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+       case MONO_TYPE_PTR:
+               *(gpointer*)ret = (gpointer)res;
+               break;
+       case MONO_TYPE_I1:
+               *(gint8*)ret = res;
+               break;
+       case MONO_TYPE_U1:
+       case MONO_TYPE_BOOLEAN:
+               *(guint8*)ret = res;
+               break;
+       case MONO_TYPE_I2:
+               *(gint16*)ret = res;
+               break;
+       case MONO_TYPE_U2:
+       case MONO_TYPE_CHAR:
+               *(guint16*)ret = res;
+               break;
+       case MONO_TYPE_I4:
+               *(gint32*)ret = res;
+               break;
+       case MONO_TYPE_U4:
+               *(guint32*)ret = res;
+               break;
+       case MONO_TYPE_I8:
+       case MONO_TYPE_U8:
+               *(guint64*)ret = res;
+               break;
+       case MONO_TYPE_R4:
+               *(float*)ret = bitcast_r8_to_r4 (args->fpregs [0]);
+               break;
+       case MONO_TYPE_R8:
+               *(double*)ret = args->fpregs [0];
+               break;
+       case MONO_TYPE_GENERICINST:
+               if (MONO_TYPE_IS_REFERENCE (ptype)) {
+                       *(gpointer*)ret = (gpointer)res;
+                       break;
+               } else {
+                       /* Fall though */
+               }
+       case MONO_TYPE_VALUETYPE:
+               switch (ainfo->cinfo->ret.storage) {
+               case ArgVtypeInIRegs:
+                       *(mgreg_t*)ret = res;
+                       if (ainfo->cinfo->ret.nregs > 1)
+                               ((mgreg_t*)ret) [1] = res2;
+                       break;
+               case ArgHFA:
+                       /* Use the same area for returning fp values */
+                       if (cinfo->ret.esize == 4) {
+                               for (i = 0; i < cinfo->ret.nregs; ++i)
+                                       ((float*)ret) [cinfo->ret.foffsets [i] / 4] = bitcast_r8_to_r4 (args->fpregs [i]);
+                       } else {
+                               for (i = 0; i < cinfo->ret.nregs; ++i)
+                                       ((double*)ret) [cinfo->ret.foffsets [i] / 8] = args->fpregs [i];
+                       }
+                       break;
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+               break;
+       default:
+               g_assert_not_reached ();
+       }
+}
+
+#if __APPLE__
+void sys_icache_invalidate (void *start, size_t len);
+#endif
+
+void
+mono_arch_flush_icache (guint8 *code, gint size)
+{
+#ifndef MONO_CROSS_COMPILE
+#if __APPLE__
+       sys_icache_invalidate (code, size);
+#else
+       __clear_cache (code, code + size);
+#endif
+#endif
+}
+
+#ifndef DISABLE_JIT
+
+gboolean
+mono_arch_opcode_needs_emulation (MonoCompile *cfg, int opcode)
+{
+       NOT_IMPLEMENTED;
+       return FALSE;
+}
+
+GList *
+mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
+{
+       GList *vars = NULL;
+       int i;
+
+       for (i = 0; i < cfg->num_varinfo; i++) {
+               MonoInst *ins = cfg->varinfo [i];
+               MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
+
+               /* unused vars */
+               if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
+                       continue;
+
+               if ((ins->flags & (MONO_INST_IS_DEAD|MONO_INST_VOLATILE|MONO_INST_INDIRECT)) || 
+                   (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
+                       continue;
+
+               if (mono_is_regsize_var (ins->inst_vtype)) {
+                       g_assert (MONO_VARINFO (cfg, i)->reg == -1);
+                       g_assert (i == vmv->idx);
+                       vars = g_list_prepend (vars, vmv);
+               }
+       }
+
+       vars = mono_varlist_sort (cfg, vars, 0);
+
+       return vars;
+}
+
+GList *
+mono_arch_get_global_int_regs (MonoCompile *cfg)
+{
+       GList *regs = NULL;
+       int i;
+
+       /* r28 is reserved for cfg->arch.args_reg */
+       /* r27 is reserved for the imt argument */
+       for (i = ARMREG_R19; i <= ARMREG_R26; ++i)
+               regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
+
+       return regs;
+}
+
+guint32
+mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
+{
+       MonoInst *ins = cfg->varinfo [vmv->idx];
+
+       if (ins->opcode == OP_ARG)
+               return 1;
+       else
+               return 2;
+}
+
+void
+mono_arch_create_vars (MonoCompile *cfg)
+{
+       MonoMethodSignature *sig;
+       CallInfo *cinfo;
+
+       sig = mono_method_signature (cfg->method);
+       if (!cfg->arch.cinfo)
+               cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
+       cinfo = cfg->arch.cinfo;
+
+       if (cinfo->ret.storage == ArgVtypeByRef) {
+               cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+               cfg->vret_addr->flags |= MONO_INST_VOLATILE;
+       }
+
+       if (cfg->gen_sdb_seq_points) {
+               MonoInst *ins;
+
+               if (cfg->compile_aot) {
+                       ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+                       ins->flags |= MONO_INST_VOLATILE;
+                       cfg->arch.seq_point_info_var = ins;
+               }
+
+               ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+               ins->flags |= MONO_INST_VOLATILE;
+               cfg->arch.ss_tramp_var = ins;
+
+               ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+               ins->flags |= MONO_INST_VOLATILE;
+               cfg->arch.bp_tramp_var = ins;
+       }
+
+       if (cfg->method->save_lmf) {
+               cfg->create_lmf_var = TRUE;
+               cfg->lmf_ir = TRUE;
+#ifndef TARGET_MACH
+               cfg->lmf_ir_mono_lmf = TRUE;
+#endif
+       }
+}
+
+void
+mono_arch_allocate_vars (MonoCompile *cfg)
+{
+       MonoMethodSignature *sig;
+       MonoInst *ins;
+       CallInfo *cinfo;
+       ArgInfo *ainfo;
+       int i, offset, size, align;
+       guint32 locals_stack_size, locals_stack_align;
+       gint32 *offsets;
+
+       /*
+        * Allocate arguments and locals to either register (OP_REGVAR) or to a stack slot (OP_REGOFFSET).
+        * Compute cfg->stack_offset and update cfg->used_int_regs.
+        */
+
+       sig = mono_method_signature (cfg->method);
+
+       if (!cfg->arch.cinfo)
+               cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
+       cinfo = cfg->arch.cinfo;
+
+       /*
+        * The ARM64 ABI always uses a frame pointer.
+        * The instruction set prefers positive offsets, so fp points to the bottom of the
+        * frame, and stack slots are at positive offsets.
+        * If some arguments are received on the stack, their offsets relative to fp can
+        * not be computed right now because the stack frame might grow due to spilling
+        * done by the local register allocator. To solve this, we reserve a register
+        * which points to them.
+        * The stack frame looks like this:
+        * args_reg -> <bottom of parent frame>
+        *             <locals etc>
+        *       fp -> <saved fp+lr>
+     *       sp -> <localloc/params area>
+        */
+       cfg->frame_reg = ARMREG_FP;
+       cfg->flags |= MONO_CFG_HAS_SPILLUP;
+       offset = 0;
+
+       /* Saved fp+lr */
+       offset += 16;
+
+       if (cinfo->stack_usage) {
+               g_assert (!(cfg->used_int_regs & (1 << ARMREG_R28)));
+               cfg->arch.args_reg = ARMREG_R28;
+               cfg->used_int_regs |= 1 << ARMREG_R28;
+       }
+
+       if (cfg->method->save_lmf) {
+               /* The LMF var is allocated normally */
+       } else {
+               /* Callee saved regs */
+               cfg->arch.saved_gregs_offset = offset;
+               for (i = 0; i < 32; ++i)
+                       if ((MONO_ARCH_CALLEE_SAVED_REGS & (1 << i)) && (cfg->used_int_regs & (1 << i)))
+                               offset += 8;
+       }
+
+       /* Return value */
+       switch (cinfo->ret.storage) {
+       case ArgNone:
+               break;
+       case ArgInIReg:
+       case ArgInFReg:
+       case ArgInFRegR4:
+               cfg->ret->opcode = OP_REGVAR;
+               cfg->ret->dreg = cinfo->ret.reg;
+               break;
+       case ArgVtypeInIRegs:
+       case ArgHFA:
+               /* Allocate a local to hold the result, the epilog will copy it to the correct place */
+               cfg->ret->opcode = OP_REGOFFSET;
+               cfg->ret->inst_basereg = cfg->frame_reg;
+               cfg->ret->inst_offset = offset;
+               if (cinfo->ret.storage == ArgHFA)
+                       // FIXME:
+                       offset += 64;
+               else
+                       offset += 16;
+               break;
+       case ArgVtypeByRef:
+               /* This variable will be initalized in the prolog from R8 */
+               cfg->vret_addr->opcode = OP_REGOFFSET;
+               cfg->vret_addr->inst_basereg = cfg->frame_reg;
+               cfg->vret_addr->inst_offset = offset;
+               offset += 8;
+               if (G_UNLIKELY (cfg->verbose_level > 1)) {
+                       printf ("vret_addr =");
+                       mono_print_ins (cfg->vret_addr);
+               }
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+
+       /* Arguments */
+       for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
+               ainfo = cinfo->args + i;
+
+               ins = cfg->args [i];
+               if (ins->opcode == OP_REGVAR)
+                       continue;
+
+               ins->opcode = OP_REGOFFSET;
+               ins->inst_basereg = cfg->frame_reg;
+
+               switch (ainfo->storage) {
+               case ArgInIReg:
+               case ArgInFReg:
+               case ArgInFRegR4:
+                       // FIXME: Use nregs/size
+                       /* These will be copied to the stack in the prolog */
+                       ins->inst_offset = offset;
+                       offset += 8;
+                       break;
+               case ArgOnStack:
+               case ArgOnStackR4:
+               case ArgOnStackR8:
+               case ArgVtypeOnStack:
+                       /* These are in the parent frame */
+                       g_assert (cfg->arch.args_reg);
+                       ins->inst_basereg = cfg->arch.args_reg;
+                       ins->inst_offset = ainfo->offset;
+                       break;
+               case ArgVtypeInIRegs:
+               case ArgHFA:
+                       ins->opcode = OP_REGOFFSET;
+                       ins->inst_basereg = cfg->frame_reg;
+                       /* These arguments are saved to the stack in the prolog */
+                       ins->inst_offset = offset;
+                       if (cfg->verbose_level >= 2)
+                               printf ("arg %d allocated to %s+0x%0x.\n", i, mono_arch_regname (ins->inst_basereg), (int)ins->inst_offset);
+                       if (ainfo->storage == ArgHFA)
+                               // FIXME:
+                               offset += 64;
+                       else
+                               offset += 16;
+                       break;
+               case ArgVtypeByRefOnStack: {
+                       MonoInst *vtaddr;
+
+                       if (ainfo->gsharedvt) {
+                               ins->opcode = OP_REGOFFSET;
+                               ins->inst_basereg = cfg->arch.args_reg;
+                               ins->inst_offset = ainfo->offset;
+                               break;
+                       }
+
+                       /* The vtype address is in the parent frame */
+                       g_assert (cfg->arch.args_reg);
+                       MONO_INST_NEW (cfg, vtaddr, 0);
+                       vtaddr->opcode = OP_REGOFFSET;
+                       vtaddr->inst_basereg = cfg->arch.args_reg;
+                       vtaddr->inst_offset = ainfo->offset;
+
+                       /* Need an indirection */
+                       ins->opcode = OP_VTARG_ADDR;
+                       ins->inst_left = vtaddr;
+                       break;
+               }
+               case ArgVtypeByRef: {
+                       MonoInst *vtaddr;
+
+                       if (ainfo->gsharedvt) {
+                               ins->opcode = OP_REGOFFSET;
+                               ins->inst_basereg = cfg->frame_reg;
+                               ins->inst_offset = offset;
+                               offset += 8;
+                               break;
+                       }
+
+                       /* The vtype address is in a register, will be copied to the stack in the prolog */
+                       MONO_INST_NEW (cfg, vtaddr, 0);
+                       vtaddr->opcode = OP_REGOFFSET;
+                       vtaddr->inst_basereg = cfg->frame_reg;
+                       vtaddr->inst_offset = offset;
+                       offset += 8;
+
+                       /* Need an indirection */
+                       ins->opcode = OP_VTARG_ADDR;
+                       ins->inst_left = vtaddr;
+                       break;
+               }
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+       }
+
+       /* Allocate these first so they have a small offset, OP_SEQ_POINT depends on this */
+       // FIXME: Allocate these to registers
+       ins = cfg->arch.seq_point_info_var;
+       if (ins) {
+               size = 8;
+               align = 8;
+               offset += align - 1;
+               offset &= ~(align - 1);
+               ins->opcode = OP_REGOFFSET;
+               ins->inst_basereg = cfg->frame_reg;
+               ins->inst_offset = offset;
+               offset += size;
+       }
+       ins = cfg->arch.ss_tramp_var;
+       if (ins) {
+               size = 8;
+               align = 8;
+               offset += align - 1;
+               offset &= ~(align - 1);
+               ins->opcode = OP_REGOFFSET;
+               ins->inst_basereg = cfg->frame_reg;
+               ins->inst_offset = offset;
+               offset += size;
+       }
+       ins = cfg->arch.bp_tramp_var;
+       if (ins) {
+               size = 8;
+               align = 8;
+               offset += align - 1;
+               offset &= ~(align - 1);
+               ins->opcode = OP_REGOFFSET;
+               ins->inst_basereg = cfg->frame_reg;
+               ins->inst_offset = offset;
+               offset += size;
+       }
+
+       /* Locals */
+       offsets = mono_allocate_stack_slots (cfg, FALSE, &locals_stack_size, &locals_stack_align);
+       if (locals_stack_align)
+               offset = ALIGN_TO (offset, locals_stack_align);
+
+       for (i = cfg->locals_start; i < cfg->num_varinfo; i++) {
+               if (offsets [i] != -1) {
+                       ins = cfg->varinfo [i];
+                       ins->opcode = OP_REGOFFSET;
+                       ins->inst_basereg = cfg->frame_reg;
+                       ins->inst_offset = offset + offsets [i];
+                       //printf ("allocated local %d to ", i); mono_print_tree_nl (ins);
+               }
+       }
+       offset += locals_stack_size;
+
+       offset = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
+
+       cfg->stack_offset = offset;
+}
+
+#ifdef ENABLE_LLVM
+LLVMCallInfo*
+mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
+{
+       int i, n;
+       CallInfo *cinfo;
+       ArgInfo *ainfo;
+       LLVMCallInfo *linfo;
+
+       n = sig->param_count + sig->hasthis;
+
+       cinfo = get_call_info (cfg->mempool, sig);
+
+       linfo = mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMCallInfo) + (sizeof (LLVMArgInfo) * n));
+
+       switch (cinfo->ret.storage) {
+       case ArgInIReg:
+       case ArgInFReg:
+       case ArgInFRegR4:
+       case ArgNone:
+               break;
+       case ArgVtypeByRef:
+               linfo->ret.storage = LLVMArgVtypeByRef;
+               break;
+               //
+               // FIXME: This doesn't work yet since the llvm backend represents these types as an i8
+               // array which is returned in int regs
+               //
+       case ArgHFA:
+               linfo->ret.storage = LLVMArgFpStruct;
+               linfo->ret.nslots = cinfo->ret.nregs;
+               linfo->ret.esize = cinfo->ret.esize;
+               break;
+       case ArgVtypeInIRegs:
+               /* LLVM models this by returning an int */
+               linfo->ret.storage = LLVMArgVtypeAsScalar;
+               linfo->ret.nslots = cinfo->ret.nregs;
+               linfo->ret.esize = cinfo->ret.esize;
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+
+       for (i = 0; i < n; ++i) {
+               LLVMArgInfo *lainfo = &linfo->args [i];
+
+               ainfo = cinfo->args + i;
+
+               lainfo->storage = LLVMArgNone;
+
+               switch (ainfo->storage) {
+               case ArgInIReg:
+               case ArgInFReg:
+               case ArgInFRegR4:
+               case ArgOnStack:
+               case ArgOnStackR4:
+               case ArgOnStackR8:
+                       lainfo->storage = LLVMArgNormal;
+                       break;
+               case ArgVtypeByRef:
+               case ArgVtypeByRefOnStack:
+                       lainfo->storage = LLVMArgVtypeByRef;
+                       break;
+               case ArgHFA: {
+                       int j;
+
+                       lainfo->storage = LLVMArgAsFpArgs;
+                       lainfo->nslots = ainfo->nregs;
+                       lainfo->esize = ainfo->esize;
+                       for (j = 0; j < ainfo->nregs; ++j)
+                               lainfo->pair_storage [j] = LLVMArgInFPReg;
+                       break;
+               }
+               case ArgVtypeInIRegs:
+                       lainfo->storage = LLVMArgAsIArgs;
+                       lainfo->nslots = ainfo->nregs;
+                       break;
+               case ArgVtypeOnStack:
+                       if (ainfo->hfa) {
+                               int j;
+                               /* Same as above */
+                               lainfo->storage = LLVMArgAsFpArgs;
+                               lainfo->nslots = ainfo->nregs;
+                               lainfo->esize = ainfo->esize;
+                               lainfo->ndummy_fpargs = ainfo->nfregs_to_skip;
+                               for (j = 0; j < ainfo->nregs; ++j)
+                                       lainfo->pair_storage [j] = LLVMArgInFPReg;
+                       } else {
+                               lainfo->storage = LLVMArgAsIArgs;
+                               lainfo->nslots = ainfo->size / 8;
+                       }
+                       break;
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+       }
+
+       return linfo;
+}
+#endif
+
+static void
+add_outarg_reg (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *arg)
+{
+       MonoInst *ins;
+
+       switch (storage) {
+       case ArgInIReg:
+               MONO_INST_NEW (cfg, ins, OP_MOVE);
+               ins->dreg = mono_alloc_ireg_copy (cfg, arg->dreg);
+               ins->sreg1 = arg->dreg;
+               MONO_ADD_INS (cfg->cbb, ins);
+               mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
+               break;
+       case ArgInFReg:
+               MONO_INST_NEW (cfg, ins, OP_FMOVE);
+               ins->dreg = mono_alloc_freg (cfg);
+               ins->sreg1 = arg->dreg;
+               MONO_ADD_INS (cfg->cbb, ins);
+               mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
+               break;
+       case ArgInFRegR4:
+               if (COMPILE_LLVM (cfg))
+                       MONO_INST_NEW (cfg, ins, OP_FMOVE);
+               else if (cfg->r4fp)
+                       MONO_INST_NEW (cfg, ins, OP_RMOVE);
+               else
+                       MONO_INST_NEW (cfg, ins, OP_ARM_SETFREG_R4);
+               ins->dreg = mono_alloc_freg (cfg);
+               ins->sreg1 = arg->dreg;
+               MONO_ADD_INS (cfg->cbb, ins);
+               mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+}
+
+static void
+emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
+{
+       MonoMethodSignature *tmp_sig;
+       int sig_reg;
+
+       if (call->tail_call)
+               NOT_IMPLEMENTED;
+
+       g_assert (cinfo->sig_cookie.storage == ArgOnStack);
+                       
+       /*
+        * mono_ArgIterator_Setup assumes the signature cookie is 
+        * passed first and all the arguments which were before it are
+        * passed on the stack after the signature. So compensate by 
+        * passing a different signature.
+        */
+       tmp_sig = mono_metadata_signature_dup (call->signature);
+       tmp_sig->param_count -= call->signature->sentinelpos;
+       tmp_sig->sentinelpos = 0;
+       memcpy (tmp_sig->params, call->signature->params + call->signature->sentinelpos, tmp_sig->param_count * sizeof (MonoType*));
+
+       sig_reg = mono_alloc_ireg (cfg);
+       MONO_EMIT_NEW_SIGNATURECONST (cfg, sig_reg, tmp_sig);
+
+       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ARMREG_SP, cinfo->sig_cookie.offset, sig_reg);
+}
+
+void
+mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
+{
+       MonoMethodSignature *sig;
+       MonoInst *arg, *vtarg;
+       CallInfo *cinfo;
+       ArgInfo *ainfo;
+       int i;
+
+       sig = call->signature;
+
+       cinfo = get_call_info (cfg->mempool, sig);
+
+       switch (cinfo->ret.storage) {
+       case ArgVtypeInIRegs:
+       case ArgHFA:
+               /*
+                * The vtype is returned in registers, save the return area address in a local, and save the vtype into
+                * the location pointed to by it after call in emit_move_return_value ().
+                */
+               if (!cfg->arch.vret_addr_loc) {
+                       cfg->arch.vret_addr_loc = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+                       /* Prevent it from being register allocated or optimized away */
+                       ((MonoInst*)cfg->arch.vret_addr_loc)->flags |= MONO_INST_VOLATILE;
+               }
+
+               MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ((MonoInst*)cfg->arch.vret_addr_loc)->dreg, call->vret_var->dreg);
+               break;
+       case ArgVtypeByRef:
+               /* Pass the vtype return address in R8 */
+               MONO_INST_NEW (cfg, vtarg, OP_MOVE);
+               vtarg->sreg1 = call->vret_var->dreg;
+               vtarg->dreg = mono_alloc_preg (cfg);
+               MONO_ADD_INS (cfg->cbb, vtarg);
+
+               mono_call_inst_add_outarg_reg (cfg, call, vtarg->dreg, cinfo->ret.reg, FALSE);
+               break;
+       default:
+               break;
+       }
+
+       for (i = 0; i < cinfo->nargs; ++i) {
+               ainfo = cinfo->args + i;
+               arg = call->args [i];
+
+               if ((sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
+                       /* Emit the signature cookie just before the implicit arguments */
+                       emit_sig_cookie (cfg, call, cinfo);
+               }
+
+               switch (ainfo->storage) {
+               case ArgInIReg:
+               case ArgInFReg:
+               case ArgInFRegR4:
+                       add_outarg_reg (cfg, call, ainfo->storage, ainfo->reg, arg);
+                       break;
+               case ArgOnStack:
+                       switch (ainfo->slot_size) {
+                       case 8:
+                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ARMREG_SP, ainfo->offset, arg->dreg);
+                               break;
+                       case 4:
+                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, ARMREG_SP, ainfo->offset, arg->dreg);
+                               break;
+                       case 2:
+                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, ARMREG_SP, ainfo->offset, arg->dreg);
+                               break;
+                       case 1:
+                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, ARMREG_SP, ainfo->offset, arg->dreg);
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                               break;
+                       }
+                       break;
+               case ArgOnStackR8:
+                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, ARMREG_SP, ainfo->offset, arg->dreg);
+                       break;
+               case ArgOnStackR4:
+                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, ARMREG_SP, ainfo->offset, arg->dreg);
+                       break;
+               case ArgVtypeInIRegs:
+               case ArgVtypeByRef:
+               case ArgVtypeByRefOnStack:
+               case ArgVtypeOnStack:
+               case ArgHFA: {
+                       MonoInst *ins;
+                       guint32 align;
+                       guint32 size;
+
+                       size = mono_class_value_size (arg->klass, &align);
+
+                       MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
+                       ins->sreg1 = arg->dreg;
+                       ins->klass = arg->klass;
+                       ins->backend.size = size;
+                       ins->inst_p0 = call;
+                       ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
+                       memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
+                       MONO_ADD_INS (cfg->cbb, ins);
+                       break;
+               }
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+       }
+
+       /* Handle the case where there are no implicit arguments */
+       if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (cinfo->nargs == sig->sentinelpos))
+               emit_sig_cookie (cfg, call, cinfo);
+
+       call->call_info = cinfo;
+       call->stack_usage = cinfo->stack_usage;
+}
+
+void
+mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
+{
+       MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
+       ArgInfo *ainfo = ins->inst_p1;
+       MonoInst *load;
+       int i;
+
+       if (ins->backend.size == 0 && !ainfo->gsharedvt)
+               return;
+
+       switch (ainfo->storage) {
+       case ArgVtypeInIRegs:
+               for (i = 0; i < ainfo->nregs; ++i) {
+                       // FIXME: Smaller sizes
+                       MONO_INST_NEW (cfg, load, OP_LOADI8_MEMBASE);
+                       load->dreg = mono_alloc_ireg (cfg);
+                       load->inst_basereg = src->dreg;
+                       load->inst_offset = i * sizeof(mgreg_t);
+                       MONO_ADD_INS (cfg->cbb, load);
+                       add_outarg_reg (cfg, call, ArgInIReg, ainfo->reg + i, load);
+               }
+               break;
+       case ArgHFA:
+               for (i = 0; i < ainfo->nregs; ++i) {
+                       if (ainfo->esize == 4)
+                               MONO_INST_NEW (cfg, load, OP_LOADR4_MEMBASE);
+                       else
+                               MONO_INST_NEW (cfg, load, OP_LOADR8_MEMBASE);
+                       load->dreg = mono_alloc_freg (cfg);
+                       load->inst_basereg = src->dreg;
+                       load->inst_offset = ainfo->foffsets [i];
+                       MONO_ADD_INS (cfg->cbb, load);
+                       add_outarg_reg (cfg, call, ainfo->esize == 4 ? ArgInFRegR4 : ArgInFReg, ainfo->reg + i, load);
+               }
+               break;
+       case ArgVtypeByRef:
+       case ArgVtypeByRefOnStack: {
+               MonoInst *vtaddr, *load, *arg;
+
+               /* Pass the vtype address in a reg/on the stack */
+               if (ainfo->gsharedvt) {
+                       load = src;
+               } else {
+                       /* Make a copy of the argument */
+                       vtaddr = mono_compile_create_var (cfg, &ins->klass->byval_arg, OP_LOCAL);
+
+                       MONO_INST_NEW (cfg, load, OP_LDADDR);
+                       load->inst_p0 = vtaddr;
+                       vtaddr->flags |= MONO_INST_INDIRECT;
+                       load->type = STACK_MP;
+                       load->klass = vtaddr->klass;
+                       load->dreg = mono_alloc_ireg (cfg);
+                       MONO_ADD_INS (cfg->cbb, load);
+                       mini_emit_memcpy (cfg, load->dreg, 0, src->dreg, 0, ainfo->size, 8);
+               }
+
+               if (ainfo->storage == ArgVtypeByRef) {
+                       MONO_INST_NEW (cfg, arg, OP_MOVE);
+                       arg->dreg = mono_alloc_preg (cfg);
+                       arg->sreg1 = load->dreg;
+                       MONO_ADD_INS (cfg->cbb, arg);
+                       add_outarg_reg (cfg, call, ArgInIReg, ainfo->reg, arg);
+               } else {
+                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ARMREG_SP, ainfo->offset, load->dreg);
+               }
+               break;
+       }
+       case ArgVtypeOnStack:
+               for (i = 0; i < ainfo->size / 8; ++i) {
+                       MONO_INST_NEW (cfg, load, OP_LOADI8_MEMBASE);
+                       load->dreg = mono_alloc_ireg (cfg);
+                       load->inst_basereg = src->dreg;
+                       load->inst_offset = i * 8;
+                       MONO_ADD_INS (cfg->cbb, load);
+                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, ARMREG_SP, ainfo->offset + (i * 8), load->dreg);
+               }
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+}
+
+void
+mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
+{
+       MonoMethodSignature *sig;
+       CallInfo *cinfo;
+
+       sig = mono_method_signature (cfg->method);
+       if (!cfg->arch.cinfo)
+               cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
+       cinfo = cfg->arch.cinfo;
+
+       switch (cinfo->ret.storage) {
+       case ArgNone:
+               break;
+       case ArgInIReg:
+               MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
+               break;
+       case ArgInFReg:
+               MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
+               break;
+       case ArgInFRegR4:
+               if (COMPILE_LLVM (cfg))
+                       MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
+               else if (cfg->r4fp)
+                       MONO_EMIT_NEW_UNALU (cfg, OP_RMOVE, cfg->ret->dreg, val->dreg);
+               else
+                       MONO_EMIT_NEW_UNALU (cfg, OP_ARM_SETFREG_R4, cfg->ret->dreg, val->dreg);
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+}
+
+gboolean
+mono_arch_tail_call_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig)
+{
+       CallInfo *c1, *c2;
+       gboolean res;
+
+       if (cfg->compile_aot && !cfg->full_aot)
+               /* OP_TAILCALL doesn't work with AOT */
+               return FALSE;
+
+       c1 = get_call_info (NULL, caller_sig);
+       c2 = get_call_info (NULL, callee_sig);
+       res = TRUE;
+       // FIXME: Relax these restrictions
+       if (c1->stack_usage != 0)
+               res = FALSE;
+       if (c1->stack_usage != c2->stack_usage)
+               res = FALSE;
+       if ((c1->ret.storage != ArgNone && c1->ret.storage != ArgInIReg) || c1->ret.storage != c2->ret.storage)
+               res = FALSE;
+
+       g_free (c1);
+       g_free (c2);
+
+       return res;
+}
+
+gboolean 
+mono_arch_is_inst_imm (gint64 imm)
+{
+       return (imm >= -((gint64)1<<31) && imm <= (((gint64)1<<31)-1));
+}
+
+void*
+mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments)
+{
+       NOT_IMPLEMENTED;
+       return NULL;
+}
+
+void*
+mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
+{
+       NOT_IMPLEMENTED;
+       return NULL;
+}
+
+void
+mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+       //NOT_IMPLEMENTED;
+}
+
+void
+mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+       //NOT_IMPLEMENTED;
+}
+
+#define ADD_NEW_INS(cfg,dest,op) do {       \
+               MONO_INST_NEW ((cfg), (dest), (op)); \
+        mono_bblock_insert_before_ins (bb, ins, (dest)); \
+       } while (0)
+
+void
+mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+       MonoInst *ins, *temp, *last_ins = NULL;
+
+       MONO_BB_FOR_EACH_INS (bb, ins) {
+               switch (ins->opcode) {
+               case OP_SBB:
+               case OP_ISBB:
+               case OP_SUBCC:
+               case OP_ISUBCC:
+                       if (ins->next  && (ins->next->opcode == OP_COND_EXC_C || ins->next->opcode == OP_COND_EXC_IC))
+                               /* ARM sets the C flag to 1 if there was _no_ overflow */
+                               ins->next->opcode = OP_COND_EXC_NC;
+                       break;
+               case OP_IDIV_IMM:
+               case OP_IREM_IMM:
+               case OP_IDIV_UN_IMM:
+               case OP_IREM_UN_IMM:
+               case OP_LREM_IMM:
+                       mono_decompose_op_imm (cfg, bb, ins);
+                       break;
+               case OP_LOCALLOC_IMM:
+                       if (ins->inst_imm > 32) {
+                               ADD_NEW_INS (cfg, temp, OP_ICONST);
+                               temp->inst_c0 = ins->inst_imm;
+                               temp->dreg = mono_alloc_ireg (cfg);
+                               ins->sreg1 = temp->dreg;
+                               ins->opcode = mono_op_imm_to_op (ins->opcode);
+                       }
+                       break;
+               case OP_ICOMPARE_IMM:
+                       if (ins->inst_imm == 0 && ins->next && ins->next->opcode == OP_IBEQ) {
+                               ins->next->opcode = OP_ARM64_CBZW;
+                               ins->next->sreg1 = ins->sreg1;
+                               NULLIFY_INS (ins);
+                       } else if (ins->inst_imm == 0 && ins->next && ins->next->opcode == OP_IBNE_UN) {
+                               ins->next->opcode = OP_ARM64_CBNZW;
+                               ins->next->sreg1 = ins->sreg1;
+                               NULLIFY_INS (ins);
+                       }
+                       break;
+               case OP_LCOMPARE_IMM:
+               case OP_COMPARE_IMM:
+                       if (ins->inst_imm == 0 && ins->next && ins->next->opcode == OP_LBEQ) {
+                               ins->next->opcode = OP_ARM64_CBZX;
+                               ins->next->sreg1 = ins->sreg1;
+                               NULLIFY_INS (ins);
+                       } else if (ins->inst_imm == 0 && ins->next && ins->next->opcode == OP_LBNE_UN) {
+                               ins->next->opcode = OP_ARM64_CBNZX;
+                               ins->next->sreg1 = ins->sreg1;
+                               NULLIFY_INS (ins);
+                       }
+                       break;
+               case OP_FCOMPARE: {
+                       gboolean swap = FALSE;
+                       int reg;
+
+                       if (!ins->next) {
+                               /* Optimized away */
+                               NULLIFY_INS (ins);
+                               break;
+                       }
+
+                       /*
+                        * FP compares with unordered operands set the flags
+                        * to NZCV=0011, which matches some non-unordered compares
+                        * as well, like LE, so have to swap the operands.
+                        */
+                       switch (ins->next->opcode) {
+                       case OP_FBLT:
+                               ins->next->opcode = OP_FBGT;
+                               swap = TRUE;
+                               break;
+                       case OP_FBLE:
+                               ins->next->opcode = OP_FBGE;
+                               swap = TRUE;
+                               break;
+                       default:
+                               break;
+                       }
+                       if (swap) {
+                               reg = ins->sreg1;
+                               ins->sreg1 = ins->sreg2;
+                               ins->sreg2 = reg;
+                       }
+                       break;
+               }
+               default:
+                       break;
+               }
+
+               last_ins = ins;
+       }
+       bb->last_ins = last_ins;
+       bb->max_vreg = cfg->next_vreg;
+}
+
+void
+mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins)
+{
+}
+
+static int
+opcode_to_armcond (int opcode)
+{
+       switch (opcode) {
+       case OP_IBEQ:
+       case OP_LBEQ:
+       case OP_FBEQ:
+       case OP_CEQ:
+       case OP_ICEQ:
+       case OP_LCEQ:
+       case OP_FCEQ:
+       case OP_RCEQ:
+       case OP_COND_EXC_IEQ:
+       case OP_COND_EXC_EQ:
+               return ARMCOND_EQ;
+       case OP_IBGE:
+       case OP_LBGE:
+       case OP_FBGE:
+       case OP_ICGE:
+       case OP_FCGE:
+       case OP_RCGE:
+               return ARMCOND_GE;
+       case OP_IBGT:
+       case OP_LBGT:
+       case OP_FBGT:
+       case OP_CGT:
+       case OP_ICGT:
+       case OP_LCGT:
+       case OP_FCGT:
+       case OP_RCGT:
+       case OP_COND_EXC_IGT:
+       case OP_COND_EXC_GT:
+               return ARMCOND_GT;
+       case OP_IBLE:
+       case OP_LBLE:
+       case OP_FBLE:
+       case OP_ICLE:
+       case OP_FCLE:
+       case OP_RCLE:
+               return ARMCOND_LE;
+       case OP_IBLT:
+       case OP_LBLT:
+       case OP_FBLT:
+       case OP_CLT:
+       case OP_ICLT:
+       case OP_LCLT:
+       case OP_COND_EXC_ILT:
+       case OP_COND_EXC_LT:
+               return ARMCOND_LT;
+       case OP_IBNE_UN:
+       case OP_LBNE_UN:
+       case OP_FBNE_UN:
+       case OP_ICNEQ:
+       case OP_FCNEQ:
+       case OP_RCNEQ:
+       case OP_COND_EXC_INE_UN:
+       case OP_COND_EXC_NE_UN:
+               return ARMCOND_NE;
+       case OP_IBGE_UN:
+       case OP_LBGE_UN:
+       case OP_FBGE_UN:
+       case OP_ICGE_UN:
+       case OP_COND_EXC_IGE_UN:
+       case OP_COND_EXC_GE_UN:
+               return ARMCOND_HS;
+       case OP_IBGT_UN:
+       case OP_LBGT_UN:
+       case OP_FBGT_UN:
+       case OP_CGT_UN:
+       case OP_ICGT_UN:
+       case OP_LCGT_UN:
+       case OP_FCGT_UN:
+       case OP_RCGT_UN:
+       case OP_COND_EXC_IGT_UN:
+       case OP_COND_EXC_GT_UN:
+               return ARMCOND_HI;
+       case OP_IBLE_UN:
+       case OP_LBLE_UN:
+       case OP_FBLE_UN:
+       case OP_ICLE_UN:
+       case OP_COND_EXC_ILE_UN:
+       case OP_COND_EXC_LE_UN:
+               return ARMCOND_LS;
+       case OP_IBLT_UN:
+       case OP_LBLT_UN:
+       case OP_FBLT_UN:
+       case OP_CLT_UN:
+       case OP_ICLT_UN:
+       case OP_LCLT_UN:
+       case OP_COND_EXC_ILT_UN:
+       case OP_COND_EXC_LT_UN:
+               return ARMCOND_LO;
+               /*
+                * FCMP sets the NZCV condition bits as follows:
+                * eq = 0110
+                * < = 1000
+                * > = 0010
+                * unordered = 0011
+                * ARMCOND_LT is N!=V, so it matches unordered too, so
+                * fclt and fclt_un need to be special cased.
+                */
+       case OP_FCLT:
+       case OP_RCLT:
+               /* N==1 */
+               return ARMCOND_MI;
+       case OP_FCLT_UN:
+       case OP_RCLT_UN:
+               return ARMCOND_LT;
+       case OP_COND_EXC_C:
+       case OP_COND_EXC_IC:
+               return ARMCOND_CS;
+       case OP_COND_EXC_OV:
+       case OP_COND_EXC_IOV:
+               return ARMCOND_VS;
+       case OP_COND_EXC_NC:
+       case OP_COND_EXC_INC:
+               return ARMCOND_CC;
+       case OP_COND_EXC_NO:
+       case OP_COND_EXC_INO:
+               return ARMCOND_VC;
+       default:
+               printf ("%s\n", mono_inst_name (opcode));
+               g_assert_not_reached ();
+               return -1;
+       }
+}
+
+/* This clobbers LR */
+static inline __attribute__((warn_unused_result)) guint8*
+emit_cond_exc (MonoCompile *cfg, guint8 *code, int opcode, const char *exc_name)
+{
+       int cond;
+
+       cond = opcode_to_armcond (opcode);
+       /* Capture PC */
+       arm_adrx (code, ARMREG_IP1, code);
+       mono_add_patch_info_rel (cfg, code - cfg->native_code, MONO_PATCH_INFO_EXC, exc_name, MONO_R_ARM64_BCC);
+       arm_bcc (code, cond, 0);
+       return code;
+}
+
+static guint8*
+emit_move_return_value (MonoCompile *cfg, guint8 * code, MonoInst *ins)
+{
+       CallInfo *cinfo;
+       MonoCallInst *call;
+
+       call = (MonoCallInst*)ins;
+       cinfo = call->call_info;
+       g_assert (cinfo);
+       switch (cinfo->ret.storage) {
+       case ArgNone:
+               break;
+       case ArgInIReg:
+               /* LLVM compiled code might only set the bottom bits */
+               if (call->signature && mini_get_underlying_type (call->signature->ret)->type == MONO_TYPE_I4)
+                       arm_sxtwx (code, call->inst.dreg, cinfo->ret.reg);
+               else if (call->inst.dreg != cinfo->ret.reg)
+                       arm_movx (code, call->inst.dreg, cinfo->ret.reg);
+               break;
+       case ArgInFReg:
+               if (call->inst.dreg != cinfo->ret.reg)
+                       arm_fmovd (code, call->inst.dreg, cinfo->ret.reg);
+               break;
+       case ArgInFRegR4:
+               if (cfg->r4fp)
+                       arm_fmovs (code, call->inst.dreg, cinfo->ret.reg);
+               else
+                       arm_fcvt_sd (code, call->inst.dreg, cinfo->ret.reg);
+               break;
+       case ArgVtypeInIRegs: {
+               MonoInst *loc = cfg->arch.vret_addr_loc;
+               int i;
+
+               /* Load the destination address */
+               g_assert (loc && loc->opcode == OP_REGOFFSET);
+               code = emit_ldrx (code, ARMREG_LR, loc->inst_basereg, loc->inst_offset);
+               for (i = 0; i < cinfo->ret.nregs; ++i)
+                       arm_strx (code, cinfo->ret.reg + i, ARMREG_LR, i * 8);
+               break;
+       }
+       case ArgHFA: {
+               MonoInst *loc = cfg->arch.vret_addr_loc;
+               int i;
+
+               /* Load the destination address */
+               g_assert (loc && loc->opcode == OP_REGOFFSET);
+               code = emit_ldrx (code, ARMREG_LR, loc->inst_basereg, loc->inst_offset);
+               for (i = 0; i < cinfo->ret.nregs; ++i) {
+                       if (cinfo->ret.esize == 4)
+                               arm_strfpw (code, cinfo->ret.reg + i, ARMREG_LR, cinfo->ret.foffsets [i]);
+                       else
+                               arm_strfpx (code, cinfo->ret.reg + i, ARMREG_LR, cinfo->ret.foffsets [i]);
+               }
+               break;
+       }
+       case ArgVtypeByRef:
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+       return code;
+}
+
+/*
+ * emit_branch_island:
+ *
+ *   Emit a branch island for the conditional branches from cfg->native_code + start_offset to code.
+ */
+static guint8*
+emit_branch_island (MonoCompile *cfg, guint8 *code, int start_offset)
+{
+       MonoJumpInfo *ji;
+       int offset, island_size;
+
+       /* Iterate over the patch infos added so far by this bb */
+       island_size = 0;
+       for (ji = cfg->patch_info; ji; ji = ji->next) {
+               if (ji->ip.i < start_offset)
+                       /* The patch infos are in reverse order, so this means the end */
+                       break;
+               if (ji->relocation == MONO_R_ARM64_BCC || ji->relocation == MONO_R_ARM64_CBZ)
+                       island_size += 4;
+       }
+
+       if (island_size) {
+               offset = code - cfg->native_code;
+               if (offset > (cfg->code_size - island_size - 16)) {
+                       cfg->code_size *= 2;
+                       cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
+                       code = cfg->native_code + offset;
+               }
+
+               /* Branch over the island */
+               arm_b (code, code + 4 + island_size);
+
+               for (ji = cfg->patch_info; ji; ji = ji->next) {
+                       if (ji->ip.i < start_offset)
+                               break;
+                       if (ji->relocation == MONO_R_ARM64_BCC || ji->relocation == MONO_R_ARM64_CBZ) {
+                               /* Rewrite the cond branch so it branches to an uncoditional branch in the branch island */
+                               arm_patch_rel (cfg->native_code + ji->ip.i, code, ji->relocation);
+                               /* Rewrite the patch so it points to the unconditional branch */
+                               ji->ip.i = code - cfg->native_code;
+                               ji->relocation = MONO_R_ARM64_B;
+                               arm_b (code, code);
+                       }
+               }
+       }
+       return code;
+}
+
+void
+mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+       MonoInst *ins;
+       MonoCallInst *call;
+       guint offset;
+       guint8 *code = cfg->native_code + cfg->code_len;
+       int start_offset, max_len, dreg, sreg1, sreg2;
+       mgreg_t imm;
+
+       if (cfg->verbose_level > 2)
+               g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
+
+       start_offset = code - cfg->native_code;
+
+       MONO_BB_FOR_EACH_INS (bb, ins) {
+               offset = code - cfg->native_code;
+
+               max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
+
+               if (offset > (cfg->code_size - max_len - 16)) {
+                       cfg->code_size *= 2;
+                       cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
+                       code = cfg->native_code + offset;
+               }
+
+               if (G_UNLIKELY (cfg->arch.cond_branch_islands && offset - start_offset > 4 * 0x1ffff)) {
+                       /* Emit a branch island for large basic blocks */
+                       code = emit_branch_island (cfg, code, start_offset);
+                       offset = code - cfg->native_code;
+                       start_offset = offset;
+               }
+
+               mono_debug_record_line_number (cfg, ins, offset);
+
+               dreg = ins->dreg;
+               sreg1 = ins->sreg1;
+               sreg2 = ins->sreg2;
+               imm = ins->inst_imm;
+
+               switch (ins->opcode) {
+               case OP_ICONST:
+                       code = emit_imm (code, dreg, ins->inst_c0);
+                       break;
+               case OP_I8CONST:
+                       code = emit_imm64 (code, dreg, ins->inst_c0);
+                       break;
+               case OP_MOVE:
+                       if (dreg != sreg1)
+                               arm_movx (code, dreg, sreg1);
+                       break;
+               case OP_NOP:
+               case OP_RELAXED_NOP:
+                       break;
+               case OP_JUMP_TABLE:
+                       mono_add_patch_info_rel (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0, MONO_R_ARM64_IMM);
+                       code = emit_imm64_template (code, dreg);
+                       break;
+               case OP_BREAK:
+                       /*
+                        * gdb does not like encountering the hw breakpoint ins in the debugged code. 
+                        * So instead of emitting a trap, we emit a call a C function and place a 
+                        * breakpoint there.
+                        */
+                       code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_break");
+                       break;
+               case OP_LOCALLOC: {
+                       guint8 *buf [16];
+
+                       arm_addx_imm (code, ARMREG_IP0, sreg1, (MONO_ARCH_FRAME_ALIGNMENT - 1));
+                       // FIXME: andx_imm doesn't work yet
+                       code = emit_imm (code, ARMREG_IP1, -MONO_ARCH_FRAME_ALIGNMENT);
+                       arm_andx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
+                       //arm_andx_imm (code, ARMREG_IP0, sreg1, - MONO_ARCH_FRAME_ALIGNMENT);
+                       arm_movspx (code, ARMREG_IP1, ARMREG_SP);
+                       arm_subx (code, ARMREG_IP1, ARMREG_IP1, ARMREG_IP0);
+                       arm_movspx (code, ARMREG_SP, ARMREG_IP1);
+
+                       /* Init */
+                       /* ip1 = pointer, ip0 = end */
+                       arm_addx (code, ARMREG_IP0, ARMREG_IP1, ARMREG_IP0);
+                       buf [0] = code;
+                       arm_cmpx (code, ARMREG_IP1, ARMREG_IP0);
+                       buf [1] = code;
+                       arm_bcc (code, ARMCOND_EQ, 0);
+                       arm_stpx (code, ARMREG_RZR, ARMREG_RZR, ARMREG_IP1, 0);
+                       arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 16);
+                       arm_b (code, buf [0]);
+                       arm_patch_rel (buf [1], code, MONO_R_ARM64_BCC);
+
+                       arm_movspx (code, dreg, ARMREG_SP);
+                       if (cfg->param_area)
+                               code = emit_subx_sp_imm (code, cfg->param_area);
+                       break;
+               }
+               case OP_LOCALLOC_IMM: {
+                       int imm, offset;
+
+                       imm = ALIGN_TO (ins->inst_imm, MONO_ARCH_FRAME_ALIGNMENT);
+                       g_assert (arm_is_arith_imm (imm));
+                       arm_subx_imm (code, ARMREG_SP, ARMREG_SP, imm);
+
+                       /* Init */
+                       g_assert (MONO_ARCH_FRAME_ALIGNMENT == 16);
+                       offset = 0;
+                       while (offset < imm) {
+                               arm_stpx (code, ARMREG_RZR, ARMREG_RZR, ARMREG_SP, offset);
+                               offset += 16;
+                       }
+                       arm_movspx (code, dreg, ARMREG_SP);
+                       if (cfg->param_area)
+                               code = emit_subx_sp_imm (code, cfg->param_area);
+                       break;
+               }
+               case OP_AOTCONST:
+                       code = emit_aotconst (cfg, code, dreg, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
+                       break;
+               case OP_OBJC_GET_SELECTOR:
+                       mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_OBJC_SELECTOR_REF, ins->inst_p0);
+                       /* See arch_emit_objc_selector_ref () in aot-compiler.c */
+                       arm_ldrx_lit (code, ins->dreg, 0);
+                       arm_nop (code);
+                       arm_nop (code);
+                       break;
+               case OP_SEQ_POINT: {
+                       MonoInst *info_var = cfg->arch.seq_point_info_var;
+
+                       /*
+                        * For AOT, we use one got slot per method, which will point to a
+                        * SeqPointInfo structure, containing all the information required
+                        * by the code below.
+                        */
+                       if (cfg->compile_aot) {
+                               g_assert (info_var);
+                               g_assert (info_var->opcode == OP_REGOFFSET);
+                       }
+
+                       if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
+                               MonoInst *var = cfg->arch.ss_tramp_var;
+
+                               g_assert (var);
+                               g_assert (var->opcode == OP_REGOFFSET);
+                               /* Load ss_tramp_var */
+                               /* This is equal to &ss_trampoline */
+                               arm_ldrx (code, ARMREG_IP1, var->inst_basereg, var->inst_offset);
+                               /* Load the trampoline address */
+                               arm_ldrx (code, ARMREG_IP1, ARMREG_IP1, 0);
+                               /* Call it if it is non-null */
+                               arm_cbzx (code, ARMREG_IP1, code + 8);
+                               arm_blrx (code, ARMREG_IP1);
+                       }
+
+                       mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
+
+                       if (cfg->compile_aot) {
+                               guint32 offset = code - cfg->native_code;
+                               guint32 val;
+
+                               arm_ldrx (code, ARMREG_IP1, info_var->inst_basereg, info_var->inst_offset);
+                               /* Add the offset */
+                               val = ((offset / 4) * sizeof (guint8*)) + MONO_STRUCT_OFFSET (SeqPointInfo, bp_addrs);
+                               /* Load the info->bp_addrs [offset], which is either 0 or the address of the bp trampoline */
+                               code = emit_ldrx (code, ARMREG_IP1, ARMREG_IP1, val);
+                               /* Skip the load if its 0 */
+                               arm_cbzx (code, ARMREG_IP1, code + 8);
+                               /* Call the breakpoint trampoline */
+                               arm_blrx (code, ARMREG_IP1);
+                       } else {
+                               MonoInst *var = cfg->arch.bp_tramp_var;
+
+                               g_assert (var);
+                               g_assert (var->opcode == OP_REGOFFSET);
+                               /* Load the address of the bp trampoline into IP0 */
+                               arm_ldrx (code, ARMREG_IP0, var->inst_basereg, var->inst_offset);
+                               /* 
+                                * A placeholder for a possible breakpoint inserted by
+                                * mono_arch_set_breakpoint ().
+                                */
+                               arm_nop (code);
+                       }
+                       break;
+               }
+
+                       /* BRANCH */
+               case OP_BR:
+                       mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb, MONO_R_ARM64_B);
+                       arm_b (code, code);
+                       break;
+               case OP_BR_REG:
+                       arm_brx (code, sreg1);
+                       break;
+               case OP_IBEQ:
+               case OP_IBGE:
+               case OP_IBGT:
+               case OP_IBLE:
+               case OP_IBLT:
+               case OP_IBNE_UN:
+               case OP_IBGE_UN:
+               case OP_IBGT_UN:
+               case OP_IBLE_UN:
+               case OP_IBLT_UN:
+               case OP_LBEQ:
+               case OP_LBGE:
+               case OP_LBGT:
+               case OP_LBLE:
+               case OP_LBLT:
+               case OP_LBNE_UN:
+               case OP_LBGE_UN:
+               case OP_LBGT_UN:
+               case OP_LBLE_UN:
+               case OP_LBLT_UN:
+               case OP_FBEQ:
+               case OP_FBNE_UN:
+               case OP_FBLT:
+               case OP_FBGT:
+               case OP_FBGT_UN:
+               case OP_FBLE:
+               case OP_FBGE:
+               case OP_FBGE_UN: {
+                       int cond;
+
+                       mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_true_bb, MONO_R_ARM64_BCC);
+                       cond = opcode_to_armcond (ins->opcode);
+                       arm_bcc (code, cond, 0);
+                       break;
+               }
+               case OP_FBLT_UN:
+                       mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_true_bb, MONO_R_ARM64_BCC);
+                       /* For fp compares, ARMCOND_LT is lt or unordered */
+                       arm_bcc (code, ARMCOND_LT, 0);
+                       break;
+               case OP_FBLE_UN:
+                       mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_true_bb, MONO_R_ARM64_BCC);
+                       arm_bcc (code, ARMCOND_EQ, 0);
+                       offset = code - cfg->native_code;
+                       mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_true_bb, MONO_R_ARM64_BCC);
+                       /* For fp compares, ARMCOND_LT is lt or unordered */
+                       arm_bcc (code, ARMCOND_LT, 0);
+                       break;
+               case OP_ARM64_CBZW:
+                       mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_true_bb, MONO_R_ARM64_CBZ);
+                       arm_cbzw (code, sreg1, 0);
+                       break;
+               case OP_ARM64_CBZX:
+                       mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_true_bb, MONO_R_ARM64_CBZ);
+                       arm_cbzx (code, sreg1, 0);
+                       break;
+               case OP_ARM64_CBNZW:
+                       mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_true_bb, MONO_R_ARM64_CBZ);
+                       arm_cbnzw (code, sreg1, 0);
+                       break;
+               case OP_ARM64_CBNZX:
+                       mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_true_bb, MONO_R_ARM64_CBZ);
+                       arm_cbnzx (code, sreg1, 0);
+                       break;
+                       /* ALU */
+               case OP_IADD:
+                       arm_addw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LADD:
+                       arm_addx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_ISUB:
+                       arm_subw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LSUB:
+                       arm_subx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_IAND:
+                       arm_andw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LAND:
+                       arm_andx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_IOR:
+                       arm_orrw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LOR:
+                       arm_orrx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_IXOR:
+                       arm_eorw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LXOR:
+                       arm_eorx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_INEG:
+                       arm_negw (code, dreg, sreg1);
+                       break;
+               case OP_LNEG:
+                       arm_negx (code, dreg, sreg1);
+                       break;
+               case OP_INOT:
+                       arm_mvnw (code, dreg, sreg1);
+                       break;
+               case OP_LNOT:
+                       arm_mvnx (code, dreg, sreg1);
+                       break;
+               case OP_IADDCC:
+                       arm_addsw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_ADDCC:
+               case OP_LADDCC:
+                       arm_addsx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_ISUBCC:
+                       arm_subsw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LSUBCC:
+               case OP_SUBCC:
+                       arm_subsx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_ICOMPARE:
+                       arm_cmpw (code, sreg1, sreg2);
+                       break;
+               case OP_COMPARE:
+               case OP_LCOMPARE:
+                       arm_cmpx (code, sreg1, sreg2);
+                       break;
+               case OP_IADD_IMM:
+                       code = emit_addw_imm (code, dreg, sreg1, imm);
+                       break;
+               case OP_LADD_IMM:
+               case OP_ADD_IMM:
+                       code = emit_addx_imm (code, dreg, sreg1, imm);
+                       break;
+               case OP_ISUB_IMM:
+                       code = emit_subw_imm (code, dreg, sreg1, imm);
+                       break;
+               case OP_LSUB_IMM:
+                       code = emit_subx_imm (code, dreg, sreg1, imm);
+                       break;
+               case OP_IAND_IMM:
+                       code = emit_andw_imm (code, dreg, sreg1, imm);
+                       break;
+               case OP_LAND_IMM:
+               case OP_AND_IMM:
+                       code = emit_andx_imm (code, dreg, sreg1, imm);
+                       break;
+               case OP_IOR_IMM:
+                       code = emit_orrw_imm (code, dreg, sreg1, imm);
+                       break;
+               case OP_LOR_IMM:
+                       code = emit_orrx_imm (code, dreg, sreg1, imm);
+                       break;
+               case OP_IXOR_IMM:
+                       code = emit_eorw_imm (code, dreg, sreg1, imm);
+                       break;
+               case OP_LXOR_IMM:
+                       code = emit_eorx_imm (code, dreg, sreg1, imm);
+                       break;
+               case OP_ICOMPARE_IMM:
+                       code = emit_cmpw_imm (code, sreg1, imm);
+                       break;
+               case OP_LCOMPARE_IMM:
+               case OP_COMPARE_IMM:
+                       if (imm == 0) {
+                               arm_cmpx (code, sreg1, ARMREG_RZR);
+                       } else {
+                               // FIXME: 32 vs 64 bit issues for 0xffffffff
+                               code = emit_imm64 (code, ARMREG_LR, imm);
+                               arm_cmpx (code, sreg1, ARMREG_LR);
+                       }
+                       break;
+               case OP_ISHL:
+                       arm_lslvw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LSHL:
+                       arm_lslvx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_ISHR:
+                       arm_asrvw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LSHR:
+                       arm_asrvx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_ISHR_UN:
+                       arm_lsrvw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LSHR_UN:
+                       arm_lsrvx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_ISHL_IMM:
+                       if (imm == 0)
+                               arm_movx (code, dreg, sreg1);
+                       else
+                               arm_lslw (code, dreg, sreg1, imm);
+                       break;
+               case OP_LSHL_IMM:
+                       if (imm == 0)
+                               arm_movx (code, dreg, sreg1);
+                       else
+                               arm_lslx (code, dreg, sreg1, imm);
+                       break;
+               case OP_ISHR_IMM:
+                       if (imm == 0)
+                               arm_movx (code, dreg, sreg1);
+                       else
+                               arm_asrw (code, dreg, sreg1, imm);
+                       break;
+               case OP_LSHR_IMM:
+               case OP_SHR_IMM:
+                       if (imm == 0)
+                               arm_movx (code, dreg, sreg1);
+                       else
+                               arm_asrx (code, dreg, sreg1, imm);
+                       break;
+               case OP_ISHR_UN_IMM:
+                       if (imm == 0)
+                               arm_movx (code, dreg, sreg1);
+                       else
+                               arm_lsrw (code, dreg, sreg1, imm);
+                       break;
+               case OP_SHR_UN_IMM:
+               case OP_LSHR_UN_IMM:
+                       if (imm == 0)
+                               arm_movx (code, dreg, sreg1);
+                       else
+                               arm_lsrx (code, dreg, sreg1, imm);
+                       break;
+
+                       /* 64BIT ALU */
+               case OP_SEXT_I4:
+                       arm_sxtwx (code, dreg, sreg1);
+                       break;
+               case OP_ZEXT_I4:
+                       /* Clean out the upper word */
+                       arm_movw (code, dreg, sreg1);
+                       break;
+               case OP_SHL_IMM:
+                       arm_lslx (code, dreg, sreg1, imm);
+                       break;
+
+                       /* MULTIPLY/DIVISION */
+               case OP_IDIV:
+               case OP_IREM:
+                       // FIXME: Optimize this
+                       /* Check for zero */
+                       arm_cmpx_imm (code, sreg2, 0);
+                       code = emit_cond_exc (cfg, code, OP_COND_EXC_IEQ, "DivideByZeroException");
+                       /* Check for INT_MIN/-1 */
+                       code = emit_imm (code, ARMREG_IP0, 0x80000000);
+                       arm_cmpx (code, sreg1, ARMREG_IP0);
+                       arm_cset (code, ARMCOND_EQ, ARMREG_IP1);
+                       code = emit_imm (code, ARMREG_IP0, 0xffffffff);
+                       arm_cmpx (code, sreg2, ARMREG_IP0);
+                       arm_cset (code, ARMCOND_EQ, ARMREG_IP0);
+                       arm_andx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
+                       arm_cmpx_imm (code, ARMREG_IP0, 1);
+                       code = emit_cond_exc (cfg, code, OP_COND_EXC_IEQ, "OverflowException");
+                       if (ins->opcode == OP_IREM) {
+                               arm_sdivw (code, ARMREG_LR, sreg1, sreg2);
+                               arm_msubw (code, dreg, ARMREG_LR, sreg2, sreg1);
+                       } else {
+                               arm_sdivw (code, dreg, sreg1, sreg2);
+                       }
+                       break;
+               case OP_IDIV_UN:
+                       arm_cmpx_imm (code, sreg2, 0);
+                       code = emit_cond_exc (cfg, code, OP_COND_EXC_IEQ, "DivideByZeroException");
+                       arm_udivw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_IREM_UN:
+                       arm_cmpx_imm (code, sreg2, 0);
+                       code = emit_cond_exc (cfg, code, OP_COND_EXC_IEQ, "DivideByZeroException");
+                       arm_udivw (code, ARMREG_LR, sreg1, sreg2);
+                       arm_msubw (code, dreg, ARMREG_LR, sreg2, sreg1);
+                       break;
+               case OP_LDIV:
+               case OP_LREM:
+                       // FIXME: Optimize this
+                       /* Check for zero */
+                       arm_cmpx_imm (code, sreg2, 0);
+                       code = emit_cond_exc (cfg, code, OP_COND_EXC_IEQ, "DivideByZeroException");
+                       /* Check for INT64_MIN/-1 */
+                       code = emit_imm64 (code, ARMREG_IP0, 0x8000000000000000);
+                       arm_cmpx (code, sreg1, ARMREG_IP0);
+                       arm_cset (code, ARMCOND_EQ, ARMREG_IP1);
+                       code = emit_imm64 (code, ARMREG_IP0, 0xffffffffffffffff);
+                       arm_cmpx (code, sreg2, ARMREG_IP0);
+                       arm_cset (code, ARMCOND_EQ, ARMREG_IP0);
+                       arm_andx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
+                       arm_cmpx_imm (code, ARMREG_IP0, 1);
+                       /* 64 bit uses ArithmeticException */
+                       code = emit_cond_exc (cfg, code, OP_COND_EXC_IEQ, "ArithmeticException");
+                       if (ins->opcode == OP_LREM) {
+                               arm_sdivx (code, ARMREG_LR, sreg1, sreg2);
+                               arm_msubx (code, dreg, ARMREG_LR, sreg2, sreg1);
+                       } else {
+                               arm_sdivx (code, dreg, sreg1, sreg2);
+                       }
+                       break;
+               case OP_LDIV_UN:
+                       arm_cmpx_imm (code, sreg2, 0);
+                       code = emit_cond_exc (cfg, code, OP_COND_EXC_IEQ, "DivideByZeroException");
+                       arm_udivx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LREM_UN:
+                       arm_cmpx_imm (code, sreg2, 0);
+                       code = emit_cond_exc (cfg, code, OP_COND_EXC_IEQ, "DivideByZeroException");
+                       arm_udivx (code, ARMREG_LR, sreg1, sreg2);
+                       arm_msubx (code, dreg, ARMREG_LR, sreg2, sreg1);
+                       break;
+               case OP_IMUL:
+                       arm_mulw (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_LMUL:
+                       arm_mulx (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_IMUL_IMM:
+                       code = emit_imm (code, ARMREG_LR, imm);
+                       arm_mulw (code, dreg, sreg1, ARMREG_LR);
+                       break;
+               case OP_MUL_IMM:
+               case OP_LMUL_IMM:
+                       code = emit_imm (code, ARMREG_LR, imm);
+                       arm_mulx (code, dreg, sreg1, ARMREG_LR);
+                       break;
+
+                       /* CONVERSIONS */
+               case OP_ICONV_TO_I1:
+               case OP_LCONV_TO_I1:
+                       arm_sxtbx (code, dreg, sreg1);
+                       break;
+               case OP_ICONV_TO_I2:
+               case OP_LCONV_TO_I2:
+                       arm_sxthx (code, dreg, sreg1);
+                       break;
+               case OP_ICONV_TO_U1:
+               case OP_LCONV_TO_U1:
+                       arm_uxtbw (code, dreg, sreg1);
+                       break;
+               case OP_ICONV_TO_U2:
+               case OP_LCONV_TO_U2:
+                       arm_uxthw (code, dreg, sreg1);
+                       break;
+
+                       /* CSET */
+               case OP_CEQ:
+               case OP_ICEQ:
+               case OP_LCEQ:
+               case OP_CLT:
+               case OP_ICLT:
+               case OP_LCLT:
+               case OP_CGT:
+               case OP_ICGT:
+               case OP_LCGT:
+               case OP_CLT_UN:
+               case OP_ICLT_UN:
+               case OP_LCLT_UN:
+               case OP_CGT_UN:
+               case OP_ICGT_UN:
+               case OP_LCGT_UN:
+               case OP_ICNEQ:
+               case OP_ICGE:
+               case OP_ICLE:
+               case OP_ICGE_UN:
+               case OP_ICLE_UN: {
+                       int cond;
+
+                       cond = opcode_to_armcond (ins->opcode);
+                       arm_cset (code, cond, dreg);
+                       break;
+               }
+               case OP_FCEQ:
+               case OP_FCLT:
+               case OP_FCLT_UN:
+               case OP_FCGT:
+               case OP_FCGT_UN:
+               case OP_FCNEQ:
+               case OP_FCLE:
+               case OP_FCGE: {
+                       int cond;
+
+                       cond = opcode_to_armcond (ins->opcode);
+                       arm_fcmpd (code, sreg1, sreg2);
+                       arm_cset (code, cond, dreg);
+                       break;
+               }
+
+                       /* MEMORY */
+               case OP_LOADI1_MEMBASE:
+                       code = emit_ldrsbx (code, dreg, ins->inst_basereg, ins->inst_offset);
+                       break;
+               case OP_LOADU1_MEMBASE:
+                       code = emit_ldrb (code, dreg, ins->inst_basereg, ins->inst_offset);
+                       break;
+               case OP_LOADI2_MEMBASE:
+                       code = emit_ldrshx (code, dreg, ins->inst_basereg, ins->inst_offset);
+                       break;
+               case OP_LOADU2_MEMBASE:
+                       code = emit_ldrh (code, dreg, ins->inst_basereg, ins->inst_offset);
+                       break;
+               case OP_LOADI4_MEMBASE:
+                       code = emit_ldrswx (code, dreg, ins->inst_basereg, ins->inst_offset);
+                       break;
+               case OP_LOADU4_MEMBASE:
+                       code = emit_ldrw (code, dreg, ins->inst_basereg, ins->inst_offset);
+                       break;
+               case OP_LOAD_MEMBASE:
+               case OP_LOADI8_MEMBASE:
+                       code = emit_ldrx (code, dreg, ins->inst_basereg, ins->inst_offset);
+                       break;
+               case OP_STOREI1_MEMBASE_IMM:
+               case OP_STOREI2_MEMBASE_IMM:
+               case OP_STOREI4_MEMBASE_IMM:
+               case OP_STORE_MEMBASE_IMM:
+               case OP_STOREI8_MEMBASE_IMM: {
+                       int immreg;
+
+                       if (imm != 0) {
+                               code = emit_imm (code, ARMREG_LR, imm);
+                               immreg = ARMREG_LR;
+                       } else {
+                               immreg = ARMREG_RZR;
+                       }
+
+                       switch (ins->opcode) {
+                       case OP_STOREI1_MEMBASE_IMM:
+                               code = emit_strb (code, immreg, ins->inst_destbasereg, ins->inst_offset);
+                               break;
+                       case OP_STOREI2_MEMBASE_IMM:
+                               code = emit_strh (code, immreg, ins->inst_destbasereg, ins->inst_offset);
+                               break;
+                       case OP_STOREI4_MEMBASE_IMM:
+                               code = emit_strw (code, immreg, ins->inst_destbasereg, ins->inst_offset);
+                               break;
+                       case OP_STORE_MEMBASE_IMM:
+                       case OP_STOREI8_MEMBASE_IMM:
+                               code = emit_strx (code, immreg, ins->inst_destbasereg, ins->inst_offset);
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                               break;
+                       }
+                       break;
+               }
+               case OP_STOREI1_MEMBASE_REG:
+                       code = emit_strb (code, sreg1, ins->inst_destbasereg, ins->inst_offset);
+                       break;
+               case OP_STOREI2_MEMBASE_REG:
+                       code = emit_strh (code, sreg1, ins->inst_destbasereg, ins->inst_offset);
+                       break;
+               case OP_STOREI4_MEMBASE_REG:
+                       code = emit_strw (code, sreg1, ins->inst_destbasereg, ins->inst_offset);
+                       break;
+               case OP_STORE_MEMBASE_REG:
+               case OP_STOREI8_MEMBASE_REG:
+                       code = emit_strx (code, sreg1, ins->inst_destbasereg, ins->inst_offset);
+                       break;
+
+               case OP_TLS_GET:
+                       code = emit_tls_get (code, dreg, ins->inst_offset);
+                       break;
+               case OP_TLS_GET_REG:
+                       code = emit_tls_get_reg (code, dreg, sreg1);
+                       break;
+               case OP_TLS_SET:
+                       code = emit_tls_set (code, sreg1, ins->inst_offset);
+                       break;
+               case OP_TLS_SET_REG:
+                       code = emit_tls_set_reg (code, sreg1, sreg2);
+                       break;
+
+                       /* Atomic */
+               case OP_MEMORY_BARRIER:
+                       arm_dmb (code, 0);
+                       break;
+               case OP_ATOMIC_ADD_I4: {
+                       guint8 *buf [16];
+
+                       buf [0] = code;
+                       arm_ldaxrw (code, ARMREG_IP0, sreg1);
+                       arm_addx (code, ARMREG_IP0, ARMREG_IP0, sreg2);
+                       arm_stlxrw (code, ARMREG_IP1, ARMREG_IP0, sreg1);
+                       arm_cbnzw (code, ARMREG_IP1, buf [0]);
+
+                       arm_movx (code, dreg, ARMREG_IP0);
+                       break;
+               }
+               case OP_ATOMIC_ADD_I8: {
+                       guint8 *buf [16];
+
+                       buf [0] = code;
+                       arm_ldaxrx (code, ARMREG_IP0, sreg1);
+                       arm_addx (code, ARMREG_IP0, ARMREG_IP0, sreg2);
+                       arm_stlxrx (code, ARMREG_IP1, ARMREG_IP0, sreg1);
+                       arm_cbnzx (code, ARMREG_IP1, buf [0]);
+
+                       arm_movx (code, dreg, ARMREG_IP0);
+                       break;
+               }
+               case OP_ATOMIC_EXCHANGE_I4: {
+                       guint8 *buf [16];
+
+                       buf [0] = code;
+                       arm_ldaxrw (code, ARMREG_IP0, sreg1);
+                       arm_stlxrw (code, ARMREG_IP1, sreg2, sreg1);
+                       arm_cbnzw (code, ARMREG_IP1, buf [0]);
+
+                       arm_movx (code, dreg, ARMREG_IP0);
+                       break;
+               }
+               case OP_ATOMIC_EXCHANGE_I8: {
+                       guint8 *buf [16];
+
+                       buf [0] = code;
+                       arm_ldaxrx (code, ARMREG_IP0, sreg1);
+                       arm_stlxrx (code, ARMREG_IP1, sreg2, sreg1);
+                       arm_cbnzw (code, ARMREG_IP1, buf [0]);
+
+                       arm_movx (code, dreg, ARMREG_IP0);
+                       break;
+               }
+               case OP_ATOMIC_CAS_I4: {
+                       guint8 *buf [16];
+
+                       /* sreg2 is the value, sreg3 is the comparand */
+                       buf [0] = code;
+                       arm_ldaxrw (code, ARMREG_IP0, sreg1);
+                       arm_cmpw (code, ARMREG_IP0, ins->sreg3);
+                       buf [1] = code;
+                       arm_bcc (code, ARMCOND_NE, 0);
+                       arm_stlxrw (code, ARMREG_IP1, sreg2, sreg1);
+                       arm_cbnzw (code, ARMREG_IP1, buf [0]);
+                       arm_patch_rel (buf [1], code, MONO_R_ARM64_BCC);
+
+                       arm_movx (code, dreg, ARMREG_IP0);
+                       break;
+               }
+               case OP_ATOMIC_CAS_I8: {
+                       guint8 *buf [16];
+
+                       buf [0] = code;
+                       arm_ldaxrx (code, ARMREG_IP0, sreg1);
+                       arm_cmpx (code, ARMREG_IP0, ins->sreg3);
+                       buf [1] = code;
+                       arm_bcc (code, ARMCOND_NE, 0);
+                       arm_stlxrx (code, ARMREG_IP1, sreg2, sreg1);
+                       arm_cbnzw (code, ARMREG_IP1, buf [0]);
+                       arm_patch_rel (buf [1], code, MONO_R_ARM64_BCC);
+
+                       arm_movx (code, dreg, ARMREG_IP0);
+                       break;
+               }
+               case OP_ATOMIC_LOAD_I1: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_basereg, ins->inst_offset);
+                       arm_ldarb (code, ins->dreg, ARMREG_LR);
+                       arm_sxtbx (code, ins->dreg, ins->dreg);
+                       break;
+               }
+               case OP_ATOMIC_LOAD_U1: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_basereg, ins->inst_offset);
+                       arm_ldarb (code, ins->dreg, ARMREG_LR);
+                       arm_uxtbx (code, ins->dreg, ins->dreg);
+                       break;
+               }
+               case OP_ATOMIC_LOAD_I2: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_basereg, ins->inst_offset);
+                       arm_ldarh (code, ins->dreg, ARMREG_LR);
+                       arm_sxthx (code, ins->dreg, ins->dreg);
+                       break;
+               }
+               case OP_ATOMIC_LOAD_U2: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_basereg, ins->inst_offset);
+                       arm_ldarh (code, ins->dreg, ARMREG_LR);
+                       arm_uxthx (code, ins->dreg, ins->dreg);
+                       break;
+               }
+               case OP_ATOMIC_LOAD_I4: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_basereg, ins->inst_offset);
+                       arm_ldarw (code, ins->dreg, ARMREG_LR);
+                       arm_sxtwx (code, ins->dreg, ins->dreg);
+                       break;
+               }
+               case OP_ATOMIC_LOAD_U4: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_basereg, ins->inst_offset);
+                       arm_ldarw (code, ins->dreg, ARMREG_LR);
+                       arm_movw (code, ins->dreg, ins->dreg); /* Clear upper half of the register. */
+                       break;
+               }
+               case OP_ATOMIC_LOAD_I8:
+               case OP_ATOMIC_LOAD_U8: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_basereg, ins->inst_offset);
+                       arm_ldarx (code, ins->dreg, ARMREG_LR);
+                       break;
+               }
+               case OP_ATOMIC_LOAD_R4: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_basereg, ins->inst_offset);
+                       if (cfg->r4fp) {
+                               arm_ldarw (code, ARMREG_LR, ARMREG_LR);
+                               arm_fmov_rx_to_double (code, ins->dreg, ARMREG_LR);
+                       } else {
+                               arm_ldarw (code, ARMREG_LR, ARMREG_LR);
+                               arm_fmov_rx_to_double (code, FP_TEMP_REG, ARMREG_LR);
+                               arm_fcvt_sd (code, ins->dreg, FP_TEMP_REG);
+                       }
+                       break;
+               }
+               case OP_ATOMIC_LOAD_R8: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_basereg, ins->inst_offset);
+                       arm_ldarx (code, ARMREG_LR, ARMREG_LR);
+                       arm_fmov_rx_to_double (code, ins->dreg, ARMREG_LR);
+                       break;
+               }
+               case OP_ATOMIC_STORE_I1:
+               case OP_ATOMIC_STORE_U1: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_destbasereg, ins->inst_offset);
+                       arm_stlrb (code, ARMREG_LR, ins->sreg1);
+                       break;
+               }
+               case OP_ATOMIC_STORE_I2:
+               case OP_ATOMIC_STORE_U2: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_destbasereg, ins->inst_offset);
+                       arm_stlrh (code, ARMREG_LR, ins->sreg1);
+                       break;
+               }
+               case OP_ATOMIC_STORE_I4:
+               case OP_ATOMIC_STORE_U4: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_destbasereg, ins->inst_offset);
+                       arm_stlrw (code, ARMREG_LR, ins->sreg1);
+                       break;
+               }
+               case OP_ATOMIC_STORE_I8:
+               case OP_ATOMIC_STORE_U8: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_destbasereg, ins->inst_offset);
+                       arm_stlrx (code, ARMREG_LR, ins->sreg1);
+                       break;
+               }
+               case OP_ATOMIC_STORE_R4: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_destbasereg, ins->inst_offset);
+                       if (cfg->r4fp) {
+                               arm_fmov_double_to_rx (code, ARMREG_IP0, ins->sreg1);
+                               arm_stlrw (code, ARMREG_LR, ARMREG_IP0);
+                       } else {
+                               arm_fcvt_ds (code, FP_TEMP_REG, ins->sreg1);
+                               arm_fmov_double_to_rx (code, ARMREG_IP0, FP_TEMP_REG);
+                               arm_stlrw (code, ARMREG_LR, ARMREG_IP0);
+                       }
+                       break;
+               }
+               case OP_ATOMIC_STORE_R8: {
+                       code = emit_addx_imm (code, ARMREG_LR, ins->inst_destbasereg, ins->inst_offset);
+                       arm_fmov_double_to_rx (code, ARMREG_IP0, ins->sreg1);
+                       arm_stlrx (code, ARMREG_LR, ARMREG_IP0);
+                       break;
+               }
+
+                       /* FP */
+               case OP_R8CONST: {
+                       guint64 imm = *(guint64*)ins->inst_p0;
+
+                       if (imm == 0) {
+                               arm_fmov_rx_to_double (code, dreg, ARMREG_RZR);
+                       } else {
+                               code = emit_imm64 (code, ARMREG_LR, imm);
+                               arm_fmov_rx_to_double (code, ins->dreg, ARMREG_LR);
+                       }
+                       break;
+               }
+               case OP_R4CONST: {
+                       guint64 imm = *(guint32*)ins->inst_p0;
+
+                       code = emit_imm64 (code, ARMREG_LR, imm);
+                       if (cfg->r4fp) {
+                               arm_fmov_rx_to_double (code, dreg, ARMREG_LR);
+                       } else {
+                               arm_fmov_rx_to_double (code, FP_TEMP_REG, ARMREG_LR);
+                               arm_fcvt_sd (code, dreg, FP_TEMP_REG);
+                       }
+                       break;
+               }
+               case OP_LOADR8_MEMBASE:
+                       code = emit_ldrfpx (code, dreg, ins->inst_basereg, ins->inst_offset);
+                       break;
+               case OP_LOADR4_MEMBASE:
+                       if (cfg->r4fp) {
+                               code = emit_ldrfpw (code, dreg, ins->inst_basereg, ins->inst_offset);
+                       } else {
+                               code = emit_ldrfpw (code, FP_TEMP_REG, ins->inst_basereg, ins->inst_offset);
+                               arm_fcvt_sd (code, dreg, FP_TEMP_REG);
+                       }
+                       break;
+               case OP_STORER8_MEMBASE_REG:
+                       code = emit_strfpx (code, sreg1, ins->inst_destbasereg, ins->inst_offset);
+                       break;
+               case OP_STORER4_MEMBASE_REG:
+                       if (cfg->r4fp) {
+                               code = emit_strfpw (code, sreg1, ins->inst_destbasereg, ins->inst_offset);
+                       } else {
+                               arm_fcvt_ds (code, FP_TEMP_REG, sreg1);
+                               code = emit_strfpw (code, FP_TEMP_REG, ins->inst_destbasereg, ins->inst_offset);
+                       }
+                       break;
+               case OP_FMOVE:
+                       if (dreg != sreg1)
+                               arm_fmovd (code, dreg, sreg1);
+                       break;
+               case OP_RMOVE:
+                       if (dreg != sreg1)
+                               arm_fmovs (code, dreg, sreg1);
+                       break;
+               case OP_MOVE_F_TO_I4:
+                       if (cfg->r4fp) {
+                               arm_fmov_double_to_rx (code, ins->dreg, ins->sreg1);
+                       } else {
+                               arm_fcvt_ds (code, ins->dreg, ins->sreg1);
+                               arm_fmov_double_to_rx (code, ins->dreg, ins->dreg);
+                       }
+                       break;
+               case OP_MOVE_I4_TO_F:
+                       if (cfg->r4fp) {
+                               arm_fmov_rx_to_double (code, ins->dreg, ins->sreg1);
+                       } else {
+                               arm_fmov_rx_to_double (code, ins->dreg, ins->sreg1);
+                               arm_fcvt_sd (code, ins->dreg, ins->dreg);
+                       }
+                       break;
+               case OP_MOVE_F_TO_I8:
+                       arm_fmov_double_to_rx (code, ins->dreg, ins->sreg1);
+                       break;
+               case OP_MOVE_I8_TO_F:
+                       arm_fmov_rx_to_double (code, ins->dreg, ins->sreg1);
+                       break;
+               case OP_FCOMPARE:
+                       arm_fcmpd (code, sreg1, sreg2);
+                       break;
+               case OP_RCOMPARE:
+                       arm_fcmps (code, sreg1, sreg2);
+                       break;
+               case OP_FCONV_TO_I1:
+                       arm_fcvtzs_dx (code, dreg, sreg1);
+                       arm_sxtbx (code, dreg, dreg);
+                       break;
+               case OP_FCONV_TO_U1:
+                       arm_fcvtzu_dx (code, dreg, sreg1);
+                       arm_uxtbw (code, dreg, dreg);
+                       break;
+               case OP_FCONV_TO_I2:
+                       arm_fcvtzs_dx (code, dreg, sreg1);
+                       arm_sxthx (code, dreg, dreg);
+                       break;
+               case OP_FCONV_TO_U2:
+                       arm_fcvtzu_dx (code, dreg, sreg1);
+                       arm_uxthw (code, dreg, dreg);
+                       break;
+               case OP_FCONV_TO_I4:
+                       arm_fcvtzs_dx (code, dreg, sreg1);
+                       arm_sxtwx (code, dreg, dreg);
+                       break;
+               case OP_FCONV_TO_U4:
+                       arm_fcvtzu_dx (code, dreg, sreg1);
+                       break;
+               case OP_FCONV_TO_I8:
+                       arm_fcvtzs_dx (code, dreg, sreg1);
+                       break;
+               case OP_FCONV_TO_U8:
+                       arm_fcvtzu_dx (code, dreg, sreg1);
+                       break;
+               case OP_FCONV_TO_R4:
+                       if (cfg->r4fp) {
+                               arm_fcvt_ds (code, dreg, sreg1);
+                       } else {
+                               arm_fcvt_ds (code, FP_TEMP_REG, sreg1);
+                               arm_fcvt_sd (code, dreg, FP_TEMP_REG);
+                       }
+                       break;
+               case OP_ICONV_TO_R4:
+                       if (cfg->r4fp) {
+                               arm_scvtf_rw_to_s (code, dreg, sreg1);
+                       } else {
+                               arm_scvtf_rw_to_s (code, FP_TEMP_REG, sreg1);
+                               arm_fcvt_sd (code, dreg, FP_TEMP_REG);
+                       }
+                       break;
+               case OP_LCONV_TO_R4:
+                       if (cfg->r4fp) {
+                               arm_scvtf_rx_to_s (code, dreg, sreg1);
+                       } else {
+                               arm_scvtf_rx_to_s (code, FP_TEMP_REG, sreg1);
+                               arm_fcvt_sd (code, dreg, FP_TEMP_REG);
+                       }
+                       break;
+               case OP_ICONV_TO_R8:
+                       arm_scvtf_rw_to_d (code, dreg, sreg1);
+                       break;
+               case OP_LCONV_TO_R8:
+                       arm_scvtf_rx_to_d (code, dreg, sreg1);
+                       break;
+               case OP_ICONV_TO_R_UN:
+                       arm_ucvtf_rw_to_d (code, dreg, sreg1);
+                       break;
+               case OP_LCONV_TO_R_UN:
+                       arm_ucvtf_rx_to_d (code, dreg, sreg1);
+                       break;
+               case OP_FADD:
+                       arm_fadd_d (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_FSUB:
+                       arm_fsub_d (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_FMUL:
+                       arm_fmul_d (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_FDIV:
+                       arm_fdiv_d (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_FREM:
+                       /* Emulated */
+                       g_assert_not_reached ();
+                       break;
+               case OP_FNEG:
+                       arm_fneg_d (code, dreg, sreg1);
+                       break;
+               case OP_ARM_SETFREG_R4:
+                       arm_fcvt_ds (code, dreg, sreg1);
+                       break;
+               case OP_CKFINITE:
+                       /* Check for infinity */
+                       code = emit_imm64 (code, ARMREG_LR, 0x7fefffffffffffffLL);
+                       arm_fmov_rx_to_double (code, FP_TEMP_REG, ARMREG_LR);
+                       arm_fabs_d (code, FP_TEMP_REG2, sreg1);
+                       arm_fcmpd (code, FP_TEMP_REG2, FP_TEMP_REG);
+                       code = emit_cond_exc (cfg, code, OP_COND_EXC_GT, "ArithmeticException");
+                       /* Check for nans */
+                       arm_fcmpd (code, FP_TEMP_REG2, FP_TEMP_REG2);
+                       code = emit_cond_exc (cfg, code, OP_COND_EXC_OV, "ArithmeticException");
+                       arm_fmovd (code, dreg, sreg1);
+                       break;
+
+                       /* R4 */
+               case OP_RADD:
+                       arm_fadd_s (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_RSUB:
+                       arm_fsub_s (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_RMUL:
+                       arm_fmul_s (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_RDIV:
+                       arm_fdiv_s (code, dreg, sreg1, sreg2);
+                       break;
+               case OP_RNEG:
+                       arm_fneg_s (code, dreg, sreg1);
+                       break;
+               case OP_RCONV_TO_I1:
+                       arm_fcvtzs_sx (code, dreg, sreg1);
+                       arm_sxtbx (code, dreg, dreg);
+                       break;
+               case OP_RCONV_TO_U1:
+                       arm_fcvtzu_sx (code, dreg, sreg1);
+                       arm_uxtbw (code, dreg, dreg);
+                       break;
+               case OP_RCONV_TO_I2:
+                       arm_fcvtzs_sx (code, dreg, sreg1);
+                       arm_sxthx (code, dreg, dreg);
+                       break;
+               case OP_RCONV_TO_U2:
+                       arm_fcvtzu_sx (code, dreg, sreg1);
+                       arm_uxthw (code, dreg, dreg);
+                       break;
+               case OP_RCONV_TO_I4:
+                       arm_fcvtzs_sx (code, dreg, sreg1);
+                       arm_sxtwx (code, dreg, dreg);
+                       break;
+               case OP_RCONV_TO_U4:
+                       arm_fcvtzu_sx (code, dreg, sreg1);
+                       break;
+               case OP_RCONV_TO_I8:
+                       arm_fcvtzs_sx (code, dreg, sreg1);
+                       break;
+               case OP_RCONV_TO_U8:
+                       arm_fcvtzu_sx (code, dreg, sreg1);
+                       break;
+               case OP_RCONV_TO_R8:
+                       arm_fcvt_sd (code, dreg, sreg1);
+                       break;
+               case OP_RCONV_TO_R4:
+                       if (dreg != sreg1)
+                               arm_fmovs (code, dreg, sreg1);
+                       break;
+               case OP_RCEQ:
+               case OP_RCLT:
+               case OP_RCLT_UN:
+               case OP_RCGT:
+               case OP_RCGT_UN:
+               case OP_RCNEQ:
+               case OP_RCLE:
+               case OP_RCGE: {
+                       int cond;
+
+                       cond = opcode_to_armcond (ins->opcode);
+                       arm_fcmps (code, sreg1, sreg2);
+                       arm_cset (code, cond, dreg);
+                       break;
+               }
+
+                       /* CALLS */
+               case OP_VOIDCALL:
+               case OP_CALL:
+               case OP_LCALL:
+               case OP_FCALL:
+               case OP_RCALL:
+               case OP_VCALL2:
+                       call = (MonoCallInst*)ins;
+                       if (ins->flags & MONO_INST_HAS_METHOD)
+                               code = emit_call (cfg, code, MONO_PATCH_INFO_METHOD, call->method);
+                       else
+                               code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, call->fptr);
+                       code = emit_move_return_value (cfg, code, ins);
+                       break;
+               case OP_VOIDCALL_REG:
+               case OP_CALL_REG:
+               case OP_LCALL_REG:
+               case OP_FCALL_REG:
+               case OP_RCALL_REG:
+               case OP_VCALL2_REG:
+                       arm_blrx (code, sreg1);
+                       code = emit_move_return_value (cfg, code, ins);
+                       break;
+               case OP_VOIDCALL_MEMBASE:
+               case OP_CALL_MEMBASE:
+               case OP_LCALL_MEMBASE:
+               case OP_FCALL_MEMBASE:
+               case OP_RCALL_MEMBASE:
+               case OP_VCALL2_MEMBASE:
+                       code = emit_ldrx (code, ARMREG_IP0, ins->inst_basereg, ins->inst_offset);
+                       arm_blrx (code, ARMREG_IP0);
+                       code = emit_move_return_value (cfg, code, ins);
+                       break;
+               case OP_TAILCALL: {
+                       MonoCallInst *call = (MonoCallInst*)ins;
+
+                       g_assert (!cfg->method->save_lmf);
+
+                       // FIXME: Copy stack arguments
+
+                       /* Restore registers */
+                       code = emit_load_regset (code, MONO_ARCH_CALLEE_SAVED_REGS & cfg->used_int_regs, ARMREG_FP, cfg->arch.saved_gregs_offset);
+
+                       /* Destroy frame */
+                       code = mono_arm_emit_destroy_frame (code, cfg->stack_offset, ((1 << ARMREG_IP0) | (1 << ARMREG_IP1)));
+
+                       if (cfg->compile_aot) {
+                               /* This is not a PLT patch */
+                               code = emit_aotconst (cfg, code, ARMREG_IP0, MONO_PATCH_INFO_METHOD_JUMP, call->method);
+                               arm_brx (code, ARMREG_IP0);
+                       } else {
+                               mono_add_patch_info_rel (cfg, code - cfg->native_code, MONO_PATCH_INFO_METHOD_JUMP, call->method, MONO_R_ARM64_B);
+                               arm_b (code, code);
+                       }
+                       ins->flags |= MONO_INST_GC_CALLSITE;
+                       ins->backend.pc_offset = code - cfg->native_code;
+                       break;
+               }
+               case OP_ARGLIST:
+                       g_assert (cfg->arch.cinfo);
+                       code = emit_addx_imm (code, ARMREG_IP0, cfg->arch.args_reg, ((CallInfo*)cfg->arch.cinfo)->sig_cookie.offset);
+                       arm_strx (code, ARMREG_IP0, sreg1, 0);
+                       break;
+               case OP_DYN_CALL: {
+                       MonoInst *var = cfg->dyn_call_var;
+                       guint8 *labels [16];
+                       int i;
+
+                       /*
+                        * sreg1 points to a DynCallArgs structure initialized by mono_arch_start_dyn_call ().
+                        * sreg2 is the function to call.
+                        */
+
+                       g_assert (var->opcode == OP_REGOFFSET);
+
+                       arm_movx (code, ARMREG_LR, sreg1);
+                       arm_movx (code, ARMREG_IP1, sreg2);
+
+                       /* Save args buffer */
+                       code = emit_strx (code, ARMREG_LR, var->inst_basereg, var->inst_offset);
+
+                       /* Set fp argument regs */
+                       code = emit_ldrw (code, ARMREG_R0, ARMREG_LR, MONO_STRUCT_OFFSET (DynCallArgs, n_fpargs));
+                       arm_cmpw (code, ARMREG_R0, ARMREG_RZR);
+                       labels [0] = code;
+                       arm_bcc (code, ARMCOND_EQ, 0);
+                       for (i = 0; i < 8; ++i)
+                               code = emit_ldrfpx (code, ARMREG_D0 + i, ARMREG_LR, MONO_STRUCT_OFFSET (DynCallArgs, fpregs) + (i * 8));
+                       arm_patch_rel (labels [0], code, MONO_R_ARM64_BCC);
+
+                       /* Set stack args */
+                       for (i = 0; i < DYN_CALL_STACK_ARGS; ++i) {
+                               code = emit_ldrx (code, ARMREG_R0, ARMREG_LR, MONO_STRUCT_OFFSET (DynCallArgs, regs) + ((PARAM_REGS + 1 + i) * sizeof (mgreg_t)));
+                               code = emit_strx (code, ARMREG_R0, ARMREG_SP, i * sizeof (mgreg_t));
+                       }
+
+                       /* Set argument registers + r8 */
+                       code = mono_arm_emit_load_regarray (code, 0x1ff, ARMREG_LR, 0);
+
+                       /* Make the call */
+                       arm_blrx (code, ARMREG_IP1);
+
+                       /* Save result */
+                       code = emit_ldrx (code, ARMREG_LR, var->inst_basereg, var->inst_offset);
+                       arm_strx (code, ARMREG_R0, ARMREG_LR, MONO_STRUCT_OFFSET (DynCallArgs, res));
+                       arm_strx (code, ARMREG_R1, ARMREG_LR, MONO_STRUCT_OFFSET (DynCallArgs, res2));
+                       /* Save fp result */
+                       code = emit_ldrw (code, ARMREG_R0, ARMREG_LR, MONO_STRUCT_OFFSET (DynCallArgs, n_fpret));
+                       arm_cmpw (code, ARMREG_R0, ARMREG_RZR);
+                       labels [1] = code;
+                       arm_bcc (code, ARMCOND_EQ, 0);
+                       for (i = 0; i < 8; ++i)
+                               code = emit_strfpx (code, ARMREG_D0 + i, ARMREG_LR, MONO_STRUCT_OFFSET (DynCallArgs, fpregs) + (i * 8));
+                       arm_patch_rel (labels [1], code, MONO_R_ARM64_BCC);
+                       break;
+               }
+
+               case OP_GENERIC_CLASS_INIT: {
+                       static int byte_offset = -1;
+                       static guint8 bitmask;
+                       guint8 *jump;
+
+                       if (byte_offset < 0)
+                               mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
+
+                       /* Load vtable->initialized */
+                       arm_ldrsbx (code, ARMREG_IP0, sreg1, byte_offset);
+                       // FIXME: No andx_imm yet */
+                       code = mono_arm_emit_imm64 (code, ARMREG_IP1, bitmask);
+                       arm_andx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
+                       jump = code;
+                       arm_cbnzx (code, ARMREG_IP0, 0);
+
+                       /* Slowpath */
+                       g_assert (sreg1 == ARMREG_R0);
+                       code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD,
+                                                         (gpointer)"mono_generic_class_init");
+
+                       mono_arm_patch (jump, code, MONO_R_ARM64_CBZ);
+                       break;
+               }
+
+               case OP_CHECK_THIS:
+                       arm_ldrx (code, ARMREG_LR, sreg1, 0);
+                       break;
+               case OP_NOT_NULL:
+               case OP_NOT_REACHED:
+               case OP_DUMMY_USE:
+                       break;
+               case OP_IL_SEQ_POINT:
+                       mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
+                       break;
+
+                       /* EH */
+               case OP_COND_EXC_C:
+               case OP_COND_EXC_IC:
+               case OP_COND_EXC_OV:
+               case OP_COND_EXC_IOV:
+               case OP_COND_EXC_NC:
+               case OP_COND_EXC_INC:
+               case OP_COND_EXC_NO:
+               case OP_COND_EXC_INO:
+               case OP_COND_EXC_EQ:
+               case OP_COND_EXC_IEQ:
+               case OP_COND_EXC_NE_UN:
+               case OP_COND_EXC_INE_UN:
+               case OP_COND_EXC_ILT:
+               case OP_COND_EXC_LT:
+               case OP_COND_EXC_ILT_UN:
+               case OP_COND_EXC_LT_UN:
+               case OP_COND_EXC_IGT:
+               case OP_COND_EXC_GT:
+               case OP_COND_EXC_IGT_UN:
+               case OP_COND_EXC_GT_UN:
+               case OP_COND_EXC_IGE:
+               case OP_COND_EXC_GE:
+               case OP_COND_EXC_IGE_UN:
+               case OP_COND_EXC_GE_UN:
+               case OP_COND_EXC_ILE:
+               case OP_COND_EXC_LE:
+               case OP_COND_EXC_ILE_UN:
+               case OP_COND_EXC_LE_UN:
+                       code = emit_cond_exc (cfg, code, ins->opcode, ins->inst_p1);
+                       break;
+               case OP_THROW:
+                       if (sreg1 != ARMREG_R0)
+                               arm_movx (code, ARMREG_R0, sreg1);
+                       code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, 
+                                                         (gpointer)"mono_arch_throw_exception");
+                       break;
+               case OP_RETHROW:
+                       if (sreg1 != ARMREG_R0)
+                               arm_movx (code, ARMREG_R0, sreg1);
+                       code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, 
+                                                         (gpointer)"mono_arch_rethrow_exception");
+                       break;
+               case OP_CALL_HANDLER:
+                       mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb, MONO_R_ARM64_BL);
+                       arm_bl (code, 0);
+                       cfg->thunk_area += THUNK_SIZE;
+                       break;
+               case OP_START_HANDLER: {
+                       MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
+
+                       /* Save caller address */
+                       code = emit_strx (code, ARMREG_LR, spvar->inst_basereg, spvar->inst_offset);
+
+                       /*
+                        * Reserve a param area, see test_0_finally_param_area ().
+                        * This is needed because the param area is not set up when
+                        * we are called from EH code.
+                        */
+                       if (cfg->param_area)
+                               code = emit_subx_sp_imm (code, cfg->param_area);
+                       break;
+               }
+               case OP_ENDFINALLY:
+               case OP_ENDFILTER: {
+                       MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
+
+                       if (cfg->param_area)
+                               code = emit_addx_sp_imm (code, cfg->param_area);
+
+                       if (ins->opcode == OP_ENDFILTER && sreg1 != ARMREG_R0)
+                               arm_movx (code, ARMREG_R0, sreg1);
+
+                       /* Return to either after the branch in OP_CALL_HANDLER, or to the EH code */
+                       code = emit_ldrx (code, ARMREG_LR, spvar->inst_basereg, spvar->inst_offset);
+                       arm_brx (code, ARMREG_LR);
+                       break;
+               }
+               case OP_GET_EX_OBJ:
+                       if (ins->dreg != ARMREG_R0)
+                               arm_movx (code, ins->dreg, ARMREG_R0);
+                       break;
+               case OP_GC_SAFE_POINT: {
+#if defined (USE_COOP_GC)
+                       guint8 *buf [1];
+
+                       arm_ldrx (code, ARMREG_IP1, ins->sreg1, 0);
+                       /* Call it if it is non-null */
+                       buf [0] = code;
+                       arm_cbzx (code, ARMREG_IP1, 0);
+                       code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, "mono_threads_state_poll");
+                       mono_arm_patch (buf [0], code, MONO_R_ARM64_CBZ);
+#endif
+                       break;
+               }
+
+               default:
+                       g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
+                       g_assert_not_reached ();
+               }
+
+               if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
+                       g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %d)",
+                                  mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
+                       g_assert_not_reached ();
+               }
+       }
+
+       /*
+        * If the compiled code size is larger than the bcc displacement (19 bits signed),
+        * insert branch islands between/inside basic blocks.
+        */
+       if (cfg->arch.cond_branch_islands)
+               code = emit_branch_island (cfg, code, start_offset);
+
+       cfg->code_len = code - cfg->native_code;
+}
+
+static guint8*
+emit_move_args (MonoCompile *cfg, guint8 *code)
+{
+       MonoInst *ins;
+       CallInfo *cinfo;
+       ArgInfo *ainfo;
+       int i, part;
+
+       cinfo = cfg->arch.cinfo;
+       g_assert (cinfo);
+       for (i = 0; i < cinfo->nargs; ++i) {
+               ainfo = cinfo->args + i;
+               ins = cfg->args [i];
+
+               if (ins->opcode == OP_REGVAR) {
+                       switch (ainfo->storage) {
+                       case ArgInIReg:
+                               arm_movx (code, ins->dreg, ainfo->reg);
+                               break;
+                       case ArgOnStack:
+                               switch (ainfo->slot_size) {
+                               case 1:
+                                       if (ainfo->sign)
+                                               code = emit_ldrsbx (code, ins->dreg, cfg->arch.args_reg, ainfo->offset);
+                                       else
+                                               code = emit_ldrb (code, ins->dreg, cfg->arch.args_reg, ainfo->offset);
+                                       break;
+                               case 2:
+                                       if (ainfo->sign)
+                                               code = emit_ldrshx (code, ins->dreg, cfg->arch.args_reg, ainfo->offset);
+                                       else
+                                               code = emit_ldrh (code, ins->dreg, cfg->arch.args_reg, ainfo->offset);
+                                       break;
+                               case 4:
+                                       if (ainfo->sign)
+                                               code = emit_ldrswx (code, ins->dreg, cfg->arch.args_reg, ainfo->offset);
+                                       else
+                                               code = emit_ldrw (code, ins->dreg, cfg->arch.args_reg, ainfo->offset);
+                                       break;
+                               default:
+                                       code = emit_ldrx (code, ins->dreg, cfg->arch.args_reg, ainfo->offset);
+                                       break;
+                               }
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                               break;
+                       }
+               } else {
+                       if (ainfo->storage != ArgVtypeByRef && ainfo->storage != ArgVtypeByRefOnStack)
+                               g_assert (ins->opcode == OP_REGOFFSET);
+
+                       switch (ainfo->storage) {
+                       case ArgInIReg:
+                               /* Stack slots for arguments have size 8 */
+                               code = emit_strx (code, ainfo->reg, ins->inst_basereg, ins->inst_offset);
+                               break;
+                       case ArgInFReg:
+                               code = emit_strfpx (code, ainfo->reg, ins->inst_basereg, ins->inst_offset);
+                               break;
+                       case ArgInFRegR4:
+                               code = emit_strfpw (code, ainfo->reg, ins->inst_basereg, ins->inst_offset);
+                               break;
+                       case ArgOnStack:
+                       case ArgOnStackR4:
+                       case ArgOnStackR8:
+                       case ArgVtypeByRefOnStack:
+                       case ArgVtypeOnStack:
+                               break;
+                       case ArgVtypeByRef: {
+                               MonoInst *addr_arg = ins->inst_left;
+
+                               if (ainfo->gsharedvt) {
+                                       g_assert (ins->opcode == OP_GSHAREDVT_ARG_REGOFFSET);
+                                       arm_strx (code, ainfo->reg, ins->inst_basereg, ins->inst_offset);
+                               } else {
+                                       g_assert (ins->opcode == OP_VTARG_ADDR);
+                                       g_assert (addr_arg->opcode == OP_REGOFFSET);
+                                       arm_strx (code, ainfo->reg, addr_arg->inst_basereg, addr_arg->inst_offset);
+                               }
+                               break;
+                       }
+                       case ArgVtypeInIRegs:
+                               for (part = 0; part < ainfo->nregs; part ++) {
+                                       code = emit_strx (code, ainfo->reg + part, ins->inst_basereg, ins->inst_offset + (part * 8));
+                               }
+                               break;
+                       case ArgHFA:
+                               for (part = 0; part < ainfo->nregs; part ++) {
+                                       if (ainfo->esize == 4)
+                                               code = emit_strfpw (code, ainfo->reg + part, ins->inst_basereg, ins->inst_offset + ainfo->foffsets [part]);
+                                       else
+                                               code = emit_strfpx (code, ainfo->reg + part, ins->inst_basereg, ins->inst_offset + ainfo->foffsets [part]);
+                               }
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                               break;
+                       }
+               }
+       }
+
+       return code;
+}
+
+/*
+ * emit_store_regarray:
+ *
+ *   Emit code to store the registers in REGS into the appropriate elements of
+ * the register array at BASEREG+OFFSET.
+ */
+static __attribute__((warn_unused_result)) guint8*
+emit_store_regarray (guint8 *code, guint64 regs, int basereg, int offset)
+{
+       int i;
+
+       for (i = 0; i < 32; ++i) {
+               if (regs & (1 << i)) {
+                       if (i + 1 < 32 && (regs & (1 << (i + 1))) && (i + 1 != ARMREG_SP)) {
+                               arm_stpx (code, i, i + 1, basereg, offset + (i * 8));
+                               i++;
+                       } else if (i == ARMREG_SP) {
+                               arm_movspx (code, ARMREG_IP1, ARMREG_SP);
+                               arm_strx (code, ARMREG_IP1, basereg, offset + (i * 8));
+                       } else {
+                               arm_strx (code, i, basereg, offset + (i * 8));
+                       }
+               }
+       }
+       return code;
+}
+
+/*
+ * emit_load_regarray:
+ *
+ *   Emit code to load the registers in REGS from the appropriate elements of
+ * the register array at BASEREG+OFFSET.
+ */
+static __attribute__((warn_unused_result)) guint8*
+emit_load_regarray (guint8 *code, guint64 regs, int basereg, int offset)
+{
+       int i;
+
+       for (i = 0; i < 32; ++i) {
+               if (regs & (1 << i)) {
+                       if ((regs & (1 << (i + 1))) && (i + 1 != ARMREG_SP)) {
+                               if (offset + (i * 8) < 500)
+                                       arm_ldpx (code, i, i + 1, basereg, offset + (i * 8));
+                               else {
+                                       code = emit_ldrx (code, i, basereg, offset + (i * 8));
+                                       code = emit_ldrx (code, i + 1, basereg, offset + ((i + 1) * 8));
+                               }
+                               i++;
+                       } else if (i == ARMREG_SP) {
+                               g_assert_not_reached ();
+                       } else {
+                               code = emit_ldrx (code, i, basereg, offset + (i * 8));
+                       }
+               }
+       }
+       return code;
+}
+
+/*
+ * emit_store_regset:
+ *
+ *   Emit code to store the registers in REGS into consecutive memory locations starting
+ * at BASEREG+OFFSET.
+ */
+static __attribute__((warn_unused_result)) guint8*
+emit_store_regset (guint8 *code, guint64 regs, int basereg, int offset)
+{
+       int i, pos;
+
+       pos = 0;
+       for (i = 0; i < 32; ++i) {
+               if (regs & (1 << i)) {
+                       if ((regs & (1 << (i + 1))) && (i + 1 != ARMREG_SP)) {
+                               arm_stpx (code, i, i + 1, basereg, offset + (pos * 8));
+                               i++;
+                               pos++;
+                       } else if (i == ARMREG_SP) {
+                               arm_movspx (code, ARMREG_IP1, ARMREG_SP);
+                               arm_strx (code, ARMREG_IP1, basereg, offset + (pos * 8));
+                       } else {
+                               arm_strx (code, i, basereg, offset + (pos * 8));
+                       }
+                       pos++;
+               }
+       }
+       return code;
+}
+
+/*
+ * emit_load_regset:
+ *
+ *   Emit code to load the registers in REGS from consecutive memory locations starting
+ * at BASEREG+OFFSET.
+ */
+static __attribute__((warn_unused_result)) guint8*
+emit_load_regset (guint8 *code, guint64 regs, int basereg, int offset)
+{
+       int i, pos;
+
+       pos = 0;
+       for (i = 0; i < 32; ++i) {
+               if (regs & (1 << i)) {
+                       if ((regs & (1 << (i + 1))) && (i + 1 != ARMREG_SP)) {
+                               arm_ldpx (code, i, i + 1, basereg, offset + (pos * 8));
+                               i++;
+                               pos++;
+                       } else if (i == ARMREG_SP) {
+                               g_assert_not_reached ();
+                       } else {
+                               arm_ldrx (code, i, basereg, offset + (pos * 8));
+                       }
+                       pos++;
+               }
+       }
+       return code;
+}
+
+__attribute__((warn_unused_result)) guint8*
+mono_arm_emit_load_regarray (guint8 *code, guint64 regs, int basereg, int offset)
+{
+       return emit_load_regarray (code, regs, basereg, offset);
+}
+
+__attribute__((warn_unused_result)) guint8*
+mono_arm_emit_store_regarray (guint8 *code, guint64 regs, int basereg, int offset)
+{
+       return emit_store_regarray (code, regs, basereg, offset);
+}
+
+__attribute__((warn_unused_result)) guint8*
+mono_arm_emit_store_regset (guint8 *code, guint64 regs, int basereg, int offset)
+{
+       return emit_store_regset (code, regs, basereg, offset);
+}
+
+/* Same as emit_store_regset, but emit unwind info too */
+/* CFA_OFFSET is the offset between the CFA and basereg */
+static __attribute__((warn_unused_result)) guint8*
+emit_store_regset_cfa (MonoCompile *cfg, guint8 *code, guint64 regs, int basereg, int offset, int cfa_offset, guint64 no_cfa_regset)
+{
+       int i, j, pos, nregs;
+       guint32 cfa_regset = regs & ~no_cfa_regset;
+
+       pos = 0;
+       for (i = 0; i < 32; ++i) {
+               nregs = 1;
+               if (regs & (1 << i)) {
+                       if ((regs & (1 << (i + 1))) && (i + 1 != ARMREG_SP)) {
+                               if (offset < 256) {
+                                       arm_stpx (code, i, i + 1, basereg, offset + (pos * 8));
+                               } else {
+                                       code = emit_strx (code, i, basereg, offset + (pos * 8));
+                                       code = emit_strx (code, i + 1, basereg, offset + (pos * 8) + 8);
+                               }
+                               nregs = 2;
+                       } else if (i == ARMREG_SP) {
+                               arm_movspx (code, ARMREG_IP1, ARMREG_SP);
+                               code = emit_strx (code, ARMREG_IP1, basereg, offset + (pos * 8));
+                       } else {
+                               code = emit_strx (code, i, basereg, offset + (pos * 8));
+                       }
+
+                       for (j = 0; j < nregs; ++j) {
+                               if (cfa_regset & (1 << (i + j)))
+                                       mono_emit_unwind_op_offset (cfg, code, i + j, (- cfa_offset) + offset + ((pos + j) * 8));
+                       }
+
+                       i += nregs - 1;
+                       pos += nregs;
+               }
+       }
+       return code;
+}
+
+/*
+ * emit_setup_lmf:
+ *
+ *   Emit code to initialize an LMF structure at LMF_OFFSET.
+ * Clobbers ip0/ip1.
+ */
+static guint8*
+emit_setup_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset, int cfa_offset)
+{
+       /*
+        * The LMF should contain all the state required to be able to reconstruct the machine state
+        * at the current point of execution. Since the LMF is only read during EH, only callee
+        * saved etc. registers need to be saved.
+        * FIXME: Save callee saved fp regs, JITted code doesn't use them, but native code does, and they
+        * need to be restored during EH.
+        */
+
+       /* pc */
+       arm_adrx (code, ARMREG_LR, code);
+       code = emit_strx (code, ARMREG_LR, ARMREG_FP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, pc));
+       /* gregs + fp + sp */
+       /* Don't emit unwind info for sp/fp, they are already handled in the prolog */
+       code = emit_store_regset_cfa (cfg, code, MONO_ARCH_LMF_REGS, ARMREG_FP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, gregs), cfa_offset, (1 << ARMREG_FP) | (1 << ARMREG_SP));
+
+       return code;
+}
+
+guint8 *
+mono_arch_emit_prolog (MonoCompile *cfg)
+{
+       MonoMethod *method = cfg->method;
+       MonoMethodSignature *sig;
+       MonoBasicBlock *bb;
+       guint8 *code;
+       int cfa_offset, max_offset;
+
+       sig = mono_method_signature (method);
+       cfg->code_size = 256 + sig->param_count * 64;
+       code = cfg->native_code = g_malloc (cfg->code_size);
+
+       /* This can be unaligned */
+       cfg->stack_offset = ALIGN_TO (cfg->stack_offset, MONO_ARCH_FRAME_ALIGNMENT);
+
+       /*
+        * - Setup frame
+        */
+       cfa_offset = 0;
+       mono_emit_unwind_op_def_cfa (cfg, code, ARMREG_SP, 0);
+
+       /* Setup frame */
+       if (arm_is_ldpx_imm (-cfg->stack_offset)) {
+               arm_stpx_pre (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, -cfg->stack_offset);
+       } else {
+               /* sp -= cfg->stack_offset */
+               /* This clobbers ip0/ip1 */
+               code = emit_subx_sp_imm (code, cfg->stack_offset);
+               arm_stpx (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, 0);
+       }
+       cfa_offset += cfg->stack_offset;
+       mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
+       mono_emit_unwind_op_offset (cfg, code, ARMREG_FP, (- cfa_offset) + 0);
+       mono_emit_unwind_op_offset (cfg, code, ARMREG_LR, (- cfa_offset) + 8);
+       arm_movspx (code, ARMREG_FP, ARMREG_SP);
+       mono_emit_unwind_op_def_cfa_reg (cfg, code, ARMREG_FP);
+       if (cfg->param_area) {
+               /* The param area is below the frame pointer */
+               code = emit_subx_sp_imm (code, cfg->param_area);
+       }
+
+       if (cfg->method->save_lmf) {
+               code = emit_setup_lmf (cfg, code, cfg->lmf_var->inst_offset, cfa_offset);
+       } else {
+               /* Save gregs */
+               code = emit_store_regset_cfa (cfg, code, MONO_ARCH_CALLEE_SAVED_REGS & cfg->used_int_regs, ARMREG_FP, cfg->arch.saved_gregs_offset, cfa_offset, 0);
+       }
+
+       /* Setup args reg */
+       if (cfg->arch.args_reg) {
+               /* The register was already saved above */
+               code = emit_addx_imm (code, cfg->arch.args_reg, ARMREG_FP, cfg->stack_offset);
+       }
+
+       /* Save return area addr received in R8 */
+       if (cfg->vret_addr) {
+               MonoInst *ins = cfg->vret_addr;
+
+               g_assert (ins->opcode == OP_REGOFFSET);
+               code = emit_strx (code, ARMREG_R8, ins->inst_basereg, ins->inst_offset);
+       }
+
+       /* Save mrgctx received in MONO_ARCH_RGCTX_REG */
+       if (cfg->rgctx_var) {
+               MonoInst *ins = cfg->rgctx_var;
+
+               g_assert (ins->opcode == OP_REGOFFSET);
+
+               code = emit_strx (code, MONO_ARCH_RGCTX_REG, ins->inst_basereg, ins->inst_offset); 
+       }
+               
+       /*
+        * Move arguments to their registers/stack locations.
+        */
+       code = emit_move_args (cfg, code);
+
+       /* Initialize seq_point_info_var */
+       if (cfg->arch.seq_point_info_var) {
+               MonoInst *ins = cfg->arch.seq_point_info_var;
+
+               /* Initialize the variable from a GOT slot */
+               code = emit_aotconst (cfg, code, ARMREG_IP0, MONO_PATCH_INFO_SEQ_POINT_INFO, cfg->method);
+               g_assert (ins->opcode == OP_REGOFFSET);
+               code = emit_strx (code, ARMREG_IP0, ins->inst_basereg, ins->inst_offset);
+
+               /* Initialize ss_tramp_var */
+               ins = cfg->arch.ss_tramp_var;
+               g_assert (ins->opcode == OP_REGOFFSET);
+
+               code = emit_ldrx (code, ARMREG_IP1, ARMREG_IP0, MONO_STRUCT_OFFSET (SeqPointInfo, ss_tramp_addr));
+               code = emit_strx (code, ARMREG_IP1, ins->inst_basereg, ins->inst_offset);
+       } else {
+               MonoInst *ins;
+
+               if (cfg->arch.ss_tramp_var) {
+                       /* Initialize ss_tramp_var */
+                       ins = cfg->arch.ss_tramp_var;
+                       g_assert (ins->opcode == OP_REGOFFSET);
+
+                       code = emit_imm64 (code, ARMREG_IP0, (guint64)&ss_trampoline);
+                       code = emit_strx (code, ARMREG_IP0, ins->inst_basereg, ins->inst_offset);
+               }
+
+               if (cfg->arch.bp_tramp_var) {
+                       /* Initialize bp_tramp_var */
+                       ins = cfg->arch.bp_tramp_var;
+                       g_assert (ins->opcode == OP_REGOFFSET);
+
+                       code = emit_imm64 (code, ARMREG_IP0, (guint64)bp_trampoline);
+                       code = emit_strx (code, ARMREG_IP0, ins->inst_basereg, ins->inst_offset);
+               }
+       }
+
+       max_offset = 0;
+       if (cfg->opt & MONO_OPT_BRANCH) {
+               for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+                       MonoInst *ins;
+                       bb->max_offset = max_offset;
+
+                       MONO_BB_FOR_EACH_INS (bb, ins) {
+                               max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
+                       }
+               }
+       }
+       if (max_offset > 0x3ffff * 4)
+               cfg->arch.cond_branch_islands = TRUE;
+
+       return code;
+}
+
+static guint8*
+realloc_code (MonoCompile *cfg, int size)
+{
+       while (cfg->code_len + size > (cfg->code_size - 16)) {
+               cfg->code_size *= 2;
+               cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
+               cfg->stat_code_reallocs++;
+       }
+       return cfg->native_code + cfg->code_len;
+}
+
+void
+mono_arch_emit_epilog (MonoCompile *cfg)
+{
+       CallInfo *cinfo;
+       int max_epilog_size;
+       guint8 *code;
+       int i;
+
+       max_epilog_size = 16 + 20*4;
+       code = realloc_code (cfg, max_epilog_size);
+
+       if (cfg->method->save_lmf) {
+               code = mono_arm_emit_load_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS & cfg->used_int_regs, ARMREG_FP, cfg->lmf_var->inst_offset + MONO_STRUCT_OFFSET (MonoLMF, gregs) - (MONO_ARCH_FIRST_LMF_REG * 8));
+       } else {
+               /* Restore gregs */
+               code = emit_load_regset (code, MONO_ARCH_CALLEE_SAVED_REGS & cfg->used_int_regs, ARMREG_FP, cfg->arch.saved_gregs_offset);
+       }
+
+       /* Load returned vtypes into registers if needed */
+       cinfo = cfg->arch.cinfo;
+       switch (cinfo->ret.storage) {
+       case ArgVtypeInIRegs: {
+               MonoInst *ins = cfg->ret;
+
+               for (i = 0; i < cinfo->ret.nregs; ++i)
+                       code = emit_ldrx (code, cinfo->ret.reg + i, ins->inst_basereg, ins->inst_offset + (i * 8));
+               break;
+       }
+       case ArgHFA: {
+               MonoInst *ins = cfg->ret;
+
+               for (i = 0; i < cinfo->ret.nregs; ++i) {
+                       if (cinfo->ret.esize == 4)
+                               code = emit_ldrfpw (code, cinfo->ret.reg + i, ins->inst_basereg, ins->inst_offset + cinfo->ret.foffsets [i]);
+                       else
+                               code = emit_ldrfpx (code, cinfo->ret.reg + i, ins->inst_basereg, ins->inst_offset + cinfo->ret.foffsets [i]);
+               }
+               break;
+       }
+       default:
+               break;
+       }
+
+       /* Destroy frame */
+       code = mono_arm_emit_destroy_frame (code, cfg->stack_offset, ((1 << ARMREG_IP0) | (1 << ARMREG_IP1)));
+
+       arm_retx (code, ARMREG_LR);
+
+       g_assert (code - (cfg->native_code + cfg->code_len) < max_epilog_size);
+
+       cfg->code_len = code - cfg->native_code;
+}
+
+void
+mono_arch_emit_exceptions (MonoCompile *cfg)
+{
+       MonoJumpInfo *ji;
+       MonoClass *exc_class;
+       guint8 *code, *ip;
+       guint8* exc_throw_pos [MONO_EXC_INTRINS_NUM];
+       guint8 exc_throw_found [MONO_EXC_INTRINS_NUM];
+       int i, id, size = 0;
+
+       for (i = 0; i < MONO_EXC_INTRINS_NUM; i++) {
+               exc_throw_pos [i] = NULL;
+               exc_throw_found [i] = 0;
+       }
+
+       for (ji = cfg->patch_info; ji; ji = ji->next) {
+               if (ji->type == MONO_PATCH_INFO_EXC) {
+                       i = mini_exception_id_by_name (ji->data.target);
+                       if (!exc_throw_found [i]) {
+                               size += 32;
+                               exc_throw_found [i] = TRUE;
+                       }
+               }
+       }
+
+       code = realloc_code (cfg, size);
+
+       /* Emit code to raise corlib exceptions */
+       for (ji = cfg->patch_info; ji; ji = ji->next) {
+               if (ji->type != MONO_PATCH_INFO_EXC)
+                       continue;
+
+               ip = cfg->native_code + ji->ip.i;
+
+               id = mini_exception_id_by_name (ji->data.target);
+
+               if (exc_throw_pos [id]) {
+                       /* ip points to the bcc () in OP_COND_EXC_... */
+                       arm_patch_rel (ip, exc_throw_pos [id], ji->relocation);
+                       ji->type = MONO_PATCH_INFO_NONE;
+                       continue;
+               }
+
+               exc_throw_pos [id] = code;
+               arm_patch_rel (ip, code, ji->relocation);
+
+               /* We are being branched to from the code generated by emit_cond_exc (), the pc is in ip1 */
+
+               /* r0 = type token */
+               exc_class = mono_class_load_from_name (mono_defaults.corlib, "System", ji->data.name);
+               code = emit_imm (code, ARMREG_R0, exc_class->type_token - MONO_TOKEN_TYPE_DEF);
+               /* r1 = throw ip */
+               arm_movx (code, ARMREG_R1, ARMREG_IP1);
+               /* Branch to the corlib exception throwing trampoline */
+               ji->ip.i = code - cfg->native_code;
+               ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
+               ji->data.name = "mono_arch_throw_corlib_exception";
+               ji->relocation = MONO_R_ARM64_BL;
+               arm_bl (code, 0);
+               cfg->thunk_area += THUNK_SIZE;
+       }
+
+       cfg->code_len = code - cfg->native_code;
+
+       g_assert (cfg->code_len < cfg->code_size);
+}
+
+MonoInst*
+mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
+{
+       return NULL;
+}
+
+gboolean
+mono_arch_print_tree (MonoInst *tree, int arity)
+{
+       return FALSE;
+}
+
+guint32
+mono_arch_get_patch_offset (guint8 *code)
+{
+       return 0;
+}
+
+gpointer
+mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+                                                  gpointer fail_tramp)
+{
+       int i, buf_len, imt_reg;
+       guint8 *buf, *code;
+
+#if DEBUG_IMT
+       printf ("building IMT thunk for class %s %s entries %d code size %d code at %p end %p vtable %p\n", vtable->klass->name_space, vtable->klass->name, count, size, start, ((guint8*)start) + size, vtable);
+       for (i = 0; i < count; ++i) {
+               MonoIMTCheckItem *item = imt_entries [i];
+               printf ("method %d (%p) %s vtable slot %p is_equals %d chunk size %d\n", i, item->key, item->key->name, &vtable->vtable [item->value.vtable_slot], item->is_equals, item->chunk_size);
+       }
+#endif
+
+       buf_len = 0;
+       for (i = 0; i < count; ++i) {
+               MonoIMTCheckItem *item = imt_entries [i];
+               if (item->is_equals) {
+                       gboolean fail_case = !item->check_target_idx && fail_tramp;
+
+                       if (item->check_target_idx || fail_case) {
+                               if (!item->compare_done || fail_case) {
+                                       buf_len += 4 * 4 + 4;
+                               }
+                               buf_len += 4;
+                               if (item->has_target_code) {
+                                       buf_len += 5 * 4;
+                               } else {
+                                       buf_len += 6 * 4;
+                               }
+                               if (fail_case) {
+                                       buf_len += 5 * 4;
+                               }
+                       } else {
+                               buf_len += 6 * 4;
+                       }
+               } else {
+                       buf_len += 6 * 4;
+               }
+       }
+
+       if (fail_tramp)
+               buf = mono_method_alloc_generic_virtual_thunk (domain, buf_len);
+       else
+               buf = mono_domain_code_reserve (domain, buf_len);
+       code = buf;
+
+       /*
+        * We are called by JITted code, which passes in the IMT argument in
+        * MONO_ARCH_RGCTX_REG (r27). We need to preserve all caller saved regs
+        * except ip0/ip1.
+        */
+       imt_reg = MONO_ARCH_RGCTX_REG;
+       for (i = 0; i < count; ++i) {
+               MonoIMTCheckItem *item = imt_entries [i];
+
+               item->code_target = code;
+
+               if (item->is_equals) {
+                       /*
+                        * Check the imt argument against item->key, if equals, jump to either
+                        * item->value.target_code or to vtable [item->value.vtable_slot].
+                        * If fail_tramp is set, jump to it if not-equals.
+                        */
+                       gboolean fail_case = !item->check_target_idx && fail_tramp;
+
+                       if (item->check_target_idx || fail_case) {
+                               /* Compare imt_reg with item->key */
+                               if (!item->compare_done || fail_case) {
+                                       // FIXME: Optimize this
+                                       code = emit_imm64 (code, ARMREG_IP0, (guint64)item->key);
+                                       arm_cmpx (code, imt_reg, ARMREG_IP0);
+                               }
+                               item->jmp_code = code;
+                               arm_bcc (code, ARMCOND_NE, 0);
+                               /* Jump to target if equals */
+                               if (item->has_target_code) {
+                                       code = emit_imm64 (code, ARMREG_IP0, (guint64)item->value.target_code);
+                                       arm_brx (code, ARMREG_IP0);
+                               } else {
+                                       guint64 imm = (guint64)&(vtable->vtable [item->value.vtable_slot]);
+
+                                       code = emit_imm64 (code, ARMREG_IP0, imm);
+                                       arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0);
+                                       arm_brx (code, ARMREG_IP0);
+                               }
+
+                               if (fail_case) {
+                                       arm_patch_rel (item->jmp_code, code, MONO_R_ARM64_BCC);
+                                       item->jmp_code = NULL;
+                                       code = emit_imm64 (code, ARMREG_IP0, (guint64)fail_tramp);
+                                       arm_brx (code, ARMREG_IP0);
+                               }
+                       } else {
+                               guint64 imm = (guint64)&(vtable->vtable [item->value.vtable_slot]);
+
+                               code = emit_imm64 (code, ARMREG_IP0, imm);
+                               arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0);
+                               arm_brx (code, ARMREG_IP0);
+                       }
+               } else {
+                       code = emit_imm64 (code, ARMREG_IP0, (guint64)item->key);
+                       arm_cmpx (code, imt_reg, ARMREG_IP0);
+                       item->jmp_code = code;
+                       arm_bcc (code, ARMCOND_HS, 0);
+               }
+       }
+       /* Patch the branches */
+       for (i = 0; i < count; ++i) {
+               MonoIMTCheckItem *item = imt_entries [i];
+               if (item->jmp_code && item->check_target_idx)
+                       arm_patch_rel (item->jmp_code, imt_entries [item->check_target_idx]->code_target, MONO_R_ARM64_BCC);
+       }
+
+       g_assert ((code - buf) < buf_len);
+
+       mono_arch_flush_icache (buf, code - buf);
+
+       return buf;
+}
+
+GSList *
+mono_arch_get_trampolines (gboolean aot)
+{
+       return mono_arm_get_exception_trampolines (aot);
+}
+
+#else /* DISABLE_JIT */
+
+gpointer
+mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+                                                  gpointer fail_tramp)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+#endif /* !DISABLE_JIT */
+
+#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
+
+void
+mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
+{
+       guint8 *code = ip;
+       guint32 native_offset = ip - (guint8*)ji->code_start;
+
+       if (ji->from_aot) {
+               SeqPointInfo *info = mono_arch_get_seq_point_info (mono_domain_get (), ji->code_start);
+
+               g_assert (native_offset % 4 == 0);
+               g_assert (info->bp_addrs [native_offset / 4] == 0);
+               info->bp_addrs [native_offset / 4] = mini_get_breakpoint_trampoline ();
+       } else {
+               /* ip points to an ldrx */
+               code += 4;
+               arm_blrx (code, ARMREG_IP0);
+               mono_arch_flush_icache (ip, code - ip);
+       }
+}
+
+void
+mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
+{
+       guint8 *code = ip;
+
+       if (ji->from_aot) {
+               guint32 native_offset = ip - (guint8*)ji->code_start;
+               SeqPointInfo *info = mono_arch_get_seq_point_info (mono_domain_get (), ji->code_start);
+
+               g_assert (native_offset % 4 == 0);
+               info->bp_addrs [native_offset / 4] = NULL;
+       } else {
+               /* ip points to an ldrx */
+               code += 4;
+               arm_nop (code);
+               mono_arch_flush_icache (ip, code - ip);
+       }
+}
+
+void
+mono_arch_start_single_stepping (void)
+{
+       ss_trampoline = mini_get_single_step_trampoline ();
+}
+
+void
+mono_arch_stop_single_stepping (void)
+{
+       ss_trampoline = NULL;
+}
+
+gboolean
+mono_arch_is_single_step_event (void *info, void *sigctx)
+{
+       /* We use soft breakpoints on arm64 */
+       return FALSE;
+}
+
+gboolean
+mono_arch_is_breakpoint_event (void *info, void *sigctx)
+{
+       /* We use soft breakpoints on arm64 */
+       return FALSE;
+}
+
+void
+mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
+{
+       g_assert_not_reached ();
+}
+
+void
+mono_arch_skip_single_step (MonoContext *ctx)
+{
+       g_assert_not_reached ();
+}
+
+gpointer
+mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
+{
+       SeqPointInfo *info;
+       MonoJitInfo *ji;
+
+       // FIXME: Add a free function
+
+       mono_domain_lock (domain);
+       info = g_hash_table_lookup (domain_jit_info (domain)->arch_seq_points, 
+                                                               code);
+       mono_domain_unlock (domain);
+
+       if (!info) {
+               ji = mono_jit_info_table_find (domain, (char*)code);
+               g_assert (ji);
+
+               info = g_malloc0 (sizeof (SeqPointInfo) + (ji->code_size / 4) * sizeof(guint8*));
+
+               info->ss_tramp_addr = &ss_trampoline;
+
+               mono_domain_lock (domain);
+               g_hash_table_insert (domain_jit_info (domain)->arch_seq_points,
+                                                        code, info);
+               mono_domain_unlock (domain);
+       }
+
+       return info;
+}
+
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+       ext->lmf.previous_lmf = prev_lmf;
+       /* Mark that this is a MonoLMFExt */
+       ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+       ext->lmf.gregs [MONO_ARCH_LMF_REG_SP] = (gssize)ext;
+}
+
+#endif /* MONO_ARCH_SOFT_DEBUG_SUPPORTED */
+
+gboolean
+mono_arch_opcode_supported (int opcode)
+{
+       switch (opcode) {
+       case OP_ATOMIC_ADD_I4:
+       case OP_ATOMIC_ADD_I8:
+       case OP_ATOMIC_EXCHANGE_I4:
+       case OP_ATOMIC_EXCHANGE_I8:
+       case OP_ATOMIC_CAS_I4:
+       case OP_ATOMIC_CAS_I8:
+       case OP_ATOMIC_LOAD_I1:
+       case OP_ATOMIC_LOAD_I2:
+       case OP_ATOMIC_LOAD_I4:
+       case OP_ATOMIC_LOAD_I8:
+       case OP_ATOMIC_LOAD_U1:
+       case OP_ATOMIC_LOAD_U2:
+       case OP_ATOMIC_LOAD_U4:
+       case OP_ATOMIC_LOAD_U8:
+       case OP_ATOMIC_LOAD_R4:
+       case OP_ATOMIC_LOAD_R8:
+       case OP_ATOMIC_STORE_I1:
+       case OP_ATOMIC_STORE_I2:
+       case OP_ATOMIC_STORE_I4:
+       case OP_ATOMIC_STORE_I8:
+       case OP_ATOMIC_STORE_U1:
+       case OP_ATOMIC_STORE_U2:
+       case OP_ATOMIC_STORE_U4:
+       case OP_ATOMIC_STORE_U8:
+       case OP_ATOMIC_STORE_R4:
+       case OP_ATOMIC_STORE_R8:
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}
+
+CallInfo*
+mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
+{
+       return get_call_info (mp, sig);
+}
+
index a963c75d51c94066c43d482262b48ff4e9eb2b52..154859e7165a50298f3d43ac989abaebc062bd80 100644 (file)
@@ -1 +1,268 @@
-#include "../../../mono-extensions/mono/mini/mini-arm64.h"
+/*
+ * mini-arm64.h
+ *
+ * Copyright 2013 Xamarin Inc
+ *
+ * Based on mini-arm.h:
+ *
+ * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#ifndef __MONO_MINI_ARM64_H__
+#define __MONO_MINI_ARM64_H__
+
+#include <mono/arch/arm64/arm64-codegen.h>
+#include <mono/mini/mini-arm64-gsharedvt.h>
+
+#define MONO_ARCH_CPU_SPEC mono_arm64_cpu_desc
+
+#define MONO_MAX_IREGS 32
+#define MONO_MAX_FREGS 32
+
+#define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->regs [0] = (gsize)exc; } while (0)
+
+#define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do {     \
+               MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0));       \
+               MONO_CONTEXT_SET_SP ((ctx), __builtin_frame_address (0));       \
+               MONO_CONTEXT_SET_IP ((ctx), (func));    \
+       } while (0)
+
+#define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
+
+/* Parameters used by the register allocator */
+/* r0..r7, r9..r14 (r15 is the imt/rgctx reg) */
+#define MONO_ARCH_CALLEE_REGS 0xfeff
+/* r19..r28 */
+#define MONO_ARCH_CALLEE_SAVED_REGS (0x3ff << 19)
+
+/* v16/v17 is reserved for a scratch reg */
+#define MONO_ARCH_CALLEE_FREGS 0xfffc00ff
+/* v8..v15 */
+#define MONO_ARCH_CALLEE_SAVED_FREGS 0xff00
+
+#define MONO_ARCH_USE_FPSTACK FALSE
+#define MONO_ARCH_FPSTACK_SIZE 0
+
+#define MONO_ARCH_INST_SREG2_MASK(ins) (0)
+
+#define MONO_ARCH_INST_FIXED_REG(desc) ((desc) == 'a' ? ARMREG_R0 : -1)
+
+#define MONO_ARCH_INST_IS_REGPAIR(desc) (0)
+
+#define MONO_ARCH_INST_IS_FLOAT(desc) ((desc) == 'f')
+
+#define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (-1)
+
+#define MONO_ARCH_USE_FPSTACK FALSE
+
+#define MONO_ARCH_FRAME_ALIGNMENT 16
+
+#define MONO_ARCH_CODE_ALIGNMENT 32
+
+/* callee saved regs + fp + sp */
+#define MONO_ARCH_LMF_REGS ((0x3ff << 19) | (1 << ARMREG_FP) | (1 << ARMREG_SP))
+#define MONO_ARCH_NUM_LMF_REGS (10 + 2)
+#define MONO_ARCH_FIRST_LMF_REG ARMREG_R19
+#define MONO_ARCH_LMF_REG_FP 10
+#define MONO_ARCH_LMF_REG_SP 11
+
+struct MonoLMF {
+       /* 
+        * If the second lowest bit is set to 1, then this is a MonoLMFExt structure, and
+        * the other fields are not valid.
+        */
+       gpointer    previous_lmf;
+       gpointer    lmf_addr;
+       mgreg_t    pc;
+       mgreg_t    gregs [MONO_ARCH_NUM_LMF_REGS];
+};
+
+/* Structure used by the sequence points in AOTed code */
+typedef struct {
+       gpointer ss_trigger_page;
+       gpointer bp_trigger_page;
+       gpointer ss_tramp_addr;
+       guint8* bp_addrs [MONO_ZERO_LEN_ARRAY];
+} SeqPointInfo;
+
+#define PARAM_REGS 8
+#define FP_PARAM_REGS 8
+
+#define DYN_CALL_STACK_ARGS 6
+
+typedef struct {
+       /* The +1 is for r8 */
+       mgreg_t regs [PARAM_REGS + 1 + DYN_CALL_STACK_ARGS];
+       mgreg_t res, res2;
+       guint8 *ret;
+       double fpregs [FP_PARAM_REGS];
+       int n_fpargs, n_fpret;
+       guint8 buffer [256];
+} DynCallArgs;
+
+typedef struct {
+       gpointer cinfo;
+       int saved_gregs_offset;
+       /* Points to arguments received on the stack */
+       int args_reg;
+       gboolean cond_branch_islands;
+       gpointer vret_addr_loc;
+       gpointer seq_point_info_var;
+       gpointer ss_tramp_var;
+       gpointer bp_tramp_var;
+       guint8 *thunks;
+       int thunks_size;
+} MonoCompileArch;
+
+#define MONO_ARCH_EMULATE_FREM 1
+#define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS 1
+#define MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS 1
+#define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS 1
+#define MONO_ARCH_NEED_DIV_CHECK 1
+#define MONO_ARCH_EMULATE_MUL_OVF 1
+#define MONO_ARCH_HAVE_IMT 1
+#define MONO_ARCH_HAVE_OP_TAIL_CALL 1
+#define MONO_ARCH_THIS_AS_FIRST_ARG 1
+#define MONO_ARCH_RGCTX_REG ARMREG_R15
+#define MONO_ARCH_IMT_REG MONO_ARCH_RGCTX_REG
+#define MONO_ARCH_VTABLE_REG ARMREG_R0
+#define MONO_ARCH_EXC_REG ARMREG_R0
+#define MONO_ARCH_HAVE_XP_UNWIND 1
+#define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
+#define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
+#define MONO_ARCH_USE_SIGACTION 1
+#define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
+#define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1
+#define MONO_ARCH_GSHARED_SUPPORTED 1
+#define MONO_ARCH_AOT_SUPPORTED 1
+#define MONO_ARCH_LLVM_SUPPORTED 1
+#define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
+#define MONO_ARCH_HAVE_EXCEPTIONS_INIT 1
+#define MONO_ARCH_HAVE_GET_TRAMPOLINES 1
+#define MONO_ARCH_DYN_CALL_SUPPORTED 1
+#define MONO_ARCH_DYN_CALL_PARAM_AREA (DYN_CALL_STACK_ARGS * 8)
+#define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
+#ifndef TARGET_ANDROID
+#define MONO_ARCH_GSHAREDVT_SUPPORTED 1
+#endif
+#define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
+#define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1
+#define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE 1
+#ifndef MONO_CROSS_COMPILE
+#define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
+#endif
+#define MONO_ARCH_HAVE_OP_GET_EX_OBJ 1
+#define MONO_ARCH_HAVE_OBJC_GET_SELECTOR 1
+#define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1
+#define MONO_ARCH_HAVE_PATCH_CODE_NEW 1
+#define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT 1
+#define MONO_ARCH_HAVE_OPCODE_NEEDS_EMULATION 1
+#define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
+
+#ifdef TARGET_IOS
+
+#define MONO_ARCH_REDZONE_SIZE 128
+
+#else
+
+#define MONO_ARCH_REDZONE_SIZE 0
+#if !defined(__PIC__)
+#define MONO_ARCH_HAVE_TLS_GET 1
+#endif
+#define MONO_ARCH_HAVE_TLS_GET_REG 1
+
+#endif
+
+#if defined(TARGET_APPLETVOS)
+#define MONO_ARCH_HAVE_UNWIND_BACKTRACE 1
+#endif
+
+/* Relocations */
+#define MONO_R_ARM64_B 1
+#define MONO_R_ARM64_BCC 2
+#define MONO_R_ARM64_IMM 3
+#define MONO_R_ARM64_BL 4
+#define MONO_R_ARM64_BL_SHORT 5
+#define MONO_R_ARM64_CBZ 6
+
+
+typedef enum {
+       ArgInIReg,
+       ArgInFReg,
+       ArgInFRegR4,
+       ArgOnStack,
+       ArgOnStackR8,
+       ArgOnStackR4,
+       /*
+        * Vtype passed in consecutive int registers.
+        * ainfo->reg is the firs register,
+        * ainfo->nregs is the number of registers,
+        * ainfo->size is the size of the structure.
+        */
+       ArgVtypeInIRegs,
+       ArgVtypeByRef,
+       ArgVtypeByRefOnStack,
+       ArgVtypeOnStack,
+       ArgHFA,
+       ArgNone
+} ArgStorage;
+
+typedef struct {
+       ArgStorage storage;
+       int reg;
+       /* ArgOnStack */
+       int offset;
+       /* ArgVtypeInIRegs/ArgHFA */
+       int nregs, size;
+       /* ArgHFA */
+       int esize;
+       /* ArgHFA */
+       /* The offsets of the float values inside the arg */
+       guint16 foffsets [4];
+       /* ArgOnStack */
+       int slot_size;
+       /* hfa */
+       int nfregs_to_skip;
+       gboolean sign;
+       gboolean gsharedvt;
+       gboolean hfa;
+} ArgInfo;
+
+typedef struct {
+       int nargs;
+       int gr, fr, stack_usage;
+       ArgInfo ret;
+       ArgInfo sig_cookie;
+       ArgInfo args [1];
+} CallInfo;
+
+
+guint8* mono_arm_emit_imm64 (guint8 *code, int dreg, gint64 imm);
+
+guint8* mono_arm_emit_ldrx (guint8 *code, int rt, int rn, int imm);
+
+guint8* mono_arm_emit_destroy_frame (guint8 *code, int stack_offset, guint64 temp_regs);
+
+guint8* mono_arm_emit_store_regset (guint8 *code, guint64 regs, int basereg, int offset);
+
+guint8* mono_arm_emit_store_regarray (guint8 *code, guint64 regs, int basereg, int offset);
+
+guint8* mono_arm_emit_load_regarray (guint8 *code, guint64 regs, int basereg, int offset);
+
+/* MonoJumpInfo **ji */
+guint8* mono_arm_emit_aotconst (gpointer ji, guint8 *code, guint8 *code_start, int dreg, guint32 patch_type, gconstpointer data);
+
+void mono_arm_patch (guint8 *code, guint8 *target, int relocation);
+
+void mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow);
+
+void mono_arm_gsharedvt_init (void);
+
+GSList* mono_arm_get_exception_trampolines (gboolean aot);
+
+void mono_arm_resume_unwind (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow);
+
+CallInfo* mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig);
+
+#endif /* __MONO_MINI_ARM64_H__ */
index dede99f3ee9abba38dbfc55a6fdfafdd2e823ee9..28e04d6d6288388a8ca141a481b7262cd1b7ea5a 100644 (file)
@@ -1,13 +1,93 @@
 #include "config.h"
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/mini/mini-cross-helpers.c"
+#include <stdio.h>
+
+#include "config.h"
+
+#include "mini.h"
+#include "tasklets.h"
+#include <mono/metadata/abi-details.h>
+
+void
+mono_dump_metadata_offsets (void);
+
+void
+mono_metadata_cross_helpers_run (void);
+
+
+static void
+mono_dump_jit_offsets (void)
+{
+#ifdef USED_CROSS_COMPILER_OFFSETS
+       g_print ("#error not using native offsets\n");
 #else
+       mono_dump_metadata_offsets ();
+
+       g_print ("#ifndef DISABLE_JIT_OFFSETS\n");
+       g_print ("#define USED_CROSS_COMPILER_OFFSETS\n");
+#define DISABLE_METADATA_OFFSETS
+#define DECL_OFFSET2(struct,field,offset) this_should_not_happen
+#define DECL_ALIGN2(type,size) this_should_not_happen
 
-void mono_cross_helpers_run (void);
+#define DECL_OFFSET(struct,field) g_print ("DECL_OFFSET2(%s,%s,%d)\n", #struct, #field, (int)MONO_STRUCT_OFFSET (struct, field));
+#define DECL_ALIGN(type)
+#define DECL_SIZE2(type,size) this_should_not_happen
+#define DECL_SIZE(type)
+#include <mono/metadata/object-offsets.h>
+
+       g_print ("#endif //disable jit check\n");
+       g_print ("#endif //cross compiler checks\n");
+       g_print ("#endif //gc check\n");
+       g_print ("#endif //os check\n");
+       g_print ("#endif //arch check\n");
+       g_print ("#endif //USED_CROSS_COMPILER_OFFSETS check\n");
+#endif
+}
 
 void
 mono_cross_helpers_run (void)
 {
-}
+#if defined (HAS_CROSS_COMPILER_OFFSETS) && !defined (MONO_CROSS_COMPILE)
+       gboolean is_broken = FALSE;
+#endif
+
+#ifndef USED_CROSS_COMPILER_OFFSETS
+       if (g_getenv ("DUMP_CROSS_OFFSETS"))
+               mono_dump_jit_offsets ();
 #endif
+       
+#if defined (HAS_CROSS_COMPILER_OFFSETS) && !defined (MONO_CROSS_COMPILE)
+       mono_metadata_cross_helpers_run ();
+
+#define DISABLE_METADATA_OFFSETS
+#define USE_CROSS_COMPILE_OFFSETS
+#define DECL_OFFSET(struct,field) this_should_not_happen_for_cross_fields
+#define DECL_OFFSET2(struct,field,offset) \
+        if ((int)G_STRUCT_OFFSET (struct, field) != offset) { \
+               g_print (#struct ":" #field " invalid struct offset %d (expected %d)\n",        \
+                       offset, \
+                       (int)G_STRUCT_OFFSET (struct, field));  \
+               is_broken = TRUE;       \
+       }
+#define DECL_ALIGN(name,type) this_should_not_happen_for_cross_align
+#define DECL_ALIGN2(name,size) \
+        if (MONO_ALIGN_ ## name != size) { \
+               g_print (#name ": invalid alignment %d (expected %d)\n",        \
+               size,   \
+               MONO_ALIGN_ ## name);   \
+               is_broken = TRUE;       \
+       }
+#define DECL_SIZE(type) this_should_not_happen_for_cross_size
+#define DECL_SIZE2(name,size) \
+        if (MONO_SIZEOF_ ## name != size) { \
+               g_print (#name ": invalid size %d (expected %d)\n",     \
+               size,   \
+               MONO_SIZEOF_ ## name);  \
+               is_broken = TRUE;       \
+       }
+
+#include <mono/metadata/object-offsets.h>
+
+       g_assert (!is_broken);
+#endif
+}
index 659075cc30a7f7297017b408d8df42eaf82f72c6..4f8fbcf65853f668acdb0cc1be9140ae552f395a 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  *
- * See LICENSE for licensing information.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <signal.h>
diff --git a/mono/mini/mini-exceptions-native-unwinder.c b/mono/mini/mini-exceptions-native-unwinder.c
new file mode 100644 (file)
index 0000000..64e0e39
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * mini-exceptions-native-unwinder.c: libcorkscrew-based native unwinder
+ *
+ * Authors:
+ *   Alex Rønne Petersen (alexrp@xamarin.com)
+ *
+ * Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <config.h>
+
+/*
+ * Attempt to handle native SIGSEGVs with libunwind or libcorkscrew.
+ */
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#include <mono/utils/mono-signal-handler.h>
+#include "mini.h"
+
+#if defined (PLATFORM_ANDROID)
+
+#include <signal.h>
+#include <sys/types.h>
+#include <mono/utils/mono-dl.h>
+
+#define UNW_LOCAL_ONLY
+#undef _U /* ctype.h apparently defines this and it screws up the libunwind headers. */
+#include "android-libunwind/libunwind.h"
+#define _U 0x01
+
+#define FUNC_NAME_LENGTH 512
+#define FRAMES_TO_UNWIND 256
+
+/* Expand the SYM argument. */
+#define LOAD_SYM(DL, ERR, SYM, VAR) _LOAD_SYM(DL, ERR, SYM, VAR)
+#define _LOAD_SYM(DL, ERR, SYM, VAR) \
+       do { \
+               if ((ERR = mono_dl_symbol (DL, #SYM, (void **) &VAR))) { \
+                       mono_dl_close (DL); \
+                       return ERR; \
+               } \
+       } while (0)
+
+typedef int (*unw_init_local_t) (unw_cursor_t *, unw_context_t *);
+typedef int (*unw_get_reg_t) (unw_cursor_t *, int, unw_word_t *);
+typedef int (*unw_get_proc_name_t) (unw_cursor_t *, char *, size_t, unw_word_t *);
+typedef int (*unw_step_t) (unw_cursor_t *);
+
+static char *
+mono_extension_handle_native_sigsegv_libunwind (void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
+{
+       char *dl_err;
+       int unw_err;
+
+       unw_init_local_t unw_init_local_fn;
+       unw_get_reg_t unw_get_reg_fn;
+       unw_get_proc_name_t unw_get_proc_name_fn;
+       unw_step_t unw_step_fn;
+
+       unw_cursor_t cursor;
+
+       size_t frames = 0;
+
+       MonoDl *dl = mono_dl_open ("libunwind.so", MONO_DL_LAZY, &dl_err);
+
+       if (!dl)
+               return dl_err;
+
+       LOAD_SYM (dl, dl_err, UNW_OBJ (init_local), unw_init_local_fn);
+       LOAD_SYM (dl, dl_err, UNW_OBJ (get_reg), unw_get_reg_fn);
+       LOAD_SYM (dl, dl_err, UNW_OBJ (get_proc_name), unw_get_proc_name_fn);
+       LOAD_SYM (dl, dl_err, UNW_OBJ (step), unw_step_fn);
+
+       if ((unw_err = unw_init_local_fn (&cursor, ctx))) {
+               mono_dl_close (dl);
+
+               return g_strdup_printf ("unw_init_local () returned %d", unw_err);
+       }
+
+       do {
+               int reg_err;
+
+               unw_word_t ip, off;
+               char name [FUNC_NAME_LENGTH];
+
+               if ((reg_err = unw_get_reg_fn (&cursor, UNW_REG_IP, &ip))) {
+                       mono_runtime_printf_err ("unw_get_reg (UNW_REG_IP) returned %d", reg_err);
+                       break;
+               }
+
+               reg_err = unw_get_proc_name_fn (&cursor, name, FUNC_NAME_LENGTH, &off);
+
+               if (reg_err == -UNW_ENOINFO)
+                       strcpy (name, "???");
+
+               mono_runtime_printf_err (" at %s+%zu [0x%zx]", name, off, ip);
+
+               unw_err = unw_step_fn (&cursor);
+               frames++;
+       } while (unw_err > 0 && frames < FRAMES_TO_UNWIND);
+
+       if (unw_err < 0)
+               mono_runtime_printf_err ("unw_step () returned %d", unw_err);
+
+       mono_dl_close (dl);
+
+       return NULL;
+}
+
+/*
+ * This code is based on the AOSP header system/core/include/corkscrew/backtrace.h.
+ *
+ * This is copied here because libcorkscrew is not a stable library and the header (and
+ * other headers that it depends on) will eventually go away.
+ *
+ * We can probably remove this one day when libunwind becomes the norm.
+ */
+
+typedef struct {
+       uintptr_t absolute_pc;
+       uintptr_t stack_top;
+       size_t stack_size;
+} backtrace_frame_t;
+
+typedef struct {
+       uintptr_t relative_pc;
+       uintptr_t relative_symbol_addr;
+       char *map_name;
+       char *symbol_name;
+       char *demangled_name;
+} backtrace_symbol_t;
+
+typedef void (*get_backtrace_symbols_t) (const backtrace_frame_t *backtrace, size_t frames, backtrace_symbol_t *backtrace_symbols);
+typedef void (*free_backtrace_symbols_t) (backtrace_symbol_t *backtrace_symbols, size_t frames);
+
+enum {
+       MAX_BACKTRACE_LINE_LENGTH = 800,
+};
+
+/* Internals that we're exploiting to work in a signal handler. Only works on ARM/x86. */
+
+typedef struct map_info_t map_info_t;
+
+typedef ssize_t (*unwind_backtrace_signal_arch_t) (siginfo_t *si, void *sc, const map_info_t *lst, backtrace_frame_t *bt, size_t ignore_depth, size_t max_depth);
+typedef map_info_t *(*acquire_my_map_info_list_t) (void);
+typedef void (*release_my_map_info_list_t) (map_info_t *milist);
+
+static char *
+mono_extension_handle_native_sigsegv_libcorkscrew (void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
+{
+#if defined (__arm__) || defined (__i386__)
+       char *dl_err;
+
+       get_backtrace_symbols_t get_backtrace_symbols;
+       free_backtrace_symbols_t free_backtrace_symbols;
+       unwind_backtrace_signal_arch_t unwind_backtrace_signal_arch;
+       acquire_my_map_info_list_t acquire_my_map_info_list;
+       release_my_map_info_list_t release_my_map_info_list;
+
+       backtrace_frame_t frames [FRAMES_TO_UNWIND];
+       backtrace_symbol_t symbols [FRAMES_TO_UNWIND];
+
+       map_info_t *map_info;
+       ssize_t frames_unwound;
+       size_t i;
+
+       MonoDl *dl = mono_dl_open ("libcorkscrew.so", MONO_DL_LAZY, &dl_err);
+
+       if (!dl)
+               return dl_err;
+
+       LOAD_SYM (dl, dl_err, get_backtrace_symbols, get_backtrace_symbols);
+       LOAD_SYM (dl, dl_err, free_backtrace_symbols, free_backtrace_symbols);
+       LOAD_SYM (dl, dl_err, unwind_backtrace_signal_arch, unwind_backtrace_signal_arch);
+       LOAD_SYM (dl, dl_err, acquire_my_map_info_list, acquire_my_map_info_list);
+       LOAD_SYM (dl, dl_err, release_my_map_info_list, release_my_map_info_list);
+
+       map_info = acquire_my_map_info_list ();
+       frames_unwound = unwind_backtrace_signal_arch (info, ctx, map_info, frames, 0, FRAMES_TO_UNWIND);
+       release_my_map_info_list (map_info);
+
+       if (frames_unwound == -1) {
+               mono_dl_close (dl);
+
+               return g_strdup ("unwind_backtrace_signal_arch () returned -1");
+       }
+
+       get_backtrace_symbols (frames, frames_unwound, symbols);
+
+       for (i = 0; i < frames_unwound; i++) {
+               backtrace_frame_t *frame = frames + i;
+               backtrace_symbol_t *symbol = symbols + i;
+
+               const char *name = symbol->demangled_name ? symbol->demangled_name : (symbol->symbol_name ? symbol->symbol_name : "???");
+               uintptr_t off = symbol->relative_pc - symbol->relative_symbol_addr;
+               uintptr_t ip = frame->absolute_pc;
+
+               mono_runtime_printf_err ("  at %s+%zu [0x%zx]", name, off, ip);
+       }
+
+       free_backtrace_symbols (symbols, frames_unwound);
+
+       mono_dl_close (dl);
+
+       return NULL;
+#else
+       return g_strdup ("libcorkscrew is only supported on 32-bit ARM/x86");
+#endif
+}
+
+void
+mono_exception_native_unwind (void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
+{
+       char *unwind_err, *corkscrew_err;
+
+       mono_runtime_printf_err ("\nAttempting native Android stacktrace:\n");
+
+       unwind_err = mono_extension_handle_native_sigsegv_libunwind (ctx, info);
+
+       if (unwind_err) {
+               corkscrew_err = mono_extension_handle_native_sigsegv_libcorkscrew (ctx, info);
+
+               if (corkscrew_err) {
+                       mono_runtime_printf_err ("\tCould not unwind with `libunwind.so`: %s", unwind_err);
+                       mono_runtime_printf_err ("\tCould not unwind with `libcorkscrew.so`: %s", corkscrew_err);
+                       mono_runtime_printf_err ("\n\tNo options left to get a native stacktrace :-(");
+
+                       g_free (corkscrew_err);
+               }
+
+               g_free (unwind_err);
+       }
+}
+
+#else
+
+void
+mono_exception_native_unwind (void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
+{
+}
+
+#endif
index cde7e06bf05f165dced94e47bf0cf5f544aebee0..479aed2f41ab71ae43f465101c120d87934a2162 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2001-2003 Ximian, Inc.
  * Copyright 2003-2008 Novell, Inc.
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
 #include "mini-llvm-cpp.h"
 #endif
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/mini/mini-exceptions.c"
-#endif
-
 #ifndef MONO_ARCH_CONTEXT_DEF
 #define MONO_ARCH_CONTEXT_DEF
 #endif
@@ -1348,6 +1345,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 +1371,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 +1538,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 +1549,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 +1605,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 +1620,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 +1834,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 +1887,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));
@@ -2393,8 +2397,8 @@ mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *i
        }
 #endif
  }
-#elif defined (ENABLE_EXTENSION_MODULE)
-       mono_extension_handle_native_sigsegv (ctx, info);
+#else
+       mono_exception_native_unwind (ctx, info);
 #endif
 
        /*
@@ -2882,7 +2886,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 +3027,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 +3043,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 +3056,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 47265e1d10f50156070c8372ba7447619fb12436..f50d686347e2102ed79bba2a89bed8ec186244cf 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index cba6d8e7ac92b6fc1aeedb0fba64f6455c2cef49..928763b23494cf9466b63c9a1a4863ca9ad98325 100644 (file)
@@ -1,11 +1,12 @@
 /*
- * generic-sharing.c: Support functions for generic sharing.
+ * mini-generic-sharing.c: Support functions for generic sharing.
  *
  * Author:
  *   Mark Probst (mark.probst@gmail.com)
  *
  * Copyright 2007-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -2485,11 +2486,6 @@ mono_method_lookup_rgctx (MonoVTable *class_vtable, MonoGenericInst *method_inst
        return mrgctx;
 }
 
-
-static gboolean
-generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars,
-                                                 gboolean allow_partial);
-
 static gboolean
 type_is_sharable (MonoType *type, gboolean allow_type_vars, gboolean allow_partial)
 {
@@ -2510,9 +2506,9 @@ type_is_sharable (MonoType *type, gboolean allow_type_vars, gboolean allow_parti
        if (allow_partial && !type->byref && type->type == MONO_TYPE_GENERICINST && MONO_TYPE_ISSTRUCT (type)) {
                MonoGenericClass *gclass = type->data.generic_class;
 
-               if (gclass->context.class_inst && !generic_inst_is_sharable (gclass->context.class_inst, allow_type_vars, allow_partial))
+               if (gclass->context.class_inst && !mini_generic_inst_is_sharable (gclass->context.class_inst, allow_type_vars, allow_partial))
                        return FALSE;
-               if (gclass->context.method_inst && !generic_inst_is_sharable (gclass->context.method_inst, allow_type_vars, allow_partial))
+               if (gclass->context.method_inst && !mini_generic_inst_is_sharable (gclass->context.method_inst, allow_type_vars, allow_partial))
                        return FALSE;
                if (mono_class_is_nullable (mono_class_from_mono_type (type)))
                        return FALSE;
@@ -2522,8 +2518,8 @@ type_is_sharable (MonoType *type, gboolean allow_type_vars, gboolean allow_parti
        return FALSE;
 }
 
-static gboolean
-generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars,
+gboolean
+mini_generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars,
                                                  gboolean allow_partial)
 {
        int i;
@@ -2572,10 +2568,10 @@ mono_generic_context_is_sharable_full (MonoGenericContext *context,
 {
        g_assert (context->class_inst || context->method_inst);
 
-       if (context->class_inst && !generic_inst_is_sharable (context->class_inst, allow_type_vars, allow_partial))
+       if (context->class_inst && !mini_generic_inst_is_sharable (context->class_inst, allow_type_vars, allow_partial))
                return FALSE;
 
-       if (context->method_inst && !generic_inst_is_sharable (context->method_inst, allow_type_vars, allow_partial))
+       if (context->method_inst && !mini_generic_inst_is_sharable (context->method_inst, allow_type_vars, allow_partial))
                return FALSE;
 
        return TRUE;
@@ -2863,7 +2859,6 @@ mono_method_construct_object_context (MonoMethod *method)
 }
 
 static gboolean gshared_supported;
-static gboolean gsharedvt_supported;
 
 void
 mono_set_generic_sharing_supported (gboolean supported)
@@ -2871,11 +2866,6 @@ mono_set_generic_sharing_supported (gboolean supported)
        gshared_supported = supported;
 }
 
-void
-mono_set_generic_sharing_vt_supported (gboolean supported)
-{
-       gsharedvt_supported = supported;
-}
 
 void
 mono_set_partial_sharing_supported (gboolean supported)
@@ -3385,7 +3375,7 @@ get_shared_inst (MonoGenericInst *inst, MonoGenericInst *shared_inst, MonoGeneri
                if (all_vt || gsharedvt) {
                        type_argv [i] = get_gsharedvt_type (shared_inst->type_argv [i]);
                } else {
-                       /* These types match the ones in generic_inst_is_sharable () */
+                       /* These types match the ones in mini_generic_inst_is_sharable () */
                        type_argv [i] = get_shared_type (shared_inst->type_argv [i], inst->type_argv [i]);
                }
        }
@@ -3529,10 +3519,242 @@ mini_get_rgctx_entry_slot (MonoJumpInfoRgctxEntry *entry)
        return slot;
 }
 
-#if defined(ENABLE_GSHAREDVT)
+static gboolean gsharedvt_supported;
+
+void
+mono_set_generic_sharing_vt_supported (gboolean supported)
+{
+       gsharedvt_supported = supported;
+}
+
+#ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
+
+/*
+ * mini_is_gsharedvt_type:
+ *
+ *   Return whenever T references type arguments instantiated with gshared vtypes.
+ */
+gboolean
+mini_is_gsharedvt_type (MonoType *t)
+{
+       int i;
+
+       if (t->byref)
+               return FALSE;
+       if ((t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && t->data.generic_param->gshared_constraint && t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE)
+               return TRUE;
+       else if (t->type == MONO_TYPE_GENERICINST) {
+               MonoGenericClass *gclass = t->data.generic_class;
+               MonoGenericContext *context = &gclass->context;
+               MonoGenericInst *inst;
+
+               inst = context->class_inst;
+               if (inst) {
+                       for (i = 0; i < inst->type_argc; ++i)
+                               if (mini_is_gsharedvt_type (inst->type_argv [i]))
+                                       return TRUE;
+               }
+               inst = context->method_inst;
+               if (inst) {
+                       for (i = 0; i < inst->type_argc; ++i)
+                               if (mini_is_gsharedvt_type (inst->type_argv [i]))
+                                       return TRUE;
+               }
+
+               return FALSE;
+       } else {
+               return FALSE;
+       }
+}
+
+gboolean
+mini_is_gsharedvt_klass (MonoClass *klass)
+{
+       return mini_is_gsharedvt_type (&klass->byval_arg);
+}
+
+gboolean
+mini_is_gsharedvt_signature (MonoMethodSignature *sig)
+{
+       int i;
+
+       if (sig->ret && mini_is_gsharedvt_type (sig->ret))
+               return TRUE;
+       for (i = 0; i < sig->param_count; ++i) {
+               if (mini_is_gsharedvt_type (sig->params [i]))
+                       return TRUE;
+       }
+       return FALSE;
+}
+
+/*
+ * mini_is_gsharedvt_variable_type:
+ *
+ *   Return whenever T refers to a GSHAREDVT type whose size differs depending on the values of type parameters.
+ */
+gboolean
+mini_is_gsharedvt_variable_type (MonoType *t)
+{
+       if (!mini_is_gsharedvt_type (t))
+               return FALSE;
+       if (t->type == MONO_TYPE_GENERICINST) {
+               MonoGenericClass *gclass = t->data.generic_class;
+               MonoGenericContext *context = &gclass->context;
+               MonoGenericInst *inst;
+               int i;
+
+               if (t->data.generic_class->container_class->byval_arg.type != MONO_TYPE_VALUETYPE || t->data.generic_class->container_class->enumtype)
+                       return FALSE;
+
+               inst = context->class_inst;
+               if (inst) {
+                       for (i = 0; i < inst->type_argc; ++i)
+                               if (mini_is_gsharedvt_variable_type (inst->type_argv [i]))
+                                       return TRUE;
+               }
+               inst = context->method_inst;
+               if (inst) {
+                       for (i = 0; i < inst->type_argc; ++i)
+                               if (mini_is_gsharedvt_variable_type (inst->type_argv [i]))
+                                       return TRUE;
+               }
+
+               return FALSE;
+       }
+       return TRUE;
+}
+
+static gboolean
+is_variable_size (MonoType *t)
+{
+       int i;
+
+       if (t->byref)
+               return FALSE;
+
+       if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
+               MonoGenericParam *param = t->data.generic_param;
+
+               if (param->gshared_constraint && param->gshared_constraint->type != MONO_TYPE_VALUETYPE && param->gshared_constraint->type != MONO_TYPE_GENERICINST)
+                       return FALSE;
+               if (param->gshared_constraint && param->gshared_constraint->type == MONO_TYPE_GENERICINST)
+                       return is_variable_size (param->gshared_constraint);
+               return TRUE;
+       }
+       if (t->type == MONO_TYPE_GENERICINST && t->data.generic_class->container_class->byval_arg.type == MONO_TYPE_VALUETYPE) {
+               MonoGenericClass *gclass = t->data.generic_class;
+               MonoGenericContext *context = &gclass->context;
+               MonoGenericInst *inst;
+
+               inst = context->class_inst;
+               if (inst) {
+                       for (i = 0; i < inst->type_argc; ++i)
+                               if (is_variable_size (inst->type_argv [i]))
+                                       return TRUE;
+               }
+               inst = context->method_inst;
+               if (inst) {
+                       for (i = 0; i < inst->type_argc; ++i)
+                               if (is_variable_size (inst->type_argv [i]))
+                                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+gboolean
+mini_is_gsharedvt_sharable_inst (MonoGenericInst *inst)
+{
+       int i;
+       gboolean has_vt = FALSE;
+
+       for (i = 0; i < inst->type_argc; ++i) {
+               MonoType *type = inst->type_argv [i];
+
+               if ((MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && !mini_is_gsharedvt_type (type)) {
+               } else {
+                       has_vt = TRUE;
+               }
+       }
 
-#include "../../../mono-extensions/mono/mini/mini-generic-sharing-gsharedvt.c"
+       return has_vt;
+}
+
+gboolean
+mini_is_gsharedvt_sharable_method (MonoMethod *method)
+{
+       MonoMethodSignature *sig;
 
+       /*
+        * A method is gsharedvt if:
+        * - it has type parameters instantiated with vtypes
+        */
+       if (!gsharedvt_supported)
+               return FALSE;
+       if (method->is_inflated) {
+               MonoMethodInflated *inflated = (MonoMethodInflated*)method;
+               MonoGenericContext *context = &inflated->context;
+               MonoGenericInst *inst;
+
+               if (context->class_inst && context->method_inst) {
+                       /* At least one inst has to be gsharedvt sharable, and the other normal or gsharedvt sharable */
+                       gboolean vt1 = mini_is_gsharedvt_sharable_inst (context->class_inst);
+                       gboolean vt2 = mini_is_gsharedvt_sharable_inst (context->method_inst);
+
+                       if ((vt1 && vt2) ||
+                               (vt1 && mini_generic_inst_is_sharable (context->method_inst, TRUE, FALSE)) ||
+                               (vt2 && mini_generic_inst_is_sharable (context->class_inst, TRUE, FALSE)))
+                               ;
+                       else
+                               return FALSE;
+               } else {
+                       inst = context->class_inst;
+                       if (inst && !mini_is_gsharedvt_sharable_inst (inst))
+                               return FALSE;
+                       inst = context->method_inst;
+                       if (inst && !mini_is_gsharedvt_sharable_inst (inst))
+                               return FALSE;
+               }
+       } else {
+               return FALSE;
+       }
+
+       sig = mono_method_signature (mono_method_get_declaring_generic_method (method));
+       if (!sig)
+               return FALSE;
+
+       /*
+       if (mini_is_gsharedvt_variable_signature (sig))
+               return FALSE;
+       */
+
+       //DEBUG ("GSHAREDVT SHARABLE: %s\n", mono_method_full_name (method, TRUE));
+
+       return TRUE;
+}
+
+/*
+ * mini_is_gsharedvt_variable_signature:
+ *
+ *   Return whenever the calling convention used to call SIG varies depending on the values of type parameters used by SIG,
+ * i.e. FALSE for swap(T[] arr, int i, int j), TRUE for T get_t ().
+ */
+gboolean
+mini_is_gsharedvt_variable_signature (MonoMethodSignature *sig)
+{
+       int i;
+
+       if (sig->ret && is_variable_size (sig->ret))
+               return TRUE;
+       for (i = 0; i < sig->param_count; ++i) {
+               MonoType *t = sig->params [i];
+
+               if (is_variable_size (t))
+                       return TRUE;
+       }
+       return FALSE;
+}
 #else
 
 gboolean
@@ -3571,4 +3793,4 @@ mini_is_gsharedvt_variable_signature (MonoMethodSignature *sig)
        return FALSE;
 }
 
-#endif /* !MONOTOUCH */
+#endif /* !MONO_ARCH_GSHAREDVT_SUPPORTED */
index 8122365cab91355de3aada21aef334d32c2b4dc8..e3219686ae2cf5beb7eb8ea5adb7fc9987e51d86 100644 (file)
@@ -3,6 +3,7 @@
 //
 // (C) 2009-2011 Novell, Inc.
 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 //
 
 //
index 9e8596e7bf135c3a31b057172fff8588306cdbb7..adec297e3c3ebfaff926f66a07fea1c05851de76 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright 2009-2011 Novell Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mini.h"
@@ -24,8 +25,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 +2069,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 +2118,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 +2153,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 9dadbc30a5dc24609231c554e99a53ca26d78671..9ce9be8a98c08ce51866bafee0324a087b8ee4c0 100644 (file)
+/*
+ * magic-types.c: intrinsics for variable sized int/floats
+ *
+ * Author:
+ *   Rodrigo Kumpera (kumpera@gmail.com)
+ *
+ * (C) 2013 Xamarin
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
 #include <config.h>
+#include <stdio.h>
+
+#include "mini.h"
+#include "ir-emit.h"
+#include "glib.h"
+
+
+typedef struct {
+       const char *op_name;
+       short op_table[4];
+} IntIntrisic;
+
+typedef struct {
+       short op_index;
+       short big_stack_type;
+       short small_stack_type;
+       short stack_type;
+       short conv_4_to_8;
+       short conv_8_to_4;
+       short move;
+       short inc_op;
+       short dec_op;
+       short store_op;
+       short compare_op;
+} MagicTypeInfo;
+
 
-#if defined(MONO_NATIVE_TYPES)
+#if SIZEOF_VOID_P == 8
+#define OP_PT_ADD OP_LADD
+#define OP_PT_SUB OP_LSUB
+#define OP_PT_MUL OP_LMUL
+#define OP_PT_DIV OP_LDIV
+#define OP_PT_REM OP_LREM
+#define OP_PT_NEG OP_LNEG
+#define OP_PT_AND OP_LAND
+#define OP_PT_OR OP_LOR
+#define OP_PT_XOR OP_LXOR
+#define OP_PT_NOT OP_LNOT
+#define OP_PT_SHL OP_LSHL
+#define OP_PT_SHR OP_LSHR
 
-#include "../../../mono-extensions/mono/mini/mini-native-types.c"
+#define OP_PT_DIV_UN OP_LDIV_UN
+#define OP_PT_REM_UN OP_LREM_UN
+#define OP_PT_SHR_UN OP_LSHR_UN
+
+#define OP_PT_ADD_IMM OP_LADD_IMM
+#define OP_PT_SUB_IMM OP_LSUB_IMM
+
+#define OP_PT_STORE_FP_MEMBASE_REG OP_STORER8_MEMBASE_REG
+
+#define OP_PCOMPARE OP_LCOMPARE
 
 #else
+#define OP_PT_ADD OP_IADD
+#define OP_PT_SUB OP_ISUB
+#define OP_PT_MUL OP_IMUL
+#define OP_PT_DIV OP_IDIV
+#define OP_PT_REM OP_IREM
+#define OP_PT_NEG OP_INEG
+#define OP_PT_AND OP_IAND
+#define OP_PT_OR OP_IOR
+#define OP_PT_XOR OP_IXOR
+#define OP_PT_NOT OP_INOT
+#define OP_PT_SHL OP_ISHL
+#define OP_PT_SHR OP_ISHR
 
-#include "mini.h"
+#define OP_PT_DIV_UN OP_IDIV_UN
+#define OP_PT_REM_UN OP_IREM_UN
+#define OP_PT_SHR_UN OP_ISHR_UN
 
-MonoType*
-mini_native_type_replace_type (MonoType *type)
+#define OP_PT_ADD_IMM OP_IADD_IMM
+#define OP_PT_SUB_IMM OP_ISUB_IMM
+
+#define OP_PT_STORE_FP_MEMBASE_REG OP_STORER4_MEMBASE_REG
+
+#define OP_PCOMPARE OP_ICOMPARE
+
+#endif
+
+static const IntIntrisic int_binop[] = {
+       { "op_Addition", { OP_PT_ADD, OP_PT_ADD, OP_FADD, OP_RADD } },
+       { "op_Subtraction", { OP_PT_SUB, OP_PT_SUB, OP_FSUB, OP_RSUB } },
+       { "op_Multiply", { OP_PT_MUL, OP_PT_MUL, OP_FMUL, OP_RMUL } },
+       { "op_Division", { OP_PT_DIV, OP_PT_DIV_UN, OP_FDIV, OP_RDIV } },
+       { "op_Modulus", { OP_PT_REM, OP_PT_REM_UN, OP_FREM, OP_RREM } },
+       { "op_BitwiseAnd", { OP_PT_AND, OP_PT_AND } },
+       { "op_BitwiseOr", { OP_PT_OR, OP_PT_OR } },
+       { "op_ExclusiveOr", { OP_PT_XOR, OP_PT_XOR } },
+       { "op_LeftShift", { OP_PT_SHL, OP_PT_SHL } },
+       { "op_RightShift", { OP_PT_SHR, OP_PT_SHR_UN } },
+};
+
+static const IntIntrisic int_unnop[] = {
+       { "op_UnaryPlus", { OP_MOVE, OP_MOVE, OP_FMOVE, OP_RMOVE } },
+       { "op_UnaryNegation", { OP_PT_NEG, OP_PT_NEG, OP_FNEG, OP_RNEG } },
+       { "op_OnesComplement", { OP_PT_NOT, OP_PT_NOT, OP_FNOT, OP_RNOT } },
+};
+
+static const IntIntrisic int_cmpop[] = {
+       { "op_Inequality", { OP_ICNEQ, OP_ICNEQ, OP_FCNEQ, OP_RCNEQ } },
+       { "op_Equality", { OP_ICEQ, OP_ICEQ, OP_FCEQ, OP_RCEQ } },
+       { "op_GreaterThan", { OP_ICGT, OP_ICGT_UN, OP_FCGT, OP_RCGT } },
+       { "op_GreaterThanOrEqual", { OP_ICGE, OP_ICGE_UN, OP_FCGE, OP_RCGE } },
+       { "op_LessThan", { OP_ICLT, OP_ICLT_UN, OP_FCLT, OP_RCLT } },
+       { "op_LessThanOrEqual", { OP_ICLE, OP_ICLE_UN, OP_FCLE, OP_RCLE } },
+};
+
+static const MagicTypeInfo type_info[] = {
+       //nint
+       { 0, STACK_I8, STACK_I4, STACK_PTR, OP_ICONV_TO_I8, OP_LCONV_TO_I4, OP_MOVE, OP_PT_ADD_IMM, OP_PT_SUB_IMM, OP_STORE_MEMBASE_REG, OP_PCOMPARE },
+       //nuint
+       { 1, STACK_I8, STACK_I4, STACK_PTR, OP_ICONV_TO_U8, OP_LCONV_TO_U4, OP_MOVE, OP_PT_ADD_IMM, OP_PT_SUB_IMM, OP_STORE_MEMBASE_REG, OP_PCOMPARE },
+       //nfloat
+       { 2, STACK_R8, STACK_R8, STACK_R8, OP_FCONV_TO_R8, OP_FCONV_TO_R4, OP_FMOVE, 0, 0, OP_PT_STORE_FP_MEMBASE_REG, 0 },
+};
+
+static inline gboolean mono_class_is_magic_int (MonoClass *klass);
+static inline gboolean mono_class_is_magic_float (MonoClass *klass);
+
+
+static inline gboolean
+type_size (MonoCompile *cfg, MonoType *type)
 {
-       return type;
+       if (type->type == MONO_TYPE_I4 || type->type == MONO_TYPE_U4)
+               return 4;
+       else if (type->type == MONO_TYPE_I8 || type->type == MONO_TYPE_U8)
+               return 8;
+       else if (type->type == MONO_TYPE_R4 && !type->byref && cfg->r4fp)
+               return 4;
+       else if (type->type == MONO_TYPE_R8 && !type->byref)
+               return 8;
+       return SIZEOF_VOID_P;
 }
 
+#ifndef DISABLE_JIT
+
+static gboolean is_int_type (MonoType *t);
+static gboolean is_float_type (MonoType *t);
+
+static MonoInst*
+emit_narrow (MonoCompile *cfg, const MagicTypeInfo *info, int sreg)
+{
+       MonoInst *ins;
+
+       MONO_INST_NEW (cfg, ins, info->conv_8_to_4);
+       ins->sreg1 = sreg;
+       if (info->conv_8_to_4 == OP_FCONV_TO_R4)
+               ins->type = cfg->r4_stack_type;
+       else
+               ins->type = info->small_stack_type;
+       ins->dreg = alloc_dreg (cfg, ins->type);
+       MONO_ADD_INS (cfg->cbb, ins);
+       return mono_decompose_opcode (cfg, ins);
+}
+
+static MonoInst*
+emit_widen (MonoCompile *cfg, const MagicTypeInfo *info, int sreg)
+{
+       MonoInst *ins;
+
+       if (cfg->r4fp && info->conv_4_to_8 == OP_FCONV_TO_R8)
+               MONO_INST_NEW (cfg, ins, OP_RCONV_TO_R8);
+       else
+               MONO_INST_NEW (cfg, ins, info->conv_4_to_8);
+       ins->sreg1 = sreg;
+       ins->type = info->big_stack_type;
+       ins->dreg = alloc_dreg (cfg, info->big_stack_type); 
+       MONO_ADD_INS (cfg->cbb, ins);
+       return mono_decompose_opcode (cfg, ins);
+}
+
+static MonoInst*
+emit_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args, const MagicTypeInfo *info)
+{
+       int i = 0;
+       const char *name = cmethod->name;
+       MonoInst *ins;
+       int type_index, stack_type;
+
+       if (info->op_index == 2 && cfg->r4fp && SIZEOF_VOID_P == 4) {
+               type_index = 3;
+               stack_type = STACK_R4;
+       } else {
+               type_index = info->op_index;
+               stack_type = info->stack_type;
+       }
+
+       if (!strcmp ("op_Implicit", name) || !strcmp ("op_Explicit", name)) {
+               int source_size = type_size (cfg, fsig->params [0]);
+               int dest_size = type_size (cfg, fsig->ret);
+
+               switch (info->big_stack_type) {
+               case STACK_I8:
+                       if (!is_int_type (fsig->params [0]) || !is_int_type (fsig->ret))
+                               return NULL;
+                       break;
+               case STACK_R8:
+                       if (!is_float_type (fsig->params [0]) || !is_float_type (fsig->ret))
+                               return NULL;
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+
+               //4 -> 4 or 8 -> 8
+               if (source_size == dest_size)
+                       return args [0];
+
+               //4 -> 8
+               if (source_size < dest_size)
+                       return emit_widen (cfg, info, args [0]->dreg);
+
+               //8 -> 4
+               return emit_narrow (cfg, info, args [0]->dreg);
+       }
+
+       if (!strcmp (".ctor", name)) {
+               gboolean is_ldaddr = args [0]->opcode == OP_LDADDR;
+               int arg0 = args [1]->dreg;
+               int arg_size = type_size (cfg, fsig->params [0]);
+
+               if (arg_size > SIZEOF_VOID_P) //8 -> 4
+                       arg0 = emit_narrow (cfg, info, arg0)->dreg;
+               else if (arg_size < SIZEOF_VOID_P) //4 -> 8
+                       arg0 = emit_widen (cfg, info, arg0)->dreg;
+
+               if (is_ldaddr) { /*Eliminate LDADDR if it's initing a local var*/
+                       int dreg = ((MonoInst*)args [0]->inst_p0)->dreg;
+                       NULLIFY_INS (args [0]);
+                       EMIT_NEW_UNALU (cfg, ins, info->move, dreg, arg0);
+                       cfg->has_indirection = TRUE;
+               } else {
+                       EMIT_NEW_STORE_MEMBASE (cfg, ins, info->store_op, args [0]->dreg, 0, arg0);
+               }
+               return ins;
+       }
+
+       if (!strcmp ("op_Increment", name) || !strcmp ("op_Decrement", name)) {
+               gboolean inc = !strcmp ("op_Increment", name);
+               /* FIXME float inc is too complex to bother with*/
+               //this is broken with ints too
+               // if (!info->inc_op)
+                       return NULL;
+
+               /* We have IR for inc/dec */
+               MONO_INST_NEW (cfg, ins, inc ? info->inc_op : info->dec_op);
+               ins->dreg = alloc_dreg (cfg, info->stack_type);
+               ins->sreg1 = args [0]->dreg;
+               ins->inst_imm = 1;
+               ins->type = info->stack_type;
+               MONO_ADD_INS (cfg->cbb, ins);
+               return ins;
+       }
+
+       for (i = 0; i < sizeof (int_binop) / sizeof  (IntIntrisic); ++i) {
+               if (!strcmp (int_binop [i].op_name, name)) {
+                       if (!int_binop [i].op_table [info->op_index])
+                               return NULL;
+                       g_assert (int_binop [i].op_table [type_index]);
+
+                       MONO_INST_NEW (cfg, ins, int_binop [i].op_table [type_index]);
+                       ins->dreg = alloc_dreg (cfg, stack_type);
+                       ins->sreg1 = args [0]->dreg;
+               ins->sreg2 = args [1]->dreg;
+                       ins->type = stack_type;
+                       MONO_ADD_INS (cfg->cbb, ins);
+                       return mono_decompose_opcode (cfg, ins);
+               }
+       }
+
+       for (i = 0; i < sizeof (int_unnop) / sizeof  (IntIntrisic); ++i) {
+               if (!strcmp (int_unnop [i].op_name, name)) {
+                       g_assert (int_unnop [i].op_table [type_index]);
+
+                       MONO_INST_NEW (cfg, ins, int_unnop [i].op_table [type_index]);
+                       ins->dreg = alloc_dreg (cfg, stack_type);
+                       ins->sreg1 = args [0]->dreg;
+                       ins->type = stack_type;
+                       MONO_ADD_INS (cfg->cbb, ins);
+                       return ins;
+               }
+       }
+
+       for (i = 0; i < sizeof (int_cmpop) / sizeof  (IntIntrisic); ++i) {
+               if (!strcmp (int_cmpop [i].op_name, name)) {
+                       g_assert (int_cmpop [i].op_table [type_index]);
+
+                       if (info->compare_op) {
+                               MONO_INST_NEW (cfg, ins, info->compare_op);
+                       ins->dreg = -1;
+                               ins->sreg1 = args [0]->dreg;
+                       ins->sreg2 = args [1]->dreg;
+                               MONO_ADD_INS (cfg->cbb, ins);
+
+                               MONO_INST_NEW (cfg, ins, int_cmpop [i].op_table [type_index]);
+                       ins->dreg = alloc_preg (cfg);
+                               ins->type = STACK_I4;
+                               MONO_ADD_INS (cfg->cbb, ins);
+                       } else {
+                               MONO_INST_NEW (cfg, ins, int_cmpop [i].op_table [type_index]);
+                               ins->dreg = alloc_ireg (cfg);
+                               ins->sreg1 = args [0]->dreg;
+                       ins->sreg2 = args [1]->dreg;
+                               MONO_ADD_INS (cfg->cbb, ins);
+                       }
+
+                       return ins;
+               }
+       }
+
+       return NULL;
+}
+
+
 MonoInst*
 mono_emit_native_types_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
 {
+       if (mono_class_is_magic_int (cmethod->klass)) {
+               const char *class_name = cmethod->klass->name;
+               if (!strcmp ("nint", class_name))
+                       return emit_intrinsics (cfg, cmethod, fsig, args, &type_info [0]);
+               else
+                       return emit_intrinsics (cfg, cmethod, fsig, args, &type_info [1]);
+       } else if (mono_class_is_magic_float (cmethod->klass))
+               return emit_intrinsics (cfg, cmethod, fsig, args, &type_info [2]);
+
        return NULL;
 }
 
+#endif /* !DISABLE_JIT */
+
+static inline gboolean
+mono_class_is_magic_assembly (MonoClass *klass)
+{
+       if (!klass->image->assembly_name)
+               return FALSE;
+       if (!strcmp ("Xamarin.iOS", klass->image->assembly_name))
+               return TRUE;
+       if (!strcmp ("Xamarin.Mac", klass->image->assembly_name))
+               return TRUE;
+       return FALSE;
+}
+
+static inline gboolean
+mono_class_is_magic_int (MonoClass *klass)
+{
+       static MonoClass *magic_nint_class;
+       static MonoClass *magic_nuint_class;
+
+       if (klass == magic_nint_class)
+               return TRUE;
+
+       if (klass == magic_nuint_class)
+               return TRUE;
+
+       if (magic_nint_class && magic_nuint_class)
+               return FALSE;
+
+       if (!mono_class_is_magic_assembly (klass))
+               return FALSE;
+
+       if (strcmp ("System", klass->name_space) != 0)
+               return FALSE;
+
+       if (strcmp ("nint", klass->name) == 0) {
+               magic_nint_class = klass;
+               return TRUE;
+       }
+
+       if (strcmp ("nuint", klass->name) == 0){
+               magic_nuint_class = klass;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static inline gboolean
+mono_class_is_magic_float (MonoClass *klass)
+{
+       static MonoClass *magic_nfloat_class;
+
+       if (klass == magic_nfloat_class)
+               return TRUE;
+
+       if (magic_nfloat_class)
+               return FALSE;
+
+       if (!mono_class_is_magic_assembly (klass))
+               return FALSE;
+
+       if (strcmp ("System", klass->name_space) != 0)
+               return FALSE;
+
+       if (strcmp ("nfloat", klass->name) == 0) {
+               magic_nfloat_class = klass;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static gboolean
+is_int_type (MonoType *t)
+{
+       if (t->type != MONO_TYPE_I4 && t->type != MONO_TYPE_I8 && t->type != MONO_TYPE_U4 && t->type != MONO_TYPE_U8 && !mono_class_is_magic_int (mono_class_from_mono_type (t)))
+               return FALSE;
+       return TRUE;
+}
+
+static gboolean
+is_float_type (MonoType *t)
+{
+       if (t->type != MONO_TYPE_R4 && t->type != MONO_TYPE_R8 && !mono_class_is_magic_float (mono_class_from_mono_type (t)))
+               return FALSE;
+       return TRUE;
+}
+
+MonoType*
+mini_native_type_replace_type (MonoType *type)
+{
+       MonoClass *klass;
+
+       if (type->type != MONO_TYPE_VALUETYPE)
+               return type;
+       klass = type->data.klass;
+
+       if (mono_class_is_magic_int (klass))
+               return type->byref ? &mono_defaults.int_class->this_arg : &mono_defaults.int_class->byval_arg;
+       if (mono_class_is_magic_float (klass))
+#if SIZEOF_VOID_P == 8
+               return type->byref ? &mono_defaults.double_class->this_arg : &mono_defaults.double_class->byval_arg;
+#else
+               return type->byref ? &mono_defaults.single_class->this_arg : &mono_defaults.single_class->byval_arg;
 #endif
+       return type;
+}
index 7e1e72ce4978c9c82fcefbe77a3da12fc52102d4..ad48c07158e3f0877ae4033b5c2dd0ab9a1f207a 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright 2003 Ximian, Inc
  * Copyright 2003-2011 Novell Inc
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 MINI_OP(OP_LOAD,       "load", NONE, NONE, NONE)
 MINI_OP(OP_LDADDR,     "ldaddr", IREG, NONE, NONE)
index 63198d79083cdafc1718a111016e0be15ad63a87..7be84488f5877f979e259857c2383e12c373d542 100644 (file)
@@ -9,6 +9,7 @@
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  *
  * See LICENSE for licensing information.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <signal.h>
index 6a9f054864b68efb5c4915a9b234c442443ec58e..06238b4d68898a161a0b196d77a2fb05774f94f4 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * mini-runtime.c: Runtime code for the JIT
  *
@@ -8,6 +9,7 @@
  * Copyright 2002-2003 Ximian, Inc.
  * Copyright 2003-2010 Novell, Inc.
  * Copyright 2011-2015 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -2007,7 +2009,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;
@@ -2388,7 +2392,7 @@ create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer com
 
        if (!info->dyn_call_info) {
                if (mono_llvm_only) {
-#ifndef ENABLE_GSHAREDVT
+#ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
                        g_assert_not_reached ();
 #endif
                        info->gsharedvt_invoke = TRUE;
@@ -2500,7 +2504,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 +2679,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..c464a0033a77c727829ba44f5e6acea3bba0e84c 100644 (file)
@@ -2,6 +2,7 @@
  * (C) 2003 Ximian, Inc.
  * (C) 2003-2011 Novell, Inc.
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <glib.h>
@@ -1057,36 +1058,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 +1547,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 +1566,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 41f12051f906929073be867a6b0076a04b8dbf11..621a7a5fc31970e22d3e75e4993623ae10dddece 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2003-2008 Ximian, Inc.
  *
  * See LICENSE for licensing information.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <signal.h>
diff --git a/mono/mini/mini-x86-gsharedvt.c b/mono/mini/mini-x86-gsharedvt.c
new file mode 100644 (file)
index 0000000..130d48e
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * mini-x86-gsharedvt.c: gsharedvt support code for x86
+ *
+ * Authors:
+ *   Zoltan Varga <vargaz@gmail.com>
+ *
+ * Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include "mini.h"
+
+#ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
+
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+/*
+ * GSHAREDVT
+ */
+
+gboolean
+mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)
+{
+       /*
+       if (sig->ret && is_variable_size (sig->ret))
+               return FALSE;
+       */
+       return TRUE;
+}
+
+/*
+ * mono_arch_get_gsharedvt_call_info:
+ *
+ *   Compute calling convention information for marshalling a call between NORMAL_SIG and GSHAREDVT_SIG.
+ * If GSHAREDVT_IN is TRUE, then the caller calls using the signature NORMAL_SIG but the call is received by
+ * a method with signature GSHAREDVT_SIG, otherwise its the other way around.
+ */
+gpointer
+mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
+{
+       GSharedVtCallInfo *info;
+       CallInfo *caller_cinfo, *callee_cinfo;
+       MonoMethodSignature *caller_sig, *callee_sig;
+       int i, j;
+       gboolean var_ret = FALSE;
+       CallInfo *cinfo, *gcinfo;
+       MonoMethodSignature *sig, *gsig;
+       GPtrArray *map;
+
+       if (gsharedvt_in) {
+               caller_sig = normal_sig;
+               callee_sig = gsharedvt_sig;
+               caller_cinfo = mono_arch_get_call_info (NULL, caller_sig);
+               callee_cinfo = mono_arch_get_call_info (NULL, callee_sig);
+       } else {
+               callee_sig = normal_sig;
+               callee_cinfo = mono_arch_get_call_info (NULL, callee_sig);
+               caller_sig = gsharedvt_sig;
+               caller_cinfo = mono_arch_get_call_info (NULL, caller_sig);
+       }
+
+       /*
+        * If GSHAREDVT_IN is true, this means we are transitioning from normal to gsharedvt code. The caller uses the
+        * normal call signature, while the callee uses the gsharedvt signature.
+        * If GSHAREDVT_IN is false, its the other way around.
+        */
+
+       /* sig/cinfo describes the normal call, while gsig/gcinfo describes the gsharedvt call */
+       if (gsharedvt_in) {
+               sig = caller_sig;
+               gsig = callee_sig;
+               cinfo = caller_cinfo;
+               gcinfo = callee_cinfo;
+       } else {
+               sig = callee_sig;
+               gsig = caller_sig;
+               cinfo = callee_cinfo;
+               gcinfo = caller_cinfo;
+       }
+
+       if (gcinfo->vtype_retaddr && gsig->ret && mini_is_gsharedvt_type (gsig->ret)) {
+               /*
+                * The return type is gsharedvt
+                */
+               var_ret = TRUE;
+       }
+
+       /*
+        * The stack looks like this:
+        * <arguments>
+        * <ret addr>
+        * <saved ebp>
+        * <call area>
+        * We have to map the stack slots in <arguments> to the stack slots in <call area>.
+        */
+       map = g_ptr_array_new ();
+
+       if (cinfo->vtype_retaddr) {
+               /*
+                * Map ret arg.
+                * This handles the case when the method returns a normal vtype, and when it returns a type arg, and its instantiated
+                * with a vtype.
+                */             
+               g_ptr_array_add (map, GUINT_TO_POINTER (caller_cinfo->vret_arg_offset / sizeof (gpointer)));
+               g_ptr_array_add (map, GUINT_TO_POINTER (callee_cinfo->vret_arg_offset / sizeof (gpointer)));
+       }
+
+       for (i = 0; i < cinfo->nargs; ++i) {
+               ArgInfo *ainfo = &caller_cinfo->args [i];
+               ArgInfo *ainfo2 = &callee_cinfo->args [i];
+               int nslots;
+
+               switch (ainfo->storage) {
+               case ArgGSharedVt:
+                       if (ainfo2->storage == ArgOnStack) {
+                               nslots = callee_cinfo->args [i].nslots;
+                               if (!nslots)
+                                       nslots = 1;
+                               g_ptr_array_add (map, GUINT_TO_POINTER ((ainfo->offset / sizeof (gpointer)) + (1 << 16) + (nslots << 18)));
+                               g_ptr_array_add (map, GUINT_TO_POINTER ((ainfo2->offset / sizeof (gpointer))));
+                       } else {
+                               g_ptr_array_add (map, GUINT_TO_POINTER ((ainfo->offset / sizeof (gpointer))));
+                               g_ptr_array_add (map, GUINT_TO_POINTER ((ainfo2->offset / sizeof (gpointer))));
+                       }
+                       break;
+               default:
+                       if (ainfo2->storage == ArgOnStack) {
+                               nslots = cinfo->args [i].nslots;
+                               if (!nslots)
+                                       nslots = 1;
+                               for (j = 0; j < nslots; ++j) {
+                                       g_ptr_array_add (map, GUINT_TO_POINTER ((ainfo->offset / sizeof (gpointer)) + j));
+                                       g_ptr_array_add (map, GUINT_TO_POINTER ((ainfo2->offset / sizeof (gpointer)) + j));
+                               }
+                       } else {
+                               g_assert (ainfo2->storage == ArgGSharedVt);
+                               g_ptr_array_add (map, GUINT_TO_POINTER ((ainfo->offset / sizeof (gpointer)) + (2 << 16)));
+                               g_ptr_array_add (map, GUINT_TO_POINTER ((ainfo2->offset / sizeof (gpointer))));
+                       }
+                       break;
+               }
+       }
+
+       info = mono_domain_alloc0 (mono_domain_get (), sizeof (GSharedVtCallInfo) + (map->len * sizeof (int)));
+       info->addr = addr;
+       info->stack_usage = callee_cinfo->stack_usage;
+       info->ret_marshal = GSHAREDVT_RET_NONE;
+       info->gsharedvt_in = gsharedvt_in ? 1 : 0;
+       info->vret_slot = -1;
+       info->calli = calli ? 1 : 0;
+       if (var_ret)
+               info->vret_arg_slot = gcinfo->vret_arg_offset / sizeof (gpointer);
+       else
+               info->vret_arg_slot = -1;
+       info->vcall_offset = vcall_offset;
+       info->map_count = map->len / 2;
+       for (i = 0; i < map->len; ++i)
+               info->map [i] = GPOINTER_TO_UINT (g_ptr_array_index (map, i));
+       g_ptr_array_free (map, TRUE);
+
+       /* Compute return value marshalling */
+       if (var_ret) {
+               switch (cinfo->ret.storage) {
+               case ArgInIReg:
+                       if (gsharedvt_in && !sig->ret->byref && sig->ret->type == MONO_TYPE_I1)
+                               info->ret_marshal = GSHAREDVT_RET_I1;
+                       else if (gsharedvt_in && !sig->ret->byref && (sig->ret->type == MONO_TYPE_U1 || sig->ret->type == MONO_TYPE_BOOLEAN))
+                               info->ret_marshal = GSHAREDVT_RET_U1;
+                       else if (gsharedvt_in && !sig->ret->byref && sig->ret->type == MONO_TYPE_I2)
+                               info->ret_marshal = GSHAREDVT_RET_I2;
+                       else if (gsharedvt_in && !sig->ret->byref && (sig->ret->type == MONO_TYPE_U2 || sig->ret->type == MONO_TYPE_CHAR))
+                               info->ret_marshal = GSHAREDVT_RET_U2;
+                       else if (cinfo->ret.is_pair)
+                               info->ret_marshal = GSHAREDVT_RET_IREGS;
+                       else
+                               info->ret_marshal = GSHAREDVT_RET_IREG;
+                       break;
+               case ArgOnDoubleFpStack:
+                       info->ret_marshal = GSHAREDVT_RET_DOUBLE_FPSTACK;
+                       break;
+               case ArgOnFloatFpStack:
+                       info->ret_marshal = GSHAREDVT_RET_FLOAT_FPSTACK;
+                       break;
+               case ArgOnStack:
+                       /* The caller passes in a vtype ret arg as well */
+                       g_assert (gcinfo->vtype_retaddr);
+                       /* Just have to pop the arg, as done by normal methods in their epilog */
+                       info->ret_marshal = GSHAREDVT_RET_STACK_POP;
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+       } else if (gsharedvt_in && cinfo->vtype_retaddr) {
+               info->ret_marshal = GSHAREDVT_RET_STACK_POP;
+       }
+
+       if (gsharedvt_in && var_ret && !caller_cinfo->vtype_retaddr) {
+               /* Allocate stack space for the return value */
+               info->vret_slot = info->stack_usage / sizeof (gpointer);
+               // FIXME:
+               info->stack_usage += sizeof (gpointer) * 3;
+       }
+
+       info->stack_usage = ALIGN_TO (info->stack_usage, MONO_ARCH_FRAME_ALIGNMENT);
+
+       g_free (caller_cinfo);
+       g_free (callee_cinfo);
+
+       return info;
+}
+#endif
index 9802e46c58f88cffa1743c6a92d41085ec439774..5e9204611d7bf37760b7aae0a19dcb1057196085 100644 (file)
@@ -9,6 +9,7 @@
  * Copyright 2003 Ximian, Inc.
  * Copyright 2003-2011 Novell Inc.
  * Copyright 2011 Xamarin Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "mini.h"
 #include <string.h>
@@ -179,49 +180,6 @@ mono_x86_patch (unsigned char* code, gpointer target)
        x86_patch (code, (unsigned char*)target);
 }
 
-typedef enum {
-       ArgInIReg,
-       ArgInFloatSSEReg,
-       ArgInDoubleSSEReg,
-       ArgOnStack,
-       ArgValuetypeInReg,
-       ArgOnFloatFpStack,
-       ArgOnDoubleFpStack,
-       /* gsharedvt argument passed by addr */
-       ArgGSharedVt,
-       ArgNone
-} ArgStorage;
-
-typedef struct {
-       gint16 offset;
-       gint8  reg;
-       ArgStorage storage;
-       int nslots;
-       gboolean is_pair;
-
-       /* Only if storage == ArgValuetypeInReg */
-       ArgStorage pair_storage [2];
-       gint8 pair_regs [2];
-} ArgInfo;
-
-typedef struct {
-       int nargs;
-       guint32 stack_usage;
-       guint32 reg_usage;
-       guint32 freg_usage;
-       gboolean need_stack_align;
-       guint32 stack_align_amount;
-       gboolean vtype_retaddr;
-       /* The index of the vret arg in the argument list */
-       int vret_arg_index;
-       int vret_arg_offset;
-       /* Argument space popped by the callee */
-       int callee_stack_pop;
-       ArgInfo ret;
-       ArgInfo sig_cookie;
-       ArgInfo args [1];
-} CallInfo;
-
 #define FLOAT_PARAM_REGS 0
 
 static const guint32 thiscall_param_regs [] = { X86_ECX, X86_NREG };
@@ -761,7 +719,7 @@ mono_arch_init (void)
 
        mono_aot_register_jit_icall ("mono_x86_throw_exception", mono_x86_throw_exception);
        mono_aot_register_jit_icall ("mono_x86_throw_corlib_exception", mono_x86_throw_corlib_exception);
-#if defined(ENABLE_GSHAREDVT)
+#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
        mono_aot_register_jit_icall ("mono_x86_start_gsharedvt_call", mono_x86_start_gsharedvt_call);
 #endif
 }
@@ -2475,26 +2433,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)
@@ -6826,8 +6764,8 @@ mono_arch_opcode_supported (int opcode)
        }
 }
 
-#if defined(ENABLE_GSHAREDVT)
-
-#include "../../../mono-extensions/mono/mini/mini-x86-gsharedvt.c"
-
-#endif /* !MONOTOUCH */
+CallInfo*
+mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
+{
+       return get_call_info (mp, sig);
+}
index 212f844af4ca27f1076c08c4b917081aeac08c4e..969b679f29bbfdd161bd5a77c6c68cf7d6900cbc 100644 (file)
@@ -300,6 +300,49 @@ typedef struct {
        int map [MONO_ZERO_LEN_ARRAY];
 } GSharedVtCallInfo;
 
+typedef enum {
+       ArgInIReg,
+       ArgInFloatSSEReg,
+       ArgInDoubleSSEReg,
+       ArgOnStack,
+       ArgValuetypeInReg,
+       ArgOnFloatFpStack,
+       ArgOnDoubleFpStack,
+       /* gsharedvt argument passed by addr */
+       ArgGSharedVt,
+       ArgNone
+} ArgStorage;
+
+typedef struct {
+       gint16 offset;
+       gint8  reg;
+       ArgStorage storage;
+       int nslots;
+       gboolean is_pair;
+
+       /* Only if storage == ArgValuetypeInReg */
+       ArgStorage pair_storage [2];
+       gint8 pair_regs [2];
+} ArgInfo;
+
+typedef struct {
+       int nargs;
+       guint32 stack_usage;
+       guint32 reg_usage;
+       guint32 freg_usage;
+       gboolean need_stack_align;
+       guint32 stack_align_amount;
+       gboolean vtype_retaddr;
+       /* The index of the vret arg in the argument list */
+       int vret_arg_index;
+       int vret_arg_offset;
+       /* Argument space popped by the callee */
+       int callee_stack_pop;
+       ArgInfo ret;
+       ArgInfo sig_cookie;
+       ArgInfo args [1];
+} CallInfo;
+
 guint8*
 mono_x86_emit_tls_get (guint8* code, int dreg, int tls_offset);
 
@@ -326,5 +369,8 @@ mono_x86_patch (unsigned char* code, gpointer target);
 gpointer
 mono_x86_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg);
 
+CallInfo*
+mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig);
+
 #endif /* __MONO_MINI_X86_H__ */  
 
index 046572a332925011fdfb5b9d33a0f3ec30c14f7a..7101e69b33c22c279a381de66ddecf27a2bed2bd 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2002-2003 Ximian, Inc.
  * Copyright 2003-2010 Novell, Inc.
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 2a1b331f809921750df32acc131c984005861ce1..23f048881db7d08408bf81b82a47158b15d003e8 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright 2002-2003 Ximian Inc
  * Copyright 2003-2011 Novell Inc
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_MINI_H__
 #define __MONO_MINI_H__
@@ -3009,6 +3010,10 @@ mono_method_is_generic_sharable_full (MonoMethod *method, gboolean allow_type_va
 gboolean
 mini_class_is_generic_sharable (MonoClass *klass);
 
+
+gboolean
+mini_generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars, gboolean allow_partial);
+
 gboolean
 mono_is_partially_sharable_inst (MonoGenericInst *inst);
 
@@ -3189,4 +3194,10 @@ gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal);
 #define ARCH_VARARG_ICALLS 0
 #endif
 
+/*
+ * Native unwinder integration
+ */
+void mono_exception_native_unwind (void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info);
+
+
 #endif /* __MONO_MINI_H__ */
index 434a11f43702db5e180d652eac020f06740566db..fd9cc01200d0c9d3ba020853ac7b3f39e9a38732 100644 (file)
@@ -5,6 +5,7 @@
  *   Marcos Henrich (marcos.henrich@xamarin.com)
  *
  * Copyright 2014 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mini.h"
index d0e6f5aa1575f5fd87bde866a4d8fc31a51eea50..79915205a2d7e25bcd94b944edff81803fc48474 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2014 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
  
 #ifndef __MONO_SEQ_POINTS_H__
index a29108872a4adbb4dfb50430f70595a6eb3c9b17..cb100267ef706a6c3608f7b09e12f5dcb92e1cfb 100644 (file)
@@ -6,6 +6,7 @@
  *
  * (C) 2003 Ximian, Inc.
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <string.h>
index 765bc111c09bb22e86740bdc03f19ff6b4bf29fb..d8e4437b75d5ddb7836dbee0230e052f673744d6 100644 (file)
@@ -7,6 +7,7 @@
  *
  * (C) 2002 Ximian, Inc.
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
diff --git a/mono/mini/tramp-amd64-gsharedvt.c b/mono/mini/tramp-amd64-gsharedvt.c
new file mode 100644 (file)
index 0000000..0b28eeb
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * tramp-amd64-gsharedvt.c: libcorkscrew-based native unwinder
+ *
+ * Authors:
+ *   Zoltan Varga <vargaz@gmail.com>
+ *   Rodrigo Kumpera <kumpera@gmail.com>
+ *   Andi McClure <andi.mcclure@xamarin.com>
+ *
+ * Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <config.h>
+#include <glib.h>
+
+#include <mono/metadata/abi-details.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/marshal.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/mono-debug-debugger.h>
+#include <mono/metadata/profiler-private.h>
+#include <mono/metadata/gc-internals.h>
+#include <mono/arch/amd64/amd64-codegen.h>
+
+#include <mono/utils/memcheck.h>
+
+#include "mini.h"
+#include "mini-amd64.h"
+#include "mini-amd64-gsharedvt.h"
+#include "debugger-agent.h"
+
+#if defined (MONO_ARCH_GSHAREDVT_SUPPORTED)
+
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+#define SRC_REG_SHIFT 0
+#define SRC_REG_MASK 0xFFFF
+
+#define SRC_DESCRIPTOR_MARSHAL_SHIFT 16
+#define SRC_DESCRIPTOR_MARSHAL_MASK 0x0FF
+
+#define SLOT_COUNT_SHIFT 24
+#define SLOT_COUNT_MASK 0xFF
+
+gpointer
+mono_amd64_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg)
+{
+       int i;
+
+#ifdef DEBUG_AMD64_GSHAREDVT
+       printf ("mono_amd64_start_gsharedvt_call info %p caller %p callee %p ctx %p\n", info, caller, callee, mrgctx_reg);
+
+       for (i = 0; i < PARAM_REGS; ++i)
+               printf ("\treg [%d] -> %p\n", i, caller [i]);
+#endif
+
+       /* Set vtype ret arg */
+       if (info->vret_slot != -1) {
+               DEBUG_AMD64_GSHAREDVT_PRINT ("vret handling\n[%d] < &%d (%p)\n", info->vret_arg_reg, info->vret_slot, &callee [info->vret_slot]);
+               g_assert (info->vret_slot);
+               callee [info->vret_arg_reg] = &callee [info->vret_slot];
+       }
+
+       for (i = 0; i < info->map_count; ++i) {
+               int src = info->map [i * 2];
+               int dst = info->map [(i * 2) + 1];
+               int arg_marshal = (src >> SRC_DESCRIPTOR_MARSHAL_SHIFT) & SRC_DESCRIPTOR_MARSHAL_MASK;
+
+               int source_reg = src & SRC_REG_MASK;
+               int dest_reg = dst & SRC_REG_MASK;
+
+               DEBUG_AMD64_GSHAREDVT_PRINT ("source %x dest %x marshal %d: ", src, dst, arg_marshal);
+               switch (arg_marshal) {
+               case GSHAREDVT_ARG_NONE:
+                       callee [dest_reg] = caller [source_reg];
+                       DEBUG_AMD64_GSHAREDVT_PRINT ("[%d] <- %d (%p) <- (%p)\n", dest_reg, source_reg, &callee [dest_reg], caller [source_reg]);
+                       break;
+               case GSHAREDVT_ARG_BYVAL_TO_BYREF:
+                       /* gsharedvt argument passed by addr in reg/stack slot */
+                       callee [dest_reg] = &caller [source_reg];
+                       DEBUG_AMD64_GSHAREDVT_PRINT ("[%d] <- &%d (%p) <- (%p)\n", dest_reg, source_reg, &callee [dest_reg], &caller [source_reg]);
+                       break;
+               case GSHAREDVT_ARG_BYREF_TO_BYVAL: {
+                       int slot_count = (src >> SLOT_COUNT_SHIFT) & SLOT_COUNT_MASK;
+                       int j;
+                       gpointer *addr = caller [source_reg];
+
+                       for (j = 0; j < slot_count; ++j)
+                               callee [dest_reg + j] = addr [j];
+                       DEBUG_AMD64_GSHAREDVT_PRINT ("[%d] <- [%d] (%d words) (%p) <- (%p)\n", dest_reg, source_reg, slot_count, &callee [dest_reg], &caller [source_reg]);
+                       break;
+               }
+               default:
+                       g_error ("cant handle arg marshal %d\n", arg_marshal);
+               }
+       }
+
+       //Can't handle for now
+       if (info->vcall_offset != -1){
+               MonoObject *this_obj = caller [0];
+
+               DEBUG_AMD64_GSHAREDVT_PRINT ("target is a vcall at offset %d\n", info->vcall_offset / 8);
+               if (G_UNLIKELY (!this_obj))
+                       return NULL;
+               if (info->vcall_offset == MONO_GSHAREDVT_DEL_INVOKE_VT_OFFSET)
+                       /* delegate invoke */
+                       return ((MonoDelegate*)this_obj)->invoke_impl;
+               else
+                       return *(gpointer*)((char*)this_obj->vtable + info->vcall_offset);
+       } else if (info->calli) {
+               /* The address to call is passed in the mrgctx reg */
+               return mrgctx_reg;
+       } else {
+               DEBUG_AMD64_GSHAREDVT_PRINT ("target is %p\n", info->addr);
+               return info->addr;
+       }
+}
+
+#ifndef DISABLE_JIT
+
+// Compiler support
+
+/*
+ * mono_arch_get_gsharedvt_arg_trampoline:
+ *
+ *   See tramp-x86.c for documentation.
+ */
+gpointer
+mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr)
+{
+       guint8 *code, *start;
+       int buf_len;
+
+       buf_len = 32;
+
+       start = code = mono_domain_code_reserve (domain, buf_len);
+
+       amd64_mov_reg_imm (code, AMD64_RAX, arg);
+       amd64_jump_code (code, addr);
+       g_assert ((code - start) < buf_len);
+
+       nacl_domain_code_validate (domain, &start, buf_len, &code);
+       mono_arch_flush_icache (start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+
+       g_assert (0);
+       return start;
+}
+
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *code, *buf;
+       int buf_len, cfa_offset;
+       GSList *unwind_ops = NULL;
+       MonoJumpInfo *ji = NULL;
+       int n_arg_regs, n_arg_fregs, framesize, i;
+       int info_offset, offset, rgctx_arg_reg_offset;
+       int caller_reg_area_offset, callee_reg_area_offset, callee_stack_area_offset;
+       guint8 *br_out, *br [64], *br_ret [64];
+       int b_ret_index;
+       int reg_area_size;
+
+       buf_len = 2048;
+       buf = code = mono_global_codeman_reserve (buf_len);
+
+       /*
+        * We are being called by an gsharedvt arg trampoline, the info argument is in AMD64_RAX.
+        */
+       n_arg_regs = PARAM_REGS;
+       n_arg_fregs = FLOAT_PARAM_REGS;
+
+       /* Compute stack frame size and offsets */
+       offset = 0;
+       /* info reg */
+       info_offset = offset;
+       offset += 8;
+
+       /* rgctx reg */
+       rgctx_arg_reg_offset = offset;
+       offset += 8;
+
+       /*callconv in regs */
+       caller_reg_area_offset = offset;
+       reg_area_size = ALIGN_TO ((n_arg_regs + n_arg_fregs) * 8, MONO_ARCH_FRAME_ALIGNMENT);
+       offset += reg_area_size;
+
+       framesize = offset;
+
+       g_assert (framesize % MONO_ARCH_FRAME_ALIGNMENT == 0);
+       g_assert (reg_area_size % MONO_ARCH_FRAME_ALIGNMENT == 0);
+
+       /* unwind markers 1/3 */
+       cfa_offset = sizeof (gpointer);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, AMD64_RSP, cfa_offset);
+       mono_add_unwind_op_offset (unwind_ops, code, buf, AMD64_RIP, -cfa_offset);
+
+       /* save the old frame pointer */
+       amd64_push_reg (code, AMD64_RBP);
+
+       /* unwind markers 2/3 */
+       cfa_offset += sizeof (gpointer);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
+       mono_add_unwind_op_offset (unwind_ops, code, buf, AMD64_RBP, - cfa_offset);
+
+       /* set it as the new frame pointer */
+       amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, sizeof(mgreg_t));
+
+       /* unwind markers 3/3 */
+       mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, AMD64_RBP);
+
+       /* setup the frame */
+       amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, framesize);
+       
+       /* save stuff */
+
+       /* save info */
+       amd64_mov_membase_reg (code, AMD64_RSP, info_offset, AMD64_RAX, sizeof (mgreg_t));
+       /* save rgctx */
+       amd64_mov_membase_reg (code, AMD64_RSP, rgctx_arg_reg_offset, MONO_ARCH_RGCTX_REG, sizeof (mgreg_t));
+
+       for (i = 0; i < n_arg_regs; ++i)
+               amd64_mov_membase_reg (code, AMD64_RSP, caller_reg_area_offset + i * 8, param_regs [i], sizeof (mgreg_t));
+
+       for (i = 0; i < n_arg_fregs; ++i)
+               amd64_sse_movsd_membase_reg (code, AMD64_RSP, caller_reg_area_offset + (i + n_arg_regs) * 8, i);
+
+       /* TODO Allocate stack area used to pass arguments to the method */
+
+
+       /* Allocate callee register area just below the caller area so it can be accessed from start_gsharedvt_call using negative offsets */
+       /* XXX figure out alignment */
+       callee_reg_area_offset = reg_area_size - ((n_arg_regs + n_arg_fregs) * 8); /* Ensure alignment */
+       callee_stack_area_offset = callee_reg_area_offset + reg_area_size;
+       amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, reg_area_size);
+
+       /* Allocate stack area used to pass arguments to the method */
+       amd64_mov_reg_membase (code, AMD64_R11, AMD64_RAX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, stack_usage), 4);
+       amd64_alu_reg_reg (code, X86_SUB, AMD64_RSP, AMD64_R11);
+
+       /* The stack now looks like this:
+
+       <caller stack params area>
+       <return address>
+       <old frame pointer>
+       <caller registers area>
+       <rgctx>
+       <gsharedvt info>
+       <calee stack area>
+       <calee reg area>
+        */
+
+       /* Call start_gsharedvt_call () */
+       /* arg1 == info */
+       amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, AMD64_RAX, sizeof(mgreg_t));
+       /* arg2 = caller stack area */
+       amd64_lea_membase (code, MONO_AMD64_ARG_REG2, AMD64_RBP, -(framesize - caller_reg_area_offset)); 
+
+       /* arg3 == callee stack area */
+       amd64_lea_membase (code, MONO_AMD64_ARG_REG3, AMD64_RSP, callee_reg_area_offset);
+
+       /* arg4 = mrgctx reg */
+       amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG4, MONO_ARCH_RGCTX_REG, sizeof(mgreg_t));
+
+       if (aot) {
+               code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_amd64_start_gsharedvt_call");
+               amd64_call_reg (code, AMD64_R11);
+       } else {
+               g_error ("no aot");
+       }
+
+       /* Method to call is now on RAX. Restore regs and jump */
+       amd64_mov_reg_reg (code, AMD64_R11, AMD64_RAX, sizeof(mgreg_t));
+
+       for (i = 0; i < n_arg_regs; ++i)
+               amd64_mov_reg_membase (code, param_regs [i], AMD64_RSP, callee_reg_area_offset + i * 8, sizeof (mgreg_t));
+
+       for (i = 0; i < n_arg_fregs; ++i)
+               amd64_sse_movsd_reg_membase (code, i, AMD64_RSP, callee_reg_area_offset + (i + n_arg_regs) * 8);
+
+       //load rgctx
+       amd64_mov_reg_membase (code, MONO_ARCH_RGCTX_REG, AMD64_RBP, -(framesize - rgctx_arg_reg_offset), sizeof (mgreg_t));
+
+       /* Clear callee reg area */
+       amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, reg_area_size);
+
+       /* Call the thing */
+       amd64_call_reg (code, AMD64_R11);
+
+       /* Marshal return value. Available registers: R10 and R11 */
+       /* Load info struct */
+       amd64_mov_reg_membase (code, AMD64_R10, AMD64_RBP, -(framesize - info_offset), sizeof (mgreg_t));
+
+       /* Branch to the in/out handling code */
+       amd64_alu_membase_imm_size (code, X86_CMP, AMD64_R10, MONO_STRUCT_OFFSET (GSharedVtCallInfo, gsharedvt_in), 1, 4);
+
+       b_ret_index = 0;
+       br_out = code;
+       x86_branch32 (code, X86_CC_NE, 0, TRUE);
+
+       /*
+        * IN CASE
+        */
+
+       /* Load vret_slot */
+       amd64_mov_reg_membase (code, AMD64_RDI, AMD64_R10, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_slot), 4);
+       amd64_alu_reg_imm (code, X86_SUB, AMD64_RDI, n_arg_regs + n_arg_fregs);
+       amd64_shift_reg_imm (code, X86_SHL, AMD64_RDI, 3);
+
+       /* vret address is RBP - (framesize - caller_reg_area_offset) */
+       amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof(mgreg_t));
+       amd64_alu_reg_reg (code, X86_ADD, AMD64_R11, AMD64_RDI);
+
+       /* Load ret marshal type */
+       /* Load vret address in R11 */
+       amd64_mov_reg_membase (code, AMD64_R10, AMD64_R10, MONO_STRUCT_OFFSET (GSharedVtCallInfo, ret_marshal), 4);
+
+       for (i = GSHAREDVT_RET_NONE; i < GSHAREDVT_RET_NUM; ++i) {
+               amd64_alu_reg_imm (code, X86_CMP, AMD64_R10, i);
+               br [i] = code;
+               amd64_branch8 (code, X86_CC_EQ, 0, TRUE);
+       }
+       x86_breakpoint (code); /* unhandled case */
+
+       for (i = GSHAREDVT_RET_NONE; i < GSHAREDVT_RET_NUM; ++i) {
+               mono_amd64_patch (br [i], code);
+               switch (i) {
+               case GSHAREDVT_RET_NONE:
+                       break;
+               case GSHAREDVT_RET_I1:
+                       amd64_widen_membase (code, AMD64_RAX, AMD64_R11, 0, TRUE, FALSE);
+                       break;
+               case GSHAREDVT_RET_U1:
+                       amd64_widen_membase (code, AMD64_RAX, AMD64_R11, 0, FALSE, FALSE);
+                       break;
+               case GSHAREDVT_RET_I2:
+                       amd64_widen_membase (code, AMD64_RAX, AMD64_R11, 0, TRUE, TRUE);
+                       break;
+               case GSHAREDVT_RET_U2:
+                       amd64_widen_membase (code, AMD64_RAX, AMD64_R11, 0, FALSE, TRUE);
+                       break;
+               case GSHAREDVT_RET_I4: // CORRECT
+               case GSHAREDVT_RET_U4: // THIS IS INCORRECT. WHY IS IT NOT FAILING?
+                       amd64_movsxd_reg_membase (code, AMD64_RAX, AMD64_R11, 0);
+                       break;
+               case GSHAREDVT_RET_I8:
+                       amd64_mov_reg_membase (code, AMD64_RAX, AMD64_R11, 0, 8);
+                       break;
+               case GSHAREDVT_RET_IREGS_1:
+                       amd64_mov_reg_membase (code, return_regs [i - GSHAREDVT_RET_IREGS_1], AMD64_R11, 0, 8);
+                       break;
+               case GSHAREDVT_RET_R8:
+                       amd64_sse_movsd_reg_membase (code, AMD64_XMM0, AMD64_R11, 0);
+                       break;
+               default:
+                       x86_breakpoint (code); /* can't handle specific case */
+               }
+
+               br_ret [b_ret_index ++] = code;
+               x86_jump32 (code, 0);
+       }
+
+       /*
+        * OUT CASE
+        */
+       mono_amd64_patch (br_out, code);
+
+       /*
+               Address to write return to is in the original value of the register specified by vret_arg_reg.
+               This will be either RSI or RDI depending on whether this is a static call.
+               Its location:
+               We alloc 'framesize' bytes below RBP to save regs, info and rgctx. RSP = RBP - framesize
+               We store rdi at RSP + caller_reg_area_offset + slot_index_of (register) * 8.
+
+               address: RBP - framesize + caller_reg_area_offset + 8*slot
+       */
+
+       int caller_vret_offset = caller_reg_area_offset - framesize;
+
+       /* Load vret address in R11 */
+       /* Position to return to is passed as a hidden argument. Load 'vret_arg_slot' to find it */
+       amd64_movsxd_reg_membase (code, AMD64_R11, AMD64_R10, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_arg_reg));
+
+       // In the GSHAREDVT_RET_NONE case, vret_arg_slot is -1. In this case, skip marshalling.
+       amd64_alu_reg_imm (code, X86_CMP, AMD64_R11, 0);
+       br_ret [b_ret_index ++] = code;
+       amd64_branch32 (code, X86_CC_LT, 0, TRUE);
+
+       /* Compute ret area address in the caller frame, *( ((gpointer *)RBP) [R11+2] ) */
+       amd64_shift_reg_imm (code, X86_SHL, AMD64_R11, 3);
+       amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, caller_vret_offset);
+       amd64_alu_reg_reg (code, X86_ADD, AMD64_R11, AMD64_RBP);
+       amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, sizeof (gpointer));
+
+       /* Load ret marshal type in R10 */
+       amd64_mov_reg_membase (code, AMD64_R10, AMD64_R10, MONO_STRUCT_OFFSET (GSharedVtCallInfo, ret_marshal), 4);
+
+       // Switch table for ret_marshal value
+       for (i = GSHAREDVT_RET_NONE; i < GSHAREDVT_RET_NUM; ++i) {
+               amd64_alu_reg_imm (code, X86_CMP, AMD64_R10, i);
+               br [i] = code;
+               amd64_branch8 (code, X86_CC_EQ, 0, TRUE);
+       }
+       x86_breakpoint (code); /* unhandled case */
+
+       for (i = GSHAREDVT_RET_NONE; i < GSHAREDVT_RET_NUM; ++i) {
+               mono_amd64_patch (br [i], code);
+               switch (i) {
+               case GSHAREDVT_RET_NONE:
+                       break;
+               case GSHAREDVT_RET_IREGS_1:
+                       amd64_mov_membase_reg (code, AMD64_R11, 0, return_regs [i - GSHAREDVT_RET_IREGS_1], 8);
+                       break;
+               case GSHAREDVT_RET_R8:
+                       amd64_sse_movsd_membase_reg (code, AMD64_R11, 0, AMD64_XMM0);
+                       break;
+               default:
+                       x86_breakpoint (code); /* can't handle specific case */
+               }
+
+               br_ret [b_ret_index ++] = code;
+               x86_jump32 (code, 0);
+       }
+
+       /* exit path */
+       for (i = 0; i < b_ret_index; ++i)
+               mono_amd64_patch (br_ret [i], code);
+
+       /* Exit code path */
+       amd64_leave (code);
+       amd64_ret (code);
+
+       g_assert ((code - buf) < buf_len);
+
+       if (info)
+               *info = mono_tramp_info_create ("gsharedvt_trampoline", buf, code - buf, ji, unwind_ops);
+
+       mono_arch_flush_icache (buf, code - buf);
+       return buf;
+}
+
+#else
+
+gpointer
+mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+#endif
+
+#else
+
+gpointer
+mono_amd64_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       *info = NULL;
+       return NULL;
+}
+
+#endif
\ No newline at end of file
index a5ba7000e4089c1607a0dc8ccfb9747f8e6944ac..05fb2cecac28d58dd2f4146a7bc60ec6d434763c 100644 (file)
@@ -8,6 +8,7 @@
  * (C) 2001 Ximian, Inc.
  * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -1009,32 +1010,3 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo
 
        return buf;
 }
-
-#if defined(ENABLE_GSHAREDVT) && defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
-
-#include "../../../mono-extensions/mono/mini/tramp-amd64-gsharedvt.c"
-
-#else
-
-gpointer
-mono_amd64_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg)
-{
-       g_assert_not_reached ();
-       return NULL;
-}
-
-gpointer
-mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr)
-{
-       g_assert_not_reached ();
-       return NULL;
-}
-
-gpointer
-mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
-{
-       *info = NULL;
-       return NULL;
-}
-
-#endif /* !ENABLE_GSHAREDVT */
diff --git a/mono/mini/tramp-arm-gsharedvt.c b/mono/mini/tramp-arm-gsharedvt.c
new file mode 100644 (file)
index 0000000..f84c542
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * tramp-arm-gsharedvt.c: gsharedvt support code for arm
+ *
+ * Authors:
+ *   Zoltan Varga <vargaz@gmail.com>
+ *
+ * Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <config.h>
+#include <glib.h>
+
+#include <mono/metadata/abi-details.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/marshal.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/profiler-private.h>
+#include <mono/arch/arm/arm-codegen.h>
+#include <mono/arch/arm/arm-vfp-codegen.h>
+
+#include "mini.h"
+#include "mini-arm.h"
+
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+
+#ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
+
+static inline guint8*
+emit_bx (guint8* code, int reg)
+{
+       if (mono_arm_thumb_supported ())
+               ARM_BX (code, reg);
+       else
+               ARM_MOV_REG_REG (code, ARMREG_PC, reg);
+       return code;
+}
+
+
+gpointer
+mono_arm_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg)
+{
+       int i;
+
+       /*
+        * The caller/callee regs are mapped to slot 0..3, stack slot 0 is mapped to slot 4, etc.
+        */
+
+       /* Set vtype ret arg */
+       if (info->vret_slot != -1) {
+               callee [info->vret_arg_reg] = &callee [info->vret_slot];
+       }
+
+       for (i = 0; i < info->map_count; ++i) {
+               int src = info->map [i * 2];
+               int dst = info->map [(i * 2) + 1];
+               int arg_marshal = (src >> 16) & 0xff;
+
+               switch (arg_marshal) {
+               case GSHAREDVT_ARG_NONE:
+                       callee [dst] = caller [src];
+                       break;
+               case GSHAREDVT_ARG_BYVAL_TO_BYREF:
+                       /* gsharedvt argument passed by addr in reg/stack slot */
+                       src = src & 0xffff;
+                       callee [dst] = caller + src;
+                       break;
+               case GSHAREDVT_ARG_BYREF_TO_BYVAL: {
+                       /* gsharedvt argument passed by value */
+                       int nslots = (src >> 4) & 0xff;
+                       int src_slot = src & 0xf;
+                       int j;
+                       gpointer *addr = caller [src_slot];
+
+                       for (j = 0; j < nslots; ++j)
+                               callee [dst + j] = addr [j];
+                       break;
+               }
+               case GSHAREDVT_ARG_BYREF_TO_BYVAL_I1: {
+                       int src_slot = src & 0xf;
+                       gpointer *addr = caller [src_slot];
+
+                       callee [dst] = GINT_TO_POINTER ((int)*(gint8*)addr);
+                       break;
+               }
+               case GSHAREDVT_ARG_BYREF_TO_BYVAL_I2: {
+                       int src_slot = src & 0xf;
+                       gpointer *addr = caller [src_slot];
+
+                       callee [dst] = GINT_TO_POINTER ((int)*(gint16*)addr);
+                       break;
+               }
+               case GSHAREDVT_ARG_BYREF_TO_BYVAL_U1: {
+                       int src_slot = src & 0xf;
+                       gpointer *addr = caller [src_slot];
+
+                       callee [dst] = GUINT_TO_POINTER ((guint)*(guint8*)addr);
+                       break;
+               }
+               case GSHAREDVT_ARG_BYREF_TO_BYVAL_U2: {
+                       int src_slot = src & 0xf;
+                       gpointer *addr = caller [src_slot];
+
+                       callee [dst] = GUINT_TO_POINTER ((guint)*(guint16*)addr);
+                       break;
+               }
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+       }
+
+       if (info->vcall_offset != -1) {
+               MonoObject *this_obj = caller [0];
+
+               if (G_UNLIKELY (!this_obj))
+                       return NULL;
+               if (info->vcall_offset == MONO_GSHAREDVT_DEL_INVOKE_VT_OFFSET)
+                       /* delegate invoke */
+                       return ((MonoDelegate*)this_obj)->invoke_impl;
+               else
+                       return *(gpointer*)((char*)this_obj->vtable + info->vcall_offset);
+       } else if (info->calli) {
+               /* The address to call is passed in the mrgctx reg */
+               return mrgctx_reg;
+       } else {
+               return info->addr;
+       }
+}
+
+#ifndef DISABLE_JIT
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *code, *buf;
+       int buf_len, cfa_offset;
+       GSList *unwind_ops = NULL;
+       MonoJumpInfo *ji = NULL;
+       guint8 *br_out, *br [16], *br_ret [16];
+       int i, arg_reg, npushed, info_offset, mrgctx_offset, caller_reg_area_offset, callee_reg_area_offset;
+       int lr_offset, fp, br_ret_index, args_size;
+
+       buf_len = 512;
+       buf = code = mono_global_codeman_reserve (buf_len);
+
+       arg_reg = ARMREG_R0;
+       /* Registers pushed by the arg trampoline */
+       npushed = 4;
+
+       // ios abi compatible frame
+       fp = ARMREG_R7;
+       cfa_offset = npushed * sizeof (gpointer);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, ARMREG_SP, cfa_offset);
+       ARM_PUSH (code, (1 << fp) | (1 << ARMREG_LR));
+       cfa_offset += 2 * sizeof (gpointer);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
+       mono_add_unwind_op_offset (unwind_ops, code, buf, fp, (- cfa_offset));
+       mono_add_unwind_op_offset (unwind_ops, code, buf, ARMREG_LR, ((- cfa_offset) + 4));
+       ARM_MOV_REG_REG (code, fp, ARMREG_SP);
+       mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, fp);
+       /* Allocate stack frame */
+       ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 32);
+       info_offset = -4;
+       mrgctx_offset = -8;
+       callee_reg_area_offset = - (6 * 4);
+       caller_reg_area_offset = cfa_offset - (npushed * sizeof (gpointer));
+       lr_offset = 4;
+       /* Save info struct which is in r0 */
+       ARM_STR_IMM (code, arg_reg, fp, info_offset);
+       /* Save rgctx reg */
+       ARM_STR_IMM (code, MONO_ARCH_RGCTX_REG, fp, mrgctx_offset);
+       /* Allocate callee area */
+       ARM_LDR_IMM (code, ARMREG_IP, arg_reg, MONO_STRUCT_OFFSET (GSharedVtCallInfo, stack_usage));
+       ARM_SUB_REG_REG (code, ARMREG_SP, ARMREG_SP, ARMREG_IP);
+       /* Allocate callee register area just below the callee area so it can be accessed from start_gsharedvt_call using negative offsets */
+       ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 4 * sizeof (gpointer));
+
+       /*
+        * The stack now looks like this:
+        * <caller frame>
+        * <saved r0-r3, lr>
+        * <saved fp> <- fp
+        * <our frame>
+        * <callee area> <- sp
+        */
+       g_assert (mono_arm_thumb_supported ());
+
+       /* Call start_gsharedvt_call () */
+       /* 4 arguments, needs 0 stack slot, need to clean it up after the call */
+       args_size = 0 * sizeof (gpointer);
+       ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, args_size);
+       /* arg1 == info */
+       ARM_LDR_IMM (code, ARMREG_R0, fp, info_offset);
+       /* arg2 == caller stack area */
+       ARM_ADD_REG_IMM8 (code, ARMREG_R1, fp, cfa_offset - 4 * sizeof (gpointer));
+       /* arg3 == callee stack area */
+       ARM_ADD_REG_IMM8 (code, ARMREG_R2, ARMREG_SP, args_size);
+       /* arg4 == mrgctx reg */
+       ARM_LDR_IMM (code, ARMREG_R3, fp, mrgctx_offset);
+       /* Make the call */
+       if (aot) {
+               ji = mono_patch_info_list_prepend (ji, code - buf, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_arm_start_gsharedvt_call");
+               ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
+               ARM_B (code, 0);
+               *(gpointer*)code = NULL;
+               code += 4;
+               ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP);
+       } else {
+               ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
+               ARM_B (code, 0);
+               *(gpointer*)code = mono_arm_start_gsharedvt_call;
+               code += 4;
+       }
+       ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
+       code = emit_bx (code, ARMREG_IP);
+       /* Clean up stack */
+       ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, args_size);
+
+       /* Make the real method call */
+       /* R0 contains the addr to call */
+       ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_R0);
+       /* Load argument registers */
+       ARM_LDM (code, ARMREG_SP, (1 << ARMREG_R0) | (1 << ARMREG_R1) | (1 << ARMREG_R2) | (1 << ARMREG_R3));
+       /* Pop callee register area */
+       ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 4 * sizeof (gpointer));
+       /* Load rgctx */
+       ARM_LDR_IMM (code, MONO_ARCH_RGCTX_REG, fp, mrgctx_offset);
+       /* Make the call */
+#if 0
+       ARM_LDR_IMM (code, ARMREG_IP, fp, info_offset);
+       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, MONO_STRUCT_OFFSET (GSharedVtCallInfo, addr));
+#endif
+       /* mono_arch_find_imt_method () depends on this */
+       ARM_ADD_REG_IMM8 (code, ARMREG_LR, ARMREG_PC, 4);
+       ARM_BX (code, ARMREG_IP);
+       *((gpointer*)code) = NULL;
+       code += 4;
+
+       br_ret_index = 0;
+
+       /* Branch between IN/OUT cases */
+       ARM_LDR_IMM (code, ARMREG_IP, fp, info_offset);
+       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, MONO_STRUCT_OFFSET (GSharedVtCallInfo, gsharedvt_in));
+
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, 1);
+       br_out = code;
+       ARM_B_COND (code, ARMCOND_NE, 0);
+
+       /* IN CASE */
+
+       /* LR == return marshalling type */
+       ARM_LDR_IMM (code, ARMREG_IP, fp, info_offset);
+       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, MONO_STRUCT_OFFSET (GSharedVtCallInfo, ret_marshal));
+
+       /* Continue if no marshalling required */
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, GSHAREDVT_RET_NONE);
+       br_ret [br_ret_index ++] = code;
+       ARM_B_COND (code, ARMCOND_EQ, 0);
+
+       /* Compute vret area address in LR */
+       ARM_LDR_IMM (code, ARMREG_LR, fp, info_offset);
+       ARM_LDR_IMM (code, ARMREG_LR, ARMREG_LR, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_slot));
+       /* The slot value is off by 4 */
+       ARM_SUB_REG_IMM8 (code, ARMREG_LR, ARMREG_LR, 4);
+       ARM_SHL_IMM (code, ARMREG_LR, ARMREG_LR, 2);
+       ARM_ADD_REG_REG (code, ARMREG_LR, ARMREG_LR, ARMREG_SP);
+
+       /* Branch to specific marshalling code */
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, GSHAREDVT_RET_IREG);
+       br [0] = code;
+       ARM_B_COND (code, ARMCOND_EQ, 0);
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, GSHAREDVT_RET_IREGS);
+       br [1] = code;
+       ARM_B_COND (code, ARMCOND_EQ, 0);
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, GSHAREDVT_RET_I1);
+       br [2] = code;
+       ARM_B_COND (code, ARMCOND_EQ, 0);
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, GSHAREDVT_RET_U1);
+       br [3] = code;
+       ARM_B_COND (code, ARMCOND_EQ, 0);
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, GSHAREDVT_RET_I2);
+       br [4] = code;
+       ARM_B_COND (code, ARMCOND_EQ, 0);
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, GSHAREDVT_RET_U2);
+       br [5] = code;
+       ARM_B_COND (code, ARMCOND_EQ, 0);
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+
+       /* IN IREG case */
+       arm_patch (br [0], code);
+       ARM_LDR_IMM (code, ARMREG_R0, ARMREG_LR, 0);
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+       /* IN IREGS case */
+       arm_patch (br [1], code);
+       ARM_LDR_IMM (code, ARMREG_R0, ARMREG_LR, 0);
+       ARM_LDR_IMM (code, ARMREG_R1, ARMREG_LR, 4);
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+       /* I1 case */
+       arm_patch (br [2], code);
+       ARM_LDRSB_IMM (code, ARMREG_R0, ARMREG_LR, 0);
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+       /* U1 case */
+       arm_patch (br [3], code);
+       ARM_LDRB_IMM (code, ARMREG_R0, ARMREG_LR, 0);
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+       /* I2 case */
+       arm_patch (br [4], code);
+       ARM_LDRSH_IMM (code, ARMREG_R0, ARMREG_LR, 0);
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+       /* U2 case */
+       arm_patch (br [5], code);
+       ARM_LDRH_IMM (code, ARMREG_R0, ARMREG_LR, 0);
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+
+       /* OUT CASE */
+       arm_patch (br_out, code);
+
+       /* Marshal return value */
+       ARM_LDR_IMM (code, ARMREG_IP, fp, info_offset);
+       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, MONO_STRUCT_OFFSET (GSharedVtCallInfo, ret_marshal));
+
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, GSHAREDVT_RET_IREGS);
+       br [0] = code;
+       ARM_B_COND (code, ARMCOND_NE, 0);
+
+       /* OUT IREGS case */
+       /* Load vtype ret addr from the caller arg regs */
+       ARM_LDR_IMM (code, ARMREG_IP, fp, info_offset);
+       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_arg_reg));
+       ARM_SHL_IMM (code, ARMREG_IP, ARMREG_IP, 2);
+       ARM_ADD_REG_REG (code, ARMREG_IP, ARMREG_IP, fp);
+       ARM_ADD_REG_IMM8 (code, ARMREG_IP, ARMREG_IP, caller_reg_area_offset);
+       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 0);
+       /* Save both registers for simplicity */
+       ARM_STR_IMM (code, ARMREG_R0, ARMREG_IP, 0);
+       ARM_STR_IMM (code, ARMREG_R1, ARMREG_IP, 4);
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+       arm_patch (br [0], code);
+
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, GSHAREDVT_RET_IREG);
+       br [0] = code;
+       ARM_B_COND (code, ARMCOND_NE, 0);
+
+       /* OUT IREG case */
+       /* Load vtype ret addr from the caller arg regs */
+       ARM_LDR_IMM (code, ARMREG_IP, fp, info_offset);
+       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_arg_reg));
+       ARM_SHL_IMM (code, ARMREG_IP, ARMREG_IP, 2);
+       ARM_ADD_REG_REG (code, ARMREG_IP, ARMREG_IP, fp);
+       ARM_ADD_REG_IMM8 (code, ARMREG_IP, ARMREG_IP, caller_reg_area_offset);
+       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 0);
+       /* Save the return value to the buffer pointed to by the vret addr */
+       ARM_STR_IMM (code, ARMREG_R0, ARMREG_IP, 0);
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+       arm_patch (br [0], code);
+
+       ARM_CMP_REG_IMM8 (code, ARMREG_IP, GSHAREDVT_RET_U1);
+       br [0] = code;
+       ARM_B_COND (code, ARMCOND_NE, 0);
+
+       /* OUT U1 case */
+       /* Load vtype ret addr from the caller arg regs */
+       ARM_LDR_IMM (code, ARMREG_IP, fp, info_offset);
+       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_arg_reg));
+       ARM_SHL_IMM (code, ARMREG_IP, ARMREG_IP, 2);
+       ARM_ADD_REG_REG (code, ARMREG_IP, ARMREG_IP, fp);
+       ARM_ADD_REG_IMM8 (code, ARMREG_IP, ARMREG_IP, caller_reg_area_offset);
+       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 0);
+       /* Save the return value to the buffer pointed to by the vret addr */
+       ARM_STRB_IMM (code, ARMREG_R0, ARMREG_IP, 0);
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+       arm_patch (br [0], code);
+
+       /* OUT other cases */
+       br_ret [br_ret_index ++] = code;
+       ARM_B (code, 0);
+
+       for (i = 0; i < br_ret_index; ++i)
+               arm_patch (br_ret [i], code);
+
+       /* Normal return */
+       /* Restore registers + stack */
+       ARM_MOV_REG_REG (code, ARMREG_SP, fp);
+       ARM_LDM (code, fp, (1 << fp) | (1 << ARMREG_LR));
+       ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, cfa_offset);
+       /* Return */
+       ARM_BX (code, ARMREG_LR);
+
+       g_assert ((code - buf) < buf_len);
+
+       if (info)
+               *info = mono_tramp_info_create ("gsharedvt_trampoline", buf, code - buf, ji, unwind_ops);
+
+       mono_arch_flush_icache (buf, code - buf);
+       return buf;
+}
+
+#else
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+#endif
+
+
+#else
+
+
+gpointer
+mono_arm_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       *info = NULL;
+       return NULL;
+}
+
+
+#endif
index 2430e2295ceda8979dab5340ee18e038b737c70b..5ff7bbfdfc8309b5105e0052c8b39dc1199e92b4 100644 (file)
@@ -7,6 +7,7 @@
  * (C) 2001-2003 Ximian, Inc.
  * Copyright 2003-2011 Novell Inc
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -910,7 +911,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 */
@@ -1134,25 +1135,3 @@ mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpoint
 }
 
 #endif
-
-#if defined(ENABLE_GSHAREDVT)
-
-#include "../../../mono-extensions/mono/mini/tramp-arm-gsharedvt.c"
-
-#else
-
-gpointer
-mono_arm_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg)
-{
-       g_assert_not_reached ();
-       return NULL;
-}
-
-gpointer
-mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
-{
-       *info = NULL;
-       return NULL;
-}
-
-#endif /* !MONOTOUCH */
diff --git a/mono/mini/tramp-arm64-gsharedvt.c b/mono/mini/tramp-arm64-gsharedvt.c
new file mode 100644 (file)
index 0000000..13f73d9
--- /dev/null
@@ -0,0 +1,582 @@
+/*
+ * tramp-arm64-gsharedvt.c: gsharedvt support code for arm64
+ *
+ * Authors:
+ *   Zoltan Varga <vargaz@gmail.com>
+ *
+ * Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <mono/metadata/abi-details.h>
+
+#include "mini.h"
+#include "mini-arm64.h"
+#include "mini-arm64-gsharedvt.h"
+
+/*
+ * GSHAREDVT
+ */
+#ifdef MONO_ARCH_GSHARED_SUPPORTED
+
+/*
+ * mono_arch_get_gsharedvt_arg_trampoline:
+ *
+ *   See tramp-x86.c for documentation.
+ */
+gpointer
+mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr)
+{
+       guint8 *code, *buf;
+       int buf_len = 40;
+
+       /*
+        * Return a trampoline which calls ADDR passing in ARG.
+        * Pass the argument in ip1, clobbering ip0.
+        */
+       buf = code = mono_global_codeman_reserve (buf_len);
+
+       code = mono_arm_emit_imm64 (code, ARMREG_IP1, (guint64)arg);
+       code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)addr);
+
+       arm_brx (code, ARMREG_IP0);
+
+       g_assert ((code - buf) < buf_len);
+       mono_arch_flush_icache (buf, code - buf);
+
+       return buf;
+}
+
+gpointer
+mono_arm_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg)
+{
+       int i;
+
+       /* Set vtype ret arg */
+       if (info->vret_slot != -1) {
+               g_assert (info->vret_slot);
+               callee [info->vret_arg_reg] = &callee [info->vret_slot];
+       }
+
+       for (i = 0; i < info->map_count; ++i) {
+               int src = info->map [i * 2];
+               int dst = info->map [(i * 2) + 1];
+               int arg_marshal = (src >> 18) & 0xf;
+               int arg_size = (src >> 22) & 0xf;
+
+               if (G_UNLIKELY (arg_size)) {
+                       int src_offset = (src >> 26) & 0xf;
+                       int dst_offset = (dst >> 26) & 0xf;
+                       int src_slot, dst_slot;
+                       guint8 *src_ptr, *dst_ptr;
+
+                       /*
+                        * Argument passed in part of a stack slot on ios.
+                        * src_offset/dst_offset is the offset within the stack slot.
+                        */
+                       switch (arg_marshal) {
+                       case GSHAREDVT_ARG_NONE:
+                               src_slot = src & 0xffff;
+                               dst_slot = dst & 0xffff;
+                               src_ptr = (guint8*)(caller + src_slot) + src_offset;
+                               dst_ptr = (guint8*)(callee + dst_slot) + dst_offset;
+                               break;
+                       case GSHAREDVT_ARG_BYREF_TO_BYVAL:
+                               src_slot = src & 0x3f;
+                               dst_slot = dst & 0xffff;
+                               src_ptr = caller [src_slot];
+                               dst_ptr = (guint8*)(callee + dst_slot) + dst_offset;
+                               break;
+                       case GSHAREDVT_ARG_BYVAL_TO_BYREF_HFAR4:
+                       case GSHAREDVT_ARG_BYREF_TO_BYVAL_HFAR4:
+                       case GSHAREDVT_ARG_BYREF_TO_BYREF:
+                               g_assert_not_reached ();
+                               break;
+                       case GSHAREDVT_ARG_BYVAL_TO_BYREF:
+                               src_slot = src & 0x3f;
+                               src_ptr = caller + src_slot + src_offset;
+                               callee [dst] = src_ptr;
+                               break;
+                       default:
+                               NOT_IMPLEMENTED;
+                               break;
+                       }
+
+                       if (arg_marshal == GSHAREDVT_ARG_BYVAL_TO_BYREF)
+                               continue;
+
+                       switch (arg_size) {
+                       case GSHAREDVT_ARG_SIZE_I1:
+                               *(gint8*)dst_ptr = *(gint8*)src_ptr;
+                               break;
+                       case GSHAREDVT_ARG_SIZE_U1:
+                               *(guint8*)dst_ptr = *(guint8*)src_ptr;
+                               break;
+                       case GSHAREDVT_ARG_SIZE_I2:
+                               *(gint16*)dst_ptr = *(gint16*)src_ptr;
+                               break;
+                       case GSHAREDVT_ARG_SIZE_U2:
+                               *(guint16*)dst_ptr = *(guint16*)src_ptr;
+                               break;
+                       case GSHAREDVT_ARG_SIZE_I4:
+                               *(gint32*)dst_ptr = *(gint32*)src_ptr;
+                               break;
+                       case GSHAREDVT_ARG_SIZE_U4:
+                               *(guint32*)dst_ptr = *(guint32*)src_ptr;
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                       }
+                       continue;
+               }
+
+               switch (arg_marshal) {
+               case GSHAREDVT_ARG_NONE:
+                       callee [dst] = caller [src];
+                       break;
+               case GSHAREDVT_ARG_BYVAL_TO_BYREF:
+                       /* gsharedvt argument passed by addr in reg/stack slot */
+                       src = src & 0x3f;
+                       callee [dst] = caller + src;
+                       break;
+               case GSHAREDVT_ARG_BYVAL_TO_BYREF_HFAR4: {
+                       int nslots = (src >> 6) & 0xff;
+                       int src_slot = src & 0x3f;
+                       int j;
+                       float *dst_arr = (float*)(caller + src_slot);
+
+                       /* The r4 hfa is in separate slots, need to compress them together in place */
+                       for (j = 0; j < nslots; ++j)
+                               dst_arr [j] = *(float*)(caller + src_slot + j);
+
+                       callee [dst] = caller + src_slot;
+                       break;
+               }
+               case GSHAREDVT_ARG_BYREF_TO_BYVAL: {
+                       int nslots = (src >> 6) & 0xff;
+                       int src_slot = src & 0x3f;
+                       int j;
+                       gpointer *addr = caller [src_slot];
+
+                       for (j = 0; j < nslots; ++j)
+                               callee [dst + j] = addr [j];
+                       break;
+               }
+               case GSHAREDVT_ARG_BYREF_TO_BYVAL_HFAR4: {
+                       int nslots = (src >> 6) & 0xff;
+                       int src_slot = src & 0x3f;
+                       int j;
+                       guint32 *addr = (guint32*)(caller [src_slot]);
+
+                       /* addr points to an array of floats, need to load them to registers */
+                       for (j = 0; j < nslots; ++j)
+                               callee [dst + j] = GUINT_TO_POINTER (addr [j]);
+                       break;
+               }
+               case GSHAREDVT_ARG_BYREF_TO_BYREF: {
+                       int src_slot = src & 0x3f;
+
+                       callee [dst] = caller [src_slot];
+                       break;
+               }
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+       }
+
+       if (info->vcall_offset != -1) {
+               MonoObject *this_obj = caller [0];
+
+               if (G_UNLIKELY (!this_obj))
+                       return NULL;
+               if (info->vcall_offset == MONO_GSHAREDVT_DEL_INVOKE_VT_OFFSET)
+                       /* delegate invoke */
+                       return ((MonoDelegate*)this_obj)->invoke_impl;
+               else
+                       return *(gpointer*)((char*)this_obj->vtable + info->vcall_offset);
+       } else if (info->calli) {
+               /* The address to call is passed in the mrgctx reg */
+               return mrgctx_reg;
+       } else {
+               return info->addr;
+       }
+}
+
+#ifndef DISABLE_JIT
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *code, *buf;
+       int buf_len, cfa_offset;
+       GSList *unwind_ops = NULL;
+       MonoJumpInfo *ji = NULL;
+       guint8 *br_out, *br [64], *br_ret [64], *bcc_ret [64];
+       int i, n_arg_regs, n_arg_fregs, offset, arg_reg, info_offset, rgctx_arg_reg_offset;
+       int caller_reg_area_offset, callee_reg_area_offset, callee_stack_area_offset;
+       int br_ret_index, bcc_ret_index;
+
+       buf_len = 2048;
+       buf = code = mono_global_codeman_reserve (buf_len);
+
+       /*
+        * We are being called by an gsharedvt arg trampoline, the info argument is in IP1.
+        */
+       arg_reg = ARMREG_IP1;
+       n_arg_regs = NUM_GSHAREDVT_ARG_GREGS;
+       n_arg_fregs = NUM_GSHAREDVT_ARG_FREGS;
+
+       /* Compute stack frame size and offsets */
+       offset = 0;
+       /* frame block */
+       offset += 2 * 8;
+       /* info argument */
+       info_offset = offset;
+       offset += 8;
+       /* saved rgctx */
+       rgctx_arg_reg_offset = offset;
+       offset += 8;
+       /* alignment */
+       offset += 8;
+       /* argument regs */
+       caller_reg_area_offset = offset;
+       offset += (n_arg_regs + n_arg_fregs) * 8;
+
+       /* We need the argument regs to be saved at the top of the frame */
+       g_assert (offset % MONO_ARCH_FRAME_ALIGNMENT == 0);
+
+       cfa_offset = offset;
+
+       /* Setup frame */
+       arm_stpx_pre (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, -cfa_offset);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, ARMREG_SP, cfa_offset);
+       mono_add_unwind_op_offset (unwind_ops, code, buf, ARMREG_FP, -cfa_offset + 0);
+       mono_add_unwind_op_offset (unwind_ops, code, buf, ARMREG_LR, -cfa_offset + 8);
+       arm_movspx (code, ARMREG_FP, ARMREG_SP);
+       mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, ARMREG_FP);
+
+       /* Save info argument */
+       arm_strx (code, arg_reg, ARMREG_FP, info_offset);
+
+       /* Save rgxctx */
+       arm_strx (code, MONO_ARCH_RGCTX_REG, ARMREG_FP, rgctx_arg_reg_offset);
+
+       /* Save argument regs below the stack arguments */
+       for (i = 0; i < n_arg_regs; ++i)
+               arm_strx (code, i, ARMREG_SP, caller_reg_area_offset + (i * 8));
+       // FIXME: Only do this if fp regs are used
+       for (i = 0; i < n_arg_fregs; ++i)
+               arm_strfpx (code, i, ARMREG_SP, caller_reg_area_offset + ((n_arg_regs + i) * 8));
+
+       /* Allocate callee area */
+       arm_ldrw (code, ARMREG_IP0, arg_reg, MONO_STRUCT_OFFSET (GSharedVtCallInfo, stack_usage));
+       arm_movspx (code, ARMREG_LR, ARMREG_SP);
+       arm_subx (code, ARMREG_LR, ARMREG_LR, ARMREG_IP0);
+       arm_movspx (code, ARMREG_SP, ARMREG_LR);
+       /* Allocate callee register area just below the callee area so it can be accessed from start_gsharedvt_call using negative offsets */
+       /* The + 8 is for alignment */
+       callee_reg_area_offset = 8;
+       callee_stack_area_offset = callee_reg_area_offset + (n_arg_regs * sizeof (gpointer));
+       arm_subx_imm (code, ARMREG_SP, ARMREG_SP, ((n_arg_regs + n_arg_fregs) * sizeof (gpointer)) + 8);
+
+       /*
+        * The stack now looks like this:
+        * <caller frame>
+        * <saved r0-r8>
+        * <our frame>
+        * <saved fp, lr> <- fp
+        * <callee area> <- sp
+        */
+
+       /* Call start_gsharedvt_call () */
+       /* arg1 == info */
+       arm_ldrx (code, ARMREG_R0, ARMREG_FP, info_offset);
+       /* arg2 = caller stack area */
+       arm_addx_imm (code, ARMREG_R1, ARMREG_FP, caller_reg_area_offset);
+       /* arg3 == callee stack area */
+       arm_addx_imm (code, ARMREG_R2, ARMREG_SP, callee_reg_area_offset);
+       /* arg4 = mrgctx reg */
+       arm_ldrx (code, ARMREG_R3, ARMREG_FP, rgctx_arg_reg_offset);
+
+       if (aot)
+               code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_arm_start_gsharedvt_call");
+       else
+               code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)mono_arm_start_gsharedvt_call);
+       arm_blrx (code, ARMREG_IP0);
+
+       /* Make the real method call */
+       /* R0 contains the addr to call */
+       arm_movx (code, ARMREG_IP1, ARMREG_R0);
+       /* Load rgxctx */
+       arm_ldrx (code, MONO_ARCH_RGCTX_REG, ARMREG_FP, rgctx_arg_reg_offset);
+       /* Load argument registers */
+       // FIXME:
+       for (i = 0; i < n_arg_regs; ++i)
+               arm_ldrx (code, i, ARMREG_SP, callee_reg_area_offset + (i * 8));
+       // FIXME: Only do this if needed
+       for (i = 0; i < n_arg_fregs; ++i)
+               arm_ldrfpx (code, i, ARMREG_SP, callee_reg_area_offset + ((n_arg_regs + i) * 8));
+       /* Clear callee reg area */
+       arm_addx_imm (code, ARMREG_SP, ARMREG_SP, ((n_arg_regs + n_arg_fregs) * sizeof (gpointer)) + 8);
+       /* Make the call */
+       arm_blrx (code, ARMREG_IP1);
+
+       br_ret_index = 0;
+       bcc_ret_index = 0;
+
+       // FIXME: Use a switch
+       /* Branch between IN/OUT cases */
+       arm_ldrx (code, ARMREG_IP1, ARMREG_FP, info_offset);
+       arm_ldrw (code, ARMREG_IP1, ARMREG_IP1, MONO_STRUCT_OFFSET (GSharedVtCallInfo, gsharedvt_in));
+       br_out = code;
+       arm_cbzx (code, ARMREG_IP1, 0);
+
+       /* IN CASE */
+
+       /* IP1 == return marshalling type */
+       arm_ldrx (code, ARMREG_IP1, ARMREG_FP, info_offset);
+       arm_ldrw (code, ARMREG_IP1, ARMREG_IP1, MONO_STRUCT_OFFSET (GSharedVtCallInfo, ret_marshal));
+
+       /* Continue if no marshalling required */
+       // FIXME: Use cmpx_imm
+       code = mono_arm_emit_imm64 (code, ARMREG_IP0, GSHAREDVT_RET_NONE);
+       arm_cmpx (code, ARMREG_IP0, ARMREG_IP1);
+       bcc_ret [bcc_ret_index ++] = code;
+       arm_bcc (code, ARMCOND_EQ, 0);
+
+       /* Compute vret area address in LR */
+       arm_ldrx (code, ARMREG_LR, ARMREG_FP, info_offset);
+       arm_ldrw (code, ARMREG_LR, ARMREG_LR, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_slot));
+       arm_subx_imm (code, ARMREG_LR, ARMREG_LR, n_arg_regs + n_arg_fregs);
+       arm_lslx (code, ARMREG_LR, ARMREG_LR, 3);
+       arm_movspx (code, ARMREG_IP0, ARMREG_SP);
+       arm_addx (code, ARMREG_LR, ARMREG_IP0, ARMREG_LR);
+
+       /* Branch to specific marshalling code */
+       for (i = GSHAREDVT_RET_NONE; i < GSHAREDVT_RET_NUM; ++i) {
+               code = mono_arm_emit_imm64 (code, ARMREG_IP0, i);
+               arm_cmpx (code, ARMREG_IP0, ARMREG_IP1);
+               br [i] = code;
+               arm_bcc (code, ARMCOND_EQ, 0);
+       }
+
+       arm_brk (code, 0);
+
+       /*
+        * The address of the return value area is in LR, have to load it into
+        * registers.
+        */
+       for (i = GSHAREDVT_RET_NONE; i < GSHAREDVT_RET_NUM; ++i) {
+               mono_arm_patch (br [i], code, MONO_R_ARM64_BCC);
+               switch (i) {
+               case GSHAREDVT_RET_NONE:
+                       break;
+               case GSHAREDVT_RET_I8:
+                       arm_ldrx (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_I1:
+                       arm_ldrsbx (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_U1:
+                       arm_ldrb (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_I2:
+                       arm_ldrshx (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_U2:
+                       arm_ldrh (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_I4:
+                       arm_ldrswx (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_U4:
+                       arm_ldrw (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_R8:
+                       arm_ldrfpx (code, ARMREG_D0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_R4:
+                       arm_ldrfpw (code, ARMREG_D0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_IREGS_1:
+               case GSHAREDVT_RET_IREGS_2:
+               case GSHAREDVT_RET_IREGS_3:
+               case GSHAREDVT_RET_IREGS_4:
+               case GSHAREDVT_RET_IREGS_5:
+               case GSHAREDVT_RET_IREGS_6:
+               case GSHAREDVT_RET_IREGS_7:
+               case GSHAREDVT_RET_IREGS_8: {
+                       int j;
+
+                       for (j = 0; j < i - GSHAREDVT_RET_IREGS_1 + 1; ++j)
+                               arm_ldrx (code, j, ARMREG_LR, j * 8);
+                       break;
+               }
+               case GSHAREDVT_RET_HFAR8_1:
+               case GSHAREDVT_RET_HFAR8_2:
+               case GSHAREDVT_RET_HFAR8_3:
+               case GSHAREDVT_RET_HFAR8_4: {
+                       int j;
+
+                       for (j = 0; j < i - GSHAREDVT_RET_HFAR8_1 + 1; ++j)
+                               arm_ldrfpx (code, j, ARMREG_LR, j * 8);
+                       break;
+               }
+               case GSHAREDVT_RET_HFAR4_1:
+               case GSHAREDVT_RET_HFAR4_2:
+               case GSHAREDVT_RET_HFAR4_3:
+               case GSHAREDVT_RET_HFAR4_4: {
+                       int j;
+
+                       for (j = 0; j < i - GSHAREDVT_RET_HFAR4_1 + 1; ++j)
+                               arm_ldrfpw (code, j, ARMREG_LR, j * 4);
+                       break;
+               }
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+               br_ret [br_ret_index ++] = code;
+               arm_b (code, 0);
+       }
+
+       /* OUT CASE */
+       mono_arm_patch (br_out, code, MONO_R_ARM64_CBZ);
+
+       /* Compute vret area address in LR */
+       arm_ldrx (code, ARMREG_LR, ARMREG_FP, caller_reg_area_offset + (ARMREG_R8 * 8));
+
+       /* IP1 == return marshalling type */
+       arm_ldrx (code, ARMREG_IP1, ARMREG_FP, info_offset);
+       arm_ldrw (code, ARMREG_IP1, ARMREG_IP1, MONO_STRUCT_OFFSET (GSharedVtCallInfo, ret_marshal));
+
+       /* Branch to specific marshalling code */
+       for (i = GSHAREDVT_RET_NONE; i < GSHAREDVT_RET_NUM; ++i) {
+               code = mono_arm_emit_imm64 (code, ARMREG_IP0, i);
+               arm_cmpx (code, ARMREG_IP0, ARMREG_IP1);
+               br [i] = code;
+               arm_bcc (code, ARMCOND_EQ, 0);
+       }
+
+       /*
+        * The return value is in registers, need to save to the return area passed by the caller in
+        * R8.
+        */
+       for (i = GSHAREDVT_RET_NONE; i < GSHAREDVT_RET_NUM; ++i) {
+               mono_arm_patch (br [i], code, MONO_R_ARM64_BCC);
+               switch (i) {
+               case GSHAREDVT_RET_NONE:
+                       break;
+               case GSHAREDVT_RET_I8:
+                       arm_strx (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_I1:
+               case GSHAREDVT_RET_U1:
+                       arm_strb (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_I2:
+               case GSHAREDVT_RET_U2:
+                       arm_strh (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_I4:
+               case GSHAREDVT_RET_U4:
+                       arm_strw (code, ARMREG_R0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_R8:
+                       arm_strfpx (code, ARMREG_D0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_R4:
+                       arm_strfpw (code, ARMREG_D0, ARMREG_LR, 0);
+                       break;
+               case GSHAREDVT_RET_IREGS_1:
+               case GSHAREDVT_RET_IREGS_2:
+               case GSHAREDVT_RET_IREGS_3:
+               case GSHAREDVT_RET_IREGS_4:
+               case GSHAREDVT_RET_IREGS_5:
+               case GSHAREDVT_RET_IREGS_6:
+               case GSHAREDVT_RET_IREGS_7:
+               case GSHAREDVT_RET_IREGS_8: {
+                       int j;
+
+                       for (j = 0; j < i - GSHAREDVT_RET_IREGS_1 + 1; ++j)
+                               arm_strx (code, j, ARMREG_LR, j * 8);
+                       break;
+               }
+               case GSHAREDVT_RET_HFAR8_1:
+               case GSHAREDVT_RET_HFAR8_2:
+               case GSHAREDVT_RET_HFAR8_3:
+               case GSHAREDVT_RET_HFAR8_4: {
+                       int j;
+
+                       for (j = 0; j < i - GSHAREDVT_RET_HFAR8_1 + 1; ++j)
+                               arm_strfpx (code, j, ARMREG_LR, j * 8);
+                       break;
+               }
+               case GSHAREDVT_RET_HFAR4_1:
+               case GSHAREDVT_RET_HFAR4_2:
+               case GSHAREDVT_RET_HFAR4_3:
+               case GSHAREDVT_RET_HFAR4_4: {
+                       int j;
+
+                       for (j = 0; j < i - GSHAREDVT_RET_HFAR4_1 + 1; ++j)
+                               arm_strfpw (code, j, ARMREG_LR, j * 4);
+                       break;
+               }
+               default:
+                       arm_brk (code, i);
+                       break;
+               }
+               br_ret [br_ret_index ++] = code;
+               arm_b (code, 0);
+       }
+
+       arm_brk (code, 0);
+
+       for (i = 0; i < br_ret_index; ++i)
+               mono_arm_patch (br_ret [i], code, MONO_R_ARM64_B);
+       for (i = 0; i < bcc_ret_index; ++i)
+               mono_arm_patch (bcc_ret [i], code, MONO_R_ARM64_BCC);
+
+       /* Normal return */
+       arm_movspx (code, ARMREG_SP, ARMREG_FP);
+       arm_ldpx_post (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, offset);
+       arm_retx (code, ARMREG_LR);
+
+       g_assert ((code - buf) < buf_len);
+
+       if (info)
+               *info = mono_tramp_info_create ("gsharedvt_trampoline", buf, code - buf, ji, unwind_ops);
+
+       mono_arch_flush_icache (buf, code - buf);
+       return buf;
+}
+
+#else
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+#endif
+
+#else
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       if (info)
+               *info = NULL;
+       return NULL;
+}
+
+gpointer
+mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+#endif /* MONO_ARCH_GSHARED_SUPPORTED */
\ No newline at end of file
index 16504375d849259e6969308533fcf70d29245161..5088fea22978419b52d1251e9be4633be87e6c81 100644 (file)
@@ -1 +1,616 @@
-#include "../../../mono-extensions/mono/mini/tramp-arm64.c"
+/*
+ * tramp-arm64.c: JIT trampoline code for ARM64
+ *
+ * Copyright 2013 Xamarin Inc
+ *
+ * Based on tramp-arm.c:
+ * 
+ * Authors:
+ *   Paolo Molaro (lupus@ximian.com)
+ *
+ * (C) 2001-2003 Ximian, Inc.
+ * Copyright 2003-2011 Novell Inc
+ * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "mini.h"
+#include "debugger-agent.h"
+
+#include <mono/arch/arm64/arm64-codegen.h>
+#include <mono/metadata/abi-details.h>
+
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+void
+mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr)
+{
+       mono_arm_patch (code_ptr - 4, addr, MONO_R_ARM64_BL);
+       mono_arch_flush_icache (code_ptr - 4, 4);
+}
+
+void
+mono_arch_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr)
+{
+       guint32 ins;
+       guint64 slot_addr;
+       int disp;
+
+       /* 
+        * Decode the address loaded by the PLT entry emitted by arch_emit_plt_entry () in
+        * aot-compiler.c
+        */
+
+       /* adrp */
+       ins = ((guint32*)code) [0];
+       g_assert (((ins >> 24) & 0x1f) == 0x10);
+       disp = (((ins >> 5) & 0x7ffff) << 2) | ((ins >> 29) & 0x3);
+       /* FIXME: disp is signed */
+       g_assert ((disp >> 20) == 0);
+
+       slot_addr = ((guint64)code + (disp << 12)) & ~0xfff;
+
+       /* add x16, x16, :lo12:got */
+       ins = ((guint32*)code) [1];
+       g_assert (((ins >> 22) & 0x3) == 0);
+       slot_addr += (ins >> 10) & 0xfff;
+
+       /* ldr x16, [x16, <offset>] */
+       ins = ((guint32*)code) [2];
+       g_assert (((ins >> 24) & 0x3f) == 0x39);
+       slot_addr += ((ins >> 10) & 0xfff) * 8;
+
+       g_assert (*(guint64*)slot_addr);
+       *(gpointer*)slot_addr = addr;
+}
+
+guint8*
+mono_arch_get_call_target (guint8 *code)
+{
+       guint32 imm;
+       int disp;
+
+       code -= 4;
+
+       imm = *(guint32*)code;
+       /* Should be a bl */
+       g_assert (((imm >> 31) & 0x1) == 0x1);
+       g_assert (((imm >> 26) & 0x7) == 0x5);
+
+       disp = (imm & 0x3ffffff);
+       if ((disp >> 25) != 0)
+               /* Negative, sing extend to 32 bits */
+               disp = disp | 0xfc000000;
+
+       return code + (disp * 4);
+}
+
+guint32
+mono_arch_get_plt_info_offset (guint8 *plt_entry, mgreg_t *regs, guint8 *code)
+{
+       /* The offset is stored as the 5th word of the plt entry */
+       return ((guint32*)plt_entry) [4];
+}
+
+#ifndef DISABLE_JIT
+
+guchar*
+mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *code, *buf, *tramp;
+       int i, buf_len, imm;
+       int frame_size, offset, gregs_offset, num_fregs, fregs_offset, arg_offset, lmf_offset;
+       guint64 gregs_regset;
+       GSList *unwind_ops = NULL;
+       MonoJumpInfo *ji = NULL;
+       char *tramp_name;
+
+       buf_len = 768;
+       buf = code = mono_global_codeman_reserve (buf_len);
+
+       /*
+        * We are getting called by a specific trampoline, ip1 contains the trampoline argument.
+        */
+
+       /* Compute stack frame size and offsets */
+       offset = 0;
+       /* frame block */
+       offset += 2 * 8;
+       /* gregs */
+       gregs_offset = offset;
+       offset += 32 * 8;
+       /* fregs */
+       // FIXME: Save 128 bits
+       /* Only have to save the argument regs */
+       num_fregs = 8;
+       fregs_offset = offset;
+       offset += num_fregs * 8;
+       /* arg */
+       arg_offset = offset;
+       offset += 8;
+       /* LMF */
+       lmf_offset = offset;
+       offset += sizeof (MonoLMF);
+       //offset += 22 * 8;
+       frame_size = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
+
+       /* Setup stack frame */
+       imm = frame_size;
+       while (imm > 256) {
+               arm_subx_imm (code, ARMREG_SP, ARMREG_SP, 256);
+               imm -= 256;
+       }
+       arm_subx_imm (code, ARMREG_SP, ARMREG_SP, imm);
+       arm_stpx (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, 0);
+       arm_movspx (code, ARMREG_FP, ARMREG_SP);
+
+       /* Save gregs */
+       // FIXME: Optimize this
+       gregs_regset = ~((1 << ARMREG_FP) | (1 << ARMREG_SP));
+       code = mono_arm_emit_store_regarray (code, gregs_regset, ARMREG_FP, gregs_offset);
+       /* Save fregs */
+       for (i = 0; i < num_fregs; ++i)
+               arm_strfpx (code, i, ARMREG_FP, fregs_offset + (i * 8));
+       /* Save trampoline arg */
+       arm_strx (code, ARMREG_IP1, ARMREG_FP, arg_offset);
+
+       /* Setup LMF */
+       arm_addx_imm (code, ARMREG_IP0, ARMREG_FP, lmf_offset);
+       code = mono_arm_emit_store_regset (code, MONO_ARCH_LMF_REGS, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, gregs));
+       /* Save caller fp */
+       arm_ldrx (code, ARMREG_IP1, ARMREG_FP, 0);
+       arm_strx (code, ARMREG_IP1, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, gregs) + (MONO_ARCH_LMF_REG_FP * 8));
+       /* Save caller sp */
+       arm_movx (code, ARMREG_IP1, ARMREG_FP);
+       imm = frame_size;
+       while (imm > 256) {
+               arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 256);
+               imm -= 256;
+       }
+       arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, imm);
+       arm_strx (code, ARMREG_IP1, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, gregs) + (MONO_ARCH_LMF_REG_SP * 8));
+       /* Save caller pc */
+       if (tramp_type == MONO_TRAMPOLINE_JUMP)
+               arm_movx (code, ARMREG_LR, ARMREG_RZR);
+       else
+               arm_ldrx (code, ARMREG_LR, ARMREG_FP, 8);
+       arm_strx (code, ARMREG_LR, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, pc));
+
+       /* Save LMF */
+       /* Similar to emit_save_lmf () */
+       if (aot) {
+               code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_get_lmf_addr");
+       } else {
+               tramp = (guint8*)mono_get_lmf_addr;
+               code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)tramp);
+       }
+       arm_blrx (code, ARMREG_IP0);
+       /* r0 contains the address of the tls slot holding the current lmf */
+       /* ip0 = lmf */
+       arm_addx_imm (code, ARMREG_IP0, ARMREG_FP, lmf_offset);
+       /* lmf->lmf_addr = lmf_addr */
+       arm_strx (code, ARMREG_R0, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, lmf_addr));
+       /* lmf->previous_lmf = *lmf_addr */
+       arm_ldrx (code, ARMREG_IP1, ARMREG_R0, 0);
+       arm_strx (code, ARMREG_IP1, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
+       /* *lmf_addr = lmf */
+       arm_strx (code, ARMREG_IP0, ARMREG_R0, 0);
+
+       /* Call the C trampoline function */
+       /* Arg 1 = gregs */
+       arm_addx_imm (code, ARMREG_R0, ARMREG_FP, gregs_offset);
+       /* Arg 2 = caller */
+       if (tramp_type == MONO_TRAMPOLINE_JUMP)
+               arm_movx (code, ARMREG_R1, ARMREG_RZR);
+       else
+               arm_ldrx (code, ARMREG_R1, ARMREG_FP, gregs_offset + (ARMREG_LR * 8));
+       /* Arg 3 = arg */
+       if (MONO_TRAMPOLINE_TYPE_HAS_ARG (tramp_type))
+               /* Passed in r0 */
+               arm_ldrx (code, ARMREG_R2, ARMREG_FP, gregs_offset + (ARMREG_R0 * 8));
+       else
+               arm_ldrx (code, ARMREG_R2, ARMREG_FP, arg_offset);
+       /* Arg 4 = trampoline addr */
+       arm_movx (code, ARMREG_R3, ARMREG_RZR);
+
+       if (aot) {
+               char *icall_name = g_strdup_printf ("trampoline_func_%d", tramp_type);
+               code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, icall_name);
+       } else {
+               tramp = (guint8*)mono_get_trampoline_func (tramp_type);
+               code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)tramp);
+       }
+       arm_blrx (code, ARMREG_IP0);
+
+       /* Restore LMF */
+       /* Similar to emit_restore_lmf () */
+       /* Clobbers ip0/ip1 */
+       /* ip0 = lmf */
+       arm_addx_imm (code, ARMREG_IP0, ARMREG_FP, lmf_offset);
+       /* ip1 = lmf->previous_lmf */
+       arm_ldrx (code, ARMREG_IP1, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
+       /* ip0 = lmf->lmf_addr */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, lmf_addr));
+       /* *lmf_addr = previous_lmf */
+       arm_strx (code, ARMREG_IP1, ARMREG_IP0, 0);
+
+       /* Save the result to ip1 */
+       arm_movx (code, ARMREG_IP1, ARMREG_R0);
+
+       /* Restore gregs */
+       /* Only have to load the argument regs (r0..r8) and the rgctx reg */
+       code = mono_arm_emit_load_regarray (code, 0x1ff | (1 << ARMREG_LR) | (1 << MONO_ARCH_RGCTX_REG), ARMREG_FP, gregs_offset);
+       /* Restore fregs */
+       for (i = 0; i < num_fregs; ++i)
+               arm_ldrfpx (code, i, ARMREG_FP, fregs_offset + (i * 8));
+
+       /* These trampolines return a value */
+       if (tramp_type == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH)
+               arm_movx (code, ARMREG_R0, ARMREG_IP1);
+
+       /* Cleanup frame */
+       code = mono_arm_emit_destroy_frame (code, frame_size, ((1 << ARMREG_IP0)));
+
+       if (tramp_type == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH)
+               arm_retx (code, ARMREG_LR);
+       else
+               arm_brx (code, ARMREG_IP1);
+
+       g_assert ((code - buf) < buf_len);
+       mono_arch_flush_icache (buf, code - buf);
+
+       if (info) {
+               tramp_name = mono_get_generic_trampoline_name (tramp_type);
+               *info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
+               g_free (tramp_name);
+       }
+
+       return buf;
+}
+
+gpointer
+mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len)
+{
+       guint8 *code, *buf, *tramp;
+       int buf_len = 64;
+
+       /*
+        * Return a trampoline which calls generic trampoline TRAMP_TYPE passing in ARG1.
+        * Pass the argument in ip1, clobbering ip0.
+        */
+       tramp = mono_get_trampoline_code (tramp_type);
+
+       buf = code = mono_global_codeman_reserve (buf_len);
+
+       code = mono_arm_emit_imm64 (code, ARMREG_IP1, (guint64)arg1);
+       code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)tramp);
+
+       arm_brx (code, ARMREG_IP0);
+
+       g_assert ((code - buf) < buf_len);
+       mono_arch_flush_icache (buf, code - buf);
+       if (code_len)
+               *code_len = code - buf;
+
+       return buf;
+}
+
+gpointer
+mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
+{
+       guint8 *code, *start;
+       guint32 size = 32;
+       MonoDomain *domain = mono_domain_get ();
+
+       start = code = mono_domain_code_reserve (domain, size);
+       code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)addr);
+       arm_addx_imm (code, ARMREG_R0, ARMREG_R0, sizeof (MonoObject));
+       arm_brx (code, ARMREG_IP0);
+
+       g_assert ((code - start) <= size);
+       mono_arch_flush_icache (start, code - start);
+       return start;
+}
+
+gpointer
+mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericContext *mrgctx, gpointer addr)
+{
+       guint8 *code, *start;
+       guint32 buf_len = 32;
+       MonoDomain *domain = mono_domain_get ();
+
+       start = code = mono_domain_code_reserve (domain, buf_len);
+       code = mono_arm_emit_imm64 (code, MONO_ARCH_RGCTX_REG, (guint64)mrgctx);
+       code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)addr);
+       arm_brx (code, ARMREG_IP0);
+
+       g_assert ((code - start) <= buf_len);
+
+       mono_arch_flush_icache (start, code - start);
+
+       return start;
+}
+
+gpointer
+mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *code, *buf;
+       int buf_size;
+       int i, depth, index, njumps;
+       gboolean is_mrgctx;
+       guint8 **rgctx_null_jumps;
+       MonoJumpInfo *ji = NULL;
+       GSList *unwind_ops = NULL;
+       guint8 *tramp;
+       guint32 code_len;
+
+       is_mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
+       index = MONO_RGCTX_SLOT_INDEX (slot);
+       if (is_mrgctx)
+               index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
+       for (depth = 0; ; ++depth) {
+               int size = mono_class_rgctx_get_array_size (depth, is_mrgctx);
+
+               if (index < size - 1)
+                       break;
+               index -= size - 1;
+       }
+
+       buf_size = 64 + 16 * depth;
+       code = buf = mono_global_codeman_reserve (buf_size);
+
+       rgctx_null_jumps = g_malloc0 (sizeof (guint8*) * (depth + 2));
+       njumps = 0;
+
+       /* The vtable/mrgtx is in R0 */
+       g_assert (MONO_ARCH_VTABLE_REG == ARMREG_R0);
+
+       if (is_mrgctx) {
+               /* get mrgctx ptr */
+               arm_movx (code, ARMREG_IP1, ARMREG_R0);
+       } else {
+               /* load rgctx ptr from vtable */
+               code = mono_arm_emit_ldrx (code, ARMREG_IP1, ARMREG_R0, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context));
+               /* is the rgctx ptr null? */
+               /* if yes, jump to actual trampoline */
+               rgctx_null_jumps [njumps ++] = code;
+               arm_cbzx (code, ARMREG_IP1, 0);
+       }
+
+       for (i = 0; i < depth; ++i) {
+               /* load ptr to next array */
+               if (is_mrgctx && i == 0) {
+                       code = mono_arm_emit_ldrx (code, ARMREG_IP1, ARMREG_IP1, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT);
+               } else {
+                       code = mono_arm_emit_ldrx (code, ARMREG_IP1, ARMREG_IP1, 0);
+               }
+               /* is the ptr null? */
+               /* if yes, jump to actual trampoline */
+               rgctx_null_jumps [njumps ++] = code;
+               arm_cbzx (code, ARMREG_IP1, 0);
+       }
+
+       /* fetch slot */
+       code = mono_arm_emit_ldrx (code, ARMREG_IP1, ARMREG_IP1, sizeof (gpointer) * (index + 1));
+       /* is the slot null? */
+       /* if yes, jump to actual trampoline */
+       rgctx_null_jumps [njumps ++] = code;
+       arm_cbzx (code, ARMREG_IP1, 0);
+       /* otherwise return, result is in IP1 */
+       arm_movx (code, ARMREG_R0, ARMREG_IP1);
+       arm_brx (code, ARMREG_LR);
+
+       g_assert (njumps <= depth + 2);
+       for (i = 0; i < njumps; ++i)
+               mono_arm_patch (rgctx_null_jumps [i], code, MONO_R_ARM64_CBZ);
+
+       g_free (rgctx_null_jumps);
+
+       /* Slowpath */
+
+       /* Call mono_rgctx_lazy_fetch_trampoline (), passing in the slot as argument */
+       /* The vtable/mrgctx is still in R0 */
+       if (aot) {
+               code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, g_strdup_printf ("specific_trampoline_lazy_fetch_%u", slot));
+       } else {
+               tramp = mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), &code_len);
+               code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)tramp);
+       }
+       arm_brx (code, ARMREG_IP0);
+
+       mono_arch_flush_icache (buf, code - buf);
+
+       g_assert (code - buf <= buf_size);
+
+       if (info) {
+               char *name = mono_get_rgctx_fetch_trampoline_name (slot);
+               *info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops);
+               g_free (name);
+       }
+
+       return buf;
+}
+
+gpointer
+mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *code, *buf;
+       int tramp_size;
+       MonoJumpInfo *ji = NULL;
+       GSList *unwind_ops = NULL;
+
+       g_assert (aot);
+
+       tramp_size = 32;
+
+       code = buf = mono_global_codeman_reserve (tramp_size);
+
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, ARMREG_SP, 0);
+
+       // FIXME: Currently, we always go to the slow path.
+       /* Load trampoline addr */
+       arm_ldrx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG, 8);
+       /* The vtable/mrgctx is in R0 */
+       g_assert (MONO_ARCH_VTABLE_REG == ARMREG_R0);
+       arm_brx (code, ARMREG_IP0);
+
+       mono_arch_flush_icache (buf, code - buf);
+
+       g_assert (code - buf <= tramp_size);
+
+       if (info)
+               *info = mono_tramp_info_create ("rgctx_fetch_trampoline_general", buf, code - buf, ji, unwind_ops);
+
+       return buf;
+}
+
+/*
+ * mono_arch_create_sdb_trampoline:
+ *
+ *   Return a trampoline which captures the current context, passes it to
+ * debugger_agent_single_step_from_context ()/debugger_agent_breakpoint_from_context (),
+ * then restores the (potentially changed) context.
+ */
+guint8*
+mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gboolean aot)
+{
+       int tramp_size = 512;
+       int offset, imm, frame_size, ctx_offset;
+       guint64 gregs_regset;
+       guint8 *code, *buf;
+       GSList *unwind_ops = NULL;
+       MonoJumpInfo *ji = NULL;
+
+       code = buf = mono_global_codeman_reserve (tramp_size);
+
+       /* Compute stack frame size and offsets */
+       offset = 0;
+       /* frame block */
+       offset += 2 * 8;
+       /* MonoContext */
+       ctx_offset = offset;
+       offset += sizeof (MonoContext);
+       offset = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
+       frame_size = offset;
+
+       // FIXME: Unwind info
+
+       /* Setup stack frame */
+       imm = frame_size;
+       while (imm > 256) {
+               arm_subx_imm (code, ARMREG_SP, ARMREG_SP, 256);
+               imm -= 256;
+       }
+       arm_subx_imm (code, ARMREG_SP, ARMREG_SP, imm);
+       arm_stpx (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, 0);
+       arm_movspx (code, ARMREG_FP, ARMREG_SP);
+
+       /* Initialize a MonoContext structure on the stack */
+       /* No need to save fregs */
+       gregs_regset = ~((1 << ARMREG_FP) | (1 << ARMREG_SP));
+       code = mono_arm_emit_store_regarray (code, gregs_regset, ARMREG_FP, ctx_offset + G_STRUCT_OFFSET (MonoContext, regs));
+       /* Save caller fp */
+       arm_ldrx (code, ARMREG_IP1, ARMREG_FP, 0);
+       arm_strx (code, ARMREG_IP1, ARMREG_FP, ctx_offset + G_STRUCT_OFFSET (MonoContext, regs) + (ARMREG_FP * 8));
+       /* Save caller sp */
+       arm_movx (code, ARMREG_IP1, ARMREG_FP);
+       imm = frame_size;
+       while (imm > 256) {
+               arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 256);
+               imm -= 256;
+       }
+       arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, imm);
+       arm_strx (code, ARMREG_IP1, ARMREG_FP, ctx_offset + G_STRUCT_OFFSET (MonoContext, regs) + (ARMREG_SP * 8));
+       /* Save caller ip */
+       arm_ldrx (code, ARMREG_IP1, ARMREG_FP, 8);
+       arm_strx (code, ARMREG_IP1, ARMREG_FP, ctx_offset + G_STRUCT_OFFSET (MonoContext, pc));
+
+       /* Call the single step/breakpoint function in sdb */
+       /* Arg1 = ctx */
+       arm_addx_imm (code, ARMREG_R0, ARMREG_FP, ctx_offset);
+       if (aot) {
+               if (single_step)
+                       code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "debugger_agent_single_step_from_context");
+               else
+                       code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "debugger_agent_breakpoint_from_context");
+       } else {
+               gpointer addr = single_step ? debugger_agent_single_step_from_context : debugger_agent_breakpoint_from_context;
+
+               code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)addr);
+       }
+       arm_blrx (code, ARMREG_IP0);
+
+       /* Restore ctx */
+       /* Save fp/pc into the frame block */
+       arm_ldrx (code, ARMREG_IP0, ARMREG_FP, ctx_offset + G_STRUCT_OFFSET (MonoContext, regs) + (ARMREG_FP * 8));
+       arm_strx (code, ARMREG_IP0, ARMREG_FP, 0);
+       arm_ldrx (code, ARMREG_IP0, ARMREG_FP, ctx_offset + G_STRUCT_OFFSET (MonoContext, pc));
+       arm_strx (code, ARMREG_IP0, ARMREG_FP, 8);
+       gregs_regset = ~((1 << ARMREG_FP) | (1 << ARMREG_SP));
+       code = mono_arm_emit_load_regarray (code, gregs_regset, ARMREG_FP, ctx_offset + G_STRUCT_OFFSET (MonoContext, regs));
+
+       code = mono_arm_emit_destroy_frame (code, frame_size, ((1 << ARMREG_IP0) | (1 << ARMREG_IP1)));
+
+       arm_retx (code, ARMREG_LR);
+
+       mono_arch_flush_icache (code, code - buf);
+       g_assert (code - buf <= tramp_size);
+
+       const char *tramp_name = single_step ? "sdb_single_step_trampoline" : "sdb_breakpoint_trampoline";
+       *info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
+
+       return buf;
+}
+
+#else /* DISABLE_JIT */
+
+guchar*
+mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericContext *mrgctx, gpointer addr)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_arch_get_nullified_class_init_trampoline (MonoTrampInfo **info)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+guint8*
+mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+#endif /* !DISABLE_JIT */
index eb61dc05cd4771475e8771c1572ac1ff4218fc22..408997daace8d426c6ba6ffaf4a81c9b8eea032c 100644 (file)
@@ -13,7 +13,7 @@
 /*              Dietmar Maurer (dietmar@ximian.com)                */
 /*                                                                 */
 /* Copyright   - 2001 Ximian, Inc.                                 */
-/*                                                                 */
+/* Licensed under the MIT license. See LICENSE file in the project root for full license information.*/
 /*------------------------------------------------------------------*/
 
 /*------------------------------------------------------------------*/
diff --git a/mono/mini/tramp-x86-gsharedvt.c b/mono/mini/tramp-x86-gsharedvt.c
new file mode 100644 (file)
index 0000000..757325c
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * tramp-x86-gsharedvt.c: gsharedvt support code for x86
+ *
+ * Authors:
+ *   Zoltan Varga <vargaz@gmail.com>
+ *
+ * Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include "mini.h"
+#include <mono/metadata/abi-details.h>
+
+#ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
+
+gpointer
+mono_x86_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg)
+{
+       int i;
+       int *map = info->map;
+
+       /* Set vtype ret arg */
+       if (info->vret_arg_slot != -1) {
+               callee [info->vret_arg_slot] = &callee [info->vret_slot];
+       }
+       /* Copy data from the caller argument area to the callee */
+       for (i = 0; i < info->map_count; ++i) {
+               int src = map [i * 2];
+               int dst = map [i * 2 + 1];
+
+               switch ((src >> 16) & 0x3) {
+               case 0:
+                       callee [dst] = caller [src];
+                       break;
+               case 1: {
+                       int j, nslots;
+                       gpointer *arg;
+
+                       /* gsharedvt->normal */
+                       nslots = src >> 18;
+                       arg = (gpointer*)caller [src & 0xffff];
+                       for (j = 0; j < nslots; ++j)
+                               callee [dst + j] = arg [j];
+                       break;
+               }
+               case 2:
+                       /* gsharedvt arg, have to take its address */
+                       callee [dst] = caller + (src & 0xffff);
+                       break;
+#if 0
+               int dst = map [i * 2 + 1];
+               if (dst >= 0xffff) {
+                       /* gsharedvt arg, have to take its address */
+                       callee [dst - 0xffff] = caller + map [i * 2];
+               } else {
+                       callee [dst] = caller [map [i * 2]];
+               }
+#endif
+               }
+       }
+
+       if (info->vcall_offset != -1) {
+               MonoObject *this_obj = caller [0];
+
+               if (G_UNLIKELY (!this_obj))
+                       return NULL;
+               if (info->vcall_offset == MONO_GSHAREDVT_DEL_INVOKE_VT_OFFSET)
+                       /* delegate invoke */
+                       return ((MonoDelegate*)this_obj)->invoke_impl;
+               else
+                       return *(gpointer*)((char*)this_obj->vtable + info->vcall_offset);
+       } else if (info->calli) {
+               /* The address to call is passed in the mrgctx reg */
+               return mrgctx_reg;
+       } else {
+               return info->addr;
+       }
+
+}
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *code, *buf;
+       int buf_len, cfa_offset;
+       GSList *unwind_ops = NULL;
+       MonoJumpInfo *ji = NULL;
+       guint8 *br_out, *br [16];
+       int info_offset, mrgctx_offset;
+
+       buf_len = 320;
+       buf = code = mono_global_codeman_reserve (buf_len);
+
+       /*
+        * This trampoline is responsible for marshalling calls between normal code and gsharedvt code. The
+        * caller is a normal or gshared method which uses the signature of the inflated method to make the call, while
+        * the callee is a gsharedvt method which has a signature which uses valuetypes in place of type parameters, i.e.
+        * caller:
+        * foo<bool> (bool b)
+        * callee:
+        * T=<type used to represent vtype type arguments, currently TypedByRef>
+        * foo<T> (T b)
+        * The trampoline is responsible for marshalling the arguments and marshalling the result back. To simplify
+        * things, we create our own stack frame, and do most of the work in a C function, which receives a
+        * GSharedVtCallInfo structure as an argument. The structure should contain information to execute the C function to
+        * be as fast as possible. The argument is received in EAX from a gsharedvt trampoline. So the real
+        * call sequence looks like this:
+        * caller -> gsharedvt trampoline -> gsharevt in trampoline -> start_gsharedvt_call
+        * FIXME: Optimize this.
+        */
+
+       cfa_offset = sizeof (gpointer);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, X86_ESP, cfa_offset);
+       mono_add_unwind_op_offset (unwind_ops, code, buf, X86_NREG, -cfa_offset);
+       x86_push_reg (code, X86_EBP);
+       cfa_offset += sizeof (gpointer);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
+       mono_add_unwind_op_offset (unwind_ops, code, buf, X86_EBP, - cfa_offset);
+       x86_mov_reg_reg (code, X86_EBP, X86_ESP, sizeof (gpointer));
+       mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, X86_EBP);
+       /* Alloc stack frame/align stack */
+       x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8);
+       info_offset = -4;
+       mrgctx_offset = - 8;
+       /* The info struct is put into EAX by the gsharedvt trampoline */
+       /* Save info struct addr */
+       x86_mov_membase_reg (code, X86_EBP, info_offset, X86_EAX, 4);
+       /* Save rgctx */
+       x86_mov_membase_reg (code, X86_EBP, mrgctx_offset, MONO_ARCH_RGCTX_REG, 4);
+
+       /* Allocate stack area used to pass arguments to the method */
+       x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, stack_usage), sizeof (gpointer));
+       x86_alu_reg_reg (code, X86_SUB, X86_ESP, X86_EAX);
+
+#if 0
+       /* Stack alignment check */
+       x86_mov_reg_reg (code, X86_ECX, X86_ESP, 4);
+       x86_alu_reg_imm (code, X86_AND, X86_ECX, MONO_ARCH_FRAME_ALIGNMENT - 1);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, 0);
+       x86_branch_disp (code, X86_CC_EQ, 3, FALSE);
+       x86_breakpoint (code);
+#endif
+
+       /* ecx = caller argument area */
+       x86_mov_reg_reg (code, X86_ECX, X86_EBP, 4);
+       x86_alu_reg_imm (code, X86_ADD, X86_ECX, 8);
+       /* eax = callee argument area */
+       x86_mov_reg_reg (code, X86_EAX, X86_ESP, 4);
+
+       /* Call start_gsharedvt_call */
+       /* Arg 4 */
+       x86_push_membase (code, X86_EBP, mrgctx_offset);
+       /* Arg3 */
+       x86_push_reg (code, X86_EAX);
+       /* Arg2 */
+       x86_push_reg (code, X86_ECX);
+       /* Arg1 */
+       x86_push_membase (code, X86_EBP, info_offset);
+       if (aot) {
+               code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_x86_start_gsharedvt_call");
+               x86_call_reg (code, X86_EAX);
+       } else {
+               x86_call_code (code, mono_x86_start_gsharedvt_call);
+       }
+       x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4 * 4);
+       /* The address to call is in eax */
+       /* The stack is now setup for the real call */
+       /* Load info struct */
+       x86_mov_reg_membase (code, X86_ECX, X86_EBP, info_offset, 4);
+       /* Load rgctx */
+       x86_mov_reg_membase (code, MONO_ARCH_RGCTX_REG, X86_EBP, mrgctx_offset, sizeof (gpointer));
+       /* Make the call */
+       x86_call_reg (code, X86_EAX);
+       /* The return value is either in registers, or stored to an area beginning at sp [info->vret_slot] */
+       /* EAX/EDX might contain the return value, only ECX is free */
+       /* Load info struct */
+       x86_mov_reg_membase (code, X86_ECX, X86_EBP, info_offset, 4);
+
+       /* Branch to the in/out handling code */
+       x86_alu_membase_imm (code, X86_CMP, X86_ECX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, gsharedvt_in), 1);  
+       br_out = code;
+       x86_branch32 (code, X86_CC_NE, 0, TRUE);
+
+       /*
+        * IN CASE
+        */
+
+       /* Load ret marshal type */
+       x86_mov_reg_membase (code, X86_ECX, X86_ECX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, ret_marshal), 4);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_NONE);
+       br [0] = code;
+       x86_branch8 (code, X86_CC_NE, 0, TRUE);
+
+       /* Normal return, no marshalling required */
+       x86_leave (code);
+       x86_ret (code);
+
+       /* Return value marshalling */
+       x86_patch (br [0], code);
+       /* Load info struct */
+       x86_mov_reg_membase (code, X86_EAX, X86_EBP, info_offset, 4);
+       /* Load 'vret_slot' */
+       x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_slot), 4);
+       /* Compute ret area address */
+       x86_shift_reg_imm (code, X86_SHL, X86_EAX, 2);
+       x86_alu_reg_reg (code, X86_ADD, X86_EAX, X86_ESP);
+       /* The callee does a ret $4, so sp is off by 4 */
+       x86_alu_reg_imm (code, X86_SUB, X86_EAX, sizeof (gpointer));
+
+       /* Branch to specific marshalling code */
+       // FIXME: Move the I4 case to the top */
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_DOUBLE_FPSTACK);
+       br [1] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_FLOAT_FPSTACK);
+       br [2] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_STACK_POP);
+       br [3] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_I1);
+       br [4] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_U1);
+       br [5] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_I2);
+       br [6] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_U2);
+       br [7] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       /* IREGS case */
+       /* Load both eax and edx for simplicity */
+       x86_mov_reg_membase (code, X86_EDX, X86_EAX, sizeof (gpointer), sizeof (gpointer));
+       x86_mov_reg_membase (code, X86_EAX, X86_EAX, 0, sizeof (gpointer));
+       x86_leave (code);
+       x86_ret (code);
+       /* DOUBLE_FPSTACK case */
+       x86_patch (br [1], code);
+       x86_fld_membase (code, X86_EAX, 0, TRUE);
+       x86_jump8 (code, 0);
+       x86_leave (code);
+       x86_ret (code);
+       /* FLOAT_FPSTACK case */
+       x86_patch (br [2], code);
+       x86_fld_membase (code, X86_EAX, 0, FALSE);
+       x86_leave (code);
+       x86_ret (code);
+       /* STACK_POP case */
+       x86_patch (br [3], code);
+       x86_leave (code);
+       x86_ret_imm (code, 4);
+       /* I1 case */
+       x86_patch (br [4], code);
+       x86_widen_membase (code, X86_EAX, X86_EAX, 0, TRUE, FALSE);
+       x86_leave (code);
+       x86_ret (code);
+       /* U1 case */
+       x86_patch (br [5], code);
+       x86_widen_membase (code, X86_EAX, X86_EAX, 0, FALSE, FALSE);
+       x86_leave (code);
+       x86_ret (code);
+       /* I2 case */
+       x86_patch (br [6], code);
+       x86_widen_membase (code, X86_EAX, X86_EAX, 0, TRUE, TRUE);
+       x86_leave (code);
+       x86_ret (code);
+       /* U2 case */
+       x86_patch (br [7], code);
+       x86_widen_membase (code, X86_EAX, X86_EAX, 0, FALSE, TRUE);
+       x86_leave (code);
+       x86_ret (code);
+
+       /*
+        * OUT CASE
+        */
+
+       x86_patch (br_out, code);
+       /* Load ret marshal type into ECX */
+       x86_mov_reg_membase (code, X86_ECX, X86_ECX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, ret_marshal), 4);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_NONE);
+       br [0] = code;
+       x86_branch8 (code, X86_CC_NE, 0, TRUE);
+
+       /* Normal return, no marshalling required */
+       x86_leave (code);
+       x86_ret (code);
+
+       /* Return value marshalling */
+       x86_patch (br [0], code);
+
+       /* EAX might contain the return value */
+       // FIXME: Use moves
+       x86_push_reg (code, X86_EAX);
+
+       /* Load info struct */
+       x86_mov_reg_membase (code, X86_EAX, X86_EBP, info_offset, 4);
+       /* Load 'vret_arg_slot' */
+       x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_arg_slot), 4);
+       /* Compute ret area address in the caller frame in EAX */
+       x86_shift_reg_imm (code, X86_SHL, X86_EAX, 2);
+       x86_alu_reg_reg (code, X86_ADD, X86_EAX, X86_EBP);
+       x86_alu_reg_imm (code, X86_ADD, X86_EAX, 8);
+       x86_mov_reg_membase (code, X86_EAX, X86_EAX, 0, sizeof (gpointer));
+
+       /* Branch to specific marshalling code */
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_DOUBLE_FPSTACK);
+       br [1] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_FLOAT_FPSTACK);
+       br [2] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_STACK_POP);
+       br [3] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       x86_alu_reg_imm (code, X86_CMP, X86_ECX, GSHAREDVT_RET_IREGS);
+       br [4] = code;
+       x86_branch8 (code, X86_CC_E, 0, TRUE);
+       /* IREG case */
+       x86_mov_reg_reg (code, X86_ECX, X86_EAX, sizeof (gpointer));
+       x86_pop_reg (code, X86_EAX);
+       x86_mov_membase_reg (code, X86_ECX, 0, X86_EAX, sizeof (gpointer));
+       x86_leave (code);
+       x86_ret_imm (code, 4);
+       /* IREGS case */
+       x86_patch (br [4], code);
+       x86_mov_reg_reg (code, X86_ECX, X86_EAX, sizeof (gpointer));
+       x86_pop_reg (code, X86_EAX);
+       x86_mov_membase_reg (code, X86_ECX, sizeof (gpointer), X86_EDX, sizeof (gpointer));
+       x86_mov_membase_reg (code, X86_ECX, 0, X86_EAX, sizeof (gpointer));
+       x86_leave (code);
+       x86_ret_imm (code, 4);
+       /* DOUBLE_FPSTACK case */
+       x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
+       x86_patch (br [1], code);
+       x86_fst_membase (code, X86_EAX, 0, TRUE, TRUE);
+       x86_jump8 (code, 0);
+       x86_leave (code);
+       x86_ret_imm (code, 4);
+       /* FLOAT_FPSTACK case */
+       x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
+       x86_patch (br [2], code);
+       x86_fst_membase (code, X86_EAX, 0, FALSE, TRUE);
+       x86_leave (code);
+       x86_ret_imm (code, 4);
+       /* STACK_POP case */
+       x86_patch (br [3], code);
+       x86_leave (code);
+       x86_ret_imm (code, 4);
+
+       g_assert ((code - buf) < buf_len);
+
+       if (info)
+               *info = mono_tramp_info_create ("gsharedvt_trampoline", buf, code - buf, ji, unwind_ops);
+
+       mono_arch_flush_icache (buf, code - buf);
+       return buf;
+}
+
+#else
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       *info = NULL;
+       return NULL;
+}
+
+#endif /* MONO_ARCH_GSHAREDVT_SUPPORTED */
index e416527c2b3ceb59d8979a129a84384581520cfe..dd560843018d8a2a3a59b8917eb25aada8874680 100644 (file)
@@ -878,17 +878,3 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo
        return buf;
 }
 
-#if defined(ENABLE_GSHAREDVT)
-
-#include "../../../mono-extensions/mono/mini/tramp-x86-gsharedvt.c"
-
-#else
-
-gpointer
-mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
-{
-       *info = NULL;
-       return NULL;
-}
-
-#endif /* !MONOTOUCH */
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 e57211635ee700b0ea1bea48015d8709333b89fd..d88694d198ebb4fcb7fec4e2a0705c2fe63f3395 100644 (file)
@@ -6,6 +6,7 @@
  *   Alex Rønne Petersen (alexrp@xamarin.com)
  *
  * Copyright 2010 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /*
index 79d80717aaabb9fed6e46a05a8403e7a5f2cd43e..4cf48bbd1b2491a54e3155c2c793b1934d5bb441 100644 (file)
@@ -9,6 +9,7 @@
  * The AOT compiler can load these files during compilation.
  * Currently, only the order in which methods were compiled is saved, 
  * allowing more efficient function ordering in the AOT files.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 7030a4b3e5fa4149528fda724c8c49e8fd51a321..445e1bf1f893cab64898eed096e0c072ea009b1e 100644 (file)
@@ -8,6 +8,7 @@
  *
  * Note: this profiler is completely unsafe wrt handling managed objects,
  * don't use and don't copy code from here.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "config.h"
 
index 99d6ad4bbe537f8b80eb66f2af5909b8005299c7..c32f40c62d32009737404f7732419fbdd4447a19 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright 2010 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 9266dee403c1d5f91a6182e89ae820fb85c70c25..753024dcf72963e30c7ebef03da79e54b7cdc7e0 100644 (file)
@@ -12,6 +12,7 @@
  *   Paolo Molaro (lupus@ximian.com)
  *
  * Copyright 2010 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "utils.h"
 #include <stdlib.h>
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 \
index a609c69d86fdb5e8185662c48775eea22ce5bb87..9fe2f3ceeb4a62b9fc16be861e6d28179fcaac1c 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_METADATA_GCINTERNALAGNOSTIC_H__
index 9d3f45195e115047b8e3c303c5d0ec1d21fbce6b..2bc3214f143745d39b577525eea5a6bbc257bd66 100644 (file)
  * Copyright 2011 Xamarin, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /*
index 5e349f8416ee22539b4e1eee99f7e4599765cbd8..b4c058f13a4e61dc048136b4bc5bf5d3b1dfaf9c 100644 (file)
@@ -5,18 +5,7 @@
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_SGENARCHDEP_H__
 #define __MONO_SGENARCHDEP_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..05dfe7d90743b041f12bcf26d587213920fe46c0 100644 (file)
@@ -9,18 +9,7 @@
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -342,6 +331,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 +438,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 +489,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..059fb77fa64925d61f73ff1311c1f7b979b7343e 100644 (file)
@@ -2,24 +2,7 @@
  * Copyright 2001-2003 Ximian, Inc
  * Copyright 2003-2010 Novell, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_SGEN_CARD_TABLE_INLINES_H__
 #define __MONO_SGEN_CARD_TABLE_INLINES_H__
@@ -31,7 +14,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 +23,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..4cf9f003d5584bb55b5c7ab30f9170661647c3f7 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2014 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/sgen/sgen-pointer-queue.h"
@@ -105,7 +94,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 11a8998478e765e8083e337c57a9f48c6fb7a9ee..429dcb26af30a8b2370225bf988dc247aa7db7b5 100644 (file)
@@ -6,18 +6,7 @@
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_SGENCONF_H__
 #define __MONO_SGENCONF_H__
index 2b7bc60670a3751b20566b5c35f100d1b0d8ecf8..016fc462e0e762772ccbb9f6701eaf4c583937af 100644 (file)
@@ -5,18 +5,7 @@
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 extern guint64 stat_copy_object_called_nursery;
index 27e8cb0addf54d760ef99b1b351bd011eab5eb73..28e77a77e87d53c9a3145a586f0545f3b049c639 100644 (file)
  * Copyright 2011 Xamarin, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 1d5b36637eede053a25c3593da22d285e8a0c866..852a4a63329d2fdd134ebfb7c5e762fdd901c000 100644 (file)
@@ -6,18 +6,7 @@
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "config.h"
 #ifdef HAVE_SGEN_GC
index c61fa5f74d6bda3391e959ce4b0b580a15d0cdf2..2b1f9e4da49c2bf558145f09e1757c354f4b1d06 100644 (file)
@@ -7,18 +7,7 @@
  *
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_SGEN_DESCRIPTOR_H__
 #define __MONO_SGEN_DESCRIPTOR_H__
index 5130b1c6b3894de6727e094a73032dd045a6f42c..dd7cca93dbecc2634a3c6dce3ece2278a5d040ca 100644 (file)
  * Copyright 2011 Xamarin, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 89af85f4387d92646edc38554aa138dd0b9dbdec..57e6f6931fc85ae980bee580694ee17c045b6d6f 100644 (file)
  * Copyright 2011 Xamarin, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  *
  * Important: allocation provides always zeroed memory, having to do
  * a memset after allocation is deadly for performance.
@@ -245,6 +234,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;
@@ -341,7 +332,6 @@ nursery_canaries_enabled (void)
  * ######################################################################
  */
 MonoCoopMutex gc_mutex;
-gboolean sgen_try_free_some_memory;
 
 #define SCAN_START_SIZE        SGEN_SCAN_START_SIZE
 
@@ -1167,7 +1157,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 +1382,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 +1393,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 +1549,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 +1559,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 +1600,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 ();
@@ -1698,7 +1701,7 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, CopyOrMarkFromRootsMod
 
        sgen_client_pre_collection_checks ();
 
-       if (!concurrent) {
+       if (mode != COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
                /* Remsets are not useful for a major collection */
                remset.clear_cards ();
        }
@@ -1709,8 +1712,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 +1777,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 +1805,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 +1851,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 +2950,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;
 
@@ -3147,11 +3175,7 @@ sgen_gc_lock (void)
 void
 sgen_gc_unlock (void)
 {
-       gboolean try_free = sgen_try_free_some_memory;
-       sgen_try_free_some_memory = FALSE;
        mono_coop_mutex_unlock (&gc_mutex);
-       if (try_free)
-               mono_thread_hazardous_try_free_some ();
 }
 
 void
@@ -3218,8 +3242,6 @@ sgen_restart_world (int generation, GGTimingInfo *timing)
 
        binary_protocol_world_restarted (generation, sgen_timestamp ());
 
-       sgen_try_free_some_memory = TRUE;
-
        if (sgen_client_bridge_need_processing ())
                sgen_client_bridge_processing_finish (generation);
 
index 4b2f895d890badc5f42157ebe4009f57211ad1b4..f3d868a541648015aba3ef73d8a88f8345a30390 100644 (file)
@@ -6,18 +6,7 @@
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_SGENGC_H__
 #define __MONO_SGENGC_H__
@@ -407,12 +396,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 +586,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 +621,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 +847,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..223116861a66974e1139928cbb335f127254da88 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -22,6 +11,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 +19,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 +29,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 +71,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 +116,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 +144,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 +177,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 +312,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 +353,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 +368,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 +394,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 cb6694342fe484cc50bfdff9b940ca12ad0d6e92..809215136f9799d817b0b157d6c1ac972f085f93 100644 (file)
@@ -5,18 +5,7 @@
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "config.h"
 #ifdef HAVE_SGEN_GC
index 79d2c701a0e4938ecd873144e72132546cbcae83..019f44c927c8e5fbee00e0d291c0234cb54b73cb 100644 (file)
@@ -4,18 +4,7 @@
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_SGEN_GRAY_H__
 #define __MONO_SGEN_GRAY_H__
index e5327399c584f0a83868b64313fb7679b7e2a26b..256e32b20a1b0108ae4c69d4328e7fe7fc0759ed 100644 (file)
@@ -3,18 +3,7 @@
  *
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 2f9ca117783ea2921c5379cd5dfeb202c6a3ea62..74c5c02a0278355074ab21273d63831791da11af 100644 (file)
@@ -1,24 +1,7 @@
 /*
  * Copyright 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 3853d3463480df2dd6497196c474f2b372e517b7..024e0192442b01e66e451189399ddf06bd99a18a 100644 (file)
@@ -1,24 +1,7 @@
 /*
  * Copyright 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_SGEN_LAYOUT_STATS_H__
 #define __MONO_SGEN_LAYOUT_STATS_H__
index a89ec99fe353517580f0695f6d45e68859a18101..5cb3c71253d1bb6ce1cced697b7affe438d61067 100644 (file)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -73,6 +62,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 +400,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 +612,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 a4b10ff85df2967fd4a4ba18740a88d838c6cd9b..826aca9dfd1fa7b5fb32ebe9d8f9f0a6175a036a 100644 (file)
@@ -5,18 +5,7 @@
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #define collector_pin_object(obj, queue) do { \
index 677435a0a09cba9abd3d598b18ab7b20350451b1..ad2bb6fe272a44cbf08ce80ac65da5dbd177a0c7 100644 (file)
@@ -4,18 +4,7 @@
  *
  * Copyright (C) 2014 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /*
@@ -234,7 +223,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 +235,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 +257,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 +313,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..9f4cbfc129dbb205f60d61eda9fb83d6bbec9f0b 100644 (file)
@@ -7,18 +7,7 @@
  * Copyright 2009-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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
 #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 +187,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 +424,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 +555,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 +803,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 +1064,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 +1172,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 +1222,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 +1436,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 +1446,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 +1454,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 +1466,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 +1560,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 +1571,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 +1589,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 +1609,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 +2037,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 +2171,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 +2186,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 +2202,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 +2210,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 +2273,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 +2288,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 +2306,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 +2493,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 611ae5c118f4d66b7e1eb982fd4d32048e78a20b..398c36e2ab24f9588638699b7c33bd548854b1f7 100644 (file)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 669b59734e99200ffadae2dc540a7b8137f6349c..4ce17f5993b05a3dabffb71822d5a5042661ca16 100644 (file)
@@ -2,24 +2,7 @@
  * Copyright 2001-2003 Ximian, Inc
  * Copyright 2003-2010 Novell, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_SGEN_MEMORY_GOVERNOR_H__
 #define __MONO_SGEN_MEMORY_GOVERNOR_H__
index 49b42265c7a7d4076c214b5c80f55a8634e248af..a77d53b4744bed22af7beefdba02232bbb373c22 100644 (file)
@@ -5,18 +5,7 @@
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #define collector_pin_object(obj, queue) sgen_pin_object (obj, queue);
index b1895985dc34e340f32093abfb423f967711f44a..4b62a739f27183622a0dbc4441e1ea2b17536b9c 100644 (file)
@@ -5,18 +5,7 @@
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 extern guint64 stat_scan_object_called_nursery;
@@ -80,7 +69,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 e42e3bf64aa75efc7001025dbb4a124c254d0576..785f46d5645c183043c8f09d047f4f2f3e7efeca 100644 (file)
@@ -7,18 +7,7 @@
  * Copyright 2011 Xamarin Inc  (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /*
index 5edccfaabec10720fcb6658f1eb8e7d54b8ccc24..26fcfd116af32464cb5d01bcb1a6573144c5082e 100644 (file)
@@ -3,24 +3,7 @@
  * Copyright 2003-2010 Novell, Inc.
  * Copyright 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index a94af9ddf4494db961697faac801a9273bece46b..eedd1f0343a93e720cac0838ec29ff70e8bd773e 100644 (file)
@@ -5,18 +5,7 @@
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -182,6 +171,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 +187,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..00eb20dd819830f40a45a620981e812426673df2 100644 (file)
@@ -4,18 +4,7 @@
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_SGEN_PINNING_H__
 #define __MONO_SGEN_PINNING_H__
@@ -56,6 +45,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 196bc3010716ef21708b019d4bddafb2656b4618..5fb25b0bdc53ce85ac6244422f841c6ff645e813 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2014 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifdef HAVE_SGEN_GC
index 3352dab3c58f0e308ae9b1b4d3b44526f474b9c4..5127b5bdc1db15038b16213469545ee12d17c76a 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2014 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_SGEN_POINTER_QUEUE_H__
index 963035950b32ecdad234e250174df43819e5f02c..ffc47f248de05a2c17a3f93648118bed4e2079ea 100644 (file)
@@ -6,18 +6,7 @@
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifdef HAVE_SGEN_GC
index 220418e8167deea8101378669fffc325ee38be66..5ec3680fc5a58018a358eaa583afdf9613753ddf 100644 (file)
@@ -6,18 +6,7 @@
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_SGENPROTOCOL_H__
index 7566bddbc1d6370ea7c6715c4446b0b1c7fc35be..802dd561e9ed260df85cfd512b843034f9d4fcf1 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2013 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 75577e57122c354f36d195e5ba23e5da3bbfc876..b9d0f648138e4c694eac038b0d3b295001df4270 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2014 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_SGENQSORT_H__
 #define __MONO_SGENQSORT_H__
index b7f973646315254877cee62e526435d6f8dcba7b..b5cbedaa92ec50bb9d0b1237e353a244ad4a6303 100644 (file)
@@ -5,18 +5,7 @@
  * Copyright 2003-2010 Novell, Inc.
  * Copyright (C) 2013 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  *
  *
  * Scans one object, using the OBJ_XXX macros.  The start of the
index 40639d7050b1db8d2793aa66cf7156285fe0bb9a..56a235aa30f42473511957269500bc45a86870c1 100644 (file)
@@ -6,18 +6,7 @@
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 588651fbc0b67965c946fadc800602c16ca05b0d..3606607809e954c2888f1dceae8b70d0ea4cb135 100644 (file)
@@ -9,18 +9,7 @@
  * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 2d55abbbcc19839bf2e6348f6a683ffd6c5c123a..8b28fde01707b1b46fa2d5f292400cefca3154fc 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2014 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_SGEN_TAGGED_POINTER_H__
index e9706943f847803dc38b88b633b6464aefe85c75..f1664f6a23fcb7fd727fe533a45cea606d00134b 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -41,6 +30,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 +101,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 +126,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 +137,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 +166,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..339526ca59876dac1ca4422a818e67421d68ee47 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_SGEN_THREAD_POOL_H__
@@ -37,6 +26,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..adc600a090f3dc801f8d1b16b4796acb28a69988 100644 (file)
@@ -5,18 +5,7 @@
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -64,6 +53,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 +220,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 +283,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 +293,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..780d2eb6df921ed6a096879c4876eef75f8adbaf 100644 (file)
@@ -4,18 +4,7 @@
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_SGEN_WORKER_H__
@@ -30,7 +19,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 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 cf87dbd103ebb573474156857868bb06f1522177..5e0f474ec40ac451ce6034bf5af400896980c0ca 100644 (file)
@@ -1,5 +1,6 @@
 //
 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 //
 
 using System;
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 9690179180636dd693a25f4074ec459840ddb700..da90ba1c35f5cc620149a389272f22af4539ba22 100644 (file)
@@ -10,7 +10,7 @@
 //
 // Bill Seurer (seurer@linux.vnet.ibm.com)
 //
-// (C) {Copyright holder}
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 //
 
 using System;
index c4bafea09894ac1d0307a71e98fbea37d50950d9..602706345e91e17d3e953e19f9ca8a3fa1ff84da 100644 (file)
@@ -10,7 +10,7 @@
 //
 // Bill Seurer (seurer@linux.vnet.ibm.com)
 //
-// (C) {Copyright holder}
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 //
 
 using System;
index a529a5331fecfb0ab0f98ad8ecfe4cfcd4ed341e..a7f519e557cef0ab9011a5487120becb5a64aba2 100644 (file)
@@ -10,7 +10,7 @@
 //
 // Bill Seurer (seurer@linux.vnet.ibm.com)
 //
-// (C) {Copyright holder}
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 //
 
 using System;
index e7c1d395c79faf5ee446565b20609261e8b41ea6..34021e0b053a6c99d9728913c67563c442ba996c 100644 (file)
@@ -10,7 +10,7 @@
 //
 // Bill Seurer (seurer@linux.vnet.ibm.com)
 //
-// (C) {Copyright holder}
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 //
 
 using System;
index a57a909850083ded55c984f0db75b7650915a952..08ad1d6eccd40994ab972de400b48d6f8d0b5d10 100644 (file)
@@ -10,7 +10,7 @@
 //
 // Bill Seurer (seurer@linux.vnet.ibm.com)
 //
-// (C) {Copyright holder}
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 //
 
 using System;
index e58e009a269117778ad7472a5b7f780a33221539..ae52220e335db404bdfe5ff59d2c6d0aa701d702 100644 (file)
@@ -6,24 +6,7 @@
 //
 // Copyright (C) 2008 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.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 //
 using System;
 using System.IO;
@@ -33,6 +16,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 +252,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 e66f751d24e4033bc08aaa520ee31862174679ca..b4627e0d048c8d3dc1499e8365b2effd501db705 100644 (file)
@@ -6,24 +6,7 @@
 //
 // Copyright (C) 2007 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.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.//
 //
 using System;
 using System.IO;
index 2233f10ce72855e2414605204bad7efe64d9949e..cb18ef67a89ea12c3a8b952ad65598455a8ee7d9 100644 (file)
@@ -6,25 +6,7 @@
 //
 // Copyright (C) 2008 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.
-//
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 using System;
 using System.IO;
 using System.Reflection;
diff --git a/mono/tests/verifier/COPYING.LIB b/mono/tests/verifier/COPYING.LIB
deleted file mode 100755 (executable)
index a14a130..0000000
+++ /dev/null
@@ -1,484 +0,0 @@
-These CLI bytecode verifier tests are licensed under the 
-terms of the GNU Library General Public License, version 2.
-                 
-               GNU LIBRARY GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
-                    675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-\f
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-\f
-                 GNU LIBRARY GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-\f
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-\f
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-\f
-  6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    c) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    d) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-\f
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-\f
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-\f
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-                           NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-\f
-     Appendix: How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    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 along with this library; if not, write to the Free
-    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
index c5303a1a6cd7b3060fae2b5be3aeeaa1815d952b..32d859c50d56cee18c92a9518db37a9c762a0597 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2014 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 2fb1498f60995e14dde7add344b9f5722e030ec2..07c33a90eff324a61714991810a62093243072a1 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2013 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index fd916a659061434fe2f093a56469eeb23170509a..3438039a4b0cb91900fa6e057be353b38b47e04b 100644 (file)
@@ -5,6 +5,7 @@
  *   Aleksey Kliger <aleksey@xamarin.com>
  *
  * Copyright 2015 Xamarin, Inc. (www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 951b1b7321bb04a0f35ef4d9408308265748ac41..7cc6b627445a683c4af6a12971246b36ab28864a 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2013 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 447af4e8995727ef2a353acbeb766b5110127109..b6d1e5f20554000d4b037008ee01dce5e1d5eeba 100644 (file)
@@ -505,8 +505,54 @@ InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
 
 #elif defined (HAVE_64BIT_CMPXCHG_FALLBACK)
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/utils/atomic.c"
+#if defined (TARGET_IOS) || defined (TARGET_WATCHOS)
+
+#ifndef __clang__
+#error "Not supported."
+#endif
+
+gint64
+InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
+{
+       return  __sync_val_compare_and_swap (dest, comp, exch);
+}
+
+#elif defined (TARGET_ANDROID)
+
+/* Some Android systems can't find the 64-bit CAS intrinsic at runtime,
+ * so we have to roll our own...
+ */
+
+gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp) __attribute__ ((naked));
+
+gint64
+InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
+{
+       __asm__ (
+               "push           {r4, r5, r6, r7}\n"
+               "ldrd           r4, [sp, #16]\n"
+               "dmb            sy\n"
+       "1:\n"
+               "ldrexd         r6, [r0]\n"
+               "cmp            r7, r5\n"
+               "cmpeq          r6, r4\n"
+               "bne            2f\n"
+               "strexd         r1, r2, [r0]\n"
+               "cmp            r1, #0\n"
+               "bne            1b\n"
+       "2:\n"
+               "dmb            sy\n"
+               "mov            r0, r6\n"
+               "mov            r1, r7\n"
+               "pop            {r4, r5, r6, r7}\n"
+               "bx                     lr\n"
+       );
+}
+
+#else
+
+#error "Need a 64-bit CAS fallback!"
+
 #endif
 
 #else
index 306800cfe1d0cd508a56aafb341a815de949233c..78ab036a22b9f2b013fb61bb946113306110f29a 100755 (executable)
@@ -6,6 +6,7 @@
  *
  * (C) 2002 Ximian, Inc.
  * Copyright 2012 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef _WAPI_ATOMIC_H_
 #include "config.h"
 #include <glib.h>
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/utils/atomic.h"
+/*
+The current Nexus 7 arm-v7a fails with:
+F/MonoDroid( 1568): shared runtime initialization error: Cannot load library: reloc_library[1285]:    37 cannot locate '__sync_val_compare_and_swap_8'
+
+Apple targets have historically being problematic, xcode 4.6 would miscompile the intrinsic.
+*/
+
+#if defined (__arm__) && defined (HAVE_ARMV7)
+#define HAVE_64BIT_CMPXCHG_FALLBACK /* See atomic.c in this directory. */
 #endif
 
 /* On Windows, we always use the functions provided by the Windows API. */
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 074f947f291ff5be3bec063f56a14989be79c66a..44a8f6b7c7b55abd903984267e19b17bb59bb571 100644 (file)
@@ -52,9 +52,21 @@ extern "C" {
 #define dlindependent_comalloc independent_comalloc
 #endif /* USE_DL_PREFIX */
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/utils/dlmalloc.h"
-#endif
+#define dlcalloc               mono_dlcalloc
+#define dlfree                 mono_dlfree
+#define dlmalloc               mono_dlmalloc
+#define dlmemalign             mono_dlmemalign
+#define dlrealloc              mono_dlrealloc
+#define dlvalloc               mono_dlvalloc
+#define dlpvalloc              mono_dlpvalloc
+#define dlmallinfo             mono_dlmallinfo
+#define dlmallopt              mono_dlmallopt
+#define dlmalloc_trim          mono_dlmalloc_trim
+#define dlmalloc_stats         mono_dlmalloc_stats
+#define dlmalloc_usable_size   mono_dlmalloc_usable_size
+#define dlmalloc_footprint     mono_dlmalloc_footprint
+#define dlindependent_calloc   mono_dlindependent_calloc
+#define dlindependent_comalloc mono_dlindependent_comalloc
 
 /*
   malloc(size_t n)
index a90d27c064f4d60458a09512fc5cdf32ef8a9b82..908bcabc5125d0e594237ac67286015302cd8ff9 100644 (file)
@@ -1,6 +1,7 @@
 /* 
  * Copyright 2004-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_OS_GC_WRAPPER_H__
 #define __MONO_OS_GC_WRAPPER_H__
index df1e4cdc8e96744b8aed11c16686b66af0064fdd..efe6b649b3039450cbdc176f0373cd55754a69be 100644 (file)
@@ -2,6 +2,7 @@
  * hazard-pointer.c: Hazard pointer related code.
  *
  * (C) Copyright 2011 Novell, Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -42,6 +43,7 @@ typedef struct {
 
 static volatile int hazard_table_size = 0;
 static MonoThreadHazardPointers * volatile hazard_table = NULL;
+static MonoHazardFreeQueueSizeCallback queue_size_cb;
 
 /*
  * Each entry is either 0 or 1, indicating whether that overflow small
@@ -305,29 +307,63 @@ try_free_delayed_free_item (HazardFreeContext context)
        return TRUE;
 }
 
+/**
+ * mono_thread_hazardous_try_free:
+ * @p: the pointer to free
+ * @free_func: the function that can free the pointer
+ *
+ * If @p is not a hazardous pointer it will be immediately freed by calling @free_func.
+ * Otherwise it will be queued for later.
+ *
+ * Use this function if @free_func can ALWAYS be called in the context where this function is being called.
+ *
+ * This function doesn't pump the free queue so try to accommodate a call at an appropriate time.
+ * See mono_thread_hazardous_try_free_some for when it's appropriate.
+ *
+ * Return: TRUE if @p was free or FALSE if it was queued.
+ */
+gboolean
+mono_thread_hazardous_try_free (gpointer p, MonoHazardousFreeFunc free_func)
+{
+       if (!is_pointer_hazardous (p)) {
+               free_func (p);
+               return TRUE;
+       } else {
+               mono_thread_hazardous_queue_free (p, free_func);
+               return FALSE;
+       }
+}
+
+/**
+ * mono_thread_hazardous_queue_free:
+ * @p: the pointer to free
+ * @free_func: the function that can free the pointer
+ *
+ * Queue @p to be freed later. @p will be freed once the hazard free queue is pumped.
+ *
+ * This function doesn't pump the free queue so try to accommodate a call at an appropriate time.
+ * See mono_thread_hazardous_try_free_some for when it's appropriate.
+ *
+ */
 void
-mono_thread_hazardous_free_or_queue (gpointer p, MonoHazardousFreeFunc free_func,
-                                     HazardFreeLocking locking, HazardFreeContext context)
+mono_thread_hazardous_queue_free (gpointer p, MonoHazardousFreeFunc free_func)
 {
-       int i;
+       DelayedFreeItem item = { p, free_func, HAZARD_FREE_MAY_LOCK };
 
-       /* First try to free a few entries in the delayed free
-          table. */
-       for (i = 0; i < 3; ++i)
-               try_free_delayed_free_item (context);
+       InterlockedIncrement (&hazardous_pointer_count);
 
-       /* Now see if the pointer we're freeing is hazardous.  If it
-          isn't, free it.  Otherwise put it in the delay list. */
-       if ((context == HAZARD_FREE_ASYNC_CTX && locking == HAZARD_FREE_MAY_LOCK) ||
-           is_pointer_hazardous (p)) {
-               DelayedFreeItem item = { p, free_func, locking };
+       mono_lock_free_array_queue_push (&delayed_free_queue, &item);
 
-               ++hazardous_pointer_count;
+       guint32 queue_size = delayed_free_queue.num_used_entries;
+       if (queue_size && queue_size_cb)
+               queue_size_cb (queue_size);
+}
 
-               mono_lock_free_array_queue_push (&delayed_free_queue, &item);
-       } else {
-               free_func (p);
-       }
+
+void
+mono_hazard_pointer_install_free_queue_size_callback (MonoHazardFreeQueueSizeCallback cb)
+{
+       queue_size_cb = cb;
 }
 
 void
index fa70e71bb40d1853f0269b95ada6d32f1262eda7..3cb2c0aeba33817f0aad3b33bdb9c906913e6fb9 100644 (file)
@@ -2,6 +2,7 @@
  * hazard-pointer.h: Hazard pointer related code.
  *
  * (C) Copyright 2011 Novell, Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_HAZARD_POINTER_H__
 #define __MONO_HAZARD_POINTER_H__
@@ -28,8 +29,9 @@ typedef enum {
        HAZARD_FREE_ASYNC_CTX,
 } HazardFreeContext;
 
-void mono_thread_hazardous_free_or_queue (gpointer p, MonoHazardousFreeFunc free_func,
-                                          HazardFreeLocking locking, HazardFreeContext context);
+gboolean mono_thread_hazardous_try_free (gpointer p, MonoHazardousFreeFunc free_func);
+void mono_thread_hazardous_queue_free (gpointer p, MonoHazardousFreeFunc free_func);
+
 void mono_thread_hazardous_try_free_all (void);
 void mono_thread_hazardous_try_free_some (void);
 MonoThreadHazardPointers* mono_hazard_pointer_get (void);
@@ -57,6 +59,9 @@ int mono_thread_small_id_alloc (void);
 int mono_hazard_pointer_save_for_signal_handler (void);
 void mono_hazard_pointer_restore_for_signal_handler (int small_id);
 
+typedef void (*MonoHazardFreeQueueSizeCallback)(size_t size);
+void mono_hazard_pointer_install_free_queue_size_callback (MonoHazardFreeQueueSizeCallback cb);
+
 void mono_thread_smr_init (void);
 void mono_thread_smr_cleanup (void);
 #endif /*__MONO_HAZARD_POINTER_H__*/
index 2ca9ec247457aa5490ec14587282698366ab081c..331f9038081e178c45067a123ccedf5e4e9c9c01 100644 (file)
@@ -5,6 +5,7 @@
  *   Joao Matos (joao.matos@xamarin.com)
  *
  * Copyright 2015 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <mono/utils/json.h>
index cee9c8905dcfa9ea200a8bc63b07b11037a35c8e..79b26165e77eb3a7c6518733c60a89e881b028f3 100644 (file)
@@ -5,6 +5,7 @@
  *   Joao Matos (joao.matos@xamarin.com)
  *
  * Copyright 2015 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_UTILS_JSON_H__
index 66cb6ea3f8075fc44c9e6793c6bb86b5a7350844..e879d910f1c2e60fe32934c079f98eb840b24169 100644 (file)
@@ -3,24 +3,7 @@
  *
  * (C) Copyright 2011 Novell, 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /*
@@ -250,7 +233,7 @@ desc_retire (Descriptor *desc)
        g_assert (desc->in_use);
        desc->in_use = FALSE;
        free_sb (desc->sb, desc->block_size);
-       mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
+       mono_thread_hazardous_try_free (desc, desc_enqueue_avail);
 }
 #else
 MonoLockFreeQueue available_descs;
@@ -302,7 +285,7 @@ static void
 list_put_partial (Descriptor *desc)
 {
        g_assert (desc->anchor.data.state != STATE_FULL);
-       mono_thread_hazardous_free_or_queue (desc, desc_put_partial, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
+       mono_thread_hazardous_try_free (desc, desc_put_partial);
 }
 
 static void
@@ -321,7 +304,7 @@ list_remove_empty_desc (MonoLockFreeAllocSizeClass *sc)
                        desc_retire (desc);
                } else {
                        g_assert (desc->heap->sc == sc);
-                       mono_thread_hazardous_free_or_queue (desc, desc_put_partial, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
+                       mono_thread_hazardous_try_free (desc, desc_put_partial);
                        if (++num_non_empty >= 2)
                                return;
                }
index 98a3f31745a67bbc88d0a21ceae14c29d3b3b365..b0d0a9a1dfe593ab67005f1cb52e960b0d89447b 100644 (file)
@@ -3,6 +3,7 @@
  * require hazard pointers.
  *
  * (C) Copyright 2011 Xamarin Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /*
index 620025153deeebfcb687463b8694e3a85f37201b..fc924a7639ab011bf567d6f44db039d9648ee899 100644 (file)
@@ -3,6 +3,7 @@
  * require hazard pointers.
  *
  * (C) Copyright 2011 Xamarin Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_LOCK_FREE_ARRAY_QUEUE_H__
 #define __MONO_LOCK_FREE_ARRAY_QUEUE_H__
index b0076c6d18441ade1e6d345282b60652a5f3c57e..464419960de18f73df442a23632400e78c5799ad 100644 (file)
@@ -286,7 +286,7 @@ mono_lock_free_queue_dequeue (MonoLockFreeQueue *q)
                g_assert (q->has_dummy);
                q->has_dummy = 0;
                mono_memory_write_barrier ();
-               mono_thread_hazardous_free_or_queue (head, free_dummy, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
+               mono_thread_hazardous_try_free (head, free_dummy);
                if (try_reenqueue_dummy (q))
                        goto retry;
                return NULL;
index f657b5532ee76999e868360a7dbc69f3e5fe4b0b..455ffe77ea44acc865935bab96f757e0114e71b4 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2013-2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /*
index 51a3618e70640d87cd09046f6b6910b6db130a0e..24cc0544474044307cc06261b69a2d0bf3ba59cf 100644 (file)
@@ -3,18 +3,8 @@
  *
  * Copyright (C) 2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_UTILS_MEMFUNCS_H__
index 798fddb263b00c2081b43b6e14f066fe2b84dcf6..af13bf62b982d00032f425312560f2312d5a505a 100644 (file)
@@ -5,6 +5,7 @@
 *      Joao Matos (joao.matos@xamarin.com)
 *
 * Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
+* Licensed under the MIT license. See LICENSE file in the project root for full license information.
 */
 
 #include <config.h>
index 58cf945facf0a0136f920c2f94d72622df4c7ea9..b5b3539d116c00eef3eba67d112ff9d521df3f9c 100644 (file)
@@ -56,7 +56,7 @@ conc_table_free (gpointer ptr)
 static void
 conc_table_lf_free (conc_table *table)
 {
-       mono_thread_hazardous_free_or_queue (table, conc_table_free, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
+       mono_thread_hazardous_try_free (table, conc_table_free);
 }
 
 
index 81aff561ccab6650b420e92d2613a423e519b243..632513d874f7c8069bd6a1ee0d57c23b1c06bdd3 100644 (file)
@@ -3,6 +3,7 @@
  *
  *
  * Copyright (c) 2011 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <mono/utils/mono-sigcontext.h>
index 2661e657636dde188bb897b51a5284f77f254c3f..c1159ca723a684d75ed193a6be933b2d9b193fca 100644 (file)
@@ -3,6 +3,7 @@
  *
  *
  * Copyright (c) 2011 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 
index 17170a40ed2bec07c33b774255203416740f5543..e0260f8ac848c0e79a6039c39cff0015c873b370 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright 2006-2010 Novell
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <stdlib.h>
index ff7028555c18d05f5a310a58a5caa2739e7cd4c0..225706c547ac78f411d6a57bc554f8e29e7d5290 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2001-2004 Ximian, Inc.
  * Copyright 2004-2009 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 
index 09eed6222e2ff55103654335c72eed343cca79a1..b48a1831d757df85fc1f2f9c1f6756f91cba9695 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2001-2004 Ximian, Inc.
  * Copyright 2004-2009 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 
index 19ff818f733af5e40e54a74347a51b75a2a92201..9e3efa796f7aa93503ab2fa1712d2be476519c73 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2001-2004 Ximian, Inc.
  * Copyright 2004-2009 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 
index aa57e04a50ec92185fc5d54a045e518f4be98458..62493555a30752086a450b0d954005060e9575d0 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2001-2004 Ximian, Inc.
  * Copyright 2004-2009 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "config.h"
 #include "mono/utils/mono-dl.h"
index 3bb1ac6bff637b4e8e0c60396dc382786c502dbc..de78a84aa431f0e84026576401ba4acdac96e84d 100644 (file)
@@ -10,6 +10,7 @@
  * Copyright 2001-2004 Ximian, Inc.
  * Copyright 2004-2010 Novell, Inc.
  *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "config.h"
 #include "mono/utils/mono-dl.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..94c0c4fd35a29639b9d692e08a9d7ce32d4ffbe8 100644 (file)
@@ -4,6 +4,7 @@
  * Authors:
  *     Rodrigo Kumpera    (rkumpera@novell.com)
  * Copyright 2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <glib.h>
 
 #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 +340,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 +421,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 +468,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 +480,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 +742,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 +752,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 c559ad3185dddd98572144b757fe31e93459db52..cd93eaff39fc9aacdee597c3a2d69c2c5b9fded6 100644 (file)
@@ -5,6 +5,7 @@
  *   Paolo Molaro (lupus@ximian.com)
  *
  * Copyright 2008-2008 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 2df530d824e4e7759288e2c089ab942e1cb681da..6cf8065d06a43e421bfb59737800ff73536d3f86 100644 (file)
@@ -16,6 +16,7 @@
  * Copyright 2006 Broadcom
  * Copyright 2007-2008 Andreas Faerber
  * Copyright 2011-2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/utils/mono-hwcap-arm.h"
index 5149cc06943c4b6dfc118dc874a29014b7f82341..5491cff96cfd60ec93560dee66aa7343c11c5803 100644 (file)
@@ -2,6 +2,7 @@
  * mono-hwcap-arm64.c: ARM hardware feature detection
  *
  * Copyright 2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/utils/mono-hwcap-arm64.h"
index 226ab0d6a5702e53a9252788fcc6f07cce4ef90d..b5979862208a32a61fc594f5b150a183f225df6d 100644 (file)
@@ -16,6 +16,7 @@
  * Copyright 2006 Broadcom
  * Copyright 2007-2008 Andreas Faerber
  * Copyright 2011-2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/utils/mono-hwcap-ia64.h"
index a768257ff8f0d503ecbd6cea20fde92c9067cdcf..6d809a79ac54cf488c61faf587a0f5a5d3e50196 100644 (file)
@@ -16,6 +16,7 @@
  * Copyright 2006 Broadcom
  * Copyright 2007-2008 Andreas Faerber
  * Copyright 2011-2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/utils/mono-hwcap-mips.h"
index c88b95f6ec810974cee7fbf0a33d827e073042eb..174cc620a202c7af27d8012b11075f09d78d93ed 100644 (file)
@@ -16,6 +16,7 @@
  * Copyright 2006 Broadcom
  * Copyright 2007-2008 Andreas Faerber
  * Copyright 2011-2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/utils/mono-hwcap-ppc.h"
index d5c9d254c3c95cd31648f2e6a44fb66fd1d2e483..19a7fba11017251a55864c39a93fa94ff5b5b2de 100644 (file)
@@ -16,6 +16,7 @@
  * Copyright 2006 Broadcom
  * Copyright 2007-2008 Andreas Faerber
  * Copyright 2011-2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/utils/mono-hwcap-s390x.h"
index d0456db5494386cf893d21d13c71dc2054b17ecb..ba849873632cf0798c66c34ecddf2990056d9873 100644 (file)
@@ -16,6 +16,7 @@
  * Copyright 2006 Broadcom
  * Copyright 2007-2008 Andreas Faerber
  * Copyright 2011-2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/utils/mono-hwcap-sparc.h"
index 57fff00039e71233065291ea2c746de8e2a1d30b..4a96aa3a088eeb3d6a646c123c603bb305c29296 100644 (file)
@@ -16,6 +16,7 @@
  * Copyright 2006 Broadcom
  * Copyright 2007-2008 Andreas Faerber
  * Copyright 2011-2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mono/utils/mono-hwcap-x86.h"
index 38c032696bb3052623064683ec599073fe63b2c6..a3d2b6078bfdb0d3e401d6e2854497e5ec7f3b8f 100644 (file)
@@ -16,6 +16,7 @@
  * Copyright 2006 Broadcom
  * Copyright 2007-2008 Andreas Faerber
  * Copyright 2011-2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <stdlib.h>
index 99631f08ef68c58f8b0120d0bd95d44b77360473..194eadc15c97f0a0d3541baf85fcd20f72418bf6 100644 (file)
@@ -4,6 +4,7 @@
  * Authors: Ludovic Henry <ludovic@xamarin.com>
  *
  * Copyright 2015 Xamarin, Inc. (www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_LAZY_INIT_H__
index bed9595f84d344e3209521564fc756efcfdb77c9..f076034da21d7f0dc9ff4aa6c3e1e535f20c8ef5 100644 (file)
@@ -126,7 +126,7 @@ try_again:
                                mono_memory_write_barrier ();
                                mono_hazard_pointer_clear (hp, 1);
                                if (list->free_node_func)
-                                       mono_thread_hazardous_free_or_queue (cur, list->free_node_func, list->locking, context);
+                                       mono_thread_hazardous_queue_free (cur, list->free_node_func);
                        } else
                                goto try_again;
                }
@@ -198,7 +198,7 @@ mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLink
                        mono_memory_write_barrier ();
                        mono_hazard_pointer_clear (hp, 1);
                        if (list->free_node_func)
-                               mono_thread_hazardous_free_or_queue (value, list->free_node_func, list->locking, context);
+                               mono_thread_hazardous_try_free (value, list->free_node_func);
                } else
                        mono_lls_find (list, hp, value->key, context);
                return TRUE;
index 6e0d6296fd6b53a04ba05727240d196daab5fb08..947602f0c34e2177d3a829fd6863850208d24c6f 100644 (file)
@@ -152,7 +152,7 @@ mono_lls_filter_accept_all (gpointer elem)
                                                mono_memory_write_barrier (); \
                                                mono_hazard_pointer_clear (hp__, 1); \
                                                if (list__->free_node_func) { \
-                                                       mono_thread_hazardous_free_or_queue (cur__, list__->free_node_func, list__->locking, HAZARD_FREE_ASYNC_CTX); \
+                                                       mono_thread_hazardous_queue_free (cur__, list__->free_node_func); \
                                                } \
                                        } else { \
                                                restart__ = TRUE; \
index 083f41aee33587b4a4b5928869d0fddb0fae548d..fce4e6c2ba693a5340fd455b89ac868208515f52 100644 (file)
@@ -5,6 +5,7 @@
  *     Rodrigo Kumpera (kumpera@gmail.com)
  *
  * Copyright (c) 2011 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_MONO_MACHINE_H__
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 ed6f015a647f369925ccfafda55d6e46d15edc27..faca70b8ca95e655d759182f8538356a5291a8e5 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2014 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_UTILS_MMAP_INTERNAL_H__
index f3b4d17c77bd9104d49c742c56b84d70a1d63eb7..7fa483ce593747f586e4842fed1a720ffeff2dee 100644 (file)
@@ -5,6 +5,7 @@
  *   Mono Team (mono-list@lists.ximian.com)
  *
  * Copyright 2001-2008 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 536640532ef52981ad911a9c00a45682702285a7..8f7f70307c7072e7fd47ecd46c9fd94430aa92dd 100644 (file)
@@ -5,6 +5,8 @@
  * Authors: Jeffrey Stedfast <fejj@ximian.com>
  *
  * Copyright 2002 Ximian, Inc. (www.ximian.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_OS_MUTEX_H__
index dc7ba95c73264a4b5fa54ac474b31e2dcc0f92fc..c53af96454a79e84a98239ad450d0e9f8658154d 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright 2008-2011 Novell Inc
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
index 1e20760e898ebc9ef10350fe86143811b2e92cfe..1e8297750bfb64858fe3f25ec5b5e30bc2b96ede 100644 (file)
@@ -10,6 +10,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2001 Xamarin, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 
@@ -123,7 +124,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 +187,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 +208,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 +226,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 +296,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..9e0b072a1a5e7b6659f2c9f8f83a3e0618a6db6d 100644 (file)
@@ -2,6 +2,7 @@
  * mono-signal-handler.h: Handle signal handler differences across platforms
  *
  * Copyright (C) 2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_SIGNAL_HANDLER_H__
 
 #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 456cb31bb3e7b3aba28590476cafd407483fe949..123f40ba2ada9142574079d10a086586925900e6 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright 2008-2010 Novell, Inc.
  * Copyright 2011 Xamarin Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #ifndef __MONO_MONO_STACK_UNWINDING_H__
 #define __MONO_MONO_STACK_UNWINDING_H__
index a72ee81a56075a5d45a8c36fa2ae5a356b2c9171..fa82387f26ff8e01f26dfc12874eeea0a91d56ab 100644 (file)
@@ -2,8 +2,55 @@
 
 #if defined(PLATFORM_ANDROID)
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/utils/mono-threads-android.c"
-#endif
+#include <pthread.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include "glib.h"
+
+static void
+slow_get_thread_bounds (guint8 *current, guint8 **staddr, size_t *stsize)
+{
+       char buff [1024];
+       FILE *f = fopen ("/proc/self/maps", "r");
+       if (!f)
+               g_error ("Could not determine thread bounds, failed to open /proc/self/maps");
+
+       while (fgets (buff, sizeof (buff), f)) {
+               intmax_t low, high;
+               char *ptr = buff;
+               char *end = NULL;
+               //each line starts with the range we want: f7648000-f7709000
+               low = strtoimax (ptr, &end, 16);
+               if (end) {
+                       ptr = end + 1; //skip the dash to make sure we don't get a negative number
+                       end = NULL;
+                       high = strtoimax (ptr, &end, 16);
+               }
+               if (end && low <= (intmax_t)(size_t)current && high > (intmax_t)(size_t)current) {
+                       *staddr = (guint8 *)(size_t)low;
+                       *stsize = (size_t)(high - low);
+                       fclose (f);
+                       return;
+               }
+       }
+       g_error ("Could not determine thread bounds, failed to find current stack pointer in /proc/self/maps");
+}
+
+void
+mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize)
+{
+       pthread_attr_t attr;
+       guint8 *current = (guint8*)&attr;
+
+       *staddr = NULL;
+       *stsize = (size_t)-1;
+
+       pthread_getattr_np (pthread_self (), &attr);
+       pthread_attr_getstack (&attr, (void**)staddr, stsize);
+       pthread_attr_destroy (&attr);
+
+       if (*staddr && ((current <= *staddr) || (current > *staddr + *stsize)))
+               slow_get_thread_bounds (current, staddr, stsize);
+}
 
 #endif
index 3b11148aafe3af5d8c7ff2d93368bb3033da1e10..4283537b0f9fa205fcbcd1f5752bdac1ab22afd5 100644 (file)
@@ -5,6 +5,7 @@
  *     Rodrigo Kumpera (kumpera@gmail.com)
  *
  * Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -25,6 +26,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 +224,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 +251,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 +310,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 5d08308885afd113ee3e52b0abd8b2eb6ed3ead9..0b142ee1c3f0024fedbce186aa41c65df83e484e 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -424,7 +425,10 @@ unregister_thread (void *arg)
        g_byte_array_free (info->stackdata, /*free_segment=*/TRUE);
 
        /*now it's safe to free the thread info.*/
-       mono_thread_hazardous_free_or_queue (info, free_thread_info, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
+       mono_thread_hazardous_try_free (info, free_thread_info);
+       /* Pump the HP queue */
+       mono_thread_hazardous_try_free_some ();
+
        mono_thread_small_id_free (small_id);
 }
 
index 3c940e73ddfb85b82607dafd526cad6b388219aa..5f0168ebb7475b94886d44a002331d2aa1184842 100644 (file)
@@ -2,6 +2,7 @@
  * Time utility functions.
  * Author: Paolo Molaro (<lupus@ximian.com>)
  * Copyright (C) 2008 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index 0b6cd5a1a1c65ca11233639be85ac86b13c95715..565b3fe593b6a89fd9908f88e8b3d71424f05da8 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_TLS_H__
index 0c44c3f6bfae1f47dc13f6365e98381f020f38d2..0bf17f6727b869e51d81ef173de334692914631e 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
index a899908baad9dbd057d1f4de0653693e5ecc8f1f..e2b4a83f39ac7ecd8c8717e977d39812e0efeb74 100644 (file)
@@ -1,20 +1,7 @@
 /*
  * parse.h: Parsing for GC options.
  *
- * Copyright (C) 2015 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef __MONO_UTILS_PARSE_H__
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)                \