Merge pull request #1337 from RyanMelenaNoesis/master
authorMiguel de Icaza <miguel@gnome.org>
Wed, 29 Oct 2014 19:02:30 +0000 (15:02 -0400)
committerMiguel de Icaza <miguel@gnome.org>
Wed, 29 Oct 2014 19:02:30 +0000 (15:02 -0400)
Additional JWT Security Token Support

79 files changed:
acinclude.m4
appveyor.yml [new file with mode: 0644]
configure.ac
data/Makefile.am
eglib/acinclude.m4
libgc/acinclude.m4
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/TextRenderer.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
mcs/class/System.Core/System/TimeZoneInfo.AdjustmentRule.cs
mcs/class/System.Core/System/TimeZoneInfo.Android.cs
mcs/class/System.Core/System/TimeZoneInfo.Serialization.cs
mcs/class/System.Core/System/TimeZoneInfo.TransitionTime.cs
mcs/class/System.Core/System/TimeZoneInfo.cs
mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs
mcs/class/System.Web.Abstractions/System.Web/HttpRequestBase.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.Configuration_2.0/WebConfigurationManager.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.XML/System.Xml/XmlTextReader.cs
mcs/class/System.XML/Test/System.Xml/XmlTextReaderTests.cs
mcs/class/System/System.IO.Ports/SerialPort.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/System.Net/WebClient.cs
mcs/class/System/Test/System.Net/WebClientTest.cs
mcs/class/corlib/DateTime.Now_Test.sh [new file with mode: 0755]
mcs/class/corlib/System/InvalidTimeZoneException.cs
mcs/class/corlib/System/TimeZone.cs
mcs/class/corlib/System/TimeZoneNotFoundException.cs
mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs
mono/dis/Makefile.am
mono/metadata/class.c
mono/metadata/console-unix.c
mono/metadata/sgen-cardtable.c
mono/metadata/sgen-gc.c
mono/metadata/sgen-internal.c
mono/metadata/sgen-memory-governor.c
mono/metadata/sgen-os-posix.c
mono/metadata/socket-io.c
mono/metadata/threadpool.c
mono/mini/Makefile.am.in
mono/mini/aot-compiler.c
mono/mini/branch-opts.c
mono/mini/cpu-s390x.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-codegen.c
mono/mini/mini-llvm.c
mono/mini/mini-posix.c
mono/mini/mini-s390x.c
mono/mini/mini-windows.c
mono/mini/mini.c
mono/mini/mini.h
mono/mini/ssa.c
mono/mini/support-s390x.h
mono/mini/unwind.c
mono/monograph/Makefile.am
mono/profiler/Makefile.am
mono/utils/Makefile.am
mono/utils/lock-free-alloc.c
mono/utils/lock-free-alloc.h
mono/utils/mono-mmap-internal.h [new file with mode: 0644]
mono/utils/mono-mmap.c
mono/utils/mono-signal-handler.h
scripts/Makefile.am

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 66d9a98c35954be94753c5b8ded2cc0ec650f511..664808a4977f338bc8ecc15579133af4e12eb51f 100644 (file)
@@ -1,7 +1,7 @@
 # Process this file with autoconf to produce a configure script.
 #AC_PREREQ([2.62])
 
-AC_INIT(mono, [3.10.1],
+AC_INIT(mono, [3.12.1],
         [http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono])
 
 AC_CONFIG_SRCDIR([README.md])
@@ -2505,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"
@@ -2526,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([],[
@@ -2544,7 +2542,6 @@ case "$host" in
        i*86-*-*)
                TARGET=X86;
                arch_target=x86;
-               JIT_SUPPORTED=yes
                case $host_os in
                  solaris*)
                        LIBC="libc.so"
@@ -2590,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
@@ -2622,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)])
@@ -2635,7 +2630,6 @@ case "$host" in
                        TARGET=SPARC
                fi
                arch_target=sparc;
-               JIT_SUPPORTED=yes
                ACCESS_UNALIGNED="no"
                case $host_os in
                  linux*) ;;
@@ -2668,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
@@ -2679,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
                ;;
@@ -2687,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__"
@@ -2697,7 +2688,6 @@ case "$host" in
 #              TARGET=ARM;
 #              arch_target=arm;
 #              ACCESS_UNALIGNED="no"
-#              JIT_SUPPORTED=yes
 #              sgen_supported=true
 #              AOT_SUPPORTED="no"
 #              ;;
@@ -2705,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
                ;;
@@ -2713,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"
                ;;
@@ -2729,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
@@ -2769,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__ \
@@ -2779,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
@@ -2796,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
@@ -2818,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            
@@ -2829,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])
@@ -2953,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"
 
@@ -3368,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 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 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 a9ed1ebec31cff77c3038a0458d0e0ebc8ca1ade..29921942b4eddbcd9cdbc0b9c29b4e12a60804a8 100644 (file)
@@ -369,21 +369,18 @@ namespace System.Windows.Forms
                        Image image = button.Image;
                        string text = button.Text;
                        Rectangle content_rect = button.PaddingClientRectangle;
-                       if (button.TextImageRelation != TextImageRelation.Overlay)
-                               content_rect.Inflate(-4, -4);
-                       Size text_size = TextRenderer.MeasureTextInternal (g, text, button.Font, content_rect.Size, button.TextFormatFlags, button.UseCompatibleTextRendering);
+                       Size 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)
@@ -440,16 +437,16 @@ namespace System.Windows.Forms
                                        imageRectangle = new Rectangle (image_x, image_y, image_width, image_height);
                                        break;
                                case TextImageRelation.ImageAboveText:
-                                       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:
-                                       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:
-                                       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:
-                                       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;
                        }
                }
@@ -535,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 637d0c400dffd8384193b9dd29ed72f867654d6c..37f21464dcfc9067d489e354a70b857907755364 100644 (file)
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
 using System.Runtime.CompilerServices;
 using System.Runtime.Serialization;
 
 namespace System
 {
-       public sealed partial class TimeZoneInfo {
+#if NET_4_0 || !INSIDE_CORLIB
+       public
+#endif
+       sealed partial class TimeZoneInfo {
                [SerializableAttribute]
 #if MOBILE
        [TypeForwardedFrom (Consts.AssemblySystem_Core)]
index bd35e657343646b39de3a0cda9448ba17d45297e..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 ());
                                        }
                                }
                        }
