Merge pull request #1321 from esdrubal/currentsystemtimezone
authorMarcos Henrich <marcoshenrich@gmail.com>
Tue, 28 Oct 2014 18:18:54 +0000 (18:18 +0000)
committerMarcos Henrich <marcoshenrich@gmail.com>
Tue, 28 Oct 2014 18:18:54 +0000 (18:18 +0000)
CurrentSystemTimeZone.GetUtcOffset now supports multiple DST periods.

167 files changed:
acinclude.m4
appveyor.yml [new file with mode: 0644]
configure.ac
data/Makefile.am
eglib/acinclude.m4
libgc/acinclude.m4
man/mono.1
mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng.Rnc/RncParser.jay
mcs/class/Commons.Xml.Relaxng/Test/RncTests.cs
mcs/class/Commons.Xml.Relaxng/Test/standalone_tests/Makefile
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Button.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextRenderer.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Theme.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.Engine-net_4_5.csproj
mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoTools.cs
mcs/class/System.Core/System/TimeZoneInfo.Android.cs
mcs/class/System.Core/System/TimeZoneInfo.cs
mcs/class/System.Data/System.Data-net_4_5.csproj
mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs
mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs
mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs
mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.cs
mcs/class/System.Web.Abstractions/System.Web/HttpRequestWrapper.cs
mcs/class/System.Web.Abstractions/System.Web/HttpResponseBase.cs
mcs/class/System.Web.Abstractions/System.Web/HttpResponseWrapper.cs
mcs/class/System.Web/System.Web-net_4_5.csproj
mcs/class/System.Web/System.Web.Configuration_2.0/WebConfigurationManager.cs
mcs/class/System.Web/System.Web.Hosting/HostingEnvironment.cs
mcs/class/System.Web/System.Web.Security/FormsAuthenticationModule.cs
mcs/class/System.Web/System.Web/HttpApplication.cs
mcs/class/System.Web/System.Web/HttpResponse.cs
mcs/class/System.Web/System.Web/HttpUtility.cs
mcs/class/System.Web/System.Web/ReadEntityBodyMode.cs [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web.Hosting/HostingEnvironmentTest.cs
mcs/class/System.Web/Test/System.Web/HttpUtilityTest.cs
mcs/class/System.Web/net_4_5_System.Web.dll.sources
mcs/class/System.XML/System.Xml/XmlTextReader.cs
mcs/class/System.XML/System.Xml/XmlTextReader2.cs
mcs/class/System.XML/Test/System.Xml/XmlTextReaderTests.cs
mcs/class/System/System.Collections.Concurrent/BlockingCollection.cs
mcs/class/System/System.Diagnostics/LocalFileEventLog.cs
mcs/class/System/System.Diagnostics/Process.cs
mcs/class/System/System.Diagnostics/Win32EventLog.cs
mcs/class/System/System.IO.Ports/SerialPort.cs
mcs/class/System/System.IO/DefaultWatcher.cs
mcs/class/System/System.IO/FileSystemWatcher.cs
mcs/class/System/System.IO/KeventWatcher.cs
mcs/class/System/System.IO/SearchPattern.cs
mcs/class/System/System.Media/AudioDevice.cs
mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs
mcs/class/System/System.Net.Sockets/Socket_2_1.cs
mcs/class/System/Test/System.Collections.Concurrent/BlockingCollectionTests.cs
mcs/class/System/Test/System.Net/HttpListenerTest.cs
mcs/class/corlib/System.Reflection/MonoGenericClass.cs
mcs/class/corlib/System.Security.Cryptography/HashAlgorithm.cs
mcs/class/corlib/System.Threading.Tasks/Task.cs
mcs/class/corlib/System.Threading.Tasks/TaskContinuation.cs
mcs/class/corlib/System/AppDomain.cs
mcs/class/corlib/System/String.cs
mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs
mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs
mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs
mcs/class/corlib/corlib-net_4_5.csproj
mcs/errors/cs0677-5.cs [new file with mode: 0644]
mcs/mcs/field.cs
mcs/tests/test-251.cs
mcs/tools/corcompare/mono-api-html/ApiDiff.cs
mcs/tools/corcompare/mono-api-html/ClassComparer.cs
mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs
mono/dis/Makefile.am
mono/io-layer/handles.c
mono/io-layer/handles.h
mono/io-layer/process-private.h
mono/io-layer/processes.c
mono/io-layer/processes.h
mono/io-layer/shared.c
mono/io-layer/shared.h
mono/io-layer/wapi-private.h
mono/metadata/Makefile.am
mono/metadata/boehm-gc.c
mono/metadata/class-internals.h
mono/metadata/class.c
mono/metadata/console-unix.c
mono/metadata/domain-internals.h
mono/metadata/domain.c
mono/metadata/gc-internal.h
mono/metadata/gc.c
mono/metadata/icall-def.h
mono/metadata/jit-info.c [new file with mode: 0644]
mono/metadata/mono-wsq.c
mono/metadata/mono-wsq.h
mono/metadata/object.c
mono/metadata/process.c
mono/metadata/reflection.c
mono/metadata/sgen-alloc.c
mono/metadata/sgen-archdep.h
mono/metadata/sgen-cardtable.c
mono/metadata/sgen-gc.c
mono/metadata/sgen-gc.h
mono/metadata/sgen-internal.c
mono/metadata/sgen-memory-governor.c
mono/metadata/sgen-nursery-allocator.c
mono/metadata/sgen-os-posix.c
mono/metadata/sgen-pointer-queue.c
mono/metadata/sgen-stw.c
mono/metadata/socket-io.c
mono/metadata/string-icalls.c
mono/metadata/string-icalls.h
mono/metadata/threadpool.c
mono/mini/Makefile.am.in
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/branch-opts.c
mono/mini/cpu-arm.md
mono/mini/decompose.c
mono/mini/driver.c
mono/mini/liveness.c
mono/mini/method-to-ir.c
mono/mini/mini-amd64.c
mono/mini/mini-amd64.h
mono/mini/mini-arm.c
mono/mini/mini-arm.h
mono/mini/mini-codegen.c
mono/mini/mini-exceptions.c
mono/mini/mini-ia64.h
mono/mini/mini-llvm.c
mono/mini/mini-mips.h
mono/mini/mini-posix.c
mono/mini/mini-ppc.h
mono/mini/mini-s390x.h
mono/mini/mini-sparc.h
mono/mini/mini-trampolines.c
mono/mini/mini-windows.c
mono/mini/mini-x86.c
mono/mini/mini-x86.h
mono/mini/mini.c
mono/mini/mini.h
mono/mini/ssa.c
mono/mini/tramp-arm.c
mono/mini/unwind.c
mono/mini/wapihandles.c
mono/monograph/Makefile.am
mono/profiler/Makefile.am
mono/tests/libtest.c
mono/tests/pinvoke2.cs
mono/tests/test-runner.cs
mono/utils/Makefile.am
mono/utils/lock-free-alloc.c
mono/utils/lock-free-alloc.h
mono/utils/mono-context.h
mono/utils/mono-mmap-internal.h [new file with mode: 0644]
mono/utils/mono-mmap.c
mono/utils/mono-proclib.c
mono/utils/mono-sigcontext.h
mono/utils/mono-signal-handler.h
mono/utils/mono-threads-freebsd.c
mono/utils/mono-threads.c
msvc/genmdesc.vcxproj
msvc/libgc.vcxproj
msvc/libmonoruntime.vcxproj
msvc/libtest.vcxproj
msvc/mono.props
msvc/profiler-logging.vcxproj
scripts/Makefile.am
winconfig.h

index 5216cd14a5ef88245107fe9f27c1821914e14025..bbc2781eab00efaa492b7d458dd88aa1d8d1561e 100644 (file)
@@ -26,7 +26,7 @@ i?86-*-linux*|i?86-apple-darwin*|x86_64-*-linux*|powerpc-*-linux*|powerpc64-*-li
 |amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*)
     pic_options='-fPIC'
     ;;
-?86-pc-cygwin*|i?86-pc-cygwin*)
+?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*)
     pic_options='-DDLL_EXPORT'
     ;;
 i?86-apple-darwin*|arm-apple-darwin*)
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644 (file)
index 0000000..58c9a3a
--- /dev/null
@@ -0,0 +1,98 @@
+#
+# Appveyor configuration file for CI build of Mono on Windows (under Cygwin)
+#
+# For further details see http://www.appveyor.com
+#
+
+# Use 'unstable' Appveyor build worker image as Appveyor have added Cygwin to this for us
+os: Unstable
+
+#
+# Custom environment variables
+#
+environment:
+    global:
+        CYG_ROOT: C:/cygwin
+        CYG_MIRROR: http://cygwin.mirror.constant.com
+        CYG_CACHE: C:/cygwin/var/cache/setup
+        NSIS_ROOT: C:\nsis
+   
+#
+# Initialisation prior to pulling the Mono repository
+#
+init:
+    - 'echo Building Mono for Windows'
+    - 'echo System architecture: %PLATFORM%'
+    - 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%'
+    - 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%'
+# Attempt to ensure we don't try to convert line endings to Win32 CRLF as this will cause build to fail
+    - 'git config --global core.autocrlf input'
+
+#
+# Install needed build dependencies
+# 
+install:
+# NOTE: Already installed on current Appveyor unstable image
+#    - 'echo Retrieving Cygwin'
+#   - 'appveyor DownloadFile http://cygwin.com/setup-x86.exe -FileName %CYGROOT%/setup-x86.exe'
+    - 'echo Setting up Cygwin dependencies'
+    - '%CYG_ROOT%\setup-x86.exe -qnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P autoconf -P automake -P bison -P gcc-core -P gcc-g++ -P mingw-runtime -P mingw-binutils -P mingw-gcc-core -P mingw-gcc-g++ -P mingw-pthreads -P mingw-w32api -P libtool -P make -P python -P gettext-devel -P gettext -P intltool -P libiconv -P pkg-config -P git -P wget -P curl > NUL' 
+    - 'echo Check Cygwin setup'
+    - '%CYG_ROOT%/bin/bash -lc "cygcheck -dc cygwin"'
+    - 'echo Done setting up Cygwin'
+    - 'echo Retrieving NSIS'
+    - 'appveyor DownloadFile "http://sunet.dl.sourceforge.net/project/nsis/NSIS 2/2.46/nsis-2.46-setup.exe" -FileName nsissetup.exe'
+    - 'echo Setting up NSIS'
+    - 'nsissetup.exe /S /D=%NSIS_ROOT%'
+    - 'echo Done setting up NSIS'
+
+#
+# NOTE: msbuild doesn't work at present so use Cygwin to build
+#
+#build:
+#    project: C:\projects\mono\msvc\mono.sln 
+#    verbosity: detailed
+
+# Cygwin build script
+#
+# NOTES:
+#
+# The stdin/stdout file descriptor appears not to be valid for the Appveyor
+# build which causes failures as certain functions attempt to redirect 
+# default file handles. Ensure a dummy file descriptor is opened with exec.
+#
+build_script:
+    - cmd: 'echo Cygwin root is: %CYG_ROOT%'
+    - cmd: 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%'
+    - cmd: 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%'
+    - cmd: 'echo Repo build commit is: %APPVEYOR_REPO_COMMIT%'
+    - cmd: 'echo Autogen running...'
+    - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; NOCONFIGURE=1 ./autogen.sh --prefix=/usr/local --with-preview=yes"'
+    - cmd: 'echo Configure running...'
+    - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; ./configure --host=i686-pc-mingw32"'
+    - cmd: 'echo Pulling monolite latest...'
+    - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make get-monolite-latest"'
+    - cmd: 'echo Make running...'
+    - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make"'
+    - cmd: 'echo Installing...'
+    - cmd: 'mkdir %APPVEYOR_BUILD_FOLDER%\install'
+    - cmd: '%CYG_ROOT%/bin/bash --login -lc "export CYGWIN=winsymlinks:native; mount \"$APPVEYOR_BUILD_FOLDER\install\" /usr/local; cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make install; umount /usr/local"'
+#    - cmd: 'echo Building package...'
+#    - cmd: 'cd %APPVEYOR_BUILD_FOLDER%'
+#    - cmd: '%NSIS_ROOT%\makensis /DMILESTONE=%APPVEYOR_REPO_BRANCH% /DSOURCE_INSTALL_DIR=%APPVEYOR_BUILD_FOLDER\install\*.* /DBUILDNUM=%APPVEYOR_BUILD_VERSION% monowiz.win32.nsi'
+#    - cmd: 'Building distribution...'
+#    - cmd: '%CYG_ROOT%/bin/bash -lc "export CYGWIN=winsymlinks:native; cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make dist"'
+
+#
+# Disable tests for now
+# 
+test: off
+
+#
+# NOTE: Currently this is the Mono installation tree. In future we will create an installation package artifact.
+#       It has to be relative to the project path. Thus we have installed to within the build tree.
+#
+artifacts:
+    - path: install
+      name: mono-binaries
+      type: zip
index c6c36c9eefbe2cce3aa4a24e2302536e8e66ccad..7e8f26199ad671a789abc1f32925281d0a9ed230 100644 (file)
@@ -115,9 +115,9 @@ case "$host" in
                        AC_DEFINE(MINGW_CROSS_COMPILE,1,[Cross-compiling using MinGW])
                fi
                HOST_CC="gcc"
-               # Windows 2000 is required that includes Internet Explorer 5.01
+               # Windows XP SP2 is required
                CPPFLAGS="$CPPFLAGS -DWINVER=0x0502 -D_WIN32_WINNT=0x0502 -D_WIN32_IE=0x0501 -D_UNICODE -DUNICODE -DWIN32_THREADS -DFD_SETSIZE=1024"
-               LDFLAGS="$LDFLAGS -lmswsock -lws2_32 -lole32 -loleaut32 -lpsapi -lversion -ladvapi32 -lwinmm -lkernel32"
+               LDFLAGS="$LDFLAGS -lmswsock -lws2_32 -lole32 -loleaut32 -lpsapi -lversion -ladvapi32 -lwinmm -lkernel32 -liphlpapi"
                libmono_cflags="-mms-bitfields -mwindows"
                libmono_ldflags="-mms-bitfields -mwindows"
                libdl=
@@ -767,7 +767,7 @@ DISABLED_FEATURES=none
 AC_ARG_ENABLE(minimal, [  --enable-minimal=LIST      drop support for LIST subsystems.
      LIST is a comma-separated list from: aot, profiler, decimal, pinvoke, debug, appdomains, verifier, 
      reflection_emit, reflection_emit_save, large_code, logging, com, ssa, generics, attach, jit, simd, soft_debug, perfcounters, normalization, assembly_remapping, shared_perfcounters, remoting,
-        security, sgen_remset, sgen_marksweep_par, sgen_marksweep_fixed, sgen_marksweep_fixed_par, sgen_copying.],
+        security, sgen_remset, sgen_marksweep_par, sgen_marksweep_fixed, sgen_marksweep_fixed_par, sgen_copying, shared_handles.],
 [
        for feature in `echo "$enable_minimal" | sed -e "s/,/ /g"`; do
                eval "mono_feature_disable_$feature='yes'"
@@ -941,6 +941,11 @@ if test "x$mono_feature_disable_sgen_copying" = "xyes"; then
        AC_MSG_NOTICE([Disabled major=copying support in SGEN.])
 fi
 
+if test "x$mono_feature_disable_shared_handles" = "xyes"; then
+       AC_DEFINE(DISABLE_SHARED_HANDLES, 1, [Disable inter-process shared handles])
+       AC_SUBST(DISABLE_SHARED_HANDLES)
+fi
+
 AC_ARG_ENABLE(executables, [  --disable-executables disable the build of the runtime executables], enable_executables=$enableval, enable_executables=yes)
 AM_CONDITIONAL(DISABLE_EXECUTABLES, test x$enable_executables = xno)
 
@@ -1194,7 +1199,7 @@ if test x$target_win32 = xno; then
 
        AC_CHECK_HEADERS(execinfo.h)
 
-       AC_CHECK_HEADERS(sys/auxv.h)
+       AC_CHECK_HEADERS(sys/auxv.h sys/resource.h)
 
        AC_CHECK_FUNCS(getgrgid_r)
        AC_CHECK_FUNCS(getgrnam_r)
@@ -1213,6 +1218,7 @@ if test x$target_win32 = xno; then
        AC_CHECK_FUNCS(dl_iterate_phdr)
        AC_CHECK_FUNCS(dladdr)
        AC_CHECK_FUNCS(sysconf)
+       AC_CHECK_FUNCS(getrlimit)
 
        AC_CHECK_FUNCS(sched_setaffinity)
        AC_CHECK_FUNCS(sched_getcpu)
@@ -2282,6 +2288,7 @@ if test "x$ac_cv_have_dev_random" = "xno" \
 fi
  
 AC_MSG_CHECKING([if inter-process shared handles are requested])
+# Same as --enable-minimal=shared_handles
 AC_ARG_ENABLE(shared-handles, [  --disable-shared-handles disable inter-process shared handles], try_shared_handles=$enableval, try_shared_handles=yes)
 AC_MSG_RESULT($try_shared_handles)
 if test "x$try_shared_handles" != "xyes"; then
@@ -2498,7 +2505,6 @@ AM_CONDITIONAL(LOADED_LLVM, [test x$enable_loadedllvm = xyes])
 TARGET="unknown"
 ACCESS_UNALIGNED="yes"
 
-JIT_SUPPORTED=no
 LIBC="libc.so.6"
 INTL="libc.so.6"
 SQLITE="libsqlite.so.0"
@@ -2519,7 +2525,6 @@ case "$host" in
                arch_target=mips;
                sgen_supported=true
                ACCESS_UNALIGNED="no"
-               JIT_SUPPORTED=yes
 
                AC_MSG_CHECKING(for mips n32)
                AC_TRY_COMPILE([],[
@@ -2537,7 +2542,6 @@ case "$host" in
        i*86-*-*)
                TARGET=X86;
                arch_target=x86;
-               JIT_SUPPORTED=yes
                case $host_os in
                  solaris*)
                        LIBC="libc.so"
@@ -2583,7 +2587,6 @@ case "$host" in
        x86_64-*-* | amd64-*-*)
                TARGET=AMD64;
                arch_target=amd64;
-               JIT_SUPPORTED=yes
                if test "x$ac_cv_sizeof_void_p" = "x4"; then
                        AC_DEFINE(__mono_ilp32__, 1, [64 bit mode with 4 byte longs and pointers])
                        sizeof_register=8
@@ -2615,7 +2618,6 @@ case "$host" in
                TARGET=IA64
                arch_target=ia64
                ACCESS_UNALIGNED="no"
-               JIT_SUPPORTED=yes
                LIBC="libc.so.6.1"
                INTL="libc.so.6.1"
                AC_CHECK_LIB(unwind, _U_dyn_register, [], [AC_MSG_ERROR(library libunwind not found)])
@@ -2628,7 +2630,6 @@ case "$host" in
                        TARGET=SPARC
                fi
                arch_target=sparc;
-               JIT_SUPPORTED=yes
                ACCESS_UNALIGNED="no"
                case $host_os in
                  linux*) ;;
@@ -2661,7 +2662,6 @@ case "$host" in
                        CPPFLAGS="$CPPFLAGS -D__mono_ppc__"
                fi
                arch_target=ppc;
-               JIT_SUPPORTED=yes
                case $host_os in
                  linux*|darwin*)
                        sgen_supported=true
@@ -2672,7 +2672,6 @@ case "$host" in
                TARGET=ARM;
                arch_target=arm;
                ACCESS_UNALIGNED="no"
-               JIT_SUPPORTED=yes
                CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
                sgen_supported=true
                ;;
@@ -2680,7 +2679,6 @@ case "$host" in
                TARGET=ARM;
                arch_target=arm;
                ACCESS_UNALIGNED="no"
-               JIT_SUPPORTED=yes
                sgen_supported=true
                AOT_SUPPORTED="yes"
                CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
@@ -2690,7 +2688,6 @@ case "$host" in
 #              TARGET=ARM;
 #              arch_target=arm;
 #              ACCESS_UNALIGNED="no"
-#              JIT_SUPPORTED=yes
 #              sgen_supported=true
 #              AOT_SUPPORTED="no"
 #              ;;
@@ -2698,7 +2695,6 @@ case "$host" in
                # https://lkml.org/lkml/2012/7/15/133
                TARGET=ARM64
                arch_target=arm64
-               JIT_SUPPORTED=yes
                sgen_supported=true
                boehm_supported=false
                ;;
@@ -2706,7 +2702,6 @@ case "$host" in
                TARGET=S390X;
                arch_target=s390x;
                ACCESS_UNALIGNED="yes"
-               JIT_SUPPORTED=yes
                sgen_supported=true
                CFLAGS="$CFLAGS -mbackchain -D__USE_STRING_INLINES"
                ;;
@@ -2722,9 +2717,7 @@ if test "x$host" != "x$target"; then
                TARGET=ARM;
                arch_target=arm;
                ACCESS_UNALIGNED="no"
-               JIT_SUPPORTED=yes
                CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
-               jit_wanted=true
                # Can't use tls, since it depends on the runtime detection of tls offsets
                # in mono-compiler.h
                with_tls=pthread
@@ -2762,7 +2755,6 @@ if test "x$host" != "x$target"; then
 #              arch_target=arm
 #              AC_DEFINE(TARGET_ARM, 1, [...])
 #              ACCESS_UNALIGNED="no"
-#              JIT_SUPPORTED=yes
 #              sizeof_register=4
 #               CPPFLAGS="$CPPFLAGS \
 #                    -D__ARM_EABI__ \
@@ -2772,7 +2764,6 @@ if test "x$host" != "x$target"; then
 #                    -DDISABLE_SOCKETS \
 #                    -DDISABLE_ATTACH \
 #                    -DUSE_NEWLIB"
-#              jit_wanted=true
                # Can't use tls, since it depends on the runtime detection of tls offsets
                # in mono-compiler.h
 #              with_tls=pthread
@@ -2789,9 +2780,7 @@ if test "x$host" != "x$target"; then
                AC_DEFINE(TARGET_ARM, 1, [...])
                AC_DEFINE(TARGET_ANDROID, 1, [...])
                ACCESS_UNALIGNED="no"
-               JIT_SUPPORTED=yes
                CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
-               jit_wanted=true
                # Can't use tls, since it depends on the runtime detection of tls offsets
                # in mono-compiler.h
                with_tls=pthread
@@ -2811,9 +2800,7 @@ if test "x$host" != "x$target"; then
                arch_target=x86;
                AC_DEFINE(TARGET_X86, 1, [...])
                AC_DEFINE(TARGET_ANDROID, 1, [...])
-               JIT_SUPPORTED=yes
                CPPFLAGS="$CPPFLAGS"
-               jit_wanted=true
                sgen_supported=true
                # Can't use tls, since it depends on the runtime detection of tls offsets
                # in mono-compiler.h            
@@ -2822,8 +2809,6 @@ if test "x$host" != "x$target"; then
                ;;                      
        aarch64-*)
                TARGET=ARM64
-               JIT_SUPPORTED=yes
-               jit_wanted=true
                ;;
        *)
                AC_MSG_ERROR([Cross compiling is not supported for target $target])
@@ -2946,19 +2931,7 @@ fi
 AC_SUBST(SGEN_DEFINES)
 AM_CONDITIONAL(SUPPORT_SGEN, test x$buildsgen = xyes)
 
-USEJIT=false
-if test x$JIT_SUPPORTED = xyes; then
-   if $jit_wanted; then
-      USEJIT=true
-      jit_status="Building and using the JIT"
-   else
-      AC_ERROR(No JIT support available or selected.)
-   fi
-else
-   AC_ERROR(No JIT support available or selected.)
-fi
-
-AM_CONDITIONAL(USE_JIT, test x$USEJIT = xtrue)
+jit_status="Building and using the JIT"
 
 libsuffix=".so"
 
@@ -3361,7 +3334,6 @@ AM_CONDITIONAL(HOST_ARM, test x$HOST = xARM)
 AM_CONDITIONAL(HOST_ARM64, test x$HOST = xARM64)
 AM_CONDITIONAL(CROSS_COMPILE, test "x$host" != "x$target")
 
-AM_CONDITIONAL(JIT_SUPPORTED, test x$JIT_SUPPORTED = xyes)
 AM_CONDITIONAL(INCLUDED_LIBGC, test x$libgc = xincluded)
 
 AC_SUBST(LIBC)
index 32a13623cb9d66f4c247fcd2332b771859bc7793..daf6f38a79b0f46601558a19b3da7f1952152b62 100644 (file)
@@ -26,12 +26,8 @@ else
 SGENPCFILE=
 endif
 
-if JIT_SUPPORTED
 pkgconfig_DATA= mono.pc mono-2.pc dotnet.pc dotnet35.pc wcf.pc mono-nunit.pc mono-cairo.pc mono-options.pc cecil.pc monodoc.pc mono-lineeditor.pc system.web.extensions_1.0.pc \
                system.web.extensions.design_1.0.pc system.web.mvc.pc system.web.mvc2.pc system.web.mvc3.pc aspnetwebstack.pc reactive.pc xbuild12.pc $(SGENPCFILE)
-else
-pkgconfig_DATA= mint.pc mono-nunit.pc mono-cairo.pc mono-options.pc cecil.pc monodoc.pc mono-lineeditor.pc
-endif
 
 DISTCLEANFILES= mono-2.pc mono.pc mint.pc dotnet.pc dotnet35.pc wcf.pc mono-nunit.pc mono-cairo.pc mono-options.pc cecil.pc monodoc.pc mono-lineeditor.pc system.web.extensions_1.0.pc \
                system.web.extensions.design_1.0.pc system.web.mvc.pc system.web.mvc2.pc system.web.mvc3.pc aspnetwebstack.pc reactive.pc $(SGENPCFILE) mono-sgen-gdb.py
index 5216cd14a5ef88245107fe9f27c1821914e14025..bbc2781eab00efaa492b7d458dd88aa1d8d1561e 100644 (file)
@@ -26,7 +26,7 @@ i?86-*-linux*|i?86-apple-darwin*|x86_64-*-linux*|powerpc-*-linux*|powerpc64-*-li
 |amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*)
     pic_options='-fPIC'
     ;;
-?86-pc-cygwin*|i?86-pc-cygwin*)
+?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*)
     pic_options='-DDLL_EXPORT'
     ;;
 i?86-apple-darwin*|arm-apple-darwin*)
index 5216cd14a5ef88245107fe9f27c1821914e14025..bbc2781eab00efaa492b7d458dd88aa1d8d1561e 100644 (file)
@@ -26,7 +26,7 @@ i?86-*-linux*|i?86-apple-darwin*|x86_64-*-linux*|powerpc-*-linux*|powerpc64-*-li
 |amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*)
     pic_options='-fPIC'
     ;;
-?86-pc-cygwin*|i?86-pc-cygwin*)
+?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*)
     pic_options='-DDLL_EXPORT'
     ;;
 i?86-apple-darwin*|arm-apple-darwin*)
index d058031ed16802af57ce52dd88f1c0868c40b1e5..784c078d3815302c80e86dfbf9fe73a2672e557f 100644 (file)
@@ -1257,6 +1257,11 @@ work, Mono needs to be compiled with the BINARY_PROTOCOL define on
 sgen-gc.c.   You can then use this command to explore the output
 .nf
                 sgen-grep-binprot 0x1234 0x5678 < file
+.TP
+\fBnursery-canaries\fR
+If set, objects allocated in the nursery are suffixed with a canary (guard)
+word, which is checked on each minor collection. Can be used to detect/debug
+heap corruption issues.
 .fi
 .ne
 .RE
index df3157f022a708c9b054af48eb93c0e27d0ec722..625df5ca15289a9356f574dd45f19fab3fe31ff6 100644 (file)
@@ -107,7 +107,7 @@ namespace Commons.Xml.Relaxng.Rnc
 
                public RelaxngPattern Parse (TextReader source, string baseUri, string defaultNamespace)
                {
-                       this.defaultNamespace = defaultNamespace;
+                       this.defaultNamespace = defaultNamespace ?? string.Empty;
                        if (defaultNamespace != null && defaultNamespace.Length != 0)
                                nsmgr.AddNamespace (String.Empty, defaultNamespace);
                        try {
index d25fcb1e1c76e150279eca049a214a9a7f43f853..fb7ac65e9c74f8affed9e67af3b21a4f457667be 100644 (file)
@@ -95,5 +95,19 @@ start = mine";
                                r.Close ();
                        }
                }
+               
+               [Test]
+               public void SimpleDefaultNamespace ()
+               {
+                       var g = RncParser.ParseRnc (new StringReader ("element e { empty }"));
+                       var x = XmlReader.Create (new StringReader ("<e/>"));
+                       var r = new RelaxngValidatingReader (x, g); 
+                       try {
+                               while (!r.EOF)
+                                       r.Read ();
+                       } finally {
+                               r.Close ();
+                       }
+               }
        }
 }
index 6653702d5563459e35070776146b504c79d0e618..9be0e7ff4008f3155352facffe0f0b72531fa764 100644 (file)
@@ -8,7 +8,7 @@ TEST_ARCHIVE = testSuite.zip
 RNCTESTS = test/RNCTest.xml
 RNCTEST_ARCHIVE = anglia-test-suite.zip
 
-all : relaxngtest.exe anglia-test-runner.exe
+all : relaxngtest.exe #anglia-test-runner.exe
 
 relaxngtest.exe : relaxngtest.cs $(TESTS)
        $(MCS_RUNTIME) $(MCS) -debug+ relaxngtest.cs -r:Commons.Xml.Relaxng.dll
index dc640e836cd242f4906eb100c04174895549966b..e04f3997168772d76d1497f97ac8e1b9dadc1f1d 100644 (file)
@@ -175,7 +175,7 @@ namespace System.Windows.Forms {
                        Rectangle text_rectangle;
                        Rectangle image_rectangle;
 
-                       ThemeEngine.Current.CalculateButtonTextAndImageLayout (this, out text_rectangle, out image_rectangle);
+                       ThemeEngine.Current.CalculateButtonTextAndImageLayout (pevent.Graphics, this, out text_rectangle, out image_rectangle);
 
                        // Draw our button
                        if (this.FlatStyle == FlatStyle.Standard)
index 6f3be9db10be9310c4830d8d11564c5497078377..bda5da96f78d996a6c4122998e5c19a7568cdba0 100644 (file)
@@ -258,11 +258,19 @@ namespace System.Windows.Forms
                        StringFormat sf = FlagsToStringFormat (flags);
 
                                Size retval;
-                               
+
+                               int proposedWidth;
+                               if (proposedSize.Width == 0)
+                                       proposedWidth = Int32.MaxValue;
+                               else {
+                                       proposedWidth = proposedSize.Width;
+                                       if ((flags & TextFormatFlags.NoPadding) == 0)
+                                               proposedWidth -= 9;
+                               }
                                if (dc is Graphics)
-                                       retval = (dc as Graphics).MeasureString (text, font, proposedSize.Width == 0 ? Int32.MaxValue : proposedSize.Width, sf).ToSize ();
+                                       retval = (dc as Graphics).MeasureString (text, font, proposedWidth, sf).ToSize ();
                                else
-                                       retval = TextRenderer.MeasureString (text, font, proposedSize.Width == 0 ? Int32.MaxValue : proposedSize.Width, sf).ToSize ();
+                                       retval = TextRenderer.MeasureString (text, font, proposedWidth, sf).ToSize ();
 
                                if (retval.Width > 0 && (flags & TextFormatFlags.NoPadding) == 0)
                                        retval.Width += 9;
index 18ee3dd8117ad2359379172886bca6eef8afec92..b8cc63b7e812b8592a36f56bb84d274c78b64098 100644 (file)
@@ -698,7 +698,7 @@ namespace System.Windows.Forms
 
                #region Button
                public abstract Size CalculateButtonAutoSize (Button button);
-               public abstract void CalculateButtonTextAndImageLayout (ButtonBase b, out Rectangle textRectangle, out Rectangle imageRectangle);
+               public abstract void CalculateButtonTextAndImageLayout (Graphics g, ButtonBase b, out Rectangle textRectangle, out Rectangle imageRectangle);
                public abstract void DrawButton (Graphics g, Button b, Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle);
                public abstract void DrawFlatButton (Graphics g, ButtonBase b, Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle);
                public abstract void DrawPopupButton (Graphics g, Button b, Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle);
index 522dec40ec616af384bc431f1c9406aabdaec3fb..29921942b4eddbcd9cdbc0b9c29b4e12a60804a8 100644 (file)
@@ -364,24 +364,23 @@ namespace System.Windows.Forms
                        return ret_size;
                }
 
-               public override void CalculateButtonTextAndImageLayout (ButtonBase button, out Rectangle textRectangle, out Rectangle imageRectangle)
+               public override void CalculateButtonTextAndImageLayout (Graphics g, ButtonBase button, out Rectangle textRectangle, out Rectangle imageRectangle)
                {
                        Image image = button.Image;
                        string text = button.Text;
                        Rectangle content_rect = button.PaddingClientRectangle;
-                       Size text_size = TextRenderer.MeasureTextInternal (text, button.Font, content_rect.Size, button.TextFormatFlags, button.UseCompatibleTextRendering);
+                       Size text_size = TextRenderer.MeasureTextInternal (g, text, button.Font, content_rect.Size, button.TextFormatFlags | TextFormatFlags.NoPadding, button.UseCompatibleTextRendering);
                        Size image_size = image == null ? Size.Empty : image.Size;
 
-                       textRectangle = Rectangle.Empty;
+                       textRectangle = Rectangle.Inflate (content_rect, -4, -4);
                        imageRectangle = Rectangle.Empty;
                        
                        switch (button.TextImageRelation) {
                                case TextImageRelation.Overlay:
                                        // Overlay is easy, text always goes here
-                                       textRectangle = Rectangle.Inflate (content_rect, -4, -4);
 
-                                       if (button.Pressed)
-                                               textRectangle.Offset (1, 1);
+                                               if (button.Pressed)
+                                                       textRectangle.Offset (1, 1);
                                                
                                        // Image is dependent on ImageAlign
                                        if (image == null)
@@ -438,20 +437,16 @@ namespace System.Windows.Forms
                                        imageRectangle = new Rectangle (image_x, image_y, image_width, image_height);
                                        break;
                                case TextImageRelation.ImageAboveText:
-                                       content_rect.Inflate (-4, -4);
-                                       LayoutTextAboveOrBelowImage (content_rect, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
+                                       LayoutTextAboveOrBelowImage (textRectangle, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
                                        break;
                                case TextImageRelation.TextAboveImage:
-                                       content_rect.Inflate (-4, -4);
-                                       LayoutTextAboveOrBelowImage (content_rect, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
+                                       LayoutTextAboveOrBelowImage (textRectangle, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
                                        break;
                                case TextImageRelation.ImageBeforeText:
-                                       content_rect.Inflate (-4, -4);
-                                       LayoutTextBeforeOrAfterImage (content_rect, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
+                                       LayoutTextBeforeOrAfterImage (textRectangle, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
                                        break;
                                case TextImageRelation.TextBeforeImage:
-                                       content_rect.Inflate (-4, -4);
-                                       LayoutTextBeforeOrAfterImage (content_rect, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
+                                       LayoutTextBeforeOrAfterImage (textRectangle, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
                                        break;
                        }
                }
@@ -537,12 +532,14 @@ namespace System.Windows.Forms
                                offset += (int)(2 * (excess_height / 3));
 
                        if (textFirst) {
-                               final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, totalArea.Top + offset, textSize.Width, textSize.Height);
+                               var textHeight = excess_height >= 0 ? totalArea.Height - imageSize.Height - element_spacing: textSize.Height;
+                               final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, totalArea.Top + offset, textSize.Width, textHeight);
                                final_image_rect = new Rectangle (AlignInRectangle (totalArea, imageSize, imageAlign).Left, final_text_rect.Bottom + element_spacing, imageSize.Width, imageSize.Height);
                        }
                        else {
                                final_image_rect = new Rectangle (AlignInRectangle (totalArea, imageSize, imageAlign).Left, totalArea.Top + offset, imageSize.Width, imageSize.Height);
-                               final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, final_image_rect.Bottom + element_spacing, textSize.Width, textSize.Height);
+                               var textHeight = excess_height >= 0 ? totalArea.Height - final_image_rect.Height : textSize.Height;
+                               final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, final_image_rect.Bottom + element_spacing, textSize.Width, textHeight);
                                
                                if (final_text_rect.Bottom > totalArea.Bottom)
                                        final_text_rect.Y = totalArea.Top;
index 1f3af25846450af900f33b95ed551929392ee807..657a42457c9f222751c977278db272df8f1f1caf 100644 (file)
@@ -1296,7 +1296,7 @@ namespace System.Windows.Forms {
                                                buffer [i] = Marshal.ReadByte (prop, i);
                                        Clipboard.Item = Encoding.UTF8.GetString (buffer);
                                } else if (property == UTF16_STRING) {
-                                       Clipboard.Item = Marshal.PtrToStringUni (prop, Encoding.Unicode.GetMaxCharCount ((int)nitems));
+                                       Clipboard.Item = Marshal.PtrToStringUni (prop);
                                } else if (property == RICHTEXTFORMAT)
                                        Clipboard.Item = Marshal.PtrToStringAnsi(prop);
                                else if (DataFormats.ContainsFormat (property.ToInt32 ())) {
index df6603cfa8569c53f1ea348724911660b08ee8d4..2c42dc4da76a6ae9586a4a01f2994522743f09e6 100644 (file)
     <Compile Include="Microsoft.Build.BuildEngine\TaskBatchingImpl.cs" />\r
     <Compile Include="Microsoft.Build.BuildEngine\TaskDatabase.cs" />\r
     <Compile Include="Microsoft.Build.BuildEngine\TaskEngine.cs" />\r
+    <Compile Include="Microsoft.Build.BuildEngine\TaskExecutionMode.cs" />\r
     <Compile Include="Microsoft.Build.BuildEngine\Token.cs" />\r
     <Compile Include="Microsoft.Build.BuildEngine\Toolset.cs" />\r
     <Compile Include="Microsoft.Build.BuildEngine\ToolsetCollection.cs" />\r
index 054038731aec8a6f15ef7c9ece468b1603ae68b9..d57ce5ae55c1e69d7a444b3568960b11554979be 100644 (file)
@@ -88,10 +88,6 @@ namespace Mono.Security.Cryptography {
                // block size (which isn't their real internal block size)
                public BlockProcessor (ICryptoTransform transform, int blockSize)
                {
-                       if (transform == null)
-                               throw new ArgumentNullException ("transform");
-                       if (blockSize <= 0)
-                               throw new ArgumentOutOfRangeException ("blockSize");
                        this.transform = transform;
                        this.blockSize = blockSize;
                        block = new byte [blockSize];
index 63502e555faaecfae8e0a5a6dd0e6e0b1a20e32b..079af3722d6cc9b4882304c15ee1a750aad7bc31 100644 (file)
@@ -453,29 +453,29 @@ namespace System {
                                        : db.GetAvailableIds ();
                        }
 
-                       static TimeZoneInfo _GetTimeZone (string name)
+                       static TimeZoneInfo _GetTimeZone (string id, string name)
                        {
                                if (db == null)
                                        return null;
                                byte[] buffer = db.GetTimeZoneData (name);
                                if (buffer == null)
                                        return null;
-                               return TimeZoneInfo.ParseTZBuffer (name, buffer, buffer.Length);
+                               return TimeZoneInfo.ParseTZBuffer (id, buffer, buffer.Length);
                        }
 
-                       internal static TimeZoneInfo GetTimeZone (string id)
+                       internal static TimeZoneInfo GetTimeZone (string id, string name)
                        {
-                               if (id != null) {
-                                       if (id == "GMT" || id == "UTC")
-                                               return new TimeZoneInfo (id, TimeSpan.FromSeconds (0), id, id, id, null, true);
-                                       if (id.StartsWith ("GMT"))
+                               if (name != null) {
+                                       if (name == "GMT" || name == "UTC")
+                                               return new TimeZoneInfo (id, TimeSpan.FromSeconds (0), id, name, name, null, disableDaylightSavingTime:true);
+                                       if (name.StartsWith ("GMT"))
                                                return new TimeZoneInfo (id,
-                                                               TimeSpan.FromSeconds (ParseNumericZone (id)),
-                                                               id, id, id, null, true);
+                                                               TimeSpan.FromSeconds (ParseNumericZone (name)),
+                                                               id, name, name, null, disableDaylightSavingTime:true);
                                }
 
                                try {
-                                       return _GetTimeZone (id);
+                                       return _GetTimeZone (id, name);
                                } catch (Exception) {
                                        return null;
                                }
@@ -533,12 +533,12 @@ namespace System {
                        static readonly object _lock = new object ();
 
                        static TimeZoneInfo defaultZone;
-                       internal static TimeZoneInfo Default {
+                       internal static TimeZoneInfo Local {
                                get {
                                        lock (_lock) {
                                                if (defaultZone != null)
                                                        return defaultZone;
-                                               return defaultZone = GetTimeZone (GetDefaultTimeZoneName ());
+                                               return defaultZone = GetTimeZone ("Local", GetDefaultTimeZoneName ());
                                        }
                                }
                        }
@@ -553,7 +553,10 @@ namespace System {
                        {
                                IntPtr value = IntPtr.Zero;
                                int n = 0;
-                               string defaultTimeZone;
+                               string defaultTimeZone  = Environment.GetEnvironmentVariable ("__XA_OVERRIDE_TIMEZONE_ID__");
+
+                               if (!string.IsNullOrEmpty (defaultTimeZone))
+                                       return defaultTimeZone;
 
                                // Used by the tests
                                if (Environment.GetEnvironmentVariable ("__XA_USE_JAVA_DEFAULT_TIMEZONE_ID__") == null)
@@ -576,16 +579,20 @@ namespace System {
 #if SELF_TEST
                        /*
                         * Compile:
-                        *    mcs  /out:tzi.exe /unsafe "/d:INSIDE_CORLIB;MONODROID;NET_4_0;LIBC;SELF_TEST" System/TimeZone*.cs ../../build/common/Consts.cs ../Mono.Options/Mono.Options/Options.cs
+                        *    mcs /debug+ /out:tzi.exe /unsafe "/d:INSIDE_CORLIB;MONODROID;NET_4_0;LIBC;SELF_TEST" ../corlib/System/AndroidPlatform.cs System/TimeZone*.cs ../../build/common/Consts.cs ../Mono.Options/Mono.Options/Options.cs
                         * Prep:
                         *    mkdir -p usr/share/zoneinfo
+                        *    mkdir -p misc/zoneinfo/zoneinfo
                         *    android_root=`adb shell echo '$ANDROID_ROOT' | tr -d "\r"`
+                        *    android_data=`adb shell echo '$ANDROID_DATA' | tr -d "\r"`
                         *    adb pull $android_root/usr/share/zoneinfo usr/share/zoneinfo
+                        *    adb pull $android_data/misc/zoneinfo/tzdata misc/zoneinfo
                         * Run:
-                        *    ANDROID_ROOT=`pwd` mono tzi.exe
+                        *    __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe --offset=1969-01-01
                         */
                        static void Main (string[] args)
                        {
+                               DateTime? offset           = null;
                                Func<IAndroidTimeZoneDB> c = () => GetDefaultTimeZoneDB ();
                                Mono.Options.OptionSet p = null;
                                p = new Mono.Options.OptionSet () {
@@ -595,6 +602,10 @@ namespace System {
                                        { "Z=", "Create ZoneInfoDB from {DIR}.", v => {
                                                        c = () => new ZoneInfoDB (v);
                                        } },
+                                       { "offset=", "Show timezone info offset for DateTime {OFFSET}.", v => {
+                                               offset = DateTime.Parse (v);
+                                               Console.WriteLine ("Using DateTime Offset: {0}", offset);
+                                       } },
                                        { "help", "Show this message and exit", v => {
                                                        p.WriteOptionDescriptions (Console.Out);
                                                        Environment.Exit (0);
@@ -606,9 +617,13 @@ namespace System {
                                foreach (var id in GetAvailableIds ()) {
                                        Console.Write ("name={0,-40}", id);
                                        try {
-                                               TimeZoneInfo zone = _GetTimeZone (id);
-                                               if (zone != null)
-                                                       Console.Write (" {0}", zone);
+                                               TimeZoneInfo zone = _GetTimeZone (id, id);
+                                               if (zone != null) {
+                                                       Console.Write (" {0,-40}", zone);
+                                                       if (offset.HasValue) {
+                                                               Console.Write ("From Offset: {0}", zone.GetUtcOffset (offset.Value));
+                                                       }
+                                               }
                                                else {
                                                        Console.Write (" ERROR:null");
                                                }
index 15ee8615aea7b9ca711589a12cad006ba8b64c8b..f6fa19c0d34e182fd43b44a98bfddb524e98cb96 100644 (file)
@@ -111,7 +111,7 @@ namespace System
                static TimeZoneInfo CreateLocal ()
                {
 #if MONODROID
-                       return AndroidTimeZones.Default;
+                       return AndroidTimeZones.Local;
 #elif MONOTOUCH
                        using (Stream stream = GetMonoTouchData (null)) {
                                return BuildFromStream ("Local", stream);
@@ -427,7 +427,7 @@ namespace System
                        }
 #endif
 #if MONODROID
-                       var timeZoneInfo = AndroidTimeZones.GetTimeZone (id);
+                       var timeZoneInfo = AndroidTimeZones.GetTimeZone (id, id);
                        if (timeZoneInfo == null)
                                throw new TimeZoneNotFoundException ();
                        return timeZoneInfo;
@@ -656,7 +656,7 @@ namespace System
 #endif
 #if MONODROID
                        foreach (string id in AndroidTimeZones.GetAvailableIds ()) {
-                               var tz = AndroidTimeZones.GetTimeZone (id);
+                               var tz = AndroidTimeZones.GetTimeZone (id, id);
                                if (tz != null)
                                        systemTimeZones.Add (tz);
                        }
index 95dead37499f066bc460e7be0cb115b2c6bea82f..eb65112a4177b6fc546d5ff9877b508be17ed94f 100644 (file)
     <Compile Include="System.Data.SqlClient\SqlCommandBuilder.cs" />\r
     <Compile Include="System.Data.SqlClient\SqlConnection.cs" />\r
     <Compile Include="System.Data.SqlClient\SqlConnectionStringBuilder.cs" />\r
+    <Compile Include="System.Data.SqlClient\SqlCredential.cs" />\r
     <Compile Include="System.Data.SqlClient\SqlDataAdapter.cs" />\r
     <Compile Include="System.Data.SqlClient\SqlDataReader.cs" />\r
     <Compile Include="System.Data.SqlClient\SqlDataSourceConverter.cs" />\r
index 295161932b55c2bc9b4873d642d094ceef59b064..8ae0ce57356002636911dc5d32c903933703483b 100644 (file)
@@ -84,7 +84,17 @@ namespace System.Runtime.Serialization.Json
                                throw new ArgumentOutOfRangeException ("maxItemsInObjectGraph");
 
                        this.type = type;
-                       known_types = new ReadOnlyCollection<Type> (knownTypes != null ? knownTypes.ToArray () : Type.EmptyTypes);
+
+                       var knownTypesFromAttributes = new List<Type> ();
+
+                       foreach (var attr in type.GetCustomAttributes (typeof (KnownTypeAttribute), false))
+                               knownTypesFromAttributes.Add ((attr as KnownTypeAttribute).Type);
+
+                       if (knownTypes != null)
+                               knownTypesFromAttributes.AddRange (knownTypes);
+
+                       known_types = new ReadOnlyCollection<Type> (knownTypesFromAttributes);
+
                        root = rootName;
                        max_items = maxItemsInObjectGraph;
                        ignore_extension = ignoreExtensionDataObject;
@@ -134,8 +144,6 @@ namespace System.Runtime.Serialization.Json
                public bool IgnoreExtensionDataObject {
                        get { return ignore_extension; }
                }
-
-               [MonoTODO]
                public ReadOnlyCollection<Type> KnownTypes {
                        get { return known_types; }
                }
index 55d03402ad243046eab7286730161d39e878f288..d0f84d0f93a6a66ee3a5cb41bc97ce2a14371a38 100644 (file)
@@ -182,8 +182,18 @@ namespace System.Runtime.Serialization.Json
                                        if (ct != null) {
                                                return DeserializeGenericCollection (type, ct, instance);
                                        } else {
-                                               TypeMap map = GetTypeMap (type);
-                                               return map.Deserialize (this, instance);
+                                               string typeHint = reader.GetAttribute ("__type");
+                                               if (typeHint != null) {
+                                                       // this might be a derived & known type. We allow it when it's both.
+                                                       Type exactType = GetRuntimeType (typeHint, type);
+                                                       if (exactType == null)
+                                                               throw SerializationError (String.Format ("Cannot load type '{0}'", typeHint));
+                                                        TypeMap map = GetTypeMap (exactType);
+                                                        return map.Deserialize (this, instance);
+                                               } else { // no type hint
+                                                       TypeMap map = GetTypeMap (type);
+                                                        return map.Deserialize (this, instance);
+                                               }
                                        }
                                }
                                else
@@ -198,24 +208,22 @@ namespace System.Runtime.Serialization.Json
                }
                
 
-               Type GetRuntimeType (string name)
+               Type GetRuntimeType (string name, Type baseType)
                {
-                       name = ToRuntimeTypeName (name);
+                       string properName = ToRuntimeTypeName (name);
+
+                       if (baseType != null && baseType.FullName.Equals (properName))
+                               return baseType;
+
                        if (serializer.KnownTypes != null)
                                foreach (Type t in serializer.KnownTypes)
-                                       if (t.FullName == name)
+                                       if (t.FullName.Equals (properName)) 
                                                return t;
-                       var ret = root_type.Assembly.GetType (name, false) ?? Type.GetType (name, false);
-                       if (ret != null)
-                               return ret;
 
-                       // We probably have to iterate all the existing
-                       // assemblies that are loaded in current domain.
-                       foreach (var ass in AppDomain.CurrentDomain.GetAssemblies ()) {
-                               ret = ass.GetType (name, false);
-                               if (ret != null)
-                                       return ret;
-                       }
+                       if (baseType != null)
+                               foreach (var attr in baseType.GetCustomAttributes (typeof (KnownTypeAttribute), false))
+                                       if ((attr as KnownTypeAttribute).Type.FullName.Equals (properName))
+                                               return (attr as KnownTypeAttribute).Type;
 
                        return null;
                }
@@ -230,7 +238,7 @@ namespace System.Runtime.Serialization.Json
                        case "object":
                                string runtimeType = reader.GetAttribute ("__type");
                                if (runtimeType != null) {
-                                       Type t = GetRuntimeType (runtimeType);
+                                       Type t = GetRuntimeType (runtimeType, null);
                                        if (t == null)
                                                throw SerializationError (String.Format ("Cannot load type '{0}'", runtimeType));
                                        return ReadObject (t);
index 68d9fb6a083ce21a6a60b36523769bf4afbd47ba..8a11d70baf12597633b386afe2b730be9546d3ed 100644 (file)
@@ -1191,6 +1191,15 @@ namespace MonoTests.System.Runtime.Serialization.Json
                        return ser.ReadObject (xr);
                }
 
+               public T Deserialize<T>(string json)
+               {
+                       var bytes = Encoding.Unicode.GetBytes (json);
+                       using (MemoryStream stream = new MemoryStream (bytes)) {
+                               var serializer = new DataContractJsonSerializer (typeof(T));
+                               return (T)serializer.ReadObject (stream);       
+                       }
+               }
+
                [Test]
                public void IsStartObject ()
                {
@@ -1819,6 +1828,50 @@ namespace MonoTests.System.Runtime.Serialization.Json
                        serializer.WriteObject (stream, o);
                }
                
+               // properly deserialize object with a polymorphic property (known derived type)
+               [Test]
+               public void Bug23058()
+               {
+                       string serializedObj = @"{""PolymorphicProperty"":{""__type"":""KnownDerivedType:#MonoTests.System.Runtime.Serialization.Json"",""BaseTypeProperty"":""Base"",""DerivedProperty"":""Derived 1""},""Name"":""Parent2""}";
+                       ParentType deserializedObj = Deserialize<ParentType> (serializedObj);
+
+                       Assert.AreEqual (deserializedObj.PolymorphicProperty.GetType ().FullName, "MonoTests.System.Runtime.Serialization.Json.KnownDerivedType");
+                       Assert.AreEqual (deserializedObj.PolymorphicProperty.BaseTypeProperty, "Base");
+                       Assert.AreEqual ((deserializedObj.PolymorphicProperty as KnownDerivedType).DerivedProperty, "Derived 1");
+                       Assert.AreEqual (deserializedObj.Name, "Parent2");
+               }
+
+               // properly deserialize object with a polymorphic property (base type with __type hint)
+               [Test]
+               public void DeserializeBaseTypePropHint()
+               {
+                       string serializedObj = @"{""PolymorphicProperty"":{""__type"":""BaseType:#MonoTests.System.Runtime.Serialization.Json"",""BaseTypeProperty"":""Base""},""Name"":""Parent2""}";
+                       ParentType deserializedObj = Deserialize<ParentType> (serializedObj);
+
+                       Assert.AreEqual (deserializedObj.PolymorphicProperty.GetType ().FullName, "MonoTests.System.Runtime.Serialization.Json.BaseType");
+                       Assert.AreEqual (deserializedObj.PolymorphicProperty.BaseTypeProperty, "Base");
+               }
+
+               // properly deserialize object with a polymorphic property (base type with __type hint)
+               [Test]
+               public void DeserializeBaseTypePropNoHint()
+               {
+                       string serializedObj = @"{""PolymorphicProperty"":{""BaseTypeProperty"":""Base""},""Name"":""Parent2""}";
+                       ParentType deserializedObj = Deserialize<ParentType> (serializedObj);
+
+                       Assert.AreEqual (deserializedObj.PolymorphicProperty.GetType ().FullName, "MonoTests.System.Runtime.Serialization.Json.BaseType");
+                       Assert.AreEqual (deserializedObj.PolymorphicProperty.BaseTypeProperty, "Base");
+               }
+
+               // properly fail deserializing object with a polymorphic property (unknown derived type)
+               [ExpectedException (typeof (SerializationException))]
+               [Test]
+               public void FailDeserializingUnknownTypeProp()
+               {
+                       string serializedObj = @"{""PolymorphicProperty"":{""__type"":""UnknownDerivedType:#MonoTests.System.Runtime.Serialization.Json"",""BaseTypeProperty"":""Base"",""DerivedProperty"":""Derived 1""},""Name"":""Parent2""}";
+                       ParentType deserializedObj = Deserialize<ParentType> (serializedObj);
+               }
+                       
                #endregion
        }
        
@@ -2037,6 +2090,42 @@ namespace MonoTests.System.Runtime.Serialization.Json
                public long CodedServerTimeUTC { get; set; }
                public DateTime ServerTimeUTC { get; set; }
        }
+
+       #region polymorphism test helper classes
+
+       [DataContract]
+       [KnownType (typeof (KnownDerivedType))]
+       public class ParentType
+       {
+               [DataMember]
+               public string Name { get; set; }
+
+               [DataMember]
+               public BaseType PolymorphicProperty { get; set; }
+       }
+
+       [DataContract]
+       public class BaseType
+       {
+               [DataMember]
+               public string BaseTypeProperty { get; set; }
+       }
+
+       [DataContract]
+       public class KnownDerivedType : BaseType
+       {
+               [DataMemberAttribute]
+               public string DerivedProperty { get; set; }
+       }
+
+       [DataContract]
+       public class UnknownDerivedType : BaseType
+       {
+               [DataMember]
+               public string DerivedProperty { get; set; }
+       }
+
+       #endregion
 }
 
 [DataContract]
index 3a4c58e9513cd810b029b3cdb0cffb714a8d38c4..3a31754b9499cd72e224c49210e2c2bba832b5ee 100644 (file)
@@ -136,6 +136,9 @@ namespace System.Web
 
                public virtual int TotalBytes { get { NotImplemented (); return 0; } }
 
+#if NET_4_5
+               public virtual ReadEntityBodyMode ReadEntityBodyMode { get { NotImplemented(); return ReadEntityBodyMode.Classic; } }
+#endif
                public virtual Uri Url { get { NotImplemented (); return null; } }
 
                public virtual Uri UrlReferrer { get { NotImplemented (); return null; } }
@@ -148,6 +151,12 @@ namespace System.Web
 
                public virtual string [] UserLanguages { get { NotImplemented (); return null; } }
 
+#if NET_4_5
+               public virtual void Abort ()
+               {
+                       NotImplemented();
+               }
+#endif
 
                public virtual byte [] BinaryRead (int count)
                {
index 41969c6468b2be117672101f1737746bfe64fabb..dc5098a3becfa0c727fd9633984a414b75b5fef0 100644 (file)
@@ -232,6 +232,13 @@ namespace System.Web
                        get { return w.UserLanguages; }
                }
 
+#if NET_4_5
+               public void Abort ()
+               {
+                       w.WorkerRequest.CloseConnection();
+               }
+#endif
+
                public override byte [] BinaryRead (int count)
                {
                        return w.BinaryRead (count);
index 0a3aa6694dd392a73ce18b7fa3b90133822cc49b..921ace9ea843e78321ab1d21c19f8bb476188dec 100644 (file)
@@ -105,6 +105,10 @@ namespace System.Web
 
                public virtual bool SuppressContent { get { NotImplemented (); return false; } set { NotImplemented (); } }
 
+#if NET_4_5
+               public virtual bool SuppressFormsAuthenticationRedirect { get { NotImplemented (); return false; } set { NotImplemented (); } }
+#endif
+
                public virtual bool TrySkipIisCustomErrors { get { NotImplemented (); return false; } set { NotImplemented (); } }
 
 
index eed3415cd1c1319b711c9a4e8bdadc7e5d7a09c4..1d9c20781719eca5fafb0470f0ca2a40e50bb5e8 100644 (file)
@@ -169,6 +169,13 @@ namespace System.Web
                        set { w.SuppressContent = value; }
                }
 
+#if NET_4_5
+               public override bool SuppressFormsAuthenticationRedirect {
+                       get { return w.SuppressFormsAuthenticationRedirect; }
+                       set { w.SuppressFormsAuthenticationRedirect = value; }
+               }
+#endif
+
                public override bool TrySkipIisCustomErrors {
                        get { return w.TrySkipIisCustomErrors; }
                        set { w.TrySkipIisCustomErrors = value; }
index 787662b4184549c387b62070dcba435b725de71f..186581616b89908966da650eaaad8ec7960c37d1 100644 (file)
     <Compile Include="System.Web\ProcessShutdownReason.cs" />\r
     <Compile Include="System.Web\ProcessStatus.cs" />\r
     <Compile Include="System.Web\QueueManager.cs" />\r
+    <Compile Include="System.Web\ReadEntityBodyMode.cs" />\r
     <Compile Include="System.Web\RequestNotification.cs" />\r
     <Compile Include="System.Web\RequestNotificationStatus.cs" />\r
     <Compile Include="System.Web\ServerVariablesCollection.cs" />\r
index 14bcf13a6e0c6720fbfd4e92d8709920b38e8a54..75fd8723e7051febd4288c1b04de8b472f9a8c7b 100644 (file)
@@ -67,6 +67,7 @@ namespace System.Web.Configuration {
                static readonly char[] pathTrimChars = { '/' };
                static readonly object suppressAppReloadLock = new object ();
                static readonly object saveLocationsCacheLock = new object ();
+               static readonly object getSectionLock = new object ();
                
                // See comment for the cacheLock field at top of System.Web.Caching/Cache.cs
                static readonly ReaderWriterLockSlim sectionCacheLock;
@@ -517,7 +518,10 @@ namespace System.Web.Configuration {
                                        cachePath = path;
                        }
 
-                       ConfigurationSection section = c.GetSection (sectionName);
+                       ConfigurationSection section;
+                       lock (getSectionLock) {
+                               section = c.GetSection (sectionName);
+                       }
                        if (section == null)
                                return null;
 
@@ -529,7 +533,7 @@ namespace System.Web.Configuration {
                                value = collection;
                        }
 #else
-                       object value = SettingsMappingManager.MapSection (get_runtime_object.Invoke (section, new object [0]));
+                       object value = SettingsMappingManager.MapSection (section.GetRuntimeObject ());
 #endif
                        if (cachePath != null)
                                cacheKey = baseCacheKey ^ cachePath.GetHashCode ();
@@ -677,7 +681,9 @@ namespace System.Web.Configuration {
                        configurations.Remove (GetCurrentPath (ctx));
                }
 
+#if TARGET_J2EE
                readonly static MethodInfo get_runtime_object = typeof (ConfigurationSection).GetMethod ("GetRuntimeObject", BindingFlags.NonPublic | BindingFlags.Instance);
+#endif
 
                public static object GetWebApplicationSection (string sectionName)
                {
index f5855311943f6ebd1be4c4157032aa5554d6a9f9..a2b87e029ce7335e0c190dc08f1959561b58b1bd 100644 (file)
@@ -160,7 +160,9 @@ namespace System.Web.Hosting {
                {
                        if (obj == null)
                                throw new ArgumentNullException ("obj");
-                       Host.RegisterObject (obj, false);
+
+                       if (Host != null)
+                               Host.RegisterObject (obj, false);
                }
 
                public static void RegisterVirtualPathProvider (VirtualPathProvider virtualPathProvider)
@@ -200,7 +202,9 @@ namespace System.Web.Hosting {
                {
                        if (obj == null)
                                throw new ArgumentNullException ("obj");
-                       Host.UnregisterObject (obj);
+
+                       if (Host != null)
+                               Host.UnregisterObject (obj);
                }
        }
 }
index cab57fea2f2ff83ab4b858d4e5947ac9b7c4d058..54f07294e288065497427146caf1e1577fbbee1b 100644 (file)
@@ -180,6 +180,11 @@ namespace System.Web.Security
                        if (context.Response.StatusCode != 401 || context.Request.QueryString ["ReturnUrl"] != null)
                                return;
 
+#if NET_4_5
+                       if (context.Response.StatusCode == 401 && context.Response.SuppressFormsAuthenticationRedirect)
+                               return;
+#endif
+
                        string loginPage;
                        InitConfig (context);
 #if NET_2_0
index efa4432011abe6d4b43e9702e5ac531b10d944b3..da393081d5e413dd62592439618c3348c5de7b0f 100644 (file)
@@ -230,6 +230,10 @@ namespace System.Web
                                        }
                                } catch (Exception e) {
                                        initialization_exception = e;
+                                       Console.Error.WriteLine("Exception while initOnce: "+e.ToString());
+                                       // Once initialization_exception != null, we always respond with this exception
+                                       // You have to restart the HttpApplication to "unlock" it
+                                       Console.Error.WriteLine("Please restart your app to unlock it");
                                } finally {
                                        if (mustNullContext)
                                                context = null;
@@ -1549,6 +1553,7 @@ namespace System.Web
                        if (initialization_exception != null) {
                                Exception e = initialization_exception;
                                HttpException exc = HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort);
+                               context.Response.StatusCode = 500;
                                FinalErrorWrite (context.Response, exc.GetHtmlErrorMessage ());
                                PipelineDone ();
                                return;
index 65718e5cd9bc41494cc3ec01bc9f2e62c8d39309..4bd3380a8f856e32a4cf7fea7fc13886ce43bea7 100644 (file)
@@ -400,6 +400,13 @@ namespace System.Web
                        set;
                }
 
+#if NET_4_5
+               public bool SuppressFormsAuthenticationRedirect {
+                       get;
+                       set;
+               }
+#endif
+
                public bool TrySkipIisCustomErrors {
                        get;
                        set;
index bb821a573cfc29f7bc7d0ba0ec1e224ceb956df2..7189276746944a768c178305d2d45f42ca2400da 100644 (file)
@@ -56,7 +56,7 @@ namespace System.Web {
                                StringBuilder sb = new StringBuilder ();
                                string [] keys = AllKeys;
                                for (int i = 0; i < count; i++) {
-                                       sb.AppendFormat ("{0}={1}&", keys [i], this [keys [i]]);
+                                       sb.AppendFormat ("{0}={1}&", keys [i], UrlEncode (this [keys [i]]));
                                }
                                if (sb.Length > 0)
                                        sb.Length--;
diff --git a/mcs/class/System.Web/System.Web/ReadEntityBodyMode.cs b/mcs/class/System.Web/System.Web/ReadEntityBodyMode.cs
new file mode 100644 (file)
index 0000000..a97c3cf
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// ReadEntityBodyMode.cs
+//
+// Author: Martin Thwaites (github@my2cents.co.uk)
+//
+// Copyright (C) 2014 Martin Thwaites
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+namespace System.Web {
+       public enum ReadEntityBodyMode {
+               None,
+               Classic,
+               Bufferless,
+               Buffered,
+       }
+}
index eb3aa2a3e00a47fea106abd5e4626a9ccaadce65..2f039d028944852f305c9237c724d26dc550932b 100644 (file)
@@ -35,6 +35,10 @@ using System.Web.UI;
 using MonoTests.SystemWeb.Framework;
 
 namespace MonoTests.System.Web.Hosting {
+       public class MyRegisteredObject : IRegisteredObject {
+               public void Stop(bool immediate) {}
+       }
+
        [TestFixture]
        public class HostingEnvironmentTest {
                [Test]
@@ -105,6 +109,15 @@ namespace MonoTests.System.Web.Hosting {
                {
                        Assert.IsNull (HostingEnvironment.MapPath ("hola"));
                }
+
+               [Test]
+               public void RegisterAndUnregisterObject ()
+               {
+                       var registered = new MyRegisteredObject ();
+
+                       HostingEnvironment.RegisterObject (registered);
+                       HostingEnvironment.UnregisterObject (registered);
+               }
        }
 }
 #endif
index 4c7228dd6a2b17e05f75e64870770f6663546150..5ead2173893c8bc8607417922b5e856ed40e0dbf 100644 (file)
@@ -861,6 +861,15 @@ namespace MonoTests.System.Web {
        @"&#160;&#161;&#162;&#163;&#164;&#165;&#166;&#167;&#168;&#169;&#170;&#171;&#172;&#173;&#174;&#175;&#176;&#177;&#178;&#179;&#180;&#181;&#182;&#183;&#184;&#185;&#186;&#187;&#188;&#189;&#190;&#191;&#192;&#193;&#194;&#195;&#196;&#197;&#198;&#199;&#200;&#201;&#202;&#203;&#204;&#205;&#206;&#207;&#208;&#209;&#210;&#211;&#212;&#213;&#214;&#215;&#216;&#217;&#218;&#219;&#220;&#221;&#222;&#223;&#224;&#225;&#226;&#227;&#228;&#229;&#230;&#231;&#232;&#233;&#234;&#235;&#236;&#237;&#238;&#239;&#240;&#241;&#242;&#243;&#244;&#245;&#246;&#247;&#248;&#249;&#250;&#251;&#252;&#253;&#254;&#255;",
 };
 
+               [Test]
+               public void ToStringEncoding ()
+               {
+                       var queryStringNameValues = HttpUtility.ParseQueryString(string.Empty);
+                       queryStringNameValues.Add("ReturnUrl", @"http://localhost/login/authenticate?ReturnUrl=http://localhost/secured_area&__provider__=google");
+
+                       var expected = "ReturnUrl=http%3a%2f%2flocalhost%2flogin%2fauthenticate%3fReturnUrl%3dhttp%3a%2f%2flocalhost%2fsecured_area%26__provider__%3dgoogle";
+                       Assert.AreEqual (expected, queryStringNameValues.ToString());
+               }
        }
 }
 
index a7957a0019c0d67cd94082b0149f9e5e0c9ee4d7..04c7cacd659e57694c2e908224d5291356a80a2e 100644 (file)
@@ -1,3 +1,5 @@
 #include net_4_0_System.Web.dll.sources
 
 System.Web/MimeMapping.cs
+System.Web/ReadEntityBodyMode.cs
+
index 63745fe3039117b51b56597d695550427ad8fa24..eee0580d44d22cef8487e6cbbcdd08f27ebb081b 100644 (file)
@@ -164,11 +164,6 @@ namespace Mono.Xml2
                        InitializeContext (url, context, fragment, fragType);
                }
 
-               Uri ResolveUri (string url)
-               {
-                       return resolver == null ? null : resolver.ResolveUri (null, url);
-               }
-
                Stream GetStreamFromUrl (string url, out string absoluteUriString)
                {
 #if NET_2_1
@@ -177,9 +172,13 @@ namespace Mono.Xml2
                        if (url.Length == 0)
                                throw new ArgumentException ("url");
 #endif
-                       Uri uri = ResolveUri (url);
+                       //
+                       // This needs to work even if resolver is explicitly set to null
+                       //
+                       var res = resolver ?? new XmlUrlResolver ();
+                       var uri = res.ResolveUri (null, url);
                        absoluteUriString = uri != null ? uri.ToString () : String.Empty;
-                       return resolver == null ? null : resolver.GetEntity (uri, null, typeof (Stream)) as Stream;
+                       return res.GetEntity (uri, null, typeof (Stream)) as Stream;
                }
 
                #endregion
@@ -717,7 +716,6 @@ namespace Mono.Xml2
                                        if (valueCache != null)
                                                return valueCache;
                                        if (ValueBufferStart >= 0) {
-//Console.WriteLine (NodeType + " / " + ValueBuffer.Length + " / " + ValueBufferStart + " / " + ValueBufferEnd);
                                                valueCache = Reader.valueBuffer.ToString (ValueBufferStart, ValueBufferEnd - ValueBufferStart);
                                                return valueCache;
                                        }
@@ -1801,6 +1799,7 @@ namespace Mono.Xml2
                                value,
                                false);
                        ati.Value = value;
+                       ati.ValueTokenStartIndex = ati.ValueTokenEndIndex = currentAttributeValue;
                        attributeCount++;
                }
 
index 2110bb62f17e0fbc51b3323dcef33b96073de5ba..52a7a9e687891f6a624ed2f77cc38787f7963e58 100644 (file)
@@ -254,6 +254,11 @@ namespace System.Xml
                        get { return entity != null ? ReadState.Interactive : source.ReadState; }
                }
 
+#if NET_4_0
+               [MonoTODO]
+               public DtdProcessing DtdProcessing { get; set; }
+#endif
+
 #if !NET_4_5
                public override XmlReaderSettings Settings {
                        get { return base.Settings; }
index 7ecd83780aec5a8121073bdaeeec49166d670a8a..d0898923255140ab6beee3ce26027b81790a5692 100644 (file)
@@ -1382,5 +1382,56 @@ namespace MonoTests.System.Xml
                        var xtr = new XmlTextReader (ms);
                        xtr.Read ();
                }
+               
+               [Test]
+               public void XmlDeclarationReadAttributeValue ()
+               {
+                       const string input = "<?xml version=\"1.0\" encoding=\"utf-8\"?><hello />";
+                       var reader = new XmlTextReader (new StringReader (input));
+                       reader.WhitespaceHandling = WhitespaceHandling.All;
+                       reader.Read ();
+                       
+                       Assert.AreEqual ("1.0", reader.GetAttribute ("version"), "#0");
+                       Assert.AreEqual ("utf-8", reader.GetAttribute ("encoding"), "#0-2");
+
+                       Assert.IsTrue (reader.MoveToNextAttribute (), "#1");
+                       Assert.AreEqual ("1.0", reader.Value, "#1-1");
+                       Assert.IsTrue (reader.ReadAttributeValue (), "#2");
+                       Assert.AreEqual ("1.0", reader.Value, "#3");
+                       Assert.IsFalse (reader.ReadAttributeValue (), "#4");
+
+                       Assert.IsTrue (reader.MoveToNextAttribute (), "#5");
+                       Assert.AreEqual ("utf-8", reader.Value, "#5-1");
+                       Assert.IsTrue (reader.ReadAttributeValue (), "#6");
+                       Assert.AreEqual ("utf-8", reader.Value, "#7");
+                       Assert.IsFalse (reader.ReadAttributeValue (), "#8");
+
+                       Assert.IsFalse (reader.MoveToNextAttribute (), "#9");
+                       Assert.IsFalse (reader.ReadAttributeValue (), "#10");
+               }
+               
+               [Test]
+               public void XmlDeclarationReadAttributeValue2 ()
+               {
+                       const string input = "<?xml version=\"1.0\" encoding=\"utf-8\"?><hello />";
+                       var reader = new XmlTextReader (new StringReader (input));
+                       reader.WhitespaceHandling = WhitespaceHandling.All;
+                       reader.Read ();
+                       Assert.IsTrue (reader.MoveToNextAttribute (), "#1a");
+                       Assert.IsTrue (reader.ReadAttributeValue (), "#1b");
+                       Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#1c");
+                       Assert.AreEqual ("1.0", reader.Value, "#1d");
+                       Assert.IsFalse (reader.ReadAttributeValue(), "#1e");
+
+                       Assert.IsTrue (reader.MoveToNextAttribute(), "#2a");
+                       Assert.IsTrue (reader.ReadAttributeValue(), "#2b");
+                       Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#2c");
+                       Assert.AreEqual ("utf-8", reader.Value, "#2d");
+                       Assert.IsFalse (reader.ReadAttributeValue(), "#2e");
+
+                       Assert.IsFalse (reader.MoveToNextAttribute(), "#3");
+                       Assert.IsFalse (reader.ReadAttributeValue(), "#4");
+                       Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#5");
+               }
        }
 }
index 893cd8e3a46fff54dab7039200b2ddefd09c82a3..395bc68e96d3f42fc93db9b82d25a64b2f204b75 100644 (file)
@@ -124,8 +124,12 @@ namespace System.Collections.Concurrent
                                int cachedRemoveId = removeId;
                                int itemsIn = cachedAddId - cachedRemoveId;
 
+                               // Check our transaction id against completed stored one
+                               if (isComplete.Value && cachedAddId >= completeId)
+                                       ThrowCompleteException ();
+
                                // If needed, we check and wait that the collection isn't full
-                               if (upperBound != -1 && itemsIn > upperBound) {
+                               if (upperBound != -1 && itemsIn >= upperBound) {
                                        if (millisecondsTimeout == 0)
                                                return false;
 
@@ -144,10 +148,6 @@ namespace System.Collections.Concurrent
                                        continue;
                                }
 
-                               // Check our transaction id against completed stored one
-                               if (isComplete.Value && cachedAddId >= completeId)
-                                       ThrowCompleteException ();
-
                                // Validate the steps we have been doing until now
                                if (Interlocked.CompareExchange (ref addId, cachedAddId + 1, cachedAddId) != cachedAddId)
                                        continue;
@@ -291,30 +291,28 @@ namespace System.Collections.Concurrent
 
                public static int AddToAny (BlockingCollection<T>[] collections, T item)
                {
-                       CheckArray (collections);
-                       int index = 0;
-                       foreach (var coll in collections) {
-                               try {
-                                       coll.Add (item);
-                                       return index;
-                               } catch {}
-                               index++;
-                       }
-                       return -1;
+                       return AddToAny (collections, item, CancellationToken.None);
                }
 
                public static int AddToAny (BlockingCollection<T>[] collections, T item, CancellationToken cancellationToken)
                {
                        CheckArray (collections);
-                       int index = 0;
-                       foreach (var coll in collections) {
-                               try {
-                                       coll.Add (item, cancellationToken);
-                                       return index;
-                               } catch {}
-                               index++;
+                       WaitHandle[] wait_table = null;
+                       while (true) {
+                               for (int i = 0; i < collections.Length; ++i) {
+                                       if (collections [i].TryAdd (item))
+                                               return i;
+                               }
+                               cancellationToken.ThrowIfCancellationRequested ();
+                               if (wait_table == null) {
+                                       wait_table = new WaitHandle [collections.Length + 1];
+                                       for (int i = 0; i < collections.Length; ++i)
+                                               wait_table [i] = collections [i].mreAdd.WaitHandle;
+                                       wait_table [collections.Length] = cancellationToken.WaitHandle;
+                               }
+                               WaitHandle.WaitAny (wait_table);
+                               cancellationToken.ThrowIfCancellationRequested ();
                        }
-                       return -1;
                }
 
                public static int TryAddToAny (BlockingCollection<T>[] collections, T item)
@@ -368,21 +366,7 @@ namespace System.Collections.Concurrent
 
                public static int TakeFromAny (BlockingCollection<T>[] collections, out T item)
                {
-                       item = default (T);
-                       CheckArray (collections);
-                       WaitHandle[] wait_table = null;
-                       while (true) {
-                               for (int i = 0; i < collections.Length; ++i) {
-                                       if (collections [i].TryTake (out item))
-                                               return i;
-                               }
-                               if (wait_table == null) {
-                                       wait_table = new WaitHandle [collections.Length];
-                                       for (int i = 0; i < collections.Length; ++i)
-                                               wait_table [i] = collections [i].mreRemove.WaitHandle;
-                               }
-                               WaitHandle.WaitAny (wait_table);
-                       }
+                       return TakeFromAny (collections, out item, CancellationToken.None);
                }
 
                public static int TakeFromAny (BlockingCollection<T>[] collections, out T item, CancellationToken cancellationToken)
index e5a34ff1a41478735652b7c883839575fba532a6..c013223d08108d239bdc1c84481cc55c1d407358 100644 (file)
@@ -29,7 +29,7 @@
 //
 
 using System;
-using System.Collections;
+using System.Collections.Generic;
 using System.ComponentModel;
 using System.Diagnostics;
 using System.Globalization;
@@ -227,7 +227,7 @@ namespace System.Diagnostics
                                        DateFormat, CultureInfo.InvariantCulture);
                                DateTime timeWritten = File.GetLastWriteTime (file);
                                int stringNums = int.Parse (tr.ReadLine ().Substring (20));
-                               ArrayList replacementTemp = new ArrayList ();
+                               var replacementTemp = new List<string> ();
                                StringBuilder sb = new StringBuilder ();
                                while (replacementTemp.Count < stringNums) {
                                        char c = (char) tr.Read ();
@@ -238,8 +238,7 @@ namespace System.Diagnostics
                                                sb.Append (c);
                                        }
                                }
-                               string [] replacementStrings = new string [replacementTemp.Count];
-                               replacementTemp.CopyTo (replacementStrings, 0);
+                               string [] replacementStrings = replacementTemp.ToArray ();
 
                                string message = FormatMessage (source, instanceID, replacementStrings);
                                int eventID = EventLog.GetEventID (instanceID);
index 795ebaaa80ff60ae606417ac7d6cb9599363ecaa..0cf197af1dcac3be7c072c2ee3ac51b74573023f 100644 (file)
@@ -39,7 +39,7 @@ using System.ComponentModel.Design;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Security.Permissions;
-using System.Collections;
+using System.Collections.Generic;
 using System.Security;
 using System.Threading;
 
@@ -832,13 +832,13 @@ namespace System.Diagnostics {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static int[] GetProcesses_internal();
 
-               public static Process[] GetProcesses()
+               public static Process[] GetProcesses ()
                {
                        int [] pids = GetProcesses_internal ();
                        if (pids == null)
                                return new Process [0];
 
-                       ArrayList proclist = new ArrayList (pids.Length);
+                       var proclist = new List<Process> (pids.Length);
                        for (int i = 0; i < pids.Length; i++) {
                                try {
                                        proclist.Add (GetProcessById (pids [i]));
@@ -851,7 +851,7 @@ namespace System.Diagnostics {
                                }
                        }
 
-                       return ((Process []) proclist.ToArray (typeof (Process)));
+                       return proclist.ToArray ();
                }
 
                [MonoTODO ("There is no support for retrieving process information from a remote machine")]
@@ -871,7 +871,7 @@ namespace System.Diagnostics {
                        if (pids == null)
                                return new Process [0];
                        
-                       ArrayList proclist = new ArrayList (pids.Length);
+                       var proclist = new List<Process> (pids.Length);
                        for (int i = 0; i < pids.Length; i++) {
                                try {
                                        Process p = GetProcessById (pids [i]);
@@ -886,7 +886,7 @@ namespace System.Diagnostics {
                                }
                        }
 
-                       return ((Process []) proclist.ToArray (typeof (Process)));
+                       return proclist.ToArray ();
                }
 
                [MonoTODO]
@@ -940,7 +940,7 @@ namespace System.Diagnostics {
                                                               ref proc_info);
                        } finally {
                                if (proc_info.Password != IntPtr.Zero)
-                                       Marshal.FreeBSTR (proc_info.Password);
+                                       Marshal.ZeroFreeBSTR (proc_info.Password);
                                proc_info.Password = IntPtr.Zero;
                        }
                        if (!ret) {
@@ -1080,7 +1080,7 @@ namespace System.Diagnostics {
                                                              ref proc_info);
                        } finally {
                                if (proc_info.Password != IntPtr.Zero)
-                                       Marshal.FreeBSTR (proc_info.Password);
+                                       Marshal.ZeroFreeBSTR (proc_info.Password);
                                proc_info.Password = IntPtr.Zero;
                        }
                        if (!ret) {
index 40fe3a36b157ac461654e70c532d17ec06966ce7..4002c3b7cdc4850dbe9490d4831005ed7024fc27 100644 (file)
@@ -28,7 +28,7 @@
 //
 
 using System;
-using System.Collections;
+using System.Collections.Generic;
 using System.ComponentModel;
 using System.Diagnostics;
 using System.Globalization;
@@ -177,12 +177,11 @@ namespace System.Diagnostics
 
                                string [] sources = (string []) logKey.GetValue ("Sources");
                                if (sources != null) {
-                                       ArrayList temp = new ArrayList ();
+                                       var temp = new List<string> ();
                                        for (int i = 0; i < sources.Length; i++)
                                                if (sources [i] != source)
                                                        temp.Add (sources [i]);
-                                       string [] newSources = new string [temp.Count];
-                                       temp.CopyTo (newSources, 0);
+                                       string [] newSources = temp.ToArray ();
                                        logKey.SetValue ("Sources", newSources);
                                }
                        }
index 08a9a655b2ecd2bff713cadf85c1a8cf2f454250..65189c5813f986b05aeac8d71d7bdbd7ed6f5c8a 100644 (file)
@@ -529,7 +529,7 @@ namespace System.IO.Ports
                                // Probe for Linux-styled devices: /dev/ttyS* or /dev/ttyUSB*
                                // 
                                foreach (string dev in ttys) {
-                                       if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB")){
+                                       if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM")) {
                                                linux_style = true;
                                                break;
                                        }
@@ -537,7 +537,7 @@ namespace System.IO.Ports
 
                                foreach (string dev in ttys) {
                                        if (linux_style){
-                                               if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB"))
+                                               if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM"))
                                                        serial_ports.Add (dev);
                                        } else {
                                                if (dev != "/dev/tty" && dev.StartsWith ("/dev/tty") && !dev.StartsWith ("/dev/ttyC"))
index 8988a6b97030e2180008f7c7551ac043e366a0a3..d2d8b28d86cef4ebbeeff516308503d14cf10fe2 100644 (file)
@@ -30,6 +30,7 @@
 
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.IO;
 using System.Threading;
 
@@ -240,12 +241,12 @@ namespace System.IO {
                                return;
 
                        /* Removed files */
-                       ArrayList removed = null;
+                       List<string> removed = null;
                        foreach (string filename in data.Files.Keys) {
                                FileData fd = (FileData) data.Files [filename];
                                if (fd.NotExists) {
                                        if (removed == null)
-                                               removed = new ArrayList ();
+                                               removed = new List<string> ();
 
                                        removed.Add (filename);
                                        DispatchEvents (data.FSW, FileAction.Removed, filename);
@@ -269,7 +270,7 @@ namespace System.IO {
                                } catch {
                                        /* Deleted */
                                        if (removed == null)
-                                               removed = new ArrayList ();
+                                               removed = new List<string> ();
 
                                        removed.Add (filename);
                                        DispatchEvents (data.FSW, FileAction.Removed, filename);
index 125f07805f9403f212fe5789357ff92bd0d02f33..0d293e53188b4f6155380ba838edf3443f1f7117 100644 (file)
@@ -183,7 +183,10 @@ namespace System.IO {
                internal SearchPattern2 Pattern {
                        get {
                                if (pattern == null) {
-                                       pattern = new SearchPattern2 (MangledFilter);
+                                       if (watcher.GetType () == typeof (KeventWatcher))
+                                               pattern = new SearchPattern2 (MangledFilter, true); //assume we want to ignore case (OS X)
+                                       else
+                                               pattern = new SearchPattern2 (MangledFilter);
                                }
                                return pattern;
                        }
@@ -372,52 +375,60 @@ namespace System.IO {
                        ErrorEvent,
                        RenameEvent
                }
-               private void RaiseEvent (Delegate ev, EventArgs arg, EventType evtype)
-               {
-                       if (ev == null)
-                               return;
-
-                       if (synchronizingObject == null) {
-                               switch (evtype) {
-                               case EventType.RenameEvent:
-                                       ((RenamedEventHandler)ev).BeginInvoke (this, (RenamedEventArgs) arg, null, null);
-                                       break;
-                               case EventType.ErrorEvent:
-                                       ((ErrorEventHandler)ev).BeginInvoke (this, (ErrorEventArgs) arg, null, null);
-                                       break;
-                               case EventType.FileSystemEvent:
-                                       ((FileSystemEventHandler)ev).BeginInvoke (this, (FileSystemEventArgs) arg, null, null);
-                                       break;
-                               }
-                               return;
-                       }
                        
-                       synchronizingObject.BeginInvoke (ev, new object [] {this, arg});
-               }
-
                protected void OnChanged (FileSystemEventArgs e)
                {
-                       RaiseEvent (Changed, e, EventType.FileSystemEvent);
+                       if (Changed == null)
+                               return;
+
+                       if (synchronizingObject == null)
+                               Changed (this, e);
+                       else
+                               synchronizingObject.BeginInvoke (Changed, new object[] { this, e });
                }
 
                protected void OnCreated (FileSystemEventArgs e)
                {
-                       RaiseEvent (Created, e, EventType.FileSystemEvent);
+                       if (Created == null)
+                               return;
+
+                       if (synchronizingObject == null)
+                               Created (this, e);
+                       else
+                               synchronizingObject.BeginInvoke (Created, new object[] { this, e });
                }
 
                protected void OnDeleted (FileSystemEventArgs e)
                {
-                       RaiseEvent (Deleted, e, EventType.FileSystemEvent);
+                       if (Deleted == null)
+                               return;
+
+                       if (synchronizingObject == null)
+                               Deleted (this, e);
+                       else
+                               synchronizingObject.BeginInvoke (Deleted, new object[] { this, e });
                }
 
-               protected void OnError (ErrorEventArgs e)
+               internal void OnError (ErrorEventArgs e)
                {
-                       RaiseEvent (Error, e, EventType.ErrorEvent);
+                       if (Error == null)
+                               return;
+
+                       if (synchronizingObject == null)
+                               Error (this, e);
+                       else
+                               synchronizingObject.BeginInvoke (Error, new object[] { this, e });
                }
 
                protected void OnRenamed (RenamedEventArgs e)
                {
-                       RaiseEvent (Renamed, e, EventType.RenameEvent);
+                       if (Renamed == null)
+                               return;
+
+                       if (synchronizingObject == null)
+                               Renamed (this, e);
+                       else
+                               synchronizingObject.BeginInvoke (Renamed, new object[] { this, e });
                }
 
                public WaitForChangedResult WaitForChanged (WatcherChangeTypes changeType)
index e673f99739bcaecc9623faa6a277b7c5ca60ef44..f3cc7dcc183200a81a8ca409b3ab9e49f936f7ec 100644 (file)
@@ -3,6 +3,8 @@
 //
 // Authors:
 //     Geoff Norton (gnorton@customerdna.com)
+//     Cody Russell (cody@xamarin.com)
+//     Alexis Christoforides (lexas@xamarin.com)
 //
 // (c) 2004 Geoff Norton
 // Copyright 2014 Xamarin Inc
 
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.ComponentModel;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Text;
 using System.Threading;
+using System.Reflection;
 
 namespace System.IO {
 
@@ -71,6 +75,7 @@ namespace System.IO {
                 VM = -11
         }
 
+       [Flags]
        enum FilterFlags : uint {
                 ReadPoll          = EventFlags.Flag0,
                 ReadOutOfBand     = EventFlags.Flag1,
@@ -123,13 +128,14 @@ namespace System.IO {
                 TimerNanoSeconds  =   0x00000004,
                 TimerAbsolute     =   0x00000008,
         }
-                       
+
+       [StructLayout(LayoutKind.Sequential)]
        struct kevent : IDisposable {
-               public int ident;
+               public UIntPtr ident;
                public EventFilter filter;
                public EventFlags flags;
                public FilterFlags fflags;
-               public int data;
+               public IntPtr data;
                public IntPtr udata;
 
                public void Dispose ()
@@ -137,307 +143,405 @@ namespace System.IO {
                        if (udata != IntPtr.Zero)
                                Marshal.FreeHGlobal (udata);
                }
+
+
        }
 
+       [StructLayout(LayoutKind.Sequential)]
        struct timespec {
-               public int tv_sec;
-               public int tv_usec;
+               public IntPtr tv_sec;
+               public IntPtr tv_usec;
        }
 
-       class KeventFileData {
-               public FileSystemInfo fsi;
-               public DateTime LastAccessTime;
-               public DateTime LastWriteTime;
+       class PathData
+       {
+               public string Path;
+               public bool IsDirectory;
+               public int Fd;
+       }
 
-               public KeventFileData(FileSystemInfo fsi, DateTime LastAccessTime, DateTime LastWriteTime) {
-                       this.fsi = fsi;
-                       this.LastAccessTime = LastAccessTime;
-                       this.LastWriteTime = LastWriteTime;
+       class KqueueMonitor : IDisposable
+       {
+               public int Connection
+               {
+                       get { return conn; }
                }
-       }
 
-       class KeventData {
-                public FileSystemWatcher FSW;
-                public string Directory;
-                public string FileMask;
-                public bool IncludeSubdirs;
-                public bool Enabled;
-               public Hashtable DirEntries;
-               public kevent ev;
-        }
+               public KqueueMonitor (FileSystemWatcher fsw)
+               {
+                       this.fsw = fsw;
+                       this.conn = -1;
+               }
 
-       class KeventWatcher : IFileWatcher
-       {
-               static bool failed;
-               static KeventWatcher instance;
-               static Hashtable watches;
-               static Hashtable requests;
-               static Thread thread;
-               static int conn;
-               static bool stop;
-               
-               private KeventWatcher ()
+               public void Dispose ()
                {
+                       CleanUp ();
                }
-               
-               // Locked by caller
-               public static bool GetInstance (out IFileWatcher watcher)
+
+               public void Start ()
                {
-                       if (failed == true) {
-                               watcher = null;
-                               return false;
-                       }
+                       lock (stateLock) {
+                               if (started)
+                                       return;
 
-                       if (instance != null) {
-                               watcher = instance;
-                               return true;
-                       }
+                               conn = kqueue ();
 
-                       watches = Hashtable.Synchronized (new Hashtable ());
-                       requests = Hashtable.Synchronized (new Hashtable ());
-                       conn = kqueue();
-                       if (conn == -1) {
-                               failed = true;
-                               watcher = null;
-                               return false;
-                       }
+                               if (conn == -1)
+                                       throw new IOException (String.Format (
+                                               "kqueue() error at init, error code = '{0}'", Marshal.GetLastWin32Error ()));
+                                       
+                               thread = new Thread (() => DoMonitor ());
+                               thread.IsBackground = true;
+                               thread.Start ();
 
-                       instance = new KeventWatcher ();
-                       watcher = instance;
-                       return true;
+                               startedEvent.WaitOne ();
+
+                               if (failedInit) {
+                                       thread.Join ();
+                                       CleanUp ();
+                                       throw new IOException ("Monitor thread failed while initializing.");
+                               }
+                               else 
+                                       started = true;
+                       }
                }
-               
-               public void StartDispatching (FileSystemWatcher fsw)
+
+               public void Stop ()
                {
-                       KeventData data;
-                       lock (this) {
-                               if (thread == null) {
-                                       thread = new Thread (new ThreadStart (Monitor));
-                                       thread.IsBackground = true;
-                                       thread.Start ();
-                               }
+                       lock (stateLock) {
+                               if (!started)
+                                       return;
+                                       
+                               requestStop = true;
+                               thread.Join ();
+                               requestStop = false;
 
-                               data = (KeventData) watches [fsw];
+                               CleanUp ();
+                               started = false;
                        }
+               }
 
-                       if (data == null) {
-                               data = new KeventData ();
-                               data.FSW = fsw;
-                               data.Directory = fsw.FullPath;
-                               data.FileMask = fsw.MangledFilter;
-                               data.IncludeSubdirs = fsw.IncludeSubdirectories;
-
-                               data.Enabled = true;
-                               lock (this) {
-                                       StartMonitoringDirectory (data);
-                                       watches [fsw] = data;
-                                       stop = false;
-                               }
-                       }
+               void CleanUp ()
+               {
+                       if (conn != -1)
+                               close (conn);
+
+                       conn = -1;
+
+                       foreach (int fd in fdsDict.Keys)
+                               close (fd); 
+
+                       fdsDict.Clear ();
+                       pathsDict.Clear ();
                }
 
-               static void StartMonitoringDirectory (KeventData data)
+               void DoMonitor ()
                {
-                       DirectoryInfo dir = new DirectoryInfo (data.Directory);
-                       if(data.DirEntries == null) {
-                               data.DirEntries = new Hashtable();
-                               foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() ) 
-                                       data.DirEntries.Add(fsi.FullName, new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime));
+                       Exception exc = null;
+                       failedInit = false;
+
+                       try {
+                               Setup ();
+                       } catch (Exception e) {
+                               failedInit = true;
+                               exc = e;
+                       } finally {
+                               startedEvent.Set ();
                        }
 
-                       int fd = open(data.Directory, 0, 0);
-                       kevent ev = new kevent();
-                       ev.udata = IntPtr.Zero;
-                       timespec nullts = new timespec();
-                       nullts.tv_sec = 0;
-                       nullts.tv_usec = 0;
-                       if (fd > 0) {
-                               ev.ident = fd;
-                               ev.filter = EventFilter.Vnode;
-                               ev.flags = EventFlags.Add | EventFlags.Enable | EventFlags.OneShot;
-                               ev.fflags = // 20 | 2 | 1 | 8;
-                                       FilterFlags.VNodeDelete |
-                                       FilterFlags.VNodeWrite |
-                                       FilterFlags.VNodeAttrib |
-                                       // The following two values are the equivalent of the original value "20", but we suspect the original author meant
-                                       // 0x20, we will review later with some test cases
-                                       FilterFlags.VNodeLink |
-                                       FilterFlags.VNodeExtend;
-                               ev.data = 0;
-                               ev.udata = Marshal.StringToHGlobalAuto (data.Directory);
-                               kevent outev = new kevent();
-                               outev.udata = IntPtr.Zero;
-                               kevent (conn, ref ev, 1, ref outev, 0, ref nullts);
-                               data.ev = ev;
-                               requests [fd] = data;
-                       }
-                       
-                       if (!data.IncludeSubdirs)
+                       if (failedInit) {
+                               fsw.OnError (new ErrorEventArgs (exc));
                                return;
+                       }
 
+                       try {
+                               Monitor ();
+                       } catch (Exception e) {
+                               exc = e;
+                       } finally {
+                               if (!requestStop) { // failure
+                                       CleanUp ();
+                                       started = false;
+                               }
+                               if (exc != null)
+                                       fsw.OnError (new ErrorEventArgs (exc));
+                       }
                }
 
-               public void StopDispatching (FileSystemWatcher fsw)
-               {
-                       KeventData data;
-                       lock (this) {
-                               data = (KeventData) watches [fsw];
-                               if (data == null)
-                                       return;
+               void Setup ()
+               {       
+                       var initialFds = new List<int> ();
 
-                               StopMonitoringDirectory (data);
-                               watches.Remove (fsw);
-                               if (watches.Count == 0)
-                                       stop = true;
+                       // GetFilenameFromFd() returns the *realpath* which can be different than fsw.FullPath because symlinks.
+                       // If so, introduce a fixup step.
+                       int fd = open (fsw.FullPath, O_EVTONLY, 0);
+                       var resolvedFullPath = GetFilenameFromFd (fd);
+                       close (fd);
 
-                               if (!data.IncludeSubdirs)
-                                       return;
+                       if (resolvedFullPath != fsw.FullPath)
+                               fixupPath = resolvedFullPath;
+                       else
+                               fixupPath = null;
+
+                       Scan (fsw.FullPath, false, ref initialFds);
 
+                       var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)0 };
+                       var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point
+                       var changes = CreateChangeList (ref initialFds);
+
+                       int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout);
+
+                       if (numEvents == -1) {
+                               var errMsg = String.Format ("kevent() error at initial event registration, error code = '{0}'", Marshal.GetLastWin32Error ());
+                               throw new IOException (errMsg);
                        }
                }
 
-               static void StopMonitoringDirectory (KeventData data)
+               kevent[] CreateChangeList (ref List<int> FdList)
                {
-                       close(data.ev.ident);
+                       if (FdList.Count == 0)
+                               return emptyEventList;
+
+                       var changes = new List<kevent> ();
+                       foreach (int fd in FdList) {
+                               var change = new kevent {
+
+                                       ident = (UIntPtr)fd,
+                                       filter = EventFilter.Vnode,
+                                       flags = EventFlags.Add | EventFlags.Enable | EventFlags.Clear,
+                                       fflags = FilterFlags.VNodeDelete | FilterFlags.VNodeExtend |
+                                               FilterFlags.VNodeRename | FilterFlags.VNodeAttrib |
+                                               FilterFlags.VNodeLink | FilterFlags.VNodeRevoke |
+                                               FilterFlags.VNodeWrite,
+                                       data = IntPtr.Zero,
+                                       udata = IntPtr.Zero
+                               };
+
+                               changes.Add (change);
+                       }
+                       FdList.Clear ();
+
+                       return changes.ToArray ();
                }
 
                void Monitor ()
                {
-               
-                       while (!stop) {
-                               kevent ev = new kevent();
-                               ev.udata = IntPtr.Zero;
-                               kevent nullev = new kevent();
-                               nullev.udata = IntPtr.Zero;
-                               timespec ts = new timespec();
-                               ts.tv_sec = 0;
-                               ts.tv_usec = 0;
-                               int haveEvents;
-                               lock (this) {
-                                       haveEvents = kevent (conn, ref nullev, 0, ref ev, 1, ref ts);
+                       var timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)500000000 };
+                       var eventBuffer = new kevent[32];
+                       var newFds = new List<int> ();
+                       List<PathData> removeQueue = new List<PathData> ();
+                       List<string> rescanQueue = new List<string> ();
+
+                       while (!requestStop) {
+                               var changes = CreateChangeList (ref newFds);
+
+                               int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref timeout);
+
+                               if (numEvents == -1) {
+                                       var errMsg = String.Format ("kevent() error, error code = '{0}'", Marshal.GetLastWin32Error ());
+                                       fsw.OnError (new ErrorEventArgs (new IOException (errMsg)));
                                }
 
-                               if (haveEvents > 0) {
-                                       // Restart monitoring
-                                       KeventData data = (KeventData) requests [ev.ident];
-                                       StopMonitoringDirectory (data);
-                                       StartMonitoringDirectory (data);
-                                       ProcessEvent (ev);
-                               } else {
-                                       System.Threading.Thread.Sleep (500);
+                               if (numEvents == 0)
+                                       continue;
+
+                               for (var i = 0; i < numEvents; i++) {
+                                       var kevt = eventBuffer [i];
+                                       var pathData = fdsDict [(int)kevt.ident];
+
+                                       if ((kevt.flags & EventFlags.Error) == EventFlags.Error) {
+                                               var errMsg = String.Format ("kevent() error watching path '{0}', error code = '{1}'", pathData.Path, kevt.data);
+                                               fsw.OnError (new ErrorEventArgs (new IOException (errMsg)));
+                                               continue;
+                                       }
+
+                                       if ((kevt.fflags & FilterFlags.VNodeDelete) == FilterFlags.VNodeDelete || (kevt.fflags & FilterFlags.VNodeRevoke) == FilterFlags.VNodeRevoke)
+                                               removeQueue.Add (pathData);
+
+                                       else if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) {
+                                               if (pathData.IsDirectory)
+                                                       rescanQueue.Add (pathData.Path);
+                                               else
+                                                       PostEvent (FileAction.Modified, pathData.Path);
+                                       } 
+
+                                       else if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) {
+                                               var newFilename = GetFilenameFromFd (pathData.Fd);
+
+                                               if (newFilename.StartsWith (fsw.FullPath))
+                                                       Rename (pathData, newFilename);
+                                               else //moved outside of our watched dir so stop watching
+                                                               RemoveTree (pathData);
+                                       } 
+
+                                       else if ((kevt.fflags & FilterFlags.VNodeAttrib) == FilterFlags.VNodeAttrib || (kevt.fflags & FilterFlags.VNodeExtend) == FilterFlags.VNodeExtend)
+                                               PostEvent (FileAction.Modified, pathData.Path);
                                }
+
+                               removeQueue.ForEach (Remove);
+                               removeQueue.Clear ();
+
+                               rescanQueue.ForEach (path => {
+                                       Scan (path, true, ref newFds);
+                               });
+                               rescanQueue.Clear ();
+                       }
+               }
+
+               PathData Add (string path, bool postEvents, ref List<int> fds)
+               {
+                       PathData pathData;
+                       pathsDict.TryGetValue (path, out pathData);
+
+                       if (pathData != null)
+                               return pathData;
+
+                       var fd = open (path, O_EVTONLY, 0);
+
+                       if (fd == -1) {
+                               fsw.OnError (new ErrorEventArgs (new IOException (String.Format (
+                                       "open() error while attempting to process path '{0}', error code = '{1}'", path, Marshal.GetLastWin32Error ()))));
+                               return null;
                        }
 
-                       lock (this) {
-                               thread = null;
-                               stop = false;
+                       try {
+                               fds.Add (fd);
+
+                               var attrs = File.GetAttributes (path);
+
+                               pathData = new PathData {
+                                       Path = path,
+                                       Fd = fd,
+                                       IsDirectory = (attrs & FileAttributes.Directory) == FileAttributes.Directory
+                               };
+                               
+                               pathsDict.Add (path, pathData);
+                               fdsDict.Add (fd, pathData);
+
+                               if (postEvents)
+                                       PostEvent (FileAction.Added, path);
+
+                               return pathData;
+                       } catch (Exception e) {
+                               close (fd);
+                               fsw.OnError (new ErrorEventArgs (e));
+                               return null;
                        }
+
                }
 
-               void ProcessEvent (kevent ev)
+               void Remove (PathData pathData)
                {
-                       lock (this) {
-                               KeventData data = (KeventData) requests [ev.ident];
-                               if (!data.Enabled)
-                                       return;
+                       fdsDict.Remove (pathData.Fd);
+                       pathsDict.Remove (pathData.Path);
+                       close (pathData.Fd);
+                       PostEvent (FileAction.Removed, pathData.Path);
+               }
 
-                               FileSystemWatcher fsw;
-                               string filename = "";
+               void RemoveTree (PathData pathData)
+               {
+                       var toRemove = new List<PathData> ();
 
-                               fsw = data.FSW;
-                               FileAction fa = 0;
-                               DirectoryInfo dir = new DirectoryInfo (data.Directory);
-                               FileSystemInfo changedFsi = null;
+                       toRemove.Add (pathData);
 
-                               try {
-                                       foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() )
-                                               if (data.DirEntries.ContainsKey (fsi.FullName) && (fsi is FileInfo)) {
-                                                       KeventFileData entry = (KeventFileData) data.DirEntries [fsi.FullName];
-                                                       if (entry.LastWriteTime != fsi.LastWriteTime) {
-                                                               filename = fsi.Name;
-                                                               fa = FileAction.Modified;
-                                                               data.DirEntries [fsi.FullName] = new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime);
-                                                               if (fsw.IncludeSubdirectories && fsi is DirectoryInfo) {
-                                                                       data.Directory = filename;
-                                                                       requests [ev.ident] = data;
-                                                                       ProcessEvent(ev);
-                                                               }
-                                                               changedFsi = fsi;
-                                                               PostEvent(filename, fsw, fa, changedFsi);
-                                                       }
-                                               }
-                               } catch (Exception) {
-                                       // The file system infos were changed while we processed them
-                               }
-                               // Deleted
-                               try {
-                                       bool deleteMatched = true;
-                                       while(deleteMatched) {
-                                               foreach (KeventFileData entry in data.DirEntries.Values) { 
-                                                       if (!File.Exists (entry.fsi.FullName) && !Directory.Exists (entry.fsi.FullName)) {
-                                                               filename = entry.fsi.Name;
-                                                               fa = FileAction.Removed;
-                                                               data.DirEntries.Remove (entry.fsi.FullName);
-                                                               changedFsi = entry.fsi;
-                                                               PostEvent(filename, fsw, fa, changedFsi);
-                                                               break;
-                                                       }
-                                               }
-                                               deleteMatched = false;
+                       if (pathData.IsDirectory) {
+                               var prefix = pathData.Path + Path.DirectorySeparatorChar;
+                               foreach (var path in pathsDict.Keys)
+                                       if (path.StartsWith (prefix)) {
+                                               toRemove.Add (pathsDict [path]);
                                        }
-                               } catch (Exception) {
-                                       // The file system infos were changed while we processed them
-                               }
-                               // Added
-                               try {
-                                       foreach (FileSystemInfo fsi in dir.GetFileSystemInfos()) 
-                                               if (!data.DirEntries.ContainsKey (fsi.FullName)) {
-                                                       changedFsi = fsi;
-                                                       filename = fsi.Name;
-                                                       fa = FileAction.Added;
-                                                       data.DirEntries [fsi.FullName] = new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime);
-                                                       PostEvent(filename, fsw, fa, changedFsi);
-                                               }
-                               } catch (Exception) {
-                                       // The file system infos were changed while we processed them
-                               }
-                               
+                       }
+                       toRemove.ForEach (Remove);
+               }
 
+               void Rename (PathData pathData, string newRoot)
+               {
+                       var toRename = new List<PathData> ();
+                       var oldRoot = pathData.Path;
+
+                       toRename.Add (pathData);
+                                                                                                                       
+                       if (pathData.IsDirectory) {
+                               var prefix = oldRoot + Path.DirectorySeparatorChar;
+                               foreach (var path in pathsDict.Keys)
+                                       if (path.StartsWith (prefix))
+                                               toRename.Add (pathsDict [path]);
                        }
+
+                       toRename.ForEach ((pd) => { 
+                               var oldPath = pd.Path;
+                               var newPath = newRoot + oldPath.Substring (oldRoot.Length);
+                               pd.Path = newPath;
+                               pathsDict.Remove (oldPath);
+                               pathsDict.Add (newPath, pd);
+                       });
+
+                       PostEvent (FileAction.RenamedNewName, oldRoot, newRoot);
                }
 
-               private void PostEvent (string filename, FileSystemWatcher fsw, FileAction fa, FileSystemInfo changedFsi) {
-                       RenamedEventArgs renamed = null;
-                       if (fa == 0)
+               void Scan (string path, bool postEvents, ref List<int> fds)
+               {
+                       if (requestStop)
                                return;
-                       
-                       if (fsw.IncludeSubdirectories && fa == FileAction.Added) {
-                               if (changedFsi is DirectoryInfo) {
-                                       KeventData newdirdata = new KeventData ();
-                                       newdirdata.FSW = fsw;
-                                       newdirdata.Directory = changedFsi.FullName;
-                                       newdirdata.FileMask = fsw.MangledFilter;
-                                       newdirdata.IncludeSubdirs = fsw.IncludeSubdirectories;
-       
-                                       newdirdata.Enabled = true;
-                                       lock (this) {
-                                               StartMonitoringDirectory (newdirdata);
-                                       }
+                               
+                       var pathData = Add (path, postEvents, ref fds);
+
+                       if (pathData == null)
+                               return;
+                               
+                       if (!pathData.IsDirectory)
+                               return;
+
+                       var dirsToProcess = new List<string> ();
+                       dirsToProcess.Add (path);
+
+                       while (dirsToProcess.Count > 0) {
+                               var tmp = dirsToProcess [0];
+                               dirsToProcess.RemoveAt (0);
+
+                               var info = new DirectoryInfo (tmp);
+                               FileSystemInfo[] fsInfos = null;
+                               try {
+                                       fsInfos = info.GetFileSystemInfos ();
+                                               
+                               } catch (IOException) {
+                                       // this can happen if the directory has been deleted already.
+                                       // that's okay, just keep processing the other dirs.
+                                       fsInfos = new FileSystemInfo[0];
+                               }
+
+                               foreach (var fsi in fsInfos) {
+                                       if ((fsi.Attributes & FileAttributes.Directory) == FileAttributes.Directory && !fsw.IncludeSubdirectories)
+                                               continue;
+
+                                       if ((fsi.Attributes & FileAttributes.Directory) != FileAttributes.Directory && !fsw.Pattern.IsMatch (fsi.FullName))
+                                               continue;
+
+                                       var currentPathData = Add (fsi.FullName, postEvents, ref fds);
+
+                                       if (currentPathData != null && currentPathData.IsDirectory)
+                                               dirsToProcess.Add (fsi.FullName);
                                }
                        }
-               
-                       if (!fsw.Pattern.IsMatch(filename, true))
+               }
+                       
+               void PostEvent (FileAction action, string path, string newPath = null)
+               {
+                       RenamedEventArgs renamed = null;
+
+                       if (action == 0)
                                return;
 
+                       // only post events that match filter pattern. check both old and new paths for renames
+                       if (!fsw.Pattern.IsMatch (path) && (newPath == null || !fsw.Pattern.IsMatch (newPath))) 
+                               return;
+                               
+                       if (action == FileAction.RenamedNewName)
+                               renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, "", newPath, path);
+
                        lock (fsw) {
-                               if (changedFsi.FullName.StartsWith (fsw.FullPath, StringComparison.Ordinal)) {
-                                       if (fsw.FullPath.EndsWith ("/", StringComparison.Ordinal)) {
-                                               filename = changedFsi.FullName.Substring (fsw.FullPath.Length);
-                                       } else {
-                                               filename = changedFsi.FullName.Substring (fsw.FullPath.Length + 1);
-                                       }
-                               }
-                               fsw.DispatchEvents (fa, filename, ref renamed);
+                               fsw.DispatchEvents (action, path, ref renamed);
+
                                if (fsw.Waiting) {
                                        fsw.Waiting = false;
                                        System.Threading.Monitor.PulseAll (fsw);
@@ -445,17 +549,120 @@ namespace System.IO {
                        }
                }
 
+               private string GetFilenameFromFd (int fd)
+               {
+                       var sb = new StringBuilder (__DARWIN_MAXPATHLEN);
+
+                       if (fcntl (fd, F_GETPATH, sb) != -1) {
+                               if (fixupPath != null)
+                                       sb.Replace (fixupPath, fsw.FullPath, 0, fixupPath.Length); // see Setup()
+                               return sb.ToString ();
+                       } else {
+                               fsw.OnError (new ErrorEventArgs (new IOException (String.Format (
+                                       "fcntl() error while attempting to get path for fd '{0}', error code = '{1}'", fd, Marshal.GetLastWin32Error ()))));
+                               return String.Empty;
+                       }
+               }
+
+               const int O_EVTONLY = 0x8000;
+               const int F_GETPATH = 50;
+               const int __DARWIN_MAXPATHLEN = 1024;
+               static readonly kevent[] emptyEventList = new System.IO.kevent[0];
+
+               FileSystemWatcher fsw;
+               int conn;
+               Thread thread;
+               volatile bool requestStop = false;
+               AutoResetEvent startedEvent = new AutoResetEvent (false);
+               bool started = false;
+               bool failedInit = false;
+               object stateLock = new object ();
+
+               readonly Dictionary<string, PathData> pathsDict = new Dictionary<string, PathData> ();
+               readonly Dictionary<int, PathData> fdsDict = new Dictionary<int, PathData> ();
+               string fixupPath = null;
+
+               [DllImport ("libc", EntryPoint="fcntl", CharSet=CharSet.Auto, SetLastError=true)]
+               static extern int fcntl (int file_names_by_descriptor, int cmd, StringBuilder sb);
+
+               [DllImport ("libc")]
+               extern static int open (string path, int flags, int mode_t);
+
                [DllImport ("libc")]
-               extern static int open(string path, int flags, int mode_t);
-               
+               extern static int close (int fd);
+
                [DllImport ("libc")]
-               extern static int close(int fd);
+               extern static int kqueue ();
 
                [DllImport ("libc")]
-               extern static int kqueue();
+               extern static int kevent (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, [In] ref timespec time);
+       }
+
+       class KeventWatcher : IFileWatcher
+       {
+               static bool failed;
+               static KeventWatcher instance;
+               static Hashtable watches;  // <FileSystemWatcher, KqueueMonitor>
+
+               private KeventWatcher ()
+               {
+               }
+
+               // Locked by caller
+               public static bool GetInstance (out IFileWatcher watcher)
+               {
+                       if (failed == true) {
+                               watcher = null;
+                               return false;
+                       }
+
+                       if (instance != null) {
+                               watcher = instance;
+                               return true;
+                       }
+
+                       watches = Hashtable.Synchronized (new Hashtable ());
+                       var conn = kqueue();
+                       if (conn == -1) {
+                               failed = true;
+                               watcher = null;
+                               return false;
+                       }
+                       close (conn);
+
+                       instance = new KeventWatcher ();
+                       watcher = instance;
+                       return true;
+               }
+
+               public void StartDispatching (FileSystemWatcher fsw)
+               {
+                       KqueueMonitor monitor;
+
+                       if (watches.ContainsKey (fsw)) {
+                               monitor = (KqueueMonitor)watches [fsw];
+                       } else {
+                               monitor = new KqueueMonitor (fsw);
+                               watches.Add (fsw, monitor);
+                       }
+                               
+                       monitor.Start ();
+               }
+
+               public void StopDispatching (FileSystemWatcher fsw)
+               {
+                       KqueueMonitor monitor = (KqueueMonitor)watches [fsw];
+                       if (monitor == null)
+                               return;
+
+                       monitor.Stop ();
+               }
+                       
+               [DllImport ("libc")]
+               extern static int close (int fd);
 
                [DllImport ("libc")]
-               extern static int kevent(int kqueue, ref kevent ev, int nchanges, ref kevent evtlist,  int nevents, ref timespec ts);
+               extern static int kqueue ();
        }
 }
 
index 0fbab4e5e7eb3e50be08b27174d1d8efb8b7c6bf..f302dffaaa046940f430fbec3a04b6dd78948660 100644 (file)
@@ -47,7 +47,7 @@ namespace System.IO {
                        Compile (pattern);
                }
 
-               // OSX has a retarded case-insensitive yet case-aware filesystem
+               // OSX has a case-insensitive yet case-aware filesystem
                // so we need a overload in here for the Kqueue watcher
                public bool IsMatch (string text, bool ignorecase)
                {
@@ -55,20 +55,17 @@ namespace System.IO {
                                bool match = String.Compare (pattern, text, ignorecase) == 0;
                                if (match)
                                        return true;
-                               
-                               // This is a special case for FSW. It needs to match e.g. subdir/file.txt
-                               // when the pattern is "file.txt"
-                               int idx = text.LastIndexOf ('/');
-                               if (idx == -1)
-                                       return false;
-                               idx++;
-                               if (idx == text.Length)
-                                       return false;
-                               
-                               return (String.Compare (pattern, text.Substring (idx), ignorecase) == 0);
                        }
+                               
+                       // This is a special case for FSW. It needs to match e.g. subdir/file.txt
+                       // when the pattern is "file.txt"
+                       var fileName = Path.GetFileName (text);
+                       
+                       if (!hasWildcard)
+                               return (String.Compare (pattern, fileName, ignorecase) == 0);
+                       
                        
-                       return Match (ops, text, 0);
+                       return Match (ops, fileName, 0);
                }
 
                public bool IsMatch (string text)
index 628c04d8eddcba9f61fffee9e155e50cbb622eaa..a1d0896dba63d84bb0927be9b160ec03b54c5996 100644 (file)
@@ -200,6 +200,8 @@ namespace Mono.Audio {
                                snd_pcm_hw_params_free (hw_param);
                        if (handle != IntPtr.Zero)
                                snd_pcm_close (handle);
+                       sw_param = IntPtr.Zero;
+                       hw_param = IntPtr.Zero;
                        handle = IntPtr.Zero;
                }
 
@@ -278,10 +280,14 @@ namespace Mono.Audio {
                                Console.WriteLine ("failed to alloc Alsa sw param struct");
                        }
 
-                       if (hw_param != IntPtr.Zero)
+                       if (hw_param != IntPtr.Zero) {
                                snd_pcm_hw_params_free (hw_param);  // free hw params
-                       if (sw_param != IntPtr.Zero)
+                               hw_param = IntPtr.Zero;
+                       }
+                       if (sw_param != IntPtr.Zero) {
                                snd_pcm_sw_params_free (sw_param);  // free sw params
+                               sw_param = IntPtr.Zero;
+                       }
 
                        return alsa_err == 0;
                }
index a7eeb67d883c73ab90fdb7e57a87c096b633c452..c7f6259172d3d4adbc0c35eac98a54512c80679a 100644 (file)
@@ -260,6 +260,8 @@ namespace System.Net.Sockets
                                curSocket.EndConnect (ares);
                        } catch (SocketException se) {
                                SocketError = se.SocketErrorCode;
+                       } catch (ObjectDisposedException) {
+                               SocketError = SocketError.OperationAborted;
                        } finally {
                                OnCompleted (this);
                        }
index b0295bef71beff144c4de459318150487d150b83..b44a061159207ba22e4f1ec05cd8c236eb4cbf5d 100644 (file)
@@ -952,6 +952,14 @@ namespace System.Net.Sockets {
 #endif
                }
 
+#if NET_4_5
+               [MonoTODO ("Currently hardcoded to IPv4. Ideally, support v4/v6 dual-stack.")]
+               public Socket (SocketType socketType, ProtocolType protocolType)
+                       : this (AddressFamily.InterNetwork, socketType, protocolType)
+               {
+               }
+#endif
+
                ~Socket ()
                {
                        Dispose (false);
index b33a5b4385f2620b87d09df9266a2e8c1963585a..bf41aeee21af96b1c098b5bb30e596f11cdebb69 100644 (file)
@@ -247,6 +247,40 @@ namespace MonoTests.System.Collections.Concurrent
                        Assert.AreEqual (-10, t.Result, "#5");
                        Assert.AreEqual ("canceled", res, "#6");
                }
+
+               [Test, ExpectedException (typeof(OperationCanceledException))]
+               public void BoundedAddLimit ()
+               {
+                       const int elNumber = 5;
+
+                       var c = new BlockingCollection <int> (elNumber);
+                       var token = new CancellationTokenSource (100);
+
+                       for (var i = 0; i < elNumber + 1; i++) {
+                               c.Add (1, token.Token);
+                       }
+               }
+
+               [Test]
+               public void AddAnyCancellable ()
+               {
+                       const int elNumber = 5;
+                       const int colNumber = 5;
+
+                       var cols = new BlockingCollection <int> [colNumber];
+                       for (var i = 0; i < colNumber; i++) {
+                               cols[i] = new BlockingCollection <int> (elNumber);
+                       }
+
+                       var token = new CancellationTokenSource (100);
+                       for (var i = 0; i < colNumber * elNumber; i++) {
+                               BlockingCollection <int>.AddToAny (cols, 1, token.Token);
+                       }
+
+                       foreach (var col in cols) {
+                               Assert.AreEqual (elNumber, col.Count);
+                       }
+               }
        }
 }
 #endif
index 05ff63ce8ea011b8bc9d3103fcfbe76e12d83aab..7f3011e2b9dc6ef6a7c55a20ef473fc595192b02 100644 (file)
@@ -36,6 +36,14 @@ using NUnit.Framework;
 namespace MonoTests.System.Net {
        [TestFixture]
        public class HttpListenerTest {
+
+               int port;
+
+               [SetUp]
+               public void SetUp () {
+                       port = new Random ().Next (7777, 8000);
+               }
+
                [Test]
                public void DefaultProperties ()
                {
@@ -152,10 +160,12 @@ namespace MonoTests.System.Net {
                [Test]
                public void TwoListeners_SameAddress ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener1 = new HttpListener ();
-                       listener1.Prefixes.Add ("http://127.0.0.1:7777/");
+                       listener1.Prefixes.Add ("http://127.0.0.1:" + port + "/");
                        HttpListener listener2 = new HttpListener ();
-                       listener2.Prefixes.Add ("http://127.0.0.1:7777/hola/");
+                       listener2.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/");
                        listener1.Start ();
                        listener2.Start ();
                }
@@ -164,10 +174,12 @@ namespace MonoTests.System.Net {
                [ExpectedException (typeof (HttpListenerException))]
                public void TwoListeners_SameURL ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener1 = new HttpListener ();
-                       listener1.Prefixes.Add ("http://127.0.0.1:7777/hola/");
+                       listener1.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/");
                        HttpListener listener2 = new HttpListener ();
-                       listener2.Prefixes.Add ("http://127.0.0.1:7777/hola/");
+                       listener2.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/");
                        listener1.Start ();
                        listener2.Start ();
                }
@@ -176,8 +188,10 @@ namespace MonoTests.System.Net {
                [ExpectedException (typeof (HttpListenerException))]
                public void MultipleSlashes ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener = new HttpListener ();
-                       listener.Prefixes.Add ("http://localhost:7777/hola////");
+                       listener.Prefixes.Add ("http://localhost:" + port + "/hola////");
                        // this one throws on Start(), not when adding it.
                        listener.Start ();
                }
@@ -186,8 +200,10 @@ namespace MonoTests.System.Net {
                [ExpectedException (typeof (HttpListenerException))]
                public void PercentSign ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener = new HttpListener ();
-                       listener.Prefixes.Add ("http://localhost:7777/hola%3E/");
+                       listener.Prefixes.Add ("http://localhost:" + port + "/hola%3E/");
                        // this one throws on Start(), not when adding it.
                        listener.Start ();
                }
@@ -202,8 +218,10 @@ namespace MonoTests.System.Net {
                [Test]
                public void CloseTwice ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener = new HttpListener ();
-                       listener.Prefixes.Add ("http://localhost:7777/hola/");
+                       listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
                        listener.Start ();
                        listener.Close ();
                        listener.Close ();
@@ -212,8 +230,10 @@ namespace MonoTests.System.Net {
                [Test]
                public void StartStopStart ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener = new HttpListener ();
-                       listener.Prefixes.Add ("http://localhost:7777/hola/");
+                       listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
                        listener.Start ();
                        listener.Stop ();
                        listener.Start ();
@@ -223,8 +243,10 @@ namespace MonoTests.System.Net {
                [Test]
                public void StartStopDispose ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        using (HttpListener listener = new HttpListener ()){
-                               listener.Prefixes.Add ("http://localhost:7777/hola/");
+                               listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
                                listener.Start ();
                                listener.Stop ();
                        }
@@ -240,8 +262,10 @@ namespace MonoTests.System.Net {
                [Test]
                public void AbortTwice ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener = new HttpListener ();
-                       listener.Prefixes.Add ("http://localhost:7777/hola/");
+                       listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
                        listener.Start ();
                        listener.Abort ();
                        listener.Abort ();
index c053a4bbfc3e5195a4c22577524ba73d810dd099..34c2b8489491f6d46198ce13ae71f33e1a034dc0 100644 (file)
@@ -495,11 +495,15 @@ namespace System.Reflection
 
                public override object [] GetCustomAttributes (bool inherit)
                {
+                       if (IsCreated)
+                               return generic_type.GetCustomAttributes (inherit);
                        throw new NotSupportedException ();
                }
 
                public override object [] GetCustomAttributes (Type attributeType, bool inherit)
                {
+                       if (IsCreated)
+                               return generic_type.GetCustomAttributes (attributeType, inherit);
                        throw new NotSupportedException ();
                }
 
index 150cac95bef8b1c03355909a84be750a5f29bd0b..07074f8aef3ee6b3be94a8203be37ffd3759ca31 100644 (file)
@@ -98,8 +98,6 @@ namespace System.Security.Cryptography {
                        // don't read stream unless object is ready to use
                        if (disposed)
                                throw new ObjectDisposedException ("HashAlgorithm");
-                       if (inputStream == null)
-                               throw new ArgumentNullException ("InputStream");
 
                        byte[] buffer = new byte [4096];
                        int len = inputStream.Read (buffer, 0, 4096);
index 1f8165a0d480712cad9b3affb89b3ab076376147..4f4abd33e9cd8365c7919c890e59d3f4acf04a8e 100644 (file)
@@ -635,7 +635,7 @@ namespace System.Threading.Tasks
                
                #region Cancel and Wait related method
                
-               internal void CancelReal ()
+               internal void CancelReal (bool notifyParent = false)
                {
                        Status = TaskStatus.Canceled;
 
@@ -643,6 +643,9 @@ namespace System.Threading.Tasks
                                wait_handle.Set ();
 
                        ProcessCompleteDelegates ();
+
+                       if (notifyParent && parent != null && NotifyParentOnFinish ())
+                               parent = null;
                }
 
                void HandleGenericException (Exception e)
index 2a0547850bd044fd65d53eea6bd251ea3ea5aad9..8ede25eebe4f4c81e23bc67e0583afb05b444ee6 100644 (file)
@@ -94,7 +94,7 @@ namespace System.Threading.Tasks
                public void Execute ()
                {
                        if (!ContinuationStatusCheck (continuationOptions)) {
-                               task.CancelReal ();
+                               task.CancelReal (notifyParent : true);
                                task.Dispose ();
                                return;
                        }
index 07b6fd45590ff9c00027b3a991a24689b4e10197..f04fe2a006db7e6f1b64f313cbf75eeed6b67876 100644 (file)
@@ -1354,6 +1354,11 @@ namespace System {
                                DomainUnload(this, null);
                }
 
+               internal void DoUnhandledException (UnhandledExceptionEventArgs args) {
+                       if (UnhandledException != null)
+                               UnhandledException (this, args);
+               }
+
                internal byte[] GetMarshalledDomainObjRef ()
                {
                        ObjRef oref = RemotingServices.Marshal (AppDomain.CurrentDomain, null, typeof (AppDomain));
index 2a408933eacf42bb4dfa82e80fdcf142481997d1..65e460647ca4955aecd1a8c4b97cccae46d9f582 100644 (file)
@@ -2688,24 +2688,8 @@ namespace System
                        }
                }
 
-               internal unsafe void InternalSetLength (int newLength)
-               {
-                       if (newLength > length)
-                               throw new ArgumentOutOfRangeException ("newLength", "newLength as to be <= length");
-
-                       // zero terminate, we can pass string objects directly via pinvoke
-                       // we also zero the rest of the string, since the new GC needs to be
-                       // able to handle the changing size (it will skip the 0 bytes).
-                       fixed (char * pStr = &start_char) {
-                               char *p = pStr + newLength;
-                               char *end = pStr + length;
-                               while (p < end) {
-                                       p [0] = '\0';
-                                       p++;
-                               }
-                       }
-                       length = newLength;
-               }
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               internal extern void InternalSetLength (int newLength);
 
                [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
                // When modifying it, GetCaseInsensitiveHashCode() should be modified as well.
index 54a7c42238fed25d6a1b312184884524e36ed7cf..9feea2b3385acd7eb8e93b514d86293ed0adf85e 100644 (file)
@@ -138,7 +138,7 @@ public class HashAlgorithmTest {
        }
 
        [Test]
-       [ExpectedException (typeof (ArgumentNullException))]
+       [ExpectedException (typeof (NullReferenceException))]
        public void NullStream () 
        {
                Stream s = null;
index 1be7986a43868c2790ae4d7a4d213912bbee8dbe..6cf1637d0859b55ce42067cf2461f13511c31f30 100644 (file)
@@ -251,7 +251,8 @@ public class RSACryptoServiceProviderTest {
        }
 
        [Test]
-       [ExpectedException (typeof (ArgumentNullException))]
+       //[ExpectedException (typeof (ArgumentNullException))]
+       [ExpectedException (typeof (NullReferenceException))]
        public void SignDataStreamNull () 
        {
                rsa = new RSACryptoServiceProvider (minKeySize);
index 63eb8a2aff1a8b31d9b64fe0b40193d0a3a0430f..524988828b96e23defe7013539d02c1fbf604c0e 100644 (file)
@@ -104,6 +104,8 @@ namespace MonoTests.System.Threading.Tasks
                        }
                }
 
+               int workerThreads;
+               int completionPortThreads;
 
                Task[] tasks;
                const int max = 6;
@@ -111,9 +113,18 @@ namespace MonoTests.System.Threading.Tasks
                [SetUp]
                public void Setup()
                {
+                       ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
+                       ThreadPool.SetMinThreads (1, 1);
+
                        tasks = new Task[max];                  
                }
                
+               [TearDown]
+               public void Teardown()
+               {
+                       ThreadPool.SetMinThreads (workerThreads, completionPortThreads);
+               }
+               
                void InitWithDelegate(Action action)
                {
                        for (int i = 0; i < max; i++) {
@@ -616,18 +627,18 @@ namespace MonoTests.System.Threading.Tasks
                public void ContinueWithChildren ()
                {
                        ParallelTestHelper.Repeat (delegate {
-                           bool result = false;
+                               bool result = false;
 
-                           var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
+                               var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
 
                                var mre = new ManualResetEvent (false);
-                           t.ContinueWith (l => {
+                               t.ContinueWith (l => {
                                        result = true;
                                        mre.Set ();
                                });
 
                                Assert.IsTrue (mre.WaitOne (1000), "#1");
-                           Assert.IsTrue (result, "#2");
+                               Assert.IsTrue (result, "#2");
                        }, 2);
                }
 
@@ -788,19 +799,53 @@ namespace MonoTests.System.Threading.Tasks
                {
                        ParallelTestHelper.Repeat (delegate {
                                var evt = new ManualResetEventSlim ();
-                               var t = Task.Factory.StartNew (() => evt.Wait (5000));
+                               var monitor = new object ();
+                               int finished = 0;
+                               var t = Task.Factory.StartNew (delegate {
+                                               var r = evt.Wait (5000);
+                                               lock (monitor) {
+                                                       finished ++;
+                                                       Monitor.Pulse (monitor);
+                                               }
+                                               return r;
+                                       });
                                var cntd = new CountdownEvent (2);
                                var cntd2 = new CountdownEvent (2);
 
                                bool r1 = false, r2 = false;
-                               ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000) && t.Result; cntd2.Signal (); });
-                               ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000) && t.Result; cntd2.Signal (); });
-
+                               ThreadPool.QueueUserWorkItem (delegate {
+                                               cntd.Signal ();
+                                               r1 = t.Wait (1000) && t.Result;
+                                               cntd2.Signal ();
+                                               lock (monitor) {
+                                                       finished ++;
+                                                       Monitor.Pulse (monitor);
+                                               }
+                                       });
+                               ThreadPool.QueueUserWorkItem (delegate {
+                                               cntd.Signal ();
+                                               r2 = t.Wait (1000) && t.Result;
+                                               cntd2.Signal ();
+                                               lock (monitor) {
+                                                       finished ++;
+                                                       Monitor.Pulse (monitor);
+                                               }
+                                       });
                                Assert.IsTrue (cntd.Wait (2000), "#1");
                                evt.Set ();
                                Assert.IsTrue (cntd2.Wait (2000), "#2");
                                Assert.IsTrue (r1, "r1");
                                Assert.IsTrue (r2, "r2");
+
+                               // Wait for everything to finish to avoid overloading the tpool
+                               lock (monitor) {
+                                       while (true) {
+                                               if (finished == 3)
+                                                       break;
+                                               else
+                                                       Monitor.Wait (monitor);
+                                       }
+                               }
                        }, 10);
                }
 
@@ -905,7 +950,7 @@ namespace MonoTests.System.Threading.Tasks
                        };
                        var inner = new ApplicationException ();
                        Thread t = new Thread (delegate () {
-                                       Task.Factory.StartNew (() => { Console.WriteLine ("HIT!"); throw inner; });
+                                       Task.Factory.StartNew (() => { throw inner; });
                                });
                        t.Start ();
                        t.Join ();
@@ -1094,7 +1139,7 @@ namespace MonoTests.System.Threading.Tasks
                        var t = new Task (() => {
                                new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
                                Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
-                   });
+                       });
                        t.RunSynchronously ();
 
                        Assert.IsTrue (r1);
@@ -1932,6 +1977,24 @@ namespace MonoTests.System.Threading.Tasks
                        }
                }
 
+               [Test]
+               public void ChildTaskWithUnscheduledContinuationAttachedToParent ()
+               {
+                       Task inner = null;
+                       var child = Task.Factory.StartNew (() => {
+                               inner  = Task.Run (() => {
+                                       throw new ApplicationException ();
+                               }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
+                       });
+
+                       int counter = 0;
+                       var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously);
+                       Assert.IsTrue (t.Wait (5000), "#1");
+                       Assert.AreEqual (1, counter, "#2");
+                       Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3");
+                       Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4");
+               }
+
                [Test]
                [Category("NotWorking")]
                public void TaskContinuationChainLeak()
index d80870fca6fd800b383a70095876efb58384e88c..bf5bf19095531491d14fcc25ace1b6995323dc6b 100644 (file)
     <Compile Include="System\Exception.cs" />\r
     <Compile Include="System\ExecutionEngineException.cs" />\r
     <Compile Include="System\FieldAccessException.cs" />\r
+    <Compile Include="System\FirstChanceExceptionEventArgs.cs" />\r
     <Compile Include="System\FlagsAttribute.cs" />\r
     <Compile Include="System\FormatException.cs" />\r
     <Compile Include="System\Funcs.cs" />\r
diff --git a/mcs/errors/cs0677-5.cs b/mcs/errors/cs0677-5.cs
new file mode 100644 (file)
index 0000000..a6d2248
--- /dev/null
@@ -0,0 +1,11 @@
+// CS0677: `X.e': A volatile field cannot be of the type `E'
+// Line: 10
+
+enum E : long
+{
+}
+
+class X
+{
+       volatile E e;
+}
index e3555b9383e387f42964b063ba1e7ab232b862ee..3531af044f3bc39543000501a647a96f409e8b7a 100644 (file)
@@ -605,9 +605,23 @@ namespace Mono.CSharp
                        if (TypeSpec.IsReferenceType (MemberType))
                                return true;
 
-                       if (MemberType.IsEnum)
+                       if (MemberType.IsPointer)
                                return true;
 
+                       if (MemberType.IsEnum) {
+                               switch (EnumSpec.GetUnderlyingType (MemberType).BuiltinType) {
+                               case BuiltinTypeSpec.Type.SByte:
+                               case BuiltinTypeSpec.Type.Byte:
+                               case BuiltinTypeSpec.Type.Short:
+                               case BuiltinTypeSpec.Type.UShort:
+                               case BuiltinTypeSpec.Type.Int:
+                               case BuiltinTypeSpec.Type.UInt:
+                                       return true;
+                               default:
+                                       return false;
+                               }
+                       }
+
                        return false;
                }
 
index 7878999c1d1404f1be43865809a6a95156b8913c..3b2ffbaa9c4fa39f33a807eed0b583d09026e8f8 100644 (file)
@@ -1,3 +1,4 @@
+// Compiler options: -unsafe
 //
 // Tests the valid value types for volatile fields.
 //
@@ -11,6 +12,9 @@ enum XX {
        A
 }
 
+struct S {
+}
+
 class X {
        volatile byte a;
        volatile sbyte b;
@@ -26,6 +30,9 @@ class X {
        volatile XX dd;
        volatile IntPtr ip;
        volatile UIntPtr uip;
+       unsafe volatile ushort* uc;
+       unsafe volatile XX* udd;
+       unsafe volatile S* us;
 
        public static void Main () {}
 }
index 6a7f39d90f3de38354b5d2f8721c0f9a8b12f9cb..b79dd7b886a96bee9efbf21a1ea07a8176236729 100644 (file)
@@ -64,6 +64,11 @@ namespace Xamarin.ApiDiff {
                        get { return ignoreAdded; }
                }
 
+               static List<Regex> ignoreNew = new List<Regex> ();
+               public static List<Regex> IgnoreNew {
+                       get { return ignoreNew; }
+               }
+
                static List<Regex> ignoreRemoved = new List<Regex> ();
                public static List<Regex> IgnoreRemoved {
                        get { return ignoreRemoved; }
@@ -83,11 +88,12 @@ namespace Xamarin.ApiDiff {
                        var options = new OptionSet {
                                { "h|help", "Show this help", v => showHelp = true },
                                { "d|diff=", "HTML diff file out output (omit for stdout)", v => diff = v },
-                               { "i|ignore=", "Ignore both added and removed members whose description matches a given C# regular expression (see below).",
+                               { "i|ignore=", "Ignore new, added, and removed members whose description matches a given C# regular expression (see below).",
                                        v => {
                                                var r = new Regex (v);
                                                State.IgnoreAdded.Add (r);
                                                State.IgnoreRemoved.Add (r);
+                                               State.IgnoreNew.Add (r);
                                        }
                                },
                                { "a|ignore-added=", "Ignore added members whose description matches a given C# regular expression (see below).",
@@ -96,6 +102,9 @@ namespace Xamarin.ApiDiff {
                                { "r|ignore-removed=", "Ignore removed members whose description matches a given C# regular expression (see below).",
                                        v => State.IgnoreRemoved.Add (new Regex (v))
                                },
+                               { "n|ignore-new=", "Ignore new namespaces and types whose description matches a given C# regular expression (see below).",
+                                       v => State.IgnoreNew.Add (new Regex (v))
+                               },
                                { "x|lax", "Ignore duplicate XML entries", v => State.Lax = true }
                        };
 
index bdf22fea4895b2917e0884e0d7d62a11457739f2..d96613c3e8ac69fe3a1a121e84fc4c7b6d0ed700 100644 (file)
@@ -27,6 +27,7 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
+using System.Linq;
 using System.Xml.Linq;
 
 namespace Xamarin.ApiDiff {
@@ -68,7 +69,10 @@ namespace Xamarin.ApiDiff {
 
                public override void Added (XElement target)
                {
-                       Output.WriteLine ("<h3>New Type {0}.{1}</h3>", State.Namespace, target.Attribute ("name").Value);
+                       string name = target.Attribute ("name").Value;
+                       if (State.IgnoreNew.Any (re => re.IsMatch (name)))
+                               return;
+                       Output.WriteLine ("<h3>New Type {0}.{1}</h3>", State.Namespace, name);
                        Output.WriteLine ("<pre>");
                        State.Indent = 0;
                        AddedInner (target);
index 7239385870eba9811c0caa90dafb70fa574b439e..427df66e6eb9cef2350288359f7226862dfe28ea 100644 (file)
@@ -26,6 +26,7 @@
 
 using System;
 using System.IO;
+using System.Linq;
 using System.Xml.Linq;
 
 namespace Xamarin.ApiDiff {
@@ -55,7 +56,11 @@ namespace Xamarin.ApiDiff {
 
                public override void Added (XElement target)
                {
-                       Output.WriteLine ("<h2>New Namespace {0}</h2>", target.Attribute ("name").Value);
+                       string name = target.Attribute ("name").Value;
+                       if (State.IgnoreNew.Any (re => re.IsMatch (name)))
+                               return;
+
+                       Output.WriteLine ("<h2>New Namespace {0}</h2>", name);
                        Output.WriteLine ();
                        // list all new types
                        foreach (var addedType in target.Element ("classes").Elements ("class"))
index fd581ff5514d8c6a5cbe0dfb7a2b18098cae22a1..0a6e86d0c0cbda09e0dc599d65c87c5eaa2e0d16 100644 (file)
@@ -4,7 +4,6 @@ if HOST_WIN32
 export HOST_CC
 endif
 
-if JIT_SUPPORTED
 if !SHARED_MONO
 static_libs=   \
        $(top_builddir)/mono/metadata/libmonoruntime-static.la  \
@@ -17,9 +16,6 @@ runtime_lib=../mini/$(LIBMONO_LA) $(static_libs)
 else
 runtime_lib=../mini/$(LIBMONO_LA)
 endif
-else
-runtime_lib=../interpreter/libmint.la
-endif
 
 if DISABLE_EXECUTABLES
 bin_PROGRAMS =
index 8cd74e9ff36abdf753f41f58f31f739c9d7ea1e6..5e706fb7280252ca41d3d5c07e66274ad333a435 100644 (file)
@@ -29,6 +29,9 @@
 #  include <dirent.h>
 #endif
 #include <sys/stat.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#  include <sys/resource.h>
+#endif
 
 #include <mono/io-layer/wapi.h>
 #include <mono/io-layer/wapi-private.h>
@@ -213,6 +216,21 @@ static void handle_cleanup (void)
                g_free (_wapi_private_handles [i]);
 }
 
+int
+wapi_getdtablesize (void)
+{
+#ifdef HAVE_GETRLIMIT
+       struct rlimit limit;
+       int res;
+
+       res = getrlimit (RLIMIT_NOFILE, &limit);
+       g_assert (res == 0);
+       return limit.rlim_cur;
+#else
+       return getdtablesize ();
+#endif
+}
+
 /*
  * wapi_init:
  *
@@ -223,8 +241,8 @@ wapi_init (void)
 {
        g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0]))
                  == WAPI_HANDLE_COUNT);
-       
-       _wapi_fd_reserve = getdtablesize();
+
+       _wapi_fd_reserve = wapi_getdtablesize ();
 
        /* This is needed by the code in _wapi_handle_new_internal */
        _wapi_fd_reserve = (_wapi_fd_reserve + (_WAPI_HANDLE_INITIAL_COUNT - 1)) & ~(_WAPI_HANDLE_INITIAL_COUNT - 1);
@@ -266,6 +284,7 @@ wapi_init (void)
        _wapi_global_signal_cond = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle)).signal_cond;
        _wapi_global_signal_mutex = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle)).signal_mutex;
 
+       wapi_processes_init ();
 
        /* Using g_atexit here instead of an explicit function call in
         * a cleanup routine lets us cope when a third-party library
@@ -1841,65 +1860,6 @@ void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd)
                }
        }
 
-       for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
-               struct _WapiHandleShared *shared;
-               struct _WapiHandle_process *process_handle;
-
-               shared = &_wapi_shared_layout->handles[i];
-               
-               if (shared->type == WAPI_HANDLE_PROCESS) {
-                       DIR *fd_dir;
-                       struct dirent *fd_entry;
-                       char subdir[_POSIX_PATH_MAX];
-
-                       process_handle = &shared->u.process;
-                       pid = process_handle->id;
-               
-                       /* Look in /proc/<pid>/fd/ but ignore
-                        * /proc/<our pid>/fd/<fd>, as we have the
-                        * file open too
-                        */
-                       g_snprintf (subdir, _POSIX_PATH_MAX, "/proc/%d/fd",
-                                   pid);
-                       
-                       fd_dir = opendir (subdir);
-                       if (fd_dir == NULL) {
-                               continue;
-                       }
-
-                       DEBUG ("%s: Looking in %s", __func__, subdir);
-                       
-                       proc_fds = TRUE;
-                       
-                       while ((fd_entry = readdir (fd_dir)) != NULL) {
-                               char path[_POSIX_PATH_MAX];
-                               struct stat link_stat;
-                               
-                               if (!strcmp (fd_entry->d_name, ".") ||
-                                   !strcmp (fd_entry->d_name, "..") ||
-                                   (pid == self &&
-                                    fd == atoi (fd_entry->d_name))) {
-                                       continue;
-                               }
-
-                               g_snprintf (path, _POSIX_PATH_MAX,
-                                           "/proc/%d/fd/%s", pid,
-                                           fd_entry->d_name);
-                               
-                               stat (path, &link_stat);
-                               if (link_stat.st_dev == share_info->device &&
-                                   link_stat.st_ino == share_info->inode) {
-                                       DEBUG ("%s:  Found it at %s",
-                                                  __func__, path);
-
-                                       found = TRUE;
-                               }
-                       }
-                       
-                       closedir (fd_dir);
-               }
-       }
-
        if (proc_fds == FALSE) {
                _wapi_handle_check_share_by_pid (share_info);
        } else if (found == FALSE) {
index 04444d0ae82f0d753d4e9f5bdf0a0b40e6d62090..31cab7bdb94931cf070abb89c88d20079a4f278d 100644 (file)
@@ -20,6 +20,8 @@ extern gboolean DuplicateHandle (gpointer srcprocess, gpointer src, gpointer tar
 extern void wapi_init (void);
 extern void wapi_cleanup (void);
 
+int wapi_getdtablesize (void);
+
 G_END_DECLS
 
 #endif /* _WAPI_HANDLES_H_ */
index c3e6988732dfec4fbfac0580d705dd8f9b254bfd..1da7f472f008f853b9cb838dc24e4b9b6bf23ffb 100644 (file)
 /* There doesn't seem to be a defined symbol for this */
 #define _WAPI_PROCESS_CURRENT (gpointer)0xFFFFFFFF
 
+/*
+ * Handles > _WAPI_PROCESS_UNHANDLED are pseudo handles which represent processes
+ * not started by the runtime.
+ */
 /* This marks a system process that we don't have a handle on */
 /* FIXME: Cope with PIDs > sizeof guint */
 #define _WAPI_PROCESS_UNHANDLED (1 << (8*sizeof(pid_t)-1))
 #define _WAPI_PROCESS_UNHANDLED_PID_MASK (-1 & ~_WAPI_PROCESS_UNHANDLED)
+#define WAPI_IS_PSEUDO_PROCESS_HANDLE(handle) ((GPOINTER_TO_UINT(handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED)
+#define WAPI_PID_TO_HANDLE(pid) GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + (pid))
+#define WAPI_HANDLE_TO_PID(handle) (GPOINTER_TO_UINT ((handle)) - _WAPI_PROCESS_UNHANDLED)
 
+void wapi_processes_init (void);
 extern gpointer _wapi_process_duplicate (void);
 extern void wapi_processes_cleanup (void);
 
 extern struct _WapiHandleOps _wapi_process_ops;
 
-#define _WAPI_PROC_NAME_MAX_LEN _POSIX_PATH_MAX
-
 /*
  * MonoProcess describes processes we create.
  * It contains a semaphore that can be waited on in order to wait
@@ -42,8 +48,7 @@ struct MonoProcess {
        gint32 handle_count; /* the number of handles to this mono_process instance */
        /* we keep a ref to the creating _WapiHandle_process handle until
         * the process has exited, so that the information there isn't lost.
-        * If we put the information there in this structure, it won't be
-        * available to other processes when using shared handles. */
+        */
        gpointer handle;
        struct MonoProcess *next;
 };
@@ -52,8 +57,6 @@ struct MonoProcess {
 /*
  * _WapiHandle_process is a structure containing all the required information
  * for process handling.
- * The mono_process field is only present if this process has created
- * the corresponding process.
  */
 struct _WapiHandle_process
 {
@@ -62,12 +65,13 @@ struct _WapiHandle_process
        gpointer main_thread;
        WapiFileTime create_time;
        WapiFileTime exit_time;
-       gchar proc_name[_WAPI_PROC_NAME_MAX_LEN];
+       char *proc_name;
        size_t min_working_set;
        size_t max_working_set;
        gboolean exited;
-       pid_t self; /* mono_process is shared among processes, but only usable in the process that created it */
        struct MonoProcess *mono_process;
 };
 
+typedef struct _WapiHandle_process WapiHandle_process;
+
 #endif /* _WAPI_PROCESS_PRIVATE_H_ */
index c65bf23813c0ce954166d7595113fdf40ca6a3e7..3c0531f3de0fd68b07a18dbf3e4535758982a910 100644 (file)
@@ -86,7 +86,7 @@
  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
  * in fact exist on all implementations (so far) 
  */
-gchar ***_NSGetEnviron(void);
+char ***_NSGetEnviron(void);
 #define environ (*_NSGetEnviron())
 #else
 extern char **environ;
@@ -142,22 +142,25 @@ static volatile gint32 mono_processes_cleaning_up = 0;
 static mono_mutex_t mono_processes_mutex;
 static void mono_processes_cleanup (void);
 
-static mono_once_t process_current_once=MONO_ONCE_INIT;
-static gpointer current_process=NULL;
+static gpointer current_process;
 static char *cli_launcher;
 
-static mono_once_t process_ops_once=MONO_ONCE_INIT;
-
-static void process_ops_init (void)
+static WapiHandle_process *
+lookup_process_handle (gpointer handle)
 {
-       _wapi_handle_register_capabilities (WAPI_HANDLE_PROCESS,
-                                           WAPI_HANDLE_CAP_WAIT |
-                                           WAPI_HANDLE_CAP_SPECIAL_WAIT);
-}
+       WapiHandle_process *process_data;
+       gboolean ret;
 
+       ret = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
+                                                          (gpointer *)&process_data);
+       if (!ret)
+               return NULL;
+       return process_data;
+}
 
 /* Check if a pid is valid - i.e. if a process exists with this pid. */
-static gboolean is_pid_valid (pid_t pid)
+static gboolean
+is_pid_valid (pid_t pid)
 {
        gboolean result = FALSE;
 
@@ -169,7 +172,7 @@ static gboolean is_pid_valid (pid_t pid)
        if (get_team_info ((team_id)pid, &teamInfo) == B_OK)
                result = TRUE;
 #else
-       gchar *dir = g_strdup_printf ("/proc/%d", pid);
+       char *dir = g_strdup_printf ("/proc/%d", pid);
        if (!access (dir, F_OK))
                result = TRUE;
        g_free (dir);
@@ -178,7 +181,8 @@ static gboolean is_pid_valid (pid_t pid)
        return result;
 }
 
-static void process_set_defaults (struct _WapiHandle_process *process_handle)
+static void
+process_set_defaults (WapiHandle_process *process_handle)
 {
        /* These seem to be the defaults on w2k */
        process_handle->min_working_set = 204800;
@@ -233,42 +237,6 @@ utf16_concat (const gunichar2 *first, ...)
        return ret;
 }
 
-#ifdef PLATFORM_MACOSX
-
-/* 0 = no detection; -1 = not 10.5 or higher;  1 = 10.5 or higher */
-static int osx_10_5_or_higher;
-
-static void
-detect_osx_10_5_or_higher (void)
-{
-       struct utsname u;
-       char *p;
-       int v;
-       
-       if (uname (&u) != 0){
-               osx_10_5_or_higher = 1;
-               return;
-       }
-
-       p = u.release;
-       v = atoi (p);
-       
-       if (v < 9)
-               osx_10_5_or_higher = -1;
-       else 
-               osx_10_5_or_higher = 1;
-}
-
-static gboolean
-is_macos_10_5_or_higher (void)
-{
-       if (osx_10_5_or_higher == 0)
-               detect_osx_10_5_or_higher ();
-       
-       return (osx_10_5_or_higher == 1);
-}
-#endif
-
 static const gunichar2 utf16_space_bytes [2] = { 0x20, 0 };
 static const gunichar2 *utf16_space = utf16_space_bytes; 
 static const gunichar2 utf16_quote_bytes [2] = { 0x22, 0 };
@@ -279,7 +247,7 @@ static const gunichar2 *utf16_quote = utf16_quote_bytes;
 void
 print_utf16 (gunichar2 *str)
 {
-       gchar *res;
+       char *res;
 
        res = g_utf16_to_utf8 (str, -1, NULL, NULL, NULL);
        g_print ("%s\n", res);
@@ -288,7 +256,8 @@ print_utf16 (gunichar2 *str)
 #endif
 
 /* Implemented as just a wrapper around CreateProcess () */
-gboolean ShellExecuteEx (WapiShellExecuteInfo *sei)
+gboolean
+ShellExecuteEx (WapiShellExecuteInfo *sei)
 {
        gboolean ret;
        WapiProcessInformation process_info;
@@ -299,13 +268,12 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei)
                 * that
                 */
                SetLastError (ERROR_INVALID_PARAMETER);
-               return (FALSE);
+               return FALSE;
        }
 
-       if (sei->lpFile == NULL) {
+       if (sei->lpFile == NULL)
                /* w2k returns TRUE for this, for some reason. */
-               return (TRUE);
-       }
+               return TRUE;
        
        /* Put both executable and parameters into the second argument
         * to CreateProcess (), so it searches $PATH.  The conversion
@@ -313,9 +281,9 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei)
         * g_strdup_printf () equivalent for gunichar2 :-(
         */
        args = utf16_concat (utf16_quote, sei->lpFile, utf16_quote, sei->lpParameters == NULL ? NULL : utf16_space, sei->lpParameters, NULL);
-       if (args == NULL){
+       if (args == NULL) {
                SetLastError (ERROR_INVALID_DATA);
-               return (FALSE);
+               return FALSE;
        }
        ret = CreateProcess (NULL, args, NULL, NULL, TRUE,
                             CREATE_UNICODE_ENVIRONMENT, NULL,
@@ -346,7 +314,7 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei)
                                handler = g_find_program_in_path ("kfmclient");
                                if (handler == NULL){
                                        handler_utf16 = (gunichar2 *) -1;
-                                       return (FALSE);
+                                       return FALSE;
                                } else {
                                        /* kfmclient needs exec argument */
                                        char *old = handler;
@@ -370,7 +338,7 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei)
                                     sei->lpFile, utf16_quote,
                                     sei->lpParameters == NULL ? NULL : utf16_space,
                                     sei->lpParameters, NULL);
-               if (args == NULL){
+               if (args == NULL) {
                        SetLastError (ERROR_INVALID_DATA);
                        return FALSE;
                }
@@ -378,7 +346,7 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei)
                                     CREATE_UNICODE_ENVIRONMENT, NULL,
                                     sei->lpDirectory, NULL, &process_info);
                g_free (args);
-               if (!ret){
+               if (!ret) {
                        if (GetLastError () != ERROR_OUTOFMEMORY)
                                SetLastError (ERROR_INVALID_DATA);
                        return FALSE;
@@ -388,17 +356,16 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei)
                process_info.hProcess = NULL;
        }
        
-       if (sei->fMask & SEE_MASK_NOCLOSEPROCESS) {
+       if (sei->fMask & SEE_MASK_NOCLOSEPROCESS)
                sei->hProcess = process_info.hProcess;
-       } else {
+       else
                CloseHandle (process_info.hProcess);
-       }
        
-       return (ret);
+       return ret;
 }
 
 static gboolean
-is_managed_binary (const gchar *filename)
+is_managed_binary (const char *filename)
 {
        int original_errno = errno;
 #if defined(HAVE_LARGE_FILE_SUPPORT) && defined(O_LARGEFILE)
@@ -505,17 +472,18 @@ leave:
        return managed;
 }
 
-gboolean CreateProcessWithLogonW (const gunichar2 *username,
-                                 const gunichar2 *domain,
-                                 const gunichar2 *password,
-                                 const guint32 logonFlags,
-                                 const gunichar2 *appname,
-                                 const gunichar2 *cmdline,
-                                 guint32 create_flags,
-                                 gpointer env,
-                                 const gunichar2 *cwd,
-                                 WapiStartupInfo *startup,
-                                 WapiProcessInformation *process_info)
+gboolean
+CreateProcessWithLogonW (const gunichar2 *username,
+                                                const gunichar2 *domain,
+                                                const gunichar2 *password,
+                                                const guint32 logonFlags,
+                                                const gunichar2 *appname,
+                                                const gunichar2 *cmdline,
+                                                guint32 create_flags,
+                                                gpointer env,
+                                                const gunichar2 *cwd,
+                                                WapiStartupInfo *startup,
+                                                WapiProcessInformation *process_info)
 {
        /* FIXME: use user information */
        return CreateProcess (appname, cmdline, NULL, NULL, FALSE, create_flags, env, cwd, startup, process_info);
@@ -535,17 +503,15 @@ is_executable (const char *prog)
 }
 
 static void
-switchDirectorySeparators(gchar *path)
+switch_dir_separators (char *path)
 {
        size_t i, pathLength = strlen(path);
        
        /* Turn all the slashes round the right way, except for \' */
        /* There are probably other characters that need to be excluded as well. */
-       for (i = 0; i < pathLength; i++)
-       {
-               if (path[i] == '\\' && i < pathLength - 1 && path[i+1] != '\'' ) {
+       for (i = 0; i < pathLength; i++) {
+               if (path[i] == '\\' && i < pathLength - 1 && path[i+1] != '\'' )
                        path[i] = '/';
-               }
        }
 }
 
@@ -557,11 +523,12 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                        WapiStartupInfo *startup,
                        WapiProcessInformation *process_info)
 {
-       gchar *cmd=NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL, *dir = NULL, **env_strings = NULL, **argv = NULL;
+       char *cmd = NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL;
+       char *dir = NULL, **env_strings = NULL, **argv = NULL;
        guint32 i, env_count = 0;
        gboolean ret = FALSE;
        gpointer handle;
-       struct _WapiHandle_process process_handle = {0}, *process_handle_data;
+       WapiHandle_process process_handle = {0}, *process_handle_data;
        GError *gerr = NULL;
        int in_fd, out_fd, err_fd;
        pid_t pid;
@@ -570,10 +537,9 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
        int dummy;
        struct MonoProcess *mono_process;
        gboolean fork_failed = FALSE;
-       
-       mono_once (&process_ops_once, process_ops_init);
+
        mono_once (&process_sig_chld_once, process_add_sigchld_handler);
-       
+
        /* appname and cmdline specify the executable and its args:
         *
         * If appname is not NULL, it is the name of the executable.
@@ -610,7 +576,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                        goto free_strings;
                }
 
-               switchDirectorySeparators(cmd);
+               switch_dir_separators(cmd);
        }
        
        if (cmdline != NULL) {
@@ -633,13 +599,13 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                }
 
                /* Turn all the slashes round the right way */
-               switchDirectorySeparators(dir);
+               switch_dir_separators(dir);
        }
        
 
        /* We can't put off locating the executable any longer :-( */
        if (cmd != NULL) {
-               gchar *unquoted;
+               char *unquoted;
                if (g_ascii_isalpha (cmd[0]) && (cmd[1] == ':')) {
                        /* Strip off the drive letter.  I can't
                         * believe that CP/M holdover is still
@@ -684,7 +650,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
 
                args_after_prog = args;
        } else {
-               gchar *token = NULL;
+               char *token = NULL;
                char quote;
                
                /* Dig out the first token from args, taking quotation
@@ -747,7 +713,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                /* Turn all the slashes round the right way. Only for
                 * the prg. name
                 */
-               switchDirectorySeparators(token);
+               switch_dir_separators(token);
 
                if (g_ascii_isalpha (token[0]) && (token[1] == ':')) {
                        /* Strip off the drive letter.  I can't
@@ -770,7 +736,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                                SetLastError (ERROR_FILE_NOT_FOUND);
                                goto free_strings;
                        }
-
                } else {
                        char *curdir = g_get_current_dir ();
 
@@ -846,7 +811,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
        }
 
        if (args_after_prog != NULL && *args_after_prog) {
-               gchar *qprog;
+               char *qprog;
 
                qprog = g_shell_quote (prog);
                full_prog = g_strconcat (qprog, " ", args_after_prog, NULL);
@@ -873,8 +838,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                err_fd = GPOINTER_TO_UINT (GetStdHandle (STD_ERROR_HANDLE));
        }
        
-       g_strlcpy (process_handle.proc_name, prog,
-                  _WAPI_PROC_NAME_MAX_LEN - 1);
+       process_handle.proc_name = g_strdup (prog);
 
        process_set_defaults (&process_handle);
        
@@ -895,7 +859,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
         * environment variables in the new process.  Otherwise the
         * new process inherits the same environment.
         */
-       if (new_environ != NULL) {
+       if (new_environ) {
                gunichar2 *new_environp;
 
                /* Count the number of strings */
@@ -910,7 +874,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                /* +2: one for the process handle value, and the last
                 * one is NULL
                 */
-               env_strings = g_new0 (gchar *, env_count + 2);
+               env_strings = g_new0 (char *, env_count + 2);
                
                /* Copy each environ string into 'strings' turning it
                 * into utf8 (or the requested encoding) at the same
@@ -926,14 +890,13 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                        }
                }
        } else {
-               for (i = 0; environ[i] != NULL; i++) {
+               for (i = 0; environ[i] != NULL; i++)
                        env_count++;
-               }
 
                /* +2: one for the process handle value, and the last
                 * one is NULL
                 */
-               env_strings = g_new0 (gchar *, env_count + 2);
+               env_strings = g_new0 (char *, env_count + 2);
                
                /* Copy each environ string into 'strings' turning it
                 * into utf8 (or the requested encoding) at the same
@@ -945,18 +908,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                        env_count++;
                }
        }
-       /* pass process handle info to the child, so it doesn't have
-        * to do an expensive search over the whole list
-        */
-       if (env_strings != NULL) {
-               struct _WapiHandleUnshared *handle_data;
-               struct _WapiHandle_shared_ref *ref;
-               
-               handle_data = &_WAPI_PRIVATE_HANDLES(GPOINTER_TO_UINT(handle));
-               ref = &handle_data->u.shared;
-               
-               env_strings[env_count] = g_strdup_printf ("_WAPI_PROCESS_HANDLE_OFFSET=%d", ref->offset);
-       }
 
        /* Create a pipe to make sure the child doesn't exit before 
         * we can add the process to the linked list of mono_processes */
@@ -1000,20 +951,17 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                }
                
                /* Close all file descriptors */
-               for (i = getdtablesize () - 1; i > 2; i--) {
+               for (i = wapi_getdtablesize () - 1; i > 2; i--)
                        close (i);
-               }
 
 #ifdef DEBUG_ENABLED
                DEBUG ("%s: exec()ing [%s] in dir [%s]", __func__, cmd,
-                          dir==NULL?".":dir);
-               for (i = 0; argv[i] != NULL; i++) {
+                          dir == NULL?".":dir);
+               for (i = 0; argv[i] != NULL; i++)
                        g_message ("arg %d: [%s]", i, argv[i]);
-               }
                
-               for (i = 0; env_strings[i] != NULL; i++) {
+               for (i = 0; env_strings[i] != NULL; i++)
                        g_message ("env %d: [%s]", i, env_strings[i]);
-               }
 #endif
 
                /* set cwd */
@@ -1030,9 +978,8 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
        }
        /* parent */
        
-       ret = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
-                                  (gpointer *)&process_handle_data);
-       if (ret == FALSE) {
+       process_handle_data = lookup_process_handle (handle);
+       if (!process_handle_data) {
                g_warning ("%s: error looking up process handle %p", __func__,
                           handle);
                _wapi_handle_unref (handle);
@@ -1057,7 +1004,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                _wapi_handle_ref (handle);
                mono_process->handle = handle;
 
-               process_handle_data->self = _wapi_getpid ();
                process_handle_data->mono_process = mono_process;
 
                mono_mutex_lock (&mono_processes_mutex);
@@ -1091,27 +1037,20 @@ cleanup:
        }
 
 free_strings:
-       if (cmd != NULL) {
+       if (cmd)
                g_free (cmd);
-       }
-       if (full_prog != NULL) {
+       if (full_prog)
                g_free (full_prog);
-       }
-       if (prog != NULL) {
+       if (prog)
                g_free (prog);
-       }
-       if (args != NULL) {
+       if (args)
                g_free (args);
-       }
-       if (dir != NULL) {
+       if (dir)
                g_free (dir);
-       }
-       if(env_strings != NULL) {
+       if (env_strings)
                g_strfreev (env_strings);
-       }
-       if (argv != NULL) {
+       if (argv)
                g_strfreev (argv);
-       }
        
        DEBUG ("%s: returning handle %p for pid %d", __func__, handle,
                   pid);
@@ -1119,98 +1058,39 @@ free_strings:
        /* Check if something needs to be cleaned up. */
        mono_processes_cleanup ();
        
-       return(ret);
+       return ret;
 }
                
-static void process_set_name (struct _WapiHandle_process *process_handle)
+static void
+process_set_name (WapiHandle_process *process_handle)
 {
-       gchar *progname, *utf8_progname, *slash;
+       char *progname, *utf8_progname, *slash;
        
-       progname=g_get_prgname ();
-       utf8_progname=mono_utf8_from_external (progname);
+       progname = g_get_prgname ();
+       utf8_progname = mono_utf8_from_external (progname);
 
        DEBUG ("%s: using [%s] as prog name", __func__, progname);
 
-       if(utf8_progname!=NULL) {
-               slash=strrchr (utf8_progname, '/');
-               if(slash!=NULL) {
-                       g_strlcpy (process_handle->proc_name, slash+1,
-                                  _WAPI_PROC_NAME_MAX_LEN - 1);
-               } else {
-                       g_strlcpy (process_handle->proc_name, utf8_progname,
-                                  _WAPI_PROC_NAME_MAX_LEN - 1);
-               }
-
+       if (utf8_progname) {
+               slash = strrchr (utf8_progname, '/');
+               if (slash)
+                       process_handle->proc_name = g_strdup (slash+1);
+               else
+                       process_handle->proc_name = g_strdup (utf8_progname);
                g_free (utf8_progname);
        }
 }
 
-extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime);
-
-#if !GLIB_CHECK_VERSION (2,4,0)
-#define g_setenv(a,b,c) setenv(a,b,c)
-#define g_unsetenv(a) unsetenv(a)
-#endif
-
-static void process_set_current (void)
+void
+wapi_processes_init (void)
 {
        pid_t pid = _wapi_getpid ();
-       const char *handle_env;
-       struct _WapiHandle_process process_handle = {0};
-       
-       mono_once (&process_ops_once, process_ops_init);
-       
-       handle_env = g_getenv ("_WAPI_PROCESS_HANDLE_OFFSET");
-       g_unsetenv ("_WAPI_PROCESS_HANDLE_OFFSET");
-       
-       if (handle_env != NULL) {
-               struct _WapiHandle_process *process_handlep;
-               gchar *procname = NULL;
-               gboolean ok;
-               
-               current_process = _wapi_handle_new_from_offset (WAPI_HANDLE_PROCESS, atoi (handle_env), TRUE);
-               
-               DEBUG ("%s: Found my process handle: %p (offset %d 0x%x)",
-                          __func__, current_process, atoi (handle_env),
-                          atoi (handle_env));
-
-               ok = _wapi_lookup_handle (current_process, WAPI_HANDLE_PROCESS,
-                                         (gpointer *)&process_handlep);
-               if (ok) {
-                       /* This test will probably break on linuxthreads, but
-                        * that should be ancient history on all distros we
-                        * care about by now
-                        */
-                       if (process_handlep->id == pid) {
-                               procname = process_handlep->proc_name;
-                               if (!strcmp (procname, "mono")) {
-                                       /* Set a better process name */
-                                       DEBUG ("%s: Setting better process name", __func__);
-                                       
-                                       process_set_name (process_handlep);
-                               } else {
-                                       DEBUG ("%s: Leaving process name: %s", __func__, procname);
-                               }
-
-                               return;
-                       }
-
-                       /* Wrong pid, so drop this handle and fall through to
-                        * create a new one
-                        */
-                       _wapi_handle_unref (current_process);
-               }
-       }
-
-       /* We get here if the handle wasn't specified in the
-        * environment, or if the process ID was wrong, or if the
-        * handle lookup failed (eg if the parent process forked and
-        * quit immediately, and deleted the shared data before the
-        * child got a chance to attach it.)
-        */
-
-       DEBUG ("%s: Need to create my own process handle", __func__);
+       WapiHandle_process process_handle = {0};
 
+       _wapi_handle_register_capabilities (WAPI_HANDLE_PROCESS,
+                                           WAPI_HANDLE_CAP_WAIT |
+                                           WAPI_HANDLE_CAP_SPECIAL_WAIT);
+       
        process_handle.id = pid;
 
        process_set_defaults (&process_handle);
@@ -1218,273 +1098,60 @@ static void process_set_current (void)
 
        current_process = _wapi_handle_new (WAPI_HANDLE_PROCESS,
                                            &process_handle);
-       if (current_process == _WAPI_HANDLE_INVALID) {
-               g_warning ("%s: error creating process handle", __func__);
-               return;
-       }
+       g_assert (current_process);
 }
 
-gpointer _wapi_process_duplicate ()
+gpointer
+_wapi_process_duplicate (void)
 {
-       mono_once (&process_current_once, process_set_current);
-       
        _wapi_handle_ref (current_process);
        
-       return(current_process);
+       return current_process;
 }
 
 /* Returns a pseudo handle that doesn't need to be closed afterwards */
-gpointer GetCurrentProcess (void)
+gpointer
+GetCurrentProcess (void)
 {
-       mono_once (&process_current_once, process_set_current);
-               
-       return(_WAPI_PROCESS_CURRENT);
+       return _WAPI_PROCESS_CURRENT;
 }
 
-guint32 GetProcessId (gpointer handle)
+guint32
+GetProcessId (gpointer handle)
 {
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
 
-       if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
                /* This is a pseudo handle */
-               return(GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
-       }
+               return WAPI_HANDLE_TO_PID (handle);
        
-       ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
-                                 (gpointer *)&process_handle);
-       if (ok == FALSE) {
+       process_handle = lookup_process_handle (handle);
+       if (!process_handle) {
                SetLastError (ERROR_INVALID_HANDLE);
-               return (0);
+               return 0;
        }
        
-       return (process_handle->id);
+       return process_handle->id;
 }
 
-guint32 GetCurrentProcessId (void)
+static gboolean
+process_open_compare (gpointer handle, gpointer user_data)
 {
-       mono_once (&process_current_once, process_set_current);
-               
-       return (GetProcessId (current_process));
-}
+       pid_t wanted_pid;
+       WapiHandle_process *process_handle;
+       pid_t checking_pid;
 
-/* Returns the process id as a convenience to the functions that call this */
-static pid_t signal_process_if_gone (gpointer handle)
-{
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       g_assert (!WAPI_IS_PSEUDO_PROCESS_HANDLE (handle));
        
-       g_assert ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) != _WAPI_PROCESS_UNHANDLED);
-       
-       /* Make sure the process is signalled if it has exited - if
-        * the parent process didn't wait for it then it won't be
-        */
-       ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
-                                 (gpointer *)&process_handle);
-       if (ok == FALSE) {
-               /* It's possible that the handle has vanished during
-                * the _wapi_search_handle before it gets here, so
-                * don't spam the console with warnings.
-                */
-/*             g_warning ("%s: error looking up process handle %p",
-  __func__, handle);*/
-               
-               return (0);
-       }
+       process_handle = lookup_process_handle (handle);
+       g_assert (process_handle);
        
        DEBUG ("%s: looking at process %d", __func__, process_handle->id);
 
-       if (kill (process_handle->id, 0) == -1 &&
-           (errno == ESRCH ||
-            errno == EPERM)) {
-               /* The process is dead, (EPERM tells us a new process
-                * has that ID, but as it's owned by someone else it
-                * can't be the one listed in our shared memory file)
-                */
-               _wapi_shared_handle_set_signal_state (handle, TRUE);
-       }
-
-       return (process_handle->id);
-}
-
-#ifdef UNUSED_CODE
-static gboolean process_enum (gpointer handle, gpointer user_data)
-{
-       GArray *processes=user_data;
-       pid_t pid = signal_process_if_gone (handle);
-       int i;
-       
-       if (pid == 0) {
-               return (FALSE);
-       }
-       
-       /* Ignore processes that have already exited (ie they are signalled) */
-       if (_wapi_handle_issignalled (handle) == FALSE) {
-               DEBUG ("%s: process %d added to array", __func__, pid);
-
-               /* This ensures that duplicates aren't returned (see
-                * the comment above _wapi_search_handle () for why
-                * it's needed
-                */
-               for (i = 0; i < processes->len; i++) {
-                       if (g_array_index (processes, pid_t, i) == pid) {
-                               /* We've already got this one, return
-                                * FALSE to keep searching
-                                */
-                               return (FALSE);
-                       }
-               }
-               
-               g_array_append_val (processes, pid);
-       }
-       
-       /* Return false to keep searching */
-       return(FALSE);
-}
-#endif /* UNUSED_CODE */
-
-#if defined(PLATFORM_MACOSX) || defined(__OpenBSD__)
-
-gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed)
-{
-       guint32 count, fit, i, j;
-       gint32 err;
-       gboolean done;
-       size_t proclength, size;
-#if defined(__OpenBSD__)
-       struct kinfo_proc *result;
-       int name[6];
-       name[0] = CTL_KERN;
-       name[1] = KERN_PROC;
-       name[2] = KERN_PROC_ALL;
-       name[3] = 0;
-       name[4] = sizeof(struct kinfo_proc);
-       name[5] = 0;
-#else
-       struct kinfo_proc *result;
-       static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
-#endif
-
-       mono_once (&process_current_once, process_set_current);
-
-       result = NULL;
-       done = FALSE;
-
-       do {
-               proclength = 0;
-#if defined(__OpenBSD__)
-               size = (sizeof(name) / sizeof(*name));
-#else
-               size = (sizeof(name) / sizeof(*name)) - 1;
-#endif
-               err = sysctl ((int *)name, size, NULL, &proclength, NULL, 0);
-
-               if (err == 0) {
-                       result = malloc (proclength);
-
-                       if (result == NULL)
-                               return FALSE;
+       checking_pid = process_handle->id;
 
-#if defined(__OpenBSD__)
-                       name[5] = (int)(proclength / sizeof(struct kinfo_proc));
-#endif
-
-                       err = sysctl ((int *) name, size, result, &proclength, NULL, 0);
-
-                       if (err == 0) 
-                               done = TRUE;
-                       else {
-                               free (result);
-                               result = NULL;
-                       }
-               }
-       } while (err == 0 && !done);
-       
-       if (err != 0) {
-               if (result != NULL) {
-                       free (result);
-                       result = NULL;
-               }
-               return(FALSE);
-       }       
-
-       count = proclength / sizeof(struct kinfo_proc);
-
-       fit = len / sizeof(guint32);
-       for (i = 0, j = 0; j< fit && i < count; i++) {
-#if defined(__OpenBSD__)
-               pids [j++] = result [i].p_pid;
-#else
-               if (result[i].kp_proc.p_pid > 0) /* Pid 0 not supported */
-                       pids [j++] = result [i].kp_proc.p_pid;
-#endif
-       }
-       free (result);
-       result = NULL;
-       *needed = j * sizeof(guint32);
-       
-       return(TRUE);
-}
-#elif defined(__HAIKU__)
-
-gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed)
-{
-       guint32 fit, i = 0;
-       int32 cookie = 0;
-       team_info teamInfo;
-
-       mono_once (&process_current_once, process_set_current);
-
-       fit = len / sizeof (guint32);
-       while (get_next_team_info (&cookie, &teamInfo) == B_OK && i < fit) {
-               pids [i++] = teamInfo.team;
-       }
-       *needed = i * sizeof (guint32);
-
-       return TRUE;
-}
-#else
-gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed)
-{
-       guint32 fit, i;
-       DIR *dir;
-       struct dirent *entry;
-       
-       mono_once (&process_current_once, process_set_current);
-
-       dir = opendir ("/proc");
-       if (dir == NULL) {
-               return(FALSE);
-       }
-
-       i = 0;
-       fit = len / sizeof (guint32);
-       while(i < fit && (entry = readdir (dir)) != NULL) {
-               pid_t pid;
-               char *endptr;
-
-               if (!isdigit (entry->d_name[0]))
-                       continue;
-
-               pid = (pid_t) strtol (entry->d_name, &endptr, 10);
-               if (*endptr == '\0')
-                       pids [i++] = (guint32) pid;
-       }
-       closedir (dir);
-       *needed = i * sizeof(guint32);
-       
-       return(TRUE);
-}
-#endif
-
-static gboolean process_open_compare (gpointer handle, gpointer user_data)
-{
-       pid_t wanted_pid;
-       pid_t checking_pid = signal_process_if_gone (handle);
-
-       if (checking_pid == 0) {
-               return(FALSE);
-       }
+       if (checking_pid == 0)
+               return FALSE;
        
        wanted_pid = GPOINTER_TO_UINT (user_data);
 
@@ -1493,37 +1160,34 @@ static gboolean process_open_compare (gpointer handle, gpointer user_data)
         * unsignalled
         */
        if (checking_pid == wanted_pid &&
-           _wapi_handle_issignalled (handle) == FALSE) {
+           !_wapi_handle_issignalled (handle)) {
                /* If the handle is blown away in the window between
                 * returning TRUE here and _wapi_search_handle pinging
                 * the timestamp, the search will continue
                 */
-               return(TRUE);
+               return TRUE;
        } else {
-               return(FALSE);
+               return FALSE;
        }
 }
 
-gboolean CloseProcess(gpointer handle)
+gboolean
+CloseProcess (gpointer handle)
 {
-       if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
-               /* This is a pseudo handle */
-               return(TRUE);
-       }
-
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
+               return TRUE;
        return CloseHandle (handle);
 }
 
 /*
  * The caller owns the returned handle and must call CloseProcess () on it to clean it up.
  */
-gpointer OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 pid)
+gpointer
+OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 pid)
 {
        /* Find the process handle that corresponds to pid */
        gpointer handle = NULL;
        
-       mono_once (&process_current_once, process_set_current);
-
        DEBUG ("%s: looking for process %d", __func__, pid);
 
        handle = _wapi_search_handle (WAPI_HANDLE_PROCESS,
@@ -1534,34 +1198,31 @@ gpointer OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_
                        /* Return a pseudo handle for processes we
                         * don't have handles for
                         */
-                       return GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + pid);
+                       return WAPI_PID_TO_HANDLE (pid);
                } else {
                        DEBUG ("%s: Can't find pid %d", __func__, pid);
 
                        SetLastError (ERROR_PROC_NOT_FOUND);
        
-                       return(NULL);
+                       return NULL;
                }
        }
 
        /* _wapi_search_handle () already added a ref */
-       return(handle);
+       return handle;
 }
 
-gboolean GetExitCodeProcess (gpointer process, guint32 *code)
+gboolean
+GetExitCodeProcess (gpointer process, guint32 *code)
 {
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
        guint32 pid = -1;
        
-       mono_once (&process_current_once, process_set_current);
-
-       if(code==NULL) {
-               return(FALSE);
-       }
+       if (!code)
+               return FALSE;
        
-       pid = GPOINTER_TO_UINT (process) - _WAPI_PROCESS_UNHANDLED;
-       if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
+               pid = WAPI_HANDLE_TO_PID (process);
                /* This is a pseudo handle, so we don't know what the
                 * exit code was, but we can check whether it's alive or not
                 */
@@ -1573,12 +1234,11 @@ gboolean GetExitCodeProcess (gpointer process, guint32 *code)
                }
        }
 
-       ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
-                               (gpointer *)&process_handle);
-       if(ok==FALSE) {
+       process_handle = lookup_process_handle (process);
+       if (!process_handle) {
                DEBUG ("%s: Can't find process %p", __func__, process);
                
-               return(FALSE);
+               return FALSE;
        }
        
        /* A process handle is only signalled if the process has exited
@@ -1589,53 +1249,46 @@ gboolean GetExitCodeProcess (gpointer process, guint32 *code)
         */
        process_wait (process, 0, TRUE);
        
-       if (_wapi_handle_issignalled (process) == TRUE) {
+       if (_wapi_handle_issignalled (process))
                *code = process_handle->exitstatus;
-       } else {
+       else
                *code = STILL_ACTIVE;
-       }
        
-       return(TRUE);
+       return TRUE;
 }
 
-gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time,
-                         WapiFileTime *exit_time, WapiFileTime *kernel_time,
-                         WapiFileTime *user_time)
+gboolean
+GetProcessTimes (gpointer process, WapiFileTime *create_time,
+                                WapiFileTime *exit_time, WapiFileTime *kernel_time,
+                                WapiFileTime *user_time)
 {
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
        gboolean ku_times_set = FALSE;
        
-       mono_once (&process_current_once, process_set_current);
-
-       if(create_time==NULL || exit_time==NULL || kernel_time==NULL ||
-          user_time==NULL) {
+       if (create_time == NULL || exit_time == NULL || kernel_time == NULL ||
+               user_time == NULL)
                /* Not sure if w32 allows NULLs here or not */
-               return(FALSE);
-       }
+               return FALSE;
        
-       if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
                /* This is a pseudo handle, so just fail for now
                 */
-               return(FALSE);
-       }
+               return FALSE;
        
-       ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
-                               (gpointer *)&process_handle);
-       if(ok==FALSE) {
+       process_handle = lookup_process_handle (process);
+       if (!process_handle) {
                DEBUG ("%s: Can't find process %p", __func__, process);
                
-               return(FALSE);
+               return FALSE;
        }
        
-       *create_time=process_handle->create_time;
+       *create_time = process_handle->create_time;
 
        /* A process handle is only signalled if the process has
         * exited.  Otherwise exit_time isn't set
         */
-       if(_wapi_handle_issignalled (process)==TRUE) {
-               *exit_time=process_handle->exit_time;
-       }
+       if (_wapi_handle_issignalled (process))
+               *exit_time = process_handle->exit_time;
 
 #ifdef HAVE_GETRUSAGE
        if (process_handle->id == getpid ()) {
@@ -1655,18 +1308,18 @@ gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time,
                memset (user_time, 0, sizeof (WapiFileTime));
        }
 
-       return(TRUE);
+       return TRUE;
 }
 
 typedef struct
 {
        gpointer address_start;
        gpointer address_end;
-       gchar *perms;
+       char *perms;
        gpointer address_offset;
        dev_t device;
        ino_t inode;
-       gchar *filename;
+       char *filename;
 } WapiProcModule;
 
 static void free_procmodule (WapiProcModule *mod)
@@ -1843,9 +1496,9 @@ static GSList *load_modules (FILE *fp)
 {
        GSList *ret = NULL;
        WapiProcModule *mod;
-       gchar buf[MAXPATHLEN + 1], *p, *endp;
-       gchar *start_start, *end_start, *prot_start, *offset_start;
-       gchar *maj_dev_start, *min_dev_start, *inode_start, prot_buf[5];
+       char buf[MAXPATHLEN + 1], *p, *endp;
+       char *start_start, *end_start, *prot_start, *offset_start;
+       char *maj_dev_start, *min_dev_start, *inode_start, prot_buf[5];
        gpointer address_start, address_end, address_offset;
        guint32 maj_dev, min_dev;
        ino_t inode;
@@ -1959,7 +1612,7 @@ static GSList *load_modules (FILE *fp)
 }
 #endif
 
-static gboolean match_procname_to_modulename (gchar *procname, gchar *modulename)
+static gboolean match_procname_to_modulename (char *procname, char *modulename)
 {
        char* lastsep = NULL;
        char* lastsep2 = NULL;
@@ -2006,13 +1659,13 @@ static FILE *
 open_process_map (int pid, const char *mode)
 {
        FILE *fp = NULL;
-       const gchar *proc_path[] = {
+       const char *proc_path[] = {
                "/proc/%d/maps",        /* GNU/Linux */
                "/proc/%d/map",         /* FreeBSD */
                NULL
        };
        int i;
-       gchar *filename;
+       char *filename;
 
        for (i = 0; fp == NULL && proc_path [i]; i++) {
                filename = g_strdup_printf (proc_path[i], pid);
@@ -2027,8 +1680,7 @@ open_process_map (int pid, const char *mode)
 gboolean EnumProcessModules (gpointer process, gpointer *modules,
                             guint32 size, guint32 *needed)
 {
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
 #if !defined(__OpenBSD__) && !defined(PLATFORM_MACOSX)
        FILE *fp;
 #endif
@@ -2037,7 +1689,7 @@ gboolean EnumProcessModules (gpointer process, gpointer *modules,
        guint32 count, avail = size / sizeof(gpointer);
        int i;
        pid_t pid;
-       gchar *proc_name = NULL;
+       char *proc_name = NULL;
        
        /* Store modules in an array of pointers (main module as
         * modules[0]), using the load address for each module as a
@@ -2048,72 +1700,76 @@ gboolean EnumProcessModules (gpointer process, gpointer *modules,
         * implement /dev/kmem reading or whatever other horrid
         * technique is needed.
         */
-       if (size < sizeof(gpointer)) {
-               return(FALSE);
-       }
+       if (size < sizeof(gpointer))
+               return FALSE;
 
-       if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
-               /* This is a pseudo handle */
-               pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
+               pid = WAPI_HANDLE_TO_PID (process);
        } else {
-               ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
-                                         (gpointer *)&process_handle);
-               if (ok == FALSE) {
+               process_handle = lookup_process_handle (process);
+               if (!process_handle) {
                        DEBUG ("%s: Can't find process %p", __func__, process);
                
-                       return(FALSE);
+                       return FALSE;
                }
                pid = process_handle->id;
                proc_name = process_handle->proc_name;
        }
        
 #if defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__HAIKU__)
-       {
-               mods = load_modules ();
+       mods = load_modules ();
+       if (!proc_name) {
+               modules[0] = NULL;
+               *needed = sizeof(gpointer);
+               return TRUE;
+       }
 #else
-       if ((fp = open_process_map (pid, "r")) == NULL) {
+       fp = open_process_map (pid, "r");
+       if (!fp) {
                /* No /proc/<pid>/maps so just return the main module
                 * shortcut for now
                 */
                modules[0] = NULL;
                *needed = sizeof(gpointer);
-       } else {
-               mods = load_modules (fp);
-               fclose (fp);
+               return TRUE;
+       }
+       mods = load_modules (fp);
+       fclose (fp);
 #endif
-               count = g_slist_length (mods);
+       count = g_slist_length (mods);
                
-               /* count + 1 to leave slot 0 for the main module */
-               *needed = sizeof(gpointer) * (count + 1);
-
-               /* Use the NULL shortcut, as the first line in
-                * /proc/<pid>/maps isn't the executable, and we need
-                * that first in the returned list. Check the module name 
-                * to see if it ends with the proc name and substitute 
-                * the first entry with it.  FIXME if this turns out to 
-                * be a problem.
-                */
-               modules[0] = NULL;
-               for (i = 0; i < (avail - 1) && i < count; i++) {
-                       module = (WapiProcModule *)g_slist_nth_data (mods, i);
-                       if (modules[0] != NULL)
-                               modules[i] = module->address_start;
-                       else if (match_procname_to_modulename (proc_name, module->filename))
-                               modules[0] = module->address_start;
-                       else
-                               modules[i + 1] = module->address_start;
-               }
+       /* count + 1 to leave slot 0 for the main module */
+       *needed = sizeof(gpointer) * (count + 1);
+
+       /*
+        * Use the NULL shortcut, as the first line in
+        * /proc/<pid>/maps isn't the executable, and we need
+        * that first in the returned list. Check the module name 
+        * to see if it ends with the proc name and substitute 
+        * the first entry with it.  FIXME if this turns out to 
+        * be a problem.
+        */
+       modules[0] = NULL;
+       for (i = 0; i < (avail - 1) && i < count; i++) {
+               module = (WapiProcModule *)g_slist_nth_data (mods, i);
+               if (modules[0] != NULL)
+                       modules[i] = module->address_start;
+               else if (match_procname_to_modulename (proc_name, module->filename))
+                       modules[0] = module->address_start;
+               else
+                       modules[i + 1] = module->address_start;
+       }
                
-               for (i = 0; i < count; i++) {
-                       free_procmodule (g_slist_nth_data (mods, i));
-               }
-               g_slist_free (mods);
+       for (i = 0; i < count; i++) {
+               free_procmodule (g_slist_nth_data (mods, i));
        }
+       g_slist_free (mods);
 
-       return(TRUE);
+       return TRUE;
 }
 
-static gchar *get_process_name_from_proc (pid_t pid)
+static char *
+get_process_name_from_proc (pid_t pid)
 {
 #if defined(__OpenBSD__)
        int mib [6];
@@ -2127,10 +1783,10 @@ static gchar *get_process_name_from_proc (pid_t pid)
 #endif
 #else
        FILE *fp;
-       gchar *filename = NULL;
+       char *filename = NULL;
 #endif
-       gchar buf[256];
-       gchar *ret = NULL;
+       char buf[256];
+       char *ret = NULL;
 
 #if defined(PLATFORM_SOLARIS)
        filename = g_strdup_printf ("/proc/%d/psinfo", pid);
@@ -2239,7 +1895,7 @@ retry:
        filename = g_strdup_printf ("/proc/%d/stat", pid);
        if ((fp = fopen (filename, "r")) != NULL) {
                if (fgets (buf, 256, fp) != NULL) {
-                       gchar *start, *end;
+                       char *start, *end;
                        
                        start = strchr (buf, '(');
                        if (start != NULL) {
@@ -2266,11 +1922,11 @@ retry:
  *   Return the full path of the executable of the process PID, or NULL if it cannot be determined.
  * Returns malloc-ed memory.
  */
-gchar*
+char*
 wapi_process_get_path (pid_t pid)
 {
 #if defined(PLATFORM_MACOSX) && !defined(__mono_ppc__) && defined(TARGET_OSX)
-       gchar buf [PROC_PIDPATHINFO_MAXSIZE];
+       char buf [PROC_PIDPATHINFO_MAXSIZE];
        int res;
 
        res = proc_pidpath (pid, buf, sizeof (buf));
@@ -2296,15 +1952,15 @@ wapi_process_set_cli_launcher (char *path)
        cli_launcher = path ? g_strdup (path) : NULL;
 }
 
-static guint32 get_module_name (gpointer process, gpointer module,
-                               gunichar2 *basename, guint32 size,
-                               gboolean base)
+static guint32
+get_module_name (gpointer process, gpointer module,
+                                gunichar2 *basename, guint32 size,
+                                gboolean base)
 {
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
        pid_t pid;
        gunichar2 *procname;
-       gchar *procname_ext = NULL;
+       char *procname_ext = NULL;
        glong len;
        gsize bytes;
 #if !defined(__OpenBSD__) && !defined(PLATFORM_MACOSX)
@@ -2314,31 +1970,27 @@ static guint32 get_module_name (gpointer process, gpointer module,
        WapiProcModule *found_module;
        guint32 count;
        int i;
-       gchar *proc_name = NULL;
+       char *proc_name = NULL;
        
-       mono_once (&process_current_once, process_set_current);
-
        DEBUG ("%s: Getting module base name, process handle %p module %p",
                   __func__, process, module);
 
-       size = size*sizeof(gunichar2); /* adjust for unicode characters */
+       size = size * sizeof (gunichar2); /* adjust for unicode characters */
 
-       if (basename == NULL || size == 0) {
-               return(0);
-       }
+       if (basename == NULL || size == 0)
+               return 0;
        
-       if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
                /* This is a pseudo handle */
-               pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
+               pid = (pid_t)WAPI_HANDLE_TO_PID (process);
                proc_name = get_process_name_from_proc (pid);
        } else {
-               ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
-                                         (gpointer *)&process_handle);
-               if (ok == FALSE) {
+               process_handle = lookup_process_handle (process);
+               if (!process_handle) {
                        DEBUG ("%s: Can't find process %p", __func__,
                                   process);
                        
-                       return(0);
+                       return 0;
                }
                pid = process_handle->id;
                proc_name = g_strdup (process_handle->proc_name);
@@ -2346,10 +1998,10 @@ static guint32 get_module_name (gpointer process, gpointer module,
 
        /* Look up the address in /proc/<pid>/maps */
 #if defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__HAIKU__)
-       {
-               mods = load_modules ();
+       mods = load_modules ();
 #else
-       if ((fp = open_process_map (pid, "r")) == NULL) {
+       fp = open_process_map (pid, "r");
+       if (fp == NULL) {
                if (errno == EACCES && module == NULL && base == TRUE) {
                        procname_ext = get_process_name_from_proc (pid);
                } else {
@@ -2357,47 +2009,45 @@ static guint32 get_module_name (gpointer process, gpointer module,
                         * for now
                         */
                        g_free (proc_name);
-                       return(0);
+                       return 0;
                }
        } else {
                mods = load_modules (fp);
                fclose (fp);
+       }
 #endif
-               count = g_slist_length (mods);
-
-               /* If module != NULL compare the address.
-                * If module == NULL we are looking for the main module.
-                * The best we can do for now check it the module name end with the process name.
-                */
-               for (i = 0; i < count; i++) {
-                       found_module = (WapiProcModule *)g_slist_nth_data (mods, i);
-                       if (procname_ext == NULL &&
-                           ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||    
-                            (module != NULL && found_module->address_start == module))) {
-                               if (base) {
-                                       procname_ext = g_path_get_basename (found_module->filename);
-                               } else {
-                                       procname_ext = g_strdup (found_module->filename);
-                               }
-                       }
+       count = g_slist_length (mods);
 
-                       free_procmodule (found_module);
+       /* If module != NULL compare the address.
+        * If module == NULL we are looking for the main module.
+        * The best we can do for now check it the module name end with the process name.
+        */
+       for (i = 0; i < count; i++) {
+               found_module = (WapiProcModule *)g_slist_nth_data (mods, i);
+               if (procname_ext == NULL &&
+                       ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
+                        (module != NULL && found_module->address_start == module))) {
+                       if (base)
+                               procname_ext = g_path_get_basename (found_module->filename);
+                       else
+                               procname_ext = g_strdup (found_module->filename);
                }
 
-               if (procname_ext == NULL)
-               {
-                       /* If it's *still* null, we might have hit the
-                        * case where reading /proc/$pid/maps gives an
-                        * empty file for this user.
-                        */
-                       procname_ext = get_process_name_from_proc (pid);
-               }
+               free_procmodule (found_module);
+       }
 
-               g_slist_free (mods);
-               g_free (proc_name);
+       if (procname_ext == NULL) {
+               /* If it's *still* null, we might have hit the
+                * case where reading /proc/$pid/maps gives an
+                * empty file for this user.
+                */
+               procname_ext = get_process_name_from_proc (pid);
        }
 
-       if (procname_ext != NULL) {
+       g_slist_free (mods);
+       g_free (proc_name);
+
+       if (procname_ext) {
                DEBUG ("%s: Process name is [%s]", __func__,
                           procname_ext);
 
@@ -2405,7 +2055,7 @@ static guint32 get_module_name (gpointer process, gpointer module,
                if (procname == NULL) {
                        /* bugger */
                        g_free (procname_ext);
-                       return(0);
+                       return 0;
                }
                
                len = (bytes / 2);
@@ -2427,29 +2077,31 @@ static guint32 get_module_name (gpointer process, gpointer module,
                g_free (procname);
                g_free (procname_ext);
                
-               return(len);
+               return len;
        }
        
-       return(0);
+       return 0;
 }
 
-guint32 GetModuleBaseName (gpointer process, gpointer module,
-                          gunichar2 *basename, guint32 size)
+guint32
+GetModuleBaseName (gpointer process, gpointer module,
+                                  gunichar2 *basename, guint32 size)
 {
-       return(get_module_name (process, module, basename, size, TRUE));
+       return get_module_name (process, module, basename, size, TRUE);
 }
 
-guint32 GetModuleFileNameEx (gpointer process, gpointer module,
-                            gunichar2 *filename, guint32 size)
+guint32
+GetModuleFileNameEx (gpointer process, gpointer module,
+                                        gunichar2 *filename, guint32 size)
 {
-       return(get_module_name (process, module, filename, size, FALSE));
+       return get_module_name (process, module, filename, size, FALSE);
 }
 
-gboolean GetModuleInformation (gpointer process, gpointer module,
-                              WapiModuleInfo *modinfo, guint32 size)
+gboolean
+GetModuleInformation (gpointer process, gpointer module,
+                                         WapiModuleInfo *modinfo, guint32 size)
 {
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
        pid_t pid;
 #if !defined(__OpenBSD__) && !defined(PLATFORM_MACOSX)
        FILE *fp;
@@ -2459,37 +2111,31 @@ gboolean GetModuleInformation (gpointer process, gpointer module,
        guint32 count;
        int i;
        gboolean ret = FALSE;
-       gchar *proc_name = NULL;
-       
-       mono_once (&process_current_once, process_set_current);
+       char *proc_name = NULL;
        
        DEBUG ("%s: Getting module info, process handle %p module %p",
                   __func__, process, module);
 
-       if (modinfo == NULL || size < sizeof(WapiModuleInfo)) {
-               return(FALSE);
-       }
+       if (modinfo == NULL || size < sizeof (WapiModuleInfo))
+               return FALSE;
        
-       if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
-               /* This is a pseudo handle */
-               pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
+               pid = (pid_t)WAPI_HANDLE_TO_PID (process);
                proc_name = get_process_name_from_proc (pid);
        } else {
-               ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
-                                         (gpointer *)&process_handle);
-               if (ok == FALSE) {
+               process_handle = lookup_process_handle (process);
+               if (!process_handle) {
                        DEBUG ("%s: Can't find process %p", __func__,
                                   process);
                        
-                       return(FALSE);
+                       return FALSE;
                }
                pid = process_handle->id;
                proc_name = g_strdup (process_handle->proc_name);
        }
 
 #if defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__HAIKU__)
-       {
-               mods = load_modules ();
+       mods = load_modules ();
 #else
        /* Look up the address in /proc/<pid>/maps */
        if ((fp = open_process_map (pid, "r")) == NULL) {
@@ -2497,22 +2143,22 @@ gboolean GetModuleInformation (gpointer process, gpointer module,
                 * for now
                 */
                g_free (proc_name);
-               return(FALSE);
-       } else {
-               mods = load_modules (fp);
-               fclose (fp);
+               return FALSE;
+       }
+       mods = load_modules (fp);
+       fclose (fp);
 #endif
-               count = g_slist_length (mods);
+       count = g_slist_length (mods);
 
-               /* If module != NULL compare the address.
-                * If module == NULL we are looking for the main module.
-                * The best we can do for now check it the module name end with the process name.
-                */
-               for (i = 0; i < count; i++) {
+       /* If module != NULL compare the address.
+        * If module == NULL we are looking for the main module.
+        * The best we can do for now check it the module name end with the process name.
+        */
+       for (i = 0; i < count; i++) {
                        found_module = (WapiProcModule *)g_slist_nth_data (mods, i);
-                       if ( ret == FALSE &&
-                            ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
-                             (module != NULL && found_module->address_start == module))) {
+                       if (ret == FALSE &&
+                               ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
+                                (module != NULL && found_module->address_start == module))) {
                                modinfo->lpBaseOfDll = found_module->address_start;
                                modinfo->SizeOfImage = (gsize)(found_module->address_end) - (gsize)(found_module->address_start);
                                modinfo->EntryPoint = found_module->address_offset;
@@ -2520,94 +2166,79 @@ gboolean GetModuleInformation (gpointer process, gpointer module,
                        }
 
                        free_procmodule (found_module);
-               }
-
-               g_slist_free (mods);
-               g_free (proc_name);
        }
 
-       return(ret);
+       g_slist_free (mods);
+       g_free (proc_name);
+
+       return ret;
 }
 
-gboolean GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max)
+gboolean
+GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max)
 {
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
        
-       mono_once (&process_current_once, process_set_current);
-
-       if(min==NULL || max==NULL) {
+       if (min == NULL || max == NULL)
                /* Not sure if w32 allows NULLs here or not */
-               return(FALSE);
-       }
+               return FALSE;
        
-       if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
-               /* This is a pseudo handle, so just fail for now
-                */
-               return(FALSE);
-       }
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
+               /* This is a pseudo handle, so just fail for now */
+               return FALSE;
        
-       ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
-                               (gpointer *)&process_handle);
-       if(ok==FALSE) {
+       process_handle = lookup_process_handle (process);
+       if (!process_handle) {
                DEBUG ("%s: Can't find process %p", __func__, process);
                
-               return(FALSE);
+               return FALSE;
        }
 
-       *min=process_handle->min_working_set;
-       *max=process_handle->max_working_set;
+       *min = process_handle->min_working_set;
+       *max = process_handle->max_working_set;
        
-       return(TRUE);
+       return TRUE;
 }
 
-gboolean SetProcessWorkingSetSize (gpointer process, size_t min, size_t max)
+gboolean
+SetProcessWorkingSetSize (gpointer process, size_t min, size_t max)
 {
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
 
-       mono_once (&process_current_once, process_set_current);
-       
-       if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
                /* This is a pseudo handle, so just fail for now
                 */
-               return(FALSE);
-       }
+               return FALSE;
 
-       ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
-                               (gpointer *)&process_handle);
-       if(ok==FALSE) {
+       process_handle = lookup_process_handle (process);
+       if (!process_handle) {
                DEBUG ("%s: Can't find process %p", __func__, process);
                
-               return(FALSE);
+               return FALSE;
        }
 
-       process_handle->min_working_set=min;
-       process_handle->max_working_set=max;
+       process_handle->min_working_set = min;
+       process_handle->max_working_set = max;
        
-       return(TRUE);
+       return TRUE;
 }
 
 
 gboolean
 TerminateProcess (gpointer process, gint32 exitCode)
 {
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
        int signo;
        int ret;
        pid_t pid;
        
-       if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
                /* This is a pseudo handle */
-               pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
+               pid = (pid_t)WAPI_HANDLE_TO_PID (process);
        } else {
-               ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
-                                         (gpointer *) &process_handle);
-
-               if (ok == FALSE) {
-                       DEBUG ("%s: Can't find process %p", __func__,
-                                  process);
+               process_handle = lookup_process_handle (process);
+               if (!process_handle) {
+                       DEBUG ("%s: Can't find process %p", __func__, process);
                        SetLastError (ERROR_INVALID_HANDLE);
                        return FALSE;
                }
@@ -2639,19 +2270,16 @@ guint32
 GetPriorityClass (gpointer process)
 {
 #ifdef HAVE_GETPRIORITY
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
        int ret;
        pid_t pid;
        
-       if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
                /* This is a pseudo handle */
-               pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
+               pid = (pid_t)WAPI_HANDLE_TO_PID (process);
        } else {
-               ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
-                                         (gpointer *) &process_handle);
-
-               if (!ok) {
+               process_handle = lookup_process_handle (process);
+               if (!process_handle) {
                        SetLastError (ERROR_INVALID_HANDLE);
                        return FALSE;
                }
@@ -2699,20 +2327,17 @@ gboolean
 SetPriorityClass (gpointer process, guint32  priority_class)
 {
 #ifdef HAVE_SETPRIORITY
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
        int ret;
        int prio;
        pid_t pid;
        
-       if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
+       if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
                /* This is a pseudo handle */
-               pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
+               pid = (pid_t)WAPI_HANDLE_TO_PID (process);
        } else {
-               ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
-                                         (gpointer *) &process_handle);
-
-               if (!ok) {
+               process_handle = lookup_process_handle (process);
+               if (!process_handle) {
                        SetLastError (ERROR_INVALID_HANDLE);
                        return FALSE;
                }
@@ -2796,6 +2421,12 @@ mono_processes_cleanup (void)
                mp = mp->next;
        }
 
+       /*
+        * Remove processes which exited from the mono_processes list.
+        * We need to synchronize with the sigchld handler here, which runs
+        * asynchronously. The handler requires that the mono_processes list
+        * remain valid.
+        */
        mp = mono_processes;
        spin = 0;
        while (mp != NULL) {
@@ -2807,6 +2438,10 @@ mono_processes_cleanup (void)
 
                        /* We've found a candidate */
                        mono_mutex_lock (&mono_processes_mutex);
+                       /*
+                        * This code can run parallel with the sigchld handler, but the
+                        * modifications it makes are safe.
+                        */
                        if (candidate == NULL) {
                                /* unlink it */
                                if (mp == mono_processes) {
@@ -2857,12 +2492,14 @@ mono_processes_cleanup (void)
 static void
 process_close (gpointer handle, gpointer data)
 {
-       struct _WapiHandle_process *process_handle;
+       WapiHandle_process *process_handle;
 
        DEBUG ("%s", __func__);
 
-       process_handle = (struct _WapiHandle_process *) data;
-       if (process_handle->mono_process && process_handle->self == _wapi_getpid ())
+       process_handle = (WapiHandle_process *) data;
+       g_free (process_handle->proc_name);
+       process_handle->proc_name = NULL;
+       if (process_handle->mono_process)
                InterlockedDecrement (&process_handle->mono_process->handle_count);
        mono_processes_cleanup ();
 }
@@ -2874,9 +2511,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi
        int pid;
        struct MonoProcess *p;
 
-#if DEBUG      
-       fprintf (stdout, "SIG CHILD handler for pid: %i\n", info->si_pid);
-#endif
+       DEBUG ("SIG CHILD handler for pid: %i\n", info->si_pid);
 
        InterlockedIncrement (&mono_processes_read_lock);
 
@@ -2888,9 +2523,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi
                if (pid <= 0)
                        break;
 
-#if DEBUG
-               fprintf (stdout, "child ended: %i", pid);
-#endif
+               DEBUG ("child ended: %i", pid);
                p = mono_processes;
                while (p != NULL) {
                        if (p->pid == pid) {
@@ -2905,14 +2538,13 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi
 
        InterlockedDecrement (&mono_processes_read_lock);
 
-#if DEBUG
-       fprintf (stdout, "SIG CHILD handler: done looping.");
-#endif
+       DEBUG ("SIG CHILD handler: done looping.");
 }
 
 #endif
 
-static void process_add_sigchld_handler (void)
+static void
+process_add_sigchld_handler (void)
 {
 #if HAVE_SIGACTION
        struct sigaction sa;
@@ -2925,23 +2557,15 @@ static void process_add_sigchld_handler (void)
 #endif
 }
 
-static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertable)
+static guint32
+process_wait (gpointer handle, guint32 timeout, gboolean alertable)
 {
-       struct _WapiHandle_process *process_handle;
-       gboolean ok;
+       WapiHandle_process *process_handle;
        pid_t pid, ret;
        int status;
        guint32 start;
        guint32 now;
        struct MonoProcess *mp;
-       gboolean spin;
-       gpointer current_thread;
-
-       current_thread = wapi_get_current_thread_handle ();
-       if (current_thread == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return WAIT_FAILED;
-       }
 
        /* FIXME: We can now easily wait on processes that aren't our own children,
         * but WaitFor*Object won't call us for pseudo handles. */
@@ -2949,8 +2573,8 @@ static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertabl
 
        DEBUG ("%s (%p, %u)", __func__, handle, timeout);
 
-       ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS, (gpointer *)&process_handle);
-       if (ok == FALSE) {
+       process_handle = lookup_process_handle (handle);
+       if (!process_handle) {
                g_warning ("%s: error looking up process handle %p", __func__, handle);
                return WAIT_FAILED;
        }
@@ -2968,48 +2592,33 @@ static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertabl
        /* We don't need to lock mono_processes here, the entry
         * has a handle_count > 0 which means it will not be freed. */
        mp = process_handle->mono_process;
-       if (mp && process_handle->self != _wapi_getpid ()) {
-               /* mono_process points to memory in another process' address space: we can't use it */
-               mp = NULL;
-       }
+       g_assert (mp);
 
        start = mono_msec_ticks ();
        now = start;
-       spin = mp == NULL;
 
        while (1) {
-               if (mp != NULL) {
-                       /* We have a semaphore we can wait on */
-                       if (timeout != INFINITE) {
-                               DEBUG ("%s (%p, %u): waiting on semaphore for %li ms...", 
-                                       __func__, handle, timeout, (timeout - (now - start)));
+               if (timeout != INFINITE) {
+                       DEBUG ("%s (%p, %u): waiting on semaphore for %li ms...", 
+                                  __func__, handle, timeout, (timeout - (now - start)));
 
-                               ret = MONO_SEM_TIMEDWAIT_ALERTABLE (&mp->exit_sem, (timeout - (now - start)), alertable);
-                       } else {
-                               DEBUG ("%s (%p, %u): waiting on semaphore forever...", 
-                                       __func__, handle, timeout);
-                               ret = MONO_SEM_WAIT_ALERTABLE (&mp->exit_sem, alertable);
-                       }
+                       ret = MONO_SEM_TIMEDWAIT_ALERTABLE (&mp->exit_sem, (timeout - (now - start)), alertable);
+               } else {
+                       DEBUG ("%s (%p, %u): waiting on semaphore forever...", 
+                                  __func__, handle, timeout);
+                       ret = MONO_SEM_WAIT_ALERTABLE (&mp->exit_sem, alertable);
+               }
 
-                       if (ret == -1 && errno != EINTR && errno != ETIMEDOUT) {
-                               DEBUG ("%s (%p, %u): sem_timedwait failure: %s", 
-                                       __func__, handle, timeout, g_strerror (errno));
-                               /* Should we return a failure here? */
-                       }
+               if (ret == -1 && errno != EINTR && errno != ETIMEDOUT) {
+                       DEBUG ("%s (%p, %u): sem_timedwait failure: %s", 
+                                  __func__, handle, timeout, g_strerror (errno));
+                       /* Should we return a failure here? */
+               }
 
-                       if (ret == 0) {
-                               /* Success, process has exited */
-                               MONO_SEM_POST (&mp->exit_sem);
-                               break;
-                       }
-               } else {
-                       /* We did not create this process, so we can't waidpid / sem_wait it.
-                        * We need to poll for the pid existence */
-                       DEBUG ("%s (%p, %u): polling on pid...", __func__, handle, timeout);
-                       if (!is_pid_valid (pid)) {
-                               /* Success, process has exited */
-                               break;
-                       }
+               if (ret == 0) {
+                       /* Success, process has exited */
+                       MONO_SEM_POST (&mp->exit_sem);
+                       break;
                }
 
                if (timeout == 0) {
@@ -3022,14 +2631,8 @@ static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertabl
                        DEBUG ("%s (%p, %u): WAIT_TIMEOUT", __func__, handle, timeout);
                        return WAIT_TIMEOUT;
                }
-
-               if (spin) {
-                       /* "timeout - (now - start)" will not underflow, since timeout is always >=0,
-                        * and we passed the check just above */
-                       _wapi_handle_spin (MIN (100, timeout - (now - start)));
-               }
                
-               if (alertable && _wapi_thread_apc_pending (current_thread)) {
+               if (alertable && _wapi_thread_cur_apc_pending ()) {
                        DEBUG ("%s (%p, %u): WAIT_IO_COMPLETION", __func__, handle, timeout);
                        return WAIT_IO_COMPLETION;
                }
@@ -3042,11 +2645,10 @@ static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertabl
        g_assert (ret == 0);
 
        status = mp ? mp->status : 0;
-       if (WIFSIGNALED (status)) {
+       if (WIFSIGNALED (status))
                process_handle->exitstatus = 128 + WTERMSIG (status);
-       } else {
+       else
                process_handle->exitstatus = WEXITSTATUS (status);
-       }
        _wapi_time_t_to_filetime (time (NULL), &process_handle->exit_time);
 
        process_handle->exited = TRUE;
@@ -3054,7 +2656,7 @@ static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertabl
        DEBUG ("%s (%p, %u): Setting pid %d signalled, exit status %d",
                   __func__, handle, timeout, process_handle->id, process_handle->exitstatus);
 
-       _wapi_shared_handle_set_signal_state (handle, TRUE);
+       _wapi_handle_set_signal_state (handle, TRUE, TRUE);
 
        _wapi_handle_unlock_shared_handles ();
 
index 8e4c0aa558bf78da73681abd60b9710033109243..c2b78d44387dbc11d3b0bd6105170b2bc74a07ec 100644 (file)
@@ -10,6 +10,9 @@
 #ifndef _WAPI_PROCESSES_H_
 #define _WAPI_PROCESSES_H_
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #include <glib.h>
 
 #include <mono/io-layer/handles.h>
@@ -188,8 +191,6 @@ extern gboolean CreateProcessWithLogonW (const gunichar2 *username,
 
 extern gpointer GetCurrentProcess (void);
 extern guint32 GetProcessId (gpointer handle);
-extern guint32 GetCurrentProcessId (void);
-extern gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed);
 extern gboolean CloseProcess (gpointer handle);
 extern gpointer OpenProcess (guint32 access, gboolean inherit, guint32 pid);
 extern gboolean GetExitCodeProcess (gpointer process, guint32 *code);
index 1800f9b74a72d97c853ea0579d5c50e233cd61d1..f8539039cad103441bc63f977c3331251ff5df2c 100644 (file)
@@ -44,8 +44,6 @@
 
 static mono_mutex_t noshm_sems[_WAPI_SHARED_SEM_COUNT];
 
-gboolean _wapi_shm_disabled = TRUE;
-
 static gpointer wapi_storage [16];
 
 static void
@@ -152,12 +150,13 @@ _wapi_shm_detach (_wapi_shm_t type)
 }
 
 gboolean
-_wapi_shm_enabled (void)
+_wapi_shm_enabled_internal (void)
 {
        return FALSE;
 }
 
-#else
+#else /* DISABLE_SHARED_HANDLES */
+
 /*
  * Use POSIX shared memory if possible, it is simpler, and it has the advantage that 
  * writes to the shared area does not need to be written to disk, avoiding spinning up 
@@ -167,6 +166,8 @@ _wapi_shm_enabled (void)
 #define USE_SHM 1
 #endif
 
+static gboolean _wapi_shm_disabled = TRUE;
+
 static gchar *
 _wapi_shm_base_name (_wapi_shm_t type)
 {
@@ -404,7 +405,7 @@ try_again:
 }
 
 gboolean
-_wapi_shm_enabled (void)
+_wapi_shm_enabled_internal (void)
 {
        static gboolean env_checked;
 
index b175b6e306bf2e26aeb6ed7df1571bbbe455f416..5f66a732e6d680d5dcbb4d36c220b500bc48a5d3 100644 (file)
@@ -17,15 +17,23 @@ typedef enum {
        WAPI_SHM_FILESHARE
 } _wapi_shm_t;
 
-extern gboolean _wapi_shm_disabled;
-
 extern gpointer _wapi_shm_attach (_wapi_shm_t type);
 extern void _wapi_shm_detach (_wapi_shm_t type);
-extern gboolean _wapi_shm_enabled (void);
+extern gboolean _wapi_shm_enabled_internal (void);
 extern void _wapi_shm_semaphores_init (void);
 extern void _wapi_shm_semaphores_remove (void);
 extern int _wapi_shm_sem_lock (int sem);
 extern int _wapi_shm_sem_trylock (int sem);
 extern int _wapi_shm_sem_unlock (int sem);
 
+static inline gboolean
+_wapi_shm_enabled (void)
+{
+#ifdef DISABLE_SHARED_HANDLES
+       return FALSE;
+#else
+       return _wapi_shm_enabled_internal ();
+#endif
+}
+
 #endif /* _WAPI_SHARED_H_ */
index f982d860607f49e1ae291b6d0b3ca7e123670c75..34de2f0fd992b1d42c6596df39d19755dbce88e2 100644 (file)
@@ -42,8 +42,7 @@ typedef enum {
 
 extern const char *_wapi_handle_typename[];
 
-#define _WAPI_SHARED_HANDLE(type) (type == WAPI_HANDLE_PROCESS || \
-                                  type == WAPI_HANDLE_NAMEDMUTEX || \
+#define _WAPI_SHARED_HANDLE(type) (type == WAPI_HANDLE_NAMEDMUTEX || \
                                   type == WAPI_HANDLE_NAMEDSEM || \
                                   type == WAPI_HANDLE_NAMEDEVENT)
 
@@ -136,6 +135,7 @@ struct _WapiHandleUnshared
                struct _WapiHandle_sem sem;
                struct _WapiHandle_socket sock;
                struct _WapiHandle_thread thread;
+               struct _WapiHandle_process process;
                struct _WapiHandle_shared_ref shared;
        } u;
 };
@@ -149,7 +149,6 @@ struct _WapiHandleShared
        
        union
        {
-               struct _WapiHandle_process process;
                struct _WapiHandle_namedmutex namedmutex;
                struct _WapiHandle_namedsem namedsem;
                struct _WapiHandle_namedevent namedevent;
index d27404acb0f572b91e216e47a17f9ebbe97a9833..335484ae676054522cb7b99975e7a95947ba7dfc 100644 (file)
@@ -124,6 +124,7 @@ common_sources = \
        icall.c                 \
        icall-def.h             \
        image.c                 \
+       jit-info.c              \
        loader.c                \
        locales.c               \
        locales.h               \
index 3320820f87797e0583a2fe745a242e1f1a700b8f..090f2f7a1dc98e9296d02c829debb4cba317c11c 100644 (file)
@@ -753,7 +753,7 @@ create_allocator (int atype, int tls_key)
        bytes_var = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
        if (atype == ATYPE_STRING) {
                /* a string alloator method takes the args: (vtable, len) */
-               /* bytes = (sizeof (MonoString) + ((len + 1) * 2)); */
+               /* bytes = (offsetof (MonoString, chars) + ((len + 1) * 2)); */
                mono_mb_emit_ldarg (mb, 1);
                mono_mb_emit_icon (mb, 1);
                mono_mb_emit_byte (mb, MONO_CEE_ADD);
@@ -1291,6 +1291,18 @@ mono_gc_get_los_limit (void)
        return G_MAXINT;
 }
 
+void
+mono_gc_set_string_length (MonoString *str, gint32 new_length)
+{
+       mono_unichar2 *new_end = str->chars + new_length;
+       
+       /* zero the discarded string. This null-delimits the string and allows 
+        * the space to be reclaimed by SGen. */
+        
+       memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2));
+       str->length = new_length;
+}
+
 gboolean
 mono_gc_user_markers_supported (void)
 {
index 32b5ef4561ef6d3ac52cbb93f3fdf3c48f2ebb56..2bf904143f12df4e7d1c06810fdf907c89c91440 100644 (file)
@@ -208,8 +208,8 @@ enum {
        MONO_EXCEPTION_GENERIC_SHARING_FAILED = 11,
        MONO_EXCEPTION_BAD_IMAGE = 12,
        MONO_EXCEPTION_OBJECT_SUPPLIED = 13, /*The exception object is already created.*/
-       MONO_EXCEPTION_OUT_OF_MEMORY = 14
-       /* add other exception type */
+       MONO_EXCEPTION_OUT_OF_MEMORY = 14,
+       MONO_EXCEPTION_INLINE_FAILED = 15
 };
 
 /* This struct collects the info needed for the runtime use of a class,
index baa9565e8c94c4daa1820f020fefd5edf3b3da66..519eec9a191735c93380098363c6060bd644cf19 100644 (file)
@@ -1943,7 +1943,9 @@ mono_class_layout_fields (MonoClass *class)
                        }
                }
                break;
-       case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
+       case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
+               guint8 *ref_bitmap;
+
                real_size = 0;
                for (i = 0; i < top; i++) {
                        gint32 align;
@@ -1956,7 +1958,6 @@ mono_class_layout_fields (MonoClass *class)
                         * There must be info about all the fields in a type if it
                         * uses explicit layout.
                         */
-
                        if (mono_field_is_deleted (field))
                                continue;
                        if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
@@ -1986,6 +1987,40 @@ mono_class_layout_fields (MonoClass *class)
                         */
                        real_size = MAX (real_size, size + field->offset);
                }
+
+               if (class->has_references) {
+                       ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
+
+                       /* Check for overlapping reference and non-reference fields */
+                       for (i = 0; i < top; i++) {
+                               MonoType *ftype;
+
+                               field = &class->fields [i];
+
+                               if (mono_field_is_deleted (field))
+                                       continue;
+                               if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+                                       continue;
+                               ftype = mono_type_get_underlying_type (field->type);
+                               if (MONO_TYPE_IS_REFERENCE (ftype))
+                                       ref_bitmap [field->offset / sizeof (gpointer)] = 1;
+                       }
+                       for (i = 0; i < top; i++) {
+                               field = &class->fields [i];
+
+                               if (mono_field_is_deleted (field))
+                                       continue;
+                               if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+                                       continue;
+
+                               if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
+                                       char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset);
+                                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
+                               }
+                       }
+                       g_free (ref_bitmap);
+               }
+
                class->instance_size = MAX (real_size, class->instance_size);
                if (class->instance_size & (class->min_align - 1)) {
                        class->instance_size += class->min_align - 1;
@@ -1993,6 +2028,7 @@ mono_class_layout_fields (MonoClass *class)
                }
                break;
        }
+       }
 
        if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
                /*
@@ -2477,7 +2513,7 @@ mono_class_setup_events (MonoClass *class)
 
        if (class->generic_class) {
                MonoClass *gklass = class->generic_class->container_class;
-               MonoGenericContext *context;
+               MonoGenericContext *context = NULL;
 
                mono_class_setup_events (gklass);
                if (gklass->exception_type) {
index 6a70b350085b9d7183412a63aaf9f9860fc28cf0..dffba190e31ed5d3113c5705f6e8dcf8d4b8f670 100644 (file)
@@ -277,7 +277,7 @@ mono_console_handle_async_ops (void)
 
 static gboolean in_sigint;
 
-MONO_SIGNAL_HANDLER_FUNC (static, sigint_handler, (int signo))
+MONO_SIG_HANDLER_FUNC (static, sigint_handler)
 {
        int save_errno;
        MONO_ARCH_SAVE_REGS;
@@ -295,7 +295,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, sigint_handler, (int signo))
 
 static struct sigaction save_sigcont, save_sigint, save_sigwinch;
 
-MONO_SIGNAL_HANDLER_FUNC (static, sigcont_handler, (int signo, void *the_siginfo, void *data))
+MONO_SIG_HANDLER_FUNC (static, sigcont_handler)
 {
        int unused;
        // Ignore error, there is not much we can do in the sigcont handler.
@@ -308,10 +308,10 @@ MONO_SIGNAL_HANDLER_FUNC (static, sigcont_handler, (int signo, void *the_siginfo
        if (save_sigcont.sa_sigaction != NULL &&
            save_sigcont.sa_sigaction != (void *)SIG_DFL &&
            save_sigcont.sa_sigaction != (void *)SIG_IGN)
-               (*save_sigcont.sa_sigaction) (signo, the_siginfo, data);
+               (*save_sigcont.sa_sigaction) (MONO_SIG_HANDLER_PARAMS);
 }
 
-MONO_SIGNAL_HANDLER_FUNC (static, sigwinch_handler, (int signo, void *the_siginfo, void *data))
+MONO_SIG_HANDLER_FUNC (static, sigwinch_handler)
 {
        int dims = terminal_get_dimensions ();
        if (dims != -1)
@@ -321,7 +321,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, sigwinch_handler, (int signo, void *the_siginf
        if (save_sigwinch.sa_sigaction != NULL &&
            save_sigwinch.sa_sigaction != (void *)SIG_DFL &&
            save_sigwinch.sa_sigaction != (void *)SIG_IGN)
-               (*save_sigwinch.sa_sigaction) (signo, the_siginfo, data);
+               (*save_sigwinch.sa_sigaction) (MONO_SIG_HANDLER_PARAMS);
 }
 
 /*
index 24989f49afdf023e2c9fe55de278998f64019a9a..065e0458fa20021d2210bf4f71b7aecd588f09e4 100644 (file)
@@ -188,6 +188,14 @@ typedef struct {
        gboolean    cas_method_permitonly:1;
 } MonoMethodCasInfo;
 
+typedef enum {
+       JIT_INFO_NONE = 0,
+       JIT_INFO_HAS_CAS_INFO = (1 << 0),
+       JIT_INFO_HAS_GENERIC_JIT_INFO = (1 << 1),
+       JIT_INFO_HAS_TRY_BLOCK_HOLES = (1 << 2),
+       JIT_INFO_HAS_ARCH_EH_INFO = (1 << 3)
+} MonoJitInfoFlags;
+
 struct _MonoJitInfo {
        /* NOTE: These first two elements (method and
           next_jit_code_hash) must be in the same order and at the
@@ -456,6 +464,19 @@ mono_cleanup (void) MONO_INTERNAL;
 void
 mono_close_exe_image (void) MONO_INTERNAL;
 
+int
+mono_jit_info_size (MonoJitInfoFlags flags, int num_clauses, int num_holes) MONO_INTERNAL;
+
+void
+mono_jit_info_init (MonoJitInfo *ji, MonoMethod *method, guint8 *code, int code_size,
+                                       MonoJitInfoFlags flags, int num_clauses, int num_holes) MONO_INTERNAL;
+
+MonoJitInfoTable *
+mono_jit_info_table_new (MonoDomain *domain) MONO_INTERNAL;
+
+void
+mono_jit_info_table_free (MonoJitInfoTable *table) MONO_INTERNAL;
+
 void
 mono_jit_info_table_add    (MonoDomain *domain, MonoJitInfo *ji) MONO_INTERNAL;
 
index 013e73b69109354957aa54b70fea69d06a39703b..e30c0345c0abae993f6e0394aae83b1719aedd7d 100755 (executable)
@@ -116,8 +116,6 @@ typedef struct {
 
 static const MonoRuntimeInfo *current_runtime = NULL;
 
-static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
-
 /* This is the list of runtime versions supported by this JIT.
  */
 static const MonoRuntimeInfo supported_runtimes[] = {
@@ -170,870 +168,6 @@ mono_domain_get_tls_offset (void)
        return offset;
 }
 
-#define JIT_INFO_TABLE_FILL_RATIO_NOM          3
-#define JIT_INFO_TABLE_FILL_RATIO_DENOM                4
-#define JIT_INFO_TABLE_FILLED_NUM_ELEMENTS     (MONO_JIT_INFO_TABLE_CHUNK_SIZE * JIT_INFO_TABLE_FILL_RATIO_NOM / JIT_INFO_TABLE_FILL_RATIO_DENOM)
-
-#define JIT_INFO_TABLE_LOW_WATERMARK(n)                ((n) / 2)
-#define JIT_INFO_TABLE_HIGH_WATERMARK(n)       ((n) * 5 / 6)
-
-#define JIT_INFO_TOMBSTONE_MARKER      ((MonoMethod*)NULL)
-#define IS_JIT_INFO_TOMBSTONE(ji)      ((ji)->d.method == JIT_INFO_TOMBSTONE_MARKER)
-
-#define JIT_INFO_TABLE_HAZARD_INDEX            0
-#define JIT_INFO_HAZARD_INDEX                  1
-
-static int
-jit_info_table_num_elements (MonoJitInfoTable *table)
-{
-       int i;
-       int num_elements = 0;
-
-       for (i = 0; i < table->num_chunks; ++i) {
-               MonoJitInfoTableChunk *chunk = table->chunks [i];
-               int chunk_num_elements = chunk->num_elements;
-               int j;
-
-               for (j = 0; j < chunk_num_elements; ++j) {
-                       if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
-                               ++num_elements;
-               }
-       }
-
-       return num_elements;
-}
-
-static MonoJitInfoTableChunk*
-jit_info_table_new_chunk (void)
-{
-       MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
-       chunk->refcount = 1;
-
-       return chunk;
-}
-
-static MonoJitInfoTable *
-jit_info_table_new (MonoDomain *domain)
-{
-       MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
-
-       table->domain = domain;
-       table->num_chunks = 1;
-       table->chunks [0] = jit_info_table_new_chunk ();
-
-       return table;
-}
-
-static void
-jit_info_table_free (MonoJitInfoTable *table)
-{
-       int i;
-       int num_chunks = table->num_chunks;
-       MonoDomain *domain = table->domain;
-
-       mono_domain_lock (domain);
-
-       table->domain->num_jit_info_tables--;
-       if (table->domain->num_jit_info_tables <= 1) {
-               GSList *list;
-
-               for (list = table->domain->jit_info_free_queue; list; list = list->next)
-                       g_free (list->data);
-
-               g_slist_free (table->domain->jit_info_free_queue);
-               table->domain->jit_info_free_queue = NULL;
-       }
-
-       /* At this point we assume that there are no other threads
-          still accessing the table, so we don't have to worry about
-          hazardous pointers. */
-
-       for (i = 0; i < num_chunks; ++i) {
-               MonoJitInfoTableChunk *chunk = table->chunks [i];
-               int num_elements;
-               int j;
-
-               if (--chunk->refcount > 0)
-                       continue;
-
-               num_elements = chunk->num_elements;
-               for (j = 0; j < num_elements; ++j) {
-                       MonoJitInfo *ji = chunk->data [j];
-
-                       if (IS_JIT_INFO_TOMBSTONE (ji))
-                               g_free (ji);
-               }
-
-               g_free (chunk);
-       }
-
-       mono_domain_unlock (domain);
-
-       g_free (table);
-}
-
-/* The jit_info_table is sorted in ascending order by the end
- * addresses of the compiled methods.  The reason why we have to do
- * this is that once we introduce tombstones, it becomes possible for
- * code ranges to overlap, and if we sort by code start and insert at
- * the back of the table, we cannot guarantee that we won't overlook
- * an entry.
- *
- * There are actually two possible ways to do the sorting and
- * inserting which work with our lock-free mechanism:
- *
- * 1. Sort by start address and insert at the front.  When looking for
- * an entry, find the last one with a start address lower than the one
- * you're looking for, then work your way to the front of the table.
- *
- * 2. Sort by end address and insert at the back.  When looking for an
- * entry, find the first one with an end address higher than the one
- * you're looking for, then work your way to the end of the table.
- *
- * We chose the latter out of convenience.
- */
-static int
-jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
-{
-       int left = 0, right = table->num_chunks;
-
-       g_assert (left < right);
-
-       do {
-               int pos = (left + right) / 2;
-               MonoJitInfoTableChunk *chunk = table->chunks [pos];
-
-               if (addr < chunk->last_code_end)
-                       right = pos;
-               else
-                       left = pos + 1;
-       } while (left < right);
-       g_assert (left == right);
-
-       if (left >= table->num_chunks)
-               return table->num_chunks - 1;
-       return left;
-}
-
-static int
-jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
-{
-       int left = 0, right = chunk->num_elements;
-
-       while (left < right) {
-               int pos = (left + right) / 2;
-               MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
-               gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
-
-               if (addr < code_end)
-                       right = pos;
-               else
-                       left = pos + 1;
-       }
-       g_assert (left == right);
-
-       return left;
-}
-
-static MonoJitInfo*
-jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint8 *addr)
-{
-       MonoJitInfo *ji;
-       int chunk_pos, pos;
-
-       chunk_pos = jit_info_table_index (table, (gint8*)addr);
-       g_assert (chunk_pos < table->num_chunks);
-
-       pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
-
-       /* We now have a position that's very close to that of the
-          first element whose end address is higher than the one
-          we're looking for.  If we don't have the exact position,
-          then we have a position below that one, so we'll just
-          search upward until we find our element. */
-       do {
-               MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
-
-               while (pos < chunk->num_elements) {
-                       ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
-
-                       ++pos;
-
-                       if (IS_JIT_INFO_TOMBSTONE (ji)) {
-                               mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
-                               continue;
-                       }
-                       if ((gint8*)addr >= (gint8*)ji->code_start
-                                       && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
-                               mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
-                               return ji;
-                       }
-
-                       /* If we find a non-tombstone element which is already
-                          beyond what we're looking for, we have to end the
-                          search. */
-                       if ((gint8*)addr < (gint8*)ji->code_start)
-                               goto not_found;
-               }
-
-               ++chunk_pos;
-               pos = 0;
-       } while (chunk_pos < table->num_chunks);
-
- not_found:
-       if (hp)
-               mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
-       return NULL;
-}
-
-/*
- * mono_jit_info_table_find_internal:
- *
- * If TRY_AOT is FALSE, avoid loading information for missing methods from AOT images, which is currently not async safe.
- * In this case, only those AOT methods will be found whose jit info is already loaded.
- * ASYNC SAFETY: When called in an async context (mono_thread_info_is_async_context ()), this is async safe.
- * In this case, the returned MonoJitInfo might not have metadata information, in particular,
- * mono_jit_info_get_method () could fail.
- */
-MonoJitInfo*
-mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot)
-{
-       MonoJitInfoTable *table;
-       MonoJitInfo *ji, *module_ji;
-       MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
-
-       ++mono_stats.jit_info_table_lookup_count;
-
-       /* First we have to get the domain's jit_info_table.  This is
-          complicated by the fact that a writer might substitute a
-          new table and free the old one.  What the writer guarantees
-          us is that it looks at the hazard pointers after it has
-          changed the jit_info_table pointer.  So, if we guard the
-          table by a hazard pointer and make sure that the pointer is
-          still there after we've made it hazardous, we don't have to
-          worry about the writer freeing the table. */
-       table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
-
-       ji = jit_info_table_find (table, hp, (gint8*)addr);
-       if (hp)
-               mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
-       if (ji)
-               return ji;
-
-       /* Maybe its an AOT module */
-       if (try_aot && mono_root_domain && mono_root_domain->aot_modules) {
-               table = get_hazardous_pointer ((gpointer volatile*)&mono_root_domain->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX);
-               module_ji = jit_info_table_find (table, hp, (gint8*)addr);
-               if (module_ji)
-                       ji = jit_info_find_in_aot_func (domain, module_ji->d.image, addr);
-               if (hp)
-                       mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
-       }
-       
-       return ji;
-}
-
-MonoJitInfo*
-mono_jit_info_table_find (MonoDomain *domain, char *addr)
-{
-       return mono_jit_info_table_find_internal (domain, addr, TRUE);
-}
-
-static G_GNUC_UNUSED void
-jit_info_table_check (MonoJitInfoTable *table)
-{
-       int i;
-
-       for (i = 0; i < table->num_chunks; ++i) {
-               MonoJitInfoTableChunk *chunk = table->chunks [i];
-               int j;
-
-               g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
-               if (chunk->refcount > 10)
-                       printf("warning: chunk refcount is %d\n", chunk->refcount);
-               g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
-
-               for (j = 0; j < chunk->num_elements; ++j) {
-                       MonoJitInfo *this = chunk->data [j];
-                       MonoJitInfo *next;
-
-                       g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
-
-                       if (j < chunk->num_elements - 1)
-                               next = chunk->data [j + 1];
-                       else if (i < table->num_chunks - 1) {
-                               int k;
-
-                               for (k = i + 1; k < table->num_chunks; ++k)
-                                       if (table->chunks [k]->num_elements > 0)
-                                               break;
-
-                               if (k >= table->num_chunks)
-                                       return;
-
-                               g_assert (table->chunks [k]->num_elements > 0);
-                               next = table->chunks [k]->data [0];
-                       } else
-                               return;
-
-                       g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
-               }
-       }
-}
-
-static MonoJitInfoTable*
-jit_info_table_realloc (MonoJitInfoTable *old)
-{
-       int i;
-       int num_elements = jit_info_table_num_elements (old);
-       int required_size;
-       int num_chunks;
-       int new_chunk, new_element;
-       MonoJitInfoTable *new;
-
-       /* number of needed places for elements needed */
-       required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
-       num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
-       if (num_chunks == 0) {
-               g_assert (num_elements == 0);
-               return jit_info_table_new (old->domain);
-       }
-       g_assert (num_chunks > 0);
-
-       new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
-       new->domain = old->domain;
-       new->num_chunks = num_chunks;
-
-       for (i = 0; i < num_chunks; ++i)
-               new->chunks [i] = jit_info_table_new_chunk ();
-
-       new_chunk = 0;
-       new_element = 0;
-       for (i = 0; i < old->num_chunks; ++i) {
-               MonoJitInfoTableChunk *chunk = old->chunks [i];
-               int chunk_num_elements = chunk->num_elements;
-               int j;
-
-               for (j = 0; j < chunk_num_elements; ++j) {
-                       if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
-                               g_assert (new_chunk < num_chunks);
-                               new->chunks [new_chunk]->data [new_element] = chunk->data [j];
-                               if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
-                                       new->chunks [new_chunk]->num_elements = new_element;
-                                       ++new_chunk;
-                                       new_element = 0;
-                               }
-                       }
-               }
-       }
-
-       if (new_chunk < num_chunks) {
-               g_assert (new_chunk == num_chunks - 1);
-               new->chunks [new_chunk]->num_elements = new_element;
-               g_assert (new->chunks [new_chunk]->num_elements > 0);
-       }
-
-       for (i = 0; i < num_chunks; ++i) {
-               MonoJitInfoTableChunk *chunk = new->chunks [i];
-               MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
-
-               new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
-       }
-
-       return new;
-}
-
-static void
-jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
-{
-       MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
-       MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
-
-       g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
-
-       new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
-       new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
-
-       memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
-       memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
-
-       new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
-               + new1->data [new1->num_elements - 1]->code_size;
-       new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
-               + new2->data [new2->num_elements - 1]->code_size;
-
-       *new1p = new1;
-       *new2p = new2;
-}
-
-static MonoJitInfoTable*
-jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
-{
-       MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
-               + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
-       int i, j;
-
-       new_table->domain = table->domain;
-       new_table->num_chunks = table->num_chunks + 1;
-
-       j = 0;
-       for (i = 0; i < table->num_chunks; ++i) {
-               if (table->chunks [i] == chunk) {
-                       jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
-                       j += 2;
-               } else {
-                       new_table->chunks [j] = table->chunks [i];
-                       ++new_table->chunks [j]->refcount;
-                       ++j;
-               }
-       }
-
-       g_assert (j == new_table->num_chunks);
-
-       return new_table;
-}
-
-static MonoJitInfoTableChunk*
-jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
-{
-       MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
-       int i, j;
-
-       j = 0;
-       for (i = 0; i < old->num_elements; ++i) {
-               if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
-                       new->data [j++] = old->data [i];
-       }
-
-       new->num_elements = j;
-       if (new->num_elements > 0)
-               new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
-       else
-               new->last_code_end = old->last_code_end;
-
-       return new;
-}
-
-static MonoJitInfoTable*
-jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
-{
-       MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
-               + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
-       int i, j;
-
-       new_table->domain = table->domain;
-       new_table->num_chunks = table->num_chunks;
-
-       j = 0;
-       for (i = 0; i < table->num_chunks; ++i) {
-               if (table->chunks [i] == chunk)
-                       new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
-               else {
-                       new_table->chunks [j] = table->chunks [i];
-                       ++new_table->chunks [j]->refcount;
-                       ++j;
-               }
-       }
-
-       g_assert (j == new_table->num_chunks);
-
-       return new_table;
-}
-
-/* As we add an element to the table the case can arise that the chunk
- * to which we need to add is already full.  In that case we have to
- * allocate a new table and do something about that chunk.  We have
- * several strategies:
- *
- * If the number of elements in the table is below the low watermark
- * or above the high watermark, we reallocate the whole table.
- * Otherwise we only concern ourselves with the overflowing chunk:
- *
- * If there are no tombstones in the chunk then we split the chunk in
- * two, each half full.
- *
- * If the chunk does contain tombstones, we just make a new copy of
- * the chunk without the tombstones, which will have room for at least
- * the one element we have to add.
- */
-static MonoJitInfoTable*
-jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
-{
-       int num_elements = jit_info_table_num_elements (table);
-       int i;
-
-       if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
-                       || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
-               //printf ("reallocing table\n");
-               return jit_info_table_realloc (table);
-       }
-
-       /* count the number of non-tombstone elements in the chunk */
-       num_elements = 0;
-       for (i = 0; i < chunk->num_elements; ++i) {
-               if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
-                       ++num_elements;
-       }
-
-       if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
-               //printf ("splitting chunk\n");
-               return jit_info_table_copy_and_split_chunk (table, chunk);
-       }
-
-       //printf ("purifying chunk\n");
-       return jit_info_table_copy_and_purify_chunk (table, chunk);
-}
-
-/* We add elements to the table by first making space for them by
- * shifting the elements at the back to the right, one at a time.
- * This results in duplicate entries during the process, but during
- * all the time the table is in a sorted state.  Also, when an element
- * is replaced by another one, the element that replaces it has an end
- * address that is equal to or lower than that of the replaced
- * element.  That property is necessary to guarantee that when
- * searching for an element we end up at a position not higher than
- * the one we're looking for (i.e. we either find the element directly
- * or we end up to the left of it).
- */
-static void
-jit_info_table_add (MonoDomain *domain, MonoJitInfoTable *volatile *table_ptr, MonoJitInfo *ji)
-{
-       MonoJitInfoTable *table;
-       MonoJitInfoTableChunk *chunk;
-       int chunk_pos, pos;
-       int num_elements;
-       int i;
-
-       table = *table_ptr;
-
- restart:
-       chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
-       g_assert (chunk_pos < table->num_chunks);
-       chunk = table->chunks [chunk_pos];
-
-       if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
-               MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
-
-               /* Debugging code, should be removed. */
-               //jit_info_table_check (new_table);
-
-               *table_ptr = new_table;
-               mono_memory_barrier ();
-               domain->num_jit_info_tables++;
-               mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free, TRUE, FALSE);
-               table = new_table;
-
-               goto restart;
-       }
-
-       /* Debugging code, should be removed. */
-       //jit_info_table_check (table);
-
-       num_elements = chunk->num_elements;
-
-       pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
-
-       /* First we need to size up the chunk by one, by copying the
-          last item, or inserting the first one, if the table is
-          empty. */
-       if (num_elements > 0)
-               chunk->data [num_elements] = chunk->data [num_elements - 1];
-       else
-               chunk->data [0] = ji;
-       mono_memory_write_barrier ();
-       chunk->num_elements = ++num_elements;
-
-       /* Shift the elements up one by one. */
-       for (i = num_elements - 2; i >= pos; --i) {
-               mono_memory_write_barrier ();
-               chunk->data [i + 1] = chunk->data [i];
-       }
-
-       /* Now we have room and can insert the new item. */
-       mono_memory_write_barrier ();
-       chunk->data [pos] = ji;
-
-       /* Set the high code end address chunk entry. */
-       chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
-               + chunk->data [chunk->num_elements - 1]->code_size;
-
-       /* Debugging code, should be removed. */
-       //jit_info_table_check (table);
-}
-
-void
-mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
-{
-       g_assert (ji->d.method != NULL);
-
-       mono_domain_lock (domain);
-
-       ++mono_stats.jit_info_table_insert_count;
-
-       jit_info_table_add (domain, &domain->jit_info_table, ji);
-
-       mono_domain_unlock (domain);
-}
-
-static MonoJitInfo*
-mono_jit_info_make_tombstone (MonoJitInfo *ji)
-{
-       MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
-
-       tombstone->code_start = ji->code_start;
-       tombstone->code_size = ji->code_size;
-       tombstone->d.method = JIT_INFO_TOMBSTONE_MARKER;
-
-       return tombstone;
-}
-
-/*
- * LOCKING: domain lock
- */
-static void
-mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
-{
-       if (domain->num_jit_info_tables <= 1) {
-               /* Can it actually happen that we only have one table
-                  but ji is still hazardous? */
-               mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
-       } else {
-               domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
-       }
-}
-
-static void
-jit_info_table_remove (MonoJitInfoTable *table, MonoJitInfo *ji)
-{
-       MonoJitInfoTableChunk *chunk;
-       gpointer start = ji->code_start;
-       int chunk_pos, pos;
-
-       chunk_pos = jit_info_table_index (table, start);
-       g_assert (chunk_pos < table->num_chunks);
-
-       pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
-
-       do {
-               chunk = table->chunks [chunk_pos];
-
-               while (pos < chunk->num_elements) {
-                       if (chunk->data [pos] == ji)
-                               goto found;
-
-                       g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
-                       g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
-                               <= (guint8*)ji->code_start + ji->code_size);
-
-                       ++pos;
-               }
-
-               ++chunk_pos;
-               pos = 0;
-       } while (chunk_pos < table->num_chunks);
-
- found:
-       g_assert (chunk->data [pos] == ji);
-
-       chunk->data [pos] = mono_jit_info_make_tombstone (ji);
-
-       /* Debugging code, should be removed. */
-       //jit_info_table_check (table);
-}
-
-void
-mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
-{
-       MonoJitInfoTable *table;
-
-       mono_domain_lock (domain);
-       table = domain->jit_info_table;
-
-       ++mono_stats.jit_info_table_remove_count;
-
-       jit_info_table_remove (table, ji);
-
-       mono_jit_info_free_or_queue (domain, ji);
-
-       mono_domain_unlock (domain);
-}
-
-void
-mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
-{
-       MonoJitInfo *ji;
-
-       g_assert (mono_root_domain);
-       mono_domain_lock (mono_root_domain);
-
-       /*
-        * We reuse MonoJitInfoTable to store AOT module info,
-        * this gives us async-safe lookup.
-        */
-       if (!mono_root_domain->aot_modules) {
-               mono_root_domain->num_jit_info_tables ++;
-               mono_root_domain->aot_modules = jit_info_table_new (mono_root_domain);
-       }
-
-       ji = g_new0 (MonoJitInfo, 1);
-       ji->d.image = image;
-       ji->code_start = start;
-       ji->code_size = (guint8*)end - (guint8*)start;
-       jit_info_table_add (mono_root_domain, &mono_root_domain->aot_modules, ji);
-
-       mono_domain_unlock (mono_root_domain);
-}
-
-void
-mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
-{
-       jit_info_find_in_aot_func = func;
-}
-
-gpointer
-mono_jit_info_get_code_start (MonoJitInfo* ji)
-{
-       return ji->code_start;
-}
-
-int
-mono_jit_info_get_code_size (MonoJitInfo* ji)
-{
-       return ji->code_size;
-}
-
-MonoMethod*
-mono_jit_info_get_method (MonoJitInfo* ji)
-{
-       g_assert (!ji->async);
-       return ji->d.method;
-}
-
-static gpointer
-jit_info_key_extract (gpointer value)
-{
-       MonoJitInfo *info = (MonoJitInfo*)value;
-
-       return info->d.method;
-}
-
-static gpointer*
-jit_info_next_value (gpointer value)
-{
-       MonoJitInfo *info = (MonoJitInfo*)value;
-
-       return (gpointer*)&info->next_jit_code_hash;
-}
-
-void
-mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
-{
-       mono_internal_hash_table_init (jit_code_hash,
-                                      mono_aligned_addr_hash,
-                                      jit_info_key_extract,
-                                      jit_info_next_value);
-}
-
-MonoGenericJitInfo*
-mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
-{
-       if (ji->has_generic_jit_info)
-               return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
-       else
-               return NULL;
-}
-
-/*
- * mono_jit_info_get_generic_sharing_context:
- * @ji: a jit info
- *
- * Returns the jit info's generic sharing context, or NULL if it
- * doesn't have one.
- */
-MonoGenericSharingContext*
-mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
-{
-       MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
-
-       if (gi)
-               return gi->generic_sharing_context;
-       else
-               return NULL;
-}
-
-/*
- * mono_jit_info_set_generic_sharing_context:
- * @ji: a jit info
- * @gsctx: a generic sharing context
- *
- * Sets the jit info's generic sharing context.  The jit info must
- * have memory allocated for the context.
- */
-void
-mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
-{
-       MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
-
-       g_assert (gi);
-
-       gi->generic_sharing_context = gsctx;
-}
-
-MonoTryBlockHoleTableJitInfo*
-mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
-{
-       if (ji->has_try_block_holes) {
-               char *ptr = (char*)&ji->clauses [ji->num_clauses];
-               if (ji->has_generic_jit_info)
-                       ptr += sizeof (MonoGenericJitInfo);
-               return (MonoTryBlockHoleTableJitInfo*)ptr;
-       } else {
-               return NULL;
-       }
-}
-
-static int
-try_block_hole_table_size (MonoJitInfo *ji)
-{
-       MonoTryBlockHoleTableJitInfo *table;
-
-       table = mono_jit_info_get_try_block_hole_table_info (ji);
-       g_assert (table);
-       return sizeof (MonoTryBlockHoleTableJitInfo) + table->num_holes * sizeof (MonoTryBlockHoleJitInfo);
-}
-
-MonoArchEHJitInfo*
-mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
-{
-       if (ji->has_arch_eh_info) {
-               char *ptr = (char*)&ji->clauses [ji->num_clauses];
-               if (ji->has_generic_jit_info)
-                       ptr += sizeof (MonoGenericJitInfo);
-               if (ji->has_try_block_holes)
-                       ptr += try_block_hole_table_size (ji);
-               return (MonoArchEHJitInfo*)ptr;
-       } else {
-               return NULL;
-       }
-}
-
-MonoMethodCasInfo*
-mono_jit_info_get_cas_info (MonoJitInfo *ji)
-{
-       if (ji->has_cas_info) {
-               char *ptr = (char*)&ji->clauses [ji->num_clauses];
-               if (ji->has_generic_jit_info)
-                       ptr += sizeof (MonoGenericJitInfo);
-               if (ji->has_try_block_holes)
-                       ptr += try_block_hole_table_size (ji);
-               if (ji->has_arch_eh_info)
-                       ptr += sizeof (MonoArchEHJitInfo);
-               return (MonoMethodCasInfo*)ptr;
-       } else {
-               return NULL;
-       }
-}
-
 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
 
@@ -1306,7 +440,7 @@ mono_domain_create (void)
        mono_jit_code_hash_init (&domain->jit_code_hash);
        domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
        domain->num_jit_info_tables = 1;
-       domain->jit_info_table = jit_info_table_new (domain);
+       domain->jit_info_table = mono_jit_info_table_new (domain);
        domain->jit_info_free_queue = NULL;
        domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
        domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
@@ -2098,9 +1232,9 @@ mono_domain_free (MonoDomain *domain, gboolean force)
         */
        mono_thread_hazardous_try_free_all ();
        if (domain->aot_modules)
-               jit_info_table_free (domain->aot_modules);
+               mono_jit_info_table_free (domain->aot_modules);
        g_assert (domain->num_jit_info_tables == 1);
-       jit_info_table_free (domain->jit_info_table);
+       mono_jit_info_table_free (domain->jit_info_table);
        domain->jit_info_table = NULL;
        g_assert (!domain->jit_info_free_queue);
 
index 8e8c35f836065991b4a5266b39a45da65f223441..7b8836363f8a2a769b980d2a063e7d4567c398b2 100644 (file)
@@ -329,6 +329,8 @@ void mono_gc_set_skip_thread (gboolean skip) MONO_INTERNAL;
  */
 gboolean mono_gc_is_disabled (void) MONO_INTERNAL;
 
+void mono_gc_set_string_length (MonoString *str, gint32 new_length) MONO_INTERNAL;
+
 #if defined(__MACH__)
 void mono_gc_register_mach_exception_thread (pthread_t thread) MONO_INTERNAL;
 pthread_t mono_gc_get_mach_exception_thread (void) MONO_INTERNAL;
index a0472955071df183adf0d6457be366fe0c78cb3a..4e025385b766151c779ad1f45f1e5341234c4d5d 100644 (file)
@@ -1224,7 +1224,7 @@ mono_gc_cleanup (void)
                                ret = WaitForSingleObjectEx (gc_thread->handle, INFINITE, TRUE);
                                g_assert (ret == WAIT_OBJECT_0);
 
-                               mono_thread_join ((gpointer)gc_thread->tid);
+                               mono_thread_join (MONO_UINT_TO_NATIVE_THREAD_ID (gc_thread->tid));
                        }
                }
                gc_thread = NULL;
index 103eb3c4230490ba81c24dfa376d3291fcfe98ec..257b8332f5f4ac9abaf33200788483a60daf44b7 100644 (file)
@@ -797,6 +797,7 @@ ICALL(STRING_8a, "GetLOSLimit", ves_icall_System_String_GetLOSLimit)
 ICALL(STRING_9, "InternalAllocateStr", ves_icall_System_String_InternalAllocateStr)
 ICALL(STRING_10, "InternalIntern", ves_icall_System_String_InternalIntern)
 ICALL(STRING_11, "InternalIsInterned", ves_icall_System_String_InternalIsInterned)
+ICALL(STRING_12, "InternalSetLength", ves_icall_System_String_InternalSetLength)
 
 ICALL_TYPE(TENC, "System.Text.Encoding", TENC_1)
 ICALL(TENC_1, "InternalCodePage", ves_icall_System_Text_Encoding_InternalCodePage)
diff --git a/mono/metadata/jit-info.c b/mono/metadata/jit-info.c
new file mode 100644 (file)
index 0000000..cc0b766
--- /dev/null
@@ -0,0 +1,946 @@
+/*
+ * jit-info.c: MonoJitInfo functionality
+ *
+ * Author:
+ *     Dietmar Maurer (dietmar@ximian.com)
+ *     Patrik Torstensson
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <mono/metadata/gc-internal.h>
+
+#include <mono/utils/atomic.h>
+#include <mono/utils/mono-compiler.h>
+#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-membar.h>
+#include <mono/utils/mono-counters.h>
+#include <mono/utils/hazard-pointer.h>
+#include <mono/utils/mono-tls.h>
+#include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-threads.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/domain-internals.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/exception.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/mono-debug-debugger.h>
+#include <mono/metadata/mono-config.h>
+#include <mono/metadata/threads-types.h>
+#include <mono/metadata/runtime.h>
+#include <metadata/threads.h>
+#include <metadata/profiler-private.h>
+#include <mono/metadata/coree.h>
+
+static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
+
+#define JIT_INFO_TABLE_FILL_RATIO_NOM          3
+#define JIT_INFO_TABLE_FILL_RATIO_DENOM                4
+#define JIT_INFO_TABLE_FILLED_NUM_ELEMENTS     (MONO_JIT_INFO_TABLE_CHUNK_SIZE * JIT_INFO_TABLE_FILL_RATIO_NOM / JIT_INFO_TABLE_FILL_RATIO_DENOM)
+
+#define JIT_INFO_TABLE_LOW_WATERMARK(n)                ((n) / 2)
+#define JIT_INFO_TABLE_HIGH_WATERMARK(n)       ((n) * 5 / 6)
+
+#define JIT_INFO_TOMBSTONE_MARKER      ((MonoMethod*)NULL)
+#define IS_JIT_INFO_TOMBSTONE(ji)      ((ji)->d.method == JIT_INFO_TOMBSTONE_MARKER)
+
+#define JIT_INFO_TABLE_HAZARD_INDEX            0
+#define JIT_INFO_HAZARD_INDEX                  1
+
+static int
+jit_info_table_num_elements (MonoJitInfoTable *table)
+{
+       int i;
+       int num_elements = 0;
+
+       for (i = 0; i < table->num_chunks; ++i) {
+               MonoJitInfoTableChunk *chunk = table->chunks [i];
+               int chunk_num_elements = chunk->num_elements;
+               int j;
+
+               for (j = 0; j < chunk_num_elements; ++j) {
+                       if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
+                               ++num_elements;
+               }
+       }
+
+       return num_elements;
+}
+
+static MonoJitInfoTableChunk*
+jit_info_table_new_chunk (void)
+{
+       MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
+       chunk->refcount = 1;
+
+       return chunk;
+}
+
+MonoJitInfoTable *
+mono_jit_info_table_new (MonoDomain *domain)
+{
+       MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
+
+       table->domain = domain;
+       table->num_chunks = 1;
+       table->chunks [0] = jit_info_table_new_chunk ();
+
+       return table;
+}
+
+void
+mono_jit_info_table_free (MonoJitInfoTable *table)
+{
+       int i;
+       int num_chunks = table->num_chunks;
+       MonoDomain *domain = table->domain;
+
+       mono_domain_lock (domain);
+
+       table->domain->num_jit_info_tables--;
+       if (table->domain->num_jit_info_tables <= 1) {
+               GSList *list;
+
+               for (list = table->domain->jit_info_free_queue; list; list = list->next)
+                       g_free (list->data);
+
+               g_slist_free (table->domain->jit_info_free_queue);
+               table->domain->jit_info_free_queue = NULL;
+       }
+
+       /* At this point we assume that there are no other threads
+          still accessing the table, so we don't have to worry about
+          hazardous pointers. */
+
+       for (i = 0; i < num_chunks; ++i) {
+               MonoJitInfoTableChunk *chunk = table->chunks [i];
+               int num_elements;
+               int j;
+
+               if (--chunk->refcount > 0)
+                       continue;
+
+               num_elements = chunk->num_elements;
+               for (j = 0; j < num_elements; ++j) {
+                       MonoJitInfo *ji = chunk->data [j];
+
+                       if (IS_JIT_INFO_TOMBSTONE (ji))
+                               g_free (ji);
+               }
+
+               g_free (chunk);
+       }
+
+       mono_domain_unlock (domain);
+
+       g_free (table);
+}
+
+/* The jit_info_table is sorted in ascending order by the end
+ * addresses of the compiled methods.  The reason why we have to do
+ * this is that once we introduce tombstones, it becomes possible for
+ * code ranges to overlap, and if we sort by code start and insert at
+ * the back of the table, we cannot guarantee that we won't overlook
+ * an entry.
+ *
+ * There are actually two possible ways to do the sorting and
+ * inserting which work with our lock-free mechanism:
+ *
+ * 1. Sort by start address and insert at the front.  When looking for
+ * an entry, find the last one with a start address lower than the one
+ * you're looking for, then work your way to the front of the table.
+ *
+ * 2. Sort by end address and insert at the back.  When looking for an
+ * entry, find the first one with an end address higher than the one
+ * you're looking for, then work your way to the end of the table.
+ *
+ * We chose the latter out of convenience.
+ */
+static int
+jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
+{
+       int left = 0, right = table->num_chunks;
+
+       g_assert (left < right);
+
+       do {
+               int pos = (left + right) / 2;
+               MonoJitInfoTableChunk *chunk = table->chunks [pos];
+
+               if (addr < chunk->last_code_end)
+                       right = pos;
+               else
+                       left = pos + 1;
+       } while (left < right);
+       g_assert (left == right);
+
+       if (left >= table->num_chunks)
+               return table->num_chunks - 1;
+       return left;
+}
+
+static int
+jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
+{
+       int left = 0, right = chunk->num_elements;
+
+       while (left < right) {
+               int pos = (left + right) / 2;
+               MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
+               gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
+
+               if (addr < code_end)
+                       right = pos;
+               else
+                       left = pos + 1;
+       }
+       g_assert (left == right);
+
+       return left;
+}
+
+static MonoJitInfo*
+jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint8 *addr)
+{
+       MonoJitInfo *ji;
+       int chunk_pos, pos;
+
+       chunk_pos = jit_info_table_index (table, (gint8*)addr);
+       g_assert (chunk_pos < table->num_chunks);
+
+       pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
+
+       /* We now have a position that's very close to that of the
+          first element whose end address is higher than the one
+          we're looking for.  If we don't have the exact position,
+          then we have a position below that one, so we'll just
+          search upward until we find our element. */
+       do {
+               MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
+
+               while (pos < chunk->num_elements) {
+                       ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
+
+                       ++pos;
+
+                       if (IS_JIT_INFO_TOMBSTONE (ji)) {
+                               mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
+                               continue;
+                       }
+                       if ((gint8*)addr >= (gint8*)ji->code_start
+                                       && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
+                               mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
+                               return ji;
+                       }
+
+                       /* If we find a non-tombstone element which is already
+                          beyond what we're looking for, we have to end the
+                          search. */
+                       if ((gint8*)addr < (gint8*)ji->code_start)
+                               goto not_found;
+               }
+
+               ++chunk_pos;
+               pos = 0;
+       } while (chunk_pos < table->num_chunks);
+
+ not_found:
+       if (hp)
+               mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
+       return NULL;
+}
+
+/*
+ * mono_jit_info_table_find_internal:
+ *
+ * If TRY_AOT is FALSE, avoid loading information for missing methods from AOT images, which is currently not async safe.
+ * In this case, only those AOT methods will be found whose jit info is already loaded.
+ * ASYNC SAFETY: When called in an async context (mono_thread_info_is_async_context ()), this is async safe.
+ * In this case, the returned MonoJitInfo might not have metadata information, in particular,
+ * mono_jit_info_get_method () could fail.
+ */
+MonoJitInfo*
+mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot)
+{
+       MonoJitInfoTable *table;
+       MonoJitInfo *ji, *module_ji;
+       MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
+
+       ++mono_stats.jit_info_table_lookup_count;
+
+       /* First we have to get the domain's jit_info_table.  This is
+          complicated by the fact that a writer might substitute a
+          new table and free the old one.  What the writer guarantees
+          us is that it looks at the hazard pointers after it has
+          changed the jit_info_table pointer.  So, if we guard the
+          table by a hazard pointer and make sure that the pointer is
+          still there after we've made it hazardous, we don't have to
+          worry about the writer freeing the table. */
+       table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
+
+       ji = jit_info_table_find (table, hp, (gint8*)addr);
+       if (hp)
+               mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
+       if (ji)
+               return ji;
+
+       /* Maybe its an AOT module */
+       if (try_aot && mono_get_root_domain () && mono_get_root_domain ()->aot_modules) {
+               table = get_hazardous_pointer ((gpointer volatile*)&mono_get_root_domain ()->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX);
+               module_ji = jit_info_table_find (table, hp, (gint8*)addr);
+               if (module_ji)
+                       ji = jit_info_find_in_aot_func (domain, module_ji->d.image, addr);
+               if (hp)
+                       mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
+       }
+       
+       return ji;
+}
+
+MonoJitInfo*
+mono_jit_info_table_find (MonoDomain *domain, char *addr)
+{
+       return mono_jit_info_table_find_internal (domain, addr, TRUE);
+}
+
+static G_GNUC_UNUSED void
+jit_info_table_check (MonoJitInfoTable *table)
+{
+       int i;
+
+       for (i = 0; i < table->num_chunks; ++i) {
+               MonoJitInfoTableChunk *chunk = table->chunks [i];
+               int j;
+
+               g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
+               if (chunk->refcount > 10)
+                       printf("warning: chunk refcount is %d\n", chunk->refcount);
+               g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
+
+               for (j = 0; j < chunk->num_elements; ++j) {
+                       MonoJitInfo *this = chunk->data [j];
+                       MonoJitInfo *next;
+
+                       g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
+
+                       if (j < chunk->num_elements - 1)
+                               next = chunk->data [j + 1];
+                       else if (i < table->num_chunks - 1) {
+                               int k;
+
+                               for (k = i + 1; k < table->num_chunks; ++k)
+                                       if (table->chunks [k]->num_elements > 0)
+                                               break;
+
+                               if (k >= table->num_chunks)
+                                       return;
+
+                               g_assert (table->chunks [k]->num_elements > 0);
+                               next = table->chunks [k]->data [0];
+                       } else
+                               return;
+
+                       g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
+               }
+       }
+}
+
+static MonoJitInfoTable*
+jit_info_table_realloc (MonoJitInfoTable *old)
+{
+       int i;
+       int num_elements = jit_info_table_num_elements (old);
+       int required_size;
+       int num_chunks;
+       int new_chunk, new_element;
+       MonoJitInfoTable *new;
+
+       /* number of needed places for elements needed */
+       required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
+       num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
+       if (num_chunks == 0) {
+               g_assert (num_elements == 0);
+               return mono_jit_info_table_new (old->domain);
+       }
+       g_assert (num_chunks > 0);
+
+       new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
+       new->domain = old->domain;
+       new->num_chunks = num_chunks;
+
+       for (i = 0; i < num_chunks; ++i)
+               new->chunks [i] = jit_info_table_new_chunk ();
+
+       new_chunk = 0;
+       new_element = 0;
+       for (i = 0; i < old->num_chunks; ++i) {
+               MonoJitInfoTableChunk *chunk = old->chunks [i];
+               int chunk_num_elements = chunk->num_elements;
+               int j;
+
+               for (j = 0; j < chunk_num_elements; ++j) {
+                       if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
+                               g_assert (new_chunk < num_chunks);
+                               new->chunks [new_chunk]->data [new_element] = chunk->data [j];
+                               if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
+                                       new->chunks [new_chunk]->num_elements = new_element;
+                                       ++new_chunk;
+                                       new_element = 0;
+                               }
+                       }
+               }
+       }
+
+       if (new_chunk < num_chunks) {
+               g_assert (new_chunk == num_chunks - 1);
+               new->chunks [new_chunk]->num_elements = new_element;
+               g_assert (new->chunks [new_chunk]->num_elements > 0);
+       }
+
+       for (i = 0; i < num_chunks; ++i) {
+               MonoJitInfoTableChunk *chunk = new->chunks [i];
+               MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
+
+               new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
+       }
+
+       return new;
+}
+
+static void
+jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
+{
+       MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
+       MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
+
+       g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
+
+       new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
+       new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
+
+       memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
+       memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
+
+       new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
+               + new1->data [new1->num_elements - 1]->code_size;
+       new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
+               + new2->data [new2->num_elements - 1]->code_size;
+
+       *new1p = new1;
+       *new2p = new2;
+}
+
+static MonoJitInfoTable*
+jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
+{
+       MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
+               + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
+       int i, j;
+
+       new_table->domain = table->domain;
+       new_table->num_chunks = table->num_chunks + 1;
+
+       j = 0;
+       for (i = 0; i < table->num_chunks; ++i) {
+               if (table->chunks [i] == chunk) {
+                       jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
+                       j += 2;
+               } else {
+                       new_table->chunks [j] = table->chunks [i];
+                       ++new_table->chunks [j]->refcount;
+                       ++j;
+               }
+       }
+
+       g_assert (j == new_table->num_chunks);
+
+       return new_table;
+}
+
+static MonoJitInfoTableChunk*
+jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
+{
+       MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
+       int i, j;
+
+       j = 0;
+       for (i = 0; i < old->num_elements; ++i) {
+               if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
+                       new->data [j++] = old->data [i];
+       }
+
+       new->num_elements = j;
+       if (new->num_elements > 0)
+               new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
+       else
+               new->last_code_end = old->last_code_end;
+
+       return new;
+}
+
+static MonoJitInfoTable*
+jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
+{
+       MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
+               + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
+       int i, j;
+
+       new_table->domain = table->domain;
+       new_table->num_chunks = table->num_chunks;
+
+       j = 0;
+       for (i = 0; i < table->num_chunks; ++i) {
+               if (table->chunks [i] == chunk)
+                       new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
+               else {
+                       new_table->chunks [j] = table->chunks [i];
+                       ++new_table->chunks [j]->refcount;
+                       ++j;
+               }
+       }
+
+       g_assert (j == new_table->num_chunks);
+
+       return new_table;
+}
+
+/* As we add an element to the table the case can arise that the chunk
+ * to which we need to add is already full.  In that case we have to
+ * allocate a new table and do something about that chunk.  We have
+ * several strategies:
+ *
+ * If the number of elements in the table is below the low watermark
+ * or above the high watermark, we reallocate the whole table.
+ * Otherwise we only concern ourselves with the overflowing chunk:
+ *
+ * If there are no tombstones in the chunk then we split the chunk in
+ * two, each half full.
+ *
+ * If the chunk does contain tombstones, we just make a new copy of
+ * the chunk without the tombstones, which will have room for at least
+ * the one element we have to add.
+ */
+static MonoJitInfoTable*
+jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
+{
+       int num_elements = jit_info_table_num_elements (table);
+       int i;
+
+       if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
+                       || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
+               //printf ("reallocing table\n");
+               return jit_info_table_realloc (table);
+       }
+
+       /* count the number of non-tombstone elements in the chunk */
+       num_elements = 0;
+       for (i = 0; i < chunk->num_elements; ++i) {
+               if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
+                       ++num_elements;
+       }
+
+       if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
+               //printf ("splitting chunk\n");
+               return jit_info_table_copy_and_split_chunk (table, chunk);
+       }
+
+       //printf ("purifying chunk\n");
+       return jit_info_table_copy_and_purify_chunk (table, chunk);
+}
+
+/* We add elements to the table by first making space for them by
+ * shifting the elements at the back to the right, one at a time.
+ * This results in duplicate entries during the process, but during
+ * all the time the table is in a sorted state.  Also, when an element
+ * is replaced by another one, the element that replaces it has an end
+ * address that is equal to or lower than that of the replaced
+ * element.  That property is necessary to guarantee that when
+ * searching for an element we end up at a position not higher than
+ * the one we're looking for (i.e. we either find the element directly
+ * or we end up to the left of it).
+ */
+static void
+jit_info_table_add (MonoDomain *domain, MonoJitInfoTable *volatile *table_ptr, MonoJitInfo *ji)
+{
+       MonoJitInfoTable *table;
+       MonoJitInfoTableChunk *chunk;
+       int chunk_pos, pos;
+       int num_elements;
+       int i;
+
+       table = *table_ptr;
+
+ restart:
+       chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
+       g_assert (chunk_pos < table->num_chunks);
+       chunk = table->chunks [chunk_pos];
+
+       if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
+               MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
+
+               /* Debugging code, should be removed. */
+               //jit_info_table_check (new_table);
+
+               *table_ptr = new_table;
+               mono_memory_barrier ();
+               domain->num_jit_info_tables++;
+               mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)mono_jit_info_table_free, TRUE, FALSE);
+               table = new_table;
+
+               goto restart;
+       }
+
+       /* Debugging code, should be removed. */
+       //jit_info_table_check (table);
+
+       num_elements = chunk->num_elements;
+
+       pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
+
+       /* First we need to size up the chunk by one, by copying the
+          last item, or inserting the first one, if the table is
+          empty. */
+       if (num_elements > 0)
+               chunk->data [num_elements] = chunk->data [num_elements - 1];
+       else
+               chunk->data [0] = ji;
+       mono_memory_write_barrier ();
+       chunk->num_elements = ++num_elements;
+
+       /* Shift the elements up one by one. */
+       for (i = num_elements - 2; i >= pos; --i) {
+               mono_memory_write_barrier ();
+               chunk->data [i + 1] = chunk->data [i];
+       }
+
+       /* Now we have room and can insert the new item. */
+       mono_memory_write_barrier ();
+       chunk->data [pos] = ji;
+
+       /* Set the high code end address chunk entry. */
+       chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
+               + chunk->data [chunk->num_elements - 1]->code_size;
+
+       /* Debugging code, should be removed. */
+       //jit_info_table_check (table);
+}
+
+void
+mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
+{
+       g_assert (ji->d.method != NULL);
+
+       mono_domain_lock (domain);
+
+       ++mono_stats.jit_info_table_insert_count;
+
+       jit_info_table_add (domain, &domain->jit_info_table, ji);
+
+       mono_domain_unlock (domain);
+}
+
+static MonoJitInfo*
+mono_jit_info_make_tombstone (MonoJitInfo *ji)
+{
+       MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
+
+       tombstone->code_start = ji->code_start;
+       tombstone->code_size = ji->code_size;
+       tombstone->d.method = JIT_INFO_TOMBSTONE_MARKER;
+
+       return tombstone;
+}
+
+/*
+ * LOCKING: domain lock
+ */
+static void
+mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
+{
+       if (domain->num_jit_info_tables <= 1) {
+               /* Can it actually happen that we only have one table
+                  but ji is still hazardous? */
+               mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
+       } else {
+               domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
+       }
+}
+
+static void
+jit_info_table_remove (MonoJitInfoTable *table, MonoJitInfo *ji)
+{
+       MonoJitInfoTableChunk *chunk;
+       gpointer start = ji->code_start;
+       int chunk_pos, pos;
+
+       chunk_pos = jit_info_table_index (table, start);
+       g_assert (chunk_pos < table->num_chunks);
+
+       pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
+
+       do {
+               chunk = table->chunks [chunk_pos];
+
+               while (pos < chunk->num_elements) {
+                       if (chunk->data [pos] == ji)
+                               goto found;
+
+                       g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
+                       g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
+                               <= (guint8*)ji->code_start + ji->code_size);
+
+                       ++pos;
+               }
+
+               ++chunk_pos;
+               pos = 0;
+       } while (chunk_pos < table->num_chunks);
+
+ found:
+       g_assert (chunk->data [pos] == ji);
+
+       chunk->data [pos] = mono_jit_info_make_tombstone (ji);
+
+       /* Debugging code, should be removed. */
+       //jit_info_table_check (table);
+}
+
+void
+mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
+{
+       MonoJitInfoTable *table;
+
+       mono_domain_lock (domain);
+       table = domain->jit_info_table;
+
+       ++mono_stats.jit_info_table_remove_count;
+
+       jit_info_table_remove (table, ji);
+
+       mono_jit_info_free_or_queue (domain, ji);
+
+       mono_domain_unlock (domain);
+}
+
+void
+mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
+{
+       MonoJitInfo *ji;
+       MonoDomain *domain = mono_get_root_domain ();
+
+       g_assert (domain);
+       mono_domain_lock (domain);
+
+       /*
+        * We reuse MonoJitInfoTable to store AOT module info,
+        * this gives us async-safe lookup.
+        */
+       if (!domain->aot_modules) {
+               domain->num_jit_info_tables ++;
+               domain->aot_modules = mono_jit_info_table_new (domain);
+       }
+
+       ji = g_new0 (MonoJitInfo, 1);
+       ji->d.image = image;
+       ji->code_start = start;
+       ji->code_size = (guint8*)end - (guint8*)start;
+       jit_info_table_add (domain, &domain->aot_modules, ji);
+
+       mono_domain_unlock (domain);
+}
+
+void
+mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
+{
+       jit_info_find_in_aot_func = func;
+}
+
+int
+mono_jit_info_size (MonoJitInfoFlags flags, int num_clauses, int num_holes)
+{
+       int size = MONO_SIZEOF_JIT_INFO;
+
+       size += num_clauses * sizeof (MonoJitExceptionInfo);
+       if (flags & JIT_INFO_HAS_CAS_INFO)
+               size += sizeof (MonoMethodCasInfo);
+       if (flags & JIT_INFO_HAS_GENERIC_JIT_INFO)
+               size += sizeof (MonoGenericJitInfo);
+       if (flags & JIT_INFO_HAS_TRY_BLOCK_HOLES)
+               size += sizeof (MonoTryBlockHoleTableJitInfo) + num_holes * sizeof (MonoTryBlockHoleJitInfo);
+       if (flags & JIT_INFO_HAS_ARCH_EH_INFO)
+               size += sizeof (MonoArchEHJitInfo);
+       return size;
+}
+
+void
+mono_jit_info_init (MonoJitInfo *ji, MonoMethod *method, guint8 *code, int code_size,
+                                       MonoJitInfoFlags flags, int num_clauses, int num_holes)
+{
+       ji->d.method = method;
+       ji->code_start = code;
+       ji->code_size = code_size;
+       ji->num_clauses = num_clauses;
+       if (flags & JIT_INFO_HAS_CAS_INFO)
+               ji->has_cas_info = 1;
+       if (flags & JIT_INFO_HAS_GENERIC_JIT_INFO)
+               ji->has_generic_jit_info = 1;
+       if (flags & JIT_INFO_HAS_TRY_BLOCK_HOLES)
+               ji->has_try_block_holes = 1;
+       if (flags & JIT_INFO_HAS_ARCH_EH_INFO)
+               ji->has_arch_eh_info = 1;
+}
+
+gpointer
+mono_jit_info_get_code_start (MonoJitInfo* ji)
+{
+       return ji->code_start;
+}
+
+int
+mono_jit_info_get_code_size (MonoJitInfo* ji)
+{
+       return ji->code_size;
+}
+
+MonoMethod*
+mono_jit_info_get_method (MonoJitInfo* ji)
+{
+       g_assert (!ji->async);
+       return ji->d.method;
+}
+
+static gpointer
+jit_info_key_extract (gpointer value)
+{
+       MonoJitInfo *info = (MonoJitInfo*)value;
+
+       return info->d.method;
+}
+
+static gpointer*
+jit_info_next_value (gpointer value)
+{
+       MonoJitInfo *info = (MonoJitInfo*)value;
+
+       return (gpointer*)&info->next_jit_code_hash;
+}
+
+void
+mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
+{
+       mono_internal_hash_table_init (jit_code_hash,
+                                      mono_aligned_addr_hash,
+                                      jit_info_key_extract,
+                                      jit_info_next_value);
+}
+
+MonoGenericJitInfo*
+mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
+{
+       if (ji->has_generic_jit_info)
+               return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
+       else
+               return NULL;
+}
+
+/*
+ * mono_jit_info_get_generic_sharing_context:
+ * @ji: a jit info
+ *
+ * Returns the jit info's generic sharing context, or NULL if it
+ * doesn't have one.
+ */
+MonoGenericSharingContext*
+mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
+{
+       MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
+
+       if (gi)
+               return gi->generic_sharing_context;
+       else
+               return NULL;
+}
+
+/*
+ * mono_jit_info_set_generic_sharing_context:
+ * @ji: a jit info
+ * @gsctx: a generic sharing context
+ *
+ * Sets the jit info's generic sharing context.  The jit info must
+ * have memory allocated for the context.
+ */
+void
+mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
+{
+       MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
+
+       g_assert (gi);
+
+       gi->generic_sharing_context = gsctx;
+}
+
+MonoTryBlockHoleTableJitInfo*
+mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
+{
+       if (ji->has_try_block_holes) {
+               char *ptr = (char*)&ji->clauses [ji->num_clauses];
+               if (ji->has_generic_jit_info)
+                       ptr += sizeof (MonoGenericJitInfo);
+               return (MonoTryBlockHoleTableJitInfo*)ptr;
+       } else {
+               return NULL;
+       }
+}
+
+static int
+try_block_hole_table_size (MonoJitInfo *ji)
+{
+       MonoTryBlockHoleTableJitInfo *table;
+
+       table = mono_jit_info_get_try_block_hole_table_info (ji);
+       g_assert (table);
+       return sizeof (MonoTryBlockHoleTableJitInfo) + table->num_holes * sizeof (MonoTryBlockHoleJitInfo);
+}
+
+MonoArchEHJitInfo*
+mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
+{
+       if (ji->has_arch_eh_info) {
+               char *ptr = (char*)&ji->clauses [ji->num_clauses];
+               if (ji->has_generic_jit_info)
+                       ptr += sizeof (MonoGenericJitInfo);
+               if (ji->has_try_block_holes)
+                       ptr += try_block_hole_table_size (ji);
+               return (MonoArchEHJitInfo*)ptr;
+       } else {
+               return NULL;
+       }
+}
+
+MonoMethodCasInfo*
+mono_jit_info_get_cas_info (MonoJitInfo *ji)
+{
+       if (ji->has_cas_info) {
+               char *ptr = (char*)&ji->clauses [ji->num_clauses];
+               if (ji->has_generic_jit_info)
+                       ptr += sizeof (MonoGenericJitInfo);
+               if (ji->has_try_block_holes)
+                       ptr += try_block_hole_table_size (ji);
+               if (ji->has_arch_eh_info)
+                       ptr += sizeof (MonoArchEHJitInfo);
+               return (MonoMethodCasInfo*)ptr;
+       } else {
+               return NULL;
+       }
+}
index 7a9d2258d12eae120e02b9ceb83e293625d3dec6..859fb69c55bf16d3e46548a37aeba73973c843e8 100644 (file)
@@ -24,6 +24,7 @@ struct _MonoWSQ {
        volatile gint tail;
        MonoArray *queue;
        gint32 mask;
+       gint32 suspended;
        MonoSemType lock;
 };
 
@@ -61,6 +62,7 @@ mono_wsq_create ()
 
        wsq = g_new0 (MonoWSQ, 1);
        wsq->mask = INITIAL_LENGTH - 1;
+       wsq->suspended = 0;
        MONO_GC_REGISTER_ROOT_SINGLE (wsq->queue);
        root = mono_get_root_domain ();
        wsq->queue = mono_array_new_cached (root, mono_defaults.object_class, INITIAL_LENGTH);
@@ -72,6 +74,12 @@ mono_wsq_create ()
        return wsq;
 }
 
+gboolean
+mono_wsq_suspend (MonoWSQ *wsq)
+{
+       return InterlockedCompareExchange (&wsq->suspended, 1, 0) == 0;
+}
+
 void
 mono_wsq_destroy (MonoWSQ *wsq)
 {
@@ -112,6 +120,11 @@ mono_wsq_local_push (void *obj)
                return FALSE;
        }
 
+       if (wsq->suspended) {
+               WSQ_DEBUG ("local_push: wsq suspended\n");
+               return FALSE;
+       }
+
        tail = wsq->tail;
        if (tail < wsq->head + wsq->mask) {
                mono_array_setref (wsq->queue, tail & wsq->mask, (MonoObject *) obj);
index 7208dadb6b99da6700a0db4041a2e5031e76977a..ccb064d4f180f2db73e5fce54802c500242a3b49 100644 (file)
@@ -20,6 +20,7 @@ gboolean mono_wsq_local_push (void *obj) MONO_INTERNAL;
 gboolean mono_wsq_local_pop (void **ptr) MONO_INTERNAL;
 void mono_wsq_try_steal (MonoWSQ *wsq, void **ptr, guint32 ms_timeout) MONO_INTERNAL;
 gint mono_wsq_count (MonoWSQ *wsq) MONO_INTERNAL;
+gboolean mono_wsq_suspend (MonoWSQ *wsq) MONO_INTERNAL;
 
 G_END_DECLS
 
index a2aa759293b742fa9fb342ecee505d4949476464..b9abf073f057b6bff0a1ddf21a1464150c2f24b9 100644 (file)
@@ -5041,10 +5041,10 @@ mono_string_new_size (MonoDomain *domain, gint32 len)
        size_t size;
 
        /* check for overflow */
-       if (len < 0 || len > ((SIZE_MAX - sizeof (MonoString) - 2) / 2))
+       if (len < 0 || len > ((SIZE_MAX - offsetof (MonoString, chars) - 2) / 2))
                mono_gc_out_of_memory (-1);
 
-       size = (sizeof (MonoString) + ((len + 1) * 2));
+       size = (offsetof (MonoString, chars) + ((len + 1) * 2));
        g_assert (size > 0);
 
        vtable = mono_class_vtable (domain, mono_defaults.string_class);
index c9e0f8bf63bf27db907c41d4c8a460e6c848da1f..d7cc110aec6bbca2ac91b363582f40410cf1fba0 100644 (file)
 #include <mono/utils/strenc.h>
 #include <mono/utils/mono-proclib.h>
 #include <mono/io-layer/io-layer.h>
-#ifndef HAVE_GETPROCESSID
-#if defined(_MSC_VER) || defined(HAVE_WINTERNL_H)
-#include <winternl.h>
-#ifndef NT_SUCCESS
-#define NT_SUCCESS(status) ((NTSTATUS) (status) >= 0)
-#endif /* !NT_SUCCESS */
-#else /* ! (defined(_MSC_VER) || defined(HAVE_WINTERNL_H)) */
-#include <ddk/ntddk.h>
-#include <ddk/ntapi.h>
-#endif /* (defined(_MSC_VER) || defined(HAVE_WINTERNL_H)) */
-#endif /* !HAVE_GETPROCESSID */
-/* FIXME: fix this code to not depend so much on the inetrnals */
+/* FIXME: fix this code to not depend so much on the internals */
 #include <mono/metadata/class-internals.h>
 
 #define LOGDEBUG(...)  
@@ -60,11 +49,12 @@ HANDLE ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
        return(handle);
 }
 
-guint32 ves_icall_System_Diagnostics_Process_GetPid_internal (void)
+guint32
+ves_icall_System_Diagnostics_Process_GetPid_internal (void)
 {
        MONO_ARCH_SAVE_REGS;
 
-       return(GetCurrentProcessId ());
+       return mono_process_current_pid ();
 }
 
 void ves_icall_System_Diagnostics_Process_Process_free_internal (MonoObject *this,
@@ -525,76 +515,6 @@ complete_path (const gunichar2 *appname, gchar **completed)
        return TRUE;
 }
 
-#ifndef HAVE_GETPROCESSID
-/* Run-time GetProcessId detection for Windows */
-#ifdef TARGET_WIN32
-#define HAVE_GETPROCESSID
-
-typedef DWORD (WINAPI *GETPROCESSID_PROC) (HANDLE);
-typedef DWORD (WINAPI *NTQUERYINFORMATIONPROCESS_PROC) (HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
-typedef DWORD (WINAPI *RTLNTSTATUSTODOSERROR_PROC) (NTSTATUS);
-
-static DWORD WINAPI GetProcessId_detect (HANDLE process);
-
-static GETPROCESSID_PROC GetProcessId = &GetProcessId_detect;
-static NTQUERYINFORMATIONPROCESS_PROC NtQueryInformationProcess_proc = NULL;
-static RTLNTSTATUSTODOSERROR_PROC RtlNtStatusToDosError_proc = NULL;
-
-static DWORD WINAPI GetProcessId_ntdll (HANDLE process)
-{
-       PROCESS_BASIC_INFORMATION pi;
-       NTSTATUS status;
-
-       status = NtQueryInformationProcess_proc (process, ProcessBasicInformation, &pi, sizeof (pi), NULL);
-       if (NT_SUCCESS (status)) {
-               return pi.UniqueProcessId;
-       } else {
-               SetLastError (RtlNtStatusToDosError_proc (status));
-               return 0;
-       }
-}
-
-static DWORD WINAPI GetProcessId_stub (HANDLE process)
-{
-       SetLastError (ERROR_CALL_NOT_IMPLEMENTED);
-       return 0;
-}
-
-static DWORD WINAPI GetProcessId_detect (HANDLE process)
-{
-       HMODULE module_handle;
-       GETPROCESSID_PROC GetProcessId_kernel;
-
-       /* Windows XP SP1 and above have GetProcessId API */
-       module_handle = GetModuleHandle (L"kernel32.dll");
-       if (module_handle != NULL) {
-               GetProcessId_kernel = (GETPROCESSID_PROC) GetProcAddress (module_handle, "GetProcessId");
-               if (GetProcessId_kernel != NULL) {
-                       GetProcessId = GetProcessId_kernel;
-                       return GetProcessId (process);
-               }
-       }
-
-       /* Windows 2000 and above have deprecated NtQueryInformationProcess API */
-       module_handle = GetModuleHandle (L"ntdll.dll");
-       if (module_handle != NULL) {
-               NtQueryInformationProcess_proc = (NTQUERYINFORMATIONPROCESS_PROC) GetProcAddress (module_handle, "NtQueryInformationProcess");
-               if (NtQueryInformationProcess_proc != NULL) {
-                       RtlNtStatusToDosError_proc = (RTLNTSTATUSTODOSERROR_PROC) GetProcAddress (module_handle, "RtlNtStatusToDosError");
-                       if (RtlNtStatusToDosError_proc != NULL) {
-                               GetProcessId = &GetProcessId_ntdll;
-                               return GetProcessId (process);
-                       }
-               }
-       }
-
-       /* Fall back to ERROR_CALL_NOT_IMPLEMENTED */
-       GetProcessId = &GetProcessId_stub;
-       return GetProcessId (process);
-}
-#endif /* HOST_WIN32 */
-#endif /* !HAVE_GETPROCESSID */
-
 MonoBoolean ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_info)
 {
        SHELLEXECUTEINFO shellex = {0};
@@ -891,14 +811,33 @@ MonoString *ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE pr
 /* Returns an array of pids */
 MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
 {
+#if !defined(HOST_WIN32)
+       MonoArray *procs;
+       gpointer *pidarray;
+       int i, count;
+
+       MONO_ARCH_SAVE_REGS;
+
+       pidarray = mono_process_list (&count);
+       if (!pidarray)
+               mono_raise_exception (mono_get_exception_not_supported ("This system does not support EnumProcesses"));
+       procs = mono_array_new (mono_domain_get (), mono_get_int32_class (), count);
+       if (sizeof (guint32) == sizeof (gpointer)) {
+               memcpy (mono_array_addr (procs, guint32, 0), pidarray, count);
+       } else {
+               for (i = 0; i < count; ++i)
+                       *(mono_array_addr (procs, guint32, i)) = GPOINTER_TO_UINT (pidarray [i]);
+       }
+       g_free (pidarray);
+
+       return procs;
+#else
        MonoArray *procs;
        gboolean ret;
        DWORD needed;
-       guint32 count;
+       int count;
        guint32 *pids;
 
-       MONO_ARCH_SAVE_REGS;
-
        count = 512;
        do {
                pids = g_new0 (guint32, count);
@@ -926,6 +865,7 @@ MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
        pids = NULL;
        
        return procs;
+#endif
 }
 
 MonoBoolean ves_icall_System_Diagnostics_Process_GetWorkingSet_internal (HANDLE process, guint32 *min, guint32 *max)
index 1b7570ef8cb10dc998350d654f8a6252461efa5a..6614b01e1e9863aec5a44153b0f9b5c85365b290 100644 (file)
@@ -7802,12 +7802,15 @@ mono_reflection_get_token (MonoObject *obj)
 
                if (is_field_on_inst (f->field)) {
                        MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
-                       int field_index = f->field - dgclass->fields;
-                       MonoObject *obj;
 
-                       g_assert (field_index >= 0 && field_index < dgclass->count_fields);
-                       obj = dgclass->field_objects [field_index];
-                       return mono_reflection_get_token (obj);
+                       if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
+                               int field_index = f->field - dgclass->fields;
+                               MonoObject *obj;
+
+                               g_assert (field_index >= 0 && field_index < dgclass->count_fields);
+                               obj = dgclass->field_objects [field_index];
+                               return mono_reflection_get_token (obj);
+                       }
                }
                token = mono_class_get_field_token (f->field);
        } else if (strcmp (klass->name, "MonoProperty") == 0) {
index d9a52e9b195bc77f0fdd509add23ba094a7644e4..3b0c3a3ec335e070449a21edf73a0e16c527ac53 100644 (file)
@@ -189,9 +189,12 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size)
        void **p;
        char *new_next;
        TLAB_ACCESS_INIT;
+       size_t real_size = size;
+       
+       CANARIFY_SIZE(size);
 
        HEAVY_STAT (++stat_objects_alloced);
-       if (size <= SGEN_MAX_SMALL_OBJ_SIZE)
+       if (real_size <= SGEN_MAX_SMALL_OBJ_SIZE)
                HEAVY_STAT (stat_bytes_alloced += size);
        else
                HEAVY_STAT (stat_bytes_alloced_los += size);
@@ -207,7 +210,7 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size)
                if (collect_before_allocs) {
                        if (((current_alloc % collect_before_allocs) == 0) && nursery_section) {
                                sgen_perform_collection (0, GENERATION_NURSERY, "collect-before-alloc-triggered", TRUE);
-                               if (!degraded_mode && sgen_can_alloc_size (size) && size <= SGEN_MAX_SMALL_OBJ_SIZE) {
+                               if (!degraded_mode && sgen_can_alloc_size (size) && real_size <= SGEN_MAX_SMALL_OBJ_SIZE) {
                                        // FIXME:
                                        g_assert_not_reached ();
                                }
@@ -229,8 +232,8 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size)
         * specially by the world-stopping code.
         */
 
-       if (size > SGEN_MAX_SMALL_OBJ_SIZE) {
-               p = sgen_los_alloc_large_inner (vtable, size);
+       if (real_size > SGEN_MAX_SMALL_OBJ_SIZE) {
+               p = sgen_los_alloc_large_inner (vtable, ALIGN_UP (real_size));
        } else {
                /* tlab_next and tlab_temp_end are TLS vars so accessing them might be expensive */
 
@@ -247,6 +250,7 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size)
                         * visible before the vtable store.
                         */
 
+                       CANARIFY_ALLOC(p,real_size);
                        SGEN_LOG (6, "Allocated object %p, vtable: %p (%s), size: %zd", p, vtable, vtable->klass->name, size);
                        binary_protocol_alloc (p , vtable, size);
                        if (G_UNLIKELY (MONO_GC_NURSERY_OBJ_ALLOC_ENABLED ()))
@@ -290,7 +294,7 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size)
                                do {
                                        p = sgen_nursery_alloc (size);
                                        if (!p) {
-                                               sgen_ensure_free_space (size);
+                                               sgen_ensure_free_space (real_size);
                                                if (degraded_mode)
                                                        return alloc_degraded (vtable, size, FALSE);
                                                else
@@ -347,13 +351,14 @@ mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size)
                        TLAB_TEMP_END = MIN (TLAB_REAL_END, TLAB_NEXT + SGEN_SCAN_START_SIZE);
                        SGEN_LOG (5, "Expanding local alloc: %p-%p", TLAB_NEXT, TLAB_TEMP_END);
                }
+               CANARIFY_ALLOC(p,real_size);
        }
 
        if (G_LIKELY (p)) {
                SGEN_LOG (6, "Allocated object %p, vtable: %p (%s), size: %zd", p, vtable, vtable->klass->name, size);
                binary_protocol_alloc (p, vtable, size);
                if (G_UNLIKELY (MONO_GC_MAJOR_OBJ_ALLOC_LARGE_ENABLED ()|| MONO_GC_NURSERY_OBJ_ALLOC_ENABLED ())) {
-                       if (size > SGEN_MAX_SMALL_OBJ_SIZE)
+                       if (real_size > SGEN_MAX_SMALL_OBJ_SIZE)
                                MONO_GC_MAJOR_OBJ_ALLOC_LARGE ((mword)p, size, vtable->klass->name_space, vtable->klass->name);
                        else
                                MONO_GC_NURSERY_OBJ_ALLOC ((mword)p, size, vtable->klass->name_space, vtable->klass->name);
@@ -370,12 +375,15 @@ mono_gc_try_alloc_obj_nolock (MonoVTable *vtable, size_t size)
        void **p;
        char *new_next;
        TLAB_ACCESS_INIT;
+       size_t real_size = size;
+
+       CANARIFY_SIZE(size);
 
        size = ALIGN_UP (size);
-       SGEN_ASSERT (9, size >= sizeof (MonoObject), "Object too small");
+       SGEN_ASSERT (9, real_size >= sizeof (MonoObject), "Object too small");
 
        g_assert (vtable->gc_descr);
-       if (size > SGEN_MAX_SMALL_OBJ_SIZE)
+       if (real_size > SGEN_MAX_SMALL_OBJ_SIZE)
                return NULL;
 
        if (G_UNLIKELY (size > tlab_size)) {
@@ -440,6 +448,7 @@ mono_gc_try_alloc_obj_nolock (MonoVTable *vtable, size_t size)
        HEAVY_STAT (++stat_objects_alloced);
        HEAVY_STAT (stat_bytes_alloced += size);
 
+       CANARIFY_ALLOC(p,real_size);
        SGEN_LOG (6, "Allocated object %p, vtable: %p (%s), size: %zd", p, vtable, vtable->klass->name, size);
        binary_protocol_alloc (p, vtable, size);
        if (G_UNLIKELY (MONO_GC_NURSERY_OBJ_ALLOC_ENABLED ()))
@@ -887,7 +896,7 @@ create_allocator (int atype)
                /*
                 * a string allocator method takes the args: (vtable, len)
                 *
-                * bytes = sizeof (MonoString) + ((len + 1) * 2)
+                * bytes = offsetof (MonoString, chars) + ((len + 1) * 2)
                 *
                 * condition:
                 *
@@ -895,11 +904,11 @@ create_allocator (int atype)
                 *
                 * therefore:
                 *
-                * sizeof (MonoString) + ((len + 1) * 2) <= INT32_MAX - (SGEN_ALLOC_ALIGN - 1)
-                * len <= (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - sizeof (MonoString)) / 2 - 1
+                * offsetof (MonoString, chars) + ((len + 1) * 2) <= INT32_MAX - (SGEN_ALLOC_ALIGN - 1)
+                * len <= (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - offsetof (MonoString, chars)) / 2 - 1
                 */
                mono_mb_emit_ldarg (mb, 1);
-               mono_mb_emit_icon (mb, (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - sizeof (MonoString)) / 2 - 1);
+               mono_mb_emit_icon (mb, (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - MONO_STRUCT_OFFSET (MonoString, chars)) / 2 - 1);
                pos = mono_mb_emit_short_branch (mb, MONO_CEE_BLE_UN_S);
 
                mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
@@ -911,7 +920,7 @@ create_allocator (int atype)
                mono_mb_emit_icon (mb, 1);
                mono_mb_emit_byte (mb, MONO_CEE_SHL);
                //WE manually fold the above + 2 here
-               mono_mb_emit_icon (mb, sizeof (MonoString) + 2);
+               mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoString, chars) + 2);
                mono_mb_emit_byte (mb, CEE_ADD);
                mono_mb_emit_stloc (mb, size_var);
        } else {
index b86ec318c7cb8bfb0e2139c578deacf455b507c9..420dc96e47d64a32daae9252133c0ff82f336693 100644 (file)
 #ifndef __MONO_SGENARCHDEP_H__
 #define __MONO_SGENARCHDEP_H__
 
-#include <mono/utils/mono-sigcontext.h>
+#include <mono/utils/mono-context.h>
+
+/*
+ * Define either USE_MONO_CTX, or
+ * ARCH_SIGCTX_SP/ARCH_SIGCTX_IP/ARCH_STORE_REGS/ARCH_COPY_SIGCTX_REGS.
+ * Define ARCH_NUM_REGS to be the number of general registers in MonoContext, or the
+ * number of registers stored by ARCH_STORE_REGS.
+ */
 
 #if defined(MONO_CROSS_COMPILE)
 
 
 #elif defined(TARGET_X86)
 
-#include <mono/utils/mono-context.h>
-
 #define REDZONE_SIZE   0
 
 #define ARCH_NUM_REGS 8
 
-#ifdef MONO_ARCH_HAS_MONO_CONTEXT
-#define USE_MONO_CTX
-#else
+#ifndef MONO_ARCH_HAS_MONO_CONTEXT
 #error 0
 #endif
 
-/*FIXME, move this to mono-sigcontext as this is generaly useful.*/
-#define ARCH_SIGCTX_SP(ctx)    (UCONTEXT_REG_ESP ((ctx)))
-#define ARCH_SIGCTX_IP(ctx)    (UCONTEXT_REG_EIP ((ctx)))
+#define USE_MONO_CTX
 
 #elif defined(TARGET_AMD64)
 
-#include <mono/utils/mono-context.h>
-
 #define REDZONE_SIZE   128
 
 #define ARCH_NUM_REGS 16
 #define USE_MONO_CTX
 
-/*FIXME, move this to mono-sigcontext as this is generaly useful.*/
-#define ARCH_SIGCTX_SP(ctx)    (UCONTEXT_REG_RSP (ctx))
-#define ARCH_SIGCTX_IP(ctx)    (UCONTEXT_REG_RIP (ctx))
-
 #elif defined(TARGET_POWERPC)
 
 #define REDZONE_SIZE   224
 
 /* We dont store ip, sp */
 #define ARCH_NUM_REGS 14
-#define ARCH_STORE_REGS(ptr)           \
-       __asm__ __volatile__(                   \
-               "push {lr}\n"                           \
-               "mov lr, %0\n"                          \
-               "stmia lr!, {r0-r12}\n"         \
-               "pop {lr}\n"                            \
-               :                                                       \
-               : "r" (ptr)                                     \
-       )
-
-#define ARCH_SIGCTX_SP(ctx)    (UCONTEXT_REG_SP((ctx)))
-#define ARCH_SIGCTX_IP(ctx)    (UCONTEXT_REG_PC((ctx)))
-#define ARCH_COPY_SIGCTX_REGS(a,ctx) do {                      \
-       ((a)[0]) = (gpointer) (UCONTEXT_REG_R0((ctx)));         \
-       ((a)[1]) = (gpointer) (UCONTEXT_REG_R1((ctx)));         \
-       ((a)[2]) = (gpointer) (UCONTEXT_REG_R2((ctx)));         \
-       ((a)[3]) = (gpointer) (UCONTEXT_REG_R3((ctx)));         \
-       ((a)[4]) = (gpointer) (UCONTEXT_REG_R4((ctx)));         \
-       ((a)[5]) = (gpointer) (UCONTEXT_REG_R5((ctx)));         \
-       ((a)[6]) = (gpointer) (UCONTEXT_REG_R6((ctx)));         \
-       ((a)[7]) = (gpointer) (UCONTEXT_REG_R7((ctx)));         \
-       ((a)[8]) = (gpointer) (UCONTEXT_REG_R8((ctx)));         \
-       ((a)[9]) = (gpointer) (UCONTEXT_REG_R9((ctx)));         \
-       ((a)[10]) = (gpointer) (UCONTEXT_REG_R10((ctx)));       \
-       ((a)[11]) = (gpointer) (UCONTEXT_REG_R11((ctx)));       \
-       ((a)[12]) = (gpointer) (UCONTEXT_REG_R12((ctx)));       \
-       ((a)[13]) = (gpointer) (UCONTEXT_REG_LR((ctx)));        \
-       } while (0)
 
 #elif defined(TARGET_ARM64)
 
-#include <mono/utils/mono-sigcontext.h>
-
 #ifdef __linux__
 #define REDZONE_SIZE    0
 #elif defined(__APPLE__)
 #define USE_MONO_CTX
 #define ARCH_NUM_REGS 31
 
-#define ARCH_STORE_REGS(ptr) do { g_assert_not_reached (); } while (0)
-
-#define ARCH_SIGCTX_SP(ctx)    UCONTEXT_REG_SP (ctx)
-#define ARCH_SIGCTX_IP(ctx)    UCONTEXT_REG_PC (ctx)
-#define ARCH_COPY_SIGCTX_REGS(a,ctx) do { g_assert_not_reached (); } while (0)
-
 #elif defined(__mips__)
 
 #define REDZONE_SIZE   0
 #define USE_MONO_CTX
 #define ARCH_NUM_REGS 32
 
-/*
- * These casts are necessary since glibc always makes the
- * gregs 64-bit values in userland.
- */
-#define ARCH_SIGCTX_SP(ctx)    ((gsize) UCONTEXT_GREGS((ctx))[29])
-#define ARCH_SIGCTX_IP(ctx)    ((gsize) UCONTEXT_REG_PC((ctx)))
-
 #elif defined(__s390x__)
 
 #define REDZONE_SIZE   0
 
-#include <mono/utils/mono-context.h>
-
 #define USE_MONO_CTX
 #define ARCH_NUM_REGS 16       
-#define ARCH_SIGCTX_SP(ctx)    ((UCONTEXT_GREGS((ctx))) [15])
-#define ARCH_SIGCTX_IP(ctx)    ((ucontext_t *) (ctx))->uc_mcontext.psw.addr
 
 #elif defined(__sparc__)
 
index 7ee7e07bee31616d3ee43a3e3cc6324be5e41acf..6dd91e2444261a132c8a5ed2c57bc95733a6c103 100644 (file)
@@ -479,22 +479,6 @@ mono_gc_card_table_nursery_check (void)
 }
 
 #if 0
-static void
-collect_faulted_cards (void)
-{
-#define CARD_PAGES (CARD_COUNT_IN_BYTES / 4096)
-       int i, count = 0;
-       unsigned char faulted [CARD_PAGES] = { 0 };
-       mincore (sgen_cardtable, CARD_COUNT_IN_BYTES, faulted);
-
-       for (i = 0; i < CARD_PAGES; ++i) {
-               if (faulted [i])
-                       ++count;
-       }
-
-       printf ("TOTAL card pages %d faulted %d\n", CARD_PAGES, count);
-}
-
 void
 sgen_card_table_dump_obj_card (char *object, size_t size, void *dummy)
 {
index def25a77cddc5802f10fc172b1b17e5ebb9a12bf..4b0b5a320121f3c064437be958d7da70e149d8fc 100644 (file)
@@ -290,6 +290,7 @@ static gboolean disable_major_collections = FALSE;
 gboolean do_pin_stats = FALSE;
 static gboolean do_verify_nursery = FALSE;
 static gboolean do_dump_nursery_content = FALSE;
+static gboolean enable_nursery_canaries = FALSE;
 
 #ifdef HEAVY_STATISTICS
 long long stat_objects_alloced_degraded = 0;
@@ -346,6 +347,8 @@ static long long time_major_los_sweep = 0;
 static long long time_major_sweep = 0;
 static long long time_major_fragment_creation = 0;
 
+static long long time_max = 0;
+
 static SGEN_TV_DECLARE (time_major_conc_collection_start);
 static SGEN_TV_DECLARE (time_major_conc_collection_end);
 
@@ -392,6 +395,12 @@ safe_name (void* obj)
        return vt->klass->name;
 }
 
+gboolean
+nursery_canaries_enabled (void)
+{
+       return enable_nursery_canaries;
+}
+
 #define safe_object_get_size   sgen_safe_object_get_size
 
 const char*
@@ -631,10 +640,14 @@ sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc
                        obj = start;
                }
 
-               size = ALIGN_UP (safe_object_get_size ((MonoObject*)obj));
-
-               if ((MonoVTable*)SGEN_LOAD_VTABLE (obj) != array_fill_vtable)
+               if ((MonoVTable*)SGEN_LOAD_VTABLE (obj) != array_fill_vtable) {
+                       CHECK_CANARY_FOR_OBJECT (obj);
+                       size = ALIGN_UP (safe_object_get_size ((MonoObject*)obj));
                        callback (obj, size, data);
+                       CANARIFY_SIZE (size);
+               } else {
+                       size = ALIGN_UP (safe_object_get_size ((MonoObject*)obj));
+               }
 
                start += size;
        }
@@ -693,8 +706,10 @@ clear_domain_process_object (char *obj, MonoDomain *domain)
 static void
 clear_domain_process_minor_object_callback (char *obj, size_t size, MonoDomain *domain)
 {
-       if (clear_domain_process_object (obj, domain))
+       if (clear_domain_process_object (obj, domain)) {
+               CANARIFY_SIZE (size);
                memset (obj, 0, size);
+       }
 }
 
 static void
@@ -986,6 +1001,11 @@ pin_objects_from_nursery_pin_queue (ScanCopyContext ctx)
                        }
 
                        /* Skip to the next object */
+                       if (((MonoObject*)search_start)->synchronisation != GINT_TO_POINTER (-1)) {
+                               CHECK_CANARY_FOR_OBJECT (search_start);
+                               CANARIFY_SIZE (obj_size);
+                               CANARIFY_SIZE (obj_to_pin_size);
+                       }
                        search_start = (void*)((char*)search_start + obj_size);
                } while (search_start <= addr);
 
@@ -1910,6 +1930,8 @@ init_stats (void)
        if (inited)
                return;
 
+       mono_counters_register ("Collection max time",  MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME | MONO_COUNTER_MONOTONIC, &time_max);
+
        mono_counters_register ("Minor fragment clear", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_pre_collection_fragment_clear);
        mono_counters_register ("Minor pinning", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_pinning);
        mono_counters_register ("Minor scan remembered set", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_scan_remsets);
@@ -2096,6 +2118,9 @@ verify_nursery (void)
 
        if (!do_verify_nursery)
                return;
+               
+       if (nursery_canaries_enabled ())
+               SGEN_LOG (1, "Checking nursery canaries...");
 
        /*This cleans up unused fragments */
        sgen_nursery_allocator_prepare_for_pinning ();
@@ -2124,6 +2149,10 @@ verify_nursery (void)
                                SGEN_LOG (1, "HOLE [%p %p %d]", hole_start, cur, (int)(cur - hole_start));
                        SGEN_LOG (1, "OBJ  [%p %p %d %d %s %d]", cur, cur + size, (int)size, (int)ss, sgen_safe_name ((MonoObject*)cur), (gpointer)LOAD_VTABLE (cur) == sgen_get_array_fill_vtable ());
                }
+               if (nursery_canaries_enabled () && (MonoVTable*)SGEN_LOAD_VTABLE (cur) != array_fill_vtable) {
+                       CHECK_CANARY_FOR_OBJECT (cur);
+                       CANARIFY_SIZE (size);
+               }
                cur += size;
                hole_start = cur;
        }
@@ -3119,6 +3148,8 @@ void
 sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish)
 {
        TV_DECLARE (gc_end);
+       TV_DECLARE (gc_total_start);
+       TV_DECLARE (gc_total_end);
        GGTimingInfo infos [2];
        int overflow_generation_to_collect = -1;
        int oldest_generation_collected = generation_to_collect;
@@ -3141,6 +3172,8 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const
 
        sgen_stop_world (generation_to_collect);
 
+       TV_GETTIME (gc_total_start);
+
        if (concurrent_collection_in_progress) {
                if (major_update_or_finish_concurrent_collection (wait_to_finish && generation_to_collect == GENERATION_OLD)) {
                        oldest_generation_collected = GENERATION_OLD;
@@ -3220,6 +3253,9 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const
  done:
        g_assert (sgen_gray_object_queue_is_empty (&gray_queue));
 
+       TV_GETTIME (gc_total_end);
+       time_max = MAX (time_max, TV_ELAPSED (gc_total_start, gc_total_end));
+
        sgen_restart_world (oldest_generation_collected, infos);
 
        mono_profiler_gc_event (MONO_GC_EVENT_END, generation_to_collect);
@@ -4334,6 +4370,25 @@ mono_gc_get_los_limit (void)
        return MAX_SMALL_OBJ_SIZE;
 }
 
+void
+mono_gc_set_string_length (MonoString *str, gint32 new_length)
+{
+       mono_unichar2 *new_end = str->chars + new_length;
+       
+       /* zero the discarded string. This null-delimits the string and allows 
+        * the space to be reclaimed by SGen. */
+        
+       if (nursery_canaries_enabled () && sgen_ptr_in_nursery (str)) {
+               CHECK_CANARY_FOR_OBJECT (str);
+               memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2) + CANARY_SIZE);
+               memcpy (new_end + 1 , CANARY_STRING, CANARY_SIZE);
+       } else {
+               memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2));
+       }
+       
+       str->length = new_length;
+}
+
 gboolean
 mono_gc_user_markers_supported (void)
 {
@@ -4845,11 +4900,7 @@ mono_gc_base_init (void)
                                if (opt [0] == ':')
                                        opt++;
                                if (opt [0]) {
-#ifdef HOST_WIN32
-                                       char *rf = g_strdup_printf ("%s.%d", opt, GetCurrentProcessId ());
-#else
-                                       char *rf = g_strdup_printf ("%s.%d", opt, getpid ());
-#endif
+                                       char *rf = g_strdup_printf ("%s.%d", opt, mono_process_current_pid ());
                                        gc_debug_file = fopen (rf, "wb");
                                        if (!gc_debug_file)
                                                gc_debug_file = stderr;
@@ -4936,6 +4987,10 @@ mono_gc_base_init (void)
                                        *colon = '\0';
                                }
                                binary_protocol_init (filename, (long long)limit);
+                       } else if (!strcmp (opt, "nursery-canaries")) {
+                               do_verify_nursery = TRUE;
+                               sgen_set_use_managed_allocator (FALSE);
+                               enable_nursery_canaries = TRUE;
                        } else if (!sgen_bridge_handle_gc_debug (opt)) {
                                sgen_env_var_error (MONO_GC_DEBUG_NAME, "Ignoring.", "Unknown option `%s`.", opt);
 
@@ -4965,6 +5020,7 @@ mono_gc_base_init (void)
                                fprintf (stderr, "  print-pinning\n");
                                fprintf (stderr, "  heap-dump=<filename>\n");
                                fprintf (stderr, "  binary-protocol=<filename>[:<file-size-limit>]\n");
+                               fprintf (stderr, "  nursery-canaries\n");
                                sgen_bridge_print_gc_debug_usage ();
                                fprintf (stderr, "\n");
 
@@ -5345,4 +5401,8 @@ mono_gc_register_finalizer_callbacks (MonoGCFinalizerCallbacks *callbacks)
        fin_callbacks = *callbacks;
 }
 
+
+
+
+
 #endif /* HAVE_SGEN_GC */
index 076d03bc9d76aac344229817b5f2579d2395f333..12121dc723f7dadc9fad2acce63e771cbe8f99a8 100644 (file)
@@ -731,7 +731,7 @@ slow_object_get_size (MonoVTable *vtable, MonoObject* o)
         * mono_array_length_fast not using the object's vtable.
         */
        if (klass == mono_defaults.string_class) {
-               return sizeof (MonoString) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
+               return offsetof (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
        } else if (klass->rank) {
                MonoArray *array = (MonoArray*)o;
                size_t size = sizeof (MonoArray) + klass->sizes.element_size * mono_array_length_fast (array);
@@ -782,7 +782,7 @@ sgen_par_object_get_size (MonoVTable *vtable, MonoObject* o)
        if (type == DESC_TYPE_RUN_LENGTH || type == DESC_TYPE_SMALL_BITMAP) {
                mword size = descr & 0xfff8;
                if (size == 0) /* This is used to encode a string */
-                       return sizeof (MonoString) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
+                       return offsetof (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
                return size;
        } else if (type == DESC_TYPE_VECTOR) {
                int element_size = ((descr) >> VECTOR_ELSIZE_SHIFT) & MAX_ELEMENT_SIZE;
@@ -811,6 +811,22 @@ sgen_safe_object_get_size (MonoObject *obj)
        return sgen_par_object_get_size ((MonoVTable*)SGEN_LOAD_VTABLE (obj), obj);
 }
 
+/*
+ * This variant guarantees to return the exact size of the object
+ * before alignment. Needed for canary support.
+ */
+static inline guint
+sgen_safe_object_get_size_unaligned (MonoObject *obj)
+{
+       char *forwarded;
+
+       if ((forwarded = SGEN_OBJECT_IS_FORWARDED (obj))) {
+               obj = (MonoObject*)forwarded;
+       }
+
+       return slow_object_get_size ((MonoVTable*)SGEN_LOAD_VTABLE (obj), obj);
+}
+
 const char* sgen_safe_name (void* obj) MONO_INTERNAL;
 
 gboolean sgen_object_is_live (void *obj) MONO_INTERNAL;
@@ -1144,6 +1160,37 @@ void sgen_env_var_error (const char *env_var, const char *fallback, const char *
 void sgen_qsort (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*)) MONO_INTERNAL;
 gint64 sgen_timestamp (void) MONO_INTERNAL;
 
+/*
+ * Canary (guard word) support
+ * Notes:
+ * - CANARY_SIZE must be multiple of word size in bytes
+ * - Canary space is not included on checks against SGEN_MAX_SMALL_OBJ_SIZE
+ */
+gboolean nursery_canaries_enabled (void) MONO_INTERNAL;
+
+#define CANARY_SIZE 8
+#define CANARY_STRING  "koupepia"
+
+#define CANARIFY_SIZE(size) if (nursery_canaries_enabled ()) { \
+                       size = size + CANARY_SIZE;      \
+               }
+
+#define CANARIFY_ALLOC(addr,size) if (nursery_canaries_enabled ()) {   \
+                               memcpy ((char*) (addr) + (size), CANARY_STRING, CANARY_SIZE);   \
+                       }
+
+#define CANARY_VALID(addr) (strncmp ((char*) (addr), CANARY_STRING, CANARY_SIZE) == 0)
+
+#define CHECK_CANARY_FOR_OBJECT(addr) if (nursery_canaries_enabled ()) {       \
+                               char* canary_ptr = (char*) (addr) + sgen_safe_object_get_size_unaligned ((MonoObject *) (addr));        \
+                               if (!CANARY_VALID(canary_ptr)) {        \
+                                       char canary_copy[CANARY_SIZE +1];       \
+                                       strncpy (canary_copy, canary_ptr, 8);   \
+                                       canary_copy[CANARY_SIZE] = 0;   \
+                                       g_error ("CORRUPT CANARY:\naddr->%p\ntype->%s\nexcepted->'%s'\nfound->'%s'\n", (char*) addr, ((MonoObject*)addr)->vtable->klass->name, CANARY_STRING, canary_copy);     \
+                               } }
+                                
 #endif /* HAVE_SGEN_GC */
 
 #endif /* __MONO_SGENGC_H__ */
index 9474d7cec5acf7c72e0ace70cd3c1b5cae8b92b7..333f8c3ee419261cdd9e103d4b7b4779cf1dce0f 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "utils/mono-counters.h"
 #include "metadata/sgen-gc.h"
+#include "utils/mono-mmap.h"
 #include "utils/lock-free-alloc.h"
 #include "metadata/sgen-memory-governor.h"
 
@@ -32,7 +33,7 @@ static const int allocator_sizes [] = {
           8,   16,   24,   32,   40,   48,   64,   80,
          96,  128,  160,  192,  224,  248,  296,  320,
         384,  448,  504,  528,  584,  680,  816, 1088,
-       1360, 2040, 2336, 2728, 3272, 4088, 5456, 8184 };
+       1360, 2044, 2336, 2728, 3272, 4092, 5456, 8188 };
 #else
 static const int allocator_sizes [] = {
           8,   16,   24,   32,   40,   48,   64,   80,
@@ -43,9 +44,32 @@ static const int allocator_sizes [] = {
 
 #define NUM_ALLOCATORS (sizeof (allocator_sizes) / sizeof (int))
 
+static int allocator_block_sizes [NUM_ALLOCATORS];
+
 static MonoLockFreeAllocSizeClass size_classes [NUM_ALLOCATORS];
 static MonoLockFreeAllocator allocators [NUM_ALLOCATORS];
 
+#ifdef HEAVY_STATISTICS
+static int allocator_sizes_stats [NUM_ALLOCATORS];
+#endif
+
+static size_t
+block_size (size_t slot_size)
+{
+       static int pagesize = -1;
+
+       int size;
+
+       if (pagesize == -1)
+               pagesize = mono_pagesize ();
+
+       for (size = pagesize; size < LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) {
+               if (slot_size * 2 <= LOCK_FREE_ALLOC_SB_USABLE_SIZE (size))
+                       return size;
+       }
+       return LOCK_FREE_ALLOC_SB_MAX_SIZE;
+}
+
 /*
  * Find the allocator index for memory chunks that can contain @size
  * objects.
@@ -75,6 +99,7 @@ sgen_register_fixed_internal_mem_type (int type, size_t size)
        int slot;
 
        g_assert (type >= 0 && type < INTERNAL_MEM_MAX);
+       g_assert (size <= allocator_sizes [NUM_ALLOCATORS - 1]);
 
        slot = index_for_size (size);
        g_assert (slot >= 0);
@@ -143,6 +168,10 @@ sgen_alloc_internal_dynamic (size_t size, int type, gboolean assert_on_failure)
        } else {
                index = index_for_size (size);
 
+#ifdef HEAVY_STATISTICS
+               ++ allocator_sizes_stats [index];
+#endif
+
                p = mono_lock_free_alloc (&allocators [index]);
                if (!p)
                        sgen_assert_memory_alloc (NULL, size, description_for_type (type));
@@ -162,7 +191,7 @@ sgen_free_internal_dynamic (void *addr, size_t size, int type)
        if (size > allocator_sizes [NUM_ALLOCATORS - 1])
                sgen_free_os_memory (addr, size, SGEN_ALLOC_INTERNAL);
        else
-               mono_lock_free_free (addr);
+               mono_lock_free_free (addr, block_size (size));
 
        MONO_GC_INTERNAL_DEALLOC ((mword)addr, size, type);
 }
@@ -170,10 +199,18 @@ sgen_free_internal_dynamic (void *addr, size_t size, int type)
 void*
 sgen_alloc_internal (int type)
 {
-       int index = fixed_type_allocator_indexes [type];
-       int size = allocator_sizes [index];
+       int index, size;
        void *p;
+
+       index = fixed_type_allocator_indexes [type];
        g_assert (index >= 0 && index < NUM_ALLOCATORS);
+
+#ifdef HEAVY_STATISTICS
+       ++ allocator_sizes_stats [index];
+#endif
+
+       size = allocator_sizes [index];
+
        p = mono_lock_free_alloc (&allocators [index]);
        memset (p, 0, size);
 
@@ -193,7 +230,7 @@ sgen_free_internal (void *addr, int type)
        index = fixed_type_allocator_indexes [type];
        g_assert (index >= 0 && index < NUM_ALLOCATORS);
 
-       mono_lock_free_free (addr);
+       mono_lock_free_free (addr, allocator_block_sizes [index]);
 
        if (MONO_GC_INTERNAL_DEALLOC_ENABLED ()) {
                int size G_GNUC_UNUSED = allocator_sizes [index];
@@ -219,22 +256,37 @@ sgen_dump_internal_mem_usage (FILE *heap_dump_file)
 void
 sgen_report_internal_mem_usage (void)
 {
-       /* FIXME: implement */
-       printf ("not implemented yet\n");
+       int i G_GNUC_UNUSED;
+#ifdef HEAVY_STATISTICS
+       printf ("size -> # allocations\n");
+       for (i = 0; i < NUM_ALLOCATORS; ++i)
+               printf ("%d -> %d\n", allocator_sizes [i], allocator_sizes_stats [i]);
+#endif
 }
 
 void
 sgen_init_internal_allocator (void)
 {
-       int i;
+       int i, size;
 
        for (i = 0; i < INTERNAL_MEM_MAX; ++i)
                fixed_type_allocator_indexes [i] = -1;
 
        for (i = 0; i < NUM_ALLOCATORS; ++i) {
-               mono_lock_free_allocator_init_size_class (&size_classes [i], allocator_sizes [i]);
+               allocator_block_sizes [i] = block_size (allocator_sizes [i]);
+               mono_lock_free_allocator_init_size_class (&size_classes [i], allocator_sizes [i], allocator_block_sizes [i]);
                mono_lock_free_allocator_init_allocator (&allocators [i], &size_classes [i]);
        }
+
+       for (size = mono_pagesize (); size <= LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) {
+               int max_size = LOCK_FREE_ALLOC_SB_USABLE_SIZE (size) / 2;
+               /*
+                * we assert that allocator_sizes contains the biggest possible object size
+                * per block (4K => 4080 / 2 = 2040, 8k => 8176 / 2 = 4088, 16k => 16368 / 2 = 8184 on 64bits),
+                * so that we do not get different block sizes for sizes that should go to the same one
+                */
+               g_assert (allocator_sizes [index_for_size (max_size)] == max_size);
+       }
 }
 
 #endif
index 448ebef3f05ff0df0ebabe70767c76c197de9a30..5d17a0d721cb0d1c08b4daa4c1f6d84991f8592b 100644 (file)
@@ -48,6 +48,7 @@ static double save_target_ratio = SGEN_DEFAULT_SAVE_TARGET_RATIO;
 /**/
 static mword allocated_heap;
 static mword total_alloc = 0;
+static mword total_alloc_max = 0;
 
 /* GC triggers. */
 
@@ -72,21 +73,13 @@ static mword last_collection_los_memory_alloced;
 static mword sgen_memgov_available_free_space (void);
 
 
-static mword
-double_to_mword_with_saturation (double value)
-{
-       if (value >= (double)MWORD_MAX_VALUE)
-               return MWORD_MAX_VALUE;
-       return (mword)value;
-}
-
 /* GC trigger heuristics. */
 
 static void
 sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite)
 {
-       size_t num_major_sections, num_major_sections_saved;
-       mword los_memory_saved, new_major, new_heap_size, save_target, allowance_target;
+       size_t num_major_sections;
+       mword new_major, new_heap_size, allowance_target;
 
        if (overwrite)
                g_assert (need_calculate_minor_collection_allowance);
@@ -102,32 +95,16 @@ sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite)
 
        num_major_sections = major_collector.get_num_major_sections ();
 
-       num_major_sections_saved = MAX (last_collection_old_num_major_sections - num_major_sections, 0);
-       los_memory_saved = MAX (last_collection_old_los_memory_usage - last_collection_los_memory_usage, 1);
-
        new_major = num_major_sections * major_collector.section_size;
        new_heap_size = new_major + last_collection_los_memory_usage;
 
-       save_target = (mword)((new_major + last_collection_los_memory_usage) * SGEN_DEFAULT_SAVE_TARGET_RATIO);
-
        /*
-        * We aim to allow the allocation of as many sections as is
-        * necessary to reclaim save_target sections in the next
-        * collection.  We assume the collection pattern won't change.
-        * In the last cycle, we had num_major_sections_saved for
-        * minor_collection_sections_alloced.  Assuming things won't
-        * change, this must be the same ratio as save_target for
-        * allowance_target, i.e.
-        *
-        *    num_major_sections_saved            save_target
-        * --------------------------------- == ----------------
-        * minor_collection_sections_alloced    allowance_target
-        *
-        * hence:
+        * We allow the heap to grow by one third its current size before we start the next
+        * major collection.
         */
-       allowance_target = double_to_mword_with_saturation ((double)save_target * (double)(minor_collection_sections_alloced * major_collector.section_size + last_collection_los_memory_alloced) / (double)(num_major_sections_saved * major_collector.section_size + los_memory_saved));
+       allowance_target = new_heap_size / 3;
 
-       minor_collection_allowance = MAX (MIN (allowance_target, num_major_sections * major_collector.section_size + los_memory_usage), MIN_MINOR_COLLECTION_ALLOWANCE);
+       minor_collection_allowance = MAX (allowance_target, MIN_MINOR_COLLECTION_ALLOWANCE);
 
        if (new_heap_size + minor_collection_allowance > soft_heap_limit) {
                if (new_heap_size > soft_heap_limit)
@@ -311,6 +288,7 @@ sgen_alloc_os_memory (size_t size, SgenAllocFlags flags, const char *assert_desc
                SGEN_ATOMIC_ADD_P (total_alloc, size);
                if (flags & SGEN_ALLOC_HEAP)
                        MONO_GC_HEAP_ALLOC ((mword)ptr, size);
+               total_alloc_max = MAX (total_alloc_max, total_alloc);
        }
        return ptr;
 }
@@ -329,6 +307,7 @@ sgen_alloc_os_memory_aligned (size_t size, mword alignment, SgenAllocFlags flags
                SGEN_ATOMIC_ADD_P (total_alloc, size);
                if (flags & SGEN_ALLOC_HEAP)
                        MONO_GC_HEAP_ALLOC ((mword)ptr, size);
+               total_alloc_max = MAX (total_alloc_max, total_alloc);
        }
        return ptr;
 }
@@ -345,6 +324,7 @@ sgen_free_os_memory (void *addr, size_t size, SgenAllocFlags flags)
        SGEN_ATOMIC_ADD_P (total_alloc, -(gssize)size);
        if (flags & SGEN_ALLOC_HEAP)
                MONO_GC_HEAP_FREE ((mword)addr, size);
+       total_alloc_max = MAX (total_alloc_max, total_alloc);
 }
 
 int64_t
@@ -392,6 +372,9 @@ sgen_memgov_init (size_t max_heap, size_t soft_limit, gboolean debug_allowance,
        debug_print_allowance = debug_allowance;
        minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
 
+       mono_counters_register ("Memgov alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, &total_alloc);
+       mono_counters_register ("Memgov max alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_MONOTONIC, &total_alloc_max);
+
        if (max_heap == 0)
                return;
 
index 6fc63e5496133c8e8c277c20eca68c09bd917808..01d1bd1a7960cc908c2da78769993a689e53e529 100644 (file)
@@ -785,9 +785,10 @@ sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_
                                GRAY_OBJECT_ENQUEUE (unpin_queue, addr0, sgen_obj_get_descriptor_safe (addr0));
                        else
                                SGEN_UNPIN_OBJECT (addr0);
+                       size = SGEN_ALIGN_UP (sgen_safe_object_get_size ((MonoObject*)addr0));
+                       CANARIFY_SIZE (size);
                        sgen_set_nursery_scan_start (addr0);
                        frag_end = addr0;
-                       size = SGEN_ALIGN_UP (sgen_safe_object_get_size ((MonoObject*)addr0));
                        ++i;
                } else {
                        frag_end = addr1;
@@ -871,7 +872,7 @@ sgen_can_alloc_size (size_t size)
 void*
 sgen_nursery_alloc (size_t size)
 {
-       SGEN_ASSERT (1, size >= sizeof (MonoObject) && size <= SGEN_MAX_SMALL_OBJ_SIZE, "Invalid nursery object size");
+       SGEN_ASSERT (1, size >= sizeof (MonoObject) && size <= (SGEN_MAX_SMALL_OBJ_SIZE + CANARY_SIZE), "Invalid nursery object size");
 
        SGEN_LOG (4, "Searching nursery for size: %zd", size);
        size = SGEN_ALIGN_UP (size);
index 909b8382c81e2863355d1f1f5e4c3c50a40b032f..55acf5137c38a9b740e1f4f2eb025ea779a10c36 100644 (file)
@@ -56,17 +56,30 @@ suspend_thread (SgenThreadInfo *info, void *context)
 #ifndef USE_MONO_CTX
        gpointer regs [ARCH_NUM_REGS];
 #endif
+       MonoContext ctx;
        gpointer stack_start;
 
        info->stopped_domain = mono_domain_get ();
-       info->stopped_ip = context ? (gpointer) ARCH_SIGCTX_IP (context) : NULL;
        info->signal = 0;
        stop_count = sgen_global_stop_count;
        /* duplicate signal */
        if (0 && info->stop_count == stop_count)
                return;
 
+#ifdef USE_MONO_CTX
+       if (context) {
+               mono_sigctx_to_monoctx (context, &ctx);
+               info->stopped_ip = MONO_CONTEXT_GET_IP (&ctx);
+               stack_start = MONO_CONTEXT_GET_SP (&ctx) - REDZONE_SIZE;
+       } else {
+               info->stopped_ip = NULL;
+               stack_start = NULL;
+       }
+#else
+       info->stopped_ip = context ? (gpointer) ARCH_SIGCTX_IP (context) : NULL;
        stack_start = context ? (char*) ARCH_SIGCTX_SP (context) - REDZONE_SIZE : NULL;
+#endif
+
        /* If stack_start is not within the limits, then don't set it
           in info and we will be restarted. */
        if (stack_start >= info->stack_start_limit && info->stack_start <= info->stack_end) {
@@ -74,7 +87,7 @@ suspend_thread (SgenThreadInfo *info, void *context)
 
 #ifdef USE_MONO_CTX
                if (context) {
-                       mono_sigctx_to_monoctx (context, &info->ctx);
+                       memcpy (&info->ctx, &ctx, sizeof (MonoContext));
                } else {
                        memset (&info->ctx, 0, sizeof (MonoContext));
                }
@@ -122,7 +135,7 @@ suspend_thread (SgenThreadInfo *info, void *context)
 }
 
 /* LOCKING: assumes the GC lock is held (by the stopping thread) */
-MONO_SIGNAL_HANDLER_FUNC (static, suspend_handler, (int sig, siginfo_t *siginfo, void *context))
+MONO_SIG_HANDLER_FUNC (static, suspend_handler)
 {
        /*
         * The suspend signal handler potentially uses syscalls that
@@ -131,19 +144,19 @@ MONO_SIGNAL_HANDLER_FUNC (static, suspend_handler, (int sig, siginfo_t *siginfo,
         * must restore those to the values they had when we
         * interrupted.
         */
-
        SgenThreadInfo *info;
        int old_errno = errno;
        int hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
        info = mono_thread_info_current ();
-       suspend_thread (info, context);
+       suspend_thread (info, ctx);
 
        mono_hazard_pointer_restore_for_signal_handler (hp_save_index);
        errno = old_errno;
 }
 
-MONO_SIGNAL_HANDLER_FUNC (static, restart_handler, (int sig))
+MONO_SIG_HANDLER_FUNC (static, restart_handler)
 {
        SgenThreadInfo *info;
        int old_errno = errno;
index f99c5bc5ced23aef4155f8645b7e2a9483de06cf..3c1d8fb6c61d8d036a670924fd68f6c768984acb 100644 (file)
@@ -98,7 +98,7 @@ sgen_pointer_queue_sort_uniq (SgenPointerQueue *queue)
        end = queue->data + queue->next_slot;
        while (cur < end) {
                *start = *cur++;
-               while (*start == *cur && cur < end)
+               while (cur < end && *start == *cur)
                        cur++;
                start++;
        };
index 5a2ab0e968730c6085c111060753d217ae5f6b7c..2a9bf34788c6826a485c41998a56dee33e553072 100644 (file)
@@ -52,7 +52,7 @@ align_pointer (void *ptr)
 #ifdef USE_MONO_CTX
 static MonoContext cur_thread_ctx;
 #else
-static mword cur_thread_regs [ARCH_NUM_REGS] = {0};
+static mword cur_thread_regs [ARCH_NUM_REGS];
 #endif
 
 static void
index cbce0f772694e052aecff7c62090ddb2140fa93c..949164e5548c4e82fcc5f27f9c524c9963c825ba 100644 (file)
 #include <glib.h>
 #include <string.h>
 #include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <errno.h>
-
-#include <sys/types.h>
 #ifdef HOST_WIN32
 #include <ws2tcpip.h>
 #else
 #include <netdb.h>
 #include <arpa/inet.h>
 #endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#include <sys/types.h>
 
 #include <mono/metadata/object.h>
 #include <mono/io-layer/io-layer.h>
index 0927141e7925f92d753c6579aa0905c816131f22..22b1fbbbdb49a2aed23b58776bc07811f7c39496 100644 (file)
@@ -65,5 +65,12 @@ ves_icall_System_String_GetLOSLimit (void)
 {
        int limit = mono_gc_get_los_limit ();
 
-       return (limit - 2 - sizeof (MonoString)) / 2;
+       return (limit - 2 - offsetof (MonoString, chars)) / 2;
 }
+
+void
+ves_icall_System_String_InternalSetLength (MonoString *str, gint32 new_length)
+{
+       mono_gc_set_string_length (str, new_length);
+}
+
index a0b831a1e2006411eecc26190d60ca4df45c4f27..33bcf80378b006c177992070ddac209613660b34 100644 (file)
@@ -30,4 +30,7 @@ ves_icall_System_String_InternalIsInterned (MonoString *str) MONO_INTERNAL;
 int
 ves_icall_System_String_GetLOSLimit (void) MONO_INTERNAL;
 
+void
+ves_icall_System_String_InternalSetLength (MonoString *str, gint32 new_length) MONO_INTERNAL;
+
 #endif /* _MONO_CLI_STRING_ICALLS_H_ */
index 39ade54daa14f83a12c5982a15be9d014e30f289..36514cc6ea8a06c0f26c553ecb68e59de2d846a7 100644 (file)
@@ -41,6 +41,7 @@
 #include <unistd.h>
 #endif
 #include <string.h>
+#include <math.h>
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
 #define THREAD_WANTS_A_BREAK(t) ((t->state & (ThreadState_StopRequested | \
                                                ThreadState_SuspendRequested)) != 0)
 
-#define SPIN_TRYLOCK(i) (InterlockedCompareExchange (&(i), 1, 0) == 0)
-#define SPIN_LOCK(i) do { \
-                               if (SPIN_TRYLOCK (i)) \
-                                       break; \
-                       } while (1)
-
-#define SPIN_UNLOCK(i) i = 0
 #define SMALL_STACK (128 * (sizeof (gpointer) / 4) * 1024)
 
 /* DEBUG: prints tp data every 2s */
@@ -83,6 +77,12 @@ enum {
        KQUEUE_BACKEND
 };
 
+enum {
+       MONITOR_STATE_AWAKE,
+       MONITOR_STATE_FALLING_ASLEEP,
+       MONITOR_STATE_SLEEPING
+};
+
 typedef struct {
        mono_mutex_t io_lock; /* access to sock_to_state */
        int inited; // 0 -> not initialized , 1->initializing, 2->initialized, 3->cleaned up
@@ -127,12 +127,10 @@ typedef struct {
        void *pc_nthreads; /* Performance counter for total number of active threads */
        /**/
        volatile gint destroy_thread;
-       volatile gint ignore_times; /* Used when there's a thread being created or destroyed */
-       volatile gint sp_lock; /* spin lock used to protect ignore_times */
-       volatile gint64 last_check;
-       volatile gint64 time_sum;
-       volatile gint n_sum;
-       gint64 averages [2];
+#if DEBUG
+       volatile gint32 njobs;
+#endif
+       volatile gint32 nexecuted;
        gboolean is_io;
 } ThreadPool;
 
@@ -148,6 +146,7 @@ static void threadpool_init (ThreadPool *tp, int min_threads, int max_threads, v
 static void threadpool_start_idle_threads (ThreadPool *tp);
 static void threadpool_kill_idle_threads (ThreadPool *tp);
 static gboolean threadpool_start_thread (ThreadPool *tp);
+static void threadpool_kill_thread (ThreadPool *tp);
 static void monitor_thread (gpointer data);
 static void socket_io_cleanup (SocketIOData *data);
 static MonoObject *get_io_event (MonoMList **list, gint event);
@@ -159,10 +158,17 @@ static MonoClass *async_call_klass;
 static MonoClass *socket_async_call_klass;
 static MonoClass *process_async_call_klass;
 
+static GPtrArray *threads;
+mono_mutex_t threads_lock;
 static GPtrArray *wsqs;
 mono_mutex_t wsqs_lock;
 static gboolean suspended;
 
+static volatile gint32 monitor_njobs = 0;
+static volatile gint32 monitor_state;
+static MonoSemType monitor_sem;
+static MonoInternalThread *monitor_internal_thread;
+
 /* Hooks */
 static MonoThreadPoolFunc tp_start_func;
 static MonoThreadPoolFunc tp_finish_func;
@@ -656,6 +662,16 @@ mono_async_invoke (ThreadPool *tp, MonoAsyncResult *ares)
                mono_thread_set_execution_context (ares->original_context);
                ares->original_context = NULL;
        }
+
+#if DEBUG
+       InterlockedDecrement (&tp->njobs);
+#endif
+       if (!tp->is_io)
+               InterlockedIncrement (&tp->nexecuted);
+
+       if (InterlockedDecrement (&monitor_njobs) == 0)
+               monitor_state = MONITOR_STATE_FALLING_ASLEEP;
+
        return exc;
 }
 
@@ -757,21 +773,135 @@ signal_handler (int signo)
 }
 #endif
 
+#define SAMPLES_PERIOD 500
+#define HISTORY_SIZE 10
+/* number of iteration without any jobs
+   in the queue before going to sleep */
+#define NUM_WAITING_ITERATIONS 10
+
+typedef struct {
+       gint32 nexecuted;
+       gint32 nthreads;
+       gint8 nthreads_diff;
+} SamplesHistory;
+
+/*
+ * returns :
+ *  -  1 if the number of threads should increase
+ *  -  0 if it should not change
+ *  - -1 if it should decrease
+ *  - -2 in case of error
+ */
+static gint8
+monitor_heuristic (gint16 *current, gint16 *history_size, SamplesHistory *history, ThreadPool *tp)
+{
+       int i;
+       gint8 decision;
+       gint16 cur, max = 0;
+       gboolean all_waitsleepjoin;
+       MonoInternalThread *thread;
+
+       /*
+        * The following heuristic tries to approach the optimal number of threads to maximize jobs throughput. To
+        * achieve this, it simply stores the number of jobs executed (nexecuted), the number of Threads (nthreads)
+        * and the decision (nthreads_diff) for the past HISTORY_SIZE periods of time, each period being of
+        * duration SAMPLES_PERIOD ms. This history gives us an insight into what happened, and to see if we should
+        * increase or reduce the number of threads by comparing the last period (current) to the best one.
+        *
+        * The algorithm can be describe as following :
+        *  - if we have a better throughput than the best period : we should either increase the number of threads
+        *     in case we already have more threads, either reduce the number of threads if we have less threads; this
+        *     is equivalent to move away from the number of threads of the best period, because we are currently better
+        *  - if we have a worse throughput than the best period : we should either decrease the number of threads if
+        *     we have more threads, either increase the number of threads if we have less threads;  this is equivalent
+        *     to get closer to the number of threads of the best period, because we are currently worse
+        */
+
+       *history_size = MIN (*history_size + 1, HISTORY_SIZE);
+       cur = *current = (*current + 1) % *history_size;
+
+       history [cur].nthreads = tp->nthreads;
+       history [cur].nexecuted = InterlockedExchange (&tp->nexecuted, 0);
+
+       if (tp->waiting) {
+               /* if we have waiting thread in the pool, then do not create a new one */
+               history [cur].nthreads_diff = tp->waiting > 1 ? -1 : 0;
+               decision = 0;
+       } else if (tp->nthreads < tp->min_threads) {
+               history [cur].nthreads_diff = 1;
+               decision = 1;
+       } else if (*history_size <= 1) {
+               /* first iteration, let's add a thread by default */
+               history [cur].nthreads_diff = 1;
+               decision = 2;
+       } else {
+               mono_mutex_lock (&threads_lock);
+               if (threads == NULL) {
+                       mono_mutex_unlock (&threads_lock);
+                       return -2;
+               }
+               all_waitsleepjoin = TRUE;
+               for (i = 0; i < threads->len; ++i) {
+                       thread = g_ptr_array_index (threads, i);
+                       if (!(thread->state & ThreadState_WaitSleepJoin)) {
+                               all_waitsleepjoin = FALSE;
+                               break;
+                       }
+               }
+               mono_mutex_unlock (&threads_lock);
+
+               if (all_waitsleepjoin) {
+                       /* we might be in a condition of starvation/deadlock with tasks waiting for each others */
+                       history [cur].nthreads_diff = 1;
+                       decision = 5;
+               } else {
+                       max = cur == 0 ? 1 : 0;
+                       for (i = 0; i < *history_size; i++) {
+                               if (i == cur)
+                                       continue;
+                               if (history [i].nexecuted > history [max].nexecuted)
+                                       max = i;
+                       }
+
+                       if (history [cur].nexecuted >= history [max].nexecuted) {
+                               /* we improved the situation, let's continue ! */
+                               history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? 1 : -1;
+                               decision = 3;
+                       } else {
+                               /* we made it worse, let's return to previous situation */
+                               history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? -1 : 1;
+                               decision = 4;
+                       }
+               }
+       }
+
+#if DEBUG
+       printf ("monitor_thread: decision: %1d, history [current]: {nexecuted: %5d, nthreads: %3d, waiting: %2d, nthreads_diff: %2d}, history [max]: {nexecuted: %5d, nthreads: %3d}\n",
+                       decision, history [cur].nexecuted, history [cur].nthreads, tp->waiting, history [cur].nthreads_diff, history [max].nexecuted, history [max].nthreads);
+#endif
+       
+       return history [cur].nthreads_diff;
+}
+
 static void
 monitor_thread (gpointer unused)
 {
        ThreadPool *pools [2];
        MonoInternalThread *thread;
-       guint32 ms;
-       gboolean need_one;
        int i;
 
+       guint32 ms;
+       gint8 num_waiting_iterations = 0;
+
+       gint16 history_size = 0, current = -1;
+       SamplesHistory *history = malloc (sizeof (SamplesHistory) * HISTORY_SIZE);
+
        pools [0] = &async_tp;
        pools [1] = &async_io_tp;
        thread = mono_thread_internal_current ();
        ves_icall_System_Threading_Thread_SetName_internal (thread, mono_string_new (mono_domain_get (), "Threadpool monitor"));
        while (1) {
-               ms = 500;
+               ms = SAMPLES_PERIOD;
                i = 10; //number of spurious awakes we tolerate before doing a round of rebalancing.
                do {
                        guint32 ts;
@@ -791,26 +921,44 @@ monitor_thread (gpointer unused)
                if (suspended)
                        continue;
 
+               /* threadpool is cleaning up */
+               if (async_tp.pool_status == 2 || async_io_tp.pool_status == 2)
+                       break;
+
+               switch (monitor_state) {
+               case MONITOR_STATE_AWAKE:
+                       num_waiting_iterations = 0;
+                       break;
+               case MONITOR_STATE_FALLING_ASLEEP:
+                       if (++num_waiting_iterations == NUM_WAITING_ITERATIONS) {
+                               if (monitor_state == MONITOR_STATE_FALLING_ASLEEP && InterlockedCompareExchange (&monitor_state, MONITOR_STATE_SLEEPING, MONITOR_STATE_FALLING_ASLEEP) == MONITOR_STATE_FALLING_ASLEEP) {
+                                       MONO_SEM_WAIT (&monitor_sem);
+
+                                       num_waiting_iterations = 0;
+                                       current = -1;
+                                       history_size = 0;
+                               }
+                       }
+                       break;
+               case MONITOR_STATE_SLEEPING:
+                       g_assert_not_reached ();
+               }
+
                for (i = 0; i < 2; i++) {
                        ThreadPool *tp;
                        tp = pools [i];
-                       if (tp->waiting > 0)
-                               continue;
-                       need_one = (mono_cq_count (tp->queue) > 0);
-                       if (!need_one && !tp->is_io) {
-                               mono_mutex_lock (&wsqs_lock);
-                               for (i = 0; wsqs != NULL && i < wsqs->len; i++) {
-                                       MonoWSQ *wsq;
-                                       wsq = g_ptr_array_index (wsqs, i);
-                                       if (mono_wsq_count (wsq) != 0) {
-                                               need_one = TRUE;
-                                               break;
-                                       }
-                               }
-                               mono_mutex_unlock (&wsqs_lock);
+
+                       if (tp->is_io) {
+                               if (!tp->waiting && mono_cq_count (tp->queue) > 0)
+                                       threadpool_start_thread (tp);
+                       } else {
+                               gint8 nthreads_diff = monitor_heuristic (&current, &history_size, history, tp);
+
+                               if (nthreads_diff == 1)
+                                       threadpool_start_thread (tp);
+                               else if (nthreads_diff == -1)
+                                       threadpool_kill_thread (tp);
                        }
-                       if (need_one)
-                               threadpool_start_thread (tp);
                }
        }
 }
@@ -857,6 +1005,10 @@ mono_thread_pool_init (void)
        async_call_klass = mono_class_from_name (mono_defaults.corlib, "System", "MonoAsyncCall");
        g_assert (async_call_klass);
 
+       mono_mutex_init (&threads_lock);
+       threads = g_ptr_array_sized_new (thread_count);
+       g_assert (threads);
+
        mono_mutex_init_recursive (&wsqs_lock);
        wsqs = g_ptr_array_sized_new (MAX (100 * cpu_count, thread_count));
 
@@ -878,6 +1030,10 @@ mono_thread_pool_init (void)
        signal (SIGALRM, signal_handler);
        alarm (2);
 #endif
+
+       MONO_SEM_INIT (&monitor_sem, 0);
+       monitor_state = MONITOR_STATE_AWAKE;
+       monitor_njobs = 0;
 }
 
 static MonoAsyncResult *
@@ -1004,6 +1160,14 @@ mono_thread_pool_cleanup (void)
                threadpool_kill_idle_threads (&async_tp);
                threadpool_free_queue (&async_tp);
        }
+       
+       if (threads) {
+               mono_mutex_lock (&threads_lock);
+               if (threads)
+                       g_ptr_array_free (threads, FALSE);
+               threads = NULL;
+               mono_mutex_unlock (&threads_lock);
+       }
 
        if (wsqs) {
                mono_mutex_lock (&wsqs_lock);
@@ -1014,6 +1178,8 @@ mono_thread_pool_cleanup (void)
                mono_mutex_unlock (&wsqs_lock);
                MONO_SEM_DESTROY (&async_tp.new_job);
        }
+
+       MONO_SEM_DESTROY (&monitor_sem);
 }
 
 static gboolean
@@ -1021,6 +1187,7 @@ threadpool_start_thread (ThreadPool *tp)
 {
        gint n;
        guint32 stack_size;
+       MonoInternalThread *thread;
 
        stack_size = (!tp->is_io) ? 0 : SMALL_STACK;
        while (!mono_runtime_is_shutting_down () && (n = tp->nthreads) < tp->max_threads) {
@@ -1028,7 +1195,13 @@ threadpool_start_thread (ThreadPool *tp)
 #ifndef DISABLE_PERFCOUNTERS
                        mono_perfcounter_update_value (tp->pc_nthreads, TRUE, 1);
 #endif
-                       mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size);
+                       thread = mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size);
+                       if (!tp->is_io) {
+                               mono_mutex_lock (&threads_lock);
+                               g_assert (threads != NULL);
+                               g_ptr_array_add (threads, thread);
+                               mono_mutex_unlock (&threads_lock);
+                       }
                        return TRUE;
                }
        }
@@ -1043,6 +1216,13 @@ pulse_on_new_job (ThreadPool *tp)
                MONO_SEM_POST (&tp->new_job);
 }
 
+static void
+threadpool_kill_thread (ThreadPool *tp)
+{
+       if (tp->destroy_thread == 0 && InterlockedCompareExchange (&tp->destroy_thread, 1, 0) == 0)
+               pulse_on_new_job (tp);
+}
+
 void
 icall_append_job (MonoObject *ar)
 {
@@ -1058,7 +1238,6 @@ threadpool_append_job (ThreadPool *tp, MonoObject *ar)
 static void
 threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs)
 {
-       static int job_counter;
        MonoObject *ar;
        gint i;
 
@@ -1067,7 +1246,8 @@ threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs)
 
        if (tp->pool_status == 0 && InterlockedCompareExchange (&tp->pool_status, 1, 0) == 0) {
                if (!tp->is_io) {
-                       mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK);
+                       monitor_internal_thread = mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK);
+                       monitor_internal_thread->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
                        threadpool_start_thread (tp);
                }
                /* Create on demand up to min_threads to avoid startup penalty for apps that don't use
@@ -1078,14 +1258,18 @@ threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs)
                }
        }
 
+       InterlockedAdd (&monitor_njobs, njobs);
+
+       if (monitor_state == MONITOR_STATE_SLEEPING && InterlockedCompareExchange (&monitor_state, MONITOR_STATE_AWAKE, MONITOR_STATE_SLEEPING) == MONITOR_STATE_SLEEPING)
+               MONO_SEM_POST (&monitor_sem);
+
+       if (monitor_state == MONITOR_STATE_FALLING_ASLEEP)
+               InterlockedCompareExchange (&monitor_state, MONITOR_STATE_AWAKE, MONITOR_STATE_FALLING_ASLEEP);
+
        for (i = 0; i < njobs; i++) {
                ar = jobs [i];
                if (ar == NULL || mono_domain_is_unloading (ar->vtable->domain))
                        continue; /* Might happen when cleaning domain jobs */
-               if (!tp->is_io && (InterlockedIncrement (&job_counter) % 10) == 0) {
-                       MonoAsyncResult *o = (MonoAsyncResult *) ar;
-                       o->add_time = mono_100ns_ticks ();
-               }
                threadpool_jobs_inc (ar); 
 #ifndef DISABLE_PERFCOUNTERS
                mono_perfcounter_update_value (tp->pc_nitems, TRUE, 1);
@@ -1096,6 +1280,10 @@ threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs)
                mono_cq_enqueue (tp->queue, ar);
        }
 
+#if DEBUG
+       InterlockedAdd (&tp->njobs, njobs);
+#endif
+
        for (i = 0; tp->waiting > 0 && i < MIN(njobs, tp->max_threads); i++)
                pulse_on_new_job (tp);
 }
@@ -1309,84 +1497,6 @@ dequeue_or_steal (ThreadPool *tp, gpointer *data, MonoWSQ *local_wsq)
        return (*data != NULL);
 }
 
-static void
-process_idle_times (ThreadPool *tp, gint64 t)
-{
-       gint64 ticks;
-       gint64 avg;
-       gboolean compute_avg;
-       gint new_threads;
-       gint64 per1;
-
-       if (tp->ignore_times || t <= 0)
-               return;
-
-       compute_avg = FALSE;
-       ticks = mono_100ns_ticks ();
-       t = ticks - t;
-       SPIN_LOCK (tp->sp_lock);
-       if (tp->ignore_times) {
-               SPIN_UNLOCK (tp->sp_lock);
-               return;
-       }
-       tp->time_sum += t;
-       tp->n_sum++;
-       if (tp->last_check == 0)
-               tp->last_check = ticks;
-       else if (tp->last_check > 0 && (ticks - tp->last_check) > 5000000) {
-               tp->ignore_times = 1;
-               compute_avg = TRUE;
-       }
-       SPIN_UNLOCK (tp->sp_lock);
-
-       if (!compute_avg)
-               return;
-
-       //printf ("Items: %d Time elapsed: %.3fs\n", tp->n_sum, (ticks - tp->last_check) / 10000.0);
-       tp->last_check = ticks;
-       new_threads = 0;
-       avg = tp->time_sum / tp->n_sum;
-       if (tp->averages [1] == 0) {
-               tp->averages [1] = avg;
-       } else {
-               per1 = ((100 * (ABS (avg - tp->averages [1]))) / tp->averages [1]);
-               if (per1 > 5) {
-                       if (avg > tp->averages [1]) {
-                               if (tp->averages [1] < tp->averages [0]) {
-                                       new_threads = -1;
-                               } else {
-                                       new_threads = 1;
-                               }
-                       } else if (avg < tp->averages [1] && tp->averages [1] < tp->averages [0]) {
-                               new_threads = 1;
-                       }
-               } else {
-                       int min, n;
-                       min = tp->min_threads;
-                       n = tp->nthreads;
-                       if ((n - min) < min && tp->busy_threads == n)
-                               new_threads = 1;
-               }
-               /*
-               if (new_threads != 0) {
-                       printf ("n: %d per1: %lld avg=%lld avg1=%lld avg0=%lld\n", new_threads, per1, avg, tp->averages [1], tp->averages [0]);
-               }
-               */
-       }
-
-       tp->time_sum = 0;
-       tp->n_sum = 0;
-
-       tp->averages [0] = tp->averages [1];
-       tp->averages [1] = avg;
-       tp->ignore_times = 0;
-
-       if (new_threads == -1) {
-               if (tp->destroy_thread == 0 && InterlockedCompareExchange (&tp->destroy_thread, 1, 0) == 0)
-                       pulse_on_new_job (tp);
-       }
-}
-
 static gboolean
 should_i_die (ThreadPool *tp)
 {
@@ -1513,8 +1623,6 @@ async_invoke_thread (gpointer data)
                                        if (tp_item_begin_func)
                                                tp_item_begin_func (tp_item_user_data);
 
-                                       if (!is_io_task && ar->add_time > 0)
-                                               process_idle_times (tp, ar->add_time);
                                        exc = mono_async_invoke (tp, ar);
                                        if (tp_item_end_func)
                                                tp_item_end_func (tp_item_user_data);
@@ -1541,8 +1649,12 @@ async_invoke_thread (gpointer data)
                ar = NULL;
                data = NULL;
                must_die = should_i_die (tp);
-               if (!must_die && (tp->is_io || !mono_wsq_local_pop (&data)))
-                       dequeue_or_steal (tp, &data, wsq);
+               if (must_die) {
+                       mono_wsq_suspend (wsq);
+               } else {
+                       if (tp->is_io || !mono_wsq_local_pop (&data))
+                               dequeue_or_steal (tp, &data, wsq);
+               }
 
                n_naps = 0;
                while (!must_die && !data && n_naps < 4) {
@@ -1608,6 +1720,16 @@ async_invoke_thread (gpointer data)
 
                                        if (tp_finish_func)
                                                tp_finish_func (tp_hooks_user_data);
+
+                                       if (!tp->is_io) {
+                                               if (threads) {
+                                                       mono_mutex_lock (&threads_lock);
+                                                       if (threads)
+                                                               g_ptr_array_remove_fast (threads, mono_thread_current ()->internal_thread);
+                                                       mono_mutex_unlock (&threads_lock);
+                                               }
+                                       }
+
                                        return;
                                }
                        }
index f928eec806d3ddb85afc22d2f95875b2b4702f7e..d43605ce620c8c9e472e83debd2a1451ae4b5356 100755 (executable)
@@ -83,8 +83,6 @@ libmonoldflags=$(monoldflags) -version-info 1:0:0
 endif
 endif
 
-if JIT_SUPPORTED
-
 if SUPPORT_SGEN
 sgen_binaries = mono-sgen
 sgen_libraries = libmonosgen-2.0.la
@@ -166,8 +164,6 @@ libmono_llvm_la_LIBADD += $(top_builddir)/mono/mini/libmonoboehm-$(API_VER).la $
 endif
 endif
 
-endif
-
 mono_boehm_SOURCES = \
        main.c
 
@@ -195,6 +191,8 @@ buildver-boehm.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntime-stat
 endif
        @echo "const char *build_date = \"`date`\";" > buildver-boehm.h
 mono_boehm-main.$(OBJEXT): buildver-boehm.h
+main.c: buildver-boehm.h
+
 endif
 
 if DISABLE_EXECUTABLES
@@ -204,6 +202,8 @@ buildver-sgen.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntimesgen-s
 endif
        @echo "const char *build_date = \"`date`\";" > buildver-sgen.h
 mono_sgen-main-sgen.$(OBJEXT): buildver-sgen.h
+main-sgen.c: buildver-sgen.h
+
 
 if DTRACE_G_REQUIRED
 LIBMONO_DTRACE_OBJECT = .libs/mono-dtrace.$(OBJEXT)
@@ -344,6 +344,7 @@ sparc_sources = \
 s390x_sources = \
        mini-s390x.c            \
        mini-s390x.h            \
+       support-s390x.h         \
        exceptions-s390x.c      \
        tramp-s390x.c
 
@@ -726,11 +727,7 @@ clean-local:
 
 pkgconfigdir = $(libdir)/pkgconfig
 
-if JIT_SUPPORTED
 BUILT_SOURCES = version.h $(arch_built)
-else
-BUILT_SOURCES = version.h
-endif
 
 CLEANFILES= $(BUILT_SOURCES) *.exe *.dll
 EXTRA_DIST = TestDriver.cs ldscript ldscript.mono \
index 70e11b7730f483f97e20093d88d33800cdbca90e..4b53f0cae197a61f4991636cd2179bafe4f0b333 100644 (file)
@@ -3371,8 +3371,9 @@ add_wrappers (MonoAotCompile *acfg)
                        if (info && !has_nullable) {
                                /* Supported by the dynamic runtime-invoke wrapper */
                                skip = TRUE;
-                               g_free (info);
                        }
+                       if (info)
+                               mono_arch_dyn_call_free (info);
                }
 #endif
 
@@ -5775,41 +5776,16 @@ emit_plt (MonoAotCompile *acfg)
                plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
                ji = plt_entry->ji;
 
-               if (acfg->llvm) {
-                       /*
-                        * If the target is directly callable, alias the plt symbol to point to
-                        * the method code.
-                        * FIXME: Use this to simplify emit_and_reloc_code ().
-                        * FIXME: Avoid the got slot.
-                        * FIXME: Add support to the binary writer.
-                        */
-                       if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer) {
-                               MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, ji->data.method);
-
-                               if (callee_cfg) {
-                                       if (acfg->thumb_mixed && !callee_cfg->compile_llvm) {
-                                               /* LLVM calls the PLT entries using bl, so emit a stub */
-                                               emit_set_thumb_mode (acfg);
-                                               fprintf (acfg->fp, "\n.thumb_func\n");
-                                               emit_label (acfg, plt_entry->llvm_symbol);
-                                               fprintf (acfg->fp, "bx pc\n");
-                                               fprintf (acfg->fp, "nop\n");
-                                               emit_set_arm_mode (acfg);
-                                               fprintf (acfg->fp, "b %s\n", callee_cfg->asm_symbol);
-                                       } else {
-                                               fprintf (acfg->fp, "\n.set %s, %s\n", plt_entry->llvm_symbol, callee_cfg->asm_symbol);
-                                       }
-                                       continue;
-                               }
-                       }
-               }
-
                debug_sym = plt_entry->debug_sym;
 
                if (acfg->thumb_mixed && !plt_entry->jit_used)
                        /* Emit only a thumb version */
                        continue;
 
+               /* Skip plt entries not actually called */
+               if (!plt_entry->jit_used && !plt_entry->llvm_used)
+                       continue;
+
                if (acfg->llvm && !acfg->thumb_mixed)
                        emit_label (acfg, plt_entry->llvm_symbol);
 
@@ -5849,9 +5825,6 @@ emit_plt (MonoAotCompile *acfg)
                        plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
                        ji = plt_entry->ji;
 
-                       if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer)
-                               continue;
-
                        /* Skip plt entries not actually called by LLVM code */
                        if (!plt_entry->llvm_used)
                                continue;
@@ -6464,9 +6437,10 @@ add_token_info_hash (gpointer key, gpointer value, gpointer user_data)
 {
        MonoMethod *method = (MonoMethod*)key;
        MonoJumpInfoToken *ji = (MonoJumpInfoToken*)value;
-       MonoJumpInfoToken *new_ji = g_new0 (MonoJumpInfoToken, 1);
        MonoAotCompile *acfg = user_data;
+       MonoJumpInfoToken *new_ji;
 
+       new_ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfoToken));
        new_ji->image = ji->image;
        new_ji->token = ji->token;
        g_hash_table_insert (acfg->token_info_hash, method, new_ji);
@@ -6685,6 +6659,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
        mono_acfg_lock (acfg);
        g_hash_table_foreach (cfg->token_info_hash, add_token_info_hash, acfg);
        mono_acfg_unlock (acfg);
+       g_hash_table_destroy (cfg->token_info_hash);
+       cfg->token_info_hash = NULL;
 
        /*
         * Check for absolute addresses.
@@ -7023,6 +6999,21 @@ mono_aot_get_method_name (MonoCompile *cfg)
                return get_debug_sym (cfg->orig_method, "", llvm_acfg->method_label_hash);
 }
 
+gboolean
+mono_aot_is_direct_callable (MonoJumpInfo *patch_info)
+{
+       return is_direct_callable (llvm_acfg, NULL, patch_info);
+}
+
+void
+mono_aot_mark_unused_llvm_plt_entry (MonoJumpInfo *patch_info)
+{
+       MonoPltEntry *plt_entry;
+
+       plt_entry = get_plt_entry (llvm_acfg, patch_info);
+       plt_entry->llvm_used = FALSE;
+}
+
 char*
 mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
 {
@@ -8741,7 +8732,7 @@ acfg_create (MonoAssembly *ass, guint32 opts)
                acfg->patch_to_got_offset_by_type [i] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
        acfg->got_patches = g_ptr_array_new ();
        acfg->method_to_cfg = g_hash_table_new (NULL, NULL);
-       acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+       acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, NULL);
        acfg->method_to_pinvoke_import = g_hash_table_new_full (NULL, NULL, NULL, g_free);
        acfg->image_hash = g_hash_table_new (NULL, NULL);
        acfg->image_table = g_ptr_array_new ();
index ca2f6552f7137da73a5b894dbe689bba6f9bb5b4..e9b5f42668a6b634bee63d6e68043e4c050669d1 100644 (file)
@@ -2344,7 +2344,8 @@ static MonoJitInfo*
 decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, 
                                                   MonoMethod *method, guint8 *code, 
                                                   MonoJitExceptionInfo *clauses, int num_clauses,
-                                                  int extra_size, GSList **nesting,
+                                                  MonoJitInfoFlags flags,
+                                                  GSList **nesting,
                                                   int *this_reg, int *this_offset)
 {
        guint8 *p;
@@ -2455,20 +2456,17 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain,
         * allocate a new JI.
         */
        jinfo = 
-               mono_domain_alloc0_lock_free (domain, MONO_SIZEOF_JIT_INFO + (sizeof (MonoJitExceptionInfo) * (ei_len + nested_len)) + extra_size);
+               mono_domain_alloc0_lock_free (domain, mono_jit_info_size (flags, ei_len + nested_len, 0));
+       mono_jit_info_init (jinfo, method, code, code_len, flags, ei_len + nested_len, 0);
 
-       jinfo->code_size = code_len;
        jinfo->unwind_info = mono_cache_unwind_info (info.unw_info, info.unw_info_len);
-       jinfo->d.method = method;
-       jinfo->code_start = code;
-       jinfo->domain_neutral = 0;
        /* This signals that unwind_info points to a normal cached unwind info */
        jinfo->from_aot = 0;
-       jinfo->num_clauses = ei_len + nested_len;
+       jinfo->from_llvm = 1;
 
        for (i = 0; i < ei_len; ++i) {
                /*
-                * orig_jinfo contains the original IL exception info saved by the AOT
+                * clauses contains the original IL exception info saved by the AOT
                 * compiler, we have to combine that with the information produced by LLVM
                 */
                /* The type_info entries contain IL clause indexes */
@@ -2544,7 +2542,8 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
 {
        int i, buf_len, num_clauses, len;
        MonoJitInfo *jinfo;
-       guint unwind_info, flags;
+       MonoJitInfoFlags flags = JIT_INFO_NONE;
+       guint unwind_info, eflags;
        gboolean has_generic_jit_info, has_dwarf_unwind_info, has_clauses, has_seq_points, has_try_block_holes, has_arch_eh_jit_info;
        gboolean from_llvm, has_gc_map;
        guint8 *p;
@@ -2556,15 +2555,15 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
        async = mono_thread_info_is_async_context ();
 
        p = ex_info;
-       flags = decode_value (p, &p);
-       has_generic_jit_info = (flags & 1) != 0;
-       has_dwarf_unwind_info = (flags & 2) != 0;
-       has_clauses = (flags & 4) != 0;
-       has_seq_points = (flags & 8) != 0;
-       from_llvm = (flags & 16) != 0;
-       has_try_block_holes = (flags & 32) != 0;
-       has_gc_map = (flags & 64) != 0;
-       has_arch_eh_jit_info = (flags & 128) != 0;
+       eflags = decode_value (p, &p);
+       has_generic_jit_info = (eflags & 1) != 0;
+       has_dwarf_unwind_info = (eflags & 2) != 0;
+       has_clauses = (eflags & 4) != 0;
+       has_seq_points = (eflags & 8) != 0;
+       from_llvm = (eflags & 16) != 0;
+       has_try_block_holes = (eflags & 32) != 0;
+       has_gc_map = (eflags & 64) != 0;
+       has_arch_eh_jit_info = (eflags & 128) != 0;
 
        if (has_dwarf_unwind_info) {
                unwind_info = decode_value (p, &p);
@@ -2572,13 +2571,16 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
        } else {
                unwind_info = decode_value (p, &p);
        }
-       if (has_generic_jit_info)
+       if (has_generic_jit_info) {
+               flags |= JIT_INFO_HAS_GENERIC_JIT_INFO;
                generic_info_size = sizeof (MonoGenericJitInfo);
-       else
+       } else {
                generic_info_size = 0;
+       }
 
        if (has_try_block_holes) {
                num_holes = decode_value (p, &p);
+               flags |= JIT_INFO_HAS_TRY_BLOCK_HOLES;
                try_holes_info_size = sizeof (MonoTryBlockHoleTableJitInfo) + num_holes * sizeof (MonoTryBlockHoleJitInfo);
        } else {
                num_holes = try_holes_info_size = 0;
@@ -2588,10 +2590,12 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
                num_clauses = decode_value (p, &p);
        else
                num_clauses = 0;
-       if (has_arch_eh_jit_info)
+       if (has_arch_eh_jit_info) {
+               flags |= JIT_INFO_HAS_ARCH_EH_INFO;
                arch_eh_jit_info_size = sizeof (MonoArchEHJitInfo);
-       else
+       } else {
                arch_eh_jit_info_size = 0;
+       }
 
        if (from_llvm) {
                MonoJitExceptionInfo *clauses;
@@ -2624,17 +2628,16 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
                        }
                }
 
-               jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, clauses, num_clauses, generic_info_size + try_holes_info_size + arch_eh_jit_info_size, nesting, &this_reg, &this_offset);
-               jinfo->from_llvm = 1;
+               jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, clauses, num_clauses, flags, nesting, &this_reg, &this_offset);
 
                g_free (clauses);
                for (i = 0; i < num_clauses; ++i)
                        g_slist_free (nesting [i]);
                g_free (nesting);
        } else {
-               len = MONO_SIZEOF_JIT_INFO + (sizeof (MonoJitExceptionInfo) * num_clauses) + generic_info_size + try_holes_info_size + arch_eh_jit_info_size;
+               len = mono_jit_info_size (flags, num_clauses, num_holes);
                jinfo = alloc0_jit_info_data (domain, len, async);
-               jinfo->num_clauses = num_clauses;
+               mono_jit_info_init (jinfo, method, code, code_len, flags, num_clauses, num_holes);
 
                for (i = 0; i < jinfo->num_clauses; ++i) {
                        MonoJitExceptionInfo *ei = &jinfo->clauses [i];
@@ -2661,25 +2664,11 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
                        ei->handler_start = code + decode_value (p, &p);
                }
 
-               jinfo->code_size = code_len;
                jinfo->unwind_info = unwind_info;
-               jinfo->d.method = method;
-               jinfo->code_start = code;
                jinfo->domain_neutral = 0;
                jinfo->from_aot = 1;
        }
 
-       /*
-        * Set all the 'has' flags, the mono_jit_info_get () functions depends on this to
-        * compute the addresses of data blocks.
-        */
-       if (has_generic_jit_info)
-               jinfo->has_generic_jit_info = 1;
-       if (has_arch_eh_jit_info)
-               jinfo->has_arch_eh_info = 1;
-       if (has_try_block_holes)
-               jinfo->has_try_block_holes = 1;
-
        if (has_try_block_holes) {
                MonoTryBlockHoleTableJitInfo *table;
 
index 44a78aa476b140cc42a96dad49af9be9fb3865e3..2be95e736424d43c562b3e52612273e3372788f1 100644 (file)
@@ -1299,7 +1299,7 @@ mono_optimize_branches (MonoCompile *cfg)
 
                                        /* branches to the following block can be removed */
                                        if (bb->last_ins && bb->last_ins->opcode == OP_BR && !bbn->out_of_line) {
-                                               bb->last_ins->opcode = OP_NOP;
+                                               NULLIFY_INS (bb->last_ins);
                                                changed = TRUE;
                                                if (cfg->verbose_level > 2)
                                                        g_print ("br removal triggered %d -> %d\n", bb->block_num, bbn->block_num);
index 431936113c35613cc15904147fbc8904ab575fa4..b31b368ec78550d7442a76009225d42d64bf7873 100644 (file)
@@ -211,7 +211,7 @@ sbb_imm: dest:i src1:i len:12
 br_reg: src1:i len:8
 bigmul: len:8 dest:l src1:i src2:i
 bigmul_un: len:8 dest:l src1:i src2:i
-tls_get: len:8 dest:i clob:c
+tls_get: len:24 dest:i clob:c
 
 # 32 bit opcodes
 int_add: dest:i src1:i src2:i len:4
index 07242d86138e0ce371119ddffa80e7d85e9861fe..6e9d4aaef7190601aab7461fa11b92e62e521008 100644 (file)
@@ -470,7 +470,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
                        }
 #endif
                        MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2);
-                       ins->opcode = OP_NOP;
+                       NULLIFY_INS (ins);
                } else {
                        emulate = TRUE;
                }
@@ -497,12 +497,12 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
 
                        if (power > 1) {
                                intermediate_reg = compensator_reg;
-                               MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_SHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
+                               MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_ISHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
                        } else {
                                intermediate_reg = ins->sreg1;
                        }
 
-                       MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_SHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_ISHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
                        MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LADD : OP_IADD, ins->dreg, ins->sreg1, compensator_reg);
                        /* Compute remainder */
                        MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LAND_IMM : OP_AND_IMM, ins->dreg, ins->dreg, (1 << power) - 1);
@@ -980,7 +980,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
                                        MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                }
                                case OP_LBGE:
@@ -998,7 +998,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
                                        MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
                                        MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                case OP_LCEQ: {
                                        int d1, d2;
@@ -1012,7 +1012,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
 
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
                                        MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                }
                                case OP_LCLT:
@@ -1034,7 +1034,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_START_BB (cfg, set_to_1);
                                        MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
                                        MONO_START_BB (cfg, set_to_0);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;  
                                }
                                default:
@@ -1066,7 +1066,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
                                        MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                }
 
@@ -1085,7 +1085,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
                                        MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                case OP_LCEQ: {
                                        int d1, d2;
@@ -1099,7 +1099,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
 
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
                                        MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                }
                                case OP_LCLT:
@@ -1121,7 +1121,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_START_BB (cfg, set_to_1);
                                        MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
                                        MONO_START_BB (cfg, set_to_0);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;  
                                }
                                default:
@@ -1330,18 +1330,18 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
                                        if (call->vret_in_reg) {
                                                MonoCallInst *call2;
 
-                                               /* Replace the vcall with an integer call */
+                                               /* Replace the vcall with a scalar call */
                                                MONO_INST_NEW_CALL (cfg, call2, OP_NOP);
                                                memcpy (call2, call, sizeof (MonoCallInst));
                                                switch (ins->opcode) {
                                                case OP_VCALL:
-                                                       call2->inst.opcode = OP_CALL;
+                                                       call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL : OP_CALL;
                                                        break;
                                                case OP_VCALL_REG:
-                                                       call2->inst.opcode = OP_CALL_REG;
+                                                       call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_REG : OP_CALL_REG;
                                                        break;
                                                case OP_VCALL_MEMBASE:
-                                                       call2->inst.opcode = OP_CALL_MEMBASE;
+                                                       call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_MEMBASE : OP_CALL_MEMBASE;
                                                        break;
                                                }
                                                call2->inst.dreg = alloc_preg (cfg);
@@ -1367,12 +1367,19 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
                                                        break;
                                                case 3:
                                                case 4:
-                                                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+                                                       if (call->vret_in_reg_fp)
+                                                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+                                                       else
+                                                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
                                                        break;
                                                case 5:
                                                case 6:
                                                case 7:
                                                case 8:
+                                                       if (call->vret_in_reg_fp) {
+                                                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+                                                               break;
+                                                       }
 #if SIZEOF_REGISTER == 4
                                                        /*
                                                        FIXME Other ABIs might return in different regs than the ones used for LCALL.
index 7b34b18df0e92c976e0dd49e31927121a4c50103..c6c8e20628c78b84242ab2d4c20270d31a23db79 100644 (file)
@@ -408,8 +408,7 @@ mini_regression_step (MonoImage *image, int verbose, int *total_run, int *total,
 
                        } else {
                                cfailed++;
-                               if (verbose)
-                                       g_print ("Test '%s' failed compilation.\n", method->name);
+                               g_print ("Test '%s' failed compilation.\n", method->name);
                        }
                        if (mini_stats_fd)
                                fprintf (mini_stats_fd, "%f, ",
@@ -1903,6 +1902,9 @@ mono_main (int argc, char* argv[])
                mono_load_coree (argv [i]);
 #endif
 
+       /* Set rootdir before loading config */
+       mono_set_rootdir ();
+
        /* Parse gac loading options before loading assemblies. */
        if (mono_compile_aot || action == DO_EXEC || action == DO_DEBUGGER) {
                mono_config_parse (config_file);
index a5cbabb53a53333dd2ecf2a2cfd1012bb780d507..5f304b390fd41f0c9fbc36ef9b3bc22315042b4a 100644 (file)
@@ -812,9 +812,7 @@ update_liveness2 (MonoCompile *cfg, MonoInst *ins, gboolean set_volatile, int in
                                /* Try dead code elimination */
                                if ((var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST)) && !(var->flags & MONO_INST_VOLATILE)) {
                                        LIVENESS_DEBUG (printf ("\tdead def of R%d, eliminated\n", ins->dreg));
-                                       ins->opcode = OP_NOP;
-                                       ins->dreg = -1;
-                                       MONO_INST_NULLIFY_SREGS (ins);
+                                       NULLIFY_INS (ins);
                                        return;
                                }
 
index c97c935fe9d720b9296f4bc51eedf80314b40a57..7a8c4d3f9f88efd5c5a5d0920cbc9d0b0408f267 100755 (executable)
 
 #define BRANCH_COST 10
 #define INLINE_LENGTH_LIMIT 20
+
+/* These have 'cfg' as an implicit argument */
 #define INLINE_FAILURE(msg) do {                                                                       \
-       if ((cfg->method != method) && (method->wrapper_type == MONO_WRAPPER_NONE)) { \
-               if (cfg->verbose_level >= 2)                                                                    \
-                       printf ("inline failed: %s\n", msg);                                            \
-               goto inline_failure;                                                                                    \
+       if ((cfg->method != cfg->current_method) && (cfg->current_method->wrapper_type == MONO_WRAPPER_NONE)) { \
+               inline_failure (cfg, msg);                                                                              \
+               goto exception_exit;                                                                                    \
        } \
        } while (0)
 #define CHECK_CFG_EXCEPTION do {\
-               if (cfg->exception_type != MONO_EXCEPTION_NONE)\
-                       goto exception_exit;\
+               if (cfg->exception_type != MONO_EXCEPTION_NONE) \
+                       goto exception_exit;                                            \
        } while (0)
-#define METHOD_ACCESS_FAILURE do {     \
-               char *method_fname = mono_method_full_name (method, TRUE);      \
-               char *cil_method_fname = mono_method_full_name (cil_method, TRUE);      \
-               mono_cfg_set_exception (cfg, MONO_EXCEPTION_METHOD_ACCESS);             \
-               cfg->exception_message = g_strdup_printf ("Method `%s' is inaccessible from method `%s'\n", cil_method_fname, method_fname);    \
-               g_free (method_fname);  \
-               g_free (cil_method_fname);      \
-               goto exception_exit;    \
+#define METHOD_ACCESS_FAILURE(method, cmethod) do {                    \
+               method_access_failure ((cfg), (method), (cmethod));                     \
+               goto exception_exit;                                                                            \
        } while (0)
-#define FIELD_ACCESS_FAILURE do {      \
-               char *method_fname = mono_method_full_name (method, TRUE);      \
-               char *field_fname = mono_field_full_name (field);       \
-               mono_cfg_set_exception (cfg, MONO_EXCEPTION_FIELD_ACCESS);              \
-               cfg->exception_message = g_strdup_printf ("Field `%s' is inaccessible from method `%s'\n", field_fname, method_fname);  \
-               g_free (method_fname);  \
-               g_free (field_fname);   \
+#define FIELD_ACCESS_FAILURE(method, field) do {                                       \
+               field_access_failure ((cfg), (method), (field));                        \
                goto exception_exit;    \
        } while (0)
 #define GENERIC_SHARING_FAILURE(opcode) do {           \
-               if (cfg->generic_sharing_context) {     \
-            if (cfg->verbose_level > 2) \
-                           printf ("sharing failed for method %s.%s.%s/%d opcode %s line %d\n", method->klass->name_space, method->klass->name, method->name, method->signature->param_count, mono_opcode_name ((opcode)), __LINE__); \
-                       mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED); \
+               if (cfg->gshared) {                                                                     \
+                       gshared_failure (cfg, opcode, __FILE__, __LINE__);      \
                        goto exception_exit;    \
                }                       \
        } while (0)
 #define GSHAREDVT_FAILURE(opcode) do {         \
        if (cfg->gsharedvt) {                                                                                           \
-               cfg->exception_message = g_strdup_printf ("gsharedvt failed for method %s.%s.%s/%d opcode %s %s:%d", method->klass->name_space, method->klass->name, method->name, method->signature->param_count, mono_opcode_name ((opcode)), __FILE__, __LINE__); \
-               if (cfg->verbose_level >= 2)                                                                    \
-                       printf ("%s\n", cfg->exception_message); \
-               mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED); \
+               gsharedvt_failure (cfg, opcode, __FILE__, __LINE__);                    \
                goto exception_exit;                                                                                    \
        }                                                                                                                                       \
        } while (0)
                        printf ("AOT disabled: %s:%d\n", __FILE__, __LINE__);   \
                (cfg)->disable_aot = TRUE;                                                        \
        } while (0)
+#define LOAD_ERROR do { \
+               break_on_unverified ();                                                         \
+               mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD); \
+               goto exception_exit;                                                                    \
+       } while (0)
+
+#define TYPE_LOAD_ERROR(klass) do { \
+               cfg->exception_ptr = klass; \
+               LOAD_ERROR;                                     \
+       } while (0)
 
 /* Determine whenever 'ins' represents a load of the 'this' argument */
 #define MONO_CHECK_THIS(ins) (mono_method_signature (cfg->method)->hasthis && ((ins)->opcode == OP_MOVE) && ((ins)->sreg1 == cfg->args [0]->dreg))
@@ -194,14 +190,6 @@ const gint8 ins_sreg_counts[] = {
        (vi)->idx = (id); \
 } while (0)
 
-void
-mono_inst_set_src_registers (MonoInst *ins, int *regs)
-{
-       ins->sreg1 = regs [0];
-       ins->sreg2 = regs [1];
-       ins->sreg3 = regs [2];
-}
-
 guint32
 mono_alloc_ireg (MonoCompile *cfg)
 {
@@ -367,6 +355,60 @@ mono_create_helper_signatures (void)
        helper_sig_monitor_enter_exit_trampoline_llvm = mono_create_icall_signature ("void object");
 }
 
+static MONO_NEVER_INLINE void
+break_on_unverified (void)
+{
+       if (mini_get_debug_options ()->break_on_unverified)
+               G_BREAKPOINT ();
+}
+
+static MONO_NEVER_INLINE void
+method_access_failure (MonoCompile *cfg, MonoMethod *method, MonoMethod *cil_method)
+{
+       char *method_fname = mono_method_full_name (method, TRUE);
+       char *cil_method_fname = mono_method_full_name (cil_method, TRUE);
+       mono_cfg_set_exception (cfg, MONO_EXCEPTION_METHOD_ACCESS);
+       cfg->exception_message = g_strdup_printf ("Method `%s' is inaccessible from method `%s'\n", cil_method_fname, method_fname);
+       g_free (method_fname);
+       g_free (cil_method_fname);
+}
+
+static MONO_NEVER_INLINE void
+field_access_failure (MonoCompile *cfg, MonoMethod *method, MonoClassField *field)
+{
+       char *method_fname = mono_method_full_name (method, TRUE);
+       char *field_fname = mono_field_full_name (field);
+       mono_cfg_set_exception (cfg, MONO_EXCEPTION_FIELD_ACCESS);
+       cfg->exception_message = g_strdup_printf ("Field `%s' is inaccessible from method `%s'\n", field_fname, method_fname);
+       g_free (method_fname);
+       g_free (field_fname);
+}
+
+static MONO_NEVER_INLINE void
+inline_failure (MonoCompile *cfg, const char *msg)
+{
+       if (cfg->verbose_level >= 2)
+               printf ("inline failed: %s\n", msg);
+       mono_cfg_set_exception (cfg, MONO_EXCEPTION_INLINE_FAILED);
+}
+
+static MONO_NEVER_INLINE void
+gshared_failure (MonoCompile *cfg, int opcode, const char *file, int line)
+{
+       if (cfg->verbose_level > 2)                                                                                     \
+               printf ("sharing failed for method %s.%s.%s/%d opcode %s line %d\n", cfg->current_method->klass->name_space, cfg->current_method->klass->name, cfg->current_method->name, cfg->current_method->signature->param_count, mono_opcode_name ((opcode)), __LINE__);
+       mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED);
+}
+
+static MONO_NEVER_INLINE void
+gsharedvt_failure (MonoCompile *cfg, int opcode, const char *file, int line)
+{
+       cfg->exception_message = g_strdup_printf ("gsharedvt failed for method %s.%s.%s/%d opcode %s %s:%d", cfg->current_method->klass->name_space, cfg->current_method->klass->name, cfg->current_method->name, cfg->current_method->signature->param_count, mono_opcode_name ((opcode)), file, line);
+       if (cfg->verbose_level >= 2)
+               printf ("%s\n", cfg->exception_message);
+       mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED);
+}
+
 /*
  * When using gsharedvt, some instatiations might be verifiable, and some might be not. i.e. 
  * foo<T> (int i) { ldarg.0; box T; }
@@ -378,16 +420,10 @@ mono_create_helper_signatures (void)
                mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED); \
                goto exception_exit;                                                                                    \
        }                                                                                                                                       \
-       if (mini_get_debug_options ()->break_on_unverified) \
-               G_BREAKPOINT (); \
-       else \
-               goto unverified; \
+       break_on_unverified ();                                                                                         \
+       goto unverified;                                                                                                        \
 } while (0)
 
-#define LOAD_ERROR do { if (mini_get_debug_options ()->break_on_unverified) G_BREAKPOINT (); else goto load_error; } while (0)
-
-#define TYPE_LOAD_ERROR(klass) do { if (mini_get_debug_options ()->break_on_unverified) G_BREAKPOINT (); else { cfg->exception_ptr = klass; goto load_error; } } while (0)
-
 #define GET_BBLOCK(cfg,tblock,ip) do { \
                (tblock) = cfg->cil_offset_to_bb [(ip) - cfg->cil_start]; \
                if (!(tblock)) {        \
@@ -4689,6 +4725,8 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        int i;
 #endif
 
+       if (cfg->disable_inline)
+               return FALSE;
        if (cfg->generic_sharing_context)
                return FALSE;
 
@@ -4793,6 +4831,9 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        }
 #endif
 
+       if (g_list_find (cfg->dont_inline, method))
+               return FALSE;
+
        return TRUE;
 }
 
@@ -6003,9 +6044,14 @@ emit_init_local (MonoCompile *cfg, int local, MonoType *type, gboolean init)
        }
 }
 
+/*
+ * inline_method:
+ *
+ *   Return the cost of inlining CMETHOD.
+ */
 static int
 inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp,
-               guchar *ip, guint real_offset, GList *dont_inline, gboolean inline_always)
+                          guchar *ip, guint real_offset, gboolean inline_always, MonoBasicBlock **out_cbb)
 {
        MonoInst *ins, *rvar = NULL;
        MonoMethodHeader *cheader;
@@ -6022,7 +6068,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        guint32 prev_cil_offset_to_bb_len;
        MonoMethod *prev_current_method;
        MonoGenericContext *prev_generic_context;
-       gboolean ret_var_set, prev_ret_var_set, virtual = FALSE;
+       gboolean ret_var_set, prev_ret_var_set, prev_disable_inline, virtual = FALSE;
 
        g_assert (cfg->exception_type == MONO_EXCEPTION_NONE);
 
@@ -6098,11 +6144,12 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        prev_current_method = cfg->current_method;
        prev_generic_context = cfg->generic_context;
        prev_ret_var_set = cfg->ret_var_set;
+       prev_disable_inline = cfg->disable_inline;
 
        if (*ip == CEE_CALLVIRT && !(cmethod->flags & METHOD_ATTRIBUTE_STATIC))
                virtual = TRUE;
 
-       costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, rvar, dont_inline, sp, real_offset, virtual);
+       costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, rvar, sp, real_offset, virtual);
 
        ret_var_set = cfg->ret_var_set;
 
@@ -6118,6 +6165,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        cfg->current_method = prev_current_method;
        cfg->generic_context = prev_generic_context;
        cfg->ret_var_set = prev_ret_var_set;
+       cfg->disable_inline = prev_disable_inline;
        cfg->inline_depth --;
 
        if ((costs >= 0 && costs < 60) || inline_always) {
@@ -6172,6 +6220,8 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
                        cfg->cbb = ebblock;
                }
 
+               *out_cbb = cfg->cbb;
+
                if (rvar) {
                        /*
                         * If the inlined method contains only a throw, then the ret var is not 
@@ -6228,7 +6278,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
 #define CHECK_LOCAL(num) if ((unsigned)(num) >= (unsigned)header->num_locals) UNVERIFIED
 #define CHECK_OPSIZE(size) if (ip + size > end) UNVERIFIED
 #define CHECK_UNVERIFIABLE(cfg) if (cfg->unverifiable) UNVERIFIED
-#define CHECK_TYPELOAD(klass) if (!(klass) || (klass)->exception_type) {cfg->exception_ptr = klass; LOAD_ERROR;}
+#define CHECK_TYPELOAD(klass) if (!(klass) || (klass)->exception_type) TYPE_LOAD_ERROR ((klass))
 
 /* offset from br.s -> br like opcodes */
 #define BIG_BRANCH_OFFSET 13
@@ -6650,7 +6700,7 @@ emit_optimized_ldloca_ir (MonoCompile *cfg, unsigned char *ip, unsigned char *en
                emit_init_local (cfg, local, type, TRUE);
                return ip + 6;
        }
-load_error:
+ exception_exit:
        return NULL;
 }
 
@@ -6847,6 +6897,90 @@ create_magic_tls_access (MonoCompile *cfg, MonoClassField *tls_field, MonoInst *
        return addr;
 }
 
+/*
+ * handle_ctor_call:
+ *
+ *   Handle calls made to ctors from NEWOBJ opcodes.
+ *
+ *   REF_BBLOCK will point to the current bblock after the call.
+ */
+static void
+handle_ctor_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, int context_used,
+                                 MonoInst **sp, guint8 *ip, MonoBasicBlock **ref_bblock, int *inline_costs)
+{
+       MonoInst *vtable_arg = NULL, *callvirt_this_arg = NULL, *ins;
+       MonoBasicBlock *bblock = *ref_bblock;
+
+       if (cmethod->klass->valuetype && mono_class_generic_sharing_enabled (cmethod->klass) &&
+                                       mono_method_is_generic_sharable (cmethod, TRUE)) {
+               if (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst) {
+                       mono_class_vtable (cfg->domain, cmethod->klass);
+                       CHECK_TYPELOAD (cmethod->klass);
+
+                       vtable_arg = emit_get_rgctx_method (cfg, context_used,
+                                                                                               cmethod, MONO_RGCTX_INFO_METHOD_RGCTX);
+               } else {
+                       if (context_used) {
+                               vtable_arg = emit_get_rgctx_klass (cfg, context_used,
+                                                                                                  cmethod->klass, MONO_RGCTX_INFO_VTABLE);
+                       } else {
+                               MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
+
+                               CHECK_TYPELOAD (cmethod->klass);
+                               EMIT_NEW_VTABLECONST (cfg, vtable_arg, vtable);
+                       }
+               }
+       }
+
+       /* Avoid virtual calls to ctors if possible */
+       if (mono_class_is_marshalbyref (cmethod->klass))
+               callvirt_this_arg = sp [0];
+
+       if (cmethod && (cfg->opt & MONO_OPT_INTRINS) && (ins = mini_emit_inst_for_ctor (cfg, cmethod, fsig, sp))) {
+               g_assert (MONO_TYPE_IS_VOID (fsig->ret));
+               CHECK_CFG_EXCEPTION;
+       } else if ((cfg->opt & MONO_OPT_INLINE) && cmethod && !context_used && !vtable_arg &&
+                          mono_method_check_inlining (cfg, cmethod) &&
+                          !mono_class_is_subclass_of (cmethod->klass, mono_defaults.exception_class, FALSE)) {
+               int costs;
+
+               if ((costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, FALSE, &bblock))) {
+                       cfg->real_offset += 5;
+
+                       *inline_costs += costs - 5;
+                       *ref_bblock = bblock;
+               } else {
+                       INLINE_FAILURE ("inline failure");
+                       // FIXME-VT: Clean this up
+                       if (cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig))
+                               GSHAREDVT_FAILURE(*ip);
+                       mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, callvirt_this_arg, NULL, NULL);
+               }
+       } else if (cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig)) {
+               MonoInst *addr;
+
+               addr = emit_get_rgctx_gsharedvt_call (cfg, context_used, fsig, cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE);
+               mono_emit_calli (cfg, fsig, sp, addr, NULL, vtable_arg);
+       } else if (context_used &&
+                          ((!mono_method_is_generic_sharable_full (cmethod, TRUE, FALSE, FALSE) ||
+                                !mono_class_generic_sharing_enabled (cmethod->klass)) || cfg->gsharedvt)) {
+               MonoInst *cmethod_addr;
+
+               /* Generic calls made out of gsharedvt methods cannot be patched, so use an indirect call */
+
+               cmethod_addr = emit_get_rgctx_method (cfg, context_used,
+                                                                                         cmethod, MONO_RGCTX_INFO_GENERIC_METHOD_CODE);
+
+               mono_emit_calli (cfg, fsig, sp, cmethod_addr, NULL, vtable_arg);
+       } else {
+               INLINE_FAILURE ("ctor call");
+               ins = mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp,
+                                                                                 callvirt_this_arg, NULL, vtable_arg);
+       }
+ exception_exit:
+       return;
+}
+
 /*
  * mono_method_to_ir:
  *
@@ -6854,7 +6988,7 @@ create_magic_tls_access (MonoCompile *cfg, MonoClassField *tls_field, MonoInst *
  */
 int
 mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, 
-                  MonoInst *return_var, GList *dont_inline, MonoInst **inline_args, 
+                  MonoInst *return_var, MonoInst **inline_args, 
                   guint inline_offset, gboolean is_virtual_call)
 {
        MonoError error;
@@ -6884,13 +7018,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        gboolean dont_verify, dont_verify_stloc, readonly = FALSE;
        int context_used;
        gboolean init_locals, seq_points, skip_dead_blocks;
-       gboolean disable_inline, sym_seq_points = FALSE;
+       gboolean sym_seq_points = FALSE;
        MonoInst *cached_tls_addr = NULL;
        MonoDebugMethodInfo *minfo;
        MonoBitSet *seq_point_locs = NULL;
        MonoBitSet *seq_point_set_locs = NULL;
 
-       disable_inline = is_jit_optimizer_disabled (method);
+       cfg->disable_inline = is_jit_optimizer_disabled (method);
 
        /* serialization and xdomain stuff may need access to private fields and methods */
        dont_verify = method->klass->image->assembly->corlib_internal? TRUE: FALSE;
@@ -7019,7 +7153,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                param_types [n + sig->hasthis] = sig->params [n];
        cfg->arg_types = param_types;
 
-       dont_inline = g_list_prepend (dont_inline, method);
+       cfg->dont_inline = g_list_prepend (cfg->dont_inline, method);
        if (cfg->method == method) {
 
                if (cfg->prof_options & MONO_PROFILE_INS_COVERAGE)
@@ -7947,7 +8081,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        }
                                        if (!mono_method_can_access_method (method_definition, target_method) &&
                                                !mono_method_can_access_method (method, cil_method))
-                                               METHOD_ACCESS_FAILURE;
+                                               METHOD_ACCESS_FAILURE (method, cil_method);
                                }
 
                                if (mono_security_core_clr_enabled ())
@@ -8374,8 +8508,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        /* Inlining */
                        if (cmethod && (cfg->opt & MONO_OPT_INLINE) &&
                                (!virtual || !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) || MONO_METHOD_IS_FINAL (cmethod)) &&
-                           !disable_inline && mono_method_check_inlining (cfg, cmethod) &&
-                                !g_list_find (dont_inline, cmethod)) {
+                           mono_method_check_inlining (cfg, cmethod)) {
                                int costs;
                                gboolean always = FALSE;
 
@@ -8387,10 +8520,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        always = TRUE;
                                }
 
-                               costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, dont_inline, always);
+                               costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, always, &bblock);
                                if (costs) {
                                        cfg->real_offset += 5;
-                                       bblock = cfg->cbb;
 
                                        if (!MONO_TYPE_IS_VOID (fsig->ret)) {
                                                /* *sp is already set by inline_method */
@@ -9178,7 +9310,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        ins->inst_p1 = (gpointer)(gssize)(sp [1]->inst_c0);
                                        ins->sreg2 = -1;
 
-                                       sp [1]->opcode = OP_NOP;
+                                       NULLIFY_INS (sp [1]);
                                }
                        }
 
@@ -9239,7 +9371,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                        /* Might be followed by an instruction added by ADD_WIDEN_OP */
                                        if (sp [1]->next == NULL)
-                                               sp [1]->opcode = OP_NOP;
+                                               NULLIFY_INS (sp [1]);
                                }
                        }
                        MONO_ADD_INS ((cfg)->cbb, (ins));
@@ -9556,27 +9688,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
                        */
 
-                       if (cmethod->klass->valuetype && mono_class_generic_sharing_enabled (cmethod->klass) &&
-                                       mono_method_is_generic_sharable (cmethod, TRUE)) {
-                               if (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst) {
-                                       mono_class_vtable (cfg->domain, cmethod->klass);
-                                       CHECK_TYPELOAD (cmethod->klass);
-
-                                       vtable_arg = emit_get_rgctx_method (cfg, context_used,
-                                                                                                               cmethod, MONO_RGCTX_INFO_METHOD_RGCTX);
-                               } else {
-                                       if (context_used) {
-                                               vtable_arg = emit_get_rgctx_klass (cfg, context_used,
-                                                       cmethod->klass, MONO_RGCTX_INFO_VTABLE);
-                                       } else {
-                                               MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
-
-                                               CHECK_TYPELOAD (cmethod->klass);
-                                               EMIT_NEW_VTABLECONST (cfg, vtable_arg, vtable);
-                                       }
-                               }
-                       }
-
                        n = fsig->param_count;
                        CHECK_STACK (n);
 
@@ -9590,8 +9701,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ((n < 2) || (!fsig->params [1]->byref && fsig->params [1]->type == MONO_TYPE_STRING))) {
                                MonoInst *iargs [3];
 
-                               g_assert (!vtable_arg);
-
                                sp -= n;
 
                                EMIT_NEW_ICONST (cfg, iargs [0], cmethod->klass->type_token);
@@ -9632,8 +9741,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        iargs [0] = NULL;
 
                        if (mini_class_is_system_array (cmethod->klass)) {
-                               g_assert (!vtable_arg);
-
                                *sp = emit_get_rgctx_method (cfg, context_used,
                                                                                         cmethod, MONO_RGCTX_INFO_METHOD);
 
@@ -9656,8 +9763,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                /* now call the string ctor */
                                alloc = mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, NULL, NULL, NULL);
                        } else {
-                               MonoInst* callvirt_this_arg = NULL;
-                               
                                if (cmethod->klass->valuetype) {
                                        iargs [0] = mono_compile_create_var (cfg, &cmethod->klass->byval_arg, OP_LOCAL);
                                        emit_init_rvar (cfg, iargs [0]->dreg, &cmethod->klass->byval_arg);
@@ -9701,58 +9806,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        MONO_EMIT_NEW_UNALU (cfg, OP_NOT_NULL, -1, alloc->dreg);
 
                                /* Now call the actual ctor */
-                               /* Avoid virtual calls to ctors if possible */
-                               if (mono_class_is_marshalbyref (cmethod->klass))
-                                       callvirt_this_arg = sp [0];
-
-
-                               if (cmethod && (cfg->opt & MONO_OPT_INTRINS) && (ins = mini_emit_inst_for_ctor (cfg, cmethod, fsig, sp))) {
-                                       if (!MONO_TYPE_IS_VOID (fsig->ret)) {
-                                               type_to_eval_stack_type ((cfg), fsig->ret, ins);
-                                               *sp = ins;
-                                               sp++;
-                                       }
-
-                                       CHECK_CFG_EXCEPTION;
-                               } else if ((cfg->opt & MONO_OPT_INLINE) && cmethod && !context_used && !vtable_arg &&
-                                   !disable_inline && mono_method_check_inlining (cfg, cmethod) &&
-                                   !mono_class_is_subclass_of (cmethod->klass, mono_defaults.exception_class, FALSE) &&
-                                   !g_list_find (dont_inline, cmethod)) {
-                                       int costs;
-
-                                       if ((costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, dont_inline, FALSE))) {
-                                               cfg->real_offset += 5;
-                                               bblock = cfg->cbb;
-
-                                               inline_costs += costs - 5;
-                                       } else {
-                                               INLINE_FAILURE ("inline failure");
-                                               // FIXME-VT: Clean this up
-                                               if (cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig))
-                                                       GSHAREDVT_FAILURE(*ip);
-                                               mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, callvirt_this_arg, NULL, NULL);
-                                       }
-                               } else if (cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig)) {
-                                       MonoInst *addr;
-
-                                       addr = emit_get_rgctx_gsharedvt_call (cfg, context_used, fsig, cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE);
-                                       mono_emit_calli (cfg, fsig, sp, addr, NULL, vtable_arg);
-                               } else if (context_used &&
-                                                  ((!mono_method_is_generic_sharable (cmethod, TRUE) ||
-                                                        !mono_class_generic_sharing_enabled (cmethod->klass)) || cfg->gsharedvt)) {
-                                       MonoInst *cmethod_addr;
-
-                                       /* Generic calls made out of gsharedvt methods cannot be patched, so use an indirect call */
-
-                                       cmethod_addr = emit_get_rgctx_method (cfg, context_used,
-                                               cmethod, MONO_RGCTX_INFO_GENERIC_METHOD_CODE);
-
-                                       mono_emit_calli (cfg, fsig, sp, cmethod_addr, NULL, vtable_arg);
-                               } else {
-                                       INLINE_FAILURE ("ctor call");
-                                       ins = mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp,
-                                                                                                         callvirt_this_arg, NULL, vtable_arg);
-                               }
+                               handle_ctor_call (cfg, cmethod, fsig, context_used, sp, ip, &bblock, &inline_costs);
+                               CHECK_CFG_EXCEPTION;
                        }
 
                        if (alloc == NULL) {
@@ -9760,9 +9815,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                EMIT_NEW_TEMPLOAD (cfg, ins, iargs [0]->inst_c0);
                                type_to_eval_stack_type (cfg, &ins->klass->byval_arg, ins);
                                *sp++= ins;
-                       }
-                       else
+                       } else {
                                *sp++ = alloc;
+                       }
                        
                        ip += 5;
                        inline_costs += 5;
@@ -9795,14 +9850,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                
                                save_cast_details (cfg, klass, sp [0]->dreg, TRUE, &bblock);
                                costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), 
-                                                          iargs, ip, cfg->real_offset, dont_inline, TRUE);
+                                                                          iargs, ip, cfg->real_offset, TRUE, &bblock);
                                reset_cast_details (cfg);
                                CHECK_CFG_EXCEPTION;
                                g_assert (costs > 0);
                                
                                ip += 5;
                                cfg->real_offset += 5;
-                               bblock = cfg->cbb;
 
                                *sp++ = iargs [0];
 
@@ -9856,13 +9910,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                iargs [0] = sp [0];
 
                                costs = inline_method (cfg, mono_isinst, mono_method_signature (mono_isinst), 
-                                                          iargs, ip, cfg->real_offset, dont_inline, TRUE);
+                                                                          iargs, ip, cfg->real_offset, TRUE, &bblock);
                                CHECK_CFG_EXCEPTION;
                                g_assert (costs > 0);
                                
                                ip += 5;
                                cfg->real_offset += 5;
-                               bblock = cfg->cbb;
 
                                *sp++= iargs [0];
 
@@ -9914,13 +9967,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        iargs [0] = sp [0];
 
                                        costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), 
-                                                                                  iargs, ip, cfg->real_offset, dont_inline, TRUE);
+                                                                                  iargs, ip, cfg->real_offset, TRUE, &bblock);
                                        CHECK_CFG_EXCEPTION;
                                        g_assert (costs > 0);
                                
                                        ip += 5;
                                        cfg->real_offset += 5;
-                                       bblock = cfg->cbb;
 
                                        *sp++ = iargs [0];
                                        inline_costs += costs;
@@ -10141,7 +10193,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (!field)
                                LOAD_ERROR;
                        if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_field (method, field))
-                               FIELD_ACCESS_FAILURE;
+                               FIELD_ACCESS_FAILURE (method, field);
                        mono_class_init (klass);
 
                        if (is_instance && *ip != CEE_LDFLDA && is_magic_tls_access (field))
@@ -10202,12 +10254,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                        if (cfg->opt & MONO_OPT_INLINE || cfg->compile_aot) {
                                                costs = inline_method (cfg, stfld_wrapper, mono_method_signature (stfld_wrapper), 
-                                                                      iargs, ip, cfg->real_offset, dont_inline, TRUE);
+                                                                                          iargs, ip, cfg->real_offset, TRUE, &bblock);
                                                CHECK_CFG_EXCEPTION;
                                                g_assert (costs > 0);
                                                      
                                                cfg->real_offset += 5;
-                                               bblock = cfg->cbb;
 
                                                inline_costs += costs;
                                        } else {
@@ -10266,9 +10317,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                EMIT_NEW_ICONST (cfg, iargs [3], klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset);
                                if (cfg->opt & MONO_OPT_INLINE || cfg->compile_aot) {
                                        costs = inline_method (cfg, wrapper, mono_method_signature (wrapper), 
-                                                                                  iargs, ip, cfg->real_offset, dont_inline, TRUE);
+                                                                                  iargs, ip, cfg->real_offset, TRUE, &bblock);
                                        CHECK_CFG_EXCEPTION;
-                                       bblock = cfg->cbb;
                                        g_assert (costs > 0);
                                                      
                                        cfg->real_offset += 5;
@@ -11729,9 +11779,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                         * The backends expect the fceq opcodes to do the
                                         * comparison too.
                                         */
-                                       cmp->opcode = OP_NOP;
                                        ins->sreg1 = cmp->sreg1;
                                        ins->sreg2 = cmp->sreg2;
+                                       NULLIFY_INS (cmp);
                                }
                                MONO_ADD_INS (bblock, ins);
                                *sp++ = ins;
@@ -11756,7 +11806,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                cil_method = cmethod;
                                if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod))
-                                       METHOD_ACCESS_FAILURE;
+                                       METHOD_ACCESS_FAILURE (method, cil_method);
 
                                if (mono_security_cas_enabled ()) {
                                        if (check_linkdemand (cfg, method, cmethod))
@@ -11980,7 +12030,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                         * stack overflows which is different behavior than the
                                         * non-inlined case, thus disable inlining in this case.
                                         */
-                                       goto inline_failure;
+                                       INLINE_FAILURE("localloc");
 
                                MONO_INST_NEW (cfg, ins, OP_LOCALLOC);
                                ins->dreg = alloc_preg (cfg);
@@ -12345,9 +12395,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                }
        }
 
-       g_slist_free (class_inits);
-       dont_inline = g_list_remove (dont_inline, method);
-
        if (inline_costs < 0) {
                char *mname;
 
@@ -12356,29 +12403,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                mono_cfg_set_exception (cfg, MONO_EXCEPTION_INVALID_PROGRAM);
                cfg->exception_message = g_strdup_printf ("Method %s is too complex.", mname);
                g_free (mname);
-               cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header);
-               mono_basic_block_free (original_bb);
-               return -1;
        }
 
        if ((cfg->verbose_level > 2) && (cfg->method == method)) 
                mono_print_code (cfg, "AFTER METHOD-TO-IR");
 
-       cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header);
-       mono_basic_block_free (original_bb);
-       return inline_costs;
+       goto cleanup;
  
  exception_exit:
        g_assert (cfg->exception_type != MONO_EXCEPTION_NONE);
        goto cleanup;
 
- inline_failure:
-       goto cleanup;
-
- load_error:
-       mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
-       goto cleanup;
-
  unverified:
        set_exception_type_from_invalid_il (cfg, method, ip);
        goto cleanup;
@@ -12386,9 +12421,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
  cleanup:
        g_slist_free (class_inits);
        mono_basic_block_free (original_bb);
-       dont_inline = g_list_remove (dont_inline, method);
+       cfg->dont_inline = g_list_remove (cfg->dont_inline, method);
        cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header);
-       return -1;
+       if (cfg->exception_type)
+               return -1;
+       else
+               return inline_costs;
 }
 
 static int
index faa8cafd322ca0799265305188b82a852fe7921b..a809de49e052aefd2748248d86abab00ede6d530 100755 (executable)
@@ -6417,7 +6417,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        guint alignment_check;
 #endif
 
-       cfg->code_size =  MAX (cfg->header->code_size * 4, 10240);
+       cfg->code_size = MAX (cfg->header->code_size * 4, 1024);
 
 #if defined(__default_codegen__)
        code = cfg->native_code = g_malloc (cfg->code_size);
@@ -6972,7 +6972,6 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                cfg->native_code = mono_realloc_native_code (cfg);
                cfg->stat_code_reallocs++;
        }
-
        code = cfg->native_code + cfg->code_len;
 
        cfg->has_unwind_info_for_epilog = TRUE;
@@ -8174,49 +8173,15 @@ mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
        }
 }
 
-/*MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD*/
 gpointer
 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, MonoContext *ctx, gpointer new_value)
 {
-       int offset;
        gpointer *sp, old_value;
        char *bp;
-       const unsigned char *handler;
-
-       /*Decode the first instruction to figure out where did we store the spvar*/
-       /*Our jit MUST generate the following:
-        mov    %rsp, ?(%rbp)
-
-        Which is encoded as: REX.W 0x89 mod_rm
-        mod_rm (rsp, rbp, imm) which can be: (imm will never be zero)
-               mod (reg + imm8):  01 reg(rsp): 100 rm(rbp): 101 -> 01100101 (0x65)
-               mod (reg + imm32): 10 reg(rsp): 100 rm(rbp): 101 -> 10100101 (0xA5)
-
-       FIXME can we generate frameless methods on this case?
-
-       */
-       handler = clause->handler_start;
-
-       /*REX.W*/
-       if (*handler != 0x48)
-               return NULL;
-       ++handler;
-
-       /*mov r, r/m */
-       if (*handler != 0x89)
-               return NULL;
-       ++handler;
-
-       if (*handler == 0x65)
-               offset = *(signed char*)(handler + 1);
-       else if (*handler == 0xA5)
-               offset = *(int*)(handler + 1);
-       else
-               return NULL;
 
        /*Load the spvar*/
        bp = MONO_CONTEXT_GET_BP (ctx);
-       sp = *(gpointer*)(bp + offset);
+       sp = *(gpointer*)(bp + clause->exvar_offset);
 
        old_value = *sp;
        if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
index f909b4f401abf2008bceb53399df8d615e936221..ebd2638727b7b5ba04c3a42807e2dece11a4558d 100755 (executable)
@@ -276,71 +276,9 @@ typedef struct {
 
 #endif /* !HOST_WIN32 && !__native_client__ */
 
-#if defined (__APPLE__)
-
-#define MONO_ARCH_NOMAP32BIT
-
-#elif defined (__NetBSD__)
-
-#define REG_RAX 14
-#define REG_RCX 3
-#define REG_RDX 2
-#define REG_RBX 13
-#define REG_RSP 24
-#define REG_RBP 12
-#define REG_RSI 1
-#define REG_RDI 0
-#define REG_R8 4
-#define REG_R9 5
-#define REG_R10 6
-#define REG_R11 7
-#define REG_R12 8
-#define REG_R13 9
-#define REG_R14 10
-#define REG_R15 11
-#define REG_RIP 21
-
-#define MONO_ARCH_NOMAP32BIT
-
-#elif defined (__OpenBSD__)
-
-#define MONO_ARCH_NOMAP32BIT
-
-#elif defined (__DragonFly__)
-
-#define MONO_ARCH_NOMAP32BIT
-
-#elif defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
-
-#define REG_RAX 7
-#define REG_RCX 4
-#define REG_RDX 3
-#define REG_RBX 8
-#define REG_RSP 23
-#define REG_RBP 9
-#define REG_RSI 2
-#define REG_RDI 1
-#define REG_R8  5
-#define REG_R9  6
-#define REG_R10 10
-#define REG_R11 11
-#define REG_R12 12
-#define REG_R13 13
-#define REG_R14 14
-#define REG_R15 15
-#define REG_RIP 20
-
-/* 
- * FreeBSD does not have MAP_32BIT, so code allocated by the code manager might not have a
- * 32 bit address.
- */
-#define MONO_ARCH_NOMAP32BIT
-
-#elif defined(HOST_WIN32)
-
+#if !defined(__linux__)
 #define MONO_ARCH_NOMAP32BIT 1
-
-#endif /* __FreeBSD__ */
+#endif
 
 #ifdef HOST_WIN32
 #define MONO_AMD64_ARG_REG1 AMD64_RCX
@@ -359,7 +297,6 @@ typedef struct {
 #define MONO_ARCH_EMULATE_FREM 1
 #define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1
 
-#define MONO_ARCH_ENABLE_REGALLOC_IN_EH_BLOCKS 1
 #define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
@@ -380,7 +317,6 @@ typedef struct {
 #define MONO_ARCH_ENABLE_GLOBAL_RA 1
 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
 #define MONO_ARCH_HAVE_LIVERANGE_OPS 1
-#define MONO_ARCH_HAVE_XP_UNWIND 1
 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
 #define MONO_ARCH_MONITOR_OBJECT_REG MONO_AMD64_ARG_REG1
 #define MONO_ARCH_HAVE_GET_TRAMPOLINES 1
@@ -400,7 +336,6 @@ typedef struct {
 
 #define MONO_ARCH_HAVE_LLVM_IMT_TRAMPOLINE 1
 #define MONO_ARCH_LLVM_SUPPORTED 1
-#define MONO_ARCH_THIS_AS_FIRST_ARG 1
 #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1
 #define MONO_ARCH_HAVE_CARD_TABLE_WBARRIER 1
 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
index b644d7dca7a0ab20b6d2d6150c1de81cae6c66f4..9491a442d1a6f74175524297201d62292322bda8 100644 (file)
@@ -6929,6 +6929,26 @@ mono_arch_get_trampolines (gboolean aot)
        return mono_arm_get_exception_trampolines (aot);
 }
 
+gpointer
+mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, MonoContext *ctx, gpointer new_value)
+{
+       gpointer *lr_loc;
+       char *old_value;
+       char *bp;
+
+       /*Load the spvar*/
+       bp = MONO_CONTEXT_GET_BP (ctx);
+       lr_loc = (gpointer*)(bp + clause->exvar_offset);
+
+       old_value = *lr_loc;
+       if ((char*)old_value < (char*)ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
+               return old_value;
+
+       *lr_loc = new_value;
+
+       return old_value;
+}
+
 #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED)
 /*
  * mono_arch_set_breakpoint:
index 7c3fd9ad0412e7af3f2b956764d546c4ad87726b..f22514b61ef3e58d2d6acbc1a1e4132e1ebc76c1 100644 (file)
@@ -256,7 +256,6 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_NEED_DIV_CHECK 1
 
 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
-#define MONO_ARCH_HAVE_XP_UNWIND 1
 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
 
 #define ARM_NUM_REG_ARGS (ARM_LAST_ARG_REG-ARM_FIRST_ARG_REG+1)
@@ -267,7 +266,6 @@ typedef struct MonoCompileArch {
 
 #define MONO_ARCH_AOT_SUPPORTED 1
 #define MONO_ARCH_LLVM_SUPPORTED 1
-#define MONO_ARCH_THIS_AS_FIRST_ARG 1
 
 #define MONO_ARCH_GSHARED_SUPPORTED 1
 #define MONO_ARCH_DYN_CALL_SUPPORTED 1
@@ -284,6 +282,7 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_GC_MAPS_SUPPORTED 1
 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1
 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1
+#define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1
 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
 #define MONO_ARCH_GSHAREDVT_SUPPORTED 1
 #define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE 1
index 66eb8fcdcf2f0c78f58f12ca2fd5bfeae4091fd7..f4bdecb727a31a1b7c4598ea7bd658e5086e8f6b 100644 (file)
@@ -1173,6 +1173,8 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
         * bblock.
         */
        for (ins = bb->code; ins; ins = ins->next) {
+               gboolean modify = FALSE;
+
                spec = ins_get_spec (ins->opcode);
 
                if ((ins->dreg != -1) && (ins->dreg < max)) {
@@ -1198,12 +1200,14 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 #if SIZEOF_REGISTER == 4
                                if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC1 + j])) {
                                        sregs [j]++;
+                                       modify = TRUE;
                                        memset (&reginfo [sregs [j] + 1], 0, sizeof (RegTrack));
                                }
 #endif
                        }
                }
-               mono_inst_set_src_registers (ins, sregs);
+               if (modify)
+                       mono_inst_set_src_registers (ins, sregs);
        }
 
        /*if (cfg->opt & MONO_OPT_COPYPROP)
index 5993ddddb63364b5b9834e3ea006d7260079572e..db4a1ce4b0c98834c4fd8cad0dd4f569c90c215a 100644 (file)
@@ -2227,8 +2227,8 @@ print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer d
        if (frame->ji)
                method = jinfo_get_method (frame->ji);
 
-       if (method) {
-               gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
+       if (method && frame->domain) {
+               gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
                g_string_append_printf (p, "  %s\n", location);
                g_free (location);
        } else
index d419bc26c728aaa2d9f100ff610ec629b50ce66c..15bb596d41418f5d683c71c98aaa276ea72ae6dc 100644 (file)
@@ -115,6 +115,5 @@ unw_dyn_region_info_t* mono_ia64_create_unwind_region (Ia64CodegenState *code);
 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
 #define MONO_ARCH_HAVE_SAVE_UNWIND_INFO 1
 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
-#define MONO_ARCH_THIS_AS_FIRST_ARG 1
 
 #endif /* __MONO_MINI_IA64_H__ */  
index 6551f78e021a1ed172043611b8f6a4dd9c11861b..2b778c3aaabbc729d6ca9f41b2c6b4e77242aee1 100644 (file)
@@ -10,6 +10,7 @@
 #include <mono/metadata/mempool-internals.h>
 #include <mono/utils/mono-tls.h>
 #include <mono/utils/mono-dl.h>
+#include <mono/utils/mono-time.h>
 
 #ifndef __STDC_LIMIT_MACROS
 #define __STDC_LIMIT_MACROS
@@ -35,6 +36,8 @@ typedef struct {
        LLVMValueRef got_var;
        const char *got_symbol;
        GHashTable *plt_entries;
+       GHashTable *plt_entries_ji;
+       GHashTable *method_to_lmethod;
        char **bb_names;
        int bb_names_len;
        GPtrArray *used;
@@ -1272,6 +1275,7 @@ get_plt_entry (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gc
 {
        char *callee_name = mono_aot_get_plt_symbol (type, data);
        LLVMValueRef callee;
+       MonoJumpInfo *ji = NULL;
 
        if (!callee_name)
                return NULL;
@@ -1290,6 +1294,14 @@ get_plt_entry (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gc
                g_hash_table_insert (ctx->lmodule->plt_entries, (char*)callee_name, callee);
        }
 
+       if (ctx->cfg->compile_aot) {
+               ji = g_new0 (MonoJumpInfo, 1);
+               ji->type = type;
+               ji->data.target = data;
+
+               g_hash_table_insert (ctx->lmodule->plt_entries_ji, ji, callee);
+       }
+
        return callee;
 }
 
@@ -4675,6 +4687,9 @@ mono_llvm_emit_method (MonoCompile *cfg)
                /* FIXME: Free the LLVM IL for the function */
        }
 
+       if (ctx->lmodule->method_to_lmethod)
+               g_hash_table_insert (ctx->lmodule->method_to_lmethod, cfg->method, method);
+
        goto CLEANUP;
 
  FAILURE:
@@ -5331,6 +5346,8 @@ mono_llvm_create_aot_module (const char *got_symbol)
 
        aot_module.llvm_types = g_hash_table_new (NULL, NULL);
        aot_module.plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
+       aot_module.plt_entries_ji = g_hash_table_new (NULL, NULL);
+       aot_module.method_to_lmethod = g_hash_table_new (NULL, NULL);
 }
 
 /*
@@ -5341,6 +5358,7 @@ mono_llvm_emit_aot_module (const char *filename, int got_size)
 {
        LLVMTypeRef got_type;
        LLVMValueRef real_got;
+       MonoLLVMModule *module = &aot_module;
 
        /* 
         * Create the real got variable and replace all uses of the dummy variable with
@@ -5360,6 +5378,26 @@ mono_llvm_emit_aot_module (const char *filename, int got_size)
 
        emit_llvm_used (&aot_module);
 
+       /* Replace PLT entries for directly callable methods with the methods themselves */
+       {
+               GHashTableIter iter;
+               MonoJumpInfo *ji;
+               LLVMValueRef callee;
+
+               g_hash_table_iter_init (&iter, aot_module.plt_entries_ji);
+               while (g_hash_table_iter_next (&iter, (void**)&ji, (void**)&callee)) {
+                       if (mono_aot_is_direct_callable (ji)) {
+                               LLVMValueRef lmethod;
+
+                               lmethod = g_hash_table_lookup (module->method_to_lmethod, ji->data.method);
+                               if (lmethod) {
+                                       mono_llvm_replace_uses_of (callee, lmethod);
+                                       mono_aot_mark_unused_llvm_plt_entry (ji);
+                               }
+                       }
+               }
+       }
+
 #if 0
        {
                char *verifier_err;
index c94f7c898f36c621c9b8286e562cba50fb84db01..d8d769130c4fc049ec242d90b650e55040a17865 100644 (file)
@@ -268,7 +268,6 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
-#define MONO_ARCH_HAVE_XP_UNWIND 1
 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
 #define MONO_ARCH_GSHARED_SUPPORTED 1
@@ -280,8 +279,6 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_NEED_DIV_CHECK 1
 #define MONO_ARCH_NO_IOV_CHECK 1
 
-#define MONO_ARCH_THIS_AS_FIRST_ARG 1
-
 #define MIPS_NUM_REG_ARGS (MIPS_LAST_ARG_REG-MIPS_FIRST_ARG_REG+1)
 #define MIPS_NUM_REG_FPARGS (MIPS_LAST_FPARG_REG-MIPS_FIRST_FPARG_REG+1)
 
index d26b4af4e92b4f23f34af747865109a140a43c2a..0c2fa1dc1f0a1525208eb8bdd332f933f1da6e7c 100644 (file)
@@ -81,7 +81,7 @@ mono_runtime_shutdown_stat_profiler (void)
 
 
 gboolean
-SIG_HANDLER_SIGNATURE (mono_chain_signal)
+MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
 {
        return FALSE;
 }
@@ -173,19 +173,17 @@ free_saved_signal_handlers (void)
  * was called, false otherwise.
  */
 gboolean
-SIG_HANDLER_SIGNATURE (mono_chain_signal)
+MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
 {
-       int signal = _dummy;
+       int signal = MONO_SIG_HANDLER_GET_SIGNO ();
        struct sigaction *saved_handler = get_saved_signal_handler (signal);
 
-       GET_CONTEXT;
-
        if (saved_handler && saved_handler->sa_handler) {
                if (!(saved_handler->sa_flags & SA_SIGINFO)) {
                        saved_handler->sa_handler (signal);
                } else {
 #ifdef MONO_ARCH_USE_SIGACTION
-                       saved_handler->sa_sigaction (signal, info, ctx);
+                       saved_handler->sa_sigaction (MONO_SIG_HANDLER_PARAMS);
 #endif /* MONO_ARCH_USE_SIGACTION */
                }
                return TRUE;
@@ -193,29 +191,28 @@ SIG_HANDLER_SIGNATURE (mono_chain_signal)
        return FALSE;
 }
 
-SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
 {
        MonoJitInfo *ji = NULL;
-       GET_CONTEXT;
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
        if (mono_thread_internal_current ())
-               ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
+               ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
        if (!ji) {
-        if (mono_chain_signal (SIG_HANDLER_PARAMS))
+        if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
                mono_handle_native_sigsegv (SIGABRT, ctx);
        }
 }
 
-SIG_HANDLER_FUNC (static, sigusr1_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigusr1_signal_handler)
 {
        gboolean running_managed;
        MonoException *exc;
        MonoInternalThread *thread = mono_thread_internal_current ();
        MonoDomain *domain = mono_domain_get ();
        void *ji;
-       
-       GET_CONTEXT;
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
        if (!thread || !domain) {
                /* The thread might not have started up yet */
@@ -299,9 +296,9 @@ SIG_HANDLER_FUNC (static, sigusr1_signal_handler)
 #ifdef SIGPROF
 #if defined(__ia64__) || defined(__sparc__) || defined(sparc) || defined(__s390__) || defined(s390)
 
-SIG_HANDLER_FUNC (static, sigprof_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
 {
-       if (mono_chain_signal (SIG_HANDLER_PARAMS))
+       if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                return;
 
        NOT_IMPLEMENTED;
@@ -309,11 +306,11 @@ SIG_HANDLER_FUNC (static, sigprof_signal_handler)
 
 #else
 
-SIG_HANDLER_FUNC (static, sigprof_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
 {
        int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
        MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
-       GET_CONTEXT;
+       MONO_SIG_HANDLER_GET_CONTEXT;
        
        if (call_chain_depth == 0) {
                mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx);
@@ -382,17 +379,16 @@ SIG_HANDLER_FUNC (static, sigprof_signal_handler)
                mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
        }
 
-       mono_chain_signal (SIG_HANDLER_PARAMS);
+       mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
 }
 
 #endif
 #endif
 
-SIG_HANDLER_FUNC (static, sigquit_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigquit_signal_handler)
 {
        gboolean res;
-
-       GET_CONTEXT;
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
        /* We use this signal to start the attach agent too */
        res = mono_attach_start ();
@@ -415,16 +411,16 @@ SIG_HANDLER_FUNC (static, sigquit_signal_handler)
                mono_print_thread_dump (ctx);
        }
 
-       mono_chain_signal (SIG_HANDLER_PARAMS);
+       mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
 }
 
-SIG_HANDLER_FUNC (static, sigusr2_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigusr2_signal_handler)
 {
        gboolean enabled = mono_trace_is_enabled ();
 
        mono_trace_enable (!enabled);
 
-       mono_chain_signal (SIG_HANDLER_PARAMS);
+       mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
 }
 
 static void
index c3025a712e030cc21a894ad21e9cb97c73934a03..4b39b7ac2230065934bde90bf523b94f52998571 100644 (file)
@@ -182,7 +182,6 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
 
 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
-#define MONO_ARCH_HAVE_XP_UNWIND 1
 
 #define MONO_ARCH_GSHARED_SUPPORTED 1
 
@@ -192,7 +191,6 @@ typedef struct MonoCompileArch {
 #if !defined(MONO_CROSS_COMPILE) && !defined(TARGET_PS3)
 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
 #endif
-#define MONO_ARCH_THIS_AS_FIRST_ARG 1
 #define MONO_ARCH_HAVE_OP_TAIL_CALL 1
 
 #define PPC_NUM_REG_ARGS (PPC_LAST_ARG_REG-PPC_FIRST_ARG_REG+1)
index 50b74c51fd9de7a315072acf8d89d8c198fe984f..b40425c647861be96ad3c1c0c6d9fa5475b8b929 100644 (file)
@@ -53,8 +53,6 @@ typedef struct
 #define MONO_ARCH_IMT_REG                              s390_r9
 #define MONO_ARCH_VTABLE_REG                           MONO_ARCH_IMT_REG
 #define MONO_ARCH_RGCTX_REG                            MONO_ARCH_IMT_REG
-#define MONO_ARCH_THIS_AS_FIRST_ARG                    1
-#define MONO_ARCH_HAVE_XP_UNWIND                       1
 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX               1
 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED                 1
 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG             1
index 4b9477845585d9a18e0d5efa1758b2b77e0bb1be..ab8e452b70e93292e1bced3f59298445fbc75cd2 100644 (file)
@@ -112,8 +112,6 @@ void mono_arch_tls_init (void);
 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
 #endif
 
-#define MONO_ARCH_THIS_AS_FIRST_ARG 1
-
 #ifndef __GNUC__
 /* assume Sun compiler if not GCC */
 static void * __builtin_return_address(int depth)
index 4434564ee791c374fbce341e328e96b9e66842c3..d8f1e4298e956e681b2b67aeffe75750005c678a 100644 (file)
@@ -728,10 +728,6 @@ mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp)
         * We use one vtable trampoline per vtable slot index, so we need only the vtable,
         * the other two can be computed from the vtable + the slot index.
         */
-#ifndef MONO_ARCH_THIS_AS_FIRST_ARG
-       /* All architectures should support this */
-       g_assert_not_reached ();
-#endif
 
        /*
         * Obtain the vtable from the 'this' arg.
index 614f7af6fedda0bcbd7e92055750731c6407eef9..9488ac895d991570879327ed2b2db009742fc89b 100644 (file)
@@ -79,7 +79,7 @@ mono_runtime_cleanup_handlers (void)
  * was called, false otherwise.
  */
 gboolean
-SIG_HANDLER_SIGNATURE (mono_chain_signal)
+MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
 {
        MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
        jit_tls->mono_win_chained_exception_needs_run = TRUE;
index 5f589b258b8b1393229f1637569741eb7ea17926..05b72c05f6b237f9350d8b9cb3496ff7a9d1ec49 100644 (file)
@@ -1440,6 +1440,10 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                         * result there.
                         */
                        call->vret_in_reg = TRUE;
+#if defined(__APPLE__)
+                       if (cinfo->ret.pair_storage [0] == ArgOnDoubleFpStack || cinfo->ret.pair_storage [0] == ArgOnFloatFpStack)
+                               call->vret_in_reg_fp = TRUE;
+#endif
                        if (call->vret_var)
                                NULLIFY_INS (call->vret_var);
                }
index bce110f10359ad365578fa8e3c11f927e49c4564..f6ddc930427da887278d6b004076d4d0e52e40d5 100644 (file)
@@ -217,7 +217,6 @@ typedef struct {
 #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG
 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
 #define MONO_ARCH_HAVE_LIVERANGE_OPS 1
-#define MONO_ARCH_HAVE_XP_UNWIND 1
 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
 #if defined(__linux__) || defined (__APPLE__)
 #define MONO_ARCH_MONITOR_OBJECT_REG X86_EAX
@@ -246,7 +245,6 @@ typedef struct {
 #define MONO_ARCH_GSHARED_SUPPORTED 1
 #define MONO_ARCH_HAVE_LLVM_IMT_TRAMPOLINE 1
 #define MONO_ARCH_LLVM_SUPPORTED 1
-#define MONO_ARCH_THIS_AS_FIRST_ARG 1
 
 #if defined(MONO_ARCH_USE_SIGACTION) || defined(TARGET_WIN32)
 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
index 859c91c72f9fe0b63e9abac8ce45899083cd638d..dd40298565b71964ed4a32248f601f04bc875c1c 100755 (executable)
@@ -711,17 +711,22 @@ mono_debug_count (void)
 {
        static int count = 0;
        count ++;
+       static gboolean inited;
+       static const char *value;
 
-       if (!g_getenv ("COUNT"))
+       if (!inited) {
+               value = g_getenv ("COUNT");
+               inited = TRUE;
+       }
+
+       if (!value)
                return TRUE;
 
-       if (count == atoi (g_getenv ("COUNT"))) {
+       if (count == atoi (value))
                break_count ();
-       }
 
-       if (count > atoi (g_getenv ("COUNT"))) {
+       if (count > atoi (value))
                return FALSE;
-       }
 
        return TRUE;
 }
@@ -1241,7 +1246,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
 
        if ((num + 1) >= cfg->varinfo_count) {
                int orig_count = cfg->varinfo_count;
-               cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 64;
+               cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 32;
                cfg->varinfo = (MonoInst **)g_realloc (cfg->varinfo, sizeof (MonoInst*) * cfg->varinfo_count);
                cfg->vars = (MonoMethodVar *)g_realloc (cfg->vars, sizeof (MonoMethodVar) * cfg->varinfo_count);
                memset (&cfg->vars [orig_count], 0, (cfg->varinfo_count - orig_count) * sizeof (MonoMethodVar));
@@ -4329,18 +4334,15 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
        GSList *tmp;
        MonoMethodHeader *header;
        MonoJitInfo *jinfo;
-       int num_clauses;
-       int generic_info_size, arch_eh_info_size = 0;
-       int holes_size = 0, num_holes = 0, cas_size = 0;
+       MonoJitInfoFlags flags = JIT_INFO_NONE;
+       int num_clauses, num_holes = 0;
        guint32 stack_size = 0;
 
        g_assert (method_to_compile == cfg->method);
        header = cfg->header;
 
        if (cfg->generic_sharing_context)
-               generic_info_size = sizeof (MonoGenericJitInfo);
-       else
-               generic_info_size = 0;
+               flags |= JIT_INFO_HAS_GENERIC_JIT_INFO;
 
        if (cfg->arch_eh_jit_info) {
                MonoJitArgumentInfo *arg_info;
@@ -4354,11 +4356,11 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                stack_size = mono_arch_get_argument_info (cfg->generic_sharing_context, sig, sig->param_count, arg_info);
 
                if (stack_size)
-                       arch_eh_info_size = sizeof (MonoArchEHJitInfo);
+                       flags |= JIT_INFO_HAS_ARCH_EH_INFO;
        }
 
-       if (cfg->has_unwind_info_for_epilog && !arch_eh_info_size)
-               arch_eh_info_size = sizeof (MonoArchEHJitInfo);
+       if (cfg->has_unwind_info_for_epilog && !(flags & JIT_INFO_HAS_ARCH_EH_INFO))
+               flags |= JIT_INFO_HAS_ARCH_EH_INFO;
                
        if (cfg->try_block_holes) {
                for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
@@ -4373,34 +4375,25 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                                ++num_holes;
                }
                if (num_holes)
-                       holes_size = sizeof (MonoTryBlockHoleTableJitInfo) + num_holes * sizeof (MonoTryBlockHoleJitInfo);
+                       flags |= JIT_INFO_HAS_TRY_BLOCK_HOLES;
                if (G_UNLIKELY (cfg->verbose_level >= 4))
                        printf ("Number of try block holes %d\n", num_holes);
        }
 
-       if (mono_security_method_has_declsec (cfg->method_to_register)) {
-               cas_size = sizeof (MonoMethodCasInfo);
-       }
+       if (mono_security_method_has_declsec (cfg->method_to_register))
+               flags |= JIT_INFO_HAS_ARCH_EH_INFO;
 
        if (COMPILE_LLVM (cfg))
                num_clauses = cfg->llvm_ex_info_len;
        else
                num_clauses = header->num_clauses;
 
-       if (cfg->method->dynamic) {
-               jinfo = g_malloc0 (MONO_SIZEOF_JIT_INFO + (num_clauses * sizeof (MonoJitExceptionInfo)) +
-                               generic_info_size + holes_size + arch_eh_info_size + cas_size);
-       } else {
-               jinfo = mono_domain_alloc0 (cfg->domain, MONO_SIZEOF_JIT_INFO +
-                               (num_clauses * sizeof (MonoJitExceptionInfo)) +
-                               generic_info_size + holes_size + arch_eh_info_size + cas_size);
-       }
-
-       jinfo->d.method = cfg->method_to_register;
-       jinfo->code_start = cfg->native_code;
-       jinfo->code_size = cfg->code_len;
+       if (cfg->method->dynamic)
+               jinfo = g_malloc0 (mono_jit_info_size (flags, num_clauses, num_holes));
+       else
+               jinfo = mono_domain_alloc0 (cfg->domain, mono_jit_info_size (flags, num_clauses, num_holes));
+       mono_jit_info_init (jinfo, cfg->method_to_register, cfg->native_code, cfg->code_len, flags, num_clauses, num_holes);
        jinfo->domain_neutral = (cfg->opt & MONO_OPT_SHARED) != 0;
-       jinfo->num_clauses = num_clauses;
 
        if (COMPILE_LLVM (cfg))
                jinfo->from_llvm = TRUE;
@@ -4410,8 +4403,6 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                MonoGenericJitInfo *gi;
                GSList *loclist = NULL;
 
-               jinfo->has_generic_jit_info = 1;
-
                gi = mono_jit_info_get_generic_jit_info (jinfo);
                g_assert (gi);
 
@@ -4485,7 +4476,6 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                MonoTryBlockHoleTableJitInfo *table;
                int i;
 
-               jinfo->has_try_block_holes = 1;
                table = mono_jit_info_get_try_block_hole_table_info (jinfo);
                table->num_holes = (guint16)num_holes;
                i = 0;
@@ -4514,19 +4504,14 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                g_assert (i == num_holes);
        }
 
-       if (arch_eh_info_size) {
+       if (jinfo->has_arch_eh_info) {
                MonoArchEHJitInfo *info;
 
-               jinfo->has_arch_eh_info = 1;
                info = mono_jit_info_get_arch_eh_info (jinfo);
 
                info->stack_size = stack_size;
        }
 
-       if (cas_size) {
-               jinfo->has_cas_info = 1;
-       }
-
        if (COMPILE_LLVM (cfg)) {
                if (num_clauses)
                        memcpy (&jinfo->clauses [0], &cfg->llvm_ex_info [0], num_clauses * sizeof (MonoJitExceptionInfo));
@@ -4940,6 +4925,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 #ifdef ENABLE_LLVM
        gboolean llvm = (flags & JIT_FLAG_LLVM) ? 1 : 0;
 #endif
+       static gboolean verbose_method_inited;
+       static const char *verbose_method_name;
 
        InterlockedIncrement (&mono_jit_stats.methods_compiled);
        if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
@@ -5053,6 +5040,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
        if (cfg->generic_sharing_context) {
                method_to_register = method_to_compile;
+               cfg->gshared = TRUE;
        } else {
                g_assert (method == method_to_compile);
                method_to_register = method;
@@ -5089,9 +5077,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        {
                static gboolean inited;
 
-               if (!inited) {
+               if (!inited)
                        inited = TRUE;
-               }
 
                /* 
                 * Check for methods which cannot be compiled by LLVM early, to avoid
@@ -5167,8 +5154,12 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                cfg->opt |= MONO_OPT_ABCREM;
        }
 
-       if (g_getenv ("MONO_VERBOSE_METHOD")) {
-               const char *name = g_getenv ("MONO_VERBOSE_METHOD");
+       if (!verbose_method_inited) {
+               verbose_method_name = g_getenv ("MONO_VERBOSE_METHOD");
+               verbose_method_inited = TRUE;
+       }
+       if (verbose_method_name) {
+               const char *name = verbose_method_name;
 
                if ((strchr (name, '.') > name) || strchr (name, ':')) {
                        MonoMethodDesc *desc;
@@ -5179,7 +5170,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                        }
                        mono_method_desc_free (desc);
                } else {
-                       if (strcmp (cfg->method->name, g_getenv ("MONO_VERBOSE_METHOD")) == 0)
+                       if (strcmp (cfg->method->name, name) == 0)
                                cfg->verbose_level = 4;
                }
        }
@@ -5286,7 +5277,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        /* SSAPRE is not supported on linear IR */
        cfg->opt &= ~MONO_OPT_SSAPRE;
 
-       i = mono_method_to_ir (cfg, method_to_compile, NULL, NULL, NULL, NULL, NULL, 0, FALSE);
+       i = mono_method_to_ir (cfg, method_to_compile, NULL, NULL, NULL, NULL, 0, FALSE);
 
        if (i < 0) {
                if (try_generic_shared && cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
@@ -6743,14 +6734,12 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
        return runtime_invoke (obj, params, exc, info->compiled_method);
 }
 
-SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
 {
        MonoException *exc = NULL;
        MonoJitInfo *ji;
-#if !(defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32))
-       void *info = NULL;
-#endif
-       GET_CONTEXT;
+       void *info = MONO_SIG_HANDLER_GET_INFO ();
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
        ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
 
@@ -6768,12 +6757,12 @@ SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
 #endif
 
        if (!ji) {
-               if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
 
                mono_handle_native_sigsegv (SIGSEGV, ctx);
                if (mono_do_crash_chaining) {
-                       mono_chain_signal (SIG_HANDLER_PARAMS);
+                       mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
                        return;
                }
        }
@@ -6781,10 +6770,10 @@ SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
        mono_arch_handle_exception (ctx, exc);
 }
 
-SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
 {
        MonoException *exc;
-       GET_CONTEXT;
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
        exc = mono_get_exception_execution_engine ("SIGILL");
        
@@ -6795,13 +6784,15 @@ SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
 #define HAVE_SIG_INFO
 #endif
 
-SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 {
        MonoJitInfo *ji;
        MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
        gpointer fault_addr = NULL;
-
-       GET_CONTEXT;
+#ifdef HAVE_SIG_INFO
+       MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
+#endif
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
 #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO)
        if (mono_arch_is_single_step_event (info, ctx)) {
@@ -6823,11 +6814,11 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 
        /* The thread might no be registered with the runtime */
        if (!mono_domain_get () || !jit_tls) {
-               if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
                mono_handle_native_sigsegv (SIGSEGV, ctx);
                if (mono_do_crash_chaining) {
-                       mono_chain_signal (SIG_HANDLER_PARAMS);
+                       mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
                        return;
                }
        }
@@ -6860,7 +6851,7 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
                g_assert_not_reached ();
        } else {
                /* The original handler might not like that it is executed on an altstack... */
-               if (!ji && mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!ji && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
 
                mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE);
@@ -6868,13 +6859,13 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 #else
 
        if (!ji) {
-               if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
 
                mono_handle_native_sigsegv (SIGSEGV, ctx);
 
                if (mono_do_crash_chaining) {
-                       mono_chain_signal (SIG_HANDLER_PARAMS);
+                       mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
                        return;
                }
        }
@@ -6883,10 +6874,10 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 #endif
 }
 
-SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
 {
        MonoException *exc;
-       GET_CONTEXT;
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
        exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
        
@@ -7974,6 +7965,8 @@ mono_precompile_assembly (MonoAssembly *ass, void *user_data)
                method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
                if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
                        continue;
+               if (method->is_generic || method->klass->generic_container)
+                       continue;
 
                count++;
                if (mini_verbose > 1) {
index f989bc274162fe8eb07217769c3a3789cc6b81cd..8d9bcc9f2065aad4a88f8d1510fdc5107a80d27d 100755 (executable)
@@ -31,6 +31,7 @@
 #include <mono/utils/mono-tls.h>
 #include <mono/utils/atomic.h>
 #include <mono/utils/mono-conc-hashtable.h>
+#include <mono/utils/mono-signal-handler.h>
 
 #define MONO_BREAKPOINT_ARRAY_SIZE 64
 
 #error "The code in mini/ should not depend on these defines."
 #endif
 
-#ifndef G_LIKELY
-#define G_LIKELY(a) (a)
-#define G_UNLIKELY(a) (a)
-#endif
-
-#ifndef G_MAXINT32
-#define G_MAXINT32 2147483647
-#endif
-
-#ifndef G_MININT32
-#define G_MININT32 (-G_MAXINT32 - 1)
-#endif
-
 #ifndef __GNUC__
 /*#define __alignof__(a) sizeof(a)*/
 #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
@@ -851,6 +839,8 @@ struct MonoCallInst {
         * calling convention as OP_CALL.
         */
        guint vret_in_reg : 1;
+       /* Whenever vret_in_reg returns fp values */
+       guint vret_in_reg_fp : 1;
        /* Whenever there is an IMT argument and it is dynamic */
        guint dynamic_imt_arg : 1;
        /* Whenever there is an RGCTX argument */
@@ -956,6 +946,14 @@ enum {
 #define inst_phi_args   data.op[1].phi_args
 #define inst_eh_block   data.op[1].exception_clause
 
+static inline void
+mono_inst_set_src_registers (MonoInst *ins, int *regs)
+{
+       ins->sreg1 = regs [0];
+       ins->sreg2 = regs [1];
+       ins->sreg3 = regs [2];
+}
+
 /* instruction description for use in regalloc/scheduling */
 enum {
        MONO_INST_DEST,
@@ -1426,8 +1424,6 @@ typedef struct {
        MonoGenericSharingContext gsctx;
        MonoGenericContext *gsctx_context;
 
-       gboolean gsharedvt;
-
        MonoGSharedVtMethodInfo *gsharedvt_info;
 
        /* Points to the gsharedvt locals area at runtime */
@@ -1524,6 +1520,9 @@ typedef struct {
        guint            has_atomic_cas_i4 : 1;
        guint            check_pinvoke_callconv : 1;
        guint            has_unwind_info_for_epilog : 1;
+       guint            disable_inline : 1;
+       guint            gshared : 1;
+       guint            gsharedvt : 1;
        gpointer         debug_info;
        guint32          lmf_offset;
     guint16          *intvars;
@@ -1540,6 +1539,8 @@ typedef struct {
        guint32          encoded_unwind_ops_len;
        GSList*          unwind_ops;
 
+       GList*           dont_inline;
+
        /* Fields used by the local reg allocator */
        void*            reginfo;
        int              reginfo_len;
@@ -2030,7 +2031,6 @@ MONO_API void      mono_print_method_from_ip         (void *ip);
 MONO_API char     *mono_pmip                         (void *ip);
 gboolean  mono_debug_count                  (void) MONO_INTERNAL;
 MONO_API const char* mono_inst_name                  (int op);
-void      mono_inst_set_src_registers       (MonoInst *ins, int *regs) MONO_INTERNAL;
 int       mono_op_to_op_imm                 (int opcode) MONO_INTERNAL;
 int       mono_op_imm_to_op                 (int opcode) MONO_INTERNAL;
 int       mono_load_membase_to_load_mem     (int opcode) MONO_INTERNAL;
@@ -2174,6 +2174,8 @@ guint32  mono_aot_method_hash               (MonoMethod *method) MONO_INTERNAL;
 MonoMethod* mono_aot_get_array_helper_from_wrapper (MonoMethod *method) MONO_INTERNAL;
 guint32  mono_aot_get_got_offset            (MonoJumpInfo *ji) MONO_LLVM_INTERNAL;
 char*    mono_aot_get_method_name           (MonoCompile *cfg) MONO_LLVM_INTERNAL;
+gboolean mono_aot_is_direct_callable        (MonoJumpInfo *patch_info) MONO_LLVM_INTERNAL;
+void     mono_aot_mark_unused_llvm_plt_entry(MonoJumpInfo *patch_info) MONO_LLVM_INTERNAL;
 char*    mono_aot_get_plt_symbol            (MonoJumpInfoType type, gconstpointer data) MONO_LLVM_INTERNAL;
 int      mono_aot_get_method_index          (MonoMethod *method) MONO_LLVM_INTERNAL;
 MonoJumpInfo* mono_aot_patch_info_dup       (MonoJumpInfo* ji) MONO_LLVM_INTERNAL;
@@ -2295,7 +2297,7 @@ void              mono_tramp_info_register (MonoTrampInfo *info) MONO_INTERNAL;
 int               mini_exception_id_by_name (const char *name) MONO_INTERNAL;
 
 int               mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, 
-                                                                        MonoInst *return_var, GList *dont_inline, MonoInst **inline_args, 
+                                                                        MonoInst *return_var, MonoInst **inline_args,
                                                                         guint inline_offset, gboolean is_virtual_call) MONO_INTERNAL;
 
 MonoInst         *mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) MONO_INTERNAL;
@@ -2821,53 +2823,12 @@ void mono_cross_helpers_run (void) MONO_INTERNAL;
 /*
  * Signal handling
  */
-#ifdef MONO_GET_CONTEXT
-#define GET_CONTEXT MONO_GET_CONTEXT
-#endif
-
-#ifndef GET_CONTEXT
-#ifdef HOST_WIN32
-/* seh_vectored_exception_handler () passes in a CONTEXT* */
-#define GET_CONTEXT \
-    void *ctx = context;
-#else
-#ifdef MONO_ARCH_USE_SIGACTION
-#define GET_CONTEXT \
-    void *ctx = context;
-#elif defined(__HAIKU__)
-#define GET_CONTEXT \
-       void *ctx = &regs;
-#else
-#define GET_CONTEXT \
-       void **_p = (void **)&_dummy; \
-       struct sigcontext *ctx = (struct sigcontext *)++_p;
-#endif
-#endif
-#endif
-
-#if defined(MONO_ARCH_USE_SIGACTION) && !defined(HOST_WIN32)
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *info, void *context)
-#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, siginfo_t *info, void *context))
-#define SIG_HANDLER_PARAMS _dummy, info, context
-#elif defined(HOST_WIN32)
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_POINTERS *info, void *context)
-#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, EXCEPTION_POINTERS *info, void *context))
-#define SIG_HANDLER_PARAMS _dummy, info, context
-#elif defined(__HAIKU__)
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, void *userData, vregs regs)
-#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, void *userData, vregs regs))
-#define SIG_HANDLER_PARAMS _dummy, userData, regs
-#else
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy)
-#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy))
-#define SIG_HANDLER_PARAMS _dummy
-#endif
 
-void SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler)  MONO_INTERNAL;
-void SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler)  MONO_INTERNAL;
-void SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) MONO_INTERNAL;
-void SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler)  MONO_INTERNAL;
-gboolean SIG_HANDLER_SIGNATURE (mono_chain_signal) MONO_INTERNAL;
+void MONO_SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler)  MONO_INTERNAL;
+void MONO_SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler)  MONO_INTERNAL;
+void MONO_SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) MONO_INTERNAL;
+void MONO_SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler)  MONO_INTERNAL;
+gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) MONO_INTERNAL;
 
 #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
 #define ARCH_HAVE_DELEGATE_TRAMPOLINES 1
index 801826b96e8b098caf1a5f102a3cde6b0aabce33..160db5fec5701c166d517e5b41a1739574ef52e3 100644 (file)
 //#define DEBUG_SSA 1
 
 #define NEW_PHI(cfg,dest,val) do {     \
-               (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->opcode = OP_PHI;        \
-               (dest)->inst_c0 = (val);        \
-        (dest)->dreg = (dest)->sreg1 = (dest)->sreg2 = -1; \
+       MONO_INST_NEW ((cfg), (dest), OP_PHI); \
+       (dest)->inst_c0 = (val);                                                           \
        } while (0)
 
 typedef struct {
@@ -530,8 +528,7 @@ mono_ssa_remove (MonoCompile *cfg)
                                                }
                                        }
 
-                                       ins->opcode = OP_NOP;
-                                       ins->dreg = -1;
+                                       NULLIFY_INS (ins);
                                }
                        }
                }
@@ -1287,12 +1284,10 @@ mono_ssa_deadce (MonoCompile *cfg)
                                MonoInst *src_var = get_vreg_to_inst (cfg, def->sreg1);
                                if (src_var && !(src_var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)))
                                        add_to_dce_worklist (cfg, info, MONO_VARINFO (cfg, src_var->inst_c0), &work_list);
-                               def->opcode = OP_NOP;
-                               def->dreg = def->sreg1 = def->sreg2 = -1;
+                               NULLIFY_INS (def);
                                info->reg = -1;
                        } else if ((def->opcode == OP_ICONST) || (def->opcode == OP_I8CONST) || MONO_IS_ZERO (def)) {
-                               def->opcode = OP_NOP;
-                               def->dreg = def->sreg1 = def->sreg2 = -1;
+                               NULLIFY_INS (def);
                                info->reg = -1;
                        } else if (MONO_IS_PHI (def)) {
                                int j;
@@ -1300,8 +1295,7 @@ mono_ssa_deadce (MonoCompile *cfg)
                                        MonoMethodVar *u = MONO_VARINFO (cfg, get_vreg_to_inst (cfg, def->inst_phi_args [j])->inst_c0);
                                        add_to_dce_worklist (cfg, info, u, &work_list);
                                }
-                               def->opcode = OP_NOP;
-                               def->dreg = def->sreg1 = def->sreg2 = -1;
+                               NULLIFY_INS (def);
                                info->reg = -1;
                        }
                        else if (def->opcode == OP_NOP) {
index bb500a7c0f505c954834f36b68c97deb7a424337..f9e651093b46e07958d0068840b5361de5487998 100644 (file)
@@ -505,17 +505,21 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
 
        tramp = mono_get_trampoline_code (tramp_type);
 
-       mono_domain_lock (domain);
+       if (domain) {
+               mono_domain_lock (domain);
 #ifdef USE_JUMP_TABLES
-       code = buf = mono_domain_code_reserve_align (domain, size, 4);
+               code = buf = mono_domain_code_reserve_align (domain, size, 4);
 #else
-       code = buf = mono_domain_code_reserve_align (domain, size, 4);
-       if ((short_branch = branch_for_target_reachable (code + 4, tramp))) {
-               size = 12;
-               mono_domain_code_commit (domain, code, SPEC_TRAMP_SIZE, size);
+               code = buf = mono_domain_code_reserve_align (domain, size, 4);
+               if ((short_branch = branch_for_target_reachable (code + 4, tramp))) {
+                       size = 12;
+                       mono_domain_code_commit (domain, code, SPEC_TRAMP_SIZE, size);
        }
 #endif
-       mono_domain_unlock (domain);
+               mono_domain_unlock (domain);
+       } else {
+               code = buf = mono_global_codeman_reserve (size);
+       }
 
 #ifdef USE_JUMP_TABLES
        /* For jumptables case we always generate the same code for trampolines,
@@ -894,6 +898,59 @@ mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean a
        return buf;
 }
 
+static gpointer
+handler_block_trampoline_helper (gpointer *ptr)
+{
+       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       return jit_tls->handler_block_return_address;
+}
+
+gpointer
+mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *tramp;
+       guint8 *code, *buf;
+       int tramp_size = 64;
+       MonoJumpInfo *ji = NULL;
+       GSList *unwind_ops = NULL;
+
+       g_assert (!aot);
+
+       code = buf = mono_global_codeman_reserve (tramp_size);
+
+       tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD, NULL, NULL);
+
+       /*
+       This trampoline restore the call chain of the handler block then jumps into the code that deals with it.
+       */
+
+       /*
+        * We are in a method frame after the call emitted by OP_CALL_HANDLER.
+        */
+       /* Obtain jit_tls->handler_block_return_address */
+       ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0);
+       ARM_B (code, 0);
+       *(gpointer*)code = handler_block_trampoline_helper;
+       code += 4;
+
+       /* Set it as the return address so the trampoline will return to it */
+       ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_R0);
+
+       /* Call the trampoline */
+       ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0);
+       code = emit_bx (code, ARMREG_R0);
+       *(gpointer*)code = tramp;
+       code += 4;
+
+       mono_arch_flush_icache (buf, code - buf);
+       g_assert (code - buf <= tramp_size);
+
+       if (info)
+               *info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
+
+       return buf;
+}
+
 #else
 
 guchar*
@@ -944,6 +1001,13 @@ mono_arch_get_nullified_class_init_trampoline (MonoTrampInfo **info)
        g_assert_not_reached ();
        return NULL;
 }
+
+gpointer
+mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
        
 #endif /* DISABLE_JIT */
 
index 31024bfee0fb011d9517cec37af4ca10cbe764bf..d6710939787bbe54af92a3848322942a9b98f137 100644 (file)
@@ -349,9 +349,10 @@ mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
        GSList *l;
        MonoUnwindOp *op;
        int loc;
-       guint8 *buf, *p, *res;
+       guint8 buf [4096];
+       guint8 *p, *res;
 
-       p = buf = g_malloc0 (4096);
+       p = buf;
 
        loc = 0;
        l = unwind_ops;
@@ -443,7 +444,6 @@ mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
        *out_len = p - buf;
        res = g_malloc (p - buf);
        memcpy (res, buf, p - buf);
-       g_free (buf);
        return res;
 }
 
@@ -498,6 +498,8 @@ mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
        int state_stack_pos;
 
        memset (reg_saved, 0, sizeof (reg_saved));
+       state_stack [0].cfa_reg = -1;
+       state_stack [0].cfa_offset = 0;
 
        p = unwind_info;
        pos = 0;
index c2a31ce1ea3532db21c42ecd459079fa733bfac2..7bda38843ef4d8df290858f41da479d940727c6c 100644 (file)
@@ -3,7 +3,7 @@
 
 #include "mini.h"
 
-#if defined(HOST_WIN32) || !defined(HAVE_SYS_IPC_H) || !defined(HAVE_SYS_SEM_H) || (defined(__native_client__) && defined(__GLIBC__))
+#if defined(HOST_WIN32) || !defined(HAVE_SYS_IPC_H) || !defined(HAVE_SYS_SEM_H) || (defined(__native_client__) && defined(__GLIBC__)) || defined(DISABLE_SHARED_HANDLES)
 
 int mini_wapi_hps (int argc, char **argv)
 {
@@ -42,7 +42,6 @@ static const gchar *thread_details (struct _WapiHandleShared *handle);
 static const gchar *namedmutex_details (struct _WapiHandleShared *handle);
 static const gchar *namedsem_details (struct _WapiHandleShared *handle);
 static const gchar *namedevent_details (struct _WapiHandleShared *handle);
-static const gchar *process_details (struct _WapiHandleShared *handle);
 
 /* This depends on the ordering of the enum WapiHandleType in
  * io-layer/wapi-private.h
@@ -58,7 +57,7 @@ static const gchar * (*details[])(struct _WapiHandleShared *)=
        unshared_details,               /* event */
        unshared_details,               /* socket */
        unshared_details,               /* find */
-       process_details,
+       unshared_details,       /* process */
        unshared_details,               /* pipe */
        namedmutex_details,
        namedsem_details,
@@ -191,20 +190,6 @@ static const gchar *namedevent_details (struct _WapiHandleShared *handle)
        return(buf);
 }
 
-static const gchar *process_details (struct _WapiHandleShared *handle)
-{
-       static gchar buf[80];
-       gchar *name;
-       struct _WapiHandle_process *proc=&handle->u.process;
-       
-       name = proc->proc_name;
-       
-       g_snprintf (buf, sizeof(buf), "[%25.25s] pid: %5u exit: %u",
-                   name==NULL?(gchar *)"":name, proc->id, proc->exitstatus);
-       
-       return(buf);
-}
-
 /* The old handles/semdel.c */
 int mini_wapi_semdel (int argc, char **argv)
 {
index 585b5641829af3d4668b8035161874947dca3cea..25555809f1d2c425b7721bc56361777fe40f13fb 100644 (file)
@@ -3,7 +3,6 @@ if HOST_WIN32
 export HOST_CC
 endif
 
-if JIT_SUPPORTED
 if DISABLE_EXECUTABLES
 runtime_lib=../mini/$(LIBMONO_LA) $(static_libs)
 else
@@ -20,9 +19,6 @@ else
 runtime_lib=../mini/$(LIBMONO_LA)
 endif
 endif
-else
-runtime_lib=../interpreter/libmint.la
-endif
 
 if DISABLE_EXECUTABLES
 bin_PROGRAMS =
index 25bb9b51f707d608ed13a4e80d042ebdb38f6349..b0d1e2f77de31eb14d83c4acd3f8a0a841c43b12 100644 (file)
@@ -11,7 +11,6 @@ AM_CPPFLAGS = \
 
 if !DISABLE_LIBRARIES
 if !DISABLE_PROFILER
-if JIT_SUPPORTED
 bin_PROGRAMS = mprof-report
 lib_LTLIBRARIES = libmono-profiler-cov.la libmono-profiler-aot.la libmono-profiler-iomap.la libmono-profiler-log.la
 if PLATFORM_DARWIN
@@ -22,7 +21,6 @@ libmono_profiler_log_la_LDFLAGS = -avoid-version
 endif
 endif
 endif
-endif
 
 if HAVE_OPROFILE
 # Do something that uses OPROFILE_CFLAGS and OPROFILE_LIBS
index e057944bbd7ef44810b06a3c925dbc9e51e5c0ac..ceecaf02ae426835d9d311b09c9c2e1a96b3fce8 100644 (file)
@@ -5313,6 +5313,20 @@ mono_test_marshal_return_lpwstr (void)
        return res;
 }
 
+typedef struct {
+       double d;
+} SingleDoubleStruct;
+
+LIBTEST_API SingleDoubleStruct STDCALL
+mono_test_marshal_return_single_double_struct (void)
+{
+       SingleDoubleStruct res;
+
+       res.d = 3.0;
+
+       return res;
+}
+
 
 #ifndef TARGET_X86
 
index 71c51a7d814253544288637233c608619309ac3f..edf9a6dad4566e205c8a04c0192bfa77fa4b2563 100644 (file)
@@ -71,6 +71,11 @@ public class Tests {
                public SimpleDelegate del3;
        }
 
+       [StructLayout (LayoutKind.Sequential)]
+       public struct SingleDoubleStruct {
+               public double d;
+       }
+
        /* sparcv9 has complex conventions when passing structs with doubles in them 
           by value, some simple tests for them */
        [StructLayout (LayoutKind.Sequential)]
@@ -1800,5 +1805,16 @@ public class Tests {
 
                return 0;
        }
+
+       [DllImport ("libtest", EntryPoint = "mono_test_marshal_return_single_double_struct")]
+       public static extern SingleDoubleStruct mono_test_marshal_return_single_double_struct ();
+
+       public static int test_0_x86_single_double_struct_ret () {
+               double d = mono_test_marshal_return_single_double_struct ().d;
+               if (d != 3.0)
+                       return 1;
+               else
+                       return 0;
+       }
 }
 
index ce0d65e74189bd049872cf8b414a8529a36f3348..24caf07cc133be4aa6d8ebdee53c9b05687e52c3 100644 (file)
@@ -301,6 +301,7 @@ public class TestRunner
                        lock (monitor) {
                                foreach (Process p in processes) {
                                        Console.WriteLine (process_data [p].test);
+                                       p.Kill ();
                                }
                        }
                        return 1;
index c5464d16b168375dc3ac31375765a299ebeaa97b..c2c8a0d790caf688585dc16216fbd40474f17226 100644 (file)
@@ -32,6 +32,7 @@ monoutils_sources = \
        mono-math.c             \
        mono-mmap.c             \
        mono-mmap.h             \
+       mono-mmap-internal.h    \
        mono-mutex.c            \
        mono-mutex.h            \
        mono-networkinterfaces.c                \
index 4befb3b86a04ab38e593210e624d49cba37486f3..33fed096ea4a159f6dadc96386fce36f8ba96986 100644 (file)
@@ -113,6 +113,7 @@ struct _MonoLockFreeAllocDescriptor {
        MonoLockFreeAllocator *heap;
        volatile Anchor anchor;
        unsigned int slot_size;
+       unsigned int block_size;
        unsigned int max_count;
        gpointer sb;
 #ifndef DESC_AVAIL_DUMMY
@@ -123,12 +124,11 @@ struct _MonoLockFreeAllocDescriptor {
 
 #define NUM_DESC_BATCH 64
 
-#define SB_SIZE                16384
-#define SB_HEADER_SIZE 16
-#define SB_USABLE_SIZE (SB_SIZE - SB_HEADER_SIZE)
-
-#define SB_HEADER_FOR_ADDR(a)  ((gpointer)((size_t)(a) & ~(size_t)(SB_SIZE-1)))
-#define DESCRIPTOR_FOR_ADDR(a) (*(Descriptor**)SB_HEADER_FOR_ADDR (a))
+static MONO_ALWAYS_INLINE gpointer
+sb_header_for_addr (gpointer addr, size_t block_size)
+{
+       return (gpointer)(((size_t)addr) & (~(block_size - 1)));
+}
 
 /* Taken from SGen */
 
@@ -139,41 +139,34 @@ prot_flags_for_activate (int activate)
        return prot_flags | MONO_MMAP_PRIVATE | MONO_MMAP_ANON;
 }
 
-static void*
-mono_sgen_alloc_os_memory (size_t size, int activate)
+static gpointer
+alloc_sb (Descriptor *desc)
 {
-       return mono_valloc (0, size, prot_flags_for_activate (activate));
-}
+       static int pagesize = -1;
 
-static void
-mono_sgen_free_os_memory (void *addr, size_t size)
-{
-       mono_vfree (addr, size);
-}
+       gpointer sb_header;
 
-/* size must be a power of 2 */
-static void*
-mono_sgen_alloc_os_memory_aligned (size_t size, size_t alignment, gboolean activate)
-{
-       return mono_valloc_aligned (size, alignment, prot_flags_for_activate (activate));
-}
+       if (pagesize == -1)
+               pagesize = mono_pagesize ();
 
-static gpointer
-alloc_sb (Descriptor *desc)
-{
-       gpointer sb_header = mono_sgen_alloc_os_memory_aligned (SB_SIZE, SB_SIZE, TRUE);
-       g_assert (sb_header == SB_HEADER_FOR_ADDR (sb_header));
-       DESCRIPTOR_FOR_ADDR (sb_header) = desc;
+       sb_header = desc->block_size == pagesize ?
+               mono_valloc (0, desc->block_size, prot_flags_for_activate (TRUE)) :
+               mono_valloc_aligned (desc->block_size, desc->block_size, prot_flags_for_activate (TRUE));
+
+       g_assert (sb_header == sb_header_for_addr (sb_header, desc->block_size));
+
+       *(Descriptor**)sb_header = desc;
        //g_print ("sb %p for %p\n", sb_header, desc);
-       return (char*)sb_header + SB_HEADER_SIZE;
+
+       return (char*)sb_header + LOCK_FREE_ALLOC_SB_HEADER_SIZE;
 }
 
 static void
-free_sb (gpointer sb)
+free_sb (gpointer sb, size_t block_size)
 {
-       gpointer sb_header = SB_HEADER_FOR_ADDR (sb);
-       g_assert ((char*)sb_header + SB_HEADER_SIZE == sb);
-       mono_sgen_free_os_memory (sb_header, SB_SIZE);
+       gpointer sb_header = sb_header_for_addr (sb, block_size);
+       g_assert ((char*)sb_header + LOCK_FREE_ALLOC_SB_HEADER_SIZE == sb);
+       mono_vfree (sb_header, block_size);
        //g_print ("free sb %p\n", sb_header);
 }
 
@@ -198,7 +191,7 @@ desc_alloc (void)
                        Descriptor *d;
                        int i;
 
-                       desc = mono_sgen_alloc_os_memory (desc_size * NUM_DESC_BATCH, TRUE);
+                       desc = mono_valloc (0, desc_size * NUM_DESC_BATCH, prot_flags_for_activate (TRUE));
 
                        /* Organize into linked list. */
                        d = desc;
@@ -214,7 +207,7 @@ desc_alloc (void)
                        success = (InterlockedCompareExchangePointer ((gpointer * volatile)&desc_avail, desc->next, NULL) == NULL);
 
                        if (!success)
-                               mono_sgen_free_os_memory (desc, desc_size * NUM_DESC_BATCH);
+                               mono_vfree (desc, desc_size * NUM_DESC_BATCH);
                }
 
                mono_hazard_pointer_clear (hp, 1);
@@ -251,7 +244,7 @@ desc_retire (Descriptor *desc)
        g_assert (desc->anchor.data.state == STATE_EMPTY);
        g_assert (desc->in_use);
        desc->in_use = FALSE;
-       free_sb (desc->sb);
+       free_sb (desc->sb, desc->block_size);
        mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, FALSE, TRUE);
 }
 #else
@@ -271,7 +264,7 @@ desc_alloc (void)
 static void
 desc_retire (Descriptor *desc)
 {
-       free_sb (desc->sb);
+       free_sb (desc->sb, desc->block_size);
        mono_lock_free_queue_enqueue (&available_descs, &desc->node);
 }
 #endif
@@ -388,7 +381,7 @@ alloc_from_active_or_partial (MonoLockFreeAllocator *heap)
                mono_memory_read_barrier ();
 
                next = *(unsigned int*)addr;
-               g_assert (next < SB_USABLE_SIZE / desc->slot_size);
+               g_assert (next < LOCK_FREE_ALLOC_SB_USABLE_SIZE (desc->block_size) / desc->slot_size);
 
                new_anchor.data.avail = next;
                --new_anchor.data.count;
@@ -409,17 +402,12 @@ alloc_from_active_or_partial (MonoLockFreeAllocator *heap)
 static gpointer
 alloc_from_new_sb (MonoLockFreeAllocator *heap)
 {
-       unsigned int slot_size, count, i;
+       unsigned int slot_size, block_size, count, i;
        Descriptor *desc = desc_alloc ();
 
-       desc->sb = alloc_sb (desc);
-
        slot_size = desc->slot_size = heap->sc->slot_size;
-       count = SB_USABLE_SIZE / slot_size;
-
-       /* Organize blocks into linked list. */
-       for (i = 1; i < count - 1; ++i)
-               *(unsigned int*)((char*)desc->sb + i * slot_size) = i + 1;
+       block_size = desc->block_size = heap->sc->block_size;
+       count = LOCK_FREE_ALLOC_SB_USABLE_SIZE (block_size) / slot_size;
 
        desc->heap = heap;
        /*
@@ -433,6 +421,12 @@ alloc_from_new_sb (MonoLockFreeAllocator *heap)
        desc->anchor.data.count = desc->max_count - 1;
        desc->anchor.data.state = STATE_PARTIAL;
 
+       desc->sb = alloc_sb (desc);
+
+       /* Organize blocks into linked list. */
+       for (i = 1; i < count - 1; ++i)
+               *(unsigned int*)((char*)desc->sb + i * slot_size) = i + 1;
+
        mono_memory_write_barrier ();
 
        /* Make it active or free it again. */
@@ -465,22 +459,23 @@ mono_lock_free_alloc (MonoLockFreeAllocator *heap)
 }
 
 void
-mono_lock_free_free (gpointer ptr)
+mono_lock_free_free (gpointer ptr, size_t block_size)
 {
        Anchor old_anchor, new_anchor;
        Descriptor *desc;
        gpointer sb;
        MonoLockFreeAllocator *heap = NULL;
 
-       desc = DESCRIPTOR_FOR_ADDR (ptr);
+       desc = *(Descriptor**) sb_header_for_addr (ptr, block_size);
+       g_assert (block_size == desc->block_size);
+
        sb = desc->sb;
-       g_assert (SB_HEADER_FOR_ADDR (ptr) == SB_HEADER_FOR_ADDR (sb));
 
        do {
                new_anchor = old_anchor = *(volatile Anchor*)&desc->anchor.value;
                *(unsigned int*)ptr = old_anchor.data.avail;
                new_anchor.data.avail = ((char*)ptr - (char*)sb) / desc->slot_size;
-               g_assert (new_anchor.data.avail < SB_USABLE_SIZE / desc->slot_size);
+               g_assert (new_anchor.data.avail < LOCK_FREE_ALLOC_SB_USABLE_SIZE (block_size) / desc->slot_size);
 
                if (old_anchor.data.state == STATE_FULL)
                        new_anchor.data.state = STATE_PARTIAL;
@@ -530,7 +525,7 @@ static void
 descriptor_check_consistency (Descriptor *desc, gboolean print)
 {
        int count = desc->anchor.data.count;
-       int max_count = SB_USABLE_SIZE / desc->slot_size;
+       int max_count = LOCK_FREE_ALLOC_SB_USABLE_SIZE (desc->block_size) / desc->slot_size;
 #if _MSC_VER
        gboolean* linked = alloca(max_count*sizeof(gboolean));
 #else
@@ -607,12 +602,15 @@ mono_lock_free_allocator_check_consistency (MonoLockFreeAllocator *heap)
 }
 
 void
-mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size)
+mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size, unsigned int block_size)
 {
-       g_assert (slot_size <= SB_USABLE_SIZE / 2);
+       g_assert (block_size > 0);
+       g_assert ((block_size & (block_size - 1)) == 0); /* check if power of 2 */
+       g_assert (slot_size * 2 <= LOCK_FREE_ALLOC_SB_USABLE_SIZE (block_size));
 
        mono_lock_free_queue_init (&sc->partial);
        sc->slot_size = slot_size;
+       sc->block_size = block_size;
 }
 
 void
index ed07a2971a5a54f788a922de691c6090e79e9064..84935646d372c8665fb8a4301867873bf47a084c 100644 (file)
@@ -33,6 +33,7 @@
 typedef struct {
        MonoLockFreeQueue partial;
        unsigned int slot_size;
+       unsigned int block_size;
 } MonoLockFreeAllocSizeClass;
 
 struct _MonoLockFreeAllocDescriptor;
@@ -42,11 +43,15 @@ typedef struct {
        MonoLockFreeAllocSizeClass *sc;
 } MonoLockFreeAllocator;
 
-void mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size) MONO_INTERNAL;
+#define LOCK_FREE_ALLOC_SB_MAX_SIZE                                    16384
+#define LOCK_FREE_ALLOC_SB_HEADER_SIZE                         (sizeof (MonoLockFreeAllocator))
+#define LOCK_FREE_ALLOC_SB_USABLE_SIZE(block_size)     ((block_size) - LOCK_FREE_ALLOC_SB_HEADER_SIZE)
+
+void mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size, unsigned int block_size) MONO_INTERNAL;
 void mono_lock_free_allocator_init_allocator (MonoLockFreeAllocator *heap, MonoLockFreeAllocSizeClass *sc) MONO_INTERNAL;
 
 gpointer mono_lock_free_alloc (MonoLockFreeAllocator *heap) MONO_INTERNAL;
-void mono_lock_free_free (gpointer ptr) MONO_INTERNAL;
+void mono_lock_free_free (gpointer ptr, size_t block_size) MONO_INTERNAL;
 
 gboolean mono_lock_free_allocator_check_consistency (MonoLockFreeAllocator *heap) MONO_INTERNAL;
 
index 619e574e424c509728ba2d009543f18557cacea9..3b01b49f0669d5f0abcd4c6ca1f010c59c26ea4b 100755 (executable)
@@ -240,6 +240,8 @@ extern void mono_context_get_current (void *);
 
 #elif (defined(__arm__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM)) /* defined(__x86_64__) */
 
+#include <mono/arch/arm/arm-codegen.h>
+
 typedef struct {
        mgreg_t pc;
        mgreg_t regs [16];
diff --git a/mono/utils/mono-mmap-internal.h b/mono/utils/mono-mmap-internal.h
new file mode 100644 (file)
index 0000000..1818e5c
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * mono-mmap-internal.h: Internal virtual memory stuff.
+ *
+ * Copyright (C) 2014 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MONO_UTILS_MMAP_INTERNAL_H__
+#define __MONO_UTILS_MMAP_INTERNAL_H__
+
+#include "mono-compiler.h"
+
+int mono_pages_not_faulted (void *addr, size_t length) MONO_INTERNAL;
+
+#endif /* __MONO_UTILS_MMAP_INTERNAL_H__ */
+
index 60ef156b15af7ed752361b70a36a625aee3fabbc..6caf9628380f2f3ab8cab48c096dd5a913286e17 100644 (file)
@@ -29,6 +29,7 @@
 #endif
 
 #include "mono-mmap.h"
+#include "mono-mmap-internal.h"
 #include "mono-proclib.h"
 
 #ifndef MAP_ANONYMOUS
@@ -243,6 +244,12 @@ mono_shared_area_instances (void **array, int count)
        return 0;
 }
 
+int
+mono_pages_not_faulted (void *addr, size_t length)
+{
+       return -1;
+}
+
 #else
 #if defined(HAVE_MMAP)
 
@@ -443,6 +450,30 @@ mono_mprotect (void *addr, size_t length, int flags)
 }
 #endif // __native_client__
 
+int
+mono_pages_not_faulted (void *addr, size_t size)
+{
+       int i;
+       gint64 count;
+       int pagesize = mono_pagesize ();
+       int npages = (size + pagesize - 1) / pagesize;
+       char *faulted = g_malloc0 (sizeof (char*) * npages);
+
+       if (mincore (addr, size, faulted) != 0) {
+               count = -1;
+       } else {
+               count = 0;
+               for (i = 0; i < npages; ++i) {
+                       if (faulted [i] != 0)
+                               ++count;
+               }
+       }
+
+       g_free (faulted);
+
+       return count;
+}
+
 #else
 
 /* dummy malloc-based implementation */
@@ -481,6 +512,13 @@ mono_mprotect (void *addr, size_t length, int flags)
        }
        return 0;
 }
+
+int
+mono_pages_not_faulted (void *addr, size_t length)
+{
+       return -1;
+}
+
 #endif // HAVE_MMAP
 
 #if defined(HAVE_SHM_OPEN) && !defined (DISABLE_SHARED_PERFCOUNTERS)
index 3f032f9d22c321ff8bd4627d2459557c54c5756b..1303b5b4d448498e2d6afea298f4a5599b047e8b 100644 (file)
@@ -105,6 +105,10 @@ mono_process_list (int *size)
        if (size)
                *size = res;
        return buf;
+#elif defined(__HAIKU__)
+       /* FIXME: Add back the code from 9185fcc305e43428d0f40f3ee37c8a405d41c9ae */
+       g_assert_not_reached ();
+       return NULL;
 #else
        const char *name;
        void **buf = NULL;
index 05817a842f312a69e1c43381ec4899ad5f78c9c2..cc70df01822c4cf2863a4e6c185406067de62847 100644 (file)
@@ -4,6 +4,9 @@
 #include <config.h>
 #if defined(PLATFORM_ANDROID)
 #include <asm/sigcontext.h>
+#ifdef HAVE_UCONTEXT_H
+#include <ucontext.h>
+#endif
 #endif
 
 #ifdef HAVE_UNISTD_H
@@ -87,7 +90,7 @@
        #define UCONTEXT_REG_EIP(ctx) (((ucontext_t*)(ctx))->uc_mcontext.gregs [EIP])
 #else
 
-#if defined(TARGET_ANDROID)
+#if defined(PLATFORM_ANDROID)
 /* No ucontext.h as of NDK v6b */
 typedef int greg_t;
 #define NGREG 19
index 3a01146d5e179d7a9c9a35b4aabd1b4f8023445b..fbe798eeb0e6321667023429bfc88b4cb65bb1ce 100644 (file)
 #ifdef ENABLE_EXTENSION_MODULE
 #include "../../../mono-extensions/mono/utils/mono-signal-handler.h"
 #endif
-/*
-Not all platforms support signal handlers in the same way. Some have the same concept but
-for some weird reason pass different kind of arguments.
-
-All signal handler helpers should go here so they can be properly shared across the JIT,
-utils and sgen.
-
-TODO: Cleanup & move mini's macros to here so they can leveraged by other parts.
 
-*/
+/* Don't use this */
 #ifndef MONO_SIGNAL_HANDLER_FUNC
 #define MONO_SIGNAL_HANDLER_FUNC(access, name, arglist) access void name arglist
 #endif
 
+/*
+ * Macros to work around signal handler differences on various platforms.
+ *
+ * To declare a signal handler function:
+ * void MONO_SIG_HANDLER_SIGNATURE (handler_func)
+ * To define a signal handler function:
+ * MONO_SIG_HANDLER_FUNC(access, name)
+ * To call another signal handler function:
+ * handler_func (MONO_SIG_HANDLER_PARAMS);
+ * To obtain the signal number:
+ * int signo = MONO_SIG_HANDLER_GET_SIGNO ();
+ * To obtain the signal context:
+ * MONO_SIG_HANDLER_GET_CONTEXT ().
+ * This will define a variable name 'ctx'.
+ */
+
+#ifdef HOST_WIN32
+#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_POINTERS *_info, void *context)
+#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, EXCEPTION_POINTERS *_info, void *context))
+#define MONO_SIG_HANDLER_PARAMS _dummy, _info, context
+#define MONO_SIG_HANDLER_GET_SIGNO() (_dummy)
+#define MONO_SIG_HANDLER_GET_INFO() (_info)
+#define MONO_SIG_HANDLER_INFO_TYPE EXCEPTION_POINTERS
+/* seh_vectored_exception_handler () passes in a CONTEXT* */
+#define MONO_SIG_HANDLER_GET_CONTEXT \
+    void *ctx = context;
+#else
+/* sigaction */
+#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *_info, void *context)
+#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, siginfo_t *_info, void *context))
+#define MONO_SIG_HANDLER_PARAMS _dummy, _info, context
+#define MONO_SIG_HANDLER_GET_SIGNO() (_dummy)
+#define MONO_SIG_HANDLER_GET_INFO() (_info)
+#define MONO_SIG_HANDLER_INFO_TYPE siginfo_t
+#define MONO_SIG_HANDLER_GET_CONTEXT \
+    void *ctx = context;
+#endif
+
 #endif
index 7cbbca14b57d6f6833e4e80d883f1b9044423d0c..cdee0ab40616b07bb980388ebbaefabbd882a3ac 100644 (file)
@@ -2,6 +2,7 @@
 
 #if defined(__FreeBSD__)
 
+#include <mono/utils/mono-threads.h>
 #include <pthread.h>
 #include <pthread_np.h>
 
index d5b2239e93e1559d16da756f9b30d8319c270839..9aa70ac20b0b442511afadf97dceedaf4b1302ce 100644 (file)
@@ -144,7 +144,7 @@ register_thread (MonoThreadInfo *info, gpointer baseptr)
 
        if (threads_callbacks.thread_register) {
                if (threads_callbacks.thread_register (info, baseptr) == NULL) {
-                       g_warning ("thread registation failed\n");
+                       // g_warning ("thread registation failed\n");
                        g_free (info);
                        return NULL;
                }
@@ -605,7 +605,7 @@ mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_ke
        for (;;) {
                const char *suspend_error = "Unknown error";
                if (!(info = mono_thread_info_suspend_sync (id, interrupt_kernel, &suspend_error))) {
-                       g_warning ("failed to suspend thread %p due to %s, hopefully it is dead", (gpointer)id, suspend_error);
+                       // g_warning ("failed to suspend thread %p due to %s, hopefully it is dead", (gpointer)id, suspend_error);
                        mono_thread_info_suspend_unlock ();
                        return NULL;
                }
@@ -614,7 +614,7 @@ mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_ke
                        break;
 
                if (!mono_thread_info_core_resume (info)) {
-                       g_warning ("failed to resume thread %p, hopefully it is dead", (gpointer)id);
+                       // g_warning ("failed to resume thread %p, hopefully it is dead", (gpointer)id);
                        mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
                        mono_thread_info_suspend_unlock ();
                        return NULL;
index d3c7511cd492cb8152e86c7e8e2b2d455b4f0bab..34efcacfd5cfb07aa37079b164e13c7d33c1cbef 100644 (file)
@@ -18,6 +18,7 @@
       <Platform>x64</Platform>\r
     </ProjectConfiguration>\r
   </ItemGroup>\r
+  <Import Project="mono.props" />
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{B7098DFA-31E6-4006-8A15-1C9A4E925149}</ProjectGuid>\r
     <RootNamespace>genmdesc</RootNamespace>\r
     <ClCompile>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_DEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <Optimization>MinSpace</Optimization>\r
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
       <AdditionalIncludeDirectories>..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>NDEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <FunctionLevelLinking>true</FunctionLevelLinking>\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
   <ImportGroup Label="ExtensionTargets">\r
   </ImportGroup>\r
-</Project>
\ No newline at end of file
+</Project>
index 08bcfa0ba8c3ef849546b62c0e33cef861d4b332..db5bfab6d469d6bc881f4a50a3b9abcddac667ad 100644 (file)
@@ -75,7 +75,7 @@
     <ClCompile>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>..\libgc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
@@ -95,7 +95,7 @@
     <ClCompile>\r
       <Optimization>MinSpace</Optimization>\r
       <AdditionalIncludeDirectories>..\libgc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;__i386__;TARGET_X86;i386;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>NDEBUG;__i386__;TARGET_X86;i386;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <BufferSecurityCheck>true</BufferSecurityCheck>\r
       <PrecompiledHeader>\r
     <ClCompile>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>..\libgc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_DEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
     <ClCompile>\r
       <Optimization>MinSpace</Optimization>\r
       <AdditionalIncludeDirectories>..\libgc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>NDEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <BufferSecurityCheck>true</BufferSecurityCheck>\r
       <PrecompiledHeader>\r
index 3635bdae2d58d611d345399c4860b7c3f3a55e6b..c65a603ff9f852c35b3c0229bfa5f9671dacfb60 100644 (file)
@@ -57,6 +57,7 @@
     <ClCompile Include="..\mono\metadata\gc.c" />\r
     <ClCompile Include="..\mono\metadata\icall.c" />\r
     <ClCompile Include="..\mono\metadata\image.c" />\r
+    <ClCompile Include="..\mono\metadata\jit-info.c" />\r
     <ClCompile Include="..\mono\metadata\loader.c" />\r
     <ClCompile Include="..\mono\metadata\locales.c" />\r
     <ClCompile Include="..\mono\metadata\lock-tracer.c" />\r
@@ -98,9 +99,6 @@
     <ClCompile Include="..\mono\metadata\sgen-hash-table.c" />\r
     <ClCompile Include="..\mono\metadata\sgen-internal.c" />\r
     <ClCompile Include="..\mono\metadata\sgen-los.c" />\r
-    <ClCompile Include="..\mono\metadata\sgen-marksweep-fixed-par.c" />\r
-    <ClCompile Include="..\mono\metadata\sgen-marksweep-fixed.c" />\r
-    <ClCompile Include="..\mono\metadata\sgen-marksweep-par.c" />\r
     <ClCompile Include="..\mono\metadata\sgen-marksweep.c" />\r
     <ClCompile Include="..\mono\metadata\sgen-memory-governor.c" />\r
     <ClCompile Include="..\mono\metadata\sgen-new-bridge.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 0fa69f3a15d2238ebce3a2a28c30e70b20d8d373..8e35a6e7659f69d7d45dbdbcbd9b238f3157587f 100644 (file)
@@ -18,6 +18,7 @@
       <Platform>x64</Platform>\r
     </ProjectConfiguration>\r
   </ItemGroup>\r
+  <Import Project="mono.props" />\r
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}</ProjectGuid>\r
     <RootNamespace>libtest</RootNamespace>\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
   <ImportGroup Label="ExtensionTargets">\r
   </ImportGroup>\r
-</Project>
\ No newline at end of file
+</Project>\r
index 46b4dde2c8f73227ef4cffbf11bca5ce73434455..ffec2840f23ee0878d6a57ec5fde78c3de470b9d 100644 (file)
@@ -9,11 +9,11 @@
   </PropertyGroup>
   <ItemDefinitionGroup>
     <ClCompile>
-      <PreprocessorDefinitions>__default_codegen__;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;GC_NOT_DLL;WIN32_THREADS;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;_UNICODE;UNICODE;WIN32_THREADS;FD_SETSIZE=1024;$(PreprocessorDefinitions);_WINSOCKAPI_</PreprocessorDefinitions>
+      <PreprocessorDefinitions>__default_codegen__;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;GC_NOT_DLL;WIN32_THREADS;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;_UNICODE;UNICODE;WIN32_THREADS;FD_SETSIZE=1024;$(PreprocessorDefinitions);_WINSOCKAPI_</PreprocessorDefinitions>
          <DisableSpecificWarnings>4273;4005</DisableSpecificWarnings>
     </ClCompile>
     <Link>
       <AdditionalDependencies>Mswsock.lib;ws2_32.lib;ole32.lib;oleaut32.lib;psapi.lib;version.lib;advapi32.lib;winmm.lib;kernel32.lib;$(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     </ItemDefinitionGroup>
-</Project>
\ No newline at end of file
+</Project>
index 2d28de55104093b786ac750e39a15847c1c690e7..b4576542797e35c432c4d5ad24db41ec1dafa806 100644 (file)
     <ClCompile>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>..\libgc\include;..\;..\mono\;..\mono\jit;..\mono\eglib\src;..\..\mono\eglib\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>TARGET_X86;_DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;GC_NOT_DLL;HAVE_CONFIG_H;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>TARGET_X86;_DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;GC_NOT_DLL;HAVE_CONFIG_H;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
     <ClCompile>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>..\libgc\include;..\;..\mono\;..\mono\jit;..\mono\eglib\src;..\..\mono\eglib\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>TARGET_X86;_DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;GC_NOT_DLL;HAVE_CONFIG_H;WINVER=0x0500;_WIN32_WINNT=0x0500;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>TARGET_X86;_DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;GC_NOT_DLL;HAVE_CONFIG_H;WINVER=0x0502;_WIN32_WINNT=0x0502;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <PrecompiledHeader>\r
index ac0e3a9a95706952ae1719ba43a001794181e540..be62dd633ef71d23c7a1d6007d0af53db5f3dcbc 100644 (file)
@@ -165,11 +165,7 @@ EXTRA_DIST =                       \
        get-cygwin-deps.sh      \
        mono-configuration-crypto.in
 
-if USE_JIT
 mono_interp = mono
-else
-mono_interp = mint
-endif
 
 if HOST_WIN32
 if CROSS_COMPILING
index 0c690d3a35c4213b0746b82955c88b44bbb4f0e0..b6d74e1cb41832b4768000939b1050afb14e7b50 100644 (file)
 #endif
 
 #if _WIN32_WINNT < 0x0502
-/* Required for Vectored Exception Handling.
-   Interlocked* functions are also not available in XP SP1 and below
-*/
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0502
+#error "Mono requires WinXP SP2 or later"
 #endif /* _WIN32_WINNT < 0x0502 */
 
 /*
 /* #undef HAVE_GETPRIORITY */
 
 /* Define to 1 if you have the `GetProcessId' function. */
-#if (_WIN32_WINNT >= 0x0502)
 #define HAVE_GETPROCESSID 1
-#endif
 
 /* Define to 1 if you have the `getpwnam_r' function. */
 /* #undef HAVE_GETPWNAM_R */