@@ -617,7 +617,7 @@ namespace System {
                                foreach (var id in GetAvailableIds ()) {
                                        Console.Write ("name={0,-40}", id);
                                        try {
-                                               TimeZoneInfo zone = _GetTimeZone (id);
+                                               TimeZoneInfo zone = _GetTimeZone (id, id);
                                                if (zone != null) {
                                                        Console.Write (" {0,-40}", zone);
                                                        if (offset.HasValue) {
index 22aa38c5fa62f95c7328adc53b07c98804f25225..3a7da39ec7fe52baad83a1d0c5543e9a3658787c 100644 (file)
@@ -24,7 +24,7 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
 
 using System.Collections.Generic;
 using System.Globalization;
@@ -33,7 +33,10 @@ using System.Text;
 
 namespace System
 {
-       public partial class TimeZoneInfo
+#if NET_4_0 || !INSIDE_CORLIB
+       public
+#endif
+       partial class TimeZoneInfo
        {
                public static TimeZoneInfo FromSerializedString (string source)
                {
index d57df150f0554bb1d318dd787d2b71225cc726f6..719bb9d51f382c4be9c8277ac17126df2ec8502c 100644 (file)
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
 
 using System.Runtime.CompilerServices;
 using System.Runtime.Serialization;
 
 namespace System
 {
-       public sealed partial class TimeZoneInfo 
+#if NET_4_0 || !INSIDE_CORLIB
+       public
+#endif
+       sealed partial class TimeZoneInfo
        {
                [SerializableAttribute]
 #if MOBILE
index aead18c764f230a9889dc542459b921994681f3a..f6fa19c0d34e182fd43b44a98bfddb524e98cb96 100644 (file)
@@ -35,7 +35,7 @@ using System.Threading;
 
 [assembly:TypeForwardedTo (typeof(TimeZoneInfo))]
 
-#elif (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#elif INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
 
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -57,7 +57,10 @@ namespace System
        [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
 #endif
        [SerializableAttribute]
-       public sealed partial class TimeZoneInfo : IEquatable<TimeZoneInfo>, ISerializable, IDeserializationCallback
+#if NET_4_0 || !INSIDE_CORLIB
+       public
+#endif
+       sealed partial class TimeZoneInfo : IEquatable<TimeZoneInfo>, ISerializable, IDeserializationCallback
        {
                TimeSpan baseUtcOffset;
                public TimeSpan BaseUtcOffset {
@@ -100,15 +103,31 @@ namespace System
                        }
                }
 
+               /*
+                       TimeZone transitions are stored when there is a change on the base offset.
+               */
+               private List<KeyValuePair<DateTime, TimeType>> transitions;
+
                static TimeZoneInfo CreateLocal ()
                {
 #if MONODROID
-                       return AndroidTimeZones.Default;
+                       return AndroidTimeZones.Local;
 #elif MONOTOUCH
                        using (Stream stream = GetMonoTouchData (null)) {
                                return BuildFromStream ("Local", stream);
                        }
 #elif LIBC
+                       var tz = Environment.GetEnvironmentVariable ("TZ");
+                       if (tz != null) {
+                               if (tz == String.Empty)
+                                       return Utc;
+                               try {
+                                       return FindSystemTimeZoneByFileName (tz, Path.Combine (TimeZoneDirectory, tz));
+                               } catch {
+                                       return Utc;
+                               }
+                       }
+
                        try {
                                return FindSystemTimeZoneByFileName ("Local", "/etc/localtime");        
                        } catch {
@@ -332,8 +351,7 @@ namespace System
                        if (dateTime.Kind == DateTimeKind.Utc)
                                return dateTime;
 
-                       //FIXME: do not rely on DateTime implementation !
-                       return DateTime.SpecifyKind (dateTime.ToUniversalTime (), DateTimeKind.Utc);
+                       return ConvertTimeToUtc (dateTime, TimeZoneInfo.Local);
                }
 
                public static DateTime ConvertTimeToUtc (DateTime dateTime, TimeZoneInfo sourceTimeZone)
@@ -350,15 +368,9 @@ namespace System
                        if (sourceTimeZone.IsInvalidTime (dateTime))
                                throw new ArgumentException ("dateTime parameter is an invalid time");
 
-                       if (dateTime.Kind == DateTimeKind.Utc && sourceTimeZone == TimeZoneInfo.Utc)
-                               return dateTime;
-
                        if (dateTime.Kind == DateTimeKind.Utc)
                                return dateTime;
 
-                       if (dateTime.Kind == DateTimeKind.Local)
-                               return ConvertTimeToUtc (dateTime);
-
                        if (sourceTimeZone.IsAmbiguousTime (dateTime) || !sourceTimeZone.IsDaylightSavingTime (dateTime))
                                return DateTime.SpecifyKind (dateTime - sourceTimeZone.BaseUtcOffset, DateTimeKind.Utc);
                        else {
@@ -415,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;
@@ -644,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);
                        }
@@ -684,13 +696,8 @@ namespace System
 
                public TimeSpan GetUtcOffset (DateTime dateTime)
                {
-                       if (IsDaylightSavingTime (dateTime)) {
-                               AdjustmentRule rule = GetApplicableRule (dateTime);
-                               if (rule != null)
-                                       return BaseUtcOffset + rule.DaylightDelta;
-                       }
-                       
-                       return BaseUtcOffset;
+                       bool isDST;
+                       return GetUtcOffset (dateTime, out isDST);
                }
 
                public TimeSpan GetUtcOffset (DateTimeOffset dateTimeOffset)
@@ -698,6 +705,82 @@ namespace System
                        throw new NotImplementedException ();
                }
 
+               private TimeSpan GetUtcOffset (DateTime dateTime, out bool isDST)
+               {
+                       isDST = false;
+
+                       TimeZoneInfo tz = this;
+                       if (dateTime.Kind == DateTimeKind.Utc)
+                               tz = TimeZoneInfo.Utc;
+
+                       if (dateTime.Kind == DateTimeKind.Local)
+                               tz = TimeZoneInfo.Local;
+
+                       bool isTzDst;
+                       var tzOffset = GetUtcOffset (dateTime, tz, out isTzDst);
+
+                       if (tz == this) {
+                               isDST = isTzDst;
+                               return tzOffset;
+                       }
+
+                       var utcTicks = dateTime.Ticks - tzOffset.Ticks;
+                       if (utcTicks < 0 || utcTicks > DateTime.MaxValue.Ticks)
+                               return BaseUtcOffset;
+
+                       var utcDateTime = new DateTime (utcTicks, DateTimeKind.Utc);
+
+                       return GetUtcOffset (utcDateTime, this, out isDST);
+               }
+
+               private static TimeSpan GetUtcOffset (DateTime dateTime, TimeZoneInfo tz, out bool isDST)
+               {
+                       if (dateTime.Kind == DateTimeKind.Local && tz != TimeZoneInfo.Local)
+                               throw new Exception ();
+
+                       isDST = false;
+
+                       if (tz == TimeZoneInfo.Utc)
+                               return TimeSpan.Zero;
+
+                       TimeSpan offset;
+                       if (tz.TryGetTransitionOffset(dateTime, out offset, out isDST))
+                               return offset;
+
+                       if (dateTime.Kind == DateTimeKind.Utc) {
+                               var utcRule = tz.GetApplicableRule (dateTime);
+                               if (utcRule != null && tz.IsInDST (utcRule, dateTime)) {
+                                       isDST = true;
+                                       return tz.BaseUtcOffset + utcRule.DaylightDelta;
+                               }
+
+                               return tz.BaseUtcOffset;
+                       }
+
+                       var stdTicks = dateTime.Ticks - tz.BaseUtcOffset.Ticks;
+                       if (stdTicks < 0 || stdTicks > DateTime.MaxValue.Ticks)
+                               return tz.BaseUtcOffset;
+
+                       var stdUtcDateTime = new DateTime (stdTicks, DateTimeKind.Utc);
+                       var tzRule = tz.GetApplicableRule (stdUtcDateTime);
+
+                       DateTime dstUtcDateTime = DateTime.MinValue;
+                       if (tzRule != null) {
+                               var dstTicks = stdUtcDateTime.Ticks - tzRule.DaylightDelta.Ticks;
+                               if (dstTicks < 0 || dstTicks > DateTime.MaxValue.Ticks)
+                                       return tz.BaseUtcOffset;
+
+                               dstUtcDateTime = new DateTime (dstTicks, DateTimeKind.Utc);
+                       }
+
+                       if (tzRule != null && tz.IsInDST (tzRule, stdUtcDateTime) && tz.IsInDST (tzRule, dstUtcDateTime)) {
+                               isDST = true;
+                               return tz.BaseUtcOffset + tzRule.DaylightDelta;
+                       }
+
+                       return tz.BaseUtcOffset;
+               }
+
                public bool HasSameRules (TimeZoneInfo other)
                {
                        if (other == null)
@@ -752,6 +835,16 @@ namespace System
                        throw new NotImplementedException ();
                }
 
+               private bool IsInDST (AdjustmentRule rule, DateTime dateTime)
+               {
+                       // Check whether we're in the dateTime year's DST period
+                       if (IsInDSTForYear (rule, dateTime, dateTime.Year))
+                               return true;
+
+                       // We might be in the dateTime previous year's DST period
+                       return IsInDSTForYear (rule, dateTime, dateTime.Year - 1);
+               }
+
                bool IsInDSTForYear (AdjustmentRule rule, DateTime dateTime, int year)
                {
                        DateTime DST_start = TransitionPoint (rule.DaylightTransitionStart, year);
@@ -774,25 +867,11 @@ namespace System
                        
                        if (!SupportsDaylightSavingTime)
                                return false;
-                       
-                       //FIXME: do not rely on DateTime implementation !
-                       if ((dateTime.Kind == DateTimeKind.Local || dateTime.Kind == DateTimeKind.Unspecified) && this == TimeZoneInfo.Local)
-                               return dateTime.IsDaylightSavingTime ();
-                       
-                       //FIXME: do not rely on DateTime implementation !
-                       if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Utc)
-                               return IsDaylightSavingTime (DateTime.SpecifyKind (dateTime.ToUniversalTime (), DateTimeKind.Utc));
-                       
-                       AdjustmentRule rule = GetApplicableRule (dateTime.Date);
-                       if (rule == null)
-                               return false;
 
-                       // Check whether we're in the dateTime year's DST period
-                       if (IsInDSTForYear (rule, dateTime, dateTime.Year))
-                               return true;
+                       bool isDst;
+                       GetUtcOffset (dateTime, out isDst);
 
-                       // We might be in the dateTime previous year's DST period
-                       return IsInDSTForYear (rule, dateTime, dateTime.Year - 1);
+                       return isDst;
                }
 
                public bool IsDaylightSavingTime (DateTimeOffset dateTimeOffset)
@@ -969,6 +1048,40 @@ namespace System
                        return null;
                }
 
+               private bool TryGetTransitionOffset (DateTime dateTime, out TimeSpan offset,out bool isDst)
+               {
+                       offset = BaseUtcOffset;
+                       isDst = false;
+
+                       if (transitions == null)
+                               return false;
+
+                       //Transitions are always in standard time
+                       DateTime date = dateTime;
+
+                       if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Local)
+                               date = date.ToUniversalTime () + BaseUtcOffset;
+
+                       if (dateTime.Kind == DateTimeKind.Utc && this != TimeZoneInfo.Utc)
+                               date = date + BaseUtcOffset;
+
+                       for (var i =  transitions.Count - 1; i >= 0; i--) {
+                               var pair = transitions [i];
+                               DateTime ttime = pair.Key;
+                               TimeType ttype = pair.Value;
+
+                               if (ttime > date)
+                                       continue;
+
+                               offset =  new TimeSpan (0, 0, ttype.Offset);
+                               isDst = ttype.IsDst;
+
+                               return true;
+                       }
+
+                       return false;
+               }
+
                private static DateTime TransitionPoint (TransitionTime transition, int year)
                {
                        if (transition.IsFixedDateRule)
@@ -1059,6 +1172,7 @@ namespace System
                        bool dst_observed = false;
                        DateTime dst_start = DateTime.MinValue;
                        List<AdjustmentRule> adjustmentRules = new List<AdjustmentRule> ();
+                       bool storeTransition = false;
 
                        for (int i = 0; i < transitions.Count; i++) {
                                var pair = transitions [i];
@@ -1069,6 +1183,8 @@ namespace System
                                                standardDisplayName = ttype.Name;
                                                daylightDisplayName = null;
                                                baseUtcOffset = new TimeSpan (0, 0, ttype.Offset);
+                                               if (adjustmentRules.Count > 0) // We ignore AdjustmentRules but store transitions.
+                                                       storeTransition = true;
                                                adjustmentRules = new List<AdjustmentRule> ();
                                                dst_observed = false;
                                        }
@@ -1110,16 +1226,22 @@ namespace System
                                }
                        }
 
-                       if (adjustmentRules.Count == 0) {
+                       TimeZoneInfo tz;
+                       if (adjustmentRules.Count == 0 && !storeTransition) {
                                TimeType t = (TimeType)time_types [0];
                                if (standardDisplayName == null) {
                                        standardDisplayName = t.Name;
                                        baseUtcOffset = new TimeSpan (0, 0, t.Offset);
                                }
-                               return CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName);
+                               tz = CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName);
                        } else {
-                               return CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName, daylightDisplayName, ValidateRules (adjustmentRules).ToArray ());
+                               tz = CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName, daylightDisplayName, ValidateRules (adjustmentRules).ToArray ());
                        }
+
+                       if (storeTransition)
+                               tz.transitions = transitions;
+
+                       return tz;
                }
 
                static Dictionary<int, string> ParseAbbreviations (byte [] buffer, int index, int count)
index f6ea66e98c69321b32c060c184913b9fb3a832fe..c3972e747c17df0e79a2f83a92bac99c8667f98a 100644 (file)
@@ -232,7 +232,7 @@ namespace MonoTests.System
                                DateTime afterDST = new DateTime (2007, 10, 28, 2, 0, 0, DateTimeKind.Unspecified);
                                Assert.IsFalse (london.IsDaylightSavingTime (beforeDST), "Just before DST");
                                Assert.IsTrue (london.IsDaylightSavingTime (startDST), "the first seconds of DST");
-                               Assert.IsTrue (london.IsDaylightSavingTime (endDST), "The last seconds of DST");
+                               Assert.IsFalse (london.IsDaylightSavingTime (endDST), "The last seconds of DST");
                                Assert.IsFalse (london.IsDaylightSavingTime (afterDST), "Just after DST");
                        }
                
@@ -804,6 +804,143 @@ namespace MonoTests.System
                                Assert.IsTrue (london.Equals (deserialized));
                        }
                }
+
+               [TestFixture]
+               public class MultipleDaylightSavingTimeTests {
+                       private TimeZoneInfo cairo;
+                       private DateTime dst1Start;
+                       private DateTime dst1End;
+                       private DateTime dst2Start;
+                       private DateTime dst2End;
+
+                       private TimeSpan baseUtcOffset;
+                       private TimeSpan dstUtcOffset;
+                       private TimeSpan dstOffset;
+
+                       [SetUp]
+                       public void CreateTimeZones ()
+                       {
+                               /*
+                               From 1/1/2014 12:00:00 AM to 6/30/2014 12:00:00 AM
+                                       Delta: 01:00:00
+                                       Begins at 12:00 AM on 16 May
+                                       Ends at 1:00 AM on 29 June
+                               From 7/1/2014 12:00:00 AM to 12/31/2014 12:00:00 AM
+                                       Delta: 01:00:00
+                                       Begins at 12:00 AM on 29 July
+                                       Ends at 12:00 AM on 26 September
+                               */
+                               dst1Start = new DateTime (2014, 5, 16);
+                               dst1End = new DateTime (2014, 6, 29);
+                               dst2Start = new DateTime (2014, 7, 29);
+                               dst2End = new DateTime (2014, 9, 26);
+
+                               baseUtcOffset = new TimeSpan (2, 0, 0);
+                               dstUtcOffset = new TimeSpan (3, 0, 0);
+                               dstOffset = dstUtcOffset - baseUtcOffset;
+
+                               var rule1 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (
+                                       new DateTime (2014, 1, 1), new DateTime (2014, 6, 30), dstOffset,
+                                       CreateFixedDateRule (dst1Start), CreateFixedDateRule (dst1End));
+
+                               var rule2 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (
+                                       new DateTime (2014, 7, 1), new DateTime (2014, 12, 31), dstOffset,
+                                       CreateFixedDateRule (dst2Start), CreateFixedDateRule (dst2End));
+
+                               cairo = TimeZoneInfo.CreateCustomTimeZone ("Africa/Cairo", baseUtcOffset, "Africa/Cairo", "EET", "EEST",
+                                       new [] {rule1, rule2});
+                       }
+
+                       private static TimeZoneInfo.TransitionTime CreateFixedDateRule (DateTime dateTime)
+                       {
+                               var time = new DateTime (dateTime.Ticks - dateTime.Date.Ticks);
+                               return TimeZoneInfo.TransitionTime.CreateFixedDateRule (time, dateTime.Month, dateTime.Day);
+                       }
+
+                       [Test]
+                       public void GetUtcOffset_FromUTC ()
+                       {
+                               var d = dst1Start.Add (-baseUtcOffset);
+                               d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+                               d = dst1End.Add (-baseUtcOffset-dstOffset);
+                               d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+                               d = dst2Start.Add (-baseUtcOffset);
+                               d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+                               d = dst2End.Add (-baseUtcOffset-dstOffset);
+                               d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+                       }
+
+                       [Test]
+                       public void GetUtcOffset_FromLocal ()
+                       {
+                               var d = dst1Start.Add (-baseUtcOffset);
+                               d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+                               d = d.ToLocalTime ();
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+                               d = dst1End.Add (-baseUtcOffset-dstOffset);
+                               d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+                               d = d.ToLocalTime ();
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+                               d = dst2Start.Add (-baseUtcOffset);
+                               d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+                               d = d.ToLocalTime ();
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+                               d = dst2End.Add (-baseUtcOffset-dstOffset);
+                               d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+                               d = d.ToLocalTime ();
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+                       }
+
+                       [Test]
+                       public void GetUtcOffset_FromUnspecified ()
+                       {
+                               var d = dst1Start.Add (dstOffset);
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+                               d = dst1End.Add (-dstOffset);
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+                               d = dst2Start.Add (dstOffset);
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+                               d = dst2End.Add (-dstOffset);
+                               Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+                               Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+                       }
+               }
        }
 }
 #endif
index e80cbe6ad6204400720ce8c6d1f6ad26982dcdd6..3a31754b9499cd72e224c49210e2c2bba832b5ee 100644 (file)
@@ -138,8 +138,6 @@ namespace System.Web
 
 #if NET_4_5
                public virtual ReadEntityBodyMode ReadEntityBodyMode { get { NotImplemented(); return ReadEntityBodyMode.Classic; } }
-
-               public virtual UnvalidatedRequestValuesBase Unvalidated { get { NotImplemented (); return null; } }
 #endif
                public virtual Uri Url { get { NotImplemented (); return null; } }
 
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 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 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 7dc686ba352503d26971f59ec116cd78b7971f91..eee0580d44d22cef8487e6cbbcdd08f27ebb081b 100644 (file)
@@ -716,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;
                                        }
@@ -1800,6 +1799,7 @@ namespace Mono.Xml2
                                value,
                                false);
                        ati.Value = value;
+                       ati.ValueTokenStartIndex = ati.ValueTokenEndIndex = currentAttributeValue;
                        attributeCount++;
                }
 
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 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 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 ded7767114a62349033d4746f6f240ec534895cc..38415f05c5f7ca3043da0b464e3e8ac754960e29 100644 (file)
@@ -1972,20 +1972,17 @@ namespace System.Net
                        if (fileName == null)
                                throw new ArgumentNullException ("fileName");
 
-                       WebRequest request = null;
                        try {
                                SetBusy ();
                                cts = new CancellationTokenSource ();
-                               request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
-                               var result = await UploadFileTaskAsyncCore (request, method, fileName, cts.Token).ConfigureAwait (false);
+
+                               var result = await UploadFileTaskAsyncCore (address, method, fileName, cts.Token).ConfigureAwait (false);
                                OnUploadFileCompleted (new UploadFileCompletedEventArgs (result, null, false, null));
                                return result;
                        } catch (WebException ex) {
                                OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, ex, false, null));
                                throw;
                        } catch (OperationCanceledException) {
-                               if (request != null)
-                                       request.Abort ();
                                OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, null, true, null));
                                throw;
                        } catch (Exception ex) {
@@ -1994,8 +1991,7 @@ namespace System.Net
                        }
                }
 
-               async Task<byte[]> UploadFileTaskAsyncCore (WebRequest request, string method,
-                                                           string fileName, CancellationToken token)
+               async Task<byte[]> UploadFileTaskAsyncCore (Uri address, string method, string fileName, CancellationToken token)
                {
                        token.ThrowIfCancellationRequested ();
 
@@ -2018,9 +2014,15 @@ namespace System.Net
                        Stream reqStream = null;
                        Stream fStream = null;
                        WebResponse response = null;
+                       WebRequest request = null;
 
                        fileName = Path.GetFullPath (fileName);
 
+                       try {
+                               request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
+                       } catch (OperationCanceledException) {
+                       }
+
                        try {
                                fStream = File.OpenRead (fileName);
                                token.ThrowIfCancellationRequested ();
@@ -2042,7 +2044,9 @@ namespace System.Net
                                                        Path.GetFileName (fileName), fileCType);
                                                byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
                                                ms.Write (partHeadersBytes, 0, partHeadersBytes.Length);
-                                               await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false);
+                                               var msLength = (int)ms.Position;
+                                               ms.Seek (0, SeekOrigin.Begin);
+                                               await ms.CopyToAsync (reqStream, msLength, token).ConfigureAwait (false);
                                        }
                                }
                                int nread;
@@ -2084,7 +2088,9 @@ namespace System.Net
                                                ms.WriteByte ((byte) '-');
                                                ms.WriteByte ((byte) '\r');
                                                ms.WriteByte ((byte) '\n');
-                                               await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false);
+                                               var msLength = (int)ms.Position;
+                                               ms.Seek (0, SeekOrigin.Begin);
+                                               await ms.CopyToAsync (reqStream, msLength, token).ConfigureAwait (false);
                                        }
                                }
                                reqStream.Close ();
index 48722d45510fd03642ce0aad7ff725e25529587c..ef3f681742513571b358bbfd9b9b126b4276eecd 100644 (file)
@@ -2221,6 +2221,28 @@ namespace MonoTests.System.Net
                                webClient.UploadFileAsync (uri, "PUT", tempFile);
                        });
                }
+
+               [Test]
+               public void UploadFileAsyncContentType ()
+               {
+                       var serverUri = "http://localhost:13370/";
+                       var filename = Path.GetTempFileName ();
+
+                       HttpListener listener = new HttpListener ();
+                       listener.Prefixes.Add (serverUri);
+                       listener.Start ();
+
+                       using (var client = new WebClient ())
+                       {
+                               client.UploadFileTaskAsync (new Uri (serverUri), filename);
+                               var request = listener.GetContext ().Request;
+
+                               var expected = "multipart/form-data; boundary=------------";
+                               Assert.AreEqual (expected.Length + 15, request.ContentType.Length);
+                               Assert.AreEqual (expected, request.ContentType.Substring (0, expected.Length));
+                       }
+                       listener.Close ();
+               }
 #endif
 
 #if NET_4_0
diff --git a/mcs/class/corlib/DateTime.Now_Test.sh b/mcs/class/corlib/DateTime.Now_Test.sh
new file mode 100755 (executable)
index 0000000..27b9c20
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+export MONO_PATH=${MONO_PATH:-$SCRIPT_PATH/../lib/net_4_5/}
+
+TZ_FAILS=0
+TZ_COUNT=0
+FORMAT="%a %b %d %T %Y"
+
+for tz in $(cd /usr/share/zoneinfo/; find * -type f -print); do
+       TZ_COUNT=$(expr $TZ_COUNT + 1)
+       SYS_DATETIME=$(date -ju -f "$FORMAT" "$(TZ=$tz date "+$FORMAT")" "+%s")
+       CS_DATETIME=$(TZ=$tz csharp -e '(int)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;')
+       DIFF=$(expr $SYS_DATETIME - $CS_DATETIME)
+       if [ "$DIFF" -gt "5" ] || [ "$DIFF" -lt "-5" ]; then
+               TZ_FAILS=$(expr $TZ_FAILS + 1)
+               echo ""
+               echo "DateTime.Now failed with timezone: $tz"
+               echo "    System:       $(date -ju -f "%s" "$SYS_DATETIME" "+%Y-%m-%d %T")"
+               echo "    DateTime.Now: $(date -ju -f "%s" "$CS_DATETIME" "+%Y-%m-%d %T")"
+       fi
+       echo ".\c"
+done
+echo ""
+echo "DateTime.Now failed with $TZ_FAILS of $TZ_COUNT timezones."
index 7096e56cd33f94d6d47e167ec960162873defe24..7beb2d4982c93f211fe8de1d6fc1f6d0abd26d5c 100644 (file)
@@ -24,8 +24,6 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#if NET_4_0
-
 using System.Runtime.CompilerServices;
 
 namespace System
@@ -36,7 +34,10 @@ namespace System
 #elif NET_4_0
        [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
 #endif
-       public class InvalidTimeZoneException : Exception
+#if NET_4_0
+       public
+#endif
+       class InvalidTimeZoneException : Exception
        {
                public InvalidTimeZoneException () : base ()
                {}
@@ -51,5 +52,3 @@ namespace System
                {}
        }
 }
-
-#endif
index cea224133e4ab73ff1dbd3560b1f764d942c57aa..f4e01b03be322cc4f832f672002573eb025517f7 100644 (file)
@@ -144,22 +144,7 @@ namespace System
                                        return DateTime.SpecifyKind (DateTime.MinValue, DateTimeKind.Local);
                        }
 
-                       DateTime local = DateTime.SpecifyKind (time.Add (utcOffset), DateTimeKind.Local);
-                       DaylightTime dlt = GetDaylightChanges (time.Year);
-                       if (dlt.Delta.Ticks == 0)
-                               return DateTime.SpecifyKind (local, DateTimeKind.Local);
-
-                       // FIXME: check all of the combination of
-                       //      - basis: local-based or UTC-based
-                       //      - hemisphere: Northern or Southern
-                       //      - offset: positive or negative
-
-                       // PST should work fine here.
-                       if (local < dlt.End && dlt.End.Subtract (dlt.Delta) <= local)
-                               return DateTime.SpecifyKind (local, DateTimeKind.Local);
-
-                       TimeSpan localOffset = GetUtcOffset (local);
-                       return DateTime.SpecifyKind (time.Add (localOffset), DateTimeKind.Local);
+                       return DateTime.SpecifyKind (time.Add (utcOffset), DateTimeKind.Local);
                }
 
                public virtual DateTime ToUniversalTime (DateTime time)
@@ -252,17 +237,6 @@ namespace System
                // A yearwise cache of DaylightTime.
                private Dictionary<int, DaylightTime> m_CachedDaylightChanges = new Dictionary<int, DaylightTime> (1);
 
-               // the offset when daylightsaving is not on (in ticks)
-               private long m_ticksOffset;
-
-               // the offset when daylightsaving is not on.
-               [NonSerialized]
-               private TimeSpan utcOffsetWithOutDLS;
-  
-               // the offset when daylightsaving is on.
-               [NonSerialized]
-               private TimeSpan utcOffsetWithDLS;
-
                internal enum TimeZoneData
                {
                        DaylightSavingStartIdx,
@@ -315,8 +289,6 @@ namespace System
                        m_standardName = Locale.GetText (names[(int)TimeZoneNames.StandardNameIdx]);
                        m_daylightName = Locale.GetText (names[(int)TimeZoneNames.DaylightNameIdx]);
 
-                       m_ticksOffset = data[(int)TimeZoneData.UtcOffsetIdx];
-
                        DaylightTime dlt = GetDaylightTimeFromData (data);
                        m_CachedDaylightChanges.Add (now.Year, dlt);
                        OnDeserialization (dlt);
@@ -366,20 +338,7 @@ namespace System
                        if (time.Kind == DateTimeKind.Utc)
                                return TimeSpan.Zero;
 
-                       if (IsDaylightSavingTime (time) && !IsAmbiguousTime (time))
-                               return utcOffsetWithDLS;
-
-                       return utcOffsetWithOutDLS;
-               }
-
-               private bool IsAmbiguousTime (DateTime time)
-               {
-                       if (time.Kind == DateTimeKind.Utc)
-                               return false;
-
-                       DaylightTime changes = GetDaylightChanges (time.Year);
-
-                       return time < changes.End && time >= changes.End - changes.Delta;
+                       return TimeZoneInfo.Local.GetUtcOffset (time);
                }
 
                void IDeserializationCallback.OnDeserialization (object sender)
@@ -400,8 +359,6 @@ namespace System
                        } else
                                this_year = dlt.Start.Year;
                        
-                       utcOffsetWithOutDLS = new TimeSpan (m_ticksOffset);
-                       utcOffsetWithDLS = new TimeSpan (m_ticksOffset + dlt.Delta.Ticks);
                        this_year_dlt = dlt;
                }
 
index 79b094ddde0ad00192c63c5c9253dbfedb54cdec..643b82104b385eddeefe74e3532e6a9ff55b521c 100644 (file)
@@ -24,7 +24,6 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#if NET_4_0
 
 using System.Runtime.CompilerServices;
 
@@ -36,7 +35,10 @@ namespace System
 #elif NET_4_0
        [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
 #endif
-       public class TimeZoneNotFoundException : Exception
+#if NET_4_0
+       public
+#endif
+       class TimeZoneNotFoundException : Exception
        {
                public TimeZoneNotFoundException () : base ()
                {}
@@ -51,5 +53,3 @@ namespace System
                {}
        }
 }
-
-#endif
index 4e358cadd94cf3d2a7babad89de8bd23777a6e6a..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++) {
@@ -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);
                }
 
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 54d2d5c85a80c7a8ad7f75464302a5a0cfc6e1d9..e9ff58249ef34610b39221c1f0cb51752a500f00 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,43 @@ 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;
+
+                               // FIXME: Too much code does this
+#if 0
+                               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);
+                               }
+#endif
+                       }
+                       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 +2031,7 @@ mono_class_layout_fields (MonoClass *class)
                }
                break;
        }
+       }
 
        if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
                /*
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 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 1364cc0a9e0398d13a60a92f5656228540e54acb..4b0b5a320121f3c064437be958d7da70e149d8fc 100644 (file)
@@ -347,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);
 
@@ -1928,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);
@@ -3144,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;
@@ -3166,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;
@@ -3245,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);
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 9918d16adc58182836069bc29449f642c598c4e1..55acf5137c38a9b740e1f4f2eb025ea779a10c36 100644 (file)
@@ -135,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
@@ -144,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 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 02acb073a8538c5011955c07b5264180bfcfb683..36514cc6ea8a06c0f26c553ecb68e59de2d846a7 100644 (file)
@@ -158,6 +158,8 @@ 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;
@@ -783,12 +785,21 @@ typedef struct {
        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
@@ -824,22 +835,43 @@ monitor_heuristic (gint16 *current, gint16 *history_size, SamplesHistory *histor
                history [cur].nthreads_diff = 1;
                decision = 2;
        } else {
-               max = cur == 0 ? 1 : 0;
-               for (i = 0; i < *history_size; i++) {
-                       if (i == cur)
-                               continue;
-                       if (history [i].nexecuted > history [max].nexecuted)
-                               max = i;
+               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 (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;
+               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 {
-                       /* we made it worse, let's return to previous situation */
-                       history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? -1 : 1;
-                       decision = 4;
+                       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;
+                       }
                }
        }
 
@@ -889,6 +921,10 @@ 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;
@@ -918,9 +954,9 @@ monitor_thread (gpointer unused)
                        } else {
                                gint8 nthreads_diff = monitor_heuristic (&current, &history_size, history, tp);
 
-                               if (nthreads_diff > 0)
+                               if (nthreads_diff == 1)
                                        threadpool_start_thread (tp);
-                               else if (nthreads_diff < 0)
+                               else if (nthreads_diff == -1)
                                        threadpool_kill_thread (tp);
                        }
                }
@@ -969,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));
 
@@ -1120,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);
@@ -1139,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) {
@@ -1146,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;
                }
        }
@@ -1665,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 104294b401a740f5244e6f0c7240f5b6a771a438..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
 
@@ -196,7 +192,7 @@ 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
@@ -348,6 +344,7 @@ sparc_sources = \
 s390x_sources = \
        mini-s390x.c            \
        mini-s390x.h            \
+       support-s390x.h         \
        exceptions-s390x.c      \
        tramp-s390x.c
 
@@ -730,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 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 b3dce352ec640faff6fbb71abd21c2aeaab6042c..2eee2e4e57de2513cea47bc74092da93ed3c6aa0 100644 (file)
@@ -283,6 +283,7 @@ long_xor: dest:i src1:i src2:i len:8
 long_neg: dest:i src1:i len:6
 long_not: dest:i src1:i len:12
 long_rem: dest:i src1:i src2:i len:12
+long_rem_imm: dest:i src1:i src2:i len:12
 long_rem_un: dest:i src1:i src2:i len:16
 long_shl: dest:i src1:i src2:i len:14
 long_shl_imm: dest:i src1:i len:14
index 84db9c7eab4fe85d2ab250a5124abb53e2bed538..f29e913acf91e5849479f9e12d74514ffa68c1df 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;
                }
@@ -486,6 +486,9 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
                        ins->opcode = OP_ICONST;
                        MONO_INST_NULLIFY_SREGS (ins);
                        ins->inst_c0 = 0;
+#if __s390__
+               }
+#else
                } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1)) {
                        gboolean is_long = ins->opcode == OP_LREM_IMM;
                        int compensator_reg = alloc_ireg (cfg);
@@ -497,12 +500,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);
@@ -511,6 +514,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
 
                        NULLIFY_INS (ins);
                }
+#endif
                break;
        }
 
@@ -980,7 +984,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 +1002,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 +1016,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 +1038,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 +1070,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 +1089,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 +1103,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 +1125,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:
index 258bae6cbabbf13d777845ed9d043a9bfaecedd6..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, ",
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 6f757ff8e97afbcdf3a99c807b4f062746c25a0c..7a8c4d3f9f88efd5c5a5d0920cbc9d0b0408f267 100755 (executable)
@@ -190,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)
 {
@@ -9318,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]);
                                }
                        }
 
@@ -9379,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));
@@ -11787,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;
index 9317394473a1c4e9ba2c5300a4c78c6e702c2102..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;
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 6551f78e021a1ed172043611b8f6a4dd9c11861b..28e76665e16b5a197410e2f8833ed6419092e315 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;
@@ -417,6 +420,7 @@ type_is_unsigned (EmitContext *ctx, MonoType *t)
        switch (t->type) {
        case MONO_TYPE_U1:
        case MONO_TYPE_U2:
+       case MONO_TYPE_CHAR:
        case MONO_TYPE_U4:
        case MONO_TYPE_U8:
                return TRUE;
@@ -434,7 +438,12 @@ static LLVMTypeRef
 type_to_llvm_arg_type (EmitContext *ctx, MonoType *t)
 {
        LLVMTypeRef ptype = type_to_llvm_type (ctx, t);
-       
+
+       /*
+        * This works on all abis except arm64/ios which passes multiple
+        * arguments in one stack slot.
+        */
+#ifndef TARGET_ARM64
        if (ptype == LLVMInt8Type () || ptype == LLVMInt16Type ()) {
                /* 
                 * LLVM generates code which only sets the lower bits, while JITted
@@ -442,6 +451,7 @@ type_to_llvm_arg_type (EmitContext *ctx, MonoType *t)
                 */
                ptype = LLVMInt32Type ();
        }
+#endif
 
        return ptype;
 }
@@ -1272,6 +1282,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 +1301,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;
 }
 
@@ -1805,7 +1824,7 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
                                ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
                        }
                } else {
-                       ctx->values [reg] = convert (ctx, ctx->values [reg], llvm_type_to_stack_type (type_to_llvm_type (ctx, sig->params [i])));
+                       ctx->values [reg] = convert_full (ctx, ctx->values [reg], llvm_type_to_stack_type (type_to_llvm_type (ctx, sig->params [i])), type_is_unsigned (ctx, sig->params [i]));
                }
        }
 
@@ -4675,6 +4694,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 +5353,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 +5365,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 +5385,27 @@ 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);
+                               /* The types might not match because the caller might pass an rgctx */
+                               if (lmethod && LLVMTypeOf (callee) == LLVMTypeOf (lmethod)) {
+                                       mono_llvm_replace_uses_of (callee, lmethod);
+                                       mono_aot_mark_unused_llvm_plt_entry (ji);
+                               }
+                       }
+               }
+       }
+
 #if 0
        {
                char *verifier_err;
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 435ef2904a495ce910dd6a9aa36e55ea1d9db6f7..d84c87860d1f95b652405201c0823ed719a62097 100644 (file)
@@ -624,7 +624,7 @@ indent (int diff) {
        if (diff < 0)
                indent_level += diff;
        v = indent_level;
-       printf("%p [%3d] ",pthread_self(),v);
+       printf("%p [%3d] ",(void *)pthread_self(),v);
        while (v-- > 0) {
                printf (". ");
        }
@@ -2798,6 +2798,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_IREM_UN_IMM:
                case OP_LAND_IMM:
                case OP_LOR_IMM:
+               case OP_LREM_IMM:
                case OP_LXOR_IMM:
                case OP_LOCALLOC_IMM:
                        mono_decompose_op_imm (cfg, bb, ins);
@@ -3312,6 +3313,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        s390_lgr  (code, ins->dreg, s390_r0);
                        break;
                }
+               case OP_LREM_IMM: {
+                       if (s390_is_imm16 (ins->inst_imm)) {
+                               s390_lghi (code, s390_r13, ins->inst_imm);
+                       } else {
+                               s390_lgfi (code, s390_r13, ins->inst_imm);
+                       }
+                       s390_lgr  (code, s390_r0, ins->sreg1);
+                       s390_dsgr (code, s390_r0, s390_r13);
+                       s390_lgfr (code, ins->dreg, s390_r0);
+               }
+                       break;
                case OP_LREM_UN: {
                        s390_lgr   (code, s390_r1, ins->sreg1);
                        s390_lghi  (code, s390_r0, 0);
@@ -5735,9 +5747,35 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 /*------------------------------------------------------------------*/
 
 gpointer
-mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
+mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, 
+                                           int offset, gboolean load_imt_reg)
 {
-       return NULL;
+       guint8 *code, *start;
+       int size = 20;
+
+       start = code = mono_global_codeman_reserve (size);
+
+       /*
+        * Replace the "this" argument with the target
+        */
+       s390_lgr  (code, s390_r1, s390_r2);
+       s390_lg   (code, s390_r2, s390_r1, 0, MONO_STRUCT_OFFSET(MonoDelegate, target));        
+       
+       /*
+        * Load the IMT register, if needed
+        */
+       if (load_imt_reg) {
+               s390_lg  (code, MONO_ARCH_IMT_REG, s390_r2, 0, MONO_STRUCT_OFFSET(MonoDelegate, method));
+       }
+
+       /*
+        * Load the vTable
+        */
+       s390_lg  (code, s390_r1, s390_r2, 0, MONO_STRUCT_OFFSET(MonoObject, vtable));
+       s390_agfi(code, s390_r1, offset);
+       s390_br  (code, s390_r1);
+
+       return(start);
 }
 
 /*========================= End of Function ========================*/
@@ -5833,7 +5871,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
                                                s390_lg   (code, s390_r1, 0, s390_r1, 0);
                                        }
                                        s390_br   (code, s390_r1);
-                                       target = S390_RELATIVE(code, item->jmp_code);
+                                       target = (gint64) S390_RELATIVE(code, item->jmp_code);
                                        s390_patch_rel(item->jmp_code+2, target);
                                        S390_SET  (code, s390_r1, fail_tramp);
                                        s390_br   (code, s390_r1);
@@ -5863,7 +5901,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
                if (item->jmp_code) {
                        if (item->check_target_idx) {
                                gint64 offset;
-                               offset = S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
+                               offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
                                                       item->jmp_code);
                                s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
                        }
@@ -5932,7 +5970,7 @@ mono_arch_get_cie_program (void)
 {
        GSList *l = NULL;
 
-       mono_add_unwind_op_def_cfa (l, NULL, NULL, STK_BASE, 0);
+       mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
 
        return(l);
 }
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 1ab0ac22f2047393c5087998fd3cb0ae948fc6e6..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));
@@ -4920,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)
@@ -5070,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
@@ -5148,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;
@@ -5160,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;
                }
        }
@@ -6724,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));
 
@@ -6749,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;
                }
        }
@@ -6762,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");
        
@@ -6776,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)) {
@@ -6804,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;
                }
        }
@@ -6841,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);
@@ -6849,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;
                }
        }
@@ -6864,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).");
        
index cd38442570cf84b53cd81d559bebf33afeec7dd9..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)
@@ -958,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,
@@ -2035,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;
@@ -2179,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;
@@ -2826,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 62edcc4e7e9279bb91bdb4079c45b25be997a27f..f93dc88c0c6922e3b097ffd2c0f488df657801d9 100644 (file)
@@ -4,8 +4,12 @@
 #define S390_SET(loc, dr, v)                                   \
        do {                                                    \
                guint64 val = (guint64) v;                      \
-               if (s390_is_uimm16(val)) {                      \
+               if (s390_is_imm16(val)) {                       \
+                       s390_lghi(loc, dr, val);                \
+               } else if (s390_is_uimm16(val)) {               \
                        s390_llill(loc, dr, val);               \
+               } else if (s390_is_imm32(val)) {                \
+                       s390_lgfi(loc, dr, val);                \
                } else if (s390_is_uimm32(val)) {               \
                        s390_llilf(loc, dr, val);               \
                } else {                                        \
index 517c7fbc827254c0428a129debcb42d99fa3c318..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;
 }
 
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 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;
 
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 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 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