Merge pull request #1952 from esdrubal/proc_name
authorMarcos Henrich <marcoshenrich@gmail.com>
Tue, 11 Aug 2015 12:10:27 +0000 (13:10 +0100)
committerMarcos Henrich <marcoshenrich@gmail.com>
Tue, 11 Aug 2015 12:10:27 +0000 (13:10 +0100)
Fixes process names trimmed to 15 chars.

146 files changed:
configure.ac
eglib/configure.ac
eglib/src/gspawn.c
ikvm-native/Makefile.am
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildItem.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Expression.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ExpressionCollection.cs
mcs/class/Microsoft.Build.Tasks/Test/Microsoft.Build.Tasks/MessageTest.cs
mcs/class/Microsoft.Build.Tasks/Test/Microsoft.Build.Tasks/WriteLinesToFileTest.cs
mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/TaskItem.cs
mcs/class/Mono.Data.Sqlite/Test/Bug27864.cs
mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs
mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs
mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs
mcs/class/System.Runtime.Remoting/Test/HttpServerChannelTests.cs
mcs/class/System.ServiceModel/Test/System.ServiceModel.Dispatcher/Bug652331Test.cs
mcs/class/System/System.Net/ServicePoint.cs
mcs/class/System/System.Net/WebConnectionStream.cs
mcs/class/System/System/UriBuilder.cs
mcs/class/System/Test/System.Diagnostics/ProcessTest.cs
mcs/class/System/Test/System.Net.Security/SslStreamTest.cs
mcs/class/System/Test/System/UriBuilderTest.cs
mcs/class/corlib/ReferenceSources/win32native.cs
mcs/class/corlib/System.IO/FileStream.cs
mcs/class/corlib/System.Reflection/MonoProperty.cs
mcs/class/corlib/System.Threading/Monitor.cs
mcs/class/corlib/System.Threading/ThreadPool.cs [deleted file]
mcs/class/corlib/Test/System.Reflection/AssemblyNameTest.cs
mcs/class/corlib/Test/System.Reflection/PropertyInfoTest.cs
mcs/class/corlib/Test/System.Threading/ThreadTest.cs
mcs/mcs/assembly.cs
mcs/mcs/context.cs
mcs/mcs/cs-tokenizer.cs
mcs/mcs/flowanalysis.cs
mcs/mcs/statement.cs
mcs/tests/test-async-68.cs [new file with mode: 0644]
mcs/tests/test-interpolation-08.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_x.xml
mcs/tools/mkbundle/mkbundle.cs
mcs/tools/monop/Makefile
mono/arch/arm/tramp.c [deleted file]
mono/io-layer/handles-private.h
mono/io-layer/handles.c
mono/io-layer/processes.c
mono/io-layer/thread-private.h
mono/io-layer/threads.h
mono/io-layer/wait.c
mono/io-layer/wthreads.c
mono/metadata/Makefile.am
mono/metadata/appdomain.c
mono/metadata/assembly.c
mono/metadata/class.c
mono/metadata/cominterop.c
mono/metadata/domain.c [changed mode: 0755->0644]
mono/metadata/file-io.c
mono/metadata/filewatcher.c
mono/metadata/gc-stats.c
mono/metadata/gc.c
mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/image.c
mono/metadata/loader.c
mono/metadata/marshal.c
mono/metadata/metadata-internals.h
mono/metadata/metadata.c
mono/metadata/monitor.c
mono/metadata/monitor.h
mono/metadata/mono-hash.c
mono/metadata/mono-hash.h
mono/metadata/object-internals.h
mono/metadata/object.c
mono/metadata/object.h
mono/metadata/process.c
mono/metadata/remoting.c
mono/metadata/sgen-os-coop.c [new file with mode: 0644]
mono/metadata/sgen-os-mach.c
mono/metadata/sgen-os-posix.c
mono/metadata/socket-io.c
mono/metadata/threadpool-ms.c
mono/metadata/threads.c
mono/mini/Makefile.am.in
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/cpu-arm.md
mono/mini/cpu-ppc.md
mono/mini/cpu-x86.md
mono/mini/debugger-agent.c
mono/mini/dwarfwriter.c
mono/mini/exceptions-amd64.c
mono/mini/exceptions-arm.c
mono/mini/exceptions-ia64.c
mono/mini/exceptions-mips.c
mono/mini/exceptions-ppc.c
mono/mini/exceptions-s390x.c
mono/mini/exceptions-sparc.c
mono/mini/exceptions-x86.c
mono/mini/method-to-ir.c
mono/mini/mini-amd64.c
mono/mini/mini-amd64.h
mono/mini/mini-arm-tls.S
mono/mini/mini-arm-tls.h
mono/mini/mini-arm.c
mono/mini/mini-darwin.c
mono/mini/mini-exceptions.c
mono/mini/mini-gc.c
mono/mini/mini-ia64.c
mono/mini/mini-llvm-cpp.cpp
mono/mini/mini-llvm.c
mono/mini/mini-mips.c
mono/mini/mini-ops.h
mono/mini/mini-posix.c
mono/mini/mini-ppc.c
mono/mini/mini-runtime.c
mono/mini/mini-s390x.c
mono/mini/mini-s390x.h
mono/mini/mini-sparc.c
mono/mini/mini-trampolines.c
mono/mini/mini-unwind.h
mono/mini/mini-x86.c
mono/mini/mini-x86.h
mono/mini/mini.c
mono/mini/mini.h
mono/mini/tasklets.c
mono/mini/tramp-amd64.c
mono/mini/tramp-arm.c
mono/mini/tramp-ia64.c
mono/mini/tramp-mips.c
mono/mini/tramp-ppc.c
mono/mini/tramp-s390x.c
mono/mini/tramp-sparc.c
mono/mini/tramp-x86.c
mono/mini/unwind.c
mono/tests/Makefile.am
mono/tests/monitor-resurrection.cs
mono/tests/shared-generic-synchronized.2.cs
mono/tests/synchronized.cs
mono/tests/unhandled-exception.cs [new file with mode: 0644]
mono/utils/mono-compiler.h
mono/utils/mono-stack-unwinding.h
mono/utils/mono-threads-coop.c
mono/utils/mono-threads-coop.h
mono/utils/mono-threads-mach.c
mono/utils/mono-threads-posix.c
mono/utils/mono-threads-windows.c [changed mode: 0755->0644]
mono/utils/mono-threads.c
mono/utils/mono-threads.h

index 00d0aa5ff142e10a4068c16a106e0a9516796ae2..7191db1858c1080b7a2f7b281fa2d2c1f7b75dd4 100644 (file)
@@ -77,17 +77,10 @@ has_dtrace=no
 parallel_mark=yes
 ikvm_native=yes
 
-case "$host" in
-       powerpc*-*-linux*)
-               # https://bugzilla.novell.com/show_bug.cgi?id=504411
-               disable_munmap=yes
-       ;;
-esac
-
 host_win32=no
 target_win32=no
 platform_android=no
-platform_darwin=no
+host_darwin=no
 case "$host" in
        *-mingw*|*-*-cygwin*)
                AC_DEFINE(DISABLE_PORTABILITY,1,[Disable the io-portability layer])
@@ -118,7 +111,6 @@ case "$host" in
                libgc_configure_args="$libgc_configure_args --enable-win32-dllmain=yes"
                ;;
        *-*-*netbsd*)
-               host_win32=no
                CPPFLAGS="$CPPFLAGS -D_REENTRANT -DGC_NETBSD_THREADS -D_GNU_SOURCE"
                libmono_cflags="-D_REENTRANT"
                LDFLAGS="$LDFLAGS -pthread"
@@ -131,7 +123,6 @@ case "$host" in
                use_sigposix=yes
                ;;
        *-*-kfreebsd*-gnu)
-               host_win32=no
                CPPFLAGS="$CPPFLAGS -DGC_FREEBSD_THREADS -D_GNU_SOURCE -D_REENTRANT -DUSE_MMAP -DUSE_MUNMAP -DTHREAD_LOCAL_ALLOC -pthread"
                libmono_cflags="-D_REENTRANT -DTHREAD_LOCAL_ALLOC -pthread"
                libmono_ldflags="-lpthread -pthread"
@@ -142,7 +133,6 @@ case "$host" in
                use_sigposix=yes
                ;;
        *-*-*freebsd*)
-               host_win32=no
                if test "x$PTHREAD_CFLAGS" = "x"; then
                        CPPFLAGS="$CPPFLAGS -DGC_FREEBSD_THREADS"
                        libmono_cflags=
@@ -166,7 +156,6 @@ case "$host" in
                has_dtrace=yes
                ;;
        *-*-*openbsd*)
-               host_win32=no
                CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE -DGC_OPENBSD_THREADS -DPLATFORM_BSD -D_REENTRANT -DUSE_MMAP"
                if test "x$disable_munmap" != "xyes"; then
                CPPFLAGS="$CPPFLAGS -DUSE_MUNMAP"
@@ -181,7 +170,6 @@ case "$host" in
                use_sigposix=yes
                ;;
        *-*-linux-android*)
-               host_win32=no
                platform_android=yes
                AC_DEFINE(PLATFORM_ANDROID,1,[Targeting the Android platform])
                AC_DEFINE(TARGET_ANDROID,1,[Targeting the Android platform])
@@ -220,7 +208,6 @@ case "$host" in
                mono_cv_clang=no
                ;;
        *-*-linux*)
-               host_win32=no
                CPPFLAGS="$CPPFLAGS -DGC_LINUX_THREADS -D_GNU_SOURCE -D_REENTRANT -DUSE_MMAP"
                if test "x$disable_munmap" != "xyes"; then
                        CPPFLAGS="$CPPFLAGS -DUSE_MUNMAP"
@@ -239,10 +226,13 @@ case "$host" in
                        support_boehm=no
                        with_gc=sgen
                        ;;
+               powerpc*-*-linux*)
+                       # https://bugzilla.novell.com/show_bug.cgi?id=504411
+                       disable_munmap=yes
+                       ;;
                esac
                ;;
        *-*-nacl*)
-               host_win32=no
                CPPFLAGS="$CPPFLAGS -DGC_LINUX_THREADS -D_GNU_SOURCE -D_REENTRANT -DUSE_MMAP"
                if test "x$disable_munmap" != "xyes"; then
                        CPPFLAGS="$CPPFLAGS -DUSE_MUNMAP"
@@ -256,7 +246,6 @@ case "$host" in
                AC_DEFINE(DISABLE_ATTACH, 1, [Disable agent attach support])
                ;;
        *-*-hpux*)
-               host_win32=no
                CPPFLAGS="$CPPFLAGS -DGC_HPUX_THREADS -D_HPUX_SOURCE -D_XOPEN_SOURCE_EXTENDED -D_REENTRANT"
                # +ESdbgasm only valid on bundled cc on RISC
                # silently ignored for ia64
@@ -275,7 +264,6 @@ case "$host" in
                use_sigposix=yes
                ;;
        *-*-solaris*)
-               host_win32=no
                CPPFLAGS="$CPPFLAGS -DGC_SOLARIS_THREADS -DGC_SOLARIS_PTHREADS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -DUSE_MMAP -DUSE_MUNMAP -DPLATFORM_SOLARIS"
                need_link_unlink=yes
                libmono_cflags="-D_REENTRANT"
@@ -288,8 +276,7 @@ case "$host" in
                ;;
        *-*-darwin*)
                parallel_mark="Disabled_Currently_Hangs_On_MacOSX"
-               host_win32=no
-               platform_darwin=yes
+               host_darwin=yes
                target_mach=yes
                CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE -DGC_MACOSX_THREADS -DPLATFORM_MACOSX -DUSE_MMAP -DUSE_MUNMAP"
                libmono_cflags="-D_THREAD_SAFE"
@@ -327,7 +314,6 @@ case "$host" in
                esac
                ;;
        *-*-haiku*)
-               host_win32=no
                CPPFLAGS="$CPPFLAGS -D_REENTRANT -D_THREAD_SAFE"
                libmono_cflags="-D_REENTRANT -D_THREAD_SAFE"
                libdl=
@@ -339,7 +325,6 @@ case "$host" in
                ;;
        *)
                AC_MSG_WARN([*** Please add $host to configure.ac checks!])
-               host_win32=no
                libdl="-ldl"
                ;;
 esac
@@ -360,9 +345,8 @@ fi
 AC_SUBST(extra_runtime_ldflags)
 AM_CONDITIONAL(HOST_WIN32, test x$host_win32 = xyes)
 AM_CONDITIONAL(TARGET_WIN32, test x$target_win32 = xyes)
-AM_CONDITIONAL(PLATFORM_GNU, echo x$target_os | grep -q -- -gnu)
 AM_CONDITIONAL(PLATFORM_LINUX, echo x$target_os | grep -q linux)
-AM_CONDITIONAL(PLATFORM_DARWIN, test x$platform_darwin = xyes)
+AM_CONDITIONAL(PLATFORM_DARWIN, test x$host_darwin = xyes)
 AM_CONDITIONAL(PLATFORM_SIGPOSIX, test x$use_sigposix = xyes)
 AM_CONDITIONAL(PLATFORM_ANDROID, test x$platform_android = xyes)
 
@@ -667,17 +651,9 @@ AC_CONFIG_SUBDIRS(eglib)
 
 GLIB_CFLAGS='-I$(top_srcdir)/eglib/src -I$(top_builddir)/eglib/src'
 GLIB_LIBS='-L$(top_builddir)/eglib/src -leglib -lm'
-BUILD_GLIB_CFLAGS="$GLIB_CFLAGS"
-BUILD_GLIB_LIBS="$GLIB_LIBS"
-GMODULE_CFLAGS="$GLIB_CFLAGS"
-GMODULE_LIBS="$GLIB_LIBS"
   
 AC_SUBST(GLIB_CFLAGS)
 AC_SUBST(GLIB_LIBS)
-AC_SUBST(GMODULE_CFLAGS)
-AC_SUBST(GMODULE_LIBS)
-AC_SUBST(BUILD_GLIB_CFLAGS)
-AC_SUBST(BUILD_GLIB_LIBS)
 
 # Enable support for fast thread-local storage
 # Some systems have broken support, so we allow to disable it.
@@ -953,12 +929,6 @@ if test x$has_extension_module != xno ; then
        AC_MSG_NOTICE([Enabling mono extension module.])
 fi
 
-AC_ARG_ENABLE(gsharing, [  --enable-gsharing Enable gsharing], enable_gsharing=$enableval, enable_gsharing=no)
-if test x$enable_gsharing = xyes; then
-       AC_DEFINE(ENABLE_GSHAREDVT,1,[Gsharing])
-fi
-
-# A synonym
 AC_ARG_ENABLE(gsharedvt, [  --enable-gsharedvt Enable generic valuetype sharing], enable_gsharedvt=$enableval, enable_gsharedvt=no)
 if test x$enable_gsharedvt = xyes; then
        AC_DEFINE(ENABLE_GSHAREDVT,1,[Gsharedvt])
@@ -1941,7 +1911,7 @@ if test x$host_win32 = xno; then
        dnl * back 
        dnl **************************************
        if test "x$havekqueue" = "xyes" -a "x$ac_cv_header_sys_event_h" = "xyes"; then
-               if test "x$platform_darwin" = "xno"; then
+               if test "x$host_darwin" = "xno"; then
                        AC_DEFINE(USE_KQUEUE_FOR_THREADPOOL, 1, [Use kqueue for the threadpool])
                fi
        fi
@@ -2101,6 +2071,7 @@ if test x$host_win32 = xno; then
        AC_CHECK_FUNCS(readv writev preadv pwritev)
        AC_CHECK_FUNCS(setpgid)
        AC_CHECK_FUNCS(system)
+       AC_CHECK_FUNCS(fork execve)
        AC_CHECK_SIZEOF(size_t)
        AC_CHECK_TYPES([blksize_t], [AC_DEFINE(HAVE_BLKSIZE_T)], , 
                [#include <sys/types.h>
@@ -2189,10 +2160,6 @@ if test x$host_win32 = xno; then
         #endif
        ])
        AC_CHECK_HEADERS([termios.h])
-
-       dnl * This is provided in io-layer, but on windows it's only available
-       dnl * on xp+
-       AC_DEFINE(HAVE_GETPROCESSID, 1, [Define if GetProcessId is available])
 else
        dnl *********************************
        dnl *** Checks for Windows compilation ***
@@ -2351,16 +2318,6 @@ else
        AC_CHECK_DECLS(InterlockedAdd, [], [], [[#include <windows.h>]])
        AC_CHECK_DECLS(InterlockedAdd64, [], [], [[#include <windows.h>]])
        AC_CHECK_DECLS(__readfsdword, [], [], [[#include <windows.h>]])
-
-       AC_MSG_CHECKING(for GetProcessId)
-       AC_TRY_COMPILE([#include <windows.h>], [
-               GetProcessId (0);
-       ], [
-          AC_MSG_RESULT(yes)
-          AC_DEFINE(HAVE_GETPROCESSID)
-       ], [
-          AC_MSG_RESULT(no)
-       ])
 fi
 
 dnl socklen_t check
@@ -2728,13 +2685,11 @@ XINERAMA="libXinerama.so.1"
 sizeof_register="SIZEOF_VOID_P"
 
 jit_wanted=true
-sgen_supported=false
 boehm_supported=true
 case "$host" in
        mips*)
                TARGET=MIPS;
                arch_target=mips;
-               sgen_supported=true
                ACCESS_UNALIGNED="no"
 
                AC_MSG_CHECKING(for mips n32)
@@ -2773,25 +2728,20 @@ case "$host" in
                        # foo.c:6: warning: visibility attribute not supported in this configuration; ignored
                        # ld: fatal: relocation error: R_386_GOTOFF: file /var/tmp//ccxYR96k.o: symbol astruct: relocation must bind locally
                        have_visibility_hidden=no
-                       sgen_supported=true
                        ;;
                  mingw*|cygwin*)
-                       sgen_supported=true
                        have_visibility_hidden=no                 
                        ;;
                  haiku*)
                        LIBC=libroot.so
                        ;;
                  linux*)
-                       sgen_supported=true
                        AOT_SUPPORTED="yes"
                        ;;
                  darwin*)
-                       sgen_supported=true
                        AOT_SUPPORTED="yes"
                        ;;
                  openbsd*|freebsd*|kfreebsd-gnu*)
-                       sgen_supported=true
                        ;;
                esac
                ;;
@@ -2804,18 +2754,14 @@ case "$host" in
                fi
                case $host_os in
                  linux*)
-                       sgen_supported=true
                        AOT_SUPPORTED="yes"
                        ;;
                  darwin*)
-                       sgen_supported=true
                        AOT_SUPPORTED="yes"
                        ;;
                  openbsd*|freebsd*|kfreebsd-gnu*)
-                       sgen_supported=true
                        ;;
                  mingw*)
-                       sgen_supported=true
                        ;;
                esac
                case "$host" in
@@ -2855,7 +2801,6 @@ case "$host" in
                if test x"$AR" = xfalse; then
                        AC_MSG_ERROR([The required utility 'ar' is not found in your PATH. Usually it can be found in /usr/ccs/bin.])
                fi
-               sgen_supported=true
                ;;
        *-mingw*|*-*-cygwin*)
                # When this is enabled, it leads to very strange crashes at runtime (gcc-3.4.4)
@@ -2875,7 +2820,6 @@ case "$host" in
                arch_target=ppc;
                case $host_os in
                  linux*|darwin*)
-                       sgen_supported=true
                        ;;
                esac
                ;;
@@ -2884,13 +2828,11 @@ case "$host" in
                arch_target=arm;
                ACCESS_UNALIGNED="no"
                CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
-               sgen_supported=true
                ;;
        arm*-linux*)
                TARGET=ARM;
                arch_target=arm;
                ACCESS_UNALIGNED="no"
-               sgen_supported=true
                AOT_SUPPORTED="yes"
                CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
                ;;
@@ -2899,21 +2841,18 @@ case "$host" in
 #              TARGET=ARM;
 #              arch_target=arm;
 #              ACCESS_UNALIGNED="no"
-#              sgen_supported=true
 #              AOT_SUPPORTED="no"
 #              ;;
        aarch64-*)
                # https://lkml.org/lkml/2012/7/15/133
                TARGET=ARM64
                arch_target=arm64
-               sgen_supported=true
                boehm_supported=false
                ;;
        s390x-*-linux*)
                TARGET=S390X;
                arch_target=s390x;
                ACCESS_UNALIGNED="yes"
-               sgen_supported=true
                CFLAGS="$CFLAGS -mbackchain -D__USE_STRING_INLINES"
                ;;
 esac
@@ -3012,7 +2951,6 @@ if test "x$host" != "x$target"; then
                AC_DEFINE(TARGET_X86, 1, [...])
                AC_DEFINE(TARGET_ANDROID, 1, [...])
                CPPFLAGS="$CPPFLAGS"
-               sgen_supported=true
                # Can't use tls, since it depends on the runtime detection of tls offsets
                # in mono-compiler.h            
                with_tls=pthread
@@ -3024,7 +2962,6 @@ if test "x$host" != "x$target"; then
                AC_DEFINE(TARGET_AMD64, 1, [...])
                AC_DEFINE(TARGET_ANDROID, 1, [...])
                CPPFLAGS="$CPPFLAGS"
-               sgen_supported=true
                # Can't use tls, since it depends on the runtime detection of tls offsets
                # in mono-compiler.h
                with_tls=pthread
@@ -3036,7 +2973,6 @@ if test "x$host" != "x$target"; then
                AC_DEFINE(TARGET_AMD64, 1, [...])
                AC_DEFINE(TARGET_PS4, 1, [...])
                CPPFLAGS="$CPPFLAGS"
-               sgen_supported=true
                # Can't use tls, since it depends on the runtime detection of tls offsets
                # in mono-compiler.h
                with_tls=pthread
@@ -3199,21 +3135,11 @@ fi
 dnl 
 dnl Simple Generational checks (sgen)
 dnl
-if $sgen_supported; then
-   build_sgen_default=yes
-else
-   build_sgen_default=no
-fi
 SGEN_DEFINES=
-AC_ARG_WITH(sgen, [  --with-sgen=yes,no             Extra Generational GC, default=yes],[buildsgen=$with_sgen],[buildsgen=$build_sgen_default])
+AC_ARG_WITH(sgen, [  --with-sgen=yes,no             Extra Generational GC, default=yes],[buildsgen=$with_sgen],[buildsgen=yes])
 if test x$buildsgen = xyes; then
-   if $sgen_supported; then
-       SGEN_DEFINES="-DHAVE_SGEN_GC -DHAVE_MOVING_COLLECTOR"
-       gc_msg="sgen and $gc_msg"
-   else
-       buildsgen=no
-       AC_MSG_WARN("Sgen is not supported on this platform")
-   fi
+   SGEN_DEFINES="-DHAVE_SGEN_GC -DHAVE_MOVING_COLLECTOR"
+   gc_msg="sgen and $gc_msg"
 fi
 AC_SUBST(SGEN_DEFINES)
 AM_CONDITIONAL(SUPPORT_SGEN, test x$buildsgen = xyes)
@@ -3359,7 +3285,7 @@ if test ${TARGET} = ARM; then
        fpu=NONE
 
        # iOS GCC always uses the 'softfp' ABI.
-       if test x"$GCC" = xyes && test x$platform_darwin = xyes; then
+       if test x"$GCC" = xyes && test x$host_darwin = xyes; then
                fpu=VFP
        fi
 
@@ -3543,6 +3469,13 @@ AC_ARG_WITH(cooperative_gc, [  --with-cooperative-gc=yes|no      Enable cooperat
        fi
 ], [with_cooperative_gc=no])
 
+AC_ARG_WITH(checked_build, [  --with-checked-build=yes|no      Enable checked build (expensive asserts)) (defaults to no)],[
+       if test x$with_checked_build != xno ; then
+               AC_DEFINE(CHECKED_BUILD,1,[Enable checked build.])
+       fi
+], [with_checked_build=no])
+
+
 AC_CHECK_HEADER([malloc.h], 
                [AC_DEFINE([HAVE_USR_INCLUDE_MALLOC_H], [1], 
                        [Define to 1 if you have /usr/include/malloc.h.])],,)
@@ -3915,7 +3848,7 @@ if test x$host_win32 = xyes; then
    sed -e "s,-mno-cygwin,,g" libtool > libtool.new; mv libtool.new libtool; chmod 755 libtool
 fi
 
-if test x$platform_darwin = xyes; then
+if test x$host_darwin = xyes; then
    # This doesn't seem to be required and it slows down parallel builds
    sed -e 's,lock_old_archive_extraction=yes,lock_old_archive_extraction=no,g' < libtool > libtool.new && mv libtool.new libtool && chmod +x libtool
 fi
@@ -3964,7 +3897,7 @@ fi
 
     echo "MONO_VERSION = $myver" >> $mcs_topdir/build/config.make
 
-    if test x$platform_darwin = xyes; then
+    if test x$host_darwin = xyes; then
       echo "PLATFORM = darwin" >> $mcs_topdir/build/config.make
     fi
 
index 5281419c00bcffd42155da17f705895cd7232e29..9d094ea7cdfaef28532cc71d1d167c34141178ce 100644 (file)
@@ -136,6 +136,7 @@ AC_CHECK_SIZEOF(long)
 AC_CHECK_SIZEOF(long long)
 AC_CHECK_FUNCS(strlcpy stpcpy strtok_r rewinddir vasprintf)
 AC_CHECK_FUNCS(getrlimit)
+AC_CHECK_FUNCS(fork execv execve)
 
 #
 # Mono currently supports 10.6, but strndup is not available prior to 10.7; avoiding
@@ -150,7 +151,7 @@ elif test x$target_ios = xno; then
 AC_CHECK_FUNCS(strndup getpwuid_r)
 fi
 
-AM_CONDITIONAL(NEED_VASPRINTF, test x$have_vasprintf = x )
+AM_CONDITIONAL(NEED_VASPRINTF, test x$ac_cv_func_vasprintf = x )
 AM_ICONV()
 AC_SEARCH_LIBS(sqrtf, m)
 
index a01904e3e3440cffe35c1ce0383382d9e8ceb227..4d0bf9e8eca919c44d609095fef62b01ada0f9a9 100644 (file)
@@ -248,6 +248,9 @@ g_spawn_command_line_sync (const gchar *command_line,
                                GError **error)
 {
 #ifdef G_OS_WIN32
+#elif !defined (HAVE_FORK) || !defined (HAVE_EXECV)
+       fprintf (stderr, "g_spawn_command_line_sync not supported on this platform\n");
+       return FALSE;
 #else
        pid_t pid;
        gchar **argv;
@@ -344,6 +347,9 @@ g_spawn_async_with_pipes (const gchar *working_directory,
                        GError **error)
 {
 #ifdef G_OS_WIN32
+#elif !defined (HAVE_FORK) || !defined (HAVE_EXECVE)
+       fprintf (stderr, "g_spawn_async_with_pipes is not supported on this platform\n");
+       return FALSE;
 #else
        pid_t pid;
        int info_pipe [2];
index a916688137c5acd05967a4e7c7b02e2b785d46eb..4f391fe60cbd36f3b3528e05a45d81ee60f390d8 100644 (file)
@@ -1,9 +1,9 @@
 
-AM_CPPFLAGS = $(GMODULE_CFLAGS)
+AM_CPPFLAGS = $(GLIB_CFLAGS)
 
 lib_LTLIBRARIES = libikvm-native.la
 
 libikvm_native_la_SOURCES = jni.c os.c jni.h
 
 libikvm_native_la_LDFLAGS = -avoid-version
-libikvm_native_la_LIBADD = $(GMODULE_LIBS)
+libikvm_native_la_LIBADD = $(GLIB_LIBS)
index 57352e70f4f287d3fea971795266fd008039e9eb..f663120bf798730223c944db359caa7873771dc5 100644 (file)
@@ -472,7 +472,7 @@ namespace Microsoft.Build.BuildEngine {
 
                        BuildItemGroup big;                     
                        BuildItem bi = new BuildItem (this);
-                       bi.finalItemSpec = ((ITaskItem2)taskitem).EvaluatedIncludeEscaped;
+                       bi.finalItemSpec = taskitem.ItemSpec;
 
                        foreach (DictionaryEntry de in taskitem.CloneCustomMetadata ()) {
                                bi.unevaluatedMetadata.Add ((string) de.Key, (string) de.Value);
index 536204e94fef828b98836d56953377718b88a22b..ccfc0fa3a0ea8a46c1a5018af0732e84820892b4 100644 (file)
@@ -156,7 +156,7 @@ namespace Microsoft.Build.BuildEngine {
                        for (int i = 0; i < lists.Count; i++) {
                                foreach (object o in lists [i]) {
                                        if (o is string)
-                                               expressionCollection.Add ((string) o);
+                                               expressionCollection.Add (MSBuildUtils.Unescape ((string) o));
                                        else if (!allowItems && o is ItemReference)
                                                expressionCollection.Add (((ItemReference) o).OriginalString);
                                        else if (!allowMd && o is MetadataReference) {
index d629906633200d69b14afb6c493cff7268e19b8f..ca0034a10923b5ab756aa8c38ba1c96c82115856 100644 (file)
@@ -233,11 +233,11 @@ namespace Microsoft.Build.BuildEngine {
                        // Trim and Remove empty items
                        List<ITaskItem> toRemove = new List<ITaskItem> ();
                        for (int i = 0; i < finalItems.Count; i ++) {
-                               string s = ((ITaskItem2)finalItems [i]).EvaluatedIncludeEscaped.Trim ();
+                               string s = finalItems [i].ItemSpec.Trim ();
                                if (s.Length == 0)
                                        toRemove.Add (finalItems [i]);
                                else
-                                       ((ITaskItem2)finalItems [i]).EvaluatedIncludeEscaped = s;
+                                       finalItems [i].ItemSpec = s;
                        }
                        foreach (ITaskItem ti in toRemove)
                                finalItems.Remove (ti);
index 1aa785622ba7e91e8b9f10a9d9d3cb286d17750f..24b76b6c07c3d633162467a01cb9077bbbc96397 100644 (file)
@@ -79,6 +79,7 @@ namespace MonoTests.Microsoft.Build.Tasks {
                                                <Message Text='Text5' Importance='normal'/>
                                                <Message Text='Text6' Importance='high'/>
                                                <Message Text='Text7' />
+                                               <Message Text='%22abc test%22 123 %22def%22' />
                                                <Message Text='Text8' Importance='weird_importance'/>
                                        </Target>
                                </Project>
@@ -102,7 +103,8 @@ namespace MonoTests.Microsoft.Build.Tasks {
                        Assert.AreEqual (0, testLogger.CheckAny ("Text5", MessageImportance.Normal), "A5");
                        Assert.AreEqual (0, testLogger.CheckAny ("Text6", MessageImportance.High), "A6");
                        Assert.AreEqual (0, testLogger.CheckAny ("Text7", MessageImportance.Normal), "A7");
-                       Assert.AreEqual (1, testLogger.CheckAny ("Text8", MessageImportance.Normal), "A8");
+                       Assert.AreEqual (0, testLogger.CheckAny ("\"abc test\" 123 \"def\"", MessageImportance.Normal), "A8");
+                       Assert.AreEqual (1, testLogger.CheckAny ("Text8", MessageImportance.Normal), "A9");
                }
        }
 }      
index 4a61015f0be8d245ee5ddfae52cb8bd4b48eb3fe..3342c003e8bf890d8df77900cb32aee9f6d3eb0f 100755 (executable)
@@ -91,6 +91,7 @@ namespace MonoTests.Microsoft.Build.Tasks {
                }
 
                [Test]
+               [Category("NotWorking")] // this fails due to an xbuild bug, it works on MS.NET
                public void TestLineWithEscapedSemicolon ()
                {
                        string[] lines = new string[] { "abc%3Btest%3B%3B", "%3Bdef" };
@@ -101,6 +102,7 @@ namespace MonoTests.Microsoft.Build.Tasks {
                }
 
                [Test]
+               [Category("NotWorking")] // this fails due to an xbuild bug, it works on MS.NET
                public void TestLineWithEscapedSpace ()
                {
                        string[] lines = new string[] { "  %20%20abc%20test  ", "  def%20%20" };
@@ -110,6 +112,16 @@ namespace MonoTests.Microsoft.Build.Tasks {
                        });
                }
 
+               [Test]
+               public void TestLineWithEscapedQuote ()
+               {
+                       string[] lines = new string[] { "%22abc test%22 123 %22def%22" };
+                       CreateProjectAndCheck (full_filepath, lines, false, true, delegate () {
+                               CheckFileExists (full_filepath, true);
+                               CheckLines (full_filepath, new string [] {"\"abc test\" 123 \"def\""});
+                       });
+               }
+
                [Test]
                public void TestNoOverwrite ()
                {
index 5e818caf70756dba3b45a18c8443ad9eccf03891..2d2de50cd9e6d8c4d73ab42bade65cbea2c89ff2 100644 (file)
@@ -173,7 +173,7 @@ namespace Microsoft.Build.Utilities
                }
                public override string ToString ()
                {
-                       return ItemSpec;
+                       return escapedItemSpec;
                }
                
                public string ItemSpec {
index a3a5376e48c330eeb01ca2ea8c0d9084e9e3ff65..d64d3055b999b36e07e8ba66aeed04a5aba275c0 100644 (file)
@@ -92,14 +92,12 @@ namespace MonoTests.Mono.Data.Sqlite {
                                                        Assert.AreEqual(dr["Company.Name"], "Test CO");
                                                        i += 2;
                                                }
-                                               Assert.IsTrue(dr.FieldCount>0);
+                                               Assert.IsTrue(dr.FieldCount>0, i.ToString ());
                                        }
-                                       if (BCL.Tests.TestRuntime.CheckSystemVersion (8, 2))
-                                               Assert.IsTrue (false, "Apple fixed bug 27864, this check can now be removed");
                                }
                        } catch (SqliteException ex) {
-
-                               if (BCL.Tests.TestRuntime.CheckSystemVersion (8, 2)) // Expected Exception on iOS 8.2+, if this does not happen anymore it means apple fixed it
+                               // Expected Exception from iOS 8.2 (broken) to 9.0 (fixed)
+                               if (BCL.Tests.TestRuntime.CheckSystemVersion (8,2) && !BCL.Tests.TestRuntime.CheckSystemVersion (9,0)) 
                                        Assert.That (ex.Message.Contains ("no such column: com.Name"));
                                else
                                        throw new AssertionException ("Unexpected Sqlite Error", ex); // This should not happen
index abb05921042ee5a72d4f5c36457a64208cde3aa2..05b5fe62681f3f981b067777d1cb7a7f9f32a03b 100644 (file)
@@ -363,6 +363,10 @@ namespace System.Net.Http.Headers
                                first = false;
                        }
 
+                       // Return null for empty values list
+                       if (first)
+                               return null;
+
                        return sb.ToString ();
                }
 
index ccf9a808c25b9e005b32d1d846c0efa98ef9f8ca..087e62474d2f986c1b84228fb3a2e30201e4d952 100644 (file)
@@ -30,6 +30,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using System.Collections.Specialized;
 using System.Net.Http.Headers;
+using System.Linq;
 
 namespace System.Net.Http
 {
@@ -274,7 +275,18 @@ namespace System.Net.Http
                        // Add request headers
                        var headers = wr.Headers;
                        foreach (var header in request.Headers) {
-                               headers.AddValue (header.Key, HttpRequestHeaders.GetSingleHeaderString (header.Key, header.Value));
+                               var values = header.Value;
+                               if (header.Key == "Transfer-Encoding") {
+                                       // Chunked Transfer-Encoding is never set for HttpWebRequest. It's detected
+                                       // from ContentLength by HttpWebRequest
+                                       values = values.Where (l => l != "chunked");
+                               }
+
+                               var values_formated = HttpRequestHeaders.GetSingleHeaderString (header.Key, values);
+                               if (values_formated == null)
+                                       continue;
+
+                               headers.AddValue (header.Key, values_formated);
                        }
                        
                        return wr;
index a6c69de2bb99e96640a181ab26b8ddef1712a130..ec049a932105ea973be9d262937694c89f83348e 100644 (file)
@@ -606,6 +606,62 @@ namespace MonoTests.System.Net.Http
                        }
                }
 
+               [Test]
+               public void Send_Transfer_Encoding_Chunked ()
+               {
+                       bool? failed = null;
+
+                       var listener = CreateListener (l => {
+                               var request = l.Request;
+
+                               try {
+                                       Assert.AreEqual (1, request.Headers.Count, "#1");
+                                       failed = false;
+                               } catch {
+                                       failed = true;
+                               }
+                       });
+
+                       try {
+                               var client = new HttpClient ();
+                               client.DefaultRequestHeaders.TransferEncodingChunked = true;
+
+                               client.GetAsync (LocalServer).Wait ();
+
+                               Assert.AreEqual (false, failed, "#102");
+                       } finally {
+                               listener.Abort ();
+                               listener.Close ();
+                       }
+               }
+
+               [Test]
+               public void Send_Transfer_Encoding_Custom ()
+               {
+                       bool? failed = null;
+
+                       var listener = CreateListener (l => {
+                               failed = true;
+                       });
+
+                       try {
+                               var client = new HttpClient ();
+                               client.DefaultRequestHeaders.TransferEncoding.Add (new TransferCodingHeaderValue ("chunked2"));
+
+                               var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
+
+                               try {
+                                       client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Wait ();
+                                       Assert.Fail ("#1");
+                               } catch (AggregateException e) {
+                                       Assert.AreEqual (typeof (ProtocolViolationException), e.InnerException.GetType (), "#2");
+                               }
+                               Assert.IsNull (failed, "#102");
+                       } finally {
+                               listener.Abort ();
+                               listener.Close ();
+                       }
+               }
 
                [Test]
                public void Send_Complete_Content ()
index e15a51bfe02a2bc522134f66a43ee6786b8881b5..a34e32c78a41be95ad6f4bab3773c9296c0b10f9 100644 (file)
@@ -94,7 +94,7 @@ namespace MonoTests.Remoting {
                };
                
                [Test] // HttpChannel.Parse ()
-               [Ignore ("Fails on MS")]
+               [Category ("NotWorking")] // Fails on MS
                public void ParseURL ()
                {
                        HttpChannel channel;
index 70d9c79c624ff3f6f16f89b274a894da425884f0..cdc68486779adc619e335eccabbb06dc4a72265c 100644 (file)
@@ -57,6 +57,7 @@ namespace MonoTests.System.ServiceModel.Dispatcher
                        serviceHost.AddServiceEndpoint (typeof (IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding (), "mex");
 
                        serviceHost.Open ();
+                       Thread.Sleep (2000);  // let WCF spin up
 
                        try {
                                // client
index bb47c65c48faa262a6dedeeafc554390e796d4cd..d3a3dd507be8c35b0f252f25ea9ad0e1c9cd89a6 100644 (file)
@@ -312,7 +312,7 @@ namespace System.Net
                        lock (this) {
                                idleSince = outIdleSince;
 
-                               if (removeList != null) {
+                               if (removeList != null && groups != null) {
                                        foreach (var group in removeList)
                                                if (groups.ContainsKey (group.Name))
                                                        RemoveConnectionGroup (group);
index 87f60363da8a4306b543420ccf085a142b764d2e..3862b3e4eff56284f11f2d1f768ce139c75e2c02 100644 (file)
@@ -654,7 +654,8 @@ namespace System.Net
                        if (setInternalLength && !no_writestream && writeBuffer != null)
                                request.InternalContentLength = writeBuffer.Length;
 
-                       if (!(sendChunked || request.ContentLength > -1 || no_writestream || webdav))
+                       bool has_content = !no_writestream && (writeBuffer == null || request.ContentLength > -1);
+                       if (!(sendChunked || has_content || no_writestream || webdav))
                                return false;
 
                        headersSent = true;
index 3464e0a971a9938dd0fd661294c3678855255e70..6d878731991f60945ebc74a77981c868acf44215 100644 (file)
@@ -263,7 +263,12 @@ namespace System
 
                        builder.Append (scheme);
                        // note: mailto and news use ':', not "://", as their delimiter
-                       builder.Append (Uri.GetSchemeDelimiter (scheme));
+                       if (UriParser.IsKnownScheme(scheme)) {
+                               builder.Append (Uri.GetSchemeDelimiter (scheme));
+                       }
+                       else {
+                               builder.Append (host.Length > 0 ? Uri.SchemeDelimiter : ":");
+                       }
 
                        if (username != String.Empty) {
                                builder.Append (username);
@@ -280,7 +285,8 @@ namespace System
 
                        if (path != String.Empty &&
                            builder [builder.Length - 1] != '/' &&
-                           path.Length > 0 && path [0] != '/')
+                           path.Length > 0 && path [0] != '/' &&
+                               host.Length > 0)
                                builder.Append ('/');
                        builder.Append (path);
                        builder.Append (query);
index 0a316e34494d96dc0e468a39d7dfee56188f83c8..1c9dc2484a67f7f06b5485489469f8b0f57a1925 100644 (file)
@@ -791,9 +791,11 @@ namespace MonoTests.System.Diagnostics
                        p.StartInfo.RedirectStandardError = true;
 
                        var exitedCalledCounter = 0;
+                       var exited = new ManualResetEventSlim ();
                        p.Exited += (object sender, EventArgs e) => {
                                exitedCalledCounter++;
                                Assert.IsTrue (p.HasExited);
+                               exited.Set ();
                        };
 
                        p.EnableRaisingEvents = true;
@@ -803,6 +805,7 @@ namespace MonoTests.System.Diagnostics
                        p.BeginOutputReadLine ();
                        p.WaitForExit ();
 
+                       exited.Wait (10000);
                        Assert.AreEqual (1, exitedCalledCounter);
                        Thread.Sleep (50);
                        Assert.AreEqual (1, exitedCalledCounter);
@@ -822,9 +825,11 @@ namespace MonoTests.System.Diagnostics
                        p.EnableRaisingEvents = true;
 
                        var exitedCalledCounter = 0;
+                       var exited = new ManualResetEventSlim ();
                        p.Exited += (object sender, EventArgs e) => {
                                exitedCalledCounter++;
                                Assert.IsTrue (p.HasExited);
+                               exited.Set ();
                        };
 
                        p.Start ();
@@ -832,6 +837,7 @@ namespace MonoTests.System.Diagnostics
                        p.BeginOutputReadLine ();
                        p.WaitForExit ();
 
+                       exited.Wait (10000);
                        Assert.AreEqual (1, exitedCalledCounter);
                        Thread.Sleep (50);
                        Assert.AreEqual (1, exitedCalledCounter);
index 3f3cf1a5ddbae5c2480959728273167dc5c85f25..2dd0d0674632ab82bd8a73d99724e3f1cc9c43b3 100644 (file)
@@ -77,9 +77,9 @@ public class SslStreamTest {
                        serverThread.Start ();
                        Thread clientThread = new Thread (() => StartClientAndAuthenticate (state, endPoint));
                        clientThread.Start ();
-                       Assert.AreEqual (server, state.ServerAuthenticated.WaitOne (TimeSpan.FromSeconds (2)), 
+                       Assert.AreEqual (server, state.ServerAuthenticated.WaitOne (TimeSpan.FromSeconds (5)), 
                                "server not authenticated");
-                       Assert.AreEqual (client, state.ClientAuthenticated.WaitOne (TimeSpan.FromSeconds (2)), 
+                       Assert.AreEqual (client, state.ClientAuthenticated.WaitOne (TimeSpan.FromSeconds (5)), 
                                "client not authenticated");
                } finally {
                        if (state.ClientStream != null)
index d2c19e49830c1b32663bc58d826a8ef85776645b..a01e0accc2fb580acd4c5e279ea39f8b7b7625c3 100644 (file)
@@ -383,6 +383,13 @@ namespace MonoTests.System
                        // this is what ASP.NET really means (the ?)
                        Assert.AreEqual ("http://192.168.0.21/error404.aspx?aspxerrorpath=/WebResource.axd", ub.Uri.ToString ());
                }
+
+               [Test]
+               public void NoHostname ()
+               {
+                       UriBuilder ub = new UriBuilder ("about", null, -1, "config");
+                       Assert.AreEqual ("about:config", ub.ToString ());
+               }
        }
 }
 
index c856267d8961598173a23cc91e4b85f5f6b352d1..a732d3eba0f5a602e660905a6b47db23f99ff5a8 100644 (file)
@@ -10,5 +10,10 @@ namespace Microsoft.Win32
                {
                        return "Error " + hr;
                }
+
+               public class SECURITY_ATTRIBUTES
+               {
+
+               }
        }
 }
\ No newline at end of file
index 610247d2e088429f6ca9d36eda5bbea5c5516218..5690dac24ed8f814ff12c3471e1cc5bd3a9401f1 100644 (file)
@@ -411,10 +411,8 @@ namespace System.IO
                                return ret;
                        }
                        set {
-                               if(value < 0) {
-                                       throw new ArgumentOutOfRangeException("Attempt to set the position to a negative value");
-                               }
-                               
+                               if (value < 0) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
                                Seek (value, SeekOrigin.Begin);
                        }
                }
index 0f28d20d5c7fac4cb79f68ba57c325e193aff128..87310b19e2fa8d22835a84f4e05b3d75e0d9b932 100644 (file)
@@ -82,12 +82,28 @@ namespace System.Reflection {
                        }
                }
 
+               public override Module Module {
+                       get {
+                               return GetRuntimeModule ();
+                       }
+               }
+
+               internal RuntimeType GetDeclaringTypeInternal ()
+               {
+                       return (RuntimeType) DeclaringType;
+               }
+
                RuntimeType ReflectedTypeInternal {
                        get {
                                return (RuntimeType) ReflectedType;
                        }
                }
 
+               internal RuntimeModule GetRuntimeModule ()
+               {
+                       return GetDeclaringTypeInternal ().GetRuntimeModule ();
+               }
+
         #region Object Overrides
         public override String ToString()
         {
index 026f46c3797430f24db8ba3911b8a03bd84749fd..5f00b0a1488576cb5dd1989ff4725207e9505b2b 100644 (file)
@@ -192,9 +192,12 @@ namespace System.Threading
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern static void try_enter_with_atomic_var (object obj, int millisecondsTimeout, ref bool lockTaken);
 
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static void enter_with_atomic_var (object obj, ref bool lockTaken);
+
                public static void Enter (object obj, ref bool lockTaken)
                {
-                       TryEnter (obj, Timeout.Infinite, ref lockTaken);
+                       enter_with_atomic_var (obj, ref lockTaken);
                }
 
                public static void TryEnter (object obj, ref bool lockTaken)
diff --git a/mcs/class/corlib/System.Threading/ThreadPool.cs b/mcs/class/corlib/System.Threading/ThreadPool.cs
deleted file mode 100644 (file)
index eb01abf..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-//
-// System.Threading.ThreadPool.cs
-//
-// Author:
-//   Patrik Torstensson
-//   Dick Porter (dick@ximian.com)
-//   Maurer Dietmar (dietmar@ximian.com)
-//
-// (C) Ximian, Inc.  http://www.ximian.com
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Collections;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Runtime.CompilerServices;
-using System.Runtime.Remoting.Messaging;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Security.Permissions;
-
-namespace System.Threading {
-
-       public static class ThreadPool {
-
-               [Obsolete("This method is obsolete, use BindHandle(SafeHandle) instead")]
-               public static bool BindHandle (IntPtr osHandle)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.BindHandle (osHandle);
-                       else
-                               return true;
-               }
-
-               public static bool BindHandle (SafeHandle osHandle)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool) {
-                               return Microsoft.ThreadPool.BindHandle (osHandle);
-                       } else {
-                               if (osHandle == null)
-                                       throw new ArgumentNullException ("osHandle");
-                       
-                               return true;
-                       }
-               }
-
-               public static void GetAvailableThreads (out int workerThreads, out int completionPortThreads)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               Microsoft.ThreadPool.GetAvailableThreads (out workerThreads, out completionPortThreads);
-                       else
-                               GetAvailableThreads_internal (out workerThreads, out completionPortThreads);
-               }
-
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               static extern void GetAvailableThreads_internal (out int workerThreads, out int completionPortThreads);
-
-               public static void GetMaxThreads (out int workerThreads, out int completionPortThreads)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               Microsoft.ThreadPool.GetMaxThreads (out workerThreads, out completionPortThreads);
-                       else
-                               GetMaxThreads_internal (out workerThreads, out completionPortThreads);
-               }
-
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               static extern void GetMaxThreads_internal (out int workerThreads, out int completionPortThreads);
-
-               public static void GetMinThreads (out int workerThreads, out int completionPortThreads)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               Microsoft.ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
-                       else
-                               GetMinThreads_internal (out workerThreads, out completionPortThreads);
-               }
-
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               static extern void GetMinThreads_internal (out int workerThreads, out int completionPortThreads);
-
-               [MonoTODO("The min number of completion port threads is not evaluated.")]
-               [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
-               public static bool SetMinThreads (int workerThreads, int completionPortThreads)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.SetMinThreads (workerThreads, completionPortThreads);
-                       else
-                               return SetMinThreads_internal (workerThreads, completionPortThreads);
-               }
-
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               static extern bool SetMinThreads_internal (int workerThreads, int completionPortThreads);
-
-               [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
-               public static bool SetMaxThreads (int workerThreads, int completionPortThreads)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.SetMaxThreads (workerThreads, completionPortThreads);
-                       else
-                               return SetMaxThreads_internal (workerThreads, completionPortThreads);
-               }
-
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               static extern bool SetMaxThreads_internal (int workerThreads, int completionPortThreads);
-
-               public static bool QueueUserWorkItem (WaitCallback callBack)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.QueueUserWorkItem (callBack, null);
-                       else
-                               return QueueUserWorkItem (callBack, null);
-               }
-
-               public static bool QueueUserWorkItem (WaitCallback callBack, object state)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool) {
-                               return Microsoft.ThreadPool.QueueUserWorkItem (callBack, state);
-                       } else {
-                               if (callBack == null)
-                                       throw new ArgumentNullException ("callBack");
-
-                               if (callBack.IsTransparentProxy ()) {
-                                       IAsyncResult ar = callBack.BeginInvoke (state, null, null);
-                                       if (ar == null)
-                                               return false;
-                               } else {
-                                       AsyncResult ares = new AsyncResult (callBack, state, !ExecutionContext.IsFlowSuppressed());
-                                       pool_queue (ares);
-                               }
-                               return true;
-                       }
-               }
-
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               static extern void pool_queue (AsyncResult ares);
-
-               // TODO: It should be interface interface only to avoid extra allocation
-               internal static void QueueWorkItem (WaitCallback callBack, object state)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               Microsoft.ThreadPool.QueueUserWorkItem (callBack, state);
-                       else
-                               pool_queue (new AsyncResult (callBack, state, false));
-               }
-
-               public static RegisteredWaitHandle RegisterWaitForSingleObject (WaitHandle waitObject,
-                                                                               WaitOrTimerCallback callBack,
-                                                                               object state,
-                                                                               int millisecondsTimeOutInterval,
-                                                                               bool executeOnlyOnce)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.RegisterWaitForSingleObject (waitObject, callBack, state, millisecondsTimeOutInterval, executeOnlyOnce);
-                       else
-                               return RegisterWaitForSingleObject (waitObject, callBack, state, (long) millisecondsTimeOutInterval, executeOnlyOnce);
-               }
-
-               public static RegisteredWaitHandle RegisterWaitForSingleObject (WaitHandle waitObject,
-                                                                               WaitOrTimerCallback callBack,
-                                                                               object state,
-                                                                               long millisecondsTimeOutInterval,
-                                                                               bool executeOnlyOnce)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool) {
-                               return Microsoft.ThreadPool.RegisterWaitForSingleObject (waitObject, callBack, state, millisecondsTimeOutInterval, executeOnlyOnce);
-                       } else {
-                               if (waitObject == null)
-                                       throw new ArgumentNullException ("waitObject");
-
-                               if (callBack == null)
-                                       throw new ArgumentNullException ("callBack");
-                       
-                               if (millisecondsTimeOutInterval < -1)
-                                       throw new ArgumentOutOfRangeException ("timeout", "timeout < -1");
-
-                               if (millisecondsTimeOutInterval > Int32.MaxValue)
-                                       throw new NotSupportedException ("Timeout is too big. Maximum is Int32.MaxValue");
-
-                               TimeSpan timeout = new TimeSpan (0, 0, 0, 0, (int) millisecondsTimeOutInterval);
-                       
-                               RegisteredWaitHandle waiter = new RegisteredWaitHandle (waitObject, callBack, state,
-                                                                                       timeout, executeOnlyOnce);
-                               QueueUserWorkItem (new WaitCallback (waiter.Wait), null);
-                               return waiter;
-                       }
-               }
-
-               public static RegisteredWaitHandle RegisterWaitForSingleObject (WaitHandle waitObject,
-                                                                               WaitOrTimerCallback callBack,
-                                                                               object state,
-                                                                               TimeSpan timeout,
-                                                                               bool executeOnlyOnce)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.RegisterWaitForSingleObject (waitObject, callBack, state, timeout, executeOnlyOnce);
-                       else
-                               return RegisterWaitForSingleObject (waitObject, callBack, state, (long) timeout.TotalMilliseconds, executeOnlyOnce);
-
-               }
-
-               [CLSCompliant(false)]
-               public static RegisteredWaitHandle RegisterWaitForSingleObject (WaitHandle waitObject,
-                                                                               WaitOrTimerCallback callBack,
-                                                                               object state,
-                                                                               uint millisecondsTimeOutInterval,
-                                                                               bool executeOnlyOnce)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.RegisterWaitForSingleObject (waitObject, callBack, state, millisecondsTimeOutInterval, executeOnlyOnce);
-                       else
-                               return RegisterWaitForSingleObject (waitObject, callBack, state, (long) millisecondsTimeOutInterval, executeOnlyOnce);
-               }
-
-               [CLSCompliant (false)]
-               unsafe public static bool UnsafeQueueNativeOverlapped (NativeOverlapped *overlapped)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.UnsafeQueueNativeOverlapped (overlapped);
-                       else
-                               throw new NotImplementedException ();
-               }
-
-#if !NET_2_1 || MOBILE
-
-               [SecurityPermission (SecurityAction.Demand, ControlEvidence=true, ControlPolicy=true)]
-               public static bool UnsafeQueueUserWorkItem (WaitCallback callBack, object state)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool) {
-                               return Microsoft.ThreadPool.UnsafeQueueUserWorkItem (callBack, state);
-                       } else {
-                               if (callBack == null)
-                                       throw new ArgumentNullException ("callBack");
-
-                               // no stack propagation here (that's why it's unsafe and requires extra security permissions)
-                               if (!callBack.IsTransparentProxy ()) {
-                                       AsyncResult ares = new AsyncResult (callBack, state, false);
-                                       pool_queue (ares);
-                                       return true;
-                               }
-                               try {
-                                       if (!ExecutionContext.IsFlowSuppressed ())
-                                               ExecutionContext.SuppressFlow (); // on current thread only
-                                       IAsyncResult ar = callBack.BeginInvoke (state, null, null);
-                                       if (ar == null)
-                                               return false;
-                               } finally {
-                                       if (ExecutionContext.IsFlowSuppressed ())
-                                               ExecutionContext.RestoreFlow ();
-                               }
-                               return true;
-                       }
-               }
-               
-               [MonoTODO("Not implemented")]
-               [SecurityPermission (SecurityAction.Demand, ControlEvidence=true, ControlPolicy=true)]
-               public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject (WaitHandle waitObject,
-                       WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval,
-                       bool executeOnlyOnce) 
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.UnsafeRegisterWaitForSingleObject (waitObject, callBack, state, millisecondsTimeOutInterval, executeOnlyOnce);
-                       else
-                               throw new NotImplementedException ();
-               }
-               
-               [MonoTODO("Not implemented")]
-               [SecurityPermission (SecurityAction.Demand, ControlEvidence=true, ControlPolicy=true)]
-               public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject (WaitHandle waitObject,
-                       WaitOrTimerCallback callBack, object state, long millisecondsTimeOutInterval,
-                       bool executeOnlyOnce) 
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.UnsafeRegisterWaitForSingleObject (waitObject, callBack, state, millisecondsTimeOutInterval, executeOnlyOnce);
-                       else
-                               throw new NotImplementedException ();
-               }
-
-               [MonoTODO("Not implemented")]
-               [SecurityPermission (SecurityAction.Demand, ControlEvidence=true, ControlPolicy=true)]
-               public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject (WaitHandle waitObject,
-                       WaitOrTimerCallback callBack, object state, TimeSpan timeout,
-                       bool executeOnlyOnce) 
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.UnsafeRegisterWaitForSingleObject (waitObject, callBack, state, timeout, executeOnlyOnce);
-                       else
-                               throw new NotImplementedException ();
-               }
-
-               [MonoTODO("Not implemented")]
-               [CLSCompliant (false)]
-               [SecurityPermission (SecurityAction.Demand, ControlEvidence=true, ControlPolicy=true)]
-               public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject (WaitHandle waitObject,
-                       WaitOrTimerCallback callBack, object state, uint millisecondsTimeOutInterval,
-                       bool executeOnlyOnce) 
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.UnsafeRegisterWaitForSingleObject (waitObject, callBack, state, millisecondsTimeOutInterval, executeOnlyOnce);
-                       else
-                               throw new NotImplementedException ();
-               }
-
-#endif
-
-#region ReferenceSources
-               // Extracted from ../../../../external/referencesource/mscorlib/system/threading/threadpool.cs
-               internal static void UnsafeQueueCustomWorkItem(IThreadPoolWorkItem workItem, bool forceGlobal)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               Microsoft.ThreadPool.UnsafeQueueCustomWorkItem (workItem, forceGlobal);
-                       else
-                               QueueWorkItem ((obj) => ((IThreadPoolWorkItem)obj).ExecuteWorkItem (), workItem);
-               }
-
-               internal static IEnumerable<IThreadPoolWorkItem> GetQueuedWorkItems()
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.GetQueuedWorkItems ();
-                       else
-                               return new IThreadPoolWorkItem [0];
-               }
-
-               internal static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               return Microsoft.ThreadPool.TryPopCustomWorkItem (workItem);
-                       else
-                               return false;
-               }
-
-               internal static void NotifyWorkItemProgress()
-               {
-                       if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
-                               Microsoft.ThreadPool.NotifyWorkItemProgress ();
-               }
-#endregion
-       }
-}
index 576b7380707efa5f84e1d5a0cbf06495c71822c7..4d8f1bf0ddace880834887a756e0b5f4aea2b91a 100644 (file)
@@ -1807,6 +1807,28 @@ public class AssemblyNameTest {
                }
        }
 
+       [Test] // ctor (String)
+       public void Constructor1_Quoted ()
+       {
+               AssemblyName an;
+
+               an = new AssemblyName ("'System', Version=\"10.0.0.0\", Culture='Neutral', PublicKeyToken='b67a5c561934e089', Retargetable='Yes', ProcessorArchitecture='AMD64'");
+               Assert.AreEqual ("System, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b67a5c561934e089, Retargetable=Yes", an.ToString ());
+               Assert.AreEqual (ProcessorArchitecture.Amd64, an.ProcessorArchitecture, "Amd64");
+       }
+
+       [Test] // ctor (String)
+       public void Constructor1_Quoted_Invalid ()
+       {
+               AssemblyName an;
+
+               try {
+                       an = new AssemblyName ("System, Version=\"10.0.0.0'");
+                       Assert.Fail ("#1");
+               } catch (FileLoadException) {
+               }
+       }
+
        [Test (Description="Xamarin bug #99 - whitespaces in key=value")]
        public void WhiteSpaceInKeyValue ()
        {
index 49af23097c821009566f39ac66b60b723b58fe1a..dd38e16b7e52e7588d05cdbb637b9ae47da88b5b 100644 (file)
@@ -48,6 +48,7 @@ namespace MonoTests.System.Reflection
                {
                        Type type = typeof (TestClass);
                        PropertyInfo property = type.GetProperty ("ReadOnlyProperty");
+                       Assert.IsNotNull (property.Module, "#0");
 
                        MethodInfo [] methods = property.GetAccessors (true);
                        Assert.AreEqual (1, methods.Length, "#A1");
@@ -497,8 +498,20 @@ namespace MonoTests.System.Reflection
                        Assert.AreEqual (typeof (ClassWithNullableDateTime), siblingProperty.DeclaringType, "#3");
                        Assert.AreEqual (typeof (InheritsFromClassWithNullableDateTime), siblingProperty.ReflectedType, "#4");
                }
-               
-       
+
+               class Super { public long A { get; private set; } }
+
+               class Sub : Super { }
+
+               [Test]
+               public void PrivateSetterFromDerivedType ()
+               {
+                       var prop = typeof (Sub).GetProperty ("A");
+                       Assert.AreEqual (1, prop.GetAccessors (true).Length, "#1");
+                       Assert.IsFalse (prop.CanWrite, "#2");
+                       Assert.IsNull (prop.GetSetMethod (true), "#3");
+               }
+
                public class ClassWithNullableDateTime
                {
                        public DateTime? Property1 { get; set; }
index 9bfc1c131eaa41121183797895077b5a4f308e8f..53921d2e13f30f80360c47ddd904bd3b26d20f8b 100644 (file)
@@ -800,15 +800,17 @@ namespace MonoTests.System.Threading
                [Test]
                public void Test_Interrupt ()
                {
+                       ManualResetEvent mre = new ManualResetEvent (false);
                        bool interruptedExceptionThrown = false;
+
                        ThreadPool.QueueUserWorkItem (Test_Interrupt_Worker, Thread.CurrentThread);
 
                        try {
                                try {
-                                       Thread.Sleep (3000);
+                                       mre.WaitOne (3000);
                                } finally {
                                        try {
-                                               Thread.Sleep (0);
+                                               mre.WaitOne (0);
                                        } catch (ThreadInterruptedException) {
                                                Assert.Fail ("ThreadInterruptedException thrown twice");
                                        }
@@ -838,11 +840,12 @@ namespace MonoTests.System.Threading
                [Category ("NotDotNet")] // it crashes nunit.
                public void Test_InterruptCurrentThread ()
                {
+                       ManualResetEvent mre = new ManualResetEvent (false);
                        bool interruptedExceptionThrown = false;
 
                        Thread.CurrentThread.Interrupt ();
                        try {
-                               Thread.Sleep (0);
+                               mre.WaitOne (0);
                                Assert.Fail ();
                        } catch (ThreadInterruptedException) {
                        }
index b4e797bb4862e719636307c75db6f1866a5c178c..558b0a6e07d58a45955705dae2bfb14803da8968 100644 (file)
@@ -884,8 +884,10 @@ namespace Mono.CSharp
                                } else {
                                        Builder.Save (module.Builder.ScopeName, pekind, machine);
                                }
+                       } catch (ArgumentOutOfRangeException) {
+                               Report.Error (16, "Output file `{0}' exceeds the 4GB limit");
                        } catch (Exception e) {
-                               Report.Error (16, "Could not write to file `" + name + "', cause: " + e.Message);
+                               Report.Error (16, "Could not write to file `{0}'. {1}", name, e.Message);
                        }
                        Compiler.TimeReporter.Stop (TimeReporter.TimerType.OutputSave);
 
index 88e523700706480b073713dc308dcdc7b8a31625..fbb21d0096f48e8fa1165057ec3e7d3beab341f6 100644 (file)
@@ -497,7 +497,7 @@ namespace Mono.CSharp
                        }
 
                        foreach (var existing in das) {
-                               if (DefiniteAssignmentBitSet.AreEqual (existing, DefiniteAssignment))
+                               if (DefiniteAssignmentBitSet.IsIncluded (existing, DefiniteAssignment))
                                        return true;
                        }
 
index 518e2c5ab8f6d659c4aa15361c6eb008b935d96f..02f6f3df77494ae11eec7fda3dd1b388fd94fc9b 100644 (file)
@@ -240,6 +240,7 @@ namespace Mono.CSharp
                public bool parsing_catch_when;
 
                int parsing_string_interpolation;
+               int string_interpolation_section;
                Stack<bool> parsing_string_interpolation_quoted;
 
                public bool parsing_interpolation_format;
@@ -411,6 +412,7 @@ namespace Mono.CSharp
                        public int current_token;
                        public object val;
                        public int parsing_string_interpolation;
+                       public int string_interpolation_section;
                        public Stack<bool> parsing_string_interpolation_quoted;
 
                        public Position (Tokenizer t)
@@ -430,9 +432,11 @@ namespace Mono.CSharp
                                        ifstack = new Stack<int> (clone);
                                }
                                parsing_generic_less_than = t.parsing_generic_less_than;
+                               string_interpolation_section = t.string_interpolation_section;
                                current_token = t.current_token;
                                val = t.val;
                                parsing_string_interpolation = t.parsing_string_interpolation;
+                               string_interpolation_section = t.string_interpolation_section;
                                if (t.parsing_string_interpolation_quoted != null && t.parsing_string_interpolation_quoted.Count != 0) {
                                        var clone = t.parsing_string_interpolation_quoted.ToArray ();
                                        Array.Reverse (clone);
@@ -3373,18 +3377,26 @@ namespace Mono.CSharp
 
                                case '{':
                                        val = ltb.Create (current_source, ref_line, col);
+
+                                       if (parsing_string_interpolation > 0)
+                                               ++string_interpolation_section;
+
                                        return Token.OPEN_BRACE;
                                case '}':
                                        if (parsing_string_interpolation > 0) {
-                                               --parsing_string_interpolation;
-                                               bool quoted;
-                                               if (parsing_string_interpolation_quoted != null && parsing_string_interpolation_quoted.Count > 0) {
-                                                       quoted = parsing_string_interpolation_quoted.Pop ();
-                                               } else {
-                                                       quoted = false;
+                                               if (string_interpolation_section == 0) {
+                                                       --parsing_string_interpolation;
+                                                       bool quoted;
+                                                       if (parsing_string_interpolation_quoted != null && parsing_string_interpolation_quoted.Count > 0) {
+                                                               quoted = parsing_string_interpolation_quoted.Pop ();
+                                                       } else {
+                                                               quoted = false;
+                                                       }
+
+                                                       return TokenizeInterpolatedString (quoted);
                                                }
 
-                                               return TokenizeInterpolatedString (quoted);
+                                               --string_interpolation_section;
                                        }
 
                                        val = ltb.Create (current_source, ref_line, col);
index b9189c1f3d6d8aa31ef785065331a78c969c275b..267879c043b75ef8dc40f3df4f150503cd69317c 100644 (file)
@@ -552,7 +552,7 @@ namespace Mono.CSharp
 
                public static DefiniteAssignmentBitSet operator & (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
                {
-                       if (AreEqual (a, b))
+                       if (IsEqual (a, b))
                                return a;
 
                        DefiniteAssignmentBitSet res;
@@ -575,7 +575,7 @@ namespace Mono.CSharp
 
                public static DefiniteAssignmentBitSet operator | (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
                {
-                       if (AreEqual (a, b))
+                       if (IsEqual (a, b))
                                return a;
 
                        DefiniteAssignmentBitSet res;
@@ -678,7 +678,7 @@ namespace Mono.CSharp
                                large_bits[index >> 5] |= (1 << (index & 31));
                }
 
-               public static bool AreEqual (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
+               static bool IsEqual (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
                {
                        if (a.large_bits == null)
                                return (a.bits & ~copy_on_write_flag) == (b.bits & ~copy_on_write_flag);
@@ -690,5 +690,20 @@ namespace Mono.CSharp
 
                        return true;
                }
+
+               public static bool IsIncluded (DefiniteAssignmentBitSet set, DefiniteAssignmentBitSet test)
+               {
+                       var set_bits = set.large_bits;
+                       if (set_bits == null)
+                               return (set.bits & test.bits & ~copy_on_write_flag) == (set.bits & ~copy_on_write_flag);
+
+                       var test_bits = test.large_bits;
+                       for (int i = 0; i < set_bits.Length; ++i) {
+                               if ((set_bits[i] & test_bits[i]) != set_bits[i])
+                                       return false;
+                       }
+
+                       return true;
+               }
        }
 }
index 1d431c4b7580805193a4105b2dc296c7780ffdfa..75bd8b3dd3f4d86efc83ddba5fc179a76bd4082d 100644 (file)
@@ -1222,7 +1222,7 @@ namespace Mono.CSharp {
                                                //
                                                // The return type is actually Task<T> type argument
                                                //
-                                               if (expr.Type == async_type) {
+                                               if (expr.Type == async_type && async_type.TypeArguments [0] != ec.Module.PredefinedTypes.Task.TypeSpec) {
                                                        ec.Report.Error (4016, loc,
                                                                "`{0}': The return expression type of async method must be `{1}' rather than `Task<{1}>'",
                                                                ec.GetSignatureForError (), async_type.TypeArguments[0].GetSignatureForError ());
diff --git a/mcs/tests/test-async-68.cs b/mcs/tests/test-async-68.cs
new file mode 100644 (file)
index 0000000..f101c94
--- /dev/null
@@ -0,0 +1,22 @@
+using System.Threading.Tasks;
+
+class X
+{
+       public async Task ReturnsTaskAsync (Task task)
+       {
+               await task;
+       }
+
+       public async Task<Task> ReturnsTaskOfTaskAsync ()
+       {
+               var t1 = Task.FromResult (ReturnsTaskAsync (null));
+               await t1;
+               Task<Task> t2 = Task.FromResult (ReturnsTaskAsync (null));
+               return t2;
+       }
+
+       public static void Main ()
+       {
+               new X ().ReturnsTaskOfTaskAsync ().Wait ();
+       }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-interpolation-08.cs b/mcs/tests/test-interpolation-08.cs
new file mode 100644 (file)
index 0000000..f617c52
--- /dev/null
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+
+public class Program
+{
+       public static int Main ()
+       {
+               var x = $@"({
+                               new Dictionary<int, object> {
+                                       { 1, "bbb" }
+                               }.Count
+                               });";
+
+               if (x != "(1);")
+                       return 1;
+
+               return 0;
+       }
+}
\ No newline at end of file
index 55d0bf8f5a7962c38f2304fceb1edd8a6f144061..2a64b11127c258d98656489f0195317f72652589 100644 (file)
       </method>
     </type>
   </test>
+  <test name="test-async-68.cs">
+    <type name="X">
+      <method name="System.Threading.Tasks.Task ReturnsTaskAsync(System.Threading.Tasks.Task)" attrs="134">
+        <size>41</size>
+      </method>
+      <method name="System.Threading.Tasks.Task`1[System.Threading.Tasks.Task] ReturnsTaskOfTaskAsync()" attrs="134">
+        <size>41</size>
+      </method>
+      <method name="Void Main()" attrs="150">
+        <size>17</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="X+&lt;ReturnsTaskAsync&gt;c__async0">
+      <method name="Void MoveNext()" attrs="486">
+        <size>157</size>
+      </method>
+      <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+        <size>13</size>
+      </method>
+    </type>
+    <type name="X+&lt;ReturnsTaskOfTaskAsync&gt;c__async1">
+      <method name="Void MoveNext()" attrs="486">
+        <size>217</size>
+      </method>
+      <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+        <size>13</size>
+      </method>
+    </type>
+  </test>
   <test name="test-async-69.cs">
     <type name="Test">
       <method name="System.Threading.Tasks.Task`1[System.Int32] YieldValue(Int32)" attrs="145">
       </method>
     </type>
   </test>
+  <test name="test-interpolation-08.cs">
+    <type name="Program">
+      <method name="Int32 Main()" attrs="150">
+        <size>73</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-iter-01.cs">
     <type name="X">
       <method name="Int32 Main()" attrs="150">
index 2dc2bf799d94c473556fc5796cc6f619e2b5e27b..ec5c1f10aabad6e73e5b4e84fa54d1b42b21a954 100755 (executable)
@@ -156,6 +156,13 @@ class MakeBundle {
                                }
                                ctor_func = args [++i];
                                break;
+                       case "--dos2unix":
+                       case "--dos2unix=true":
+                               use_dos2unix = true;
+                               break;
+                       case "--dos2unix=false":
+                               use_dos2unix = false;
+                               break;
                        default:
                                sources.Add (args [i]);
                                break;
@@ -651,6 +658,10 @@ void          mono_register_config_for_assembly (const char* assembly_name, cons
                                   "    -L path             Adds `path' to the search path for assemblies\n" +
                                   "    --nodeps            Turns off automatic dependency embedding (default)\n" +
                                   "    --deps              Turns on automatic dependency embedding\n" +
+                                  "    --dos2unix[=true|false]\n" +
+                                  "                        When no value provided, or when `true` specified\n" +
+                                  "                        `dos2unix` will be invoked to convert paths on Windows.\n" +
+                                  "                        When `--dos2unix=false` used, dos2unix is NEVER used.\n" +
                                   "    --keeptemp          Keeps the temporary files\n" +
                                   "    --config F          Bundle system config file `F'\n" +
                                   "    --config-dir D      Set MONO_CFG_DIR to `D'\n" +
@@ -704,7 +715,6 @@ void          mono_register_config_for_assembly (const char* assembly_name, cons
                        return system (cmdLine);
                }
                
-#if XAMARIN_ANDROID
                // on Windows, we have to pipe the output of a
                // `cmd` interpolation to dos2unix, because the shell does not
                // strip the CRLFs generated by the native pkg-config distributed
@@ -733,7 +743,6 @@ void          mono_register_config_for_assembly (const char* assembly_name, cons
                }
                // and if there is no dos2unix, just run cmd /c.
                if (use_dos2unix == false) {
-#endif
                        Console.WriteLine (cmdLine);
                        ProcessStartInfo dos2unix = new ProcessStartInfo ();
                        dos2unix.UseShellExecute = false;
@@ -744,19 +753,15 @@ void          mono_register_config_for_assembly (const char* assembly_name, cons
                                p.WaitForExit ();
                                return p.ExitCode;
                        }
-#if XAMARIN_ANDROID
                }
-#endif
 
                StringBuilder b = new StringBuilder ();
                int count = 0;
                for (int i = 0; i < cmdLine.Length; i++) {
                        if (cmdLine [i] == '`') {
-#if XAMARIN_ANDROID
                                if (count % 2 != 0) {
                                        b.Append ("|dos2unix");
                                }
-#endif
                                count++;
                        }
                        b.Append (cmdLine [i]);
index 6fc37c34271a59f7da5163add23b049f802fdfa5..52ecbbb3fb53f719e83c8f14d9518385d0a148fa 100644 (file)
@@ -13,4 +13,4 @@ run-test-local : basic-tests
 
 basic-tests:
        for type in System.Array System.String 'System.Collections.Generic.List`1'; do \
-       echo $$type; $(RUNTIME) $(build_lib) $$type >/dev/null || exit 1; done
\ No newline at end of file
+       echo $$type; MONO_PATH="$(topdir)/class/lib/$(PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(RUNTIME) $(build_lib) $$type >/dev/null || exit 1; done
diff --git a/mono/arch/arm/tramp.c b/mono/arch/arm/tramp.c
deleted file mode 100644 (file)
index f736c7a..0000000
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * Create trampolines to invoke arbitrary functions.
- * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
- *
- * Contributions by Malte Hildingson
- */
-
-#include "arm-codegen.h"
-#include "arm-dis.h"
-
-#if defined(_WIN32_WCE) || defined (UNDER_CE)
-#      include <windows.h>
-#else
-#include <unistd.h>
-#include <sys/mman.h>
-#endif
-
-#if !defined(PLATFORM_MACOSX)
-#include <errno.h>
-
-#include "mono/metadata/class.h"
-#include "mono/metadata/tabledefs.h"
-#include "mono/interpreter/interp.h"
-#include "mono/metadata/appdomain.h"
-
-
-#if 0
-#      define ARM_DUMP_DISASM 1
-#endif
-
-/* prototypes for private functions (to avoid compiler warnings) */
-void flush_icache (void);
-void* alloc_code_buff (int num_instr);
-
-
-
-/*
- * The resulting function takes the form:
- * void func (void (*callme)(), void *retval, void *this_obj, stackval *arguments);
- * NOTE: all args passed in ARM registers (A1-A4),
- *       then copied to R4-R7 (see definitions below).
- */
-
-#define REG_FUNC_ADDR ARMREG_R4
-#define REG_RETVAL    ARMREG_R5
-#define REG_THIS      ARMREG_R6
-#define REG_ARGP      ARMREG_R7
-
-
-#define ARG_SIZE sizeof(stackval)
-
-
-
-
-void flush_icache ()
-{
-#if defined(_WIN32)
-       FlushInstructionCache(GetCurrentProcess(), NULL, 0);
-#else
-# if 0
-       asm ("mov r0, r0");
-       asm ("mov r0, #0");
-       asm ("mcr p15, 0, r0, c7, c7, 0");
-# else
-       /* TODO: use (movnv  pc, rx) method */
-# endif
-#endif
-}
-
-
-void* alloc_code_buff (int num_instr)
-{
-       void* code_buff;
-       int code_size = num_instr * sizeof(arminstr_t);
-
-#if defined(_WIN32) || defined(UNDER_CE)
-       int old_prot = 0;
-
-       code_buff = malloc(code_size);
-       VirtualProtect(code_buff, code_size, PAGE_EXECUTE_READWRITE, &old_prot);
-#else
-       int page_size = sysconf(_SC_PAGESIZE);
-       int new_code_size;
-
-       new_code_size = code_size + page_size - 1;
-       code_buff = malloc(new_code_size);
-       code_buff = (void *) (((int) code_buff + page_size - 1) & ~(page_size - 1));
-
-       if (mprotect(code_buff, code_size, PROT_READ|PROT_WRITE|PROT_EXEC) != 0) {
-               g_critical (G_GNUC_PRETTY_FUNCTION
-                               ": mprotect error: %s", g_strerror (errno));
-       }
-#endif
-
-       return code_buff;
-}
-
-
-/*
- * Refer to ARM Procedure Call Standard (APCS) for more info.
- */
-MonoPIFunc mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
-{
-       MonoType* param;
-       MonoPIFunc code_buff;
-       arminstr_t* p;
-       guint32 code_size, stack_size;
-       guint32 simple_type;
-       int i, hasthis, aregs, regc, stack_offs;
-       int this_loaded;
-       guchar reg_alloc [ARM_NUM_ARG_REGS];
-
-       /* pessimistic estimation for prologue/epilogue size */
-       code_size = 16 + 16;
-       /* push/pop work regs */
-       code_size += 2; 
-       /* call */
-       code_size += 2;
-       /* handle retval */
-       code_size += 2;
-
-       stack_size = 0;
-       hasthis = sig->hasthis ? 1 : 0;
-
-       aregs = ARM_NUM_ARG_REGS - hasthis;
-
-       for (i = 0, regc = aregs; i < sig->param_count; ++i) {
-               param = sig->params [i];
-
-               /* keep track of argument sizes */
-               if (i < ARM_NUM_ARG_REGS) reg_alloc [i] = 0;
-
-               if (param->byref) {
-                       if (regc > 0) {
-                               code_size += 1;
-                               reg_alloc [i] = regc;
-                               --regc;
-                       } else {
-                               code_size += 2;
-                               stack_size += sizeof(gpointer);
-                       }
-               } else {
-                       simple_type = param->type;
-enum_calc_size:
-                       switch (simple_type) {
-                       case MONO_TYPE_BOOLEAN:
-                       case MONO_TYPE_CHAR:
-                       case MONO_TYPE_I1:
-                       case MONO_TYPE_U1:
-                       case MONO_TYPE_I2:
-                       case MONO_TYPE_U2:
-                       case MONO_TYPE_I4:
-                       case MONO_TYPE_U4:
-                       case MONO_TYPE_I:
-                       case MONO_TYPE_U:
-                       case MONO_TYPE_PTR:
-                       case MONO_TYPE_R4:
-                       case MONO_TYPE_SZARRAY:
-                       case MONO_TYPE_CLASS:
-                       case MONO_TYPE_OBJECT:
-                       case MONO_TYPE_STRING:
-                               if (regc > 0) {
-                                       /* register arg */
-                                       code_size += 1;
-                                       reg_alloc [i] = regc;
-                                       --regc;
-                               } else {
-                                       /* stack arg */
-                                       code_size += 2;
-                                       stack_size += 4;
-                               }
-                               break;
-                       case MONO_TYPE_I8:
-                       case MONO_TYPE_U8:
-                       case MONO_TYPE_R8:
-                               /* keep track of argument sizes */
-                               if (regc > 1) {
-                                       /* fits into registers, two LDRs */
-                                       code_size += 2;
-                                       reg_alloc [i] = regc;
-                                       regc -= 2;
-                               } else if (regc > 0) {
-                                       /* first half fits into register, one LDR */
-                                       code_size += 1;
-                                       reg_alloc [i] = regc;
-                                       --regc;
-                                       /* the rest on the stack, LDR/STR */
-                                       code_size += 2;
-                                       stack_size += 4;
-                               } else {
-                                       /* stack arg, 4 instrs - 2x(LDR/STR) */
-                                       code_size += 4;
-                                       stack_size += 2 * 4;
-                               }
-                               break;
-                       case MONO_TYPE_VALUETYPE:
-                               if (param->data.klass->enumtype) {
-                                       simple_type = param->data.klass->enum_basetype->type;
-                                       goto enum_calc_size;
-                               }
-
-                               if (mono_class_value_size(param->data.klass, NULL) != 4) {
-                                       g_error("can only marshal enums, not generic structures (size: %d)", mono_class_value_size(param->data.klass, NULL));
-                               }
-                               if (regc > 0) {
-                                       /* register arg */
-                                       code_size += 1;
-                                       reg_alloc [i] = regc;
-                                       --regc;
-                               } else {
-                                       /* stack arg */
-                                       code_size += 2;
-                                       stack_size += 4;
-                               }
-                               break;
-                       default :
-                               break;
-                       }
-               }
-       }
-
-       code_buff = (MonoPIFunc)alloc_code_buff(code_size);
-       p = (arminstr_t*)code_buff;
-
-       /* prologue */
-       p = arm_emit_lean_prologue(p, stack_size,
-               /* save workset (r4-r7) */
-               (1 << ARMREG_R4) | (1 << ARMREG_R5) | (1 << ARMREG_R6) | (1 << ARMREG_R7));
-
-
-       /* copy args into workset */
-       /* callme - always present */
-       ARM_MOV_REG_REG(p, ARMREG_R4, ARMREG_A1);
-       /* retval */
-       if (sig->ret->byref || string_ctor || (sig->ret->type != MONO_TYPE_VOID)) {
-               ARM_MOV_REG_REG(p, ARMREG_R5, ARMREG_A2);
-       }
-       /* this_obj */
-       if (sig->hasthis) {
-               this_loaded = 0;
-               if (stack_size == 0) {
-                       ARM_MOV_REG_REG(p, ARMREG_A1, ARMREG_A3);
-                       this_loaded = 1;
-               } else {
-                       ARM_MOV_REG_REG(p, ARMREG_R6, ARMREG_A3);
-               }
-       }
-       /* args */
-       if (sig->param_count != 0) {
-               ARM_MOV_REG_REG(p, ARMREG_R7, ARMREG_A4);
-       }
-
-       stack_offs = stack_size;
-
-       /* handle arguments */
-       /* in reverse order so we could use r0 (arg1) for memory transfers */
-       for (i = sig->param_count; --i >= 0;) {
-               param = sig->params [i];
-               if (param->byref) {
-                       if (i < aregs && reg_alloc[i] > 0) {
-                               ARM_LDR_IMM(p, ARMREG_A1 + i, REG_ARGP, i*ARG_SIZE);
-                       } else {
-                               stack_offs -= sizeof(armword_t);
-                               ARM_LDR_IMM(p, ARMREG_R0, REG_ARGP, i*ARG_SIZE);
-                               ARM_STR_IMM(p, ARMREG_R0, ARMREG_SP, stack_offs);
-                       }
-               } else {
-                       simple_type = param->type;
-enum_marshal:
-                       switch (simple_type) {
-                       case MONO_TYPE_BOOLEAN:
-                       case MONO_TYPE_CHAR:
-                       case MONO_TYPE_I1:
-                       case MONO_TYPE_U1:
-                       case MONO_TYPE_I2:
-                       case MONO_TYPE_U2:
-                       case MONO_TYPE_I4:
-                       case MONO_TYPE_U4:
-                       case MONO_TYPE_I:
-                       case MONO_TYPE_U:
-                       case MONO_TYPE_PTR:
-                       case MONO_TYPE_R4:
-                       case MONO_TYPE_SZARRAY:
-                       case MONO_TYPE_CLASS:
-                       case MONO_TYPE_OBJECT:
-                       case MONO_TYPE_STRING:
-                               if (i < aregs && reg_alloc [i] > 0) {
-                                       /* pass in register */
-                                       ARM_LDR_IMM(p, ARMREG_A1 + hasthis + (aregs - reg_alloc [i]), REG_ARGP, i*ARG_SIZE);
-                               } else {
-                                       stack_offs -= sizeof(armword_t);
-                                       ARM_LDR_IMM(p, ARMREG_R0, REG_ARGP, i*ARG_SIZE);
-                                       ARM_STR_IMM(p, ARMREG_R0, ARMREG_SP, stack_offs);
-                               }
-                               break;
-                       case MONO_TYPE_I8:
-                       case MONO_TYPE_U8:
-                       case MONO_TYPE_R8:
-                               if (i < aregs && reg_alloc [i] > 0) {
-                                       if (reg_alloc [i] > 1) {
-                                               /* pass in registers */
-                                               ARM_LDR_IMM(p, ARMREG_A1 + hasthis + (aregs - reg_alloc [i]), REG_ARGP, i*ARG_SIZE);
-                                               ARM_LDR_IMM(p, ARMREG_A1 + hasthis + (aregs - reg_alloc [i]) + 1, REG_ARGP, i*ARG_SIZE + 4);
-                                       } else {
-                                               stack_offs -= sizeof(armword_t);
-                                               ARM_LDR_IMM(p, ARMREG_R0, REG_ARGP, i*ARG_SIZE + 4);
-                                               ARM_STR_IMM(p, ARMREG_R0, ARMREG_SP, stack_offs);
-                                               ARM_LDR_IMM(p, ARMREG_A1 + hasthis + (aregs - reg_alloc [i]), REG_ARGP, i*ARG_SIZE);
-                                       }
-                               } else {
-                                       /* two words transferred on the stack */
-                                       stack_offs -= 2*sizeof(armword_t);
-                                       ARM_LDR_IMM(p, ARMREG_R0, REG_ARGP, i*ARG_SIZE);
-                                       ARM_STR_IMM(p, ARMREG_R0, ARMREG_SP, stack_offs);
-                                       ARM_LDR_IMM(p, ARMREG_R0, REG_ARGP, i*ARG_SIZE + 4);
-                                       ARM_STR_IMM(p, ARMREG_R0, ARMREG_SP, stack_offs + 4);
-                               }
-                               break;
-                       case MONO_TYPE_VALUETYPE:
-                               if (param->data.klass->enumtype) {
-                                       /* it's an enum value, proceed based on its base type */
-                                       simple_type = param->data.klass->enum_basetype->type;
-                                       goto enum_marshal;
-                               } else {
-                                       if (i < aregs && reg_alloc[i] > 0) {
-                                               int vtreg = ARMREG_A1 + hasthis +
-                                                               hasthis + (aregs - reg_alloc[i]);
-                                               ARM_LDR_IMM(p, vtreg, REG_ARGP, i * ARG_SIZE);
-                                               ARM_LDR_IMM(p, vtreg, vtreg, 0);
-                                       } else {
-                                               stack_offs -= sizeof(armword_t);
-                                               ARM_LDR_IMM(p, ARMREG_R0, REG_ARGP, i * ARG_SIZE);
-                                               ARM_LDR_IMM(p, ARMREG_R0, ARMREG_R0, 0);
-                                               ARM_STR_IMM(p, ARMREG_R0, ARMREG_SP, stack_offs);
-                                       }
-                               }
-                               break;
-
-                       default:
-                               break;
-                       }
-               }
-       }
-
-       if (sig->hasthis && !this_loaded) {
-               /* [this] always passed in A1, regardless of sig->call_convention */
-               ARM_MOV_REG_REG(p, ARMREG_A1, REG_THIS);
-       }
-
-       /* call [func] */
-       ARM_MOV_REG_REG(p, ARMREG_LR, ARMREG_PC);
-       ARM_MOV_REG_REG(p, ARMREG_PC, REG_FUNC_ADDR);
-
-       /* handle retval */
-       if (sig->ret->byref || string_ctor) {
-               ARM_STR_IMM(p, ARMREG_R0, REG_RETVAL, 0);
-       } else {
-               simple_type = sig->ret->type;
-enum_retvalue:
-               switch (simple_type) {
-               case MONO_TYPE_BOOLEAN:
-               case MONO_TYPE_I1:
-               case MONO_TYPE_U1:
-                       ARM_STRB_IMM(p, ARMREG_R0, REG_RETVAL, 0);
-                       break;
-               case MONO_TYPE_CHAR:
-               case MONO_TYPE_I2:
-               case MONO_TYPE_U2:
-                       ARM_STRH_IMM(p, ARMREG_R0, REG_RETVAL, 0);
-                       break;
-               /*
-                * A 32-bit integer and integer-equivalent return value
-                * is returned in R0.
-                * Single-precision floating-point values are returned in R0.
-                */
-               case MONO_TYPE_I:
-               case MONO_TYPE_U:
-               case MONO_TYPE_I4:
-               case MONO_TYPE_U4:
-               case MONO_TYPE_R4:
-               case MONO_TYPE_OBJECT:
-               case MONO_TYPE_CLASS:
-               case MONO_TYPE_ARRAY:
-               case MONO_TYPE_SZARRAY:
-               case MONO_TYPE_STRING:
-                       ARM_STR_IMM(p, ARMREG_R0, REG_RETVAL, 0);
-                       break;
-               /*
-                * A 64-bit integer is returned in R0 and R1.
-                * Double-precision floating-point values are returned in R0 and R1.
-                */
-               case MONO_TYPE_I8:
-               case MONO_TYPE_U8:
-               case MONO_TYPE_R8:
-                       ARM_STR_IMM(p, ARMREG_R0, REG_RETVAL, 0);
-                       ARM_STR_IMM(p, ARMREG_R1, REG_RETVAL, 4);
-                       break;
-               case MONO_TYPE_VALUETYPE:
-                       if (sig->ret->data.klass->enumtype) {
-                               simple_type = sig->ret->data.klass->enum_basetype->type;
-                               goto enum_retvalue;
-                       }
-                       break;
-               case MONO_TYPE_VOID:
-                       break;
-               default:
-                       break;
-               }
-       }
-       
-       p = arm_emit_std_epilogue(p, stack_size,
-               /* restore R4-R7 */
-               (1 << ARMREG_R4) | (1 << ARMREG_R5) | (1 << ARMREG_R6) | (1 << ARMREG_R7));
-
-       flush_icache();
-
-#ifdef ARM_DUMP_DISASM
-       _armdis_decode((arminstr_t*)code_buff, ((guint8*)p) - ((guint8*)code_buff));
-#endif
-
-       return code_buff;
-}
-
-
-
-#define MINV_OFFS(member) G_STRUCT_OFFSET(MonoInvocation, member)
-
-
-
-/*
- * Returns a pointer to a native function that can be used to
- * call the specified method.
- * The function created will receive the arguments according
- * to the call convention specified in the method.
- * This function works by creating a MonoInvocation structure,
- * filling the fields in and calling ves_exec_method on it.
- * Still need to figure out how to handle the exception stuff
- * across the managed/unmanaged boundary.
- */
-void* mono_arch_create_method_pointer (MonoMethod* method)
-{
-       MonoMethodSignature* sig;
-       guchar* p, * p_method, * p_stackval_from_data, * p_exec;
-       void* code_buff;
-       int i, stack_size, arg_pos, arg_add, stackval_pos, offs;
-       int areg, reg_args, shift, pos;
-       MonoJitInfo *ji;
-
-       code_buff = alloc_code_buff(128);
-       p = (guchar*)code_buff;
-
-       sig = method->signature;
-
-       ARM_B(p, 3);
-
-       /* embed magic number followed by method pointer */
-       *p++ = 'M';
-       *p++ = 'o';
-       *p++ = 'n';
-       *p++ = 'o';
-       /* method ptr */
-       *(void**)p = method;
-       p_method = p;
-       p += 4;
-
-       /* call table */
-       *(void**)p = stackval_from_data;
-       p_stackval_from_data = p;
-       p += 4;
-       *(void**)p = ves_exec_method;
-       p_exec = p;
-       p += 4;
-
-       stack_size = sizeof(MonoInvocation) + ARG_SIZE*(sig->param_count + 1) + ARM_NUM_ARG_REGS*2*sizeof(armword_t);
-
-       /* prologue */
-       p = (guchar*)arm_emit_lean_prologue((arminstr_t*)p, stack_size,
-           (1 << ARMREG_R4) |
-           (1 << ARMREG_R5) |
-           (1 << ARMREG_R6) |
-           (1 << ARMREG_R7));
-
-       /* R7 - ptr to stack args */
-       ARM_MOV_REG_REG(p, ARMREG_R7, ARMREG_IP);
-
-       /*
-        * Initialize MonoInvocation fields, first the ones known now.
-        */
-       ARM_MOV_REG_IMM8(p, ARMREG_R4, 0);
-       ARM_STR_IMM(p, ARMREG_R4, ARMREG_SP, MINV_OFFS(ex));
-       ARM_STR_IMM(p, ARMREG_R4, ARMREG_SP, MINV_OFFS(ex_handler));
-       ARM_STR_IMM(p, ARMREG_R4, ARMREG_SP, MINV_OFFS(parent));
-
-       /* Set the method pointer. */
-       ARM_LDR_IMM(p, ARMREG_R4, ARMREG_PC, -(int)(p - p_method + sizeof(arminstr_t)*2));
-       ARM_STR_IMM(p, ARMREG_R4, ARMREG_SP, MINV_OFFS(method));
-
-       if (sig->hasthis) {
-               /* [this] in A1 */
-               ARM_STR_IMM(p, ARMREG_A1, ARMREG_SP, MINV_OFFS(obj));
-       } else {
-               /* else set minv.obj to NULL */
-               ARM_STR_IMM(p, ARMREG_R4, ARMREG_SP, MINV_OFFS(obj));
-       }
-
-       /* copy args from registers to stack */
-       areg = ARMREG_A1 + sig->hasthis;
-       arg_pos = -(int)(ARM_NUM_ARG_REGS - sig->hasthis) * 2 * sizeof(armword_t);
-       arg_add = 0;
-       for (i = 0; i < sig->param_count; ++i) {
-               if (areg >= ARM_NUM_ARG_REGS) break;
-               ARM_STR_IMM(p, areg, ARMREG_R7, arg_pos);
-               ++areg;
-               if (!sig->params[i]->byref) {
-                       switch (sig->params[i]->type) {
-                       case MONO_TYPE_I8:
-                       case MONO_TYPE_U8:
-                       case MONO_TYPE_R8:
-                               if (areg >= ARM_NUM_ARG_REGS) {
-                                       /* load second half of 64-bit arg */
-                                       ARM_LDR_IMM(p, ARMREG_R4, ARMREG_R7, 0);
-                                       ARM_STR_IMM(p, ARMREG_R4, ARMREG_R7, arg_pos + sizeof(armword_t));
-                                       arg_add = sizeof(armword_t);
-                               } else {
-                                       /* second half is already the register */
-                                       ARM_STR_IMM(p, areg, ARMREG_R7, arg_pos + sizeof(armword_t));
-                                       ++areg;
-                               }
-                               break;
-                       case MONO_TYPE_VALUETYPE:
-                               /* assert */
-                       default:
-                               break;
-                       }
-               }
-               arg_pos += 2 * sizeof(armword_t);
-       }
-       /* number of args passed in registers */
-       reg_args = i;
-
-
-
-       /*
-        * Calc and save stack args ptr,
-        * args follow MonoInvocation struct on the stack.
-        */
-       ARM_ADD_REG_IMM8(p, ARMREG_R1, ARMREG_SP, sizeof(MonoInvocation));
-       ARM_STR_IMM(p, ARMREG_R1, ARMREG_SP, MINV_OFFS(stack_args));
-
-       /* convert method args to stackvals */
-       arg_pos = -(int)(ARM_NUM_ARG_REGS - sig->hasthis) * 2 * sizeof(armword_t);
-       stackval_pos = sizeof(MonoInvocation);
-       for (i = 0; i < sig->param_count; ++i) {
-               if (i < reg_args) {
-                       ARM_SUB_REG_IMM8(p, ARMREG_A3, ARMREG_R7, -arg_pos);
-                       arg_pos += 2 * sizeof(armword_t);
-               } else {
-                       if (arg_pos < 0) arg_pos = 0;
-                       pos = arg_pos + arg_add;
-                       if (pos <= 0xFF) {
-                               ARM_ADD_REG_IMM8(p, ARMREG_A3, ARMREG_R7, pos);
-                       } else {
-                               if (is_arm_const((armword_t)pos)) {
-                                       shift = calc_arm_mov_const_shift((armword_t)pos);
-                                       ARM_ADD_REG_IMM(p, ARMREG_A3, ARMREG_R7, pos >> ((32 - shift) & 31), shift >> 1);
-                               } else {
-                                       p = (guchar*)arm_mov_reg_imm32((arminstr_t*)p, ARMREG_R6, (armword_t)pos);
-                                       ARM_ADD_REG_REG(p, ARMREG_A2, ARMREG_R7, ARMREG_R6);
-                               }
-                       }
-                       arg_pos += sizeof(armword_t);
-                       if (!sig->params[i]->byref) {
-                               switch (sig->params[i]->type) {
-                               case MONO_TYPE_I8:
-                               case MONO_TYPE_U8:
-                               case MONO_TYPE_R8:
-                                       arg_pos += sizeof(armword_t);
-                                       break;
-                               case MONO_TYPE_VALUETYPE:
-                                       /* assert */
-                               default:
-                                       break;
-                               }
-                       }
-               }
-
-               /* A2 = result */
-               if (stackval_pos <= 0xFF) {
-                       ARM_ADD_REG_IMM8(p, ARMREG_A2, ARMREG_SP, stackval_pos);
-               } else {
-                       if (is_arm_const((armword_t)stackval_pos)) {
-                               shift = calc_arm_mov_const_shift((armword_t)stackval_pos);
-                               ARM_ADD_REG_IMM(p, ARMREG_A2, ARMREG_SP, stackval_pos >> ((32 - shift) & 31), shift >> 1);
-                       } else {
-                               p = (guchar*)arm_mov_reg_imm32((arminstr_t*)p, ARMREG_R6, (armword_t)stackval_pos);
-                               ARM_ADD_REG_REG(p, ARMREG_A2, ARMREG_SP, ARMREG_R6);
-                       }
-               }
-
-               /* A1 = type */
-               p = (guchar*)arm_mov_reg_imm32((arminstr_t*)p, ARMREG_A1, (armword_t)sig->params [i]);
-
-               stackval_pos += ARG_SIZE;
-
-               offs = -(p + 2*sizeof(arminstr_t) - p_stackval_from_data);
-               /* load function address */
-               ARM_LDR_IMM(p, ARMREG_R4, ARMREG_PC, offs);
-               /* call stackval_from_data */
-               ARM_MOV_REG_REG(p, ARMREG_LR, ARMREG_PC);
-               ARM_MOV_REG_REG(p, ARMREG_PC, ARMREG_R4);
-       }
-
-       /* store retval ptr */
-       p = (guchar*)arm_mov_reg_imm32((arminstr_t*)p, ARMREG_R5, (armword_t)stackval_pos);
-       ARM_ADD_REG_REG(p, ARMREG_R5, ARMREG_SP, ARMREG_R4);
-       ARM_STR_IMM(p, ARMREG_R5, ARMREG_SP, MINV_OFFS(retval));
-
-       /*
-        * Call the method.
-        */
-       /* A1 = MonoInvocation ptr */
-       ARM_MOV_REG_REG(p, ARMREG_A1, ARMREG_SP);
-       offs = -(p + 2*sizeof(arminstr_t) - p_exec);
-       /* load function address */
-       ARM_LDR_IMM(p, ARMREG_R4, ARMREG_PC, offs);
-       /* call ves_exec */
-       ARM_MOV_REG_REG(p, ARMREG_LR, ARMREG_PC);
-       ARM_MOV_REG_REG(p, ARMREG_PC, ARMREG_R4);
-
-
-       /*
-        * Move retval into reg.
-        */
-       if (sig->ret->byref) {
-               ARM_LDR_IMM(p, ARMREG_R0, ARMREG_R5, 0);
-       } else {
-               switch (sig->ret->type) {
-               case MONO_TYPE_BOOLEAN:
-               case MONO_TYPE_I1:
-               case MONO_TYPE_U1:
-                       ARM_LDRB_IMM(p, ARMREG_R0, ARMREG_R5, 0);
-                       break;
-               case MONO_TYPE_CHAR:
-               case MONO_TYPE_I2:
-               case MONO_TYPE_U2:
-                       ARM_LDRH_IMM(p, ARMREG_R0, ARMREG_R5, 0);
-                       break;
-               case MONO_TYPE_I:
-               case MONO_TYPE_U:
-               case MONO_TYPE_I4:
-               case MONO_TYPE_U4:
-               case MONO_TYPE_R4:
-               case MONO_TYPE_OBJECT:
-               case MONO_TYPE_CLASS:
-               case MONO_TYPE_ARRAY:
-               case MONO_TYPE_SZARRAY:
-                       ARM_LDR_IMM(p, ARMREG_R0, ARMREG_R5, 0);
-                       break;
-               case MONO_TYPE_I8:
-               case MONO_TYPE_U8:
-               case MONO_TYPE_R8:
-                       ARM_LDR_IMM(p, ARMREG_R0, ARMREG_R5, 0);
-                       ARM_LDR_IMM(p, ARMREG_R1, ARMREG_R5, 4);
-                       break;
-               case MONO_TYPE_VOID:
-               default:
-                       break;
-               }
-       }
-
-
-       p = (guchar*)arm_emit_std_epilogue((arminstr_t*)p, stack_size,
-           (1 << ARMREG_R4) |
-           (1 << ARMREG_R5) |
-           (1 << ARMREG_R6) |
-           (1 << ARMREG_R7));
-
-       flush_icache();
-
-#ifdef ARM_DUMP_DISASM
-       _armdis_decode((arminstr_t*)code_buff, ((guint8*)p) - ((guint8*)code_buff));
-#endif
-
-       ji = g_new0(MonoJitInfo, 1);
-       ji->method = method;
-       ji->code_size = ((guint8 *) p) - ((guint8 *) code_buff);
-       ji->code_start = (gpointer) code_buff;
-
-       mono_jit_info_table_add(mono_get_root_domain (), ji);
-
-       return code_buff;
-}
-
-
-/*
- * mono_create_method_pointer () will insert a pointer to the MonoMethod
- * so that the interp can easily get at the data: this function will retrieve 
- * the method from the code stream.
- */
-MonoMethod* mono_method_pointer_get (void* code)
-{
-       unsigned char* c = code;
-       /* check out magic number that follows unconditional branch */
-       if (c[4] == 'M' &&
-           c[5] == 'o' &&
-           c[6] == 'n' &&
-           c[7] == 'o') return ((MonoMethod**)code)[2];
-       return NULL;
-}
-#endif
index c938f9e4bbb9de64fcd9db711cf891aa6fdd6e68..c5d4fbeb70e94f400e7824cc1db1373a6f465094 100644 (file)
@@ -79,11 +79,8 @@ extern gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
                                                      guint32 *lowest);
 extern void _wapi_handle_unlock_handles (guint32 numhandles,
                                         gpointer *handles);
-extern int _wapi_handle_wait_signal (gboolean poll);
-extern int _wapi_handle_timedwait_signal (struct timespec *timeout, gboolean poll);
-extern int _wapi_handle_wait_signal_handle (gpointer handle, gboolean alertable);
-extern int _wapi_handle_timedwait_signal_handle (gpointer handle,
-                                                                                                struct timespec *timeout, gboolean alertable, gboolean poll);
+extern int _wapi_handle_timedwait_signal (struct timespec *timeout, gboolean poll, gboolean *alerted);
+extern int _wapi_handle_timedwait_signal_handle (gpointer handle, struct timespec *timeout, gboolean alertable, gboolean poll, gboolean *alerted);
 extern gboolean _wapi_handle_get_or_set_share (guint64 device, guint64 inode,
                                               guint32 new_sharemode,
                                               guint32 new_access,
index 3ffe49b725d17b4c76c39b7c5bd8f0c765eb1f7a..63d225aab6cfa63cf1e7ad9f665a894e4b54bfb3 100644 (file)
@@ -45,6 +45,7 @@
 
 #include <mono/utils/mono-mutex.h>
 #include <mono/utils/mono-proclib.h>
+#include <mono/utils/mono-threads.h>
 #undef DEBUG_REFS
 
 #if 0
@@ -1537,29 +1538,50 @@ static int timedwait_signal_poll_cond (pthread_cond_t *cond, mono_mutex_t *mutex
        return(ret);
 }
 
-int _wapi_handle_wait_signal (gboolean poll)
+int
+_wapi_handle_timedwait_signal (struct timespec *timeout, gboolean poll, gboolean *alerted)
 {
-       return _wapi_handle_timedwait_signal_handle (_wapi_global_signal_handle, NULL, TRUE, poll);
+       return _wapi_handle_timedwait_signal_handle (_wapi_global_signal_handle, timeout, TRUE, poll, alerted);
 }
 
-int _wapi_handle_timedwait_signal (struct timespec *timeout, gboolean poll)
+static void
+signal_handle_and_unref (gpointer handle)
 {
-       return _wapi_handle_timedwait_signal_handle (_wapi_global_signal_handle, timeout, TRUE, poll);
-}
+       pthread_cond_t *cond;
+       mono_mutex_t *mutex;
+       guint32 idx;
 
-int _wapi_handle_wait_signal_handle (gpointer handle, gboolean alertable)
-{
-       DEBUG ("%s: waiting for %p", __func__, handle);
-       
-       return _wapi_handle_timedwait_signal_handle (handle, NULL, alertable, FALSE);
+       g_assert (handle);
+
+       /* If we reach here, then interrupt token is set to the flag value, which
+        * means that the target thread is either
+        * - before the first CAS in timedwait, which means it won't enter the wait.
+        * - it is after the first CAS, so it is already waiting, or it will enter
+        *    the wait, and it will be interrupted by the broadcast. */
+       idx = GPOINTER_TO_UINT (handle);
+       cond = &_WAPI_PRIVATE_HANDLES (idx).signal_cond;
+       mutex = &_WAPI_PRIVATE_HANDLES (idx).signal_mutex;
+
+       mono_mutex_lock (mutex);
+       mono_cond_broadcast (cond);
+       mono_mutex_unlock (mutex);
+
+       _wapi_handle_unref (handle);
 }
 
-int _wapi_handle_timedwait_signal_handle (gpointer handle,
-                                                                                 struct timespec *timeout, gboolean alertable, gboolean poll)
+int
+_wapi_handle_timedwait_signal_handle (gpointer handle, struct timespec *timeout,
+               gboolean alertable, gboolean poll, gboolean *alerted)
 {
        DEBUG ("%s: waiting for %p (type %s)", __func__, handle,
                   _wapi_handle_typename[_wapi_handle_type (handle)]);
-       
+
+       if (alertable)
+               g_assert (alerted);
+
+       if (alerted)
+               *alerted = FALSE;
+
        if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) {
                if (WAPI_SHARED_HANDLE_DATA(handle).signalled == TRUE) {
                        return (0);
@@ -1593,8 +1615,12 @@ int _wapi_handle_timedwait_signal_handle (gpointer handle,
                pthread_cond_t *cond;
                mono_mutex_t *mutex;
 
-               if (alertable && !wapi_thread_set_wait_handle (handle))
-                       return 0;
+               if (alertable) {
+                       mono_thread_info_install_interrupt (signal_handle_and_unref, handle, alerted);
+                       if (*alerted)
+                               return 0;
+                       _wapi_handle_ref (handle);
+               }
 
                cond = &_WAPI_PRIVATE_HANDLES (idx).signal_cond;
                mutex = &_WAPI_PRIVATE_HANDLES (idx).signal_mutex;
@@ -1609,8 +1635,13 @@ int _wapi_handle_timedwait_signal_handle (gpointer handle,
                                res = mono_cond_wait (cond, mutex);
                }
 
-               if (alertable)
-                       wapi_thread_clear_wait_handle (handle);
+               if (alertable) {
+                       mono_thread_info_uninstall_interrupt (alerted);
+                       if (!*alerted) {
+                               /* if it is alerted, then the handle is unref in the interrupt callback */
+                               _wapi_handle_unref (handle);
+                       }
+               }
 
                return res;
        }
index 418ba46dcc3b5b325b0f07badd224c58ac1d3872..1391f67f57ac0180e6b4e8fa0e88d252be6dd13a 100644 (file)
@@ -554,6 +554,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                        WapiStartupInfo *startup,
                        WapiProcessInformation *process_info)
 {
+#if defined (HAVE_FORK) && defined (HAVE_EXECVE)
        char *cmd = NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL;
        char *dir = NULL, **env_strings = NULL, **argv = NULL;
        guint32 i, env_count = 0;
@@ -1098,6 +1099,10 @@ free_strings:
        mono_processes_cleanup ();
        
        return ret;
+#else
+       SetLastError (ERROR_NOT_SUPPORTED);
+       return FALSE;
+#endif // defined (HAVE_FORK) && defined (HAVE_EXECVE)
 }
                
 static void
index e9f8f9c8813af499e66b6191b97b1c37e6c400c8..3ea1af1197884f7efaa31af5c52d7e52b970c7d5 100644 (file)
 
 extern struct _WapiHandleOps _wapi_thread_ops;
 
-#define INTERRUPTION_REQUESTED_HANDLE (gpointer)0xFFFFFFFE
-
 struct _WapiHandle_thread
 {
        pthread_t id;
        GPtrArray *owned_mutexes;
-       /* 
-     * Handle this thread waits on. If this is INTERRUPTION_REQUESTED_HANDLE,
-        * it means the thread is interrupted by another thread, and shouldn't enter
-        * a wait.
-        * This also acts as a reference for the handle.
-        */
-       gpointer wait_handle;
 };
 
 typedef struct _WapiHandle_thread WapiHandle_thread;
 
-extern gboolean _wapi_thread_apc_pending (gpointer handle);
 extern gboolean _wapi_thread_cur_apc_pending (void);
 extern void _wapi_thread_own_mutex (gpointer mutex);
 extern void _wapi_thread_disown_mutex (gpointer mutex);
index 13b6bd1401f0b9192d258690f512272d7176e71e..a756a40fb64a7f42dd96e4b70bcda5252afd34eb 100644 (file)
@@ -30,14 +30,6 @@ extern gsize GetCurrentThreadId(void); /* NB return is 32bit in MS API */
 extern void Sleep(guint32 ms);
 extern guint32 SleepEx(guint32 ms, gboolean alertable);
 
-void wapi_clear_interruption (void);
-gboolean wapi_thread_set_wait_handle (gpointer handle);
-void wapi_thread_clear_wait_handle (gpointer handle);
-void wapi_self_interrupt (void);
-
-gpointer wapi_prepare_interrupt_thread (gpointer thread_handle);
-void wapi_finish_interrupt_thread (gpointer wait_handle);
-
 gpointer wapi_create_thread_handle (void);
 void wapi_thread_handle_set_exited (gpointer handle, guint32 exitstatus);
 void wapi_ref_thread_handle (gpointer handle);
index 8bdf39bdbf8ac54d05257c7365b73feb8b902b94..42fc96fe4fb6ad14bdeb451437b48b1bc0b0ac53 100644 (file)
@@ -130,12 +130,10 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
 
                ret = _wapi_handle_ops_special_wait (handle, timeout, alertable);
        
-               if (alertable && _wapi_thread_apc_pending (current_thread)) {
-                       apc_pending = TRUE;
+               if (alertable && _wapi_thread_cur_apc_pending ())
                        ret = WAIT_IO_COMPLETION;
-               }
 
-               goto check_pending;
+               return ret;
        }
        
        
@@ -153,13 +151,7 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
                        goto done;
                }
        }
-       
-       if (alertable && _wapi_thread_apc_pending (current_thread)) {
-               apc_pending = TRUE;
-               ret = WAIT_IO_COMPLETION;
-               goto done;
-       }
-       
+
        if (own_if_signalled (handle) == TRUE) {
                DEBUG ("%s: handle %p already signalled", __func__,
                           handle);
@@ -189,15 +181,8 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
                        ret = WAIT_OBJECT_0;
                        goto done;
                }
-                       
-               if (timeout == INFINITE) {
-                       waited = _wapi_handle_wait_signal_handle (handle, alertable);
-               } else {
-                       waited = _wapi_handle_timedwait_signal_handle (handle, &abstime, alertable, FALSE);
-               }
-       
-               if (alertable)
-                       apc_pending = _wapi_thread_apc_pending (current_thread);
+
+               waited = _wapi_handle_timedwait_signal_handle (handle, timeout == INFINITE ? NULL : &abstime, alertable, FALSE, &apc_pending);
 
                if(waited==0 && !apc_pending) {
                        /* Condition was signalled, so hopefully
@@ -220,19 +205,15 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
        DEBUG ("%s: wait on handle %p error: %s", __func__, handle,
                   strerror (waited));
 
-       ret = WAIT_TIMEOUT;
-       
+       ret = apc_pending ? WAIT_IO_COMPLETION : WAIT_TIMEOUT;
+
 done:
 
        DEBUG ("%s: unlocking handle %p", __func__, handle);
        
        thr_ret = _wapi_handle_unlock_handle (handle);
        g_assert (thr_ret == 0);
-       
-check_pending:
-       if (apc_pending)
-               ret = WAIT_IO_COMPLETION;
-               
+
        return(ret);
 }
 
@@ -351,13 +332,7 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
                        goto done;
                }
        }
-       
-       if (alertable && _wapi_thread_apc_pending (current_thread)) {
-               apc_pending = TRUE;
-               ret = WAIT_IO_COMPLETION;
-               goto done;
-       }
-       
+
        if (own_if_signalled (wait)) {
                DEBUG ("%s: handle %p already signalled", __func__, wait);
 
@@ -381,16 +356,8 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
                        ret = WAIT_OBJECT_0;
                        goto done;
                }
-               
-               if (timeout == INFINITE) {
-                       waited = _wapi_handle_wait_signal_handle (wait, alertable);
-               } else {
-                       waited = _wapi_handle_timedwait_signal_handle (wait, &abstime, alertable, FALSE);
-               }
 
-               if (alertable) {
-                       apc_pending = _wapi_thread_apc_pending (current_thread);
-               }
+               waited = _wapi_handle_timedwait_signal_handle (wait, timeout == INFINITE ? NULL : &abstime, alertable, FALSE, &apc_pending);
 
                if (waited==0 && !apc_pending) {
                        /* Condition was signalled, so hopefully
@@ -413,8 +380,8 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
        DEBUG ("%s: wait on handle %p error: %s", __func__, wait,
                   strerror (ret));
 
-       ret = WAIT_TIMEOUT;
-       
+       ret = apc_pending ? WAIT_IO_COMPLETION : WAIT_TIMEOUT;
+
 done:
 
        DEBUG ("%s: unlocking handle %p", __func__, wait);
@@ -422,9 +389,6 @@ done:
        thr_ret = _wapi_handle_unlock_handle (wait);
        g_assert (thr_ret == 0);
 
-       if (apc_pending)
-               ret = WAIT_IO_COMPLETION;
-       
        return(ret);
 }
 
@@ -500,6 +464,7 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
        guint32 retval;
        gboolean poll;
        gpointer sorted_handles [MAXIMUM_WAIT_OBJECTS];
+       gboolean apc_pending = FALSE;
        
        if (current_thread == NULL) {
                SetLastError (ERROR_INVALID_HANDLE);
@@ -590,9 +555,6 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
                _wapi_calc_timeout (&abstime, timeout);
        }
 
-       if (alertable && _wapi_thread_apc_pending (current_thread))
-               return WAIT_IO_COMPLETION;
-       
        for (i = 0; i < numobjects; i++) {
                /* Add a reference, as we need to ensure the handle wont
                 * disappear from under us while we're waiting in the loop
@@ -633,11 +595,7 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
                
                if (!done) {
                        /* Enter the wait */
-                       if (timeout == INFINITE) {
-                               ret = _wapi_handle_wait_signal (poll);
-                       } else {
-                               ret = _wapi_handle_timedwait_signal (&abstime, poll);
-                       }
+                       ret = _wapi_handle_timedwait_signal (timeout == INFINITE ? NULL : &abstime, poll, &apc_pending);
                } else {
                        /* No need to wait */
                        ret = 0;
@@ -648,7 +606,7 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
                thr_ret = _wapi_handle_unlock_signal_mutex (NULL);
                g_assert (thr_ret == 0);
                
-               if (alertable && _wapi_thread_apc_pending (current_thread)) {
+               if (alertable && apc_pending) {
                        retval = WAIT_IO_COMPLETION;
                        break;
                }
index 90a8cc4ffa855b6690c0895b78f9778b096f8b1b..910cb9af35920e3edf5933eb1939a13ea0bc4a09 100644 (file)
@@ -243,7 +243,7 @@ SleepEx (guint32 ms, gboolean alertable)
        if (alertable) {
                current_thread = get_current_thread_handle ();
                
-               if (_wapi_thread_apc_pending (current_thread))
+               if (_wapi_thread_cur_apc_pending ())
                        return WAIT_IO_COMPLETION;
        }
        
@@ -271,7 +271,7 @@ SleepEx (guint32 ms, gboolean alertable)
        while (TRUE) {
                ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &target, NULL);
 
-               if (alertable && _wapi_thread_apc_pending (current_thread))
+               if (alertable && _wapi_thread_cur_apc_pending ())
                        return WAIT_IO_COMPLETION;
 
                if (ret == 0)
@@ -288,7 +288,7 @@ again:
        memset (&rem, 0, sizeof (rem));
        ret=nanosleep(&req, &rem);
 
-       if (alertable && _wapi_thread_apc_pending (current_thread))
+       if (alertable && _wapi_thread_cur_apc_pending ())
                return WAIT_IO_COMPLETION;
        
        if(ret==-1) {
@@ -316,182 +316,7 @@ Sleep(guint32 ms)
 gboolean
 _wapi_thread_cur_apc_pending (void)
 {
-       return _wapi_thread_apc_pending (get_current_thread_handle ());
-}
-
-gboolean
-_wapi_thread_apc_pending (gpointer handle)
-{
-       WapiHandle_thread *thread;
-
-       thread = lookup_thread (handle);
-       
-       return thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE;
-}
-
-/*
- * wapi_interrupt_thread:
- *
- * The state of the thread handle HANDLE is set to 'interrupted' which means that
- * if the thread calls one of the WaitFor functions, the function will return with 
- * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
- * this function was called, the wait will be broken.
- * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
- * target thread didn't receive the interrupt signal yet, in this case it should
- * call the wait function again. This essentially means that the target thread will
- * busy wait until it is ready to process the interruption.
- */
-gpointer
-wapi_prepare_interrupt_thread (gpointer thread_handle)
-{
-       WapiHandle_thread *thread;
-       gpointer prev_handle, wait_handle;
-
-       thread = lookup_thread (thread_handle); /* FIXME this is wrong, move this whole thing to MonoThreads where it can be done lockfree */
-
-       while (TRUE) {
-               wait_handle = thread->wait_handle;
-
-               /* 
-                * Atomically obtain the handle the thread is waiting on, and
-                * change it to a flag value.
-                */
-               prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
-                                                                                                                INTERRUPTION_REQUESTED_HANDLE, wait_handle);
-               if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
-                       /* Already interrupted */
-                       return 0;
-               if (prev_handle == wait_handle)
-                       break;
-
-               /* Try again */
-       }
-
-       WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
-
-       return wait_handle;
-}
-
-void
-wapi_finish_interrupt_thread (gpointer wait_handle)
-{
-       pthread_cond_t *cond;
-       mono_mutex_t *mutex;
-       guint32 idx;
-
-       if (!wait_handle)
-               /* Not waiting */
-               return;
-
-       /* If we reach here, then wait_handle is set to the flag value, 
-        * which means that the target thread is either
-        * - before the first CAS in timedwait, which means it won't enter the
-        * wait.
-        * - it is after the first CAS, so it is already waiting, or it will 
-        * enter the wait, and it will be interrupted by the broadcast.
-        */
-       idx = GPOINTER_TO_UINT(wait_handle);
-       cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
-       mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
-
-       mono_mutex_lock (mutex);
-       mono_cond_broadcast (cond);
-       mono_mutex_unlock (mutex);
-
-       /* ref added by set_wait_handle */
-       _wapi_handle_unref (wait_handle);
-}
-
-/*
- * wapi_self_interrupt:
- *
- *   This is not part of the WIN32 API.
- * Set the 'interrupted' state of the calling thread if it's NULL.
- */
-void
-wapi_self_interrupt (void)
-{
-       gpointer wait_handle;
-
-       wait_handle = wapi_prepare_interrupt_thread (get_current_thread_handle ());
-       if (wait_handle)
-               /* ref added by set_wait_handle */
-               _wapi_handle_unref (wait_handle);
-}
-
-/*
- * wapi_clear_interruption:
- *
- *   This is not part of the WIN32 API. 
- * Clear the 'interrupted' state of the calling thread.
- * This function is signal safe
- */
-void
-wapi_clear_interruption (void)
-{
-       WapiHandle_thread *thread;
-       gpointer prev_handle;
-
-       thread = get_current_thread ();
-
-       prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
-                                                                                                        NULL, INTERRUPTION_REQUESTED_HANDLE);
-       if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
-               WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
-}
-
-/**
- * wapi_thread_set_wait_handle:
- *
- *   Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
- * if the thread is in interrupted state, and cannot start waiting.
- */
-gboolean
-wapi_thread_set_wait_handle (gpointer handle)
-{
-       WapiHandle_thread *thread;
-       gpointer prev_handle;
-
-       thread = get_current_thread ();
-
-       prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
-                                                                                                        handle, NULL);
-       if (prev_handle == NULL) {
-               /* thread->wait_handle acts as an additional reference to the handle */
-               _wapi_handle_ref (handle);
-
-               WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
-       } else {
-               g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
-               WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
-       }
-
-       return prev_handle == NULL;
-}
-
-/**
- * wapi_thread_clear_wait_handle:
- *
- *   Clear the wait handle of the current thread.
- */
-void
-wapi_thread_clear_wait_handle (gpointer handle)
-{
-       WapiHandle_thread *thread;
-       gpointer prev_handle;
-
-       thread = get_current_thread ();
-
-       prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
-                                                                                                        NULL, handle);
-       if (prev_handle == handle) {
-               _wapi_handle_unref (handle);
-               WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
-       } else {
-               /*It can be NULL if it was asynchronously cleared*/
-               g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
-               WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
-       }
+       return mono_thread_info_is_interrupt_state (mono_thread_info_current ());
 }
 
 void
@@ -524,31 +349,20 @@ wapi_current_thread_desc (void)
        WapiHandle_thread *thread;
        gpointer thread_handle;
        int i;
-       gpointer handle;
        GString* text;
        char *res;
 
        thread_handle = get_current_thread_handle ();
        thread = lookup_thread (thread_handle);
 
-       handle = thread->wait_handle;
        text = g_string_new (0);
        g_string_append_printf (text, "thread handle %p state : ", thread_handle);
 
-       if (!handle)
-               g_string_append_printf (text, "not waiting");
-       else if (handle == INTERRUPTION_REQUESTED_HANDLE)
-               g_string_append_printf (text, "interrupted state");
-       else
-               g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
+       mono_thread_info_describe_interrupt_token (mono_thread_info_current (), text);
+
        g_string_append_printf (text, " owns (");
-       for (i = 0; i < thread->owned_mutexes->len; i++) {
-               gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
-               if (i > 0)
-                       g_string_append_printf (text, ", %p", mutex);
-               else
-                       g_string_append_printf (text, "%p", mutex);
-       }
+       for (i = 0; i < thread->owned_mutexes->len; i++)
+               g_string_append_printf (text, i > 0 ? ", %p" : "%p", g_ptr_array_index (thread->owned_mutexes, i));
        g_string_append_printf (text, ")");
 
        res = text->str;
index 460c7ec00c96394aa2f58e27ebcc00fcf3c3718a..d0e6fc2fa576554f18eb5aa1984da3d40d3f4d17 100644 (file)
@@ -234,6 +234,7 @@ sgen_sources = \
        sgen-os-posix.c         \
        sgen-os-mach.c          \
        sgen-os-win32.c         \
+       sgen-os-coop.c          \
        sgen-bridge.c           \
        sgen-bridge.h           \
        sgen-bridge-internal.h  \
index 8c9320e29d599d54bb6e86842f87ff176040b3dc..2bfa5457e77c5b14d7f26180aa765d9d529840d5 100644 (file)
@@ -2366,9 +2366,9 @@ guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable)
 {
        guint32 result;
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        result = WaitForSingleObjectEx (handle, timeout, alertable);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        return result;
 }
index bd887b84f22b620cec97e9db216d7e5708d8cd99..45038289621a96ef7e59243a0f0d311c988e586b 100644 (file)
@@ -88,6 +88,8 @@ static const AssemblyVersionMap framework_assemblies [] = {
        {"I18N.Other", 0},
        {"I18N.Rare", 0},
        {"I18N.West", 0},
+       {"Microsoft.Build.Engine", 2},
+       {"Microsoft.Build.Framework", 2},
        {"Microsoft.VisualBasic", 1},
        {"Microsoft.VisualC", 1},
        {"Mono.Cairo", 0},
@@ -177,6 +179,8 @@ mono_set_corlib_data (void *data, size_t size)
 
 #endif
 
+static char* unquote (const char *str);
+
 /* This protects loaded_assemblies and image->references */
 #define mono_assemblies_lock() mono_mutex_lock (&assemblies_mutex)
 #define mono_assemblies_unlock() mono_mutex_unlock (&assemblies_mutex)
@@ -2076,11 +2080,19 @@ gboolean
 mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboolean save_public_key, gboolean *is_version_defined, gboolean *is_token_defined)
 {
        gchar *dllname;
+       gchar *dllname_uq;
        gchar *version = NULL;
+       gchar *version_uq;
        gchar *culture = NULL;
+       gchar *culture_uq;
        gchar *token = NULL;
+       gchar *token_uq;
        gchar *key = NULL;
+       gchar *key_uq;
        gchar *retargetable = NULL;
+       gchar *retargetable_uq;
+       gchar *procarch;
+       gchar *procarch_uq;
        gboolean res;
        gchar *value, *part_name;
        guint32 part_name_len;
@@ -2152,29 +2164,42 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
 
                if (part_name_len == 12 && !g_ascii_strncasecmp (part_name, "Retargetable", part_name_len)) {
                        retargetable = value;
-                       if (strlen (retargetable) == 0) {
-                               goto cleanup_and_fail;
-                       }
+                       retargetable_uq = unquote (retargetable);
+                       if (retargetable_uq != NULL)
+                               retargetable = retargetable_uq;
+
                        if (!g_ascii_strcasecmp (retargetable, "yes")) {
                                flags |= ASSEMBLYREF_RETARGETABLE_FLAG;
                        } else if (g_ascii_strcasecmp (retargetable, "no")) {
+                               free (retargetable_uq);
                                goto cleanup_and_fail;
                        }
+
+                       free (retargetable_uq);
                        tmp++;
                        continue;
                }
 
                if (part_name_len == 21 && !g_ascii_strncasecmp (part_name, "ProcessorArchitecture", part_name_len)) {
-                       if (!g_ascii_strcasecmp (value, "MSIL"))
+                       procarch = value;
+                       procarch_uq = unquote (procarch);
+                       if (procarch_uq != NULL)
+                               procarch = procarch_uq;
+
+                       if (!g_ascii_strcasecmp (procarch, "MSIL"))
                                arch = MONO_PROCESSOR_ARCHITECTURE_MSIL;
-                       else if (!g_ascii_strcasecmp (value, "X86"))
+                       else if (!g_ascii_strcasecmp (procarch, "X86"))
                                arch = MONO_PROCESSOR_ARCHITECTURE_X86;
-                       else if (!g_ascii_strcasecmp (value, "IA64"))
+                       else if (!g_ascii_strcasecmp (procarch, "IA64"))
                                arch = MONO_PROCESSOR_ARCHITECTURE_IA64;
-                       else if (!g_ascii_strcasecmp (value, "AMD64"))
+                       else if (!g_ascii_strcasecmp (procarch, "AMD64"))
                                arch = MONO_PROCESSOR_ARCHITECTURE_AMD64;
-                       else
+                       else {
+                               free (procarch_uq);
                                goto cleanup_and_fail;
+                       }
+
+                       free (procarch_uq);
                        tmp++;
                        continue;
                }
@@ -2188,8 +2213,26 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                goto cleanup_and_fail;
        }
 
-       res = build_assembly_name (dllname, version, culture, token, key, flags, arch,
-               aname, save_public_key);
+       dllname_uq = unquote (dllname);
+       version_uq = unquote (version);
+       culture_uq = unquote (culture);
+       token_uq = unquote (token);
+       key_uq = unquote (key);
+
+       res = build_assembly_name (
+               dllname_uq == NULL ? dllname : dllname_uq,
+               version_uq == NULL ? version : version_uq,
+               culture_uq == NULL ? culture : culture_uq,
+               token_uq == NULL ? token : token_uq,
+               key_uq == NULL ? key : key_uq,
+               flags, arch, aname, save_public_key);
+
+       free (dllname_uq);
+       free (version_uq);
+       free (culture_uq);
+       free (token_uq);
+       free (key_uq);
+
        g_strfreev (parts);
        return res;
 
@@ -2198,6 +2241,29 @@ cleanup_and_fail:
        return FALSE;
 }
 
+static char*
+unquote (const char *str)
+{
+       gint slen;
+       const char *end;
+
+       if (str == NULL)
+               return NULL;
+
+       slen = strlen (str);
+       if (slen < 2)
+               return NULL;
+
+       if (*str != '\'' && *str != '\"')
+               return NULL;
+
+       end = str + slen - 1;
+       if (*str != *end)
+               return NULL;
+
+       return g_strndup (str + 1, slen - 2);
+}
+
 /**
  * mono_assembly_name_parse:
  * @name: name to parse
index fef85ef11fdec152238fea699bf56750d06d556b..95d484b7912910467c4402a155ca400aa66c36a8 100644 (file)
@@ -7728,7 +7728,7 @@ search_modules (MonoImage *image, const char *name_space, const char *name)
 }
 
 static MonoClass *
-mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, MonoGHashTable* visited_images)
+mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
 {
        GHashTable *nspace_table;
        MonoImage *loaded_image;
@@ -7741,10 +7741,10 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
        mono_error_init (error);
 
        // Checking visited images avoids stack overflows when cyclic references exist.
-       if (mono_g_hash_table_lookup (visited_images, image))
+       if (g_hash_table_lookup (visited_images, image))
                return NULL;
 
-       mono_g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
+       g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
 
        if ((nested = strchr (name, '/'))) {
                int pos = nested - name;
@@ -7846,13 +7846,13 @@ MonoClass *
 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
 {
        MonoClass *klass;
-       MonoGHashTable *visited_images;
+       GHashTable *visited_images;
 
-       visited_images = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
+       visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
 
        klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
 
-       mono_g_hash_table_destroy (visited_images);
+       g_hash_table_destroy (visited_images);
 
        return klass;
 }
index 7672e4e38f3fd86bc22e3d2ebd59f407435b3a1b..14585755bc58a8baa3055a169bbf410798945802 100644 (file)
@@ -872,11 +872,7 @@ mono_cominterop_get_native_wrapper (MonoMethod *method)
 
        g_assert (method);
 
-       if (method->is_inflated) {
-               MonoMethodInflated *imethod = (MonoMethodInflated *)method;
-               cache = mono_marshal_get_cache (&imethod->owner->wrapper_caches.cominterop_wrapper_cache, mono_aligned_addr_hash, NULL);
-       } else
-               cache = mono_marshal_get_cache (&method->klass->image->wrapper_caches.cominterop_wrapper_cache, mono_aligned_addr_hash, NULL);
+       cache = mono_marshal_get_cache (&mono_method_get_wrapper_cache (method)->cominterop_wrapper_cache, mono_aligned_addr_hash, NULL);
 
        if ((res = mono_marshal_find_in_cache (cache, method)))
                return res;
@@ -988,11 +984,7 @@ mono_cominterop_get_invoke (MonoMethod *method)
        int i;
        GHashTable* cache;
        
-       if (method->is_inflated) {
-               MonoMethodInflated *imethod = (MonoMethodInflated *)method;
-               cache = mono_marshal_get_cache (&imethod->owner->wrapper_caches.cominterop_invoke_cache, mono_aligned_addr_hash, NULL);
-       } else
-               cache = mono_marshal_get_cache (&method->klass->image->wrapper_caches.cominterop_invoke_cache, mono_aligned_addr_hash, NULL);
+       cache = mono_marshal_get_cache (&mono_method_get_wrapper_cache (method)->cominterop_invoke_cache, mono_aligned_addr_hash, NULL);
 
        g_assert (method);
 
old mode 100755 (executable)
new mode 100644 (file)
index 24df067..41fa013
@@ -486,7 +486,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char *
        MonoAssembly *ass = NULL;
        MonoImageOpenStatus status = MONO_IMAGE_OK;
        const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
-       int n;
+       int n, dummy;
 
 #ifdef DEBUG_DOMAIN_UNLOAD
        debug_domain_unload = TRUE;
@@ -514,6 +514,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char *
        mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
 
        mono_gc_base_init ();
+       mono_thread_info_attach (&dummy);
 
        MONO_FAST_TLS_INIT (tls_appdomain);
        mono_native_tls_alloc (&appdomain_thread_id, NULL);
@@ -1959,9 +1960,9 @@ mono_get_aot_cache_config (void)
 void
 mono_domain_lock (MonoDomain *domain)
 {
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        mono_locks_acquire (&(domain)->lock, DomainLock);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 }
 
 void
index c4bb6df67659c364a42f5a2a2c47943bea43b63c..6f326513995b002d1d30263e77c9a0696ecd071d 100644 (file)
@@ -269,7 +269,7 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        
        *error=ERROR_SUCCESS;
        
@@ -278,7 +278,7 @@ ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
                *error=GetLastError ();
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -286,7 +286,7 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        
        *error=ERROR_SUCCESS;
        
@@ -295,7 +295,7 @@ ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
                *error=GetLastError ();
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -402,9 +402,9 @@ ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
        
        *error = ERROR_SUCCESS;
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        names = get_filesystem_entries (path, path_with_pattern, attrs, mask, error);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if (!names) {
                // If there's no array and no error, then return an empty array.
@@ -523,14 +523,14 @@ ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
        IncrementalFind *ifh = handle;
        gint32 error;
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        if (FindClose (ifh->find_handle) == FALSE){
                error = GetLastError ();
        } else
                error = ERROR_SUCCESS;
        g_free (ifh->utf8_path);
        g_free (ifh);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        return error;
 }
@@ -591,7 +591,7 @@ ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest,
                                     gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        
        *error=ERROR_SUCCESS;
 
@@ -600,7 +600,7 @@ ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest,
                *error=GetLastError ();
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -612,7 +612,7 @@ ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *
        gboolean ret;
        gunichar2 *utf16_sourceFileName = NULL, *utf16_destinationFileName = NULL, *utf16_destinationBackupFileName = NULL;
        guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        if (sourceFileName)
                utf16_sourceFileName = mono_string_chars (sourceFileName);
@@ -631,7 +631,7 @@ ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *
        if (ret == FALSE)
                *error = GetLastError ();
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return ret;
 }
 
@@ -640,7 +640,7 @@ ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
                                     MonoBoolean overwrite, gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        
        *error=ERROR_SUCCESS;
        
@@ -649,7 +649,7 @@ ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
                *error=GetLastError ();
        }
        
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -657,7 +657,7 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        
        *error=ERROR_SUCCESS;
        
@@ -666,7 +666,7 @@ ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
                *error=GetLastError ();
        }
        
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -674,7 +674,7 @@ gint32
 ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
 {
        gint32 ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        *error=ERROR_SUCCESS;
        
@@ -691,7 +691,7 @@ ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
                *error=GetLastError ();
        }
        
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -700,7 +700,7 @@ ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
                                              gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        
        *error=ERROR_SUCCESS;
        
@@ -710,7 +710,7 @@ ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
                *error=GetLastError ();
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -718,7 +718,7 @@ gint32
 ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        *error=ERROR_SUCCESS;
        
@@ -730,7 +730,7 @@ ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
                *error=GetLastError ();
        }
        
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -740,7 +740,7 @@ ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
 {
        gboolean result;
        WIN32_FILE_ATTRIBUTE_DATA data;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        *error=ERROR_SUCCESS;
        
@@ -753,7 +753,7 @@ ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
                memset (stat, 0, sizeof (MonoIOStat));
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return result;
 }
 
@@ -765,7 +765,7 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
        HANDLE ret;
        int attributes, attrs;
        gunichar2 *chars;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        chars = mono_string_chars (filename);   
        *error=ERROR_SUCCESS;
@@ -810,7 +810,7 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
                *error=GetLastError ();
        } 
        
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -818,7 +818,7 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        *error=ERROR_SUCCESS;
        
@@ -827,7 +827,7 @@ ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
                *error=GetLastError ();
        }
        
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -851,9 +851,9 @@ ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
 
        buffer = mono_array_addr (dest, guchar, dest_offset);
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        result = ReadFile (handle, buffer, count, &n, NULL);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if (!result) {
                *error=GetLastError ();
@@ -882,9 +882,9 @@ ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
        }
        
        buffer = mono_array_addr (src, guchar, src_offset);
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        result = WriteFile (handle, buffer, count, &n, NULL);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if (!result) {
                *error=GetLastError ();
@@ -899,7 +899,7 @@ ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
                                 gint32 *error)
 {
        gint32 offset_hi;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        *error=ERROR_SUCCESS;
        
@@ -911,7 +911,7 @@ ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
                *error=GetLastError ();
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return offset | ((gint64)offset_hi << 32);
 }
 
@@ -919,7 +919,7 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        *error=ERROR_SUCCESS;
        
@@ -928,7 +928,7 @@ ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
                *error=GetLastError ();
        }
        
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -937,7 +937,7 @@ ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
 {
        gint64 length;
        guint32 length_hi;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        *error=ERROR_SUCCESS;
        
@@ -946,7 +946,7 @@ ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
                *error=GetLastError ();
        }
        
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return length | ((gint64)length_hi << 32);
 }
 
@@ -1008,7 +1008,7 @@ ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
        const FILETIME *creation_filetime;
        const FILETIME *last_access_filetime;
        const FILETIME *last_write_filetime;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        *error=ERROR_SUCCESS;
        
@@ -1032,7 +1032,7 @@ ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
                *error=GetLastError ();
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return(ret);
 }
 
@@ -1065,9 +1065,9 @@ ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle,
        attr.bInheritHandle=TRUE;
        attr.lpSecurityDescriptor=NULL;
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret=CreatePipe (read_handle, write_handle, &attr, 0);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if(ret==FALSE) {
                /* FIXME: throw an exception? */
@@ -1084,9 +1084,9 @@ MonoBoolean ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_ha
        /* This is only used on Windows */
        gboolean ret;
        
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if(ret==FALSE) {
                /* FIXME: throw an exception? */
@@ -1183,7 +1183,7 @@ ves_icall_System_IO_MonoIO_GetTempPath (MonoString **mono_name)
        gunichar2 *name;
        int ret;
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        name=g_new0 (gunichar2, 256);
        
        ret=GetTempPath (256, name);
@@ -1193,7 +1193,7 @@ ves_icall_System_IO_MonoIO_GetTempPath (MonoString **mono_name)
                name=g_new0 (gunichar2, ret+2); /* include the terminator */
                ret=GetTempPath (ret, name);
        }
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        
        if(ret>0) {
 #ifdef DEBUG
@@ -1213,7 +1213,7 @@ void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
                                      gint64 length, gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        
        *error=ERROR_SUCCESS;
        
@@ -1223,14 +1223,14 @@ void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
                *error = GetLastError ();
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 }
 
 void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
                                        gint64 length, gint32 *error)
 {
        gboolean ret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        
        *error=ERROR_SUCCESS;
        
@@ -1240,7 +1240,7 @@ void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
                *error = GetLastError ();
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 }
 
 //Support for io-layer free mmap'd files.
@@ -1254,7 +1254,7 @@ mono_filesize_from_path (MonoString *string)
        gint64 res;
        char *path = mono_string_to_utf8 (string);
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        if (stat (path, &buf) == -1)
                res = -1;
        else
@@ -1262,7 +1262,7 @@ mono_filesize_from_path (MonoString *string)
 
        g_free (path);
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        return res;
 }
 
@@ -1272,9 +1272,9 @@ mono_filesize_from_fd (int fd)
        struct stat buf;
        int res;
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        res = fstat (fd, &buf);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        
        if (res == -1)
                return (gint64)-1;
index 108540654798a3e2051a3200840ab07264ab8ee5..664b28a05275b7bf3e68ec29e248736ca4c8ba37 100644 (file)
@@ -188,4 +188,3 @@ ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, gint32 watch_descriptor)
        return inotify_rm_watch (fd, watch_descriptor);
 }
 #endif
-
index 4bcdfd55e0dce63229d6c0eadef5285cdf7962f2..ff442e43f6a7faf3484ec2848e7d0bc01d0f6438 100644 (file)
@@ -27,4 +27,4 @@
 GCStats gc_stats = {};
 #else
 GCStats gc_stats;
-#endif
\ No newline at end of file
+#endif
index cdc91abedac0a91e9c53bf7cc837fcda806e402f..17afcf6be462980a96153b99e672c716fbc01847 100644 (file)
@@ -82,9 +82,9 @@ guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable)
 {
        guint32 result;
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        result = WaitForSingleObjectEx (handle, timeout, alertable);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        return result;
 }
@@ -1088,7 +1088,7 @@ finalizer_thread (gpointer unused)
 
                g_assert (mono_domain_get () == mono_get_root_domain ());
                mono_gc_set_skip_thread (TRUE);
-               MONO_PREPARE_BLOCKING
+               MONO_PREPARE_BLOCKING;
 
                if (wait) {
                /* An alertable wait is required so this thread can be suspended on windows */
@@ -1099,7 +1099,7 @@ finalizer_thread (gpointer unused)
 #endif
                }
                wait = TRUE;
-               MONO_FINISH_BLOCKING
+               MONO_FINISH_BLOCKING;
                mono_gc_set_skip_thread (FALSE);
 
                mono_threads_perform_thread_dump ();
index 677769c97e54d7930a40f7071b20d2b16412ae1d..787e5d84b3687a3175387a9ce490486acf168310 100644 (file)
@@ -873,6 +873,7 @@ ICALL(MONIT_4, "Monitor_test_owner", ves_icall_System_Threading_Monitor_Monitor_
 ICALL(MONIT_5, "Monitor_test_synchronised", ves_icall_System_Threading_Monitor_Monitor_test_synchronised)
 ICALL(MONIT_6, "Monitor_try_enter", ves_icall_System_Threading_Monitor_Monitor_try_enter)
 ICALL(MONIT_7, "Monitor_wait", ves_icall_System_Threading_Monitor_Monitor_wait)
+ICALL(MONIT_10, "enter_with_atomic_var", mono_monitor_enter_v4)
 ICALL(MONIT_9, "try_enter_with_atomic_var", ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var)
 
 ICALL_TYPE(MUTEX, "System.Threading.Mutex", MUTEX_1)
index 2d891f3fbfc0fc1342dcd6ccc2f8b0ee7ab571fc..0212a3c909d1d89fc6150ef9e9ff47f99bdf5dbe 100644 (file)
@@ -1924,28 +1924,30 @@ typedef enum {
 } PInfo;
 
 ICALL_EXPORT void
-ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
+ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
 {
        MonoDomain *domain = mono_object_domain (property); 
+       const MonoProperty *pproperty = property->property;
 
        if ((req_info & PInfo_ReflectedType) != 0)
                MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
        if ((req_info & PInfo_DeclaringType) != 0)
-               MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
+               MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &pproperty->parent->byval_arg));
 
        if ((req_info & PInfo_Name) != 0)
-               MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
+               MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
 
        if ((req_info & PInfo_Attributes) != 0)
-               info->attrs = property->property->attrs;
+               info->attrs = pproperty->attrs;
 
        if ((req_info & PInfo_GetMethod) != 0)
-               MONO_STRUCT_SETREF (info, get, property->property->get ?
-                                                       mono_method_get_object (domain, property->property->get, property->klass): NULL);
-       
+               MONO_STRUCT_SETREF (info, get, pproperty->get &&
+                                                       (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->get->klass == property->klass) ?
+                                                       mono_method_get_object (domain, pproperty->get, property->klass): NULL);
        if ((req_info & PInfo_SetMethod) != 0)
-               MONO_STRUCT_SETREF (info, set, property->property->set ?
-                                                       mono_method_get_object (domain, property->property->set, property->klass): NULL);
+               MONO_STRUCT_SETREF (info, set, pproperty->set &&
+                                                       (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->set->klass == property->klass) ?
+                                                       mono_method_get_object (domain, pproperty->set, property->klass): NULL);
        /* 
         * There may be other methods defined for properties, though, it seems they are not exposed 
         * in the reflection API 
@@ -5681,6 +5683,13 @@ ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, Mo
 {
        guint8 *src_buf, *dest_buf;
 
+       if (count < 0) {
+               mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
+               return FALSE;
+       }
+
+       g_assert (count >= 0);
+
        /* This is called directly from the class libraries without going through the managed wrapper */
        MONO_CHECK_ARG_NULL (src, FALSE);
        MONO_CHECK_ARG_NULL (dest, FALSE);
index 7045f4d05efec256289609edc29edbb0c1a65bfc..d28ea9627063e3f301f4c744e5549af0277dbb9f 100644 (file)
@@ -1491,6 +1491,34 @@ free_hash (GHashTable *hash)
                g_hash_table_destroy (hash);
 }
 
+void
+mono_wrapper_caches_free (MonoWrapperCaches *cache)
+{
+       free_hash (cache->delegate_invoke_cache);
+       free_hash (cache->delegate_begin_invoke_cache);
+       free_hash (cache->delegate_end_invoke_cache);
+       free_hash (cache->runtime_invoke_cache);
+       free_hash (cache->runtime_invoke_vtype_cache);
+       
+       free_hash (cache->delegate_abstract_invoke_cache);
+
+       free_hash (cache->runtime_invoke_direct_cache);
+       free_hash (cache->managed_wrapper_cache);
+
+       free_hash (cache->native_wrapper_cache);
+       free_hash (cache->native_wrapper_aot_cache);
+       free_hash (cache->native_wrapper_check_cache);
+       free_hash (cache->native_wrapper_aot_check_cache);
+
+       free_hash (cache->native_func_wrapper_aot_cache);
+       free_hash (cache->remoting_invoke_cache);
+       free_hash (cache->synchronized_cache);
+       free_hash (cache->unbox_wrapper_cache);
+       free_hash (cache->cominterop_invoke_cache);
+       free_hash (cache->cominterop_wrapper_cache);
+       free_hash (cache->thunk_invoke_cache);
+}
+
 /*
  * Returns whether mono_image_close_finish() must be called as well.
  * We must unload images in two steps because clearing the domain in
@@ -1650,24 +1678,7 @@ mono_image_close_except_pools (MonoImage *image)
        free_hash (image->native_func_wrapper_cache);
        free_hash (image->typespec_cache);
 
-       free_hash (image->wrapper_caches.native_wrapper_cache);
-       free_hash (image->wrapper_caches.native_wrapper_aot_cache);
-       free_hash (image->wrapper_caches.native_wrapper_check_cache);
-       free_hash (image->wrapper_caches.native_wrapper_aot_check_cache);
-       free_hash (image->wrapper_caches.managed_wrapper_cache);
-       free_hash (image->wrapper_caches.delegate_begin_invoke_cache);
-       free_hash (image->wrapper_caches.delegate_end_invoke_cache);
-       free_hash (image->wrapper_caches.delegate_invoke_cache);
-       free_hash (image->wrapper_caches.delegate_abstract_invoke_cache);
-       free_hash (image->wrapper_caches.remoting_invoke_cache);
-       free_hash (image->wrapper_caches.runtime_invoke_cache);
-       free_hash (image->wrapper_caches.runtime_invoke_vtype_cache);
-       free_hash (image->wrapper_caches.runtime_invoke_direct_cache);
-       free_hash (image->wrapper_caches.synchronized_cache);
-       free_hash (image->wrapper_caches.unbox_wrapper_cache);
-       free_hash (image->wrapper_caches.cominterop_invoke_cache);
-       free_hash (image->wrapper_caches.cominterop_wrapper_cache);
-       free_hash (image->wrapper_caches.thunk_invoke_cache);
+       mono_wrapper_caches_free (&image->wrapper_caches);
 
        for (i = 0; i < image->gshared_types_len; ++i)
                free_hash (image->gshared_types [i]);
index d9ae9d6fde02568d9854d795c587b31ca8c8043c..2c591c9e4f910177930f9c84dd38ea95e6dc659d 100644 (file)
@@ -2376,10 +2376,11 @@ stack_walk_adapter (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data)
        switch (frame->type) {
        case FRAME_TYPE_DEBUGGER_INVOKE:
        case FRAME_TYPE_MANAGED_TO_NATIVE:
+       case FRAME_TYPE_TRAMPOLINE:
                return FALSE;
        case FRAME_TYPE_MANAGED:
                g_assert (frame->ji);
-               return d->func (mono_jit_info_get_method (frame->ji), frame->native_offset, frame->il_offset, frame->managed, d->user_data);
+               return d->func (frame->actual_method, frame->native_offset, frame->il_offset, frame->managed, d->user_data);
                break;
        default:
                g_assert_not_reached ();
@@ -2415,14 +2416,16 @@ async_stack_walk_adapter (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer
        switch (frame->type) {
        case FRAME_TYPE_DEBUGGER_INVOKE:
        case FRAME_TYPE_MANAGED_TO_NATIVE:
+       case FRAME_TYPE_TRAMPOLINE:
                return FALSE;
        case FRAME_TYPE_MANAGED:
                if (!frame->ji)
                        return FALSE;
-               if (frame->ji->async)
+               if (frame->ji->async) {
                        return d->func (NULL, frame->domain, frame->ji->code_start, frame->native_offset, d->user_data);
-               else
+               } else {
                        return d->func (frame->actual_method, frame->domain, frame->ji->code_start, frame->native_offset, d->user_data);
+               }
                break;
        default:
                g_assert_not_reached ();
@@ -2474,9 +2477,9 @@ static gboolean loader_lock_track_ownership = FALSE;
 void
 mono_loader_lock (void)
 {
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        mono_locks_acquire (&loader_mutex, LoaderLock);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
                
        if (G_UNLIKELY (loader_lock_track_ownership)) {
                mono_native_tls_set_value (loader_lock_nest_id, GUINT_TO_POINTER (GPOINTER_TO_UINT (mono_native_tls_get_value (loader_lock_nest_id)) + 1));
index 0f0496f1d65a65c722d6b79cbcb7faa20a3dbf10..f8f0c4712a9b55b9ded437efe28c4f26d6b0078d 100644 (file)
@@ -3103,11 +3103,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
        } else if (callvirt) {
                GHashTable **cache_ptr;
 
-               if (method->is_inflated) {
-                       MonoMethodInflated *imethod = (MonoMethodInflated *)method;
-                       cache_ptr = &imethod->owner->wrapper_caches.delegate_abstract_invoke_cache;
-               } else
-                       cache_ptr = &method->klass->image->wrapper_caches.delegate_abstract_invoke_cache;
+               cache_ptr = &mono_method_get_wrapper_cache (method)->delegate_abstract_invoke_cache;
 
                /* We need to cache the signature+method pair */
                mono_marshal_lock ();
@@ -3837,11 +3833,9 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
         */
        if (virtual)
                cache = get_cache (&method->klass->image->runtime_invoke_vcall_cache, mono_aligned_addr_hash, NULL);
-       else if (method->is_inflated) {
-               MonoMethodInflated *imethod = (MonoMethodInflated *)method;
-               cache = get_cache (&imethod->owner->wrapper_caches.runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL);
-       } else
-               cache = get_cache (&method->klass->image->wrapper_caches.runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL);
+       else
+               cache = get_cache (&mono_method_get_wrapper_cache (method)->runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL);
+
        res = mono_marshal_find_in_cache (cache, method);
        if (res)
                return res;
@@ -3887,19 +3881,10 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
                callsig = mono_marshal_get_runtime_invoke_sig (callsig);
                GHashTable **cache_table = NULL;
 
-
-               if (method->is_inflated) {
-                       MonoMethodInflated *imethod = (MonoMethodInflated *)method;
-                       if (method->klass->valuetype && mono_method_signature (method)->hasthis)
-                               cache_table = &imethod->owner->wrapper_caches.runtime_invoke_vtype_cache;
-                       else
-                               cache_table = &imethod->owner->wrapper_caches.runtime_invoke_cache;
-               } else {
-                       if (method->klass->valuetype && mono_method_signature (method)->hasthis)
-                               cache_table = &target_klass->image->wrapper_caches.runtime_invoke_vtype_cache;
-                       else
-                               cache_table = &target_klass->image->wrapper_caches.runtime_invoke_cache;
-               }
+               if (method->klass->valuetype && mono_method_signature (method)->hasthis)
+                       cache_table = &mono_method_get_wrapper_cache (method)->runtime_invoke_vtype_cache;
+               else
+                       cache_table = &mono_method_get_wrapper_cache (method)->runtime_invoke_cache;
 
                cache = get_cache (cache_table, (GHashFunc)mono_signature_hash,
                                                           (GCompareFunc)runtime_invoke_signature_equal);
@@ -3980,11 +3965,7 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
                                res = newm;
                                g_hash_table_insert (cache, callsig, res);
                                /* Can't insert it into wrapper_hash since the key is a signature */
-
-                               if (method->is_inflated)
-                                       direct_cache = ((MonoMethodInflated*)method)->owner->wrapper_caches.runtime_invoke_direct_cache;
-                               else
-                                       direct_cache = method->klass->image->wrapper_caches.runtime_invoke_direct_cache;
+                               direct_cache = mono_method_get_wrapper_cache (method)->runtime_invoke_direct_cache;
 
                                g_hash_table_insert (direct_cache, method, res);
                        } else {
@@ -7249,31 +7230,16 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
 
        GHashTable **cache_ptr;
 
-       if (method->is_inflated) {
-               MonoMethodInflated *imethod = (MonoMethodInflated *)method;
-               if (aot) {
-                       if (check_exceptions)
-                               cache_ptr = &imethod->owner->wrapper_caches.native_wrapper_aot_check_cache;
-                       else
-                               cache_ptr = &imethod->owner->wrapper_caches.native_wrapper_aot_cache;
-               } else {
-                       if (check_exceptions)
-                               cache_ptr = &imethod->owner->wrapper_caches.native_wrapper_check_cache;
-                       else
-                               cache_ptr = &imethod->owner->wrapper_caches.native_wrapper_cache;
-               }
+       if (aot) {
+               if (check_exceptions)
+                       cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_aot_check_cache;
+               else
+                       cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_aot_cache;
        } else {
-               if (aot) {
-                       if (check_exceptions)
-                               cache_ptr = &method->klass->image->wrapper_caches.native_wrapper_aot_check_cache;
-                       else
-                               cache_ptr = &method->klass->image->wrapper_caches.native_wrapper_aot_cache;
-               } else {
-                       if (check_exceptions)
-                               cache_ptr = &method->klass->image->wrapper_caches.native_wrapper_check_cache;
-                       else
-                               cache_ptr = &method->klass->image->wrapper_caches.native_wrapper_cache;
-               }
+               if (check_exceptions)
+                       cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_check_cache;
+               else
+                       cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_cache;
        }
 
        cache = get_cache (cache_ptr, mono_aligned_addr_hash, NULL);
@@ -7549,11 +7515,7 @@ mono_marshal_get_native_func_wrapper_aot (MonoClass *klass)
        /*
         * The wrapper is associated with the delegate type, to pick up the marshalling info etc.
         */
-       if (invoke->is_inflated) {
-               MonoMethodInflated *imethod = (MonoMethodInflated *)invoke;
-               cache = get_cache (&imethod->owner->wrapper_caches.native_func_wrapper_aot_cache, mono_aligned_addr_hash, NULL);
-       } else
-               cache = get_cache (&image->wrapper_caches.native_func_wrapper_aot_cache, mono_aligned_addr_hash, NULL);
+       cache = get_cache (&mono_method_get_wrapper_cache (invoke)->native_func_wrapper_aot_cache, mono_aligned_addr_hash, NULL);
 
        if ((res = mono_marshal_find_in_cache (cache, invoke)))
                return res;
@@ -7907,11 +7869,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
         * could be called with different delegates, thus different marshalling
         * options.
         */
-       if (method->is_inflated) {
-               MonoMethodInflated *imethod = (MonoMethodInflated *)method;
-               cache = get_cache (&imethod->owner->wrapper_caches.managed_wrapper_cache, mono_aligned_addr_hash, NULL);
-       } else
-               cache = get_cache (&method->klass->image->wrapper_caches.managed_wrapper_cache, mono_aligned_addr_hash, NULL);
+       cache = get_cache (&mono_method_get_wrapper_cache (method)->managed_wrapper_cache, mono_aligned_addr_hash, NULL);
 
        if (!target_handle && (res = mono_marshal_find_in_cache (cache, method)))
                return res;
@@ -8739,7 +8697,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
        MonoMethodBuilder *mb;
        MonoMethod *res;
        GHashTable *cache;
-       int i, pos, this_local, ret_local = 0;
+       int i, pos, pos2, this_local, taken_local, ret_local = 0;
        MonoGenericContext *ctx = NULL;
        MonoMethod *orig_method = NULL;
        MonoGenericContainer *container = NULL;
@@ -8780,6 +8738,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
        mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
 
 #ifndef DISABLE_JIT
+       mb->skip_visibility = 1;
        /* result */
        if (!MONO_TYPE_IS_VOID (sig->ret))
                ret_local = mono_mb_add_local (mb, sig->ret);
@@ -8808,6 +8767,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
 #ifndef DISABLE_JIT
        /* this */
        this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
+       taken_local = mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
 
        clause = mono_image_alloc0 (method->klass->image, sizeof (MonoExceptionClause));
        clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
@@ -8818,7 +8778,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
        if (!enter_method) {
                MonoMethodDesc *desc;
 
-               desc = mono_method_desc_new ("Monitor:Enter", FALSE);
+               desc = mono_method_desc_new ("Monitor:enter_with_atomic_var(object,bool&)", FALSE);
                enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
                g_assert (enter_method);
                mono_method_desc_free (desc);
@@ -8853,6 +8813,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
 
        /* Call Monitor::Enter() */
        mono_mb_emit_ldloc (mb, this_local);
+       mono_mb_emit_ldloc_addr (mb, taken_local);
        mono_mb_emit_managed_call (mb, enter_method, NULL);
 
        clause->try_offset = mono_mb_get_label (mb);
@@ -8879,9 +8840,12 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
        clause->try_len = mono_mb_get_pos (mb) - clause->try_offset;
        clause->handler_offset = mono_mb_get_label (mb);
 
-       /* Call Monitor::Exit() */
+       /* Call Monitor::Exit() if needed */
+       mono_mb_emit_ldloc (mb, taken_local);
+       pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
        mono_mb_emit_ldloc (mb, this_local);
        mono_mb_emit_managed_call (mb, exit_method, NULL);
+       mono_mb_patch_branch (mb, pos2);
        mono_mb_emit_byte (mb, CEE_ENDFINALLY);
 
        clause->handler_len = mono_mb_get_pos (mb) - clause->handler_offset;
@@ -8920,11 +8884,7 @@ mono_marshal_get_unbox_wrapper (MonoMethod *method)
        MonoMethod *res;
        GHashTable *cache;
 
-       if (method->is_inflated) {
-               MonoMethodInflated *imethod = (MonoMethodInflated *)method;
-               cache = get_cache (&imethod->owner->wrapper_caches.unbox_wrapper_cache, mono_aligned_addr_hash, NULL);
-       } else
-               cache = get_cache (&method->klass->image->wrapper_caches.unbox_wrapper_cache, mono_aligned_addr_hash, NULL);
+       cache = get_cache (&mono_method_get_wrapper_cache (method)->unbox_wrapper_cache, mono_aligned_addr_hash, NULL);
 
        if ((res = mono_marshal_find_in_cache (cache, method)))
                return res;
@@ -11158,11 +11118,8 @@ mono_marshal_get_thunk_invoke_wrapper (MonoMethod *method)
        klass = method->klass;
        image = method->klass->image;
 
-       if (method->is_inflated) {
-               MonoMethodInflated *imethod = (MonoMethodInflated *)method;
-               cache = get_cache (&imethod->owner->wrapper_caches.thunk_invoke_cache, mono_aligned_addr_hash, NULL);
-       } else
-               cache = get_cache (&image->wrapper_caches.thunk_invoke_cache, mono_aligned_addr_hash, NULL);
+       cache = get_cache (&mono_method_get_wrapper_cache (method)->thunk_invoke_cache, mono_aligned_addr_hash, NULL);
+
 
        if ((res = mono_marshal_find_in_cache (cache, method)))
                return res;
@@ -11321,12 +11278,3 @@ mono_marshal_free_dynamic_wrappers (MonoMethod *method)
        if (marshal_mutex_initialized)
                mono_marshal_unlock ();
 }
-
-static gboolean
-signature_pointer_pair_matches_signature (gpointer key, gpointer value, gpointer user_data)
-{
-       SignaturePointerPair *pair = (SignaturePointerPair*)key;
-       MonoMethodSignature *sig = (MonoMethodSignature*)user_data;
-
-       return mono_metadata_signature_equal (pair->sig, sig);
-}
index 6c1e56eec2b78dfccafcd43a1168857c122705cd..0bed5a2ee0bbb278b7135affef5b599e90052ad3 100644 (file)
@@ -851,5 +851,14 @@ mono_get_method_checked (MonoImage *image, guint32 token, MonoClass *klass, Mono
 guint32
 mono_metadata_localscope_from_methoddef (MonoImage *meta, guint32 index);
 
+void
+mono_wrapper_caches_free (MonoWrapperCaches *cache);
+
+MonoWrapperCaches*
+mono_method_get_wrapper_cache (MonoMethod *method);
+
+MonoWrapperCaches*
+mono_method_get_wrapper_cache (MonoMethod *method);
+
 #endif /* __MONO_METADATA_INTERNALS_H__ */
 
index b0c7dfaee16301079f6742016f82fdde8046231b..b332bd6e99dbba2aac094e39770a0b244e32774c 100644 (file)
@@ -1864,7 +1864,7 @@ mono_metadata_signature_dup_internal_with_padding (MonoImage *image, MonoMemPool
        MonoMethodSignature *ret;
        sigsize = sig_header_size = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *) + padding;
        if (sig->ret)
-               sigsize += sizeof (MonoType);
+               sigsize += MONO_SIZEOF_TYPE;
 
        if (image) {
                ret = mono_image_alloc (image, sigsize);
@@ -1881,7 +1881,7 @@ mono_metadata_signature_dup_internal_with_padding (MonoImage *image, MonoMemPool
                // Danger! Do not alter padding use without changing the dup_add_this below
                intptr_t end_of_header = (intptr_t)( (char*)(ret) + sig_header_size);
                ret->ret = (MonoType *)end_of_header;
-               *ret->ret = *sig->ret;
+               memcpy (ret->ret, sig->ret, MONO_SIZEOF_TYPE);
        }
 
        return ret;
@@ -2397,42 +2397,7 @@ delete_image_set (MonoImageSet *set)
        g_hash_table_destroy (set->gmethod_cache);
        g_hash_table_destroy (set->gsignature_cache);
 
-       if (set->wrapper_caches.delegate_abstract_invoke_cache)
-               g_hash_table_destroy (set->wrapper_caches.delegate_abstract_invoke_cache);
-       if (set->wrapper_caches.runtime_invoke_direct_cache)
-               g_hash_table_destroy (set->wrapper_caches.runtime_invoke_direct_cache);
-       if (set->wrapper_caches.managed_wrapper_cache)
-               g_hash_table_destroy (set->wrapper_caches.managed_wrapper_cache);
-       if (set->wrapper_caches.native_wrapper_cache)
-               g_hash_table_destroy (set->wrapper_caches.native_wrapper_cache);
-       if (set->wrapper_caches.native_wrapper_aot_cache)
-               g_hash_table_destroy (set->wrapper_caches.native_wrapper_aot_cache);
-       if (set->wrapper_caches.native_wrapper_check_cache)
-               g_hash_table_destroy (set->wrapper_caches.native_wrapper_check_cache);
-       if (set->wrapper_caches.native_wrapper_aot_check_cache)
-               g_hash_table_destroy (set->wrapper_caches.native_wrapper_aot_check_cache);
-       if (set->wrapper_caches.native_func_wrapper_aot_cache)
-               g_hash_table_destroy (set->wrapper_caches.native_func_wrapper_aot_cache);
-       if (set->wrapper_caches.remoting_invoke_cache)
-               g_hash_table_destroy (set->wrapper_caches.remoting_invoke_cache);
-       if (set->wrapper_caches.unbox_wrapper_cache)
-               g_hash_table_destroy (set->wrapper_caches.unbox_wrapper_cache);
-       if (set->wrapper_caches.cominterop_invoke_cache)
-               g_hash_table_destroy (set->wrapper_caches.cominterop_invoke_cache);
-       if (set->wrapper_caches.cominterop_wrapper_cache)
-               g_hash_table_destroy (set->wrapper_caches.cominterop_wrapper_cache);
-       if (set->wrapper_caches.thunk_invoke_cache)
-               g_hash_table_destroy (set->wrapper_caches.thunk_invoke_cache);
-       if (set->wrapper_caches.runtime_invoke_cache)
-               g_hash_table_destroy (set->wrapper_caches.runtime_invoke_cache);
-       if (set->wrapper_caches.delegate_invoke_cache)
-               g_hash_table_destroy (set->wrapper_caches.delegate_invoke_cache);
-       if (set->wrapper_caches.delegate_begin_invoke_cache)
-               g_hash_table_destroy (set->wrapper_caches.delegate_begin_invoke_cache);
-       if (set->wrapper_caches.delegate_end_invoke_cache)
-               g_hash_table_destroy (set->wrapper_caches.delegate_end_invoke_cache);
-       if (set->wrapper_caches.synchronized_cache)
-               g_hash_table_destroy (set->wrapper_caches.synchronized_cache);
+       mono_wrapper_caches_free (&set->wrapper_caches);
 
        image_sets_lock ();
 
@@ -6595,3 +6560,13 @@ mono_metadata_get_corresponding_property_from_generic_type_definition (MonoPrope
        return gtd->ext->properties + offset;
 }
 
+MonoWrapperCaches*
+mono_method_get_wrapper_cache (MonoMethod *method)
+{
+       if (method->is_inflated) {
+               MonoMethodInflated *imethod = (MonoMethodInflated *)method;
+               return &imethod->owner->wrapper_caches;
+       } else {
+               return &method->klass->image->wrapper_caches;
+       }
+}
index 36a42db0bf7d13c23d3969b39cc8195831eb52d3..0d9001be1a05514840d263c456affd595d3765e7 100644 (file)
@@ -64,15 +64,7 @@ enum {
  *
  * Bacon's thin locks have a fast path that doesn't need a lock record
  * for the common case of locking an unlocked or shallow-nested
- * object, but the technique relies on encoding the thread ID in 15
- * bits (to avoid too much per-object space overhead.)  Unfortunately
- * I don't think it's possible to reliably encode a pthread_t into 15
- * bits. (The JVM implementation used seems to have a 15-bit
- * per-thread identifier available.)
- *
- * This implementation then combines Dice's basic lock model with
- * Bacon's simplification of keeping a lock record for the lifetime of
- * an object.
+ * object.
  */
 
 
@@ -91,6 +83,8 @@ static MonoThreadsSync *monitor_freelist;
 static MonitorArray *monitor_allocated;
 static int array_size = 16;
 
+/* MonoThreadsSync status helpers */
+
 static inline guint32
 mon_status_get_owner (guint32 status)
 {
@@ -135,6 +129,122 @@ mon_status_have_waiters (guint32 status)
        return status & ENTRY_COUNT_WAITERS;
 }
 
+/* LockWord helpers */
+
+static inline MonoThreadsSync*
+lock_word_get_inflated_lock (LockWord lw)
+{
+       lw.lock_word &= (~LOCK_WORD_STATUS_MASK);
+       return lw.sync;
+}
+
+static inline gboolean
+lock_word_is_inflated (LockWord lw)
+{
+       return lw.lock_word & LOCK_WORD_INFLATED;
+}
+
+static inline gboolean
+lock_word_has_hash (LockWord lw)
+{
+       return lw.lock_word & LOCK_WORD_HAS_HASH;
+}
+
+static inline LockWord
+lock_word_set_has_hash (LockWord lw)
+{
+       LockWord nlw;
+       nlw.lock_word = lw.lock_word | LOCK_WORD_HAS_HASH;
+       return nlw;
+}
+
+static inline gboolean
+lock_word_is_free (LockWord lw)
+{
+       return !lw.lock_word;
+}
+
+static inline gboolean
+lock_word_is_flat (LockWord lw)
+{
+       /* Return whether the lock is flat or free */
+       return (lw.lock_word & LOCK_WORD_STATUS_MASK) == LOCK_WORD_FLAT;
+}
+
+static inline gint32
+lock_word_get_hash (LockWord lw)
+{
+       return (gint32) (lw.lock_word >> LOCK_WORD_HASH_SHIFT);
+}
+
+static inline gint32
+lock_word_get_nest (LockWord lw)
+{
+       if (lock_word_is_free (lw))
+               return 0;
+       /* Inword nest count starts from 0 */
+       return ((lw.lock_word & LOCK_WORD_NEST_MASK) >> LOCK_WORD_NEST_SHIFT) + 1;
+}
+
+static inline gboolean
+lock_word_is_nested (LockWord lw)
+{
+       return lw.lock_word & LOCK_WORD_NEST_MASK;
+}
+
+static inline gboolean
+lock_word_is_max_nest (LockWord lw)
+{
+       return (lw.lock_word & LOCK_WORD_NEST_MASK) == LOCK_WORD_NEST_MASK;
+}
+
+static inline LockWord
+lock_word_increment_nest (LockWord lw)
+{
+       lw.lock_word += 1 << LOCK_WORD_NEST_SHIFT;
+       return lw;
+}
+
+static inline LockWord
+lock_word_decrement_nest (LockWord lw)
+{
+       lw.lock_word -= 1 << LOCK_WORD_NEST_SHIFT;
+       return lw;
+}
+
+static inline gint32
+lock_word_get_owner (LockWord lw)
+{
+       return lw.lock_word >> LOCK_WORD_OWNER_SHIFT;
+}
+
+static inline LockWord
+lock_word_new_thin_hash (gint32 hash)
+{
+       LockWord lw;
+       lw.lock_word = (guint32)hash;
+       lw.lock_word = (lw.lock_word << LOCK_WORD_HASH_SHIFT) | LOCK_WORD_HAS_HASH;
+       return lw;
+}
+
+static inline LockWord
+lock_word_new_inflated (MonoThreadsSync *mon)
+{
+       LockWord lw;
+       lw.sync = mon;
+       lw.lock_word |= LOCK_WORD_INFLATED;
+       return lw;
+}
+
+static inline LockWord
+lock_word_new_flat (gint32 owner)
+{
+       LockWord lw;
+       lw.lock_word = owner;
+       lw.lock_word <<= LOCK_WORD_OWNER_SHIFT;
+       return lw;
+}
+
 void
 mono_monitor_init (void)
 {
@@ -337,26 +447,107 @@ mon_new (gsize id)
        return new;
 }
 
-/*
- * Format of the lock word:
- * thinhash | fathash | data
- *
- * thinhash is the lower bit: if set data is the shifted hashcode of the object.
- * fathash is another bit: if set the hash code is stored in the MonoThreadsSync
- *   struct pointed to by data
- * if neither bit is set and data is non-NULL, data is a MonoThreadsSync
- */
-typedef union {
-       gsize lock_word;
-       MonoThreadsSync *sync;
-} LockWord;
+static MonoThreadsSync*
+alloc_mon (MonoObject *obj, gint32 id)
+{
+       MonoThreadsSync *mon;
 
-enum {
-       LOCK_WORD_THIN_HASH = 1,
-       LOCK_WORD_FAT_HASH = 1 << 1,
-       LOCK_WORD_BITS_MASK = 0x3,
-       LOCK_WORD_HASH_SHIFT = 2
-};
+       mono_monitor_allocator_lock ();
+       mon = mon_new (id);
+       mono_gc_weak_link_add (&mon->data, obj, TRUE);
+       mono_monitor_allocator_unlock ();
+
+       return mon;
+}
+
+
+static void
+discard_mon (MonoThreadsSync *mon)
+{
+       mono_monitor_allocator_lock ();
+       mono_gc_weak_link_remove (&mon->data, TRUE);
+       mon_finalize (mon);
+       mono_monitor_allocator_unlock ();
+}
+
+static void
+mono_monitor_inflate_owned (MonoObject *obj, int id)
+{
+       MonoThreadsSync *mon;
+       LockWord nlw, old_lw, tmp_lw;
+       guint32 nest;
+
+       old_lw.sync = obj->synchronisation;
+       LOCK_DEBUG (g_message ("%s: (%d) Inflating owned lock object %p; LW = %p", __func__, id, obj, old_lw.sync));
+
+       if (lock_word_is_inflated (old_lw)) {
+               /* Someone else inflated the lock in the meantime */
+               return;
+       }
+
+       mon = alloc_mon (obj, id);
+
+       nest = lock_word_get_nest (old_lw);
+       mon->nest = nest;
+
+       nlw = lock_word_new_inflated (mon);
+
+       mono_memory_write_barrier ();
+       tmp_lw.sync = InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, nlw.sync, old_lw.sync);
+       if (tmp_lw.sync != old_lw.sync) {
+               /* Someone else inflated the lock in the meantime */
+               discard_mon (mon);
+       }
+}
+
+static void
+mono_monitor_inflate (MonoObject *obj)
+{
+       MonoThreadsSync *mon;
+       LockWord nlw, old_lw;
+
+       LOCK_DEBUG (g_message ("%s: (%d) Inflating lock object %p; LW = %p", __func__, mono_thread_info_get_small_id (), obj, obj->synchronisation));
+
+       mon = alloc_mon (obj, 0);
+
+       nlw = lock_word_new_inflated (mon);
+
+       old_lw.sync = obj->synchronisation;
+
+       for (;;) {
+               LockWord tmp_lw;
+
+               if (lock_word_is_inflated (old_lw)) {
+                       break;
+               }
+#ifdef HAVE_MOVING_COLLECTOR
+                else if (lock_word_has_hash (old_lw)) {
+                       mon->hash_code = lock_word_get_hash (old_lw);
+                       mon->status = mon_status_set_owner (mon->status, 0);
+                       nlw = lock_word_set_has_hash (nlw);
+               }
+#endif
+               else if (lock_word_is_free (old_lw)) {
+                       mon->status = mon_status_set_owner (mon->status, 0);
+                       mon->nest = 1;
+               } else {
+                       /* Lock is flat */
+                       mon->status = mon_status_set_owner (mon->status, lock_word_get_owner (old_lw));
+                       mon->nest = lock_word_get_nest (old_lw);
+               }
+               mono_memory_write_barrier ();
+               tmp_lw.sync = InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, nlw.sync, old_lw.sync);
+               if (tmp_lw.sync == old_lw.sync) {
+                       /* Successfully inflated the lock */
+                       return;
+               }
+
+               old_lw.sync = tmp_lw.sync;
+       }
+
+       /* Someone else inflated the lock before us */
+       discard_mon (mon);
+}
 
 #define MONO_OBJECT_ALIGNMENT_SHIFT    3
 
@@ -375,14 +566,15 @@ mono_object_hash (MonoObject* obj)
        if (!obj)
                return 0;
        lw.sync = obj->synchronisation;
-       if (lw.lock_word & LOCK_WORD_THIN_HASH) {
-               /*g_print ("fast thin hash %d for obj %p store\n", (unsigned int)lw.lock_word >> LOCK_WORD_HASH_SHIFT, obj);*/
-               return (unsigned int)lw.lock_word >> LOCK_WORD_HASH_SHIFT;
-       }
-       if (lw.lock_word & LOCK_WORD_FAT_HASH) {
-               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-               /*g_print ("fast fat hash %d for obj %p store\n", lw.sync->hash_code, obj);*/
-               return lw.sync->hash_code;
+
+       LOCK_DEBUG (g_message("%s: (%d) Get hash for object %p; LW = %p", __func__, mono_thread_info_get_small_id (), obj, obj->synchronisation));
+
+       if (lock_word_has_hash (lw)) {
+               if (lock_word_is_inflated (lw)) {
+                       return lock_word_get_inflated_lock (lw)->hash_code;
+               } else {
+                       return lock_word_get_hash (lw);
+               }
        }
        /*
         * while we are inside this function, the GC will keep this object pinned,
@@ -392,31 +584,40 @@ mono_object_hash (MonoObject* obj)
         * with the same value.
         */
        hash = (GPOINTER_TO_UINT (obj) >> MONO_OBJECT_ALIGNMENT_SHIFT) * 2654435761u;
+#if SIZEOF_VOID_P == 4
        /* clear the top bits as they can be discarded */
-       hash &= ~(LOCK_WORD_BITS_MASK << 30);
-       /* no hash flags were set, so it must be a MonoThreadsSync pointer if not NULL */
-       if (lw.sync) {
-               lw.sync->hash_code = hash;
-               /*g_print ("storing hash code %d for obj %p in sync %p\n", hash, obj, lw.sync);*/
-               lw.lock_word |= LOCK_WORD_FAT_HASH;
-               /* this is safe since we don't deflate locks */
-               obj->synchronisation = lw.sync;
-       } else {
-               /*g_print ("storing thin hash code %d for obj %p\n", hash, obj);*/
-               lw.lock_word = LOCK_WORD_THIN_HASH | (hash << LOCK_WORD_HASH_SHIFT);
-               if (InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, lw.sync, NULL) == NULL)
+       hash &= ~(LOCK_WORD_STATUS_MASK << (32 - LOCK_WORD_STATUS_BITS));
+#endif
+       if (lock_word_is_free (lw)) {
+               LockWord old_lw;
+               lw = lock_word_new_thin_hash (hash);
+
+               old_lw.sync = InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, lw.sync, NULL);
+               if (old_lw.sync == NULL) {
                        return hash;
-               /*g_print ("failed store\n");*/
-               /* someone set the hash flag or someone inflated the object */
-               lw.sync = obj->synchronisation;
-               if (lw.lock_word & LOCK_WORD_THIN_HASH)
+               }
+
+               if (lock_word_has_hash (old_lw)) {
+                       /* Done by somebody else */
                        return hash;
-               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-               lw.sync->hash_code = hash;
-               lw.lock_word |= LOCK_WORD_FAT_HASH;
-               /* this is safe since we don't deflate locks */
-               obj->synchronisation = lw.sync;
+               }
+                       
+               mono_monitor_inflate (obj);
+               lw.sync = obj->synchronisation;
+       } else if (lock_word_is_flat (lw)) {
+               int id = mono_thread_info_get_small_id ();
+               if (lock_word_get_owner (lw) == id)
+                       mono_monitor_inflate_owned (obj, id);
+               else
+                       mono_monitor_inflate (obj);
+               lw.sync = obj->synchronisation;
        }
+
+       /* At this point, the lock is inflated */
+       lock_word_get_inflated_lock (lw)->hash_code = hash;
+       lw = lock_word_set_has_hash (lw);
+       mono_memory_write_barrier ();
+       obj->synchronisation = lw.sync;
        return hash;
 #else
 /*
@@ -427,6 +628,94 @@ mono_object_hash (MonoObject* obj)
 #endif
 }
 
+static void
+mono_monitor_ensure_owned (LockWord lw, guint32 id)
+{
+       if (lock_word_is_flat (lw)) {
+               if (lock_word_get_owner (lw) == id)
+                       return;
+       } else if (lock_word_is_inflated (lw)) {
+               if (mon_status_get_owner (lock_word_get_inflated_lock (lw)->status) == id)
+                       return;
+       }
+
+       mono_set_pending_exception (mono_get_exception_synchronization_lock ("Object synchronization method was called from an unsynchronized block of code."));
+}
+
+/*
+ * When this function is called it has already been established that the
+ * current thread owns the monitor.
+ */
+static void
+mono_monitor_exit_inflated (MonoObject *obj)
+{
+       LockWord lw;
+       MonoThreadsSync *mon;
+       guint32 nest;
+
+       lw.sync = obj->synchronisation;
+       mon = lock_word_get_inflated_lock (lw);
+
+       nest = mon->nest - 1;
+       if (nest == 0) {
+               guint32 new_status, old_status, tmp_status;
+
+               old_status = mon->status;
+
+               /*
+                * Release lock and do the wakeup stuff. It's possible that
+                * the last blocking thread gave up waiting just before we
+                * release the semaphore resulting in a negative entry count
+                * and a futile wakeup next time there's contention for this
+                * object.
+                */
+               for (;;) {
+                       gboolean have_waiters = mon_status_have_waiters (old_status);
+       
+                       new_status = mon_status_set_owner (old_status, 0);
+                       if (have_waiters)
+                               new_status = mon_status_decrement_entry_count (new_status);
+                       tmp_status = InterlockedCompareExchange ((gint32*)&mon->status, new_status, old_status);
+                       if (tmp_status == old_status) {
+                               if (have_waiters)
+                                       ReleaseSemaphore (mon->entry_sem, 1, NULL);
+                               break;
+                       }
+                       old_status = tmp_status;
+               }
+               LOCK_DEBUG (g_message ("%s: (%d) Object %p is now unlocked", __func__, mono_thread_info_get_small_id (), obj));
+       
+               /* object is now unlocked, leave nest==1 so we don't
+                * need to set it when the lock is reacquired
+                */
+       } else {
+               LOCK_DEBUG (g_message ("%s: (%d) Object %p is now locked %d times", __func__, mono_thread_info_get_small_id (), obj, nest));
+               mon->nest = nest;
+       }
+}
+
+/*
+ * When this function is called it has already been established that the
+ * current thread owns the monitor.
+ */
+static void
+mono_monitor_exit_flat (MonoObject *obj, LockWord old_lw)
+{
+       LockWord new_lw, tmp_lw;
+       if (G_UNLIKELY (lock_word_is_nested (old_lw)))
+               new_lw = lock_word_decrement_nest (old_lw);
+       else
+               new_lw.lock_word = 0;
+
+       tmp_lw.sync = InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, new_lw.sync, old_lw.sync);
+       if (old_lw.sync != tmp_lw.sync) {
+               /* Someone inflated the lock in the meantime */
+               mono_monitor_exit_inflated (obj);
+       }
+
+       LOCK_DEBUG (g_message ("%s: (%d) Object %p is now locked %d times; LW = %p", __func__, mono_thread_info_get_small_id (), obj, lock_word_get_nest (new_lw), obj->synchronisation));
+}
+
 static void
 mon_decrement_entry_count (MonoThreadsSync *mon)
 {
@@ -448,10 +737,10 @@ mon_decrement_entry_count (MonoThreadsSync *mon)
  * is requested. In this case it returns -1.
  */ 
 static inline gint32 
-mono_monitor_try_enter_internal (MonoObject *obj, guint32 ms, gboolean allow_interruption)
+mono_monitor_try_enter_inflated (MonoObject *obj, guint32 ms, gboolean allow_interruption, guint32 id)
 {
+       LockWord lw;
        MonoThreadsSync *mon;
-       gsize id = mono_thread_info_get_small_id ();
        HANDLE sem;
        guint32 then = 0, now, delta;
        guint32 waitms;
@@ -463,96 +752,13 @@ mono_monitor_try_enter_internal (MonoObject *obj, guint32 ms, gboolean allow_int
        LOCK_DEBUG (g_message("%s: (%d) Trying to lock object %p (%d ms)", __func__, id, obj, ms));
 
        if (G_UNLIKELY (!obj)) {
-               mono_raise_exception (mono_get_exception_argument_null ("obj"));
+               mono_set_pending_exception (mono_get_exception_argument_null ("obj"));
                return FALSE;
        }
 
+       lw.sync = obj->synchronisation;
+       mon = lock_word_get_inflated_lock (lw);
 retry:
-       mon = obj->synchronisation;
-
-       /* If the object has never been locked... */
-       if (G_UNLIKELY (mon == NULL)) {
-               mono_monitor_allocator_lock ();
-               mon = mon_new (id);
-               if (InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, mon, NULL) == NULL) {
-                       mono_gc_weak_link_add (&mon->data, obj, TRUE);
-                       mono_monitor_allocator_unlock ();
-                       /* Successfully locked */
-                       return 1;
-               } else {
-#ifdef HAVE_MOVING_COLLECTOR
-                       LockWord lw;
-                       lw.sync = obj->synchronisation;
-                       if (lw.lock_word & LOCK_WORD_THIN_HASH) {
-                               MonoThreadsSync *oldlw = lw.sync;
-                               /* move the already calculated hash */
-                               mon->hash_code = lw.lock_word >> LOCK_WORD_HASH_SHIFT;
-                               lw.sync = mon;
-                               lw.lock_word |= LOCK_WORD_FAT_HASH;
-                               if (InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, lw.sync, oldlw) == oldlw) {
-                                       mono_gc_weak_link_add (&mon->data, obj, TRUE);
-                                       mono_monitor_allocator_unlock ();
-                                       /* Successfully locked */
-                                       return 1;
-                               } else {
-                                       mon_finalize (mon);
-                                       mono_monitor_allocator_unlock ();
-                                       goto retry;
-                               }
-                       } else if (lw.lock_word & LOCK_WORD_FAT_HASH) {
-                               mon_finalize (mon);
-                               mono_monitor_allocator_unlock ();
-                               /* get the old lock without the fat hash bit */
-                               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-                               mon = lw.sync;
-                       } else {
-                               mon_finalize (mon);
-                               mono_monitor_allocator_unlock ();
-                               mon = obj->synchronisation;
-                       }
-#else
-                       mon_finalize (mon);
-                       mono_monitor_allocator_unlock ();
-                       mon = obj->synchronisation;
-#endif
-               }
-       } else {
-#ifdef HAVE_MOVING_COLLECTOR
-               LockWord lw;
-               lw.sync = mon;
-               if (lw.lock_word & LOCK_WORD_THIN_HASH) {
-                       MonoThreadsSync *oldlw = lw.sync;
-                       mono_monitor_allocator_lock ();
-                       mon = mon_new (id);
-                       /* move the already calculated hash */
-                       mon->hash_code = lw.lock_word >> LOCK_WORD_HASH_SHIFT;
-                       lw.sync = mon;
-                       lw.lock_word |= LOCK_WORD_FAT_HASH;
-                       if (InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, lw.sync, oldlw) == oldlw) {
-                               mono_gc_weak_link_add (&mon->data, obj, TRUE);
-                               mono_monitor_allocator_unlock ();
-                               /* Successfully locked */
-                               return 1;
-                       } else {
-                               mon_finalize (mon);
-                               mono_monitor_allocator_unlock ();
-                               goto retry;
-                       }
-               }
-#endif
-       }
-
-#ifdef HAVE_MOVING_COLLECTOR
-       {
-               LockWord lw;
-               lw.sync = mon;
-               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-               mon = lw.sync;
-       }
-#endif
-
-       /* If the object has previously been locked but isn't now... */
-
        /* This case differs from Dice's case 3 because we don't
         * deflate locks or cache unused lock records
         */
@@ -674,9 +880,9 @@ retry_contended:
         * We pass TRUE instead of allow_interruption since we have to check for the
         * StopRequested case below.
         */
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret = WaitForSingleObjectEx (mon->entry_sem, waitms, TRUE);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
        
@@ -737,6 +943,65 @@ retry_contended:
        }
 }
 
+/*
+ * If allow_interruption == TRUE, the method will be interrupted if abort or suspend
+ * is requested. In this case it returns -1.
+ */
+static inline gint32
+mono_monitor_try_enter_internal (MonoObject *obj, guint32 ms, gboolean allow_interruption)
+{
+       LockWord lw;
+       int id = mono_thread_info_get_small_id ();
+
+       LOCK_DEBUG (g_message("%s: (%d) Trying to lock object %p (%d ms)", __func__, id, obj, ms));
+
+       if (G_UNLIKELY (!obj)) {
+               mono_set_pending_exception (mono_get_exception_argument_null ("obj"));
+               return FALSE;
+       }
+
+       lw.sync = obj->synchronisation;
+
+       if (G_LIKELY (lock_word_is_free (lw))) {
+               LockWord nlw = lock_word_new_flat (id);
+               if (InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, nlw.sync, NULL) == NULL) {
+                       return 1;
+               } else {
+                       /* Someone acquired it in the meantime or put a hash */
+                       mono_monitor_inflate (obj);
+                       return mono_monitor_try_enter_inflated (obj, ms, allow_interruption, id);
+               }
+       } else if (lock_word_is_inflated (lw)) {
+               return mono_monitor_try_enter_inflated (obj, ms, allow_interruption, id);
+       } else if (lock_word_is_flat (lw)) {
+               if (lock_word_get_owner (lw) == id) {
+                       if (lock_word_is_max_nest (lw)) {
+                               mono_monitor_inflate_owned (obj, id);
+                               return mono_monitor_try_enter_inflated (obj, ms, allow_interruption, id);
+                       } else {
+                               LockWord nlw, old_lw;
+                               nlw = lock_word_increment_nest (lw);
+                               old_lw.sync = InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, nlw.sync, lw.sync);
+                               if (old_lw.sync != lw.sync) {
+                                       /* Someone else inflated it in the meantime */
+                                       g_assert (lock_word_is_inflated (old_lw));
+                                       return mono_monitor_try_enter_inflated (obj, ms, allow_interruption, id);
+                               }
+                               return 1;
+                       }
+               } else {
+                       mono_monitor_inflate (obj);
+                       return mono_monitor_try_enter_inflated (obj, ms, allow_interruption, id);
+               }
+       } else if (lock_word_has_hash (lw)) {
+               mono_monitor_inflate (obj);
+               return mono_monitor_try_enter_inflated (obj, ms, allow_interruption, id);
+       }
+
+       g_assert_not_reached ();
+       return -1;
+}
+
 gboolean 
 mono_monitor_enter (MonoObject *obj)
 {
@@ -752,90 +1017,37 @@ mono_monitor_try_enter (MonoObject *obj, guint32 ms)
 void
 mono_monitor_exit (MonoObject *obj)
 {
-       MonoThreadsSync *mon;
-       guint32 nest;
-       guint32 new_status, old_status, tmp_status;
+       LockWord lw;
        
        LOCK_DEBUG (g_message ("%s: (%d) Unlocking %p", __func__, mono_thread_info_get_small_id (), obj));
 
        if (G_UNLIKELY (!obj)) {
-               mono_raise_exception (mono_get_exception_argument_null ("obj"));
+               mono_set_pending_exception (mono_get_exception_argument_null ("obj"));
                return;
        }
 
-       mon = obj->synchronisation;
+       lw.sync = obj->synchronisation;
 
-#ifdef HAVE_MOVING_COLLECTOR
-       {
-               LockWord lw;
-               lw.sync = mon;
-               if (lw.lock_word & LOCK_WORD_THIN_HASH)
-                       return;
-               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-               mon = lw.sync;
-       }
-#endif
-       if (G_UNLIKELY (mon == NULL)) {
-               /* No one ever used Enter. Just ignore the Exit request as MS does */
-               return;
-       }
+       mono_monitor_ensure_owned (lw, mono_thread_info_get_small_id ());
 
-       old_status = mon->status;
-       if (G_UNLIKELY (mon_status_get_owner (old_status) != mono_thread_info_get_small_id ())) {
-               return;
-       }
-       
-       nest = mon->nest - 1;
-       if (nest == 0) {
-               /*
-                * Release lock and do the wakeup stuff. It's possible that
-                * the last blocking thread gave up waiting just before we
-                * release the semaphore resulting in a negative entry count
-                * and a futile wakeup next time there's contention for this
-                * object.
-                */
-               for (;;) {
-                       gboolean have_waiters = mon_status_have_waiters (old_status);
-       
-                       new_status = mon_status_set_owner (old_status, 0);
-                       if (have_waiters)
-                               new_status = mon_status_decrement_entry_count (new_status);
-                       tmp_status = InterlockedCompareExchange ((gint32*)&mon->status, new_status, old_status);
-                       if (tmp_status == old_status) {
-                               if (have_waiters)
-                                       ReleaseSemaphore (mon->entry_sem, 1, NULL);
-                               break;
-                       }
-                       old_status = tmp_status;
-               }
-               LOCK_DEBUG (g_message ("%s: (%d) Object %p is now unlocked", __func__, mono_thread_info_get_small_id (), obj));
-       
-               /* object is now unlocked, leave nest==1 so we don't
-                * need to set it when the lock is reacquired
-                */
-
-       } else {
-               LOCK_DEBUG (g_message ("%s: (%d) Object %p is now locked %d times", __func__, mono_thread_info_get_small_id (), obj, nest));
-               mon->nest = nest;
-       }
+       if (G_UNLIKELY (lock_word_is_inflated (lw)))
+               mono_monitor_exit_inflated (obj);
+       else
+               mono_monitor_exit_flat (obj, lw);
 }
 
 void**
 mono_monitor_get_object_monitor_weak_link (MonoObject *object)
 {
        LockWord lw;
-       MonoThreadsSync *sync = NULL;
 
        lw.sync = object->synchronisation;
-       if (lw.lock_word & LOCK_WORD_FAT_HASH) {
-               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-               sync = lw.sync;
-       } else if (!(lw.lock_word & LOCK_WORD_THIN_HASH)) {
-               sync = lw.sync;
-       }
 
-       if (sync && sync->data)
-               return &sync->data;
+       if (lock_word_is_inflated (lw)) {
+               MonoThreadsSync *mon = lock_word_get_inflated_lock (lw);
+               if (mon->data)
+                       return &mon->data;
+       }
        return NULL;
 }
 
@@ -889,8 +1101,11 @@ ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (MonoObject
 void
 mono_monitor_enter_v4 (MonoObject *obj, char *lock_taken)
 {
-       if (*lock_taken == 1)
-               mono_raise_exception (mono_get_exception_argument ("lockTaken", "lockTaken is already true"));
+
+       if (*lock_taken == 1) {
+               mono_set_pending_exception (mono_get_exception_argument ("lockTaken", "lockTaken is already true"));
+               return;
+       }
 
        ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (obj, INFINITE, lock_taken);
 }
@@ -898,27 +1113,16 @@ mono_monitor_enter_v4 (MonoObject *obj, char *lock_taken)
 gboolean 
 ves_icall_System_Threading_Monitor_Monitor_test_owner (MonoObject *obj)
 {
-       MonoThreadsSync *mon;
-       
+       LockWord lw;
+
        LOCK_DEBUG (g_message ("%s: Testing if %p is owned by thread %d", __func__, obj, mono_thread_info_get_small_id()));
 
-       mon = obj->synchronisation;
-#ifdef HAVE_MOVING_COLLECTOR
-       {
-               LockWord lw;
-               lw.sync = mon;
-               if (lw.lock_word & LOCK_WORD_THIN_HASH)
-                       return FALSE;
-               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-               mon = lw.sync;
-       }
-#endif
-       if (mon == NULL) {
-               return FALSE;
-       }
-       
-       if (mon_status_get_owner (mon->status) == mono_thread_info_get_small_id ()) {
-               return(TRUE);
+       lw.sync = obj->synchronisation;
+
+       if (lock_word_is_flat (lw)) {
+               return lock_word_get_owner (lw) == mono_thread_info_get_small_id ();
+       } else if (lock_word_is_inflated (lw)) {
+               return mon_status_get_owner (lock_word_get_inflated_lock (lw)->status) == mono_thread_info_get_small_id ();
        }
        
        return(FALSE);
@@ -927,29 +1131,18 @@ ves_icall_System_Threading_Monitor_Monitor_test_owner (MonoObject *obj)
 gboolean 
 ves_icall_System_Threading_Monitor_Monitor_test_synchronised (MonoObject *obj)
 {
-       MonoThreadsSync *mon;
+       LockWord lw;
 
        LOCK_DEBUG (g_message("%s: (%d) Testing if %p is owned by any thread", __func__, mono_thread_info_get_small_id (), obj));
-       
-       mon = obj->synchronisation;
-#ifdef HAVE_MOVING_COLLECTOR
-       {
-               LockWord lw;
-               lw.sync = mon;
-               if (lw.lock_word & LOCK_WORD_THIN_HASH)
-                       return FALSE;
-               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-               mon = lw.sync;
-       }
-#endif
-       if (mon == NULL) {
-               return FALSE;
-       }
-       
-       if (mon_status_get_owner (mon->status) != 0) {
-               return TRUE;
+
+       lw.sync = obj->synchronisation;
+
+       if (lock_word_is_flat (lw)) {
+               return !lock_word_is_free (lw);
+       } else if (lock_word_is_inflated (lw)) {
+               return mon_status_get_owner (lock_word_get_inflated_lock (lw)->status) != 0;
        }
-       
+
        return FALSE;
 }
 
@@ -961,34 +1154,26 @@ ves_icall_System_Threading_Monitor_Monitor_test_synchronised (MonoObject *obj)
 void
 ves_icall_System_Threading_Monitor_Monitor_pulse (MonoObject *obj)
 {
+       int id;
+       LockWord lw;
        MonoThreadsSync *mon;
-       
+
        LOCK_DEBUG (g_message ("%s: (%d) Pulsing %p", __func__, mono_thread_info_get_small_id (), obj));
        
-       mon = obj->synchronisation;
-#ifdef HAVE_MOVING_COLLECTOR
-       {
-               LockWord lw;
-               lw.sync = mon;
-               if (lw.lock_word & LOCK_WORD_THIN_HASH) {
-                       mono_set_pending_exception (mono_get_exception_synchronization_lock ("Not locked"));
-                       return;
-               }
-               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-               mon = lw.sync;
-       }
-#endif
-       if (mon == NULL) {
-               mono_set_pending_exception (mono_get_exception_synchronization_lock ("Not locked"));
-               return;
-       }
-       if (mon_status_get_owner (mon->status) != mono_thread_info_get_small_id ()) {
-               mono_set_pending_exception (mono_get_exception_synchronization_lock ("Not locked by this thread"));
+       id = mono_thread_info_get_small_id ();
+       lw.sync = obj->synchronisation;
+
+       mono_monitor_ensure_owned (lw, id);
+
+       if (!lock_word_is_inflated (lw)) {
+               /* No threads waiting. A wait would have inflated the lock */
                return;
        }
 
+       mon = lock_word_get_inflated_lock (lw);
+
        LOCK_DEBUG (g_message ("%s: (%d) %d threads waiting", __func__, mono_thread_info_get_small_id (), g_slist_length (mon->wait_list)));
-       
+
        if (mon->wait_list != NULL) {
                LOCK_DEBUG (g_message ("%s: (%d) signalling and dequeuing handle %p", __func__, mono_thread_info_get_small_id (), mon->wait_list->data));
        
@@ -1000,32 +1185,24 @@ ves_icall_System_Threading_Monitor_Monitor_pulse (MonoObject *obj)
 void
 ves_icall_System_Threading_Monitor_Monitor_pulse_all (MonoObject *obj)
 {
+       int id;
+       LockWord lw;
        MonoThreadsSync *mon;
        
        LOCK_DEBUG (g_message("%s: (%d) Pulsing all %p", __func__, mono_thread_info_get_small_id (), obj));
 
-       mon = obj->synchronisation;
-#ifdef HAVE_MOVING_COLLECTOR
-       {
-               LockWord lw;
-               lw.sync = mon;
-               if (lw.lock_word & LOCK_WORD_THIN_HASH) {
-                       mono_set_pending_exception (mono_get_exception_synchronization_lock ("Not locked"));
-                       return;
-               }
-               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-               mon = lw.sync;
-       }
-#endif
-       if (mon == NULL) {
-               mono_set_pending_exception (mono_get_exception_synchronization_lock ("Not locked"));
-               return;
-       }
-       if (mon_status_get_owner (mon->status) != mono_thread_info_get_small_id ()) {
-               mono_set_pending_exception (mono_get_exception_synchronization_lock ("Not locked by this thread"));
+       id = mono_thread_info_get_small_id ();
+       lw.sync = obj->synchronisation;
+
+       mono_monitor_ensure_owned (lw, id);
+
+       if (!lock_word_is_inflated (lw)) {
+               /* No threads waiting. A wait would have inflated the lock */
                return;
        }
 
+       mon = lock_word_get_inflated_lock (lw);
+
        LOCK_DEBUG (g_message ("%s: (%d) %d threads waiting", __func__, mono_thread_info_get_small_id (), g_slist_length (mon->wait_list)));
 
        while (mon->wait_list != NULL) {
@@ -1039,6 +1216,7 @@ ves_icall_System_Threading_Monitor_Monitor_pulse_all (MonoObject *obj)
 gboolean
 ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms)
 {
+       LockWord lw;
        MonoThreadsSync *mon;
        HANDLE event;
        guint32 nest;
@@ -1046,31 +1224,21 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms)
        gboolean success = FALSE;
        gint32 regain;
        MonoInternalThread *thread = mono_thread_internal_current ();
+       int id = mono_thread_info_get_small_id ();
 
        LOCK_DEBUG (g_message ("%s: (%d) Trying to wait for %p with timeout %dms", __func__, mono_thread_info_get_small_id (), obj, ms));
-       
-       mon = obj->synchronisation;
-#ifdef HAVE_MOVING_COLLECTOR
-       {
-               LockWord lw;
-               lw.sync = mon;
-               if (lw.lock_word & LOCK_WORD_THIN_HASH) {
-                       mono_set_pending_exception (mono_get_exception_synchronization_lock ("Not locked"));
-                       return FALSE;
-               }
-               lw.lock_word &= ~LOCK_WORD_BITS_MASK;
-               mon = lw.sync;
-       }
-#endif
-       if (mon == NULL) {
-               mono_set_pending_exception (mono_get_exception_synchronization_lock ("Not locked"));
-               return FALSE;
-       }
-       if (mon_status_get_owner (mon->status) != mono_thread_info_get_small_id ()) {
-               mono_set_pending_exception (mono_get_exception_synchronization_lock ("Not locked by this thread"));
-               return FALSE;
+
+       lw.sync = obj->synchronisation;
+
+       mono_monitor_ensure_owned (lw, id);
+
+       if (!lock_word_is_inflated (lw)) {
+               mono_monitor_inflate_owned (obj, id);
+               lw.sync = obj->synchronisation;
        }
 
+       mon = lock_word_get_inflated_lock (lw);
+
        /* Do this WaitSleepJoin check before creating the event handle */
        mono_thread_current_check_pending_interrupt ();
        
@@ -1091,7 +1259,8 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms)
        /* Save the nest count, and release the lock */
        nest = mon->nest;
        mon->nest = 1;
-       mono_monitor_exit (obj);
+       mono_memory_write_barrier ();
+       mono_monitor_exit_inflated (obj);
 
        LOCK_DEBUG (g_message ("%s: (%d) Unlocked %p lock %p", __func__, mono_thread_info_get_small_id (), obj, mon));
 
@@ -1100,9 +1269,9 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms)
         * is private to this thread.  Therefore even if the event was
         * signalled before we wait, we still succeed.
         */
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret = WaitForSingleObjectEx (event, ms, TRUE);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        /* Reset the thread state fairly early, so we don't have to worry
         * about the monitor error checking
@@ -1123,7 +1292,7 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms)
 
        /* Regain the lock with the previous nest count */
        do {
-               regain = mono_monitor_try_enter_internal (obj, INFINITE, TRUE);
+               regain = mono_monitor_try_enter_inflated (obj, INFINITE, TRUE, id);
                if (regain == -1) 
                        mono_thread_interruption_checkpoint ();
        } while (regain == -1);
@@ -1145,9 +1314,9 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms)
                /* Poll the event again, just in case it was signalled
                 * while we were trying to regain the monitor lock
                 */
-               MONO_PREPARE_BLOCKING
+               MONO_PREPARE_BLOCKING;
                ret = WaitForSingleObjectEx (event, 0, FALSE);
-               MONO_FINISH_BLOCKING
+               MONO_FINISH_BLOCKING;
        }
 
        /* Pulse will have popped our event from the queue if it signalled
index 0a7fe777eaad0dbbb75ecb6c0121f8d72bddb6e1..cc00f2044dc08d8638a7e1b0dfe4b4505ed18db1 100644 (file)
@@ -44,6 +44,62 @@ struct _MonoThreadsSync
        void *data;
 };
 
+/*
+ * Lock word format:
+ *
+ * The least significant bit stores whether a hash for the object is computed
+ * which is stored either in the lock word or in the MonoThreadsSync structure
+ * that the lock word points to.
+ *
+ * The second bit stores whether the lock word is inflated, containing an
+ * address to the MonoThreadsSync structure.
+ *
+ * If both bits are 0, either the lock word is free (entire lock word is 0)
+ * or it is a thin/flat lock.
+ *
+ * 32-bit
+ *            LOCK_WORD_FLAT:    [owner:22 | nest:8 | status:2]
+ *       LOCK_WORD_THIN_HASH:    [hash:30 | status:2]
+ *        LOCK_WORD_INFLATED:    [sync:30 | status:2]
+ *        LOCK_WORD_FAT_HASH:    [sync:30 | status:2]
+ *
+ * 64-bit
+ *            LOCK_WORD_FLAT:    [unused:22 | owner:32 | nest:8 | status:2]
+ *       LOCK_WORD_THIN_HASH:    [hash:62 | status:2]
+ *        LOCK_WORD_INFLATED:    [sync:62 | status:2]
+ *        LOCK_WORD_FAT_HASH:    [sync:62 | status:2]
+ *
+ * In order to save processing time and to have one additional value, the nest
+ * count starts from 0 for the lock word (just valid thread ID in the lock word
+ * means that the thread holds the lock once, although nest is 0).
+ * FIXME Have the same convention on inflated locks
+ */
+
+typedef union {
+#if SIZEOF_REGISTER == 8
+       guint64 lock_word;
+#elif SIZEOF_REGISTER == 4
+       guint32 lock_word;
+#endif
+       MonoThreadsSync *sync;
+} LockWord;
+
+
+enum {
+       LOCK_WORD_FLAT = 0,
+       LOCK_WORD_HAS_HASH = 1,
+       LOCK_WORD_INFLATED = 2,
+
+       LOCK_WORD_STATUS_BITS = 2,
+       LOCK_WORD_NEST_BITS = 8,
+
+       LOCK_WORD_STATUS_MASK = (1 << LOCK_WORD_STATUS_BITS) - 1,
+       LOCK_WORD_NEST_MASK = ((1 << LOCK_WORD_NEST_BITS) - 1) << LOCK_WORD_STATUS_BITS,
+
+       LOCK_WORD_HASH_SHIFT = LOCK_WORD_STATUS_BITS,
+       LOCK_WORD_NEST_SHIFT = LOCK_WORD_STATUS_BITS,
+       LOCK_WORD_OWNER_SHIFT = LOCK_WORD_STATUS_BITS + LOCK_WORD_NEST_BITS
+};
 
 MONO_API void mono_locks_dump (gboolean include_untaken);
 
index c8d7a6a10dbabdff4afc406795de473a1d29cf32..7ca1ebe857d0cba30c3ccc5eefa03abdff4df0a5 100644 (file)
@@ -65,6 +65,9 @@ struct _MonoGHashTable {
        MonoGHashGCType gc_type;
 };
 
+static MonoGHashTable *
+mono_g_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func);
+
 #ifdef HAVE_SGEN_GC
 static MonoGCDescriptor table_hash_descr = MONO_GC_DESCRIPTOR_NULL;
 
@@ -144,7 +147,7 @@ mono_g_hash_table_new_type (GHashFunc hash_func, GEqualFunc key_equal_func, Mono
        return hash;
 }
 
-MonoGHashTable *
+static MonoGHashTable *
 mono_g_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func)
 {
        MonoGHashTable *hash;
@@ -165,20 +168,6 @@ mono_g_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func)
        return hash;
 }
 
-MonoGHashTable *
-mono_g_hash_table_new_full (GHashFunc hash_func, GEqualFunc key_equal_func,
-                           GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
-{
-       MonoGHashTable *hash = mono_g_hash_table_new (hash_func, key_equal_func);
-       if (hash == NULL)
-               return NULL;
-       
-       hash->key_destroy_func = key_destroy_func;
-       hash->value_destroy_func = value_destroy_func;
-       
-       return hash;
-}
-
 typedef struct {
        MonoGHashTable *hash;
        int new_size;
index 9d382f15476457b2fd7b02a2b3242a927245dc17..970302d84db025307b7de777e9e42166bcc5b019 100644 (file)
@@ -23,9 +23,6 @@ typedef enum {
 typedef struct _MonoGHashTable MonoGHashTable;
 
 MONO_API MonoGHashTable *mono_g_hash_table_new_type (GHashFunc hash_func, GEqualFunc key_equal_func, MonoGHashGCType type);
-MONO_API MonoGHashTable *mono_g_hash_table_new      (GHashFunc hash_func, GEqualFunc key_equal_func);
-MONO_API MonoGHashTable *mono_g_hash_table_new_full (GHashFunc hash_func, GEqualFunc key_equal_func,
-                                                    GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func);
 MONO_API guint    mono_g_hash_table_size            (MonoGHashTable *hash);
 MONO_API gpointer mono_g_hash_table_lookup          (MonoGHashTable *hash, gconstpointer key);
 MONO_API gboolean mono_g_hash_table_lookup_extended (MonoGHashTable *hash, gconstpointer key, gpointer *orig_key, gpointer *value);
index 027d3e1b8a675b4d07ae1c5967789ffe0827ba0d..a303331d444f536ec9d60eb2a688953194dc851a 100644 (file)
@@ -634,10 +634,7 @@ mono_async_result_new          (MonoDomain *domain, HANDLE handle,
                             MonoObject *state, gpointer data, MonoObject *object_data);
 
 MonoObject *
-mono_async_result_invoke    (MonoAsyncResult *ares, MonoObject **exc);
-
-MonoObject *
-ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult *this_obj);
+ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult *ares);
 
 MonoWaitHandle *
 mono_wait_handle_new       (MonoDomain *domain, HANDLE handle);
index d729ffaeb8a6adc4247b966fcf9cf4f1a1ceff4f..fbf8a288446f3afb2d497ed34fde442de3e09b7e 100644 (file)
@@ -116,9 +116,9 @@ static mono_mutex_t type_initialization_section;
 static void
 mono_type_init_lock (TypeInitializationLock *lock)
 {
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        mono_mutex_lock (&lock->initialization_section);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 }
 
 static void
@@ -5783,29 +5783,23 @@ mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpo
 }
 
 MonoObject *
-mono_async_result_invoke (MonoAsyncResult *ares, MonoObject **exc)
+ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult *ares)
 {
        MonoAsyncCall *ac;
        MonoObject *res;
-       MonoInternalThread *thread;
 
        g_assert (ares);
        g_assert (ares->async_delegate);
 
-       thread = mono_thread_internal_current ();
-
        ac = (MonoAsyncCall*) ares->object_data;
        if (!ac) {
-               res = mono_runtime_delegate_invoke (ares->async_delegate, (void**) &ares->async_state, exc);
+               res = mono_runtime_delegate_invoke (ares->async_delegate, (void**) &ares->async_state, NULL);
        } else {
-               MonoArray *out_args = NULL;
                gpointer wait_event = NULL;
 
                ac->msg->exc = NULL;
-               res = mono_message_invoke (ares->async_delegate, ac->msg, exc, &out_args);
-               MONO_OBJECT_SETREF (ac->msg, exc, *exc);
+               res = mono_message_invoke (ares->async_delegate, ac->msg, &ac->msg->exc, &ac->out_args);
                MONO_OBJECT_SETREF (ac, res, res);
-               MONO_OBJECT_SETREF (ac, out_args, out_args);
 
                mono_monitor_enter ((MonoObject*) ares);
                ares->completed = 1;
@@ -5816,26 +5810,18 @@ mono_async_result_invoke (MonoAsyncResult *ares, MonoObject **exc)
                if (wait_event != NULL)
                        SetEvent (wait_event);
 
-               if (!ac->cb_method) {
-                       *exc = NULL;
-               } else {
-                       mono_runtime_invoke (ac->cb_method, ac->cb_target, (gpointer*) &ares, exc);
+               if (ac->cb_method) {
+                       /* we swallow the excepton as it is the behavior on .NET */
+                       MonoObject *exc = NULL;
+                       mono_runtime_invoke (ac->cb_method, ac->cb_target, (gpointer*) &ares, &exc);
+                       if (exc)
+                               mono_unhandled_exception (exc);
                }
        }
 
        return res;
 }
 
-MonoObject *
-ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult *this_obj)
-{
-       MonoObject *exc = NULL;
-       MonoObject *res = mono_async_result_invoke (this_obj, &exc);
-       if (exc)
-               mono_raise_exception ((MonoException*) exc);
-       return res;
-}
-
 void
 mono_message_init (MonoDomain *domain,
                   MonoMethodMessage *this_obj, 
@@ -5984,8 +5970,7 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
                object_array_klass = klass;
        }
 
-       /* FIXME: GC ensure we insert a write barrier for out_args, maybe in the caller? */
-       *out_args = mono_array_new_specific (mono_class_vtable (domain, object_array_klass), outarg_count);
+       mono_gc_wbarrier_generic_store (out_args, (MonoObject*) mono_array_new_specific (mono_class_vtable (domain, object_array_klass), outarg_count));
        *exc = NULL;
 
        ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
index f760b21a7748f94aedbf557c4ab0a27137a78c69..7aef3ad2e6095f3fb203843a5ece7843f2b09339 100644 (file)
@@ -36,6 +36,7 @@ typedef void*    (*MonoCompileFunc)        (MonoMethod *method);
 typedef void       (*MonoMainThreadFunc)    (void* user_data);
 
 #define MONO_OBJECT_SETREF(obj,fieldname,value) do {   \
+               g_assert (sizeof((obj)->fieldname) == sizeof (gpointer*));      \
                mono_gc_wbarrier_set_field ((MonoObject*)(obj), &((obj)->fieldname), (MonoObject*)value);       \
                /*(obj)->fieldname = (value);*/ \
        } while (0)
index b738510c1cc180b9faa9c5765b80be1242264688..d547e867fe6751c94ee5e48f5fd32790b4967f36 100644 (file)
@@ -663,10 +663,7 @@ MonoBoolean ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoPr
        } else {
                process_info->process_handle = shellex.hProcess;
                process_info->thread_handle = NULL;
-               /* It appears that there's no way to get the pid from a
-                * process handle before windows xp.  Really.
-                */
-#if defined(HAVE_GETPROCESSID) && !defined(MONO_CROSS_COMPILE)
+#if !defined(MONO_CROSS_COMPILE)
                process_info->pid = GetProcessId (shellex.hProcess);
 #else
                process_info->pid = 0;
@@ -807,14 +804,14 @@ MonoBoolean ves_icall_System_Diagnostics_Process_WaitForExit_internal (MonoObjec
 {
        guint32 ret;
        
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        if(ms<0) {
                /* Wait forever */
                ret=WaitForSingleObjectEx (process, INFINITE, TRUE);
        } else {
                ret=WaitForSingleObjectEx (process, ms, TRUE);
        }
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if(ret==WAIT_OBJECT_0) {
                return(TRUE);
index e2de7293ada5ce25514f6ca506d3417bb58ef10c..dcc60ecc5504a93656884ca5c78eb8ad47709457 100644 (file)
@@ -262,16 +262,11 @@ static inline MonoMethod*
 mono_marshal_remoting_find_in_cache (MonoMethod *method, int wrapper_type)
 {
        MonoMethod *res = NULL;
-       MonoRemotingMethods *wrps;
+       MonoRemotingMethods *wrps = NULL;
 
        mono_marshal_lock_internal ();
-       if (method->is_inflated && ((MonoMethodInflated *)method)->owner->wrapper_caches.remoting_invoke_cache) {
-               MonoMethodInflated *imethod = (MonoMethodInflated *)method;
-               wrps = g_hash_table_lookup (imethod->owner->wrapper_caches.remoting_invoke_cache, method);
-       } else if (method->klass->image->wrapper_caches.remoting_invoke_cache)
-               wrps = g_hash_table_lookup (method->klass->image->wrapper_caches.remoting_invoke_cache, method);
-       else
-               wrps = NULL;
+       if (mono_method_get_wrapper_cache (method)->remoting_invoke_cache)
+               wrps = g_hash_table_lookup (mono_method_get_wrapper_cache (method)->remoting_invoke_cache, method);
 
        if (wrps) {
                switch (wrapper_type) {
@@ -299,11 +294,7 @@ mono_remoting_mb_create_and_cache (MonoMethod *key, MonoMethodBuilder *mb,
        MonoRemotingMethods *wrps;
        GHashTable *cache;
 
-       if (key->is_inflated) {
-               MonoMethodInflated *imethod = (MonoMethodInflated *)key;
-               cache = get_cache_full (&imethod->owner->wrapper_caches.remoting_invoke_cache, mono_aligned_addr_hash, NULL, NULL, g_free);
-       } else
-               cache = get_cache_full (&key->klass->image->wrapper_caches.remoting_invoke_cache, mono_aligned_addr_hash, NULL, NULL, g_free);
+       cache = get_cache_full (&mono_method_get_wrapper_cache (key)->remoting_invoke_cache, mono_aligned_addr_hash, NULL, NULL, g_free);
 
        mono_marshal_lock_internal ();
        wrps = g_hash_table_lookup (cache, key);
diff --git a/mono/metadata/sgen-os-coop.c b/mono/metadata/sgen-os-coop.c
new file mode 100644 (file)
index 0000000..165c0d4
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * sgen-os-coop.c: SGen Cooperative backend support.
+ *
+ * Author:
+ *     João Matos (joao.matos@xamarin.com)
+ * Copyright (C) 2015 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+#ifdef HAVE_SGEN_GC
+
+
+#include <glib.h>
+#include "sgen/sgen-gc.h"
+#include "sgen/sgen-archdep.h"
+#include "sgen/sgen-protocol.h"
+#include "metadata/object-internals.h"
+#include "metadata/gc-internal.h"
+
+
+#if defined(USE_COOP_GC)
+
+gboolean
+sgen_resume_thread (SgenThreadInfo *info)
+{
+       g_error ("FIXME");
+       return FALSE;
+}
+
+gboolean
+sgen_suspend_thread (SgenThreadInfo *info)
+{
+       g_error ("FIXME");
+       return FALSE;
+}
+
+void
+sgen_wait_for_suspend_ack (int count)
+{
+}
+
+/* LOCKING: assumes the GC lock is held */
+int
+sgen_thread_handshake (BOOL suspend)
+{
+       g_error ("FIXME");
+       return 0;
+}
+
+void
+sgen_os_init (void)
+{
+}
+
+int
+mono_gc_get_suspend_signal (void)
+{
+       return -1;
+}
+
+int
+mono_gc_get_restart_signal (void)
+{
+       return -1;
+}
+
+#endif
+#endif
\ No newline at end of file
index db3297f15d7059d91f7f21ac2cb1d8610cc0e41c..46d30d81c4d664f3386c040356e0e60f2023ae4d 100644 (file)
@@ -137,7 +137,6 @@ sgen_thread_handshake (BOOL suspend)
        } END_FOREACH_THREAD_SAFE
        return count;
 }
-#endif
 
 void
 sgen_os_init (void)
@@ -157,3 +156,4 @@ mono_gc_get_restart_signal (void)
 }
 #endif
 #endif
+#endif
index d0aa841296abca3ffc5e6da7ec0a5080bf7ccacb..a45d6be1d9c44c13c527d31cfa2f4eded804f868 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "config.h"
 
-#ifdef HAVE_SGEN_GC
+#if defined(HAVE_SGEN_GC) && !defined(USE_COOP_GC)
 #if !defined(__MACH__) && !MONO_MACH_ARCH_SUPPORTED && defined(HAVE_PTHREAD_KILL)
 
 #include <errno.h>
index caddce127d60d81176fbfc5498913c6c818c7e45..475d8321378203b1ef83c3482f998149b2b6efba 100644 (file)
@@ -773,7 +773,7 @@ gpointer ves_icall_System_Net_Sockets_Socket_Accept_internal(SOCKET sock,
 {
        SOCKET newsock;
        MonoInternalThread* curthread G_GNUC_UNUSED = mono_thread_internal_current ();
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        
        *error = 0;
 #ifdef HOST_WIN32
@@ -785,7 +785,7 @@ gpointer ves_icall_System_Net_Sockets_Socket_Accept_internal(SOCKET sock,
 #else
        newsock = _wapi_accept (sock, NULL, 0);
 #endif
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if(newsock==INVALID_SOCKET) {
                *error = WSAGetLastError ();
@@ -976,9 +976,9 @@ extern MonoObject *ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal(SO
                return NULL;
        }
        sa = (salen <= 128) ? alloca (salen) : g_malloc0 (salen);
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret = _wapi_getsockname (sock, (struct sockaddr *)sa, &salen);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        
        if(ret==SOCKET_ERROR) {
                *error = WSAGetLastError ();
@@ -1011,9 +1011,9 @@ extern MonoObject *ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal(S
        }
        sa = (salen <= 128) ? alloca (salen) : g_malloc0 (salen);
        /* Note: linux returns just 2 for AF_UNIX. Always. */
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret = _wapi_getpeername (sock, (struct sockaddr *)sa, &salen);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        if(ret==SOCKET_ERROR) {
                *error = WSAGetLastError ();
                if (salen > 128)
@@ -1254,9 +1254,9 @@ extern void ves_icall_System_Net_Sockets_Socket_Connect_internal(SOCKET sock, Mo
        
        LOGDEBUG (g_message("%s: connecting to %s port %d", __func__, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port)));
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret = _wapi_connect (sock, sa, sa_size);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if(ret==SOCKET_ERROR) {
                *error = WSAGetLastError ();
@@ -1288,7 +1288,7 @@ extern void ves_icall_System_Net_Sockets_Socket_Disconnect_internal(SOCKET sock,
        LPFN_DISCONNECTEX _wapi_disconnectex = NULL;
        LPFN_TRANSMITFILE _wapi_transmitfile = NULL;
        gboolean bret;
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        
        *error = 0;
        
@@ -1340,7 +1340,7 @@ extern void ves_icall_System_Net_Sockets_Socket_Disconnect_internal(SOCKET sock,
                *error = WSAGetLastError ();
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 }
 
 gint32 ves_icall_System_Net_Sockets_Socket_Receive_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *error)
@@ -1366,7 +1366,7 @@ gint32 ves_icall_System_Net_Sockets_Socket_Receive_internal(SOCKET sock, MonoArr
                return (0);
        }
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 #ifdef HOST_WIN32
        {
                curthread->interrupt_on_stop = (gpointer)TRUE;
@@ -1376,7 +1376,7 @@ gint32 ves_icall_System_Net_Sockets_Socket_Receive_internal(SOCKET sock, MonoArr
 #else
        ret = _wapi_recv (sock, buf, count, recvflags);
 #endif
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if(ret==SOCKET_ERROR) {
                *error = WSAGetLastError ();
@@ -1442,9 +1442,9 @@ gint32 ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal(SOCKET sock, Mon
                return (0);
        }
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret = _wapi_recvfrom (sock, buf, count, recvflags, sa, &sa_size);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if(ret==SOCKET_ERROR) {
                g_free(sa);
@@ -1492,9 +1492,9 @@ gint32 ves_icall_System_Net_Sockets_Socket_Send_internal(SOCKET sock, MonoArray
                return (0);
        }
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret = _wapi_send (sock, buf, count, sendflags);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        if(ret==SOCKET_ERROR) {
                *error = WSAGetLastError ();
                return(0);
@@ -1563,9 +1563,9 @@ gint32 ves_icall_System_Net_Sockets_Socket_SendTo_internal(SOCKET sock, MonoArra
                return (0);
        }
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret = _wapi_sendto (sock, buf, count, sendflags, sa, sa_size);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        if(ret==SOCKET_ERROR) {
                *error = WSAGetLastError ();
        }
@@ -2189,19 +2189,18 @@ void ves_icall_System_Net_Sockets_Socket_Shutdown_internal(SOCKET sock,
                                                           gint32 *error)
 {
        int ret;
-       MONO_PREPARE_BLOCKING
 
        *error = 0;
        
        /* Currently, the values for how (recv=0, send=1, both=2) match
         * the BSD API
         */
+       MONO_PREPARE_BLOCKING;
        ret = _wapi_shutdown (sock, how);
+       MONO_FINISH_BLOCKING;
        if(ret==SOCKET_ERROR) {
                *error = WSAGetLastError ();
        }
-
-       MONO_FINISH_BLOCKING
 }
 
 gint
@@ -2381,12 +2380,11 @@ MonoBoolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, Mo
        char *hostname = mono_string_to_utf8 (host);
        int hint = get_addrinfo_family_hint ();
 
-       MONO_PREPARE_BLOCKING
-
        if (*hostname == '\0') {
                add_local_ips = TRUE;
                *h_name = host;
        }
+       MONO_PREPARE_BLOCKING;
        if (!add_local_ips && gethostname (this_hostname, sizeof (this_hostname)) != -1) {
                if (!strcmp (hostname, this_hostname)) {
                        add_local_ips = TRUE;
@@ -2398,7 +2396,7 @@ MonoBoolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, Mo
                add_info_ok = FALSE;
 
        g_free(hostname);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if (add_info_ok)
                return addrinfo_to_IPHostEntry(info, h_name, h_aliases, h_addr_list, add_local_ips);
@@ -2417,8 +2415,6 @@ extern MonoBoolean ves_icall_System_Net_Dns_GetHostByAddr_internal(MonoString *a
        int hint = get_addrinfo_family_hint ();
        gboolean add_info_ok;
 
-       MONO_PREPARE_BLOCKING
-
        address = mono_string_to_utf8 (addr);
 
        if (inet_pton (AF_INET, address, &saddr.sin_addr ) <= 0) {
@@ -2438,6 +2434,8 @@ extern MonoBoolean ves_icall_System_Net_Dns_GetHostByAddr_internal(MonoString *a
        }
        g_free(address);
 
+       MONO_PREPARE_BLOCKING;
+
        if(family == AF_INET) {
 #if HAVE_SOCKADDR_IN_SIN_LEN
                saddr.sin_len = sizeof (saddr);
@@ -2459,7 +2457,7 @@ extern MonoBoolean ves_icall_System_Net_Dns_GetHostByAddr_internal(MonoString *a
        }
 
        add_info_ok = !mono_get_address_info (hostname, 0, hint | MONO_HINT_CANONICAL_NAME | MONO_HINT_CONFIGURED_ONLY, &info);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if (add_info_ok)
                return addrinfo_to_IPHostEntry (info, h_name, h_aliases, h_addr_list, FALSE);
index c1eb63b2d15529300d08faa91d79f246ff556d56..b9a5a8d07601abde9c9d6d27f8909a1c8f27b278 100644 (file)
@@ -492,6 +492,8 @@ worker_park (void)
 
        mono_gc_set_skip_thread (TRUE);
 
+       MONO_PREPARE_BLOCKING;
+
        mono_mutex_lock (&threadpool->active_threads_lock);
 
        if (!mono_runtime_is_shutting_down ()) {
@@ -506,6 +508,8 @@ worker_park (void)
 
        mono_mutex_unlock (&threadpool->active_threads_lock);
 
+       MONO_FINISH_BLOCKING;
+
        mono_gc_set_skip_thread (FALSE);
 
        mono_cond_destroy (&cond);
@@ -1304,7 +1308,7 @@ mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, Mono
                return NULL;
        }
 
-       MONO_OBJECT_SETREF (ares, endinvoke_called, 1);
+       ares->endinvoke_called = 1;
 
        /* wait until we are really finished */
        if (ares->completed) {
@@ -1319,9 +1323,9 @@ mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, Mono
                        MONO_OBJECT_SETREF (ares, handle, (MonoObject*) mono_wait_handle_new (mono_object_domain (ares), wait_event));
                }
                mono_monitor_exit ((MonoObject*) ares);
-               MONO_PREPARE_BLOCKING
+               MONO_PREPARE_BLOCKING;
                WaitForSingleObjectEx (wait_event, INFINITE, TRUE);
-               MONO_FINISH_BLOCKING
+               MONO_FINISH_BLOCKING;
        }
 
        ac = (MonoAsyncCall*) ares->object_data;
@@ -1370,9 +1374,9 @@ mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout)
        mono_memory_write_barrier ();
 
        while (domain->threadpool_jobs) {
-               MONO_PREPARE_BLOCKING
+               MONO_PREPARE_BLOCKING;
                WaitForSingleObject (sem, timeout);
-               MONO_FINISH_BLOCKING
+               MONO_FINISH_BLOCKING;
                if (timeout != -1) {
                        timeout -= mono_msec_ticks () - start;
                        if (timeout <= 0) {
index 3a4e53eb5a231af2ac1810d03fca8f933d561ddb..a7de6445040dbe5a69dbc3664f1230c40e0c7430 100644 (file)
@@ -232,9 +232,9 @@ static gint32 managed_thread_id_counter = 0;
 static void
 mono_threads_lock (void)
 {
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        mono_locks_acquire (&threads_mutex, ThreadsLock);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 }
 
 static void
@@ -379,9 +379,9 @@ lock_thread (MonoInternalThread *thread)
 
        g_assert (thread->synch_cs);
 
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        mono_mutex_lock (thread->synch_cs);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 }
 
 static inline void
@@ -804,7 +804,7 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
         */
        if (thread_start_args == NULL) {
                MONO_GC_REGISTER_ROOT_FIXED (thread_start_args);
-               thread_start_args = mono_g_hash_table_new (NULL, NULL);
+               thread_start_args = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_CONSERVATIVE_GC);
        }
        mono_g_hash_table_insert (thread_start_args, thread, start_info->start_arg);
        if (threads_starting_up == NULL) {
@@ -832,10 +832,10 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
         */
        create_flags = CREATE_SUSPENDED;
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        thread_handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)start_wrapper, start_info,
                                                                                                stack_size, create_flags, &tid);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if (thread_handle == NULL) {
                /* The thread couldn't be created, so throw an exception */
@@ -867,9 +867,9 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
        if (!handle_store (thread, FALSE))
                return FALSE;
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        mono_thread_info_resume (tid);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if (internal->start_notify) {
                /*
@@ -880,9 +880,9 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
                 */
                THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
 
-               MONO_PREPARE_BLOCKING
+               MONO_PREPARE_BLOCKING;
                WaitForSingleObjectEx (internal->start_notify, INFINITE, FALSE);
-               MONO_FINISH_BLOCKING
+               MONO_FINISH_BLOCKING;
 
                CloseHandle (internal->start_notify);
                internal->start_notify = NULL;
@@ -1194,9 +1194,9 @@ ves_icall_System_Threading_Thread_Sleep_internal(gint32 ms)
        while (TRUE) {
                mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
        
-               MONO_PREPARE_BLOCKING
+               MONO_PREPARE_BLOCKING;
                res = SleepEx(ms,TRUE);
-               MONO_FINISH_BLOCKING
+               MONO_FINISH_BLOCKING;
        
                mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
 
@@ -1412,9 +1412,9 @@ ves_icall_System_Threading_Thread_Join_internal(MonoThread *this_obj, int ms)
        
        mono_thread_set_state (cur_thread, ThreadState_WaitSleepJoin);
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret=WaitForSingleObjectEx (handle, ms, TRUE);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        mono_thread_clr_state (cur_thread, ThreadState_WaitSleepJoin);
        
@@ -1440,12 +1440,12 @@ mono_wait_uninterrupted (MonoInternalThread *thread, gboolean multiple, guint32
 
        start = (ms == -1) ? 0 : mono_100ns_ticks ();
        do {
-               MONO_PREPARE_BLOCKING
+               MONO_PREPARE_BLOCKING;
                        if (multiple)
                        ret = WaitForMultipleObjectsEx (numhandles, handles, waitall, wait, alertable);
                else
                        ret = WaitForSingleObjectEx (handles [0], ms, alertable);
-               MONO_FINISH_BLOCKING
+               MONO_FINISH_BLOCKING;
 
                if (ret != WAIT_IO_COMPLETION)
                        break;
@@ -1606,9 +1606,9 @@ ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, H
 
        mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
        
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret = SignalObjectAndWait (toSignal, toWait, ms, TRUE);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
 
@@ -2709,9 +2709,9 @@ static void wait_for_tids (struct wait_data *wait, guint32 timeout)
        
        THREAD_DEBUG (g_message("%s: %d threads to wait for in this batch", __func__, wait->num));
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret=WaitForMultipleObjectsEx(wait->num, wait->handles, TRUE, timeout, TRUE);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if(ret==WAIT_FAILED) {
                /* See the comment in build_wait_tids() */
@@ -2772,9 +2772,9 @@ static void wait_for_tids_or_state_change (struct wait_data *wait, guint32 timeo
                count++;
        }
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        ret=WaitForMultipleObjectsEx (count, wait->handles, FALSE, timeout, TRUE);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if(ret==WAIT_FAILED) {
                /* See the comment in build_wait_tids() */
@@ -3180,7 +3180,7 @@ print_stack_frame_to_string (MonoStackFrameInfo *frame, MonoContext *ctx, gpoint
 {
        GString *p = (GString*)data;
        MonoMethod *method = NULL;
-       if (frame->ji)
+       if (frame->type == FRAME_TYPE_MANAGED)
                method = mono_jit_info_get_method (frame->ji);
 
        if (method) {
@@ -4028,8 +4028,9 @@ mono_thread_execute_interruption (MonoInternalThread *thread)
                WaitForSingleObjectEx (GetCurrentThread(), 0, TRUE);
 #endif
                InterlockedDecrement (&thread_interruption_requested);
+
                /* Clear the interrupted flag of the thread so it can wait again */
-               mono_thread_info_clear_interruption ();
+               mono_thread_info_clear_self_interrupt ();
        }
 
        if ((thread->state & ThreadState_AbortRequested) != 0) {
@@ -4399,7 +4400,7 @@ mono_thread_info_get_last_managed (MonoThreadInfo *info)
 typedef struct {
        MonoInternalThread *thread;
        gboolean install_async_abort;
-       gpointer interrupt_handle;
+       MonoThreadInfoInterruptToken *interrupt_token;
 } AbortThreadData;
 
 static SuspendThreadResult
@@ -4421,7 +4422,7 @@ abort_thread_critical (MonoThreadInfo *info, gpointer ud)
        InterlockedIncrement (&thread_interruption_requested);
 
        ji = mono_thread_info_get_last_managed (info);
-       protected_wrapper = ji && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
+       protected_wrapper = ji && !ji->is_trampoline && !ji->async && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
        running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx));
 
        if (!protected_wrapper && running_managed) {
@@ -4442,7 +4443,8 @@ abort_thread_critical (MonoThreadInfo *info, gpointer ud)
                 * functions in the io-layer until the signal handler calls QueueUserAPC which will
                 * make it return.
                 */
-               data->interrupt_handle = mono_thread_info_prepare_interrupt (thread->handle);
+               data->interrupt_token = mono_thread_info_prepare_interrupt (info);
+
                return MonoResumeThread;
        }
 }
@@ -4463,20 +4465,22 @@ abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception,
                MonoException *exc = mono_thread_request_interruption (can_raise_exception); 
                if (exc)
                        mono_raise_exception (exc);
-               mono_thread_info_interrupt (thread->handle);
+
+               mono_thread_info_self_interrupt ();
+
                return;
        }
 
        mono_thread_info_safe_suspend_and_run ((MonoNativeThreadId)(gsize)thread->tid, TRUE, abort_thread_critical, &data);
-       if (data.interrupt_handle)
-               mono_thread_info_finish_interrupt (data.interrupt_handle);
+       if (data.interrupt_token)
+               mono_thread_info_finish_interrupt (data.interrupt_token);
        /*FIXME we need to wait for interruption to complete -- figure out how much into interruption we should wait for here*/
 }
 
 typedef struct{
        MonoInternalThread *thread;
        gboolean interrupt;
-       gpointer interrupt_handle;
+       MonoThreadInfoInterruptToken *interrupt_token;
 } SuspendThreadData;
 
 static SuspendThreadResult
@@ -4489,7 +4493,7 @@ suspend_thread_critical (MonoThreadInfo *info, gpointer ud)
        gboolean running_managed;
 
        ji = mono_thread_info_get_last_managed (info);
-       protected_wrapper = ji && !ji->async && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
+       protected_wrapper = ji && !ji->is_trampoline && !ji->async && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
        running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx));
 
        if (running_managed && !protected_wrapper) {
@@ -4500,7 +4504,7 @@ suspend_thread_critical (MonoThreadInfo *info, gpointer ud)
                if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 0)
                        InterlockedIncrement (&thread_interruption_requested);
                if (data->interrupt)
-                       data->interrupt_handle = mono_thread_info_prepare_interrupt (thread->handle);
+                       data->interrupt_token = mono_thread_info_prepare_interrupt (thread->thread_info);
                
                if (mono_thread_notify_pending_exc_fn && !running_managed)
                        /* The JIT will notify the thread about the interruption */
@@ -4526,8 +4530,8 @@ suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt)
                data.interrupt = interrupt;
 
                mono_thread_info_safe_suspend_and_run ((MonoNativeThreadId)(gsize)thread->tid, interrupt, suspend_thread_critical, &data);
-               if (data.interrupt_handle)
-                       mono_thread_info_finish_interrupt (data.interrupt_handle);
+               if (data.interrupt_token)
+                       mono_thread_info_finish_interrupt (data.interrupt_token);
                UNLOCK_THREAD (thread);
        }
 }
index ee02ad4f7becedc289f30935906466e8edc32827..f9d17cfb1e31d21244f99c51c7899f5d0c10da5a 100755 (executable)
@@ -6,7 +6,7 @@ monodir=$(top_builddir)
 libgc_libs=$(monodir)/libgc/libmonogc.la
 libgc_static_libs=$(monodir)/libgc/libmonogc-static.la
 
-libs=  \
+boehm_libs=    \
        $(monodir)/mono/metadata/libmonoruntime.la      \
        $(monodir)/mono/io-layer/libwapi.la     \
        $(monodir)/mono/utils/libmonoutils.la \
@@ -20,14 +20,14 @@ sgen_libs = \
        $(monodir)/mono/utils/libmonoutils.la \
        $(GLIB_LIBS) $(LIBICONV)
 
-static_libs=   \
+boehm_static_libs=     \
        $(monodir)/mono/metadata/libmonoruntime-static.la       \
        $(monodir)/mono/io-layer/libwapi.la     \
        $(monodir)/mono/utils/libmonoutils.la \
        $(GLIB_LIBS) $(LIBICONV) \
        $(libgc_static_libs)
 
-sgenstatic_libs = \
+sgen_static_libs = \
        $(monodir)/mono/metadata/libmonoruntimesgen-static.la   \
        $(monodir)/mono/sgen/libmonosgen-static.la      \
        $(monodir)/mono/io-layer/libwapi.la     \
@@ -78,16 +78,16 @@ endif
 if SUPPORT_SGEN
 sgen_binaries = mono-sgen
 sgen_libraries = libmonosgen-2.0.la
-sgen_static_libraries = libmini-static.la $(sgenstatic_libs)
+sgen_static_libraries = libmini-static.la $(sgen_static_libs)
 endif
 
 if SUPPORT_BOEHM
 boehm_libraries = libmonoboehm-2.0.la
-boehm_static_libraries = libmini-static.la $(static_libs)
+boehm_static_libraries = libmini-static.la $(boehm_static_libs)
 boehm_binaries  = mono-boehm
 endif
 
-#The mono uses sgen, while libmono remains boehm
+# The mono executable uses sgen, while libmono remains boehm
 if SUPPORT_SGEN
 mono_bin_suffix = sgen
 else
@@ -152,7 +152,7 @@ libmono_llvm_la_LIBADD = $(GLIB_LIBS) $(LLVM_LIBS) $(LLVM_LDFLAGS)
 if PLATFORM_DARWIN
 libmono_llvm_la_LDFLAGS=-Wl,-undefined -Wl,suppress -Wl,-flat_namespace
 else
-libmono_llvm_la_LIBADD += $(top_builddir)/mono/mini/libmonoboehm-$(API_VER).la $(libs)
+libmono_llvm_la_LIBADD += $(top_builddir)/mono/mini/libmonoboehm-$(API_VER).la $(boehm_libs)
 endif
 endif
 
@@ -541,7 +541,7 @@ libmini_la_CFLAGS = $(mono_CFLAGS)
 
 libmonoboehm_2_0_la_SOURCES =
 libmonoboehm_2_0_la_CFLAGS = $(mono_boehm_CFLAGS)
-libmonoboehm_2_0_la_LIBADD = libmini.la $(libs) $(LIBMONO_DTRACE_OBJECT) $(LLVMMONOF)
+libmonoboehm_2_0_la_LIBADD = libmini.la $(boehm_libs) $(LIBMONO_DTRACE_OBJECT) $(LLVMMONOF)
 libmonoboehm_2_0_la_LDFLAGS = $(libmonoldflags)
 
 libmonosgen_2_0_la_SOURCES =
@@ -683,16 +683,36 @@ gsharedvtcheck:
 
 fullaot_regtests = $(regtests) aot-tests.exe $(if $(GSHAREDVT),gshared.exe)
 
+FULLAOT_LIBS = \
+       mscorlib.dll \
+       System.Core.dll \
+       System.dll \
+       Mono.Posix.dll \
+       System.Configuration.dll \
+       System.Security.dll \
+       System.Xml.dll \
+       Mono.Security.dll \
+       Mono.Simd.dll
+
 # This currently only works on amd64/arm
 fullaotcheck: mono $(fullaot_regtests)
        rm -rf fullaot-tmp
        mkdir fullaot-tmp
-       cp $(CLASS)/mscorlib.dll $(CLASS)/System.Core.dll $(CLASS)/System.dll $(CLASS)/Mono.Posix.dll $(CLASS)/System.Configuration.dll $(CLASS)/System.Security.dll $(CLASS)/System.Xml.dll $(CLASS)/Mono.Security.dll $(CLASS)/Mono.Simd.dll $(regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
-       cp $(fullaot_regtests) fullaot-tmp/
-       MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot=full fullaot-tmp/* || exit 1
+       $(MAKE) fullaot-libs AOT_FLAGS=full
+       cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
+       MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot=full fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
        ln -s $$PWD/mono fullaot-tmp/
        for i in $(fullaot_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --full-aot fullaot-tmp/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done
 
+# This can run in parallel
+fullaot-libs: $(patsubst %,fullaot-tmp/%.dylib,$(FULLAOT_LIBS))
+
+fullaot-tmp/%.dylib: $(CLASS)/%
+       cp $(CLASS)/$* fullaot-tmp/
+       mkdir fullaot-tmp/$*-tmp
+       MONO_PATH=fullaot-tmp/:$(CLASS) $(top_builddir)/runtime/mono-wrapper --aot=$(AOT_FLAGS),temp-path=fullaot-tmp/$*-tmp fullaot-tmp/$*
+       rm -rf fullaot-tmp/$*-tmp
+
 llvmfullaotcheck:
        $(MAKE) fullaotcheck LLVM=1
 
index c9e50793c1d52795125a5ae35a622c9872556d39..0e5fac63d80cdb7e06b32a517892f5890a19e9db 100644 (file)
@@ -42,7 +42,6 @@
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/gc-internal.h>
-#include <mono/metadata/monitor.h>
 #include <mono/metadata/mempool-internals.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/threads-types.h>
@@ -298,6 +297,9 @@ get_patch_name (int info)
 
 #endif
 
+static guint32
+get_unwind_info_offset (MonoAotCompile *acfg, guint8 *encoded, guint32 encoded_len);
+
 static char*
 get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache);
 
@@ -1196,6 +1198,22 @@ arch_emit_llvm_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offs
 #endif
 }
 
+/* Save unwind_info in the module and emit the offset to the information at symbol */
+static void save_unwind_info (MonoAotCompile *acfg, char *symbol, GSList *unwind_ops)
+{
+       guint32 uw_offset, encoded_len;
+       guint8 *encoded;
+
+       emit_section_change (acfg, RODATA_SECT, 0);
+       emit_global (acfg, symbol, FALSE);
+       emit_label (acfg, symbol);
+
+       encoded = mono_unwind_ops_encode (unwind_ops, &encoded_len);
+       uw_offset = get_unwind_info_offset (acfg, encoded, encoded_len);
+       g_free (encoded);
+       emit_int32 (acfg, uw_offset);
+}
+
 /*
  * arch_emit_specific_trampoline_pages:
  *
@@ -1219,6 +1237,7 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        guint8 *loop_start, *loop_branch_back, *loop_end_check, *imt_found_check;
        int i;
        int pagesize = MONO_AOT_TRAMP_PAGE_SIZE;
+       GSList *unwind_ops = NULL;
 #define COMMON_TRAMP_SIZE 16
        int count = (pagesize - COMMON_TRAMP_SIZE) / 8;
        int imm8, rot_amount;
@@ -1311,7 +1330,6 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        /* now the imt trampolines: each specific trampolines puts in the ip register
         * the instruction pointer address, so the generic trampoline at the start of the page
         * subtracts 4096 to get to the data page and loads the values
-        * We again fit the generic trampiline in 16 bytes.
         */
 #define IMT_TRAMP_SIZE 72
        sprintf (symbol, "%simt_trampolines_page", acfg->user_symbol_prefix);
@@ -1377,6 +1395,53 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = 16;
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = 72;
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16;
+
+       /* Unwind info for specifc trampolines */
+       sprintf (symbol, "%sspecific_trampolines_page_gen_p", acfg->user_symbol_prefix);
+       /* We unwind to the original caller, from the stack, since lr is clobbered */
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 14 * sizeof (mgreg_t));
+       mono_add_unwind_op_offset (unwind_ops, 0, 0, ARMREG_LR, -4);
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       sprintf (symbol, "%sspecific_trampolines_page_sp_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 14 * sizeof (mgreg_t));
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       /* Unwind info for rgctx trampolines */
+       sprintf (symbol, "%srgctx_trampolines_page_gen_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       save_unwind_info (acfg, symbol, unwind_ops);
+
+       sprintf (symbol, "%srgctx_trampolines_page_sp_p", acfg->user_symbol_prefix);
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       /* Unwind info for gsharedvt trampolines */
+       sprintf (symbol, "%sgsharedvt_trampolines_page_gen_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 4 * sizeof (mgreg_t));
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       sprintf (symbol, "%sgsharedvt_trampolines_page_sp_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       /* Unwind info for imt trampolines */
+       sprintf (symbol, "%simt_trampolines_page_gen_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 3 * sizeof (mgreg_t));
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       sprintf (symbol, "%simt_trampolines_page_sp_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
 #elif defined(TARGET_ARM64)
        arm64_emit_specific_trampoline_pages (acfg);
 #endif
@@ -1546,14 +1611,6 @@ arch_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size
 
        /* FIXME: Could this clobber the register needed by get_vcall_slot () ? */
 
-       /* We clobber ECX, since EAX is used as MONO_ARCH_MONITOR_OBJECT_REG */
-#ifdef MONO_ARCH_MONITOR_OBJECT_REG
-       g_assert (MONO_ARCH_MONITOR_OBJECT_REG != X86_ECX);
-#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
-       g_assert (MONO_ARCH_MONITOR_LOCK_TAKEN_REG != X86_ECX);
-#endif
-#endif
-
        code = buf;
        /* Load mscorlib got address */
        x86_mov_reg_membase (code, X86_ECX, MONO_ARCH_GOT_REG, sizeof (gpointer), 4);
@@ -3138,9 +3195,6 @@ is_plt_patch (MonoJumpInfo *patch_info)
        case MONO_PATCH_INFO_JIT_ICALL_ADDR:
        case MONO_PATCH_INFO_ICALL_ADDR:
        case MONO_PATCH_INFO_RGCTX_FETCH:
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-       case MONO_PATCH_INFO_MONITOR_EXIT:
        case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
                return TRUE;
        default:
@@ -5372,9 +5426,6 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                encode_patch (acfg, entry->data, p, &p);
                break;
        }
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-       case MONO_PATCH_INFO_MONITOR_EXIT:
        case MONO_PATCH_INFO_SEQ_POINT_INFO:
                break;
        case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
@@ -6194,7 +6245,7 @@ emit_trampoline_full (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info,
 static G_GNUC_UNUSED void
 emit_trampoline (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info)
 {
-       emit_trampoline_full (acfg, got_offset, info, FALSE);
+       emit_trampoline_full (acfg, got_offset, info, TRUE);
 }
 
 static void
@@ -6239,17 +6290,6 @@ emit_trampolines (MonoAotCompile *acfg)
                        emit_trampoline (acfg, acfg->got_offset, info);
                }
 
-#if defined(MONO_ARCH_MONITOR_OBJECT_REG)
-               mono_arch_create_monitor_enter_trampoline (&info, FALSE, TRUE);
-               emit_trampoline (acfg, acfg->got_offset, info);
-#if defined(MONO_ARCH_MONITOR_LOCK_TAKEN_REG)
-               mono_arch_create_monitor_enter_trampoline (&info, TRUE, TRUE);
-               emit_trampoline (acfg, acfg->got_offset, info);
-#endif
-               mono_arch_create_monitor_exit_trampoline (&info, TRUE);
-               emit_trampoline (acfg, acfg->got_offset, info);
-#endif
-
                /* Emit the exception related code pieces */
                mono_arch_get_restore_context (&info, TRUE);
                emit_trampoline (acfg, acfg->got_offset, info);
@@ -7543,6 +7583,7 @@ static void
 emit_code (MonoAotCompile *acfg)
 {
        int oindex, i, prev_index;
+       gboolean saved_unbox_info = FALSE;
        char symbol [256];
 
 #if defined(TARGET_POWERPC64)
@@ -7610,6 +7651,23 @@ emit_code (MonoAotCompile *acfg)
 
                        if (acfg->thumb_mixed && cfg->compile_llvm)
                                emit_set_arm_mode (acfg);
+
+                       if (!saved_unbox_info) {
+                               char user_symbol [128];
+                               GSList *unwind_ops;
+                               sprintf (user_symbol, "%sunbox_trampoline_p", acfg->user_symbol_prefix);
+
+                               emit_label (acfg, "ut_end");
+
+                               unwind_ops = mono_unwind_get_cie_program ();
+                               save_unwind_info (acfg, user_symbol, unwind_ops);
+                               mono_free_unwind_info (unwind_ops);
+
+                               /* Save the unbox trampoline size */
+                               emit_symbol_diff (acfg, "ut_end", symbol, 0);
+
+                               saved_unbox_info = TRUE;
+                       }
                }
 
                if (cfg->compile_llvm)
@@ -9137,7 +9195,7 @@ compile_asm (MonoAotCompile *acfg)
        tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
 
        if (acfg->llvm) {
-               llvm_ofile = g_strdup (acfg->llvm_ofile);
+               llvm_ofile = g_strdup_printf ("\"%s\"", acfg->llvm_ofile);
        } else {
                llvm_ofile = g_strdup ("");
        }
@@ -9146,7 +9204,7 @@ compile_asm (MonoAotCompile *acfg)
        g_strdelimit (ld_flags, ";", ' ');
 
 #ifdef LD_NAME
-       command = g_strdup_printf ("%s -o %s %s %s.o %s", LD_NAME, tmp_outfile_name, llvm_ofile, acfg->tmpfname, ld_flags);
+       command = g_strdup_printf ("%s -o \"%s\" %s \"%s.o\" %s", LD_NAME, tmp_outfile_name, llvm_ofile, acfg->tmpfname, ld_flags);
 #else
        command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s.o %s", tool_prefix, LD_OPTIONS, tmp_outfile_name, llvm_ofile,
                acfg->tmpfname, ld_flags);
@@ -9187,7 +9245,7 @@ compile_asm (MonoAotCompile *acfg)
        rename (tmp_outfile_name, outfile_name);
 
 #if defined(TARGET_MACH)
-       command = g_strdup_printf ("dsymutil %s", outfile_name);
+       command = g_strdup_printf ("dsymutil \"%s\"", outfile_name);
        aot_printf (acfg, "Executing dsymutil: %s\n", command);
        if (execute_system (command) != 0) {
                return 1;
index 868b4fa6fbb9b77ac259fa5449a9d1f01301e181..3148eec9ce409bccf0a4e8b6044e46fd2f60db21 100644 (file)
@@ -48,7 +48,6 @@
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/gc-internal.h>
-#include <mono/metadata/monitor.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/utils/mono-logger-internal.h>
@@ -889,10 +888,8 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                        int atype = decode_value (p, &p);
 
                        ref->method = mono_gc_get_managed_allocator_by_type (atype, !!(mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS));
-                       if (!ref->method) {
-                               fprintf (stderr, "Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
-                               exit (1);
-                       }
+                       if (!ref->method)
+                               g_error ("Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
                        break;
                }
                case MONO_WRAPPER_WRITE_BARRIER:
@@ -1834,10 +1831,8 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        }
 
        if (!sofile && !globals) {
-               if (mono_aot_only && assembly->image->tables [MONO_TABLE_METHOD].rows) {
-                       fprintf (stderr, "Failed to load AOT module '%s' in aot-only mode.\n", aot_name);
-                       exit (1);
-               }
+               if (mono_aot_only && assembly->image->tables [MONO_TABLE_METHOD].rows)
+                       g_error ("Failed to load AOT module '%s' in aot-only mode.\n", aot_name);
                g_free (aot_name);
                return;
        }
@@ -1864,8 +1859,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
 
        if (!usable) {
                if (mono_aot_only) {
-                       fprintf (stderr, "Failed to load AOT module '%s' while running in aot-only mode: %s.\n", aot_name, msg);
-                       exit (1);
+                       g_error ("Failed to load AOT module '%s' while running in aot-only mode: %s.\n", aot_name, msg);
                } else {
                        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: module %s is unusable: %s.\n", aot_name, msg);
                }
@@ -2078,6 +2072,20 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
 
        init_gots (amodule);
 
+       /*
+        * Register the plt region as a single trampoline so we can unwind from this code
+        */
+       mono_tramp_info_register (
+               mono_tramp_info_create (
+                       NULL,
+                       amodule->plt,
+                       amodule->plt_end - amodule->plt,
+                       NULL,
+                       mono_unwind_get_cie_program ()
+                       ),
+               NULL
+               );
+
        /*
         * Since we store methoddef and classdef tokens when referring to methods/classes in
         * referenced assemblies, we depend on the exact versions of the referenced assemblies.
@@ -2102,10 +2110,8 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
 
        if (amodule->out_of_date) {
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: Module %s is unusable because a dependency is out-of-date.\n", assembly->image->name);
-               if (mono_aot_only) {
-                       fprintf (stderr, "Failed to load AOT module '%s' while running in aot-only mode because a dependency cannot be found or it is out of date.\n", aot_name);
-                       exit (1);
-               }
+               if (mono_aot_only)
+                       g_error ("Failed to load AOT module '%s' while running in aot-only mode because a dependency cannot be found or it is out of date.\n", aot_name);
        }
        else
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: loaded AOT Module for %s.\n", assembly->image->name);
@@ -2422,9 +2428,7 @@ compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **c
        table = (gint32*)p;
 
        if (fde_count > 1) {
-               /* mono_aot_personality () */
-               g_assert (table [0] == -1);
-               *code_start = amodule->methods [table [2]];
+               *code_start = amodule->methods [table [0]];
                *code_end = (guint8*)amodule->methods [table [(fde_count - 1) * 2]] + table [fde_count * 2];
        } else {
                *code_start = NULL;
@@ -3359,9 +3363,6 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                ji->data.offset = decode_value (p, &p);
                break;
        case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-       case MONO_PATCH_INFO_MONITOR_EXIT:
        case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
        case MONO_PATCH_INFO_GC_NURSERY_START:
        case MONO_PATCH_INFO_JIT_TLS_ID:
@@ -3746,7 +3747,11 @@ find_aot_method_in_amodule (MonoAotModule *amodule, MonoMethod *method, guint32
                amodule_unlock (amodule);
                if (!m) {
                        m = decode_resolve_method_ref_with_target (amodule, method, p, &p);
-                       if (m) {
+                       /*
+                        * Can't catche runtime invoke wrappers since it would break
+                        * the check in decode_method_ref_with_target ().
+                        */
+                       if (m && m->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) {
                                amodule_lock (amodule);
                                g_hash_table_insert (amodule->method_ref_to_method, orig_p, m);
                                amodule_unlock (amodule);
@@ -4549,15 +4554,6 @@ load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **ou
                                        g_assert (res == 1);
                                        target = mono_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL);
                                        target = mono_create_ftnptr_malloc (target);
-                               } else if (!strcmp (ji->data.name, "specific_trampoline_monitor_enter")) {
-                                       target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER, mono_get_root_domain (), NULL);
-                                       target = mono_create_ftnptr_malloc (target);
-                               } else if (!strcmp (ji->data.name, "specific_trampoline_monitor_enter_v4")) {
-                                       target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER_V4, mono_get_root_domain (), NULL);
-                                       target = mono_create_ftnptr_malloc (target);
-                               } else if (!strcmp (ji->data.name, "specific_trampoline_monitor_exit")) {
-                                       target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_EXIT, mono_get_root_domain (), NULL);
-                                       target = mono_create_ftnptr_malloc (target);
                                } else if (!strcmp (ji->data.name, "mono_thread_get_and_clear_pending_exception")) {
                                        target = mono_thread_get_and_clear_pending_exception;
                                } else if (!strcmp (ji->data.name, "debugger_agent_single_step_from_context")) {
@@ -4629,7 +4625,36 @@ mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo)
 gpointer
 mono_aot_get_trampoline (const char *name)
 {
-       return mono_aot_get_trampoline_full (name, NULL);
+       MonoTrampInfo *out_tinfo;
+       gpointer code;
+
+       code =  mono_aot_get_trampoline_full (name, &out_tinfo);
+       mono_tramp_info_register (out_tinfo, NULL);
+
+       return code;
+}
+
+static gpointer
+read_unwind_info (MonoAotModule *amodule, MonoTrampInfo *info, const char *symbol_name)
+{
+       gpointer symbol_addr;
+       guint32 uw_offset, uw_info_len;
+       guint8 *uw_info;
+
+       find_symbol (amodule->sofile, amodule->globals, symbol_name, &symbol_addr);
+
+       if (!symbol_addr)
+               return NULL;
+
+       uw_offset = *(guint32*)symbol_addr;
+       uw_info = amodule->unwind_info + uw_offset;
+       uw_info_len = decode_value (uw_info, &uw_info);
+
+       info->uw_info = uw_info;
+       info->uw_info_len = uw_info_len;
+
+       /* If successful return the address of the following data */
+       return (guint32*)symbol_addr + 1;
 }
 
 #ifdef MONOTOUCH
@@ -4637,6 +4662,25 @@ mono_aot_get_trampoline (const char *name)
 
 static TrampolinePage* trampoline_pages [MONO_AOT_TRAMP_NUM];
 
+static void
+read_page_trampoline_uwinfo (MonoTrampInfo *info, int tramp_type, gboolean is_generic)
+{
+       char symbol_name [128];
+
+       if (tramp_type == MONO_AOT_TRAMP_SPECIFIC)
+               sprintf (symbol_name, "specific_trampolines_page_%s_p", is_generic ? "gen" : "sp");
+       else if (tramp_type == MONO_AOT_TRAMP_STATIC_RGCTX)
+               sprintf (symbol_name, "rgctx_trampolines_page_%s_p", is_generic ? "gen" : "sp");
+       else if (tramp_type == MONO_AOT_TRAMP_IMT_THUNK)
+               sprintf (symbol_name, "imt_trampolines_page_%s_p", is_generic ? "gen" : "sp");
+       else if (tramp_type == MONO_AOT_TRAMP_GSHAREDVT_ARG)
+               sprintf (symbol_name, "gsharedvt_trampolines_page_%s_p", is_generic ? "gen" : "sp");
+       else
+               g_assert_not_reached ();
+
+       read_unwind_info (mono_defaults.corlib->aot_module, info, symbol_name);
+}
+
 static unsigned char*
 get_new_trampoline_from_page (int tramp_type)
 {
@@ -4688,6 +4732,8 @@ get_new_trampoline_from_page (int tramp_type)
        count = 40;
        page = NULL;
        while (page == NULL && count-- > 0) {
+               MonoTrampInfo *gen_info, *sp_info;
+
                addr = 0;
                /* allocate two contiguous pages of memory: the first page will contain the data (like a local constant pool)
                 * while the second will contain the trampolines.
@@ -4728,6 +4774,23 @@ get_new_trampoline_from_page (int tramp_type)
                code = page->trampolines;
                page->trampolines += specific_trampoline_size;
                mono_aot_page_unlock ();
+
+               /* Register the generic part at the beggining of the trampoline page */
+               gen_info = mono_tramp_info_create (NULL, (guint8*)taddr, amodule->info.tramp_page_code_offsets [tramp_type], NULL, NULL);
+               read_page_trampoline_uwinfo (gen_info, tramp_type, TRUE);
+               mono_tramp_info_register (gen_info, NULL);
+               /*
+                * FIXME
+                * Registering each specific trampoline produces a lot of
+                * MonoJitInfo structures. Jump trampolines are also registered
+                * separately.
+                */
+               if (tramp_type != MONO_AOT_TRAMP_SPECIFIC) {
+                       /* Register the rest of the page as a single trampoline */
+                       sp_info = mono_tramp_info_create (NULL, code, page->trampolines_end - code, NULL, NULL);
+                       read_page_trampoline_uwinfo (sp_info, tramp_type, FALSE);
+                       mono_tramp_info_register (sp_info, NULL);
+               }
                return code;
        }
        g_error ("Cannot allocate more trampoline pages: %d", ret);
@@ -4807,6 +4870,7 @@ get_new_gsharedvt_arg_trampoline_from_page (gpointer tramp, gpointer arg)
 }
 
 /* Return a given kind of trampoline */
+/* FIXME set unwind info for these trampolines */
 static gpointer
 get_numerous_trampoline (MonoAotTrampoline tramp_type, int n_got_slots, MonoAotModule **out_amodule, guint32 *got_offset, guint32 *out_tramp_size)
 {
@@ -4925,6 +4989,8 @@ mono_aot_get_unbox_trampoline (MonoMethod *method)
        gpointer code;
        guint32 *ut, *ut_end, *entry;
        int low, high, entry_index = 0;
+       gpointer symbol_addr;
+       MonoTrampInfo *tinfo;
 
        if (method->is_inflated && !mono_method_is_generic_sharable_full (method, FALSE, FALSE, FALSE)) {
                method_index = find_aot_method (method, &amodule);
@@ -4964,6 +5030,17 @@ mono_aot_get_unbox_trampoline (MonoMethod *method)
        code = get_call_table_entry (amodule->unbox_trampoline_addresses, entry_index);
        g_assert (code);
 
+       tinfo = mono_tramp_info_create (NULL, code, 0, NULL, NULL);
+
+       symbol_addr = read_unwind_info (amodule, tinfo, "unbox_trampoline_p");
+       if (!symbol_addr) {
+               mono_tramp_info_free (tinfo);
+               return FALSE;
+       }
+
+       tinfo->code_size = *(guint32*)symbol_addr;
+       mono_tramp_info_register (tinfo, NULL);
+
        /* The caller expects an ftnptr */
        return mono_create_ftnptr (mono_domain_get (), code);
 }
index 194ff2b334534d156594405b3e4c2e26c7bb4f00..49bc57e72e84fd45a78bfde7aac37ac59a1d9e87 100644 (file)
@@ -381,6 +381,7 @@ gc_liveness_def: len:0
 gc_liveness_use: len:0
 gc_spill_slot_liveness_def: len:0
 gc_param_slot_liveness_def: len:0
+gc_safe_point: clob:c src1:i len:40
 
 atomic_add_i4: dest:i src1:i src2:i len:64
 atomic_exchange_i4: dest:i src1:i src2:i len:64
index ba2ec60d3e727b0a74beeffeeb2126607abed162..e6baf9148fcf1c56f899fdd6592b011d35e16a3d 100644 (file)
@@ -314,5 +314,5 @@ vcall2_membase: src1:b len:16 clob:c
 
 jump_table: dest:i len:8
 
-atomic_add_i4: src1:b src2:i dest:i len:20
+atomic_add_i4: src1:b src2:i dest:i len:28
 atomic_cas_i4: src1:b src2:i src3:i dest:i len:38
index 2bd196cc76c0fd4f1de577e8ae0cc99770a8554f..e9789f9461f375f76c0e242dff149d2dd0d6f68d 100644 (file)
@@ -66,7 +66,7 @@ break: len:1
 call: dest:a clob:c len:17
 tailcall: len:120 clob:c
 br: len:5
-seq_point: len:17
+seq_point: len:24 clob:c
 il_seq_point: len:0
 
 int_beq: len:6
index 5c26451397ead33aa4de0c436978d889780b0e4e..1c03f16315a2a4bdc2ed4db237cf88bcf6c5ee2e 100644 (file)
@@ -717,9 +717,9 @@ static ReplyPacket reply_packets [128];
 int nreply_packets;
 
 #define dbg_lock() do {        \
-       MONO_TRY_BLOCKING       \
+       MONO_TRY_BLOCKING;                      \
        mono_mutex_lock (&debug_mutex); \
-       MONO_FINISH_TRY_BLOCKING        \
+       MONO_FINISH_TRY_BLOCKING;               \
 } while (0)
 
 #define dbg_unlock() mono_mutex_unlock (&debug_mutex)
@@ -1088,9 +1088,9 @@ finish_agent_init (gboolean on_startup)
                }
        }
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        transport_connect (agent_config.address);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        if (!on_startup) {
                /* Do some which is usually done after sending the VMStart () event */
@@ -1322,9 +1322,9 @@ socket_transport_connect (const char *address)
                        }
                }
 
-               MONO_PREPARE_BLOCKING
+               MONO_PREPARE_BLOCKING;
                conn_fd = socket_transport_accept (sfd);
-               MONO_FINISH_BLOCKING
+               MONO_FINISH_BLOCKING;
                if (conn_fd == -1)
                        exit (1);
 
@@ -1544,18 +1544,18 @@ transport_handshake (void)
        /* Write handshake message */
        sprintf (handshake_msg, "DWP-Handshake");
        /* Must use try blocking as this can nest into code that runs blocking */
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        do {
                res = transport_send (handshake_msg, strlen (handshake_msg));
        } while (res == -1 && get_last_sock_error () == MONO_EINTR);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 
        g_assert (res != -1);
 
        /* Read answer */
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        res = transport_recv (buf, strlen (handshake_msg));
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
        if ((res != strlen (handshake_msg)) || (memcmp (buf, handshake_msg, strlen (handshake_msg)) != 0)) {
                fprintf (stderr, "debugger-agent: DWP handshake failed.\n");
                return FALSE;
@@ -1598,9 +1598,9 @@ stop_debugger_thread (void)
        if (!inited)
                return;
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        transport_close1 ();
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        /* 
         * Wait for the thread to exit.
@@ -1610,18 +1610,18 @@ stop_debugger_thread (void)
         */
        if (GetCurrentThreadId () != debugger_thread_id) {
                do {
-                       MONO_TRY_BLOCKING
+                       MONO_TRY_BLOCKING;
                        mono_mutex_lock (&debugger_thread_exited_mutex);
                        if (!debugger_thread_exited)
                                mono_cond_wait (&debugger_thread_exited_cond, &debugger_thread_exited_mutex);
                        mono_mutex_unlock (&debugger_thread_exited_mutex);
-                       MONO_FINISH_TRY_BLOCKING
+                       MONO_FINISH_TRY_BLOCKING;
                } while (!debugger_thread_exited);
        }
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        transport_close2 ();
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 }
 
 static void
@@ -1815,9 +1815,9 @@ send_packet (int command_set, int command, Buffer *data)
        buffer_add_byte (&buf, command);
        memcpy (buf.buf + 11, data->buf, data->p - data->buf);
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        res = transport_send (buf.buf, len);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        buffer_free (&buf);
 
@@ -1844,9 +1844,9 @@ send_reply_packets (int npackets, ReplyPacket *packets)
                buffer_add_buffer (&buf, packets [i].data);
        }
 
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        res = transport_send (buf.buf, len);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        buffer_free (&buf);
 
@@ -2520,7 +2520,7 @@ get_last_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
 {
        GetLastFrameUserData *data = user_data;
 
-       if (info->type == FRAME_TYPE_MANAGED_TO_NATIVE)
+       if (info->type == FRAME_TYPE_MANAGED_TO_NATIVE || info->type == FRAME_TYPE_TRAMPOLINE)
                return FALSE;
 
        if (!data->last_frame_set) {
@@ -2556,7 +2556,7 @@ thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, MonoJitInfo *ji)
        // FIXME: Races when the thread leaves managed code before hitting a single step
        // event.
 
-       if (ji) {
+       if (ji && !ji->is_trampoline) {
                /* Running managed code, will be suspended by the single step code */
                DEBUG_PRINTF (1, "[%p] Received interrupt while at %s(%p), continuing.\n", (gpointer)(gsize)tid, jinfo_get_method (ji)->name, ip);
        } else {
@@ -2648,7 +2648,11 @@ debugger_interrupt_critical (MonoThreadInfo *info, gpointer user_data)
        MonoJitInfo *ji;
 
        data->valid_info = TRUE;
-       ji = mono_jit_info_table_find (mono_thread_info_get_suspend_state (info)->unwind_data [MONO_UNWIND_DATA_DOMAIN], MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx));
+       ji = mono_jit_info_table_find_internal (
+                       mono_thread_info_get_suspend_state (info)->unwind_data [MONO_UNWIND_DATA_DOMAIN],
+                       MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx),
+                       TRUE,
+                       TRUE);
 
        /* This is signal safe */
        thread_interrupt (data->tls, info, ji);
@@ -2744,9 +2748,9 @@ suspend_vm (void)
 {
        mono_loader_lock ();
 
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        mono_mutex_lock (&suspend_mutex);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 
        suspend_count ++;
 
@@ -2784,9 +2788,9 @@ resume_vm (void)
 
        mono_loader_lock ();
 
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        mono_mutex_lock (&suspend_mutex);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 
        g_assert (suspend_count > 0);
        suspend_count --;
@@ -2830,9 +2834,9 @@ resume_thread (MonoInternalThread *thread)
        tls = mono_g_hash_table_lookup (thread_to_tls, thread);
        g_assert (tls);
        
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        mono_mutex_lock (&suspend_mutex);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 
        g_assert (suspend_count > 0);
 
@@ -2907,9 +2911,9 @@ suspend_current (void)
        tls = mono_native_tls_get_value (debugger_tls_id);
        g_assert (tls);
 
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        mono_mutex_lock (&suspend_mutex);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 
        tls->suspending = FALSE;
        tls->really_suspended = TRUE;
@@ -2921,12 +2925,12 @@ suspend_current (void)
 
        DEBUG_PRINTF (1, "[%p] Suspended.\n", (gpointer)GetCurrentThreadId ());
 
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        while (suspend_count - tls->resume_count > 0) {
                err = mono_cond_wait (&suspend_cond, &suspend_mutex);
                g_assert (err == 0);
        }
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 
        tls->suspended = FALSE;
        tls->really_suspended = FALSE;
@@ -3070,7 +3074,7 @@ process_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
                        info->il_offset = mono_debug_il_offset_from_address (method, info->domain, info->native_offset);
        }
 
-       DEBUG_PRINTF (1, "\tFrame: %s:%x(%x) %d\n", mono_method_full_name (method, TRUE), info->il_offset, info->native_offset, info->managed);
+       DEBUG_PRINTF (1, "\tFrame: %s:[il=0x%x, native=0x%x] %d\n", mono_method_full_name (method, TRUE), info->il_offset, info->native_offset, info->managed);
 
        if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
                if (!CHECK_PROTOCOL_VERSION (2, 17))
@@ -4247,7 +4251,7 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo
 #endif
        }
 
-       DEBUG_PRINTF (1, "[dbg] Inserted breakpoint at %s:0x%x [%p](%d).\n", mono_method_full_name (jinfo_get_method (ji), TRUE), (int)it.seq_point.il_offset, inst->ip, count);
+       DEBUG_PRINTF (1, "[dbg] Inserted breakpoint at %s:[il=0x%x,native=0x%x] [%p](%d).\n", mono_method_full_name (jinfo_get_method (ji), TRUE), (int)it.seq_point.il_offset, (int)it.seq_point.native_offset, inst->ip, count);
 }
 
 static void
@@ -4637,7 +4641,7 @@ process_breakpoint_inner (DebuggerTlsData *tls, gboolean from_signal)
 
        ip = MONO_CONTEXT_GET_IP (ctx);
        ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, NULL);
-       g_assert (ji);
+       g_assert (ji && !ji->is_trampoline);
        method = jinfo_get_method (ji);
 
        /* Compute the native offset of the breakpoint from the ip */
@@ -4669,7 +4673,7 @@ process_breakpoint_inner (DebuggerTlsData *tls, gboolean from_signal)
 
        g_assert (found_sp);
 
-       DEBUG_PRINTF (1, "[%p] Breakpoint hit, method=%s, ip=%p, offset=0x%x, sp il offset=0x%x.\n", (gpointer)GetCurrentThreadId (), method->name, ip, native_offset, sp.il_offset);
+       DEBUG_PRINTF (1, "[%p] Breakpoint hit, method=%s, ip=%p, [il=0x%x,native=0x%x].\n", (gpointer)GetCurrentThreadId (), method->name, ip, sp.il_offset, native_offset);
 
        bp = NULL;
        for (i = 0; i < breakpoints->len; ++i) {
@@ -4901,7 +4905,7 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal)
        }
 
        ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
-       g_assert (ji);
+       g_assert (ji && !ji->is_trampoline);
        method = jinfo_get_method (ji);
        g_assert (method);
 
@@ -9579,9 +9583,9 @@ wait_for_attach (void)
        }
 
        /* Block and wait for client connection */
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        conn_fd = socket_transport_accept (listen_fd);
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        DEBUG_PRINTF (1, "Accepted connection on %d\n", conn_fd);
        if (conn_fd == -1) {
@@ -9640,9 +9644,9 @@ debugger_thread (void *arg)
        }
        
        while (!attach_failed) {
-               MONO_PREPARE_BLOCKING
+               MONO_PREPARE_BLOCKING;
                res = transport_recv (header, HEADER_LENGTH);
-               MONO_FINISH_BLOCKING
+               MONO_FINISH_BLOCKING;
 
                /* This will break if the socket is closed during shutdown too */
                if (res != HEADER_LENGTH) {
@@ -9677,9 +9681,9 @@ debugger_thread (void *arg)
                data = g_malloc (len - HEADER_LENGTH);
                if (len - HEADER_LENGTH > 0)
                {
-                       MONO_PREPARE_BLOCKING
+                       MONO_PREPARE_BLOCKING;
                        res = transport_recv (data, len - HEADER_LENGTH);
-                       MONO_FINISH_BLOCKING
+                       MONO_FINISH_BLOCKING;
                        if (res != len - HEADER_LENGTH) {
                                DEBUG_PRINTF (1, "[dbg] transport_recv () returned %d, expected %d.\n", res, len - HEADER_LENGTH);
                                break;
@@ -9769,12 +9773,12 @@ debugger_thread (void *arg)
 
        mono_set_is_debugger_attached (FALSE);
        
-       MONO_TRY_BLOCKING
+       MONO_TRY_BLOCKING;
        mono_mutex_lock (&debugger_thread_exited_mutex);
        debugger_thread_exited = TRUE;
        mono_cond_signal (&debugger_thread_exited_cond);
        mono_mutex_unlock (&debugger_thread_exited_mutex);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 
        DEBUG_PRINTF (1, "[dbg] Debugger thread exited.\n");
        
index decdd5ec10e092bf8f0eccbdf31d72b5174171d7..fcbbe5bdc2636bfdda0036e1bc2d193f248acdf6 100644 (file)
@@ -407,7 +407,7 @@ emit_fde (MonoDwarfWriter *w, int fde_index, char *start_symbol, char *end_symbo
        }
 
        /* Convert the list of MonoUnwindOps to the format used by DWARF */     
-       uw_info = mono_unwind_ops_encode (l, &uw_info_len);
+       uw_info = mono_unwind_ops_encode_full (l, &uw_info_len, FALSE);
        emit_bytes (w, uw_info, uw_info_len);
        g_free (uw_info);
 
index 1a34f6e2f5234cc335c40a7558e315ce8dabb897..4f7e336e6d2ee53f4ef524810ac7d667809d8723 100644 (file)
@@ -540,7 +540,10 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
                guint8 *unwind_info;
                guint8 *epilog = NULL;
 
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
 
                unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
 
@@ -882,7 +885,7 @@ mono_arch_exceptions_init (void)
                        MonoTrampInfo *info = l->data;
 
                        mono_register_jit_icall (info->code, g_strdup (info->name), NULL, TRUE);
-                       mono_tramp_info_register (info);
+                       mono_tramp_info_register (info, NULL);
                }
                g_slist_free (tramps);
        }
index e06e2cb656e99098adb626242839da2136de113b..b478a713bc5e108ea30e7d59ed5e4a2f8c24a9c0 100644 (file)
@@ -376,7 +376,7 @@ mono_arch_exceptions_init (void)
                        MonoTrampInfo *info = l->data;
 
                        mono_register_jit_icall (info->code, g_strdup (info->name), NULL, TRUE);
-                       mono_tramp_info_register (info);
+                       mono_tramp_info_register (info, NULL);
                }
                g_slist_free (tramps);
        }
@@ -408,7 +408,10 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
                guint32 unwind_info_len;
                guint8 *unwind_info;
 
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
 
                unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
 
index 83ff89b174ed2360e8dbbe825f2e98e4e75a072c..b9299cbe4fd3181883a5bf90efa29e896e4f6328 100644 (file)
@@ -545,7 +545,10 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
        }
 
        if (ji) {
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
                frame->ji = ji;
 
                //print_ctx (new_ctx);
index dcdb320e29fab388f395547133e11ccc5a0efff3..f8d9dedff2ce60e3e223f4189b57c5452a456c4d 100644 (file)
@@ -410,7 +410,10 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
                guint32 unwind_info_len;
                guint8 *unwind_info;
 
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
 
                unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
 
index 922a1c6870bff045cb89dd12c9d612617f1153d2..e872d1336924448ed4bc993352b9744b18551c01 100644 (file)
@@ -532,13 +532,16 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
                guint32 unwind_info_len;
                guint8 *unwind_info;
 
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
 
                unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
 
                sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_SP (ctx);
                MONO_CONTEXT_SET_BP (new_ctx, sframe->sp);
-               if (jinfo_get_method (ji)->save_lmf) {
+               if (!ji->is_trampoline && jinfo_get_method (ji)->save_lmf) {
                        /* sframe->sp points just past the end of the LMF */
                        guint8 *lmf_addr = (guint8*)sframe->sp - sizeof (MonoLMF);
                        memcpy (&new_ctx->fregs, lmf_addr + G_STRUCT_OFFSET (MonoLMF, fregs), sizeof (double) * MONO_SAVED_FREGS);
@@ -653,7 +656,7 @@ mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *s
                const char *method;
                /* we don't do much now, but we can warn the user with a useful message */
                fprintf (stderr, "Stack overflow: IP: %p, SP: %p\n", mono_arch_ip_from_context (sigctx), (gpointer)UCONTEXT_REG_Rn(uc, 1));
-               if (ji && jinfo_get_method (ji))
+               if (ji && !ji->is_trampoline && jinfo_get_method (ji))
                        method = mono_method_full_name (jinfo_get_method (ji), TRUE);
                else
                        method = "Unmanaged";
index c3714f94ee0d37bc67485bd437ffd9e65ca95e32..83d5f6b1368771d1509397f61ba852a7f51541d7 100644 (file)
@@ -478,7 +478,10 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
                guint8 *unwind_info;
                mgreg_t regs[16];
 
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
 
                unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
 
index a5b197c8c4f5ccfd559410fbd546bf8d8bc5c9de..b3b5633597644d39ff345274d0fc4f2749b21d66 100644 (file)
@@ -350,7 +350,10 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
        *new_ctx = *ctx;
 
        if (ji != NULL) {
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
 
                /* Restore ip and sp from the saved register window */
                window = MONO_SPARC_WINDOW_ADDR (ctx->sp);
index 3b4b21c1dffd861d6bb9870786fa18283645983a..3db25ca7f810f8ab363fe926b3a75c355c3e10da 100644 (file)
@@ -564,8 +564,7 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
         * <return addr> <- esp (unaligned on apple)
         */
 
-       mono_add_unwind_op_def_cfa (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_ESP, 4);
-       mono_add_unwind_op_offset (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_NREG, -4);
+       unwind_ops = mono_arch_get_cie_program ();
 
        /* Alloc frame */
        x86_alu_reg_imm (code, X86_SUB, X86_ESP, stack_size);
@@ -717,6 +716,7 @@ void
 mono_arch_exceptions_init (void)
 {
        guint8 *tramp;
+       MonoTrampInfo *tinfo;
 
 /* 
  * If we're running WoW64, we need to set the usermode exception policy 
@@ -745,22 +745,28 @@ mono_arch_exceptions_init (void)
        }
 
        /* LLVM needs different throw trampolines */
-       tramp = get_throw_trampoline ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_throw_exception_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_rethrow_exception_trampoline", TRUE, TRUE, FALSE, FALSE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_rethrow_exception_trampoline", TRUE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_rethrow_exception_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE, FALSE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE, FALSE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_abs_trampoline", FALSE, TRUE, TRUE, TRUE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_abs_trampoline", FALSE, TRUE, TRUE, TRUE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_abs_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_resume_unwind_trampoline", FALSE, FALSE, FALSE, FALSE, TRUE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_resume_unwind_trampoline", FALSE, FALSE, FALSE, FALSE, TRUE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_resume_unwind_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       signal_exception_trampoline = mono_x86_get_signal_exception_trampoline (NULL, FALSE);
+       signal_exception_trampoline = mono_x86_get_signal_exception_trampoline (&tinfo, FALSE);
+       mono_tramp_info_register (tinfo, NULL);
 }
 
 /*
@@ -788,7 +794,10 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
                guint32 unwind_info_len;
                guint8 *unwind_info;
 
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
 
                unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
 
@@ -931,11 +940,12 @@ mono_x86_get_signal_exception_trampoline (MonoTrampInfo **info, gboolean aot)
 
        start = code = mono_global_codeman_reserve (128);
 
+       /* FIXME no unwind before we push ip */
        /* Caller ip */
        x86_push_reg (code, X86_ECX);
 
-       mono_add_unwind_op_def_cfa (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_ESP, 4);
-       mono_add_unwind_op_offset (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_NREG, -4);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, start, X86_ESP, 4);
+       mono_add_unwind_op_offset (unwind_ops, code, start, X86_NREG, -4);
 
        /* Fix the alignment to be what apple expects */
        stack_size = 12;
index eb118be0c9bf72d7da46ae02be41daf88a70fe20..f6c61beb71ba70cc84ec41d79a941a89d512f839 100644 (file)
@@ -54,7 +54,6 @@
 #include <mono/metadata/security-manager.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/security-core-clr.h>
-#include <mono/metadata/monitor.h>
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/profiler.h>
 #include <mono/metadata/debug-mono-symfile.h>
@@ -149,9 +148,6 @@ static int inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
 /* helper methods signatures */
 static MonoMethodSignature *helper_sig_domain_get;
 static MonoMethodSignature *helper_sig_rgctx_lazy_fetch_trampoline;
-static MonoMethodSignature *helper_sig_monitor_enter_exit_trampoline;
-static MonoMethodSignature *helper_sig_monitor_enter_exit_trampoline_llvm;
-static MonoMethodSignature *helper_sig_monitor_enter_v4_trampoline_llvm;
 
 /*
  * Instruction metadata
@@ -356,9 +352,6 @@ mono_create_helper_signatures (void)
 {
        helper_sig_domain_get = mono_create_icall_signature ("ptr");
        helper_sig_rgctx_lazy_fetch_trampoline = mono_create_icall_signature ("ptr ptr");
-       helper_sig_monitor_enter_exit_trampoline = mono_create_icall_signature ("void");
-       helper_sig_monitor_enter_exit_trampoline_llvm = mono_create_icall_signature ("void object");
-       helper_sig_monitor_enter_v4_trampoline_llvm = mono_create_icall_signature ("void object ptr");
 }
 
 static MONO_NEVER_INLINE void
@@ -4318,6 +4311,7 @@ icall_is_direct_callable (MonoCompile *cfg, MonoMethod *cmethod)
                g_hash_table_insert (h, (char*)"Decimal", GUINT_TO_POINTER (1));
                g_hash_table_insert (h, (char*)"Number", GUINT_TO_POINTER (1));
                g_hash_table_insert (h, (char*)"Buffer", GUINT_TO_POINTER (1));
+               g_hash_table_insert (h, (char*)"Monitor", GUINT_TO_POINTER (1));
                mono_memory_barrier ();
                direct_icall_type_hash = h;
        }
@@ -6022,59 +6016,6 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                                return ins;
                        }
                }
-       } else if (cmethod->klass == mono_defaults.monitor_class) {
-#if defined(MONO_ARCH_MONITOR_OBJECT_REG)
-               if (strcmp (cmethod->name, "Enter") == 0 && fsig->param_count == 1) {
-                       MonoCallInst *call;
-
-                       if (COMPILE_LLVM (cfg)) {
-                               /* 
-                                * Pass the argument normally, the LLVM backend will handle the
-                                * calling convention problems.
-                                */
-                               call = (MonoCallInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_MONITOR_ENTER, NULL, helper_sig_monitor_enter_exit_trampoline_llvm, args);
-                       } else {
-                               call = (MonoCallInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_MONITOR_ENTER,
-                                           NULL, helper_sig_monitor_enter_exit_trampoline, NULL);
-                               mono_call_inst_add_outarg_reg (cfg, call, args [0]->dreg,
-                                                                                          MONO_ARCH_MONITOR_OBJECT_REG, FALSE);
-                       }
-
-                       return (MonoInst*)call;
-#if defined(MONO_ARCH_MONITOR_LOCK_TAKEN_REG)
-               } else if (strcmp (cmethod->name, "Enter") == 0 && fsig->param_count == 2) {
-                       MonoCallInst *call;
-
-                       if (COMPILE_LLVM (cfg)) {
-                               /*
-                                * Pass the argument normally, the LLVM backend will handle the
-                                * calling convention problems.
-                                */
-                               call = (MonoCallInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_MONITOR_ENTER_V4, NULL, helper_sig_monitor_enter_v4_trampoline_llvm, args);
-                       } else {
-                               call = (MonoCallInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_MONITOR_ENTER_V4,
-                                           NULL, helper_sig_monitor_enter_exit_trampoline, NULL);
-                               mono_call_inst_add_outarg_reg (cfg, call, args [0]->dreg, MONO_ARCH_MONITOR_OBJECT_REG, FALSE);
-                               mono_call_inst_add_outarg_reg (cfg, call, args [1]->dreg, MONO_ARCH_MONITOR_LOCK_TAKEN_REG, FALSE);
-                       }
-
-                       return (MonoInst*)call;
-#endif
-               } else if (strcmp (cmethod->name, "Exit") == 0 && fsig->param_count == 1) {
-                       MonoCallInst *call;
-
-                       if (COMPILE_LLVM (cfg)) {
-                               call = (MonoCallInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_MONITOR_EXIT, NULL, helper_sig_monitor_enter_exit_trampoline_llvm, args);
-                       } else {
-                               call = (MonoCallInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_MONITOR_EXIT,
-                                           NULL, helper_sig_monitor_enter_exit_trampoline, NULL);
-                               mono_call_inst_add_outarg_reg (cfg, call, args [0]->dreg,
-                                                                                          MONO_ARCH_MONITOR_OBJECT_REG, FALSE);
-                       }
-
-                       return (MonoInst*)call;
-               }
-#endif
        } else if (cmethod->klass->image == mono_defaults.corlib &&
                           (strcmp (cmethod->klass->name_space, "System.Threading") == 0) &&
                           (strcmp (cmethod->klass->name, "Interlocked") == 0)) {
@@ -7918,8 +7859,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                MONO_INST_NEW (cfg, ins, OP_START_HANDLER);
                                MONO_ADD_INS (tblock, ins);
 
-                               if (seq_points && clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY) {
+                               if (seq_points && clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_FILTER) {
                                        /* finally clauses already have a seq point */
+                                       /* seq points for filter clauses are emitted below */
                                        NEW_SEQ_POINT (cfg, ins, clause->handler_offset, TRUE);
                                        MONO_ADD_INS (tblock, ins);
                                }
@@ -7961,6 +7903,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 */
                                EMIT_NEW_DUMMY_USE (cfg, dummy_use, tblock->in_stack [0]);
 #endif
+
+                               if (seq_points && clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+                                       NEW_SEQ_POINT (cfg, ins, clause->handler_offset, TRUE);
+                                       MONO_ADD_INS (tblock, ins);
+                               }
                                
                                if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
                                        GET_BBLOCK (cfg, tblock, ip + clause->data.filter_offset);
@@ -8848,6 +8795,20 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_CFG_ERROR;
                        }
 
+                       /* See code below */
+                       if (cmethod->klass == mono_defaults.monitor_class && !strcmp (cmethod->name, "Enter") && mono_method_signature (cmethod)->param_count == 1) {
+                               MonoBasicBlock *tbb;
+
+                               GET_BBLOCK (cfg, tbb, ip + 5);
+                               if (tbb->try_start && MONO_REGION_FLAGS(tbb->region) == MONO_EXCEPTION_CLAUSE_FINALLY) {
+                                       /*
+                                        * We want to extend the try block to cover the call, but we can't do it if the
+                                        * call is made directly since its followed by an exception check.
+                                        */
+                                       direct_icall = FALSE;
+                               }
+                       }
+
                        mono_save_token_info (cfg, image, token, cil_method);
 
                        if (!(seq_point_locs && mono_bitset_test_fast (seq_point_locs, ip + 5 - header->code)))
index 9d39b9e210dbe420c719cd932446d27f5fce1c2c..7ac0615d9e12260817654588ffb50efe03c9e853 100644 (file)
@@ -65,9 +65,6 @@ static gboolean optimize_for_xen = TRUE;
 #define mono_mini_arch_unlock() mono_mutex_unlock (&mini_arch_mutex)
 static mono_mutex_t mini_arch_mutex;
 
-MonoBreakpointInfo
-mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
-
 /*
  * The code generated for sequence points reads from this location, which is
  * made read-only when single stepping is enabled.
@@ -7806,11 +7803,14 @@ mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
 #define MAX_ARCH_DELEGATE_PARAMS 10
 
 static gpointer
-get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *code_len)
+get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count)
 {
        guint8 *code, *start;
+       GSList *unwind_ops = NULL;
        int i;
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        if (has_target) {
                start = code = mono_global_codeman_reserve (64);
 
@@ -7847,8 +7847,13 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
        nacl_global_codeman_validate (&start, 64, &code);
        mono_arch_flush_icache (start, code - start);
 
-       if (code_len)
-               *code_len = code - start;
+       if (has_target) {
+               *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, unwind_ops);
+       } else {
+               char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
+               *info = mono_tramp_info_create (name, start, code - start, NULL, unwind_ops);
+               g_free (name);
+       }
 
        if (mono_jit_map_is_enabled ()) {
                char *buff;
@@ -7868,16 +7873,20 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
 #define MAX_VIRTUAL_DELEGATE_OFFSET 32
 
 static gpointer
-get_delegate_virtual_invoke_impl (gboolean load_imt_reg, int offset, guint32 *code_len)
+get_delegate_virtual_invoke_impl (MonoTrampInfo **info, gboolean load_imt_reg, int offset)
 {
        guint8 *code, *start;
        int size = 20;
+       char *tramp_name;
+       GSList *unwind_ops;
 
-       if (offset / sizeof (gpointer) > MAX_VIRTUAL_DELEGATE_OFFSET)
+       if (offset / (int)sizeof (gpointer) > MAX_VIRTUAL_DELEGATE_OFFSET)
                return NULL;
 
        start = code = mono_global_codeman_reserve (size);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        /* Replace the this argument with the target */
        amd64_mov_reg_reg (code, AMD64_RAX, AMD64_ARG_REG1, 8);
        amd64_mov_reg_membase (code, AMD64_ARG_REG1, AMD64_RAX, MONO_STRUCT_OFFSET (MonoDelegate, target), 8);
@@ -7892,8 +7901,12 @@ get_delegate_virtual_invoke_impl (gboolean load_imt_reg, int offset, guint32 *co
        amd64_jump_membase (code, AMD64_RAX, offset);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
 
-       if (code_len)
-               *code_len = code - start;
+       if (load_imt_reg)
+               tramp_name = g_strdup_printf ("delegate_virtual_invoke_imt_%d", - offset / sizeof (gpointer));
+       else
+               tramp_name = g_strdup_printf ("delegate_virtual_invoke_%d", offset / sizeof (gpointer));
+       *info = mono_tramp_info_create (tramp_name, start, code - start, NULL, unwind_ops);
+       g_free (tramp_name);
 
        return start;
 }
@@ -7908,31 +7921,23 @@ GSList*
 mono_arch_get_delegate_invoke_impls (void)
 {
        GSList *res = NULL;
-       guint8 *code;
-       guint32 code_len;
+       MonoTrampInfo *info;
        int i;
-       char *tramp_name;
 
-       code = get_delegate_invoke_impl (TRUE, 0, &code_len);
-       res = g_slist_prepend (res, mono_tramp_info_create ("delegate_invoke_impl_has_target", code, code_len, NULL, NULL));
+       get_delegate_invoke_impl (&info, TRUE, 0);
+       res = g_slist_prepend (res, info);
 
-       for (i = 0; i < MAX_ARCH_DELEGATE_PARAMS; ++i) {
-               code = get_delegate_invoke_impl (FALSE, i, &code_len);
-               tramp_name = g_strdup_printf ("delegate_invoke_impl_target_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+       for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
+               get_delegate_invoke_impl (&info, FALSE, i);
+               res = g_slist_prepend (res, info);
        }
 
-       for (i = 0; i < MAX_VIRTUAL_DELEGATE_OFFSET; ++i) {
-               code = get_delegate_virtual_invoke_impl (TRUE, i * SIZEOF_VOID_P, &code_len);
-               tramp_name = g_strdup_printf ("delegate_virtual_invoke_imt_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+       for (i = 0; i <= MAX_VIRTUAL_DELEGATE_OFFSET; ++i) {
+               get_delegate_virtual_invoke_impl (&info, TRUE, - i * SIZEOF_VOID_P);
+               res = g_slist_prepend (res, info);
 
-               code = get_delegate_virtual_invoke_impl (FALSE, i * SIZEOF_VOID_P, &code_len);
-               tramp_name = g_strdup_printf ("delegate_virtual_invoke_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+               get_delegate_virtual_invoke_impl (&info, FALSE, i * SIZEOF_VOID_P);
+               res = g_slist_prepend (res, info);
        }
 
        return res;
@@ -7957,10 +7962,13 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                if (cached)
                        return cached;
 
-               if (mono_aot_only)
+               if (mono_aot_only) {
                        start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
-               else
-                       start = get_delegate_invoke_impl (TRUE, 0, NULL);
+               } else {
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, TRUE, 0);
+                       mono_tramp_info_register (info, NULL);
+               }
 
                mono_memory_barrier ();
 
@@ -7982,7 +7990,9 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        start = mono_aot_get_trampoline (name);
                        g_free (name);
                } else {
-                       start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL);
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, FALSE, sig->param_count);
+                       mono_tramp_info_register (info, NULL);
                }
 
                mono_memory_barrier ();
@@ -7996,7 +8006,13 @@ 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)
 {
-       return get_delegate_virtual_invoke_impl (load_imt_reg, offset, NULL);
+       MonoTrampInfo *info;
+       gpointer code;
+
+       code = get_delegate_virtual_invoke_impl (&info, load_imt_reg, offset);
+       if (code)
+               mono_tramp_info_register (info, NULL);
+       return code;
 }
 
 void
@@ -8055,6 +8071,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        int size = 0;
        guint8 *code, *start;
        gboolean vtable_is_32bit = ((gsize)(vtable) == (gsize)(int)(gsize)(vtable));
+       GSList *unwind_ops;
 
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
@@ -8117,6 +8134,9 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                code = mono_domain_code_reserve (domain, size);
 #endif
        start = code;
+
+       unwind_ops = mono_arch_get_cie_program ();
+
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
                item->code_target = code;
@@ -8207,6 +8227,8 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        nacl_domain_code_validate(domain, &start, size, &code);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
+
        return start;
 }
 
index 6f70402b8c8decddcebe0217b765ccfccd6d4683..c494c69fbbcaf677a3570478b9d2d60dfe5e0880 100644 (file)
@@ -325,8 +325,6 @@ typedef struct {
 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
 #define MONO_ARCH_HAVE_LIVERANGE_OPS 1
 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
-#define MONO_ARCH_MONITOR_OBJECT_REG MONO_AMD64_ARG_REG1
-#define MONO_ARCH_MONITOR_LOCK_TAKEN_REG MONO_AMD64_ARG_REG2
 #define MONO_ARCH_HAVE_GET_TRAMPOLINES 1
 
 #define MONO_ARCH_AOT_SUPPORTED 1
@@ -406,13 +404,6 @@ mono_amd64_get_exception_trampolines (gboolean aot);
 int
 mono_amd64_get_tls_gs_offset (void) MONO_LLVM_INTERNAL;
 
-typedef struct {
-       guint8 *address;
-       guint8 saved_byte;
-} MonoBreakpointInfo;
-
-extern MonoBreakpointInfo mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
-
 #ifdef TARGET_WIN32
 
 void mono_arch_unwindinfo_add_push_nonvol (gpointer* monoui, gpointer codebegin, gpointer nextip, guchar reg );
index f4e8db7feec28a3e4fe0cb2f4286f6651082d5fe..1f7204a884b0d09aae0f4319b5fc8721ab2d1b98 100644 (file)
         * within can be tracked. The tls value is returned in R0.
         */
 
+.macro DECLARE_GLOBAL_SYMBOL name
+#ifdef TARGET_MACH
+       .global _\name
+_\name:
+#else
+       .global \name
+\name:
+#endif
+.endm
+
        .text
 /* no .arch on clang. it only supports armv6+ anyway */
 #ifndef TARGET_MACH
 #endif
        .arm
        .align 4
-#ifdef TARGET_MACH
-       .global _mono_fast_get_tls_key
-_mono_fast_get_tls_key :
-#else
-       .global mono_fast_get_tls_key
-mono_fast_get_tls_key :
-#endif
+
+DECLARE_GLOBAL_SYMBOL mono_fast_get_tls_key
 #if defined(__linux__)
        mrc     p15, 0, r1, c13, c0, 3
 #if defined(HAVE_KW_THREAD)
@@ -42,6 +47,7 @@ mono_fast_get_tls_key :
        ldr     r0, [r1, r0, lsl #2]
        bx      lr
 #endif
+DECLARE_GLOBAL_SYMBOL mono_fast_get_tls_key_end
 
        /*
         * The following thunks fetch the value corresponding to the key/offset
@@ -50,13 +56,7 @@ mono_fast_get_tls_key :
         */
 
        .align 4
-#ifdef TARGET_MACH
-       .global _mono_fallback_get_tls_key
-_mono_fallback_get_tls_key :
-#else
-       .global mono_fallback_get_tls_key
-mono_fallback_get_tls_key :
-#endif
+DECLARE_GLOBAL_SYMBOL mono_fallback_get_tls_key
 #if defined(__linux__)
        mov     r1, r0
        mvn     r0, #0xf000
@@ -82,13 +82,7 @@ mono_fallback_get_tls_key :
         */
 
        .align 4
-#ifdef TARGET_MACH
-       .global _mono_fast_set_tls_key
-_mono_fast_set_tls_key :
-#else
-       .global mono_fast_set_tls_key
-mono_fast_set_tls_key :
-#endif
+DECLARE_GLOBAL_SYMBOL mono_fast_set_tls_key
 #if defined(__linux__)
        mrc     p15, 0, r2, c13, c0, 3
 #if defined(HAVE_KW_THREAD)
@@ -103,6 +97,7 @@ mono_fast_set_tls_key :
        str     r1, [r2, r0, lsl #2]
        bx      lr
 #endif
+DECLARE_GLOBAL_SYMBOL mono_fast_set_tls_key_end
 
        /*
         * The following thunks set the value corresponding to the key/offset
@@ -111,13 +106,7 @@ mono_fast_set_tls_key :
         */
 
        .align 4
-#ifdef TARGET_MACH
-       .global _mono_fallback_set_tls_key
-_mono_fallback_set_tls_key :
-#else
-       .global mono_fallback_set_tls_key
-mono_fallback_set_tls_key :
-#endif
+DECLARE_GLOBAL_SYMBOL mono_fallback_set_tls_key
 #if defined(__linux__)
        mov     r2, r0
        mvn     r0, #0xf000
index e0aa41bc630c56d2bab32d388804f309afd60ec7..30b2494dfc70c21ad396339e5e8cec5f8c86af6f 100644 (file)
@@ -11,4 +11,9 @@ void mono_fast_set_tls_key (int, int);
 int mono_fallback_get_tls_key (int);
 void mono_fallback_set_tls_key (int, int);
 
+/* End of thunks */
+
+void mono_fast_get_tls_key_end (void);
+void mono_fast_set_tls_key_end (void);
+
 #endif
index bf0ecc6eebcf42e6eb85e3eacccb9940eef0b54d..de33d16e54d2dd8c54cc9cf52bc3b8f6e988001c 100644 (file)
@@ -746,9 +746,10 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit
 #define MAX_ARCH_DELEGATE_PARAMS 3
 
 static gpointer
-get_delegate_invoke_impl (gboolean has_target, gboolean param_count, guint32 *code_size)
+get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, gboolean param_count)
 {
        guint8 *code, *start;
+       GSList *unwind_ops = mono_arch_get_cie_program ();
 
        if (has_target) {
                start = code = mono_global_codeman_reserve (12);
@@ -779,9 +780,15 @@ get_delegate_invoke_impl (gboolean has_target, gboolean param_count, guint32 *co
                mono_arch_flush_icache (start, size);
        }
 
+       if (has_target) {
+                *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, unwind_ops);
+       } else {
+                char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
+                *info = mono_tramp_info_create (name, start, code - start, NULL, unwind_ops);
+                g_free (name);
+       }
+
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
-       if (code_size)
-               *code_size = code - start;
 
        return start;
 }
@@ -796,19 +803,15 @@ GSList*
 mono_arch_get_delegate_invoke_impls (void)
 {
        GSList *res = NULL;
-       guint8 *code;
-       guint32 code_len;
+       MonoTrampInfo *info;
        int i;
-       char *tramp_name;
 
-       code = get_delegate_invoke_impl (TRUE, 0, &code_len);
-       res = g_slist_prepend (res, mono_tramp_info_create ("delegate_invoke_impl_has_target", code, code_len, NULL, NULL));
+       get_delegate_invoke_impl (&info, TRUE, 0);
+       res = g_slist_prepend (res, info);
 
        for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
-               code = get_delegate_invoke_impl (FALSE, i, &code_len);
-               tramp_name = g_strdup_printf ("delegate_invoke_impl_target_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+               get_delegate_invoke_impl (&info, FALSE, i);
+               res = g_slist_prepend (res, info);
        }
 
        return res;
@@ -833,10 +836,13 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        return cached;
                }
 
-               if (mono_aot_only)
+               if (mono_aot_only) {
                        start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
-               else
-                       start = get_delegate_invoke_impl (TRUE, 0, NULL);
+               } else {
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, TRUE, 0);
+                       mono_tramp_info_register (info, NULL);
+               }
                cached = start;
                mono_mini_arch_unlock ();
                return cached;
@@ -862,7 +868,9 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        start = mono_aot_get_trampoline (name);
                        g_free (name);
                } else {
-                       start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL);
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, FALSE, sig->param_count);
+                       mono_tramp_info_register (info, NULL);
                }
                cache [sig->param_count] = start;
                mono_mini_arch_unlock ();
@@ -3892,6 +3900,10 @@ handle_thunk (MonoCompile *cfg, MonoDomain *domain, guchar *code, const guchar *
                                        /* Free entry */
                                        target_thunk = p;
                                        break;
+                               } else if (((guint32*)p) [2] == (guint32)target) {
+                                       /* Thunk already points to target */
+                                       target_thunk = p;
+                                       break;
                                }
                        }
                }
@@ -5968,6 +5980,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ins->backend.pc_offset = code - cfg->native_code;
                        bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
                        break;
+               case OP_GC_SAFE_POINT: {
+#if defined (USE_COOP_GC)
+                       const char *polling_func = NULL;
+                       guint8 *buf [1];
+
+                       polling_func = "mono_threads_state_poll";
+                       ARM_LDR_IMM (code, ARMREG_IP, ins->sreg1, 0);
+                       ARM_CMP_REG_IMM (code, ARMREG_IP, 0, 0);
+                       buf [0] = code;
+                       ARM_B_COND (code, ARMCOND_EQ, 0);
+                       mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, polling_func);
+                       code = emit_call_seq (cfg, code);
+                       arm_patch (buf [0], code);
+#endif
+                       break;
+               }
 
                default:
                        g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
@@ -6003,6 +6031,27 @@ mono_arch_register_lowlevel_calls (void)
                if (mono_arm_have_fast_tls ()) {
                        mono_register_jit_icall (mono_fast_get_tls_key, "mono_get_tls_key", mono_create_icall_signature ("ptr ptr"), TRUE);
                        mono_register_jit_icall (mono_fast_set_tls_key, "mono_set_tls_key", mono_create_icall_signature ("void ptr ptr"), TRUE);
+
+                       mono_tramp_info_register (
+                               mono_tramp_info_create (
+                                       "mono_get_tls_key",
+                                       (guint8*)mono_fast_get_tls_key,
+                                       (guint8*)mono_fast_get_tls_key_end - (guint8*)mono_fast_get_tls_key,
+                                       NULL,
+                                       mono_arch_get_cie_program ()
+                                       ),
+                               NULL
+                               );
+                       mono_tramp_info_register (
+                               mono_tramp_info_create (
+                                       "mono_set_tls_key",
+                                       (guint8*)mono_fast_set_tls_key,
+                                       (guint8*)mono_fast_set_tls_key_end - (guint8*)mono_fast_set_tls_key,
+                                       NULL,
+                                       mono_arch_get_cie_program ()
+                                       ),
+                               NULL
+                               );
                } else {
                        g_warning ("No fast tls on device. Using fallbacks.");
                        mono_register_jit_icall (mono_fallback_get_tls_key, "mono_get_tls_key", mono_create_icall_signature ("ptr ptr"), TRUE);
@@ -6140,10 +6189,10 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                 * FIXME: Optimize this.
                 */
                ARM_PUSH (code, (1 << ARMREG_R7) | (1 << ARMREG_LR));
-               ARM_MOV_REG_REG (code, ARMREG_R7, ARMREG_SP);
                prev_sp_offset += 8; /* r7 and lr */
                mono_emit_unwind_op_def_cfa_offset (cfg, code, prev_sp_offset);
                mono_emit_unwind_op_offset (cfg, code, ARMREG_R7, (- prev_sp_offset) + 0);
+               ARM_MOV_REG_REG (code, ARMREG_R7, ARMREG_SP);
        }
 
        if (!method->save_lmf) {
@@ -6607,6 +6656,9 @@ mono_arch_emit_epilog (MonoCompile *cfg)
         */
        code = cfg->native_code + cfg->code_len;
 
+       /* Save the uwind state which is needed by the out-of-line code */
+       mono_emit_unwind_op_remember_state (cfg, code);
+
        if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
                code = mono_arch_instrument_epilog (cfg, mono_trace_leave_method, code, TRUE);
        }
@@ -6642,7 +6694,7 @@ mono_arch_emit_epilog (MonoCompile *cfg)
        }
 
        if (method->save_lmf) {
-               int lmf_offset, reg, sp_adj, regmask;
+               int lmf_offset, reg, sp_adj, regmask, nused_int_regs = 0;
                /* all but r0-r3, sp and pc */
                pos += sizeof (MonoLMF) - (MONO_ARM_NUM_SAVED_REGS * sizeof (mgreg_t));
                lmf_offset = pos;
@@ -6664,15 +6716,33 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                        regmask &= ~(1 << ARMREG_PC);
                /* point sp at the registers to restore: 10 is 14 -4, because we skip r0-r3 */
                code = emit_big_add (code, ARMREG_SP, cfg->frame_reg, cfg->stack_usage - lmf_offset + sp_adj);
+               for (i = 0; i < 16; i++) {
+                       if (regmask & (1 << i))
+                               nused_int_regs ++;
+               }
+               mono_emit_unwind_op_def_cfa (cfg, code, ARMREG_SP, ((iphone_abi ? 3 : 0) + nused_int_regs) * 4);
                /* restore iregs */
                ARM_POP (code, regmask); 
                if (iphone_abi) {
+                       for (i = 0; i < 16; i++) {
+                               if (regmask & (1 << i))
+                                       mono_emit_unwind_op_same_value (cfg, code, i);
+                       }
                        /* Restore saved r7, restore LR to PC */
                        /* Skip lr from the lmf */
+                       mono_emit_unwind_op_def_cfa_offset (cfg, code, 3 * 4);
                        ARM_ADD_REG_IMM (code, ARMREG_SP, ARMREG_SP, sizeof (gpointer), 0);
+                       mono_emit_unwind_op_def_cfa_offset (cfg, code, 2 * 4);
                        ARM_POP (code, (1 << ARMREG_R7) | (1 << ARMREG_PC));
                }
        } else {
+               int i, nused_int_regs = 0;
+
+               for (i = 0; i < 16; i++) {
+                       if (cfg->used_int_regs & (1 << i))
+                               nused_int_regs ++;
+               }
+
                if ((i = mono_arm_is_rotated_imm8 (cfg->stack_usage, &rot_amount)) >= 0) {
                        ARM_ADD_REG_IMM (code, ARMREG_SP, cfg->frame_reg, i, rot_amount);
                } else {
@@ -6680,17 +6750,32 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                        ARM_ADD_REG_REG (code, ARMREG_SP, cfg->frame_reg, ARMREG_IP);
                }
 
+               if (cfg->frame_reg != ARMREG_SP) {
+                       mono_emit_unwind_op_def_cfa_reg (cfg, code, ARMREG_SP);
+               }
+
                if (iphone_abi) {
                        /* Restore saved gregs */
-                       if (cfg->used_int_regs)
+                       if (cfg->used_int_regs) {
+                               mono_emit_unwind_op_def_cfa_offset (cfg, code, (2 + nused_int_regs) * 4);
                                ARM_POP (code, cfg->used_int_regs);
+                               for (i = 0; i < 16; i++) {
+                                       if (cfg->used_int_regs & (1 << i))
+                                               mono_emit_unwind_op_same_value (cfg, code, i);
+                               }
+                       }
+                       mono_emit_unwind_op_def_cfa_offset (cfg, code, 2 * 4);
                        /* Restore saved r7, restore LR to PC */
                        ARM_POP (code, (1 << ARMREG_R7) | (1 << ARMREG_PC));
                } else {
+                       mono_emit_unwind_op_def_cfa_offset (cfg, code, (nused_int_regs + 1) * 4);
                        ARM_POP (code, cfg->used_int_regs | (1 << ARMREG_PC));
                }
        }
 
+       /* Restore the unwind state to be the same as before the epilog */
+       mono_emit_unwind_op_restore_state (cfg, code);
+
        cfg->code_len = code - cfg->native_code;
 
        g_assert (cfg->code_len < cfg->code_size);
@@ -6845,6 +6930,16 @@ mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
        return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
 }
 
+GSList*
+mono_arch_get_cie_program (void)
+{
+       GSList *l = NULL;
+
+       mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, ARMREG_SP, 0);
+
+       return l;
+}
+
 /* #define ENABLE_WRONG_METHOD_CHECK 1 */
 #define BASE_SIZE (6 * 4)
 #define BSEARCH_ENTRY_SIZE (4 * 4)
@@ -6913,6 +7008,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
 #ifdef ENABLE_WRONG_METHOD_CHECK
        char * cond;
 #endif
+       GSList *unwind_ops;
 
        size = BASE_SIZE;
 #ifdef USE_JUMP_TABLES
@@ -6967,6 +7063,8 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                code = mono_domain_code_reserve (domain, size);
        start = code;
 
+       unwind_ops = mono_arch_get_cie_program ();
+
 #ifdef DEBUG_IMT
        g_print ("Building IMT thunk for class %s %s entries %d code size %d code at %p end %p vtable %p fail_tramp %p\n", vtable->klass->name_space, vtable->klass->name, count, size, start, ((guint8*)start) + size, vtable, fail_tramp);
        for (i = 0; i < count; ++i) {
@@ -6977,6 +7075,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
 
 #ifdef USE_JUMP_TABLES
        ARM_PUSH3 (code, ARMREG_R0, ARMREG_R1, ARMREG_R2);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, 3 * sizeof (mgreg_t));
 #define VTABLE_JTI 0
 #define IMT_METHOD_OFFSET 0
 #define TARGET_CODE_OFFSET 1
@@ -6991,10 +7090,13 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        ARM_LDR_IMM (code, ARMREG_IP, ARMREG_R2, VTABLE_JTI);
        set_jumptable_element (jte, VTABLE_JTI, vtable);
 #else
-       if (large_offsets)
+       if (large_offsets) {
                ARM_PUSH4 (code, ARMREG_R0, ARMREG_R1, ARMREG_IP, ARMREG_PC);
-       else
+               mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, 4 * sizeof (mgreg_t));
+       } else {
                ARM_PUSH2 (code, ARMREG_R0, ARMREG_R1);
+               mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, 2 * sizeof (mgreg_t));
+       }
        ARM_LDR_IMM (code, ARMREG_R0, ARMREG_LR, -4);
        vtable_target = code;
        ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
@@ -7067,6 +7169,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                                code = load_element_with_regbase_cond (code, ARMREG_R1, ARMREG_R2, target_code_jti, ARMCOND_AL);
                                /* Restore registers */
                                ARM_POP3 (code, ARMREG_R0, ARMREG_R1, ARMREG_R2);
+                               mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, 0);
                                /*  And branch */
                                ARM_BX (code, ARMREG_R1);
                                set_jumptable_element (jte, target_code_jti, item->value.target_code);
@@ -7098,6 +7201,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                                        ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_IP, ARMREG_R1);
                                        /* Restore registers and branch */
                                        ARM_POP3 (code, ARMREG_R0, ARMREG_R1, ARMREG_R2);
+                                       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, 0);
                                        ARM_BX (code, ARMREG_IP);
 #else
                                        vtable_offset_ins = code;
@@ -7114,11 +7218,15 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
 #ifdef USE_JUMP_TABLES
                                        ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, vtable_offset);
                                        ARM_POP3 (code, ARMREG_R0, ARMREG_R1, ARMREG_R2);
+                                       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, 0);
                                        ARM_BX (code, ARMREG_IP);
 #else
                                        ARM_POP2 (code, ARMREG_R0, ARMREG_R1);
-                                       if (large_offsets)
+                                       if (large_offsets) {
+                                               mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, 2 * sizeof (mgreg_t));
                                                ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 2 * sizeof (gpointer));
+                                       }
+                                       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, 0);
                                        ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, vtable_offset);
 #endif
                                }
@@ -7132,6 +7240,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                                code = load_element_with_regbase_cond (code, ARMREG_R1, ARMREG_R2, target_code_jti, ARMCOND_AL);
                                /* Restore registers */
                                ARM_POP3 (code, ARMREG_R0, ARMREG_R1, ARMREG_R2);
+                               mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, 0);
                                /* And branch */
                                ARM_BX (code, ARMREG_R1);
                                set_jumptable_element (jte, target_code_jti, fail_tramp);
@@ -7231,6 +7340,9 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        mono_stats.imt_thunks_size += code - start;
 
        g_assert (DISTANCE (start, code) <= size);
+
+       mono_tramp_info_register (mono_tramp_info_create (NULL, (guint8*)start, DISTANCE (start, code), NULL, unwind_ops), domain);
+
        return start;
 }
 
index cb7a975f9d1d36bbc8876f9f33e83b32f019e062..ab0024c41ba702293f2a6f99422328e2e5fcbe97 100644 (file)
@@ -239,12 +239,17 @@ mono_runtime_install_handlers (void)
 pid_t
 mono_runtime_syscall_fork ()
 {
+#ifdef HAVE_FORK
        return (pid_t) fork ();
+#else
+       g_assert_not_reached ();
+#endif
 }
 
 void
 mono_gdb_render_native_backtraces (pid_t crashed_pid)
 {
+#ifdef HAVE_EXECV
        const char *argv [5];
        char template [] = "/tmp/mono-gdb-commands.XXXXXX";
        FILE *commands;
@@ -288,6 +293,9 @@ mono_gdb_render_native_backtraces (pid_t crashed_pid)
 
        execv (argv [0], (char**)argv);
        unlink (template);
+#else
+       fprintf (stderr, "mono_gdb_render_native_backtraces not supported on this platform\n");
+#endif // HAVE_EXECV
 }
 
 gboolean
index 5937e45464ddab96661b29795cef6441c8b49eb7..26fccf0d08ee0864712e5eb1ee2075a06e8bd3ae 100644 (file)
@@ -98,13 +98,13 @@ mono_exceptions_init (void)
                MonoTrampInfo *info;
 
                restore_context_func = mono_arch_get_restore_context (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
                call_filter_func = mono_arch_get_call_filter (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
                throw_exception_func = mono_arch_get_throw_exception (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
                rethrow_exception_func = mono_arch_get_rethrow_exception (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
        }
 #ifdef MONO_ARCH_HAVE_RESTORE_STACK_SUPPORT
        try_more_restore_tramp = mono_create_specific_trampoline (try_more_restore, MONO_TRAMPOLINE_RESTORE_STACK_PROT, mono_domain_get (), NULL);
@@ -165,7 +165,7 @@ mono_get_throw_corlib_exception (void)
                code = mono_aot_get_trampoline ("throw_corlib_exception");
        else {
                code = mono_arch_get_throw_corlib_exception (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
        }
 
        mono_memory_barrier ();
@@ -243,6 +243,8 @@ find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, Mo
                if (managed)
                        *managed = TRUE;
                return frame.ji;
+       case FRAME_TYPE_TRAMPOLINE:
+               return frame.ji;
        case FRAME_TYPE_MANAGED_TO_NATIVE:
                if (frame.ji)
                        return frame.ji;
@@ -301,10 +303,10 @@ mono_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *re
        if (ji == (gpointer)-1)
                return ji;
 
-       if (ji)
+       if (ji && !ji->is_trampoline)
                method = jinfo_get_method (ji);
 
-       if (managed2 || (ji && method->wrapper_type)) {
+       if (managed2 || (method && method->wrapper_type)) {
                const char *real_ip, *start;
                gint32 offset;
 
@@ -397,7 +399,7 @@ mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,
                *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~(SIZEOF_VOID_P -1));
        }
 
-       if (frame->ji && !frame->ji->async)
+       if (frame->ji && !frame->ji->is_trampoline && !frame->ji->async)
                method = jinfo_get_method (frame->ji);
 
        if (frame->type == FRAME_TYPE_MANAGED && method) {
@@ -451,6 +453,9 @@ mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,
        return TRUE;
 }
 
+/*
+ * This function is async-safe.
+ */
 static gpointer
 get_generic_info_from_stack_frame (MonoJitInfo *ji, MonoContext *ctx)
 {
@@ -635,11 +640,11 @@ ves_icall_System_Exception_get_trace (MonoException *ex)
                gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0);
                gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1);
 
-               ji = mono_jit_info_table_find (domain, ip);
+               ji = mono_jit_info_table_find_internal (domain, ip, TRUE, TRUE);
                if (ji == NULL) {
                        /* Unmanaged frame */
                        g_string_append_printf (trace_str, "in (unmanaged) %p\n", ip);
-               } else {
+               } else if (!ji->is_trampoline) {
                        gchar *location;
                        gint32 address;
                        MonoMethod *method = get_method_from_stack_frame (ji, generic_info);
@@ -870,7 +875,7 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain
                if (!res)
                        return;
 
-               if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji) {
+               if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji && !frame.ji->is_trampoline) {
                        MonoDebugSourceLocation *source;
 
                        source = mono_debug_lookup_source_location (jinfo_get_method (frame.ji), frame.native_offset, domain);
@@ -889,7 +894,7 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain
 
                frame.il_offset = il_offset;
 
-               if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji) {
+               if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji && !frame.ji->is_trampoline) {
                        frame.actual_method = get_method_from_stack_frame (frame.ji, get_generic_info_from_stack_frame (frame.ji, &ctx));
                } else {
                        frame.actual_method = frame.method;
@@ -944,7 +949,9 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
                if (!res)
                        return FALSE;
 
-               if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE || frame.type == FRAME_TYPE_DEBUGGER_INVOKE)
+               if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
+                               frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
+                               frame.type == FRAME_TYPE_TRAMPOLINE)
                        continue;
 
                ji = frame.ji;
@@ -1085,7 +1092,7 @@ mini_jit_info_table_find_ext (MonoDomain *domain, char *addr, gboolean allow_tra
 MonoJitInfo*
 mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain)
 {
-       return mini_jit_info_table_find_ext (domain, addr, FALSE, out_domain);
+       return mini_jit_info_table_find_ext (domain, addr, TRUE, out_domain);
 }
 
 /*
@@ -1265,7 +1272,9 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3
 
                unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
                if (unwind_res) {
-                       if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
+                       if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
+                                       frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
+                                       frame.type == FRAME_TYPE_TRAMPOLINE) {
                                *ctx = new_ctx;
                                continue;
                        }
@@ -1602,7 +1611,9 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
 
                        unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
                        if (unwind_res) {
-                               if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
+                               if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
+                                               frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
+                                               frame.type == FRAME_TYPE_TRAMPOLINE) {
                                        *ctx = new_ctx;
                                        continue;
                                }
@@ -1731,8 +1742,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
 
                                        return 0;
                                }
-                               if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
-                                       (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT)) {
+                               if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
                                        if (mono_trace_is_enabled () && mono_trace_eval (method))
                                                g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
                                        jit_tls->orig_ex_ctx_set = TRUE;
@@ -1740,8 +1750,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
                                        jit_tls->orig_ex_ctx_set = FALSE;
                                        call_filter (ctx, ei->handler_start);
                                }
-                               if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
-                                       (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
+                               if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
                                        if (mono_trace_is_enabled () && mono_trace_eval (method))
                                                g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
                                        jit_tls->orig_ex_ctx_set = TRUE;
@@ -2044,7 +2053,7 @@ print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer da
        PrintOverflowUserData *user_data = data;
        gchar *location;
 
-       if (frame->ji)
+       if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
                method = jinfo_get_method (frame->ji);
 
        if (method) {
@@ -2097,7 +2106,7 @@ mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx,
 
        mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
 #else
-       if (ji && jinfo_get_method (ji))
+       if (ji && !ji->is_trampoline && jinfo_get_method (ji))
                mono_runtime_printf_err ("At %s", mono_method_full_name (jinfo_get_method (ji), TRUE));
        else
                mono_runtime_printf_err ("At <unmanaged>.");
@@ -2111,7 +2120,7 @@ print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer d
 {
        MonoMethod *method = NULL;
 
-       if (frame->ji)
+       if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
                method = jinfo_get_method (frame->ji);
 
        if (method) {
@@ -2130,7 +2139,7 @@ print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer d
        GString *p = (GString*)data;
        MonoMethod *method = NULL;
 
-       if (frame->ji)
+       if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
                method = jinfo_get_method (frame->ji);
 
        if (method && frame->domain) {
@@ -2552,6 +2561,26 @@ mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
 #endif
 }
 
+void
+mono_thread_state_init (MonoThreadUnwindState *ctx)
+{
+       MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
+
+#if defined(MONO_CROSS_COMPILE)
+       ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
+#elif MONO_ARCH_HAS_MONO_CONTEXT
+       MONO_CONTEXT_GET_CURRENT (ctx->ctx);
+#else
+       g_error ("Use a null sigctx requires a working mono-context");
+#endif
+
+       ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
+       ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
+       ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread ? thread->jit_data : NULL;
+       ctx->valid = TRUE;
+}
+
+
 gboolean
 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
 {
index 3d24b46d082e9d3b49bc0b4293b660efb11b20f4..27a36204ca0c354e2448695293162924744d88c8 100644 (file)
@@ -821,6 +821,7 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end)
                ji = frame.ji;
 
                // FIXME: For skipped frames, scan the param area of the parent frame conservatively ?
+               // FIXME: trampolines
 
                if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
                        /*
index d3e3f9338cc50e871d5b50a967790b7e5286016e..e1ca51ba9806b76ac01465f7ad6d8b5f0638ea26 100644 (file)
@@ -4618,6 +4618,8 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
 
        mono_stats.imt_thunks_size += size;
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, size, NULL, NULL), domain);
+
        return start;
 }
 
index 7e3522613f4daf6333429daf2bf7558e6f02972b..f894a7721648c58e1f40e1f0556a192aec0923c6 100644 (file)
@@ -648,11 +648,7 @@ mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, Func
   // EngineBuilder no longer has a copy assignment operator (?)
   std::unique_ptr<Module> Owner(unwrap(MP));
   EngineBuilder b (std::move(Owner));
-#ifdef TARGET_AMD64
-  ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).setMCPU (cpu_name).setCodeModel (CodeModel::Large).create ();
-#else
   ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).setMCPU (cpu_name).create ();
-#endif
 
   g_assert (EE);
   mono_ee->EE = EE;
index d98c658f4c446d0d99f34a19e72042d3b80c5347..af00dcd9841a504a4cfcc938128f3dbb4f0ba59e 100644 (file)
@@ -1186,6 +1186,9 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
 
                                members [0] = IntPtrType ();
                                ret_type = LLVMStructType (members, 1, FALSE);
+                       } else if (cinfo->ret.pair_storage [0] == LLVMArgNone && cinfo->ret.pair_storage [1] == LLVMArgNone) {
+                               /* Empty struct */
+                               ret_type = LLVMVoidType ();
                        } else {
                                g_assert_not_reached ();
                        }
@@ -2252,14 +2255,6 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
        ;
 }
 
-/* Have to export this for AOT */
-void
-mono_personality (void)
-{
-       /* Not used */
-       g_assert_not_reached ();
-}
-
 static void
 process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, MonoInst *ins)
 {
@@ -2546,6 +2541,10 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                case LLVMArgVtypeInReg: {
                        LLVMValueRef regs [2];
 
+                       if (LLVMTypeOf (lcall) == LLVMVoidType ())
+                               /* Empty struct */
+                               break;
+
                        if (!addresses [ins->dreg])
                                addresses [ins->dreg] = build_alloca (ctx, sig->ret);
 
@@ -2622,7 +2621,7 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
 
        if (cfg->compile_aot) {
                /* Use a dummy personality function */
-               personality = LLVMGetNamedFunction (module, "mono_aot_personality");
+               personality = LLVMGetNamedFunction (module, "mono_personality");
                g_assert (personality);
        } else {
                personality = LLVMGetNamedFunction (module, "mono_personality");
@@ -2759,7 +2758,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
        if (bb->flags & BB_EXCEPTION_HANDLER) {
                if (!bblocks [bb->block_num].invoke_target) {
-                       //LLVM_FAILURE (ctx, "handler without invokes");
+                       LLVM_FAILURE (ctx, "handler without invokes");
                }
 
                emit_handler_start (ctx, bb, builder);
@@ -6015,21 +6014,6 @@ mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix,
                LLVMSetInitializer (lmodule->got_var, LLVMConstNull (got_type));
        }
 
-       /* Add a dummy personality function */
-       {
-               LLVMBasicBlockRef lbb;
-               LLVMBuilderRef lbuilder;
-               LLVMValueRef personality;
-
-               personality = LLVMAddFunction (lmodule->module, "mono_aot_personality", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
-               LLVMSetLinkage (personality, LLVMInternalLinkage);
-               lbb = LLVMAppendBasicBlock (personality, "BB0");
-               lbuilder = LLVMCreateBuilder ();
-               LLVMPositionBuilderAtEnd (lbuilder, lbb);
-               LLVMBuildRetVoid (lbuilder);
-               mark_as_used (lmodule, personality);
-       }
-
        lmodule->llvm_types = g_hash_table_new (NULL, NULL);
        lmodule->plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
        lmodule->plt_entries_ji = g_hash_table_new (NULL, NULL);
index 4c18cc970ee5a77df3e3444edc6e00b5348872fa..362fa3a14bac36bfaf82a57b24611e83821e706b 100644 (file)
@@ -544,7 +544,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit
 #define MAX_ARCH_DELEGATE_PARAMS (4 - 1)
 
 static gpointer
-get_delegate_invoke_impl (gboolean has_target, gboolean param_count, guint32 *code_size)
+get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, gboolean param_count)
 {
        guint8 *code, *start;
 
@@ -579,8 +579,13 @@ get_delegate_invoke_impl (gboolean has_target, gboolean param_count, guint32 *co
                mono_arch_flush_icache (start, size);
        }
 
-       if (code_size)
-               *code_size = code - start;
+       if (has_target) {
+               *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
+       } else {
+               char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
+               *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
+               g_free (name);
+       }
 
        return start;
 }
@@ -595,19 +600,15 @@ GSList*
 mono_arch_get_delegate_invoke_impls (void)
 {
        GSList *res = NULL;
-       guint8 *code;
-       guint32 code_len;
+       MonoTrampInfo *info;
        int i;
-       char *tramp_name;
 
-       code = get_delegate_invoke_impl (TRUE, 0, &code_len);
-       res = g_slist_prepend (res, mono_tramp_info_create ("delegate_invoke_impl_has_target", code, code_len, NULL, NULL));
+       get_delegate_invoke_impl (&info, TRUE, 0);
+       res = g_slist_prepend (res, info);
 
        for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
-               code = get_delegate_invoke_impl (FALSE, i, &code_len);
-               tramp_name = g_strdup_printf ("delegate_invoke_impl_target_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+               get_delegate_invoke_impl (&info, FALSE, i);
+               res = g_slist_prepend (res, info);
        }
 
        return res;
@@ -630,10 +631,13 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        return cached;
                }
 
-               if (mono_aot_only)
+               if (mono_aot_only) {
                        start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
-               else
-                       start = get_delegate_invoke_impl (TRUE, 0, NULL);
+               } else {
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, TRUE, 0);
+                       mono_tramp_info_register (info, NULL);
+               }
                cached = start;
                mono_mini_arch_unlock ();
                return cached;
@@ -659,7 +663,9 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        start = mono_aot_get_trampoline (name);
                        g_free (name);
                } else {
-                       start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL);
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, FALSE, sig->param_count);
+                       mono_tramp_info_register (info, NULL);
                }
                cache [sig->param_count] = start;
                mono_mini_arch_unlock ();
@@ -6004,6 +6010,9 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                mono_stats.imt_thunks_size += code - start;
        g_assert (code - start <= size);
        mono_arch_flush_icache (start, size);
+
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return start;
 }
 
index b2a08666096f48f91f8b6b5fa65898484be9caaa..cba97096e0e0b7cbc70d1ac41480441b85d4d20a 100644 (file)
@@ -1076,10 +1076,7 @@ MINI_OP(OP_GC_PARAM_SLOT_LIVENESS_DEF, "gc_param_slot_liveness_def", NONE, NONE,
 MINI_OP(OP_GENERIC_CLASS_INIT, "generic_class_init", NONE, IREG, NONE)
 
 /* Arch specific opcodes */
-/* #if defined(__native_client_codegen__) || defined(__native_client__) */
-/* We have to define these in terms of the TARGET defines, not NaCl defines */
-/* because genmdesc.pl doesn't have multiple defines per platform.          */
-#if defined(TARGET_AMD64) || defined(TARGET_X86)
+#if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM)
 MINI_OP(OP_GC_SAFE_POINT,     "gc_safe_point", NONE, IREG, NONE)
 #endif
 
index 5bc983ae8cd6582787768fb692e4682291758291..fe5cc782f833f26e4d965be3e4667654fc703f5d 100644 (file)
@@ -96,6 +96,12 @@ mono_runtime_install_handlers (void)
 }
 #endif
 
+void
+mono_runtime_posix_install_handlers(void)
+{
+
+}
+
 void
 mono_runtime_shutdown_handlers (void)
 {
@@ -205,7 +211,7 @@ MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
        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_internal (mono_domain_get (), mono_arch_ip_from_context (ctx), TRUE, TRUE);
        if (!ji) {
         if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
index 976a7f2a518c25e2e6a5db63c7b049f6c216f24b..06528bdee781394e7fa004661f2266914fe453fe 100644 (file)
@@ -380,7 +380,7 @@ mono_ppc_is_direct_call_sequence (guint32 *code)
 #define MAX_ARCH_DELEGATE_PARAMS 7
 
 static gpointer
-get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *code_len, gboolean aot)
+get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
 {
        guint8 *code, *start;
 
@@ -430,8 +430,13 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
                mono_arch_flush_icache (start, size);
        }
 
-       if (code_len)
-               *code_len = code - start;
+       if (has_target) {
+               *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
+       } else {
+               char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
+               *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
+               g_free (name);
+       }
 
        return start;
 }
@@ -440,19 +445,15 @@ GSList*
 mono_arch_get_delegate_invoke_impls (void)
 {
        GSList *res = NULL;
-       guint8 *code;
-       guint32 code_len;
+       MonoTrampInfo *info;
        int i;
-       char *tramp_name;
 
-       code = get_delegate_invoke_impl (TRUE, 0, &code_len, TRUE);
-       res = g_slist_prepend (res, mono_tramp_info_create ("delegate_invoke_impl_has_target", code, code_len, NULL, NULL));
+       get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
+       res = g_slist_prepend (res, info);
 
-       for (i = 0; i < MAX_ARCH_DELEGATE_PARAMS; ++i) {
-               code = get_delegate_invoke_impl (FALSE, i, &code_len, TRUE);
-               tramp_name = g_strdup_printf ("delegate_invoke_impl_target_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+       for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
+               get_delegate_invoke_impl (&info, FALSE, i, TRUE);
+               res = g_slist_prepend (res, info);
        }
 
        return res;
@@ -473,11 +474,13 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                if (cached)
                        return cached;
 
-               if (mono_aot_only)
+               if (mono_aot_only) {
                        start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
-               else
-                       start = get_delegate_invoke_impl (TRUE, 0, NULL, FALSE);
-
+               } else {
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
+                       mono_tramp_info_register (info, NULL);
+               }
                mono_memory_barrier ();
 
                cached = start;
@@ -501,7 +504,9 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        start = mono_aot_get_trampoline (name);
                        g_free (name);
                } else {
-                       start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL, FALSE);
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
+                       mono_tramp_info_register (info, NULL);
                }
 
                mono_memory_barrier ();
@@ -4415,6 +4420,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        else
                                ppc_mr (code, ins->dreg, ins->sreg1);
                        break;
+#else
+               case OP_ICONV_TO_R4:
+               case OP_ICONV_TO_R8: {
+                       if (cpu_hw_caps & PPC_ISA_64) {
+                               ppc_srawi(code, ppc_r0, ins->sreg1, 31);
+                               ppc_stw (code, ppc_r0, -8, ppc_r1);
+                               ppc_stw (code, ins->sreg1, -4, ppc_r1);
+                               ppc_lfd (code, ins->dreg, -8, ppc_r1);
+                               ppc_fcfid (code, ins->dreg, ins->dreg);
+                               if (ins->opcode == OP_ICONV_TO_R4)
+                                       ppc_frsp (code, ins->dreg, ins->dreg);
+                               }
+                       break;
+               }
+#endif
+
                case OP_ATOMIC_ADD_I4:
                CASE_PPC64 (OP_ATOMIC_ADD_I8) {
                        int location = ins->inst_basereg;
@@ -4448,21 +4469,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_mr (code, ins->dreg, ppc_r0);
                        break;
                }
-#else
-               case OP_ICONV_TO_R4:
-               case OP_ICONV_TO_R8: {
-                       if (cpu_hw_caps & PPC_ISA_64) {
-                               ppc_srawi(code, ppc_r0, ins->sreg1, 31);
-                               ppc_stw (code, ppc_r0, -8, ppc_r1);
-                               ppc_stw (code, ins->sreg1, -4, ppc_r1);
-                               ppc_lfd (code, ins->dreg, -8, ppc_r1);
-                               ppc_fcfid (code, ins->dreg, ins->dreg);
-                               if (ins->opcode == OP_ICONV_TO_R4)
-                                       ppc_frsp (code, ins->dreg, ins->dreg);
-                               }
-                       break;
-               }
-#endif
                case OP_ATOMIC_CAS_I4:
                CASE_PPC64 (OP_ATOMIC_CAS_I8) {
                        int location = ins->sreg1;
@@ -5742,6 +5748,9 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                mono_stats.imt_thunks_size += code - start;
        g_assert (code - start <= size);
        mono_arch_flush_icache (start, size);
+
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return start;
 }
 
index 0111f51a4889490ccfaf22a819c9cbbf99c0d10c..fee343d69af102285c42f6ff1759f91a91ac1546 100644 (file)
@@ -155,7 +155,7 @@ get_method_from_ip (void *ip)
        if (!domain)
                domain = mono_get_root_domain ();
 
-       ji = mono_jit_info_table_find (domain, ip);
+       ji = mono_jit_info_table_find_internal (domain, ip, TRUE, TRUE);
        if (!ji) {
                user_data.ip = ip;
                user_data.method = NULL;
@@ -170,7 +170,11 @@ get_method_from_ip (void *ip)
                }
                else
                        return NULL;
+       } else if (ji->is_trampoline) {
+               res = g_strdup_printf ("<%p - %s trampoline>", ip, ((MonoTrampInfo*)ji->d.tramp_info)->name);
+               return res;
        }
+
        method = mono_method_full_name (jinfo_get_method (ji), TRUE);
        /* FIXME: unused ? */
        location = mono_debug_lookup_source_location (jinfo_get_method (ji), (guint32)((guint8*)ip - (guint8*)ji->code_start), domain);
@@ -286,7 +290,7 @@ gboolean mono_method_same_domain (MonoJitInfo *caller, MonoJitInfo *callee)
 {
        MonoMethod *cmethod;
 
-       if (!caller || !callee)
+       if (!caller || caller->is_trampoline || !callee || callee->is_trampoline)
                return FALSE;
 
        /*
@@ -460,14 +464,10 @@ mono_tramp_info_create (const char *name, guint8 *code, guint32 code_size, MonoJ
 void
 mono_tramp_info_free (MonoTrampInfo *info)
 {
-       GSList *l;
-
        g_free (info->name);
 
        // FIXME: ji
-       for (l = info->unwind_ops; l; l = l->next)
-               g_free (l->data);
-       g_slist_free (info->unwind_ops);
+       mono_free_unwind_info (info->unwind_ops);
        g_free (info);
 }
 
@@ -480,7 +480,8 @@ register_trampoline_jit_info (MonoDomain *domain, MonoTrampInfo *info)
        mono_jit_info_init (ji, NULL, info->code, info->code_size, 0, 0, 0);
        ji->d.tramp_info = info;
        ji->is_trampoline = TRUE;
-       // FIXME: Unwind info
+
+       ji->unwind_info = mono_cache_unwind_info (info->uw_info, info->uw_info_len);
 
        mono_jit_info_table_add (domain, ji);
 }
@@ -493,26 +494,38 @@ register_trampoline_jit_info (MonoDomain *domain, MonoTrampInfo *info)
  * Frees INFO.
  */
 void
-mono_tramp_info_register (MonoTrampInfo *info)
+mono_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
 {
        MonoTrampInfo *copy;
 
        if (!info)
                return;
 
+       if (!domain)
+               domain = mono_get_root_domain ();
+
        copy = g_new0 (MonoTrampInfo, 1);
        copy->code = info->code;
        copy->code_size = info->code_size;
        copy->name = g_strdup (info->name);
 
+       if (info->unwind_ops) {
+               copy->uw_info = mono_unwind_ops_encode (info->unwind_ops, &copy->uw_info_len);
+       } else {
+               /* Trampolines from aot have the unwind ops already encoded */
+               copy->uw_info = info->uw_info;
+               copy->uw_info_len = info->uw_info_len;
+       }
+
        mono_jit_lock ();
        tramp_infos = g_slist_prepend (tramp_infos, copy);
        mono_jit_unlock ();
 
        mono_save_trampoline_xdebug_info (info);
 
-       if (mono_get_root_domain ())
-               register_trampoline_jit_info (mono_get_root_domain (), copy);
+       /* Only register trampolines that have unwind infos */
+       if (mono_get_root_domain () && copy->uw_info)
+               register_trampoline_jit_info (domain, copy);
 
        if (mono_jit_map_is_enabled ())
                mono_emit_jit_tramp (info->code, info->code_size, info->name);
@@ -1199,9 +1212,6 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
        case MONO_PATCH_INFO_GC_NURSERY_START:
        case MONO_PATCH_INFO_JIT_TLS_ID:
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-       case MONO_PATCH_INFO_MONITOR_EXIT:
        case MONO_PATCH_INFO_GOT_OFFSET:
        case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
                return (ji->type << 8);
@@ -1589,15 +1599,6 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = mono_create_rgctx_lazy_fetch_trampoline (slot);
                break;
        }
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-               target = mono_create_monitor_enter_trampoline ();
-               break;
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-               target = mono_create_monitor_enter_v4_trampoline ();
-               break;
-       case MONO_PATCH_INFO_MONITOR_EXIT:
-               target = mono_create_monitor_exit_trampoline ();
-               break;
 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
        case MONO_PATCH_INFO_SEQ_POINT_INFO:
                if (!run_cctors)
@@ -2333,7 +2334,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
        MONO_SIG_HANDLER_INFO_TYPE *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));
+       ji = mono_jit_info_table_find_internal (mono_domain_get (), mono_arch_ip_from_context (ctx), TRUE, TRUE);
 
 #if defined(MONO_ARCH_HAVE_IS_INT_OVERFLOW)
        if (mono_arch_is_int_overflow (ctx, info))
@@ -2419,7 +2420,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
        }
 #endif
 
-       ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
+       ji = mono_jit_info_table_find_internal (mono_domain_get (), mono_arch_ip_from_context (ctx), TRUE, TRUE);
 
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
        if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, info, (guint8*)info->si_addr))
@@ -2599,8 +2600,10 @@ mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *met
        /* FIXME Support more cases */
        if (mono_aot_only) {
                char tramp_name [256];
+               const char *imt = load_imt_reg ? "_imt" : "";
+               int ind = (load_imt_reg ? (-offset) : offset) / SIZEOF_VOID_P;
 
-               sprintf (tramp_name, "delegate_virtual_invoke%s_%d", load_imt_reg ? "_imt" : "", offset / SIZEOF_VOID_P);
+               sprintf (tramp_name, "delegate_virtual_invoke%s_%d", imt, ind);
                cache [idx] = mono_aot_get_trampoline (tramp_name);
                g_assert (cache [idx]);
        } else {
@@ -2963,6 +2966,7 @@ mini_init (const char *filename, const char *runtime_version)
        ticallbacks.setup_async_callback = mono_setup_async_callback;
        ticallbacks.thread_state_init_from_sigctx = mono_thread_state_init_from_sigctx;
        ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle;
+       ticallbacks.thread_state_init = mono_thread_state_init;
 
        mono_counters_init ();
 
@@ -3592,6 +3596,17 @@ void mono_precompile_assemblies ()
        g_hash_table_destroy (assemblies);
 }
 
+/*
+ * Used by LLVM.
+ * Have to export this for AOT.
+ */
+void
+mono_personality (void)
+{
+       /* Not used */
+       g_assert_not_reached ();
+}
+
 #ifdef USE_JUMP_TABLES
 #define DEFAULT_JUMPTABLE_CHUNK_ELEMENTS 128
 
index 0b482454c2cf3df4b5cc8d780195e836e1fdeee1..657ee174d981764341c44fed9e5612b6304fc8df 100644 (file)
@@ -5708,7 +5708,7 @@ mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *cl
 /*------------------------------------------------------------------*/
 
 static gpointer
-get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *code_len, gboolean aot)
+get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
 {
        guint8 *code, *start;
 
@@ -5744,8 +5744,13 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
 
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
 
-       if (code_len)
-               *code_len = code - start;
+       if (has_target) {
+               *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
+       } else {
+               char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
+               *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
+               g_free (name);
+       }
 
        return start;
 }
@@ -5764,19 +5769,15 @@ GSList*
 mono_arch_get_delegate_invoke_impls (void)
 {
        GSList *res = NULL;
-       guint8 *code;
-       guint32 code_len;
+       MonoTrampInfo *info;
        int i;
-       char *tramp_name;
 
-       code = get_delegate_invoke_impl (TRUE, 0, &code_len, TRUE);
-       res = g_slist_prepend (res, mono_tramp_info_create ("delegate_invoke_impl_has_target", code, code_len, NULL, NULL));
+       get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
+       res = g_slist_prepend (res, info);
 
-       for (i = 0; i < MAX_ARCH_DELEGATE_PARAMS; ++i) {
-               code = get_delegate_invoke_impl (FALSE, i, &code_len, TRUE);
-               tramp_name = g_strdup_printf ("delegate_invoke_impl_target_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+       for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
+               get_delegate_invoke_impl (&info, FALSE, i, TRUE);
+               res = g_slist_prepend (res, info);
        }
 
        return res;
@@ -5807,10 +5808,13 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                if (cached)
                        return cached;
 
-               if (mono_aot_only)
+               if (mono_aot_only) {
                        start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
-               else
-                       start = get_delegate_invoke_impl (TRUE, 0, NULL, FALSE);
+               } else {
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
+                       mono_tramp_info_register (info, NULL);
+               }
 
                mono_memory_barrier ();
 
@@ -5835,7 +5839,9 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        start = mono_aot_get_trampoline (name);
                        g_free (name);
                } else {
-                       start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL, FALSE);
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
+                       mono_tramp_info_register (info, NULL);
                }
 
                mono_memory_barrier ();
@@ -6028,6 +6034,8 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
 
        g_assert (code - start <= size);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return (start);
 }
 
index 740ae80e1e35b25acd425a024e54e1ff0dca1199..1de03e2fd2af0df5e8b3b4cc2ac0665ab7b6c622 100644 (file)
@@ -63,8 +63,6 @@ typedef struct
 #define MONO_ARCH_HAVE_INVALIDATE_METHOD               1
 #define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT           1
 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK            1
-#define MONO_ARCH_MONITOR_OBJECT_REG                   s390_r2
-#define MONO_ARCH_LOCK_TAKEN_REG                       s390_r1
 
 #define S390_STACK_ALIGNMENT            8
 #define S390_FIRST_ARG_REG             s390_r2
index f5c0f5e89d10e3863b6f3a1112f117460673d036..5aa8d082007347d3e00681ef66511cd42582b899 100644 (file)
@@ -2352,6 +2352,9 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
 
        mono_stats.imt_thunks_size += (code - start) * 4;
        g_assert (code - start <= size);
+
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return start;
 }
 
index 72e8604c2acb36d3ec59a353ab31a9ccfc6fefa0..b8fc3337d75120dd783d9705cec484ec39015b3b 100644 (file)
@@ -340,7 +340,7 @@ mini_add_method_trampoline (MonoMethod *m, gpointer compiled_method, gboolean ad
                }
        }
 
-       if (ji)
+       if (ji && !ji->is_trampoline)
                jmethod = jinfo_get_method (ji);
        if (callee_gsharedvt && mini_is_gsharedvt_variable_signature (mono_method_signature (jmethod))) {
                MonoMethodSignature *sig, *gsig;
@@ -896,29 +896,6 @@ mono_rgctx_lazy_fetch_trampoline (mgreg_t *regs, guint8 *code, gpointer data, gu
                return mono_class_fill_runtime_generic_context (arg, index);
 }
 
-void
-mono_monitor_enter_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp)
-{
-       mono_monitor_enter (obj);
-}
-
-void
-mono_monitor_enter_v4_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp)
-{
-#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
-       char *lock_taken = (char*)regs [MONO_ARCH_MONITOR_LOCK_TAKEN_REG];
-       mono_monitor_enter_v4 (obj, lock_taken);
-#else
-       g_assert_not_reached ();
-#endif
-}
-
-void
-mono_monitor_exit_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp)
-{
-       mono_monitor_exit (obj);
-}
-
 /*
  * Precompute data to speed up mono_delegate_trampoline ().
  * METHOD might be NULL.
@@ -1171,7 +1148,7 @@ mono_create_handler_block_trampoline (void)
                gpointer tmp;
 
                tmp = mono_arch_create_handler_block_trampoline (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
                mono_memory_barrier ();
                code = tmp;
        }
@@ -1210,12 +1187,6 @@ mono_get_trampoline_func (MonoTrampolineType tramp_type)
        case MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING:
                return mono_generic_virtual_remoting_trampoline;
 #endif
-       case MONO_TRAMPOLINE_MONITOR_ENTER:
-               return mono_monitor_enter_trampoline;
-       case MONO_TRAMPOLINE_MONITOR_ENTER_V4:
-               return mono_monitor_enter_v4_trampoline;
-       case MONO_TRAMPOLINE_MONITOR_EXIT:
-               return mono_monitor_exit_trampoline;
        case MONO_TRAMPOLINE_VCALL:
                return mono_vcall_trampoline;
 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
@@ -1235,7 +1206,7 @@ create_trampoline_code (MonoTrampolineType tramp_type)
        guchar *code;
 
        code = mono_arch_create_generic_trampoline (tramp_type, &info, FALSE);
-       mono_tramp_info_register (info);
+       mono_tramp_info_register (info, NULL);
 
        return code;
 }
@@ -1260,9 +1231,6 @@ mono_trampolines_init (void)
 #ifndef DISABLE_REMOTING
        mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING] = create_trampoline_code (MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING);
 #endif
-       mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_ENTER] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER);
-       mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_ENTER_V4] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER_V4);
-       mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_EXIT] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_EXIT);
        mono_trampoline_code [MONO_TRAMPOLINE_VCALL] = create_trampoline_code (MONO_TRAMPOLINE_VCALL);
 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
        mono_trampoline_code [MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD] = create_trampoline_code (MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD);
@@ -1479,7 +1447,7 @@ mono_create_rgctx_lazy_fetch_trampoline (guint32 offset)
                ptr = mono_aot_get_lazy_fetch_trampoline (offset);
        } else {
                tramp = mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
                ptr = mono_create_ftnptr (mono_get_root_domain (), tramp);
        }
 
@@ -1502,95 +1470,6 @@ mono_create_rgctx_lazy_fetch_trampoline (guint32 offset)
 
        return ptr;
 }
-
-gpointer
-mono_create_monitor_enter_trampoline (void)
-{
-       static gpointer code;
-
-       if (mono_aot_only) {
-               if (!code)
-                       code = mono_aot_get_trampoline ("monitor_enter_trampoline");
-               return code;
-       }
-
-#ifdef MONO_ARCH_MONITOR_OBJECT_REG
-       mono_trampolines_lock ();
-
-       if (!code) {
-               MonoTrampInfo *info;
-
-               code = mono_arch_create_monitor_enter_trampoline (&info, FALSE, FALSE);
-               mono_tramp_info_register (info);
-       }
-
-       mono_trampolines_unlock ();
-#else
-       code = NULL;
-       g_assert_not_reached ();
-#endif
-
-       return code;
-}
-
-gpointer
-mono_create_monitor_enter_v4_trampoline (void)
-{
-       static gpointer code;
-
-       if (mono_aot_only) {
-               if (!code)
-                       code = mono_aot_get_trampoline ("monitor_enter_v4_trampoline");
-               return code;
-       }
-
-#if defined(MONO_ARCH_MONITOR_OBJECT_REG) && defined(MONO_ARCH_MONITOR_LOCK_TAKEN_REG)
-       mono_trampolines_lock ();
-
-       if (!code) {
-               MonoTrampInfo *info;
-
-               code = mono_arch_create_monitor_enter_trampoline (&info, TRUE, FALSE);
-               mono_tramp_info_register (info);
-       }
-
-       mono_trampolines_unlock ();
-#else
-       code = NULL;
-       g_assert_not_reached ();
-#endif
-
-       return code;
-}
-
-gpointer
-mono_create_monitor_exit_trampoline (void)
-{
-       static gpointer code;
-
-       if (mono_aot_only) {
-               if (!code)
-                       code = mono_aot_get_trampoline ("monitor_exit_trampoline");
-               return code;
-       }
-
-#ifdef MONO_ARCH_MONITOR_OBJECT_REG
-       mono_trampolines_lock ();
-
-       if (!code) {
-               MonoTrampInfo *info;
-
-               code = mono_arch_create_monitor_exit_trampoline (&info, FALSE);
-               mono_tramp_info_register (info);
-       }
-
-       mono_trampolines_unlock ();
-#else
-       code = NULL;
-       g_assert_not_reached ();
-#endif
-       return code;
-}
  
 #ifdef MONO_ARCH_LLVM_SUPPORTED
 /*
@@ -1641,9 +1520,6 @@ static const char*tramp_names [MONO_TRAMPOLINE_NUM] = {
        "delegate",
        "restore_stack_prot",
        "generic_virtual_remoting",
-       "monitor_enter",
-       "monitor_enter_v4",
-       "monitor_exit",
        "vcall",
        "handler_block_guard"
 };
@@ -1705,7 +1581,7 @@ mini_get_single_step_trampoline (void)
 #ifdef MONO_ARCH_HAVE_SDB_TRAMPOLINES
                        MonoTrampInfo *info;
                        tramp = mono_arch_create_sdb_trampoline (TRUE, &info, FALSE);
-                       mono_tramp_info_register (info);
+                       mono_tramp_info_register (info, NULL);
 #else
                        tramp = NULL;
                        g_assert_not_reached ();
@@ -1737,7 +1613,7 @@ mini_get_breakpoint_trampoline (void)
 #ifdef MONO_ARCH_HAVE_SDB_TRAMPOLINES
                        MonoTrampInfo *info;
                        tramp = mono_arch_create_sdb_trampoline (FALSE, &info, FALSE);
-                       mono_tramp_info_register (info);
+                       mono_tramp_info_register (info, NULL);
 #else
                        tramp = NULL;
                        g_assert_not_reached ();
index 657cc7708733634fb42208d8378dda25d6af5e53..ab690bf480797779f46c823999285c9b438a520c 100644 (file)
@@ -114,6 +114,8 @@ typedef struct {
 #define mono_add_unwind_op_same_value(op_list,code,buf,reg) do { (op_list) = g_slist_append ((op_list), mono_create_unwind_op ((code) - (buf), DW_CFA_same_value, (reg), 0)); } while (0)
 #define mono_add_unwind_op_offset(op_list,code,buf,reg,offset) do { (op_list) = g_slist_append ((op_list), mono_create_unwind_op ((code) - (buf), DW_CFA_offset, (reg), (offset))); } while (0)
 
+#define mono_free_unwind_info(op_list) do { GSList *l; for (l = op_list; l; l = l->next) g_free (l->data); g_slist_free (op_list); op_list = NULL; } while (0)
+
 /* Pointer Encoding in the .eh_frame */
 enum {
        DW_EH_PE_absptr = 0x00,
@@ -144,6 +146,9 @@ mono_unwind_get_dwarf_data_align (void);
 int
 mono_unwind_get_dwarf_pc_reg (void);
 
+guint8*
+mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enable_extensions);
+
 guint8*
 mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len);
 
index 4242c2b83e3a11eb4882ee94629da983c5233efa..ce89795c1a284f4f2197537070db25b9d426e26c 100644 (file)
@@ -45,6 +45,12 @@ static gboolean optimize_for_xen = TRUE;
 #endif
 #endif
 
+/* The single step trampoline */
+static gpointer ss_trampoline;
+
+/* The breakpoint trampoline */
+static gpointer bp_trampoline;
+
 /* This mutex protects architecture specific caches */
 #define mono_mini_arch_lock() mono_mutex_lock (&mini_arch_mutex)
 #define mono_mini_arch_unlock() mono_mutex_unlock (&mini_arch_mutex)
@@ -63,8 +69,7 @@ static mono_mutex_t mini_arch_mutex;
 
 #define X86_IS_CALLEE_SAVED_REG(reg) (((reg) == X86_EBX) || ((reg) == X86_EDI) || ((reg) == X86_ESI))
 
-MonoBreakpointInfo
-mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
+#define OP_SEQ_POINT_BP_OFFSET 7
 
 static guint8*
 emit_load_aotconst (guint8 *start, guint8 *code, MonoCompile *cfg, MonoJumpInfo **ji, int dreg, int tramp_type, gconstpointer target);
@@ -102,15 +107,6 @@ mono_arch_nacl_skip_nops (guint8 *code)
 
 #endif /* __native_client_codegen__ */
 
-/*
- * The code generated for sequence points reads from this location, which is
- * made read-only when single stepping is enabled.
- */
-static gpointer ss_trigger_page;
-
-/* Enabled breakpoints read from this trigger page */
-static gpointer bp_trigger_page;
-
 const char*
 mono_arch_regname (int reg)
 {
@@ -760,9 +756,7 @@ mono_arch_init (void)
 {
        mono_mutex_init_recursive (&mini_arch_mutex);
 
-       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
-       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
-       mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
+       bp_trampoline = mini_get_breakpoint_trampoline ();
 
        mono_aot_register_jit_icall ("mono_x86_throw_exception", mono_x86_throw_exception);
        mono_aot_register_jit_icall ("mono_x86_throw_corlib_exception", mono_x86_throw_corlib_exception);
@@ -777,10 +771,6 @@ mono_arch_init (void)
 void
 mono_arch_cleanup (void)
 {
-       if (ss_trigger_page)
-               mono_vfree (ss_trigger_page, mono_pagesize ());
-       if (bp_trigger_page)
-               mono_vfree (bp_trigger_page, mono_pagesize ());
        mono_mutex_destroy (&mini_arch_mutex);
 }
 
@@ -1217,6 +1207,18 @@ mono_arch_create_vars (MonoCompile *cfg)
                cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
        }
 
+       if (cfg->gen_sdb_seq_points) {
+               MonoInst *ins;
+
+               ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+               ins->flags |= MONO_INST_VOLATILE;
+               cfg->arch.ss_tramp_var = ins;
+
+               ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+               ins->flags |= MONO_INST_VOLATILE;
+               cfg->arch.bp_tramp_var = ins;
+       }
+
        if (cfg->method->save_lmf) {
                cfg->create_lmf_var = TRUE;
                cfg->lmf_ir = TRUE;
@@ -2773,22 +2775,53 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (cfg->compile_aot)
                                NOT_IMPLEMENTED;
 
+                       /* Have to use ecx as a temp reg since this can occur after OP_SETRET */
+
                        /* 
                         * Read from the single stepping trigger page. This will cause a
                         * SIGSEGV when single stepping is enabled.
                         * We do this _before_ the breakpoint, so single stepping after
                         * a breakpoint is hit will step to the next IL offset.
                         */
-                       if (ins->flags & MONO_INST_SINGLE_STEP_LOC)
-                               x86_alu_reg_mem (code, X86_CMP, X86_EAX, (guint32)ss_trigger_page);
+                       if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
+                               MonoInst *var = cfg->arch.ss_tramp_var;
+                               guint8 *br [1];
+
+                               g_assert (var);
+                               g_assert (var->opcode == OP_REGOFFSET);
+                               /* Load ss_tramp_var */
+                               /* This is equal to &ss_trampoline */
+                               x86_mov_reg_membase (code, X86_ECX, var->inst_basereg, var->inst_offset, sizeof (mgreg_t));
+                               x86_alu_membase_imm (code, X86_CMP, X86_ECX, 0, 0);
+                               br[0] = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE);
+                               x86_call_membase (code, X86_ECX, 0);
+                               x86_patch (br [0], code);
+                       }
+
+                       /*
+                        * Many parts of sdb depend on the ip after the single step trampoline call to be equal to the seq point offset.
+                        * This means we have to put the loading of bp_tramp_var after the offset.
+                        */
 
                        mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
 
+                       MonoInst *var = cfg->arch.bp_tramp_var;
+
+                       g_assert (var);
+                       g_assert (var->opcode == OP_REGOFFSET);
+                       /* Load the address of the bp trampoline */
+                       /* This needs to be constant size */
+                       guint8 *start = code;
+                       x86_mov_reg_membase (code, X86_ECX, var->inst_basereg, var->inst_offset, 4);
+                       if (code < start + OP_SEQ_POINT_BP_OFFSET) {
+                               int size = start + OP_SEQ_POINT_BP_OFFSET - code;
+                               x86_padding (code, size);
+                       }
                        /* 
                         * A placeholder for a possible breakpoint inserted by
                         * mono_arch_set_breakpoint ().
                         */
-                       for (i = 0; i < 6; ++i)
+                       for (i = 0; i < 2; ++i)
                                x86_nop (code);
                        /*
                         * Add an additional nop so skipping the bp doesn't cause the ip to point
@@ -5402,6 +5435,28 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
                code = mono_arch_instrument_prolog (cfg, mono_trace_enter_method, code, TRUE);
 
+       {
+               MonoInst *ins;
+
+               if (cfg->arch.ss_tramp_var) {
+                       /* Initialize ss_tramp_var */
+                       ins = cfg->arch.ss_tramp_var;
+                       g_assert (ins->opcode == OP_REGOFFSET);
+
+                       g_assert (!cfg->compile_aot);
+                       x86_mov_membase_imm (code, ins->inst_basereg, ins->inst_offset, (guint32)&ss_trampoline, 4);
+               }
+
+               if (cfg->arch.bp_tramp_var) {
+                       /* Initialize bp_tramp_var */
+                       ins = cfg->arch.bp_tramp_var;
+                       g_assert (ins->opcode == OP_REGOFFSET);
+
+                       g_assert (!cfg->compile_aot);
+                       x86_mov_membase_imm (code, ins->inst_basereg, ins->inst_offset, (guint32)&bp_trampoline, 4);
+               }
+       }
+
        /* load arguments allocated to register from the stack */
        sig = mono_method_signature (method);
        pos = 0;
@@ -5762,6 +5817,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        int i;
        int size = 0;
        guint8 *code, *start;
+       GSList *unwind_ops;
 
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
@@ -5798,6 +5854,9 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                code = mono_domain_code_reserve (domain, size);
 #endif
        start = code;
+
+       unwind_ops = mono_arch_get_cie_program ();
+
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
                item->code_target = code;
@@ -5884,6 +5943,8 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        nacl_domain_code_validate (domain, &start, size, &code);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
+
        return start;
 }
 
@@ -6075,10 +6136,13 @@ mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
 #define MAX_ARCH_DELEGATE_PARAMS 10
 
 static gpointer
-get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *code_len)
+get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count)
 {
        guint8 *code, *start;
        int code_reserve = 64;
+       GSList *unwind_ops;
+
+       unwind_ops = mono_arch_get_cie_program ();
 
        /*
         * The stack contains:
@@ -6139,8 +6203,13 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
 
        nacl_global_codeman_validate (&start, code_reserve, &code);
 
-       if (code_len)
-               *code_len = code - start;
+       if (has_target) {
+               *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, unwind_ops);
+       } else {
+               char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
+               *info = mono_tramp_info_create (name, start, code - start, NULL, unwind_ops);
+               g_free (name);
+       }
 
        if (mono_jit_map_is_enabled ()) {
                char *buff;
@@ -6160,10 +6229,15 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
 #define MAX_VIRTUAL_DELEGATE_OFFSET 32
 
 static gpointer
-get_delegate_virtual_invoke_impl (gboolean load_imt_reg, int offset, guint32 *code_size)
+get_delegate_virtual_invoke_impl (MonoTrampInfo **info, gboolean load_imt_reg, int offset)
 {
        guint8 *code, *start;
        int size = 24;
+       char *tramp_name;
+       GSList *unwind_ops;
+
+       if (offset / (int)sizeof (gpointer) > MAX_VIRTUAL_DELEGATE_OFFSET)
+               return NULL;
 
        /*
         * The stack contains:
@@ -6172,6 +6246,8 @@ get_delegate_virtual_invoke_impl (gboolean load_imt_reg, int offset, guint32 *co
         */
        start = code = mono_global_codeman_reserve (size);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        /* Replace the this argument with the target */
        x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
        x86_mov_reg_membase (code, X86_ECX, X86_EAX, MONO_STRUCT_OFFSET (MonoDelegate, target), 4);
@@ -6187,8 +6263,13 @@ get_delegate_virtual_invoke_impl (gboolean load_imt_reg, int offset, guint32 *co
        x86_jump_membase (code, X86_EAX, offset);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
 
-       if (code_size)
-               *code_size = code - start;
+       if (load_imt_reg)
+               tramp_name = g_strdup_printf ("delegate_virtual_invoke_imt_%d", - offset / sizeof (gpointer));
+       else
+               tramp_name = g_strdup_printf ("delegate_virtual_invoke_%d", offset / sizeof (gpointer));
+       *info = mono_tramp_info_create (tramp_name, start, code - start, NULL, unwind_ops);
+       g_free (tramp_name);
+
 
        return start;
 }
@@ -6197,31 +6278,23 @@ GSList*
 mono_arch_get_delegate_invoke_impls (void)
 {
        GSList *res = NULL;
-       guint8 *code;
-       guint32 code_len;
+       MonoTrampInfo *info;
        int i;
-       char *tramp_name;
 
-       code = get_delegate_invoke_impl (TRUE, 0, &code_len);
-       res = g_slist_prepend (res, mono_tramp_info_create ("delegate_invoke_impl_has_target", code, code_len, NULL, NULL));
+       get_delegate_invoke_impl (&info, TRUE, 0);
+       res = g_slist_prepend (res, info);
 
-       for (i = 0; i < MAX_ARCH_DELEGATE_PARAMS; ++i) {
-               code = get_delegate_invoke_impl (FALSE, i, &code_len);
-               tramp_name = g_strdup_printf ("delegate_invoke_impl_target_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+       for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
+               get_delegate_invoke_impl (&info, FALSE, i);
+               res = g_slist_prepend (res, info);
        }
 
-       for (i = 0; i < MAX_VIRTUAL_DELEGATE_OFFSET; ++i) {
-               code = get_delegate_virtual_invoke_impl (TRUE, i * SIZEOF_VOID_P, &code_len);
-               tramp_name = g_strdup_printf ("delegate_virtual_invoke_imt_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+       for (i = 0; i <= MAX_VIRTUAL_DELEGATE_OFFSET; ++i) {
+               get_delegate_virtual_invoke_impl (&info, TRUE, - i * SIZEOF_VOID_P);
+               res = g_slist_prepend (res, info);
 
-               code = get_delegate_virtual_invoke_impl (FALSE, i * SIZEOF_VOID_P, &code_len);
-               tramp_name = g_strdup_printf ("delegate_virtual_invoke_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+               get_delegate_virtual_invoke_impl (&info, FALSE, i * SIZEOF_VOID_P);
+               res = g_slist_prepend (res, info);
        }
 
        return res;
@@ -6250,10 +6323,13 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                if (cached)
                        return cached;
 
-               if (mono_aot_only)
+               if (mono_aot_only) {
                        start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
-               else
-                       start = get_delegate_invoke_impl (TRUE, 0, NULL);
+               } else {
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, TRUE, 0);
+                       mono_tramp_info_register (info, NULL);
+               }
 
                mono_memory_barrier ();
 
@@ -6275,7 +6351,9 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        start = mono_aot_get_trampoline (name);
                        g_free (name);
                } else {
-                       start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL);
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, FALSE, sig->param_count);
+                       mono_tramp_info_register (info, NULL);
                }
 
                mono_memory_barrier ();
@@ -6289,7 +6367,13 @@ 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)
 {
-       return get_delegate_virtual_invoke_impl (load_imt_reg, offset, NULL);
+       MonoTrampInfo *info;
+       gpointer code;
+
+       code = get_delegate_virtual_invoke_impl (&info, load_imt_reg, offset);
+       if (code)
+               mono_tramp_info_register (info, NULL);
+       return code;
 }
 
 mgreg_t
@@ -6623,15 +6707,10 @@ mono_arch_get_trampolines (gboolean aot)
 void
 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
 {
-       guint8 *code = ip;
+       guint8 *code = ip + OP_SEQ_POINT_BP_OFFSET;
 
-       /* 
-        * In production, we will use int3 (has to fix the size in the md 
-        * file). But that could confuse gdb, so during development, we emit a SIGSEGV
-        * instead.
-        */
        g_assert (code [0] == 0x90);
-       x86_alu_reg_mem (code, X86_CMP, X86_EAX, (guint32)bp_trigger_page);
+       x86_call_membase (code, X86_ECX, 0);
 }
 
 /*
@@ -6642,10 +6721,10 @@ mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
 void
 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
 {
-       guint8 *code = ip;
+       guint8 *code = ip + OP_SEQ_POINT_BP_OFFSET;
        int i;
 
-       for (i = 0; i < 6; ++i)
+       for (i = 0; i < 2; ++i)
                x86_nop (code);
 }
        
@@ -6657,7 +6736,7 @@ mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
 void
 mono_arch_start_single_stepping (void)
 {
-       mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
+       ss_trampoline = mini_get_single_step_trampoline ();
 }
        
 /*
@@ -6668,7 +6747,7 @@ mono_arch_start_single_stepping (void)
 void
 mono_arch_stop_single_stepping (void)
 {
-       mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
+       ss_trampoline = NULL;
 }
 
 /*
@@ -6680,43 +6759,18 @@ mono_arch_stop_single_stepping (void)
 gboolean
 mono_arch_is_single_step_event (void *info, void *sigctx)
 {
-#ifdef TARGET_WIN32
-       EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; /* Sometimes the address is off by 4 */
-
-       if (((gpointer)einfo->ExceptionInformation[1] >= ss_trigger_page && (guint8*)einfo->ExceptionInformation[1] <= (guint8*)ss_trigger_page + 128))
-               return TRUE;
-       else
-               return FALSE;
-#else
-       siginfo_t* sinfo = (siginfo_t*) info;
-       /* Sometimes the address is off by 4 */
-       if (sinfo->si_signo == DBG_SIGNAL && (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128))
-               return TRUE;
-       else
-               return FALSE;
-#endif
+       /* We use soft breakpoints */
+       return FALSE;
 }
 
 gboolean
 mono_arch_is_breakpoint_event (void *info, void *sigctx)
 {
-#ifdef TARGET_WIN32
-       EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; /* Sometimes the address is off by 4 */
-       if (((gpointer)einfo->ExceptionInformation[1] >= bp_trigger_page && (guint8*)einfo->ExceptionInformation[1] <= (guint8*)bp_trigger_page + 128))
-               return TRUE;
-       else
-               return FALSE;
-#else
-       siginfo_t* sinfo = (siginfo_t*)info;
-       /* Sometimes the address is off by 4 */
-       if (sinfo->si_signo == DBG_SIGNAL && (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128))
-               return TRUE;
-       else
-               return FALSE;
-#endif
+       /* We use soft breakpoints */
+       return FALSE;
 }
 
-#define BREAKPOINT_SIZE 6
+#define BREAKPOINT_SIZE 2
 
 /*
  * mono_arch_skip_breakpoint:
@@ -6726,7 +6780,7 @@ mono_arch_is_breakpoint_event (void *info, void *sigctx)
 void
 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
 {
-       MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
+       g_assert_not_reached ();
 }
 
 /*
@@ -6737,7 +6791,7 @@ mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
 void
 mono_arch_skip_single_step (MonoContext *ctx)
 {
-       MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 6);
+       g_assert_not_reached ();
 }
 
 /*
index 149cbd1198f99408ec2ba91b878e367fdccd3783..0547b2c807eaf15c14fb52004f094f87c1073965 100644 (file)
@@ -165,6 +165,8 @@ typedef struct {
        gboolean need_stack_frame_inited;
        gboolean need_stack_frame;
        int sp_fp_offset, param_area_size;
+       gpointer ss_tramp_var;
+       gpointer bp_tramp_var;
 } MonoCompileArch;
 
 #define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->eax = (gsize)exc; } while (0)
@@ -214,10 +216,6 @@ typedef struct {
 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
 #define MONO_ARCH_HAVE_LIVERANGE_OPS 1
 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
-#if defined(__linux__) || defined (__APPLE__)
-#define MONO_ARCH_MONITOR_OBJECT_REG X86_EAX
-#define MONO_ARCH_MONITOR_LOCK_TAKEN_REG X86_EDX
-#endif
 #if !defined(__native_client_codegen__)
 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
 #endif
@@ -239,9 +237,7 @@ typedef struct {
 #define MONO_ARCH_HAVE_LLVM_IMT_TRAMPOLINE 1
 #define MONO_ARCH_LLVM_SUPPORTED 1
 
-#if defined(MONO_ARCH_USE_SIGACTION) || defined(TARGET_WIN32)
 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
-#endif
 
 #define MONO_ARCH_HAVE_EXCEPTIONS_INIT 1
 #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1
@@ -256,6 +252,7 @@ typedef struct {
 #define MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET 1
 #define MONO_ARCH_HAVE_TLS_GET_REG 1
 #define MONO_ARCH_HAVE_DUMMY_INIT 1
+#define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1
 #define MONO_ARCH_HAVE_PATCH_CODE_NEW 1
 
 /* Used for optimization, not complete */
@@ -271,13 +268,6 @@ typedef struct {
                        MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); \
        } while (0)
 
-typedef struct {
-       guint8 *address;
-       guint8 saved_byte;
-} MonoBreakpointInfo;
-
-extern MonoBreakpointInfo mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
-
 /* Return value marshalling for calls between gsharedvt and normal code */
 typedef enum {
        GSHAREDVT_RET_NONE = 0,
index fd7d7c852be4a7545a5c22dfbe9c002f65a03939..42e9290597dd295957eb7d2c3e794ad944f20a68 100644 (file)
@@ -3098,6 +3098,23 @@ static void
 mono_insert_safepoints (MonoCompile *cfg)
 {
        MonoBasicBlock *bb;
+       if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+               WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method);
+#if defined(__native_client__) || defined(__native_client_codegen__)
+               gpointer poll_func = &mono_nacl_gc;
+#elif defined(USE_COOP_GC)
+               gpointer poll_func = &mono_threads_state_poll;
+#else
+               gpointer poll_func = NULL;
+#endif
+
+               if (info && info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER && info->d.icall.func == poll_func) {
+                       if (cfg->verbose_level > 1)
+                               printf ("SKIPPING SAFEPOINTS for the polling function icall\n");
+                       return;
+               }
+       }
+
 
        if (cfg->verbose_level > 1)
                printf ("INSERTING SAFEPOINTS\n");
@@ -3569,6 +3586,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        if (!COMPILE_LLVM (cfg))
                mono_if_conversion (cfg);
 
+       MONO_SUSPEND_CHECK ();
+
        /* Depth-first ordering on basic blocks */
        cfg->bblocks = mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * (cfg->num_bblocks + 1));
 
index 386f80c7e1ac5ce5fdd44f32cf8021b0c0b53644..8d4ec61cec7c20b2e343d448ffa8dd2a8e9bad71 100644 (file)
 #endif
 
 /* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION 120
+#define MONO_AOT_FILE_VERSION 121
 
 //TODO: This is x86/amd64 specific.
 #define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))
@@ -1326,9 +1326,6 @@ typedef enum {
        MONO_TRAMPOLINE_DELEGATE,
        MONO_TRAMPOLINE_RESTORE_STACK_PROT,
        MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
-       MONO_TRAMPOLINE_MONITOR_ENTER,
-       MONO_TRAMPOLINE_MONITOR_ENTER_V4,
-       MONO_TRAMPOLINE_MONITOR_EXIT,
        MONO_TRAMPOLINE_VCALL,
        MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD,
        MONO_TRAMPOLINE_NUM
@@ -1337,17 +1334,11 @@ typedef enum {
 /* These trampolines return normally to their caller */
 #define MONO_TRAMPOLINE_TYPE_MUST_RETURN(t)            \
        ((t) == MONO_TRAMPOLINE_RESTORE_STACK_PROT ||   \
-        (t) == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH ||     \
-        (t) == MONO_TRAMPOLINE_MONITOR_ENTER ||        \
-        (t) == MONO_TRAMPOLINE_MONITOR_ENTER_V4 ||     \
-        (t) == MONO_TRAMPOLINE_MONITOR_EXIT)
+        (t) == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH)
 
 /* These trampolines receive an argument directly in a register */
 #define MONO_TRAMPOLINE_TYPE_HAS_ARG(t)                \
-       ((t) == MONO_TRAMPOLINE_MONITOR_ENTER ||                \
-        (t) == MONO_TRAMPOLINE_MONITOR_ENTER_V4 ||             \
-        (t) == MONO_TRAMPOLINE_MONITOR_EXIT ||                 \
-        (t) == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD)
+       ((t) == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD)
 
 /* optimization flags */
 #define OPTFLAG(id,shift,name,descr) MONO_OPT_ ## id = 1 << shift,
@@ -2438,7 +2429,7 @@ void              mono_emit_unwind_op (MonoCompile *cfg, int when,
                                                                           int val);
 MonoTrampInfo*    mono_tramp_info_create (const char *name, guint8 *code, guint32 code_size, MonoJumpInfo *ji, GSList *unwind_ops);
 void              mono_tramp_info_free (MonoTrampInfo *info);
-void              mono_tramp_info_register (MonoTrampInfo *info);
+void              mono_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain);
 int               mini_exception_id_by_name (const char *name);
 gboolean          mini_type_is_hfa (MonoType *t, int *out_nfields, int *out_esize) MONO_LLVM_INTERNAL;
 
@@ -2647,6 +2638,7 @@ void     mono_walk_stack_with_ctx               (MonoJitStackWalk func, MonoCont
 void     mono_walk_stack_with_state             (MonoJitStackWalk func, MonoThreadUnwindState *state, MonoUnwindOptions unwind_options, void *user_data);
 void     mono_walk_stack                        (MonoJitStackWalk func, MonoUnwindOptions options, void *user_data);
 gboolean mono_thread_state_init_from_sigctx     (MonoThreadUnwindState *ctx, void *sigctx);
+void     mono_thread_state_init                 (MonoThreadUnwindState *ctx);
 gboolean mono_thread_state_init_from_current    (MonoThreadUnwindState *ctx);
 gboolean mono_thread_state_init_from_monoctx    (MonoThreadUnwindState *ctx, MonoContext *mctx);
 
index 28e7644d29cf3ab2f77cb4d1acd16e612f454dc2..cdd2117aceacf51710bc8067e646a91657e0144c 100644 (file)
@@ -20,7 +20,7 @@ internal_init (void)
        if (keepalive_stacks)
                return;
        MONO_GC_REGISTER_ROOT_PINNING (keepalive_stacks);
-       keepalive_stacks = mono_g_hash_table_new (NULL, NULL);
+       keepalive_stacks = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_CONSERVATIVE_GC);
 }
 
 static void*
@@ -69,7 +69,7 @@ continuation_mark_frame (MonoContinuation *cont)
                ctx = new_ctx;
                if (endloop)
                        break;
-               if (strcmp (jinfo_get_method (ji)->name, "Mark") == 0)
+               if (!ji->is_trampoline && strcmp (jinfo_get_method (ji)->name, "Mark") == 0)
                        endloop = TRUE;
        } while (1);
 
index e40510a7563d895c0a6cafcbf33da5df140dc4a6..dc169f04d76941f232c6e3266bdbbc5d132588ea 100644 (file)
@@ -18,7 +18,6 @@
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/mono-debug-debugger.h>
-#include <mono/metadata/monitor.h>
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/gc-internal.h>
 #include <mono/arch/amd64/amd64-codegen.h>
@@ -51,6 +50,7 @@ gpointer
 mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
 {
        guint8 *code, *start;
+       GSList *unwind_ops;
        int this_reg, size = NACL_SIZE (20, 32);
 
        MonoDomain *domain = mono_domain_get ();
@@ -59,6 +59,8 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
 
        start = code = mono_domain_code_reserve (domain, size);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        amd64_alu_reg_imm (code, X86_ADD, this_reg, sizeof (MonoObject));
        /* FIXME: Optimize this */
        amd64_mov_reg_imm (code, AMD64_RAX, addr);
@@ -70,6 +72,8 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
        mono_arch_flush_icache (start, code - start);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
+
        return start;
 }
 
@@ -82,6 +86,7 @@ gpointer
 mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericContext *mrgctx, gpointer addr)
 {
        guint8 *code, *start;
+       GSList *unwind_ops;
        int buf_len;
 
        MonoDomain *domain = mono_domain_get ();
@@ -98,6 +103,8 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo
 
        start = code = mono_domain_code_reserve (domain, buf_len);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        amd64_mov_reg_imm (code, MONO_ARCH_RGCTX_REG, mrgctx);
        amd64_jump_code (code, addr);
        g_assert ((code - start) < buf_len);
@@ -106,6 +113,8 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo
        mono_arch_flush_icache (start, code - start);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
+
        return start;
 }
 
@@ -339,13 +348,12 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        offset += sizeof (MonoLMFTramp);
        lmf_offset = -offset;
 
-       framesize = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
+#ifdef TARGET_WIN32
+       /* Reserve space where the callee can save the argument registers */
+       offset += 4 * sizeof (mgreg_t);
+#endif
 
-       orig_rsp_to_rbp_offset = 0;
-       r11_save_code = code;
-       /* Reserve space for the mov_membase_reg to save R11 */
-       code += 5;
-       after_r11_save_code = code;
+       framesize = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
 
        // CFA = sp + 16 (the trampoline address is on the stack)
        cfa_offset = 16;
@@ -353,6 +361,12 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        // IP saved at CFA - 8
        mono_add_unwind_op_offset (unwind_ops, code, buf, AMD64_RIP, -8);
 
+       orig_rsp_to_rbp_offset = 0;
+       r11_save_code = code;
+       /* Reserve space for the mov_membase_reg to save R11 */
+       code += 5;
+       after_r11_save_code = code;
+
        /* Pop the return address off the stack */
        amd64_pop_reg (code, AMD64_R11);
        orig_rsp_to_rbp_offset += sizeof(mgreg_t);
@@ -440,10 +454,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        //amd64_breakpoint (code);
 #endif
 
-       if (tramp_type != MONO_TRAMPOLINE_MONITOR_ENTER &&
-               tramp_type != MONO_TRAMPOLINE_MONITOR_ENTER_V4 &&
-               tramp_type != MONO_TRAMPOLINE_MONITOR_EXIT &&
-               tramp_type != MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD) {
+       if (tramp_type != MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD) {
                /* Obtain the trampoline argument which is encoded in the instruction stream */
                if (aot) {
                        /* Load the GOT offset */
@@ -590,6 +601,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 
        /* Restore stack */
        amd64_leave (code);
+       cfa_offset -= sizeof (mgreg_t);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, AMD64_RSP, cfa_offset);
+
 
        if (MONO_TRAMPOLINE_TYPE_MUST_RETURN (tramp_type)) {
                /* Load result */
@@ -697,7 +711,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
        int i;
        gboolean mrgctx;
        MonoJumpInfo *ji = NULL;
-       GSList *unwind_ops = NULL;
+       GSList *unwind_ops;
 
        mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
        index = MONO_RGCTX_SLOT_INDEX (slot);
@@ -786,317 +800,6 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
        return buf;
 }
 
-#ifdef MONO_ARCH_MONITOR_OBJECT_REG
-
-gpointer
-mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot)
-{
-       guint8 *tramp;
-       guint8 *code, *buf;
-       guint8 *jump_obj_null, *jump_sync_null, *jump_cmpxchg_failed, *jump_other_owner, *jump_tid, *jump_sync_thin_hash = NULL;
-       guint8 *jump_lock_taken_true = NULL;
-       int tramp_size;
-       int status_offset, nest_offset;
-       MonoJumpInfo *ji = NULL;
-       GSList *unwind_ops = NULL;
-       int obj_reg = MONO_AMD64_ARG_REG1;
-       int lock_taken_reg = MONO_AMD64_ARG_REG2;
-       int sync_reg = MONO_AMD64_ARG_REG3;
-       int tid_reg = MONO_AMD64_ARG_REG4;
-       int status_reg = AMD64_RAX;
-
-       g_assert (MONO_ARCH_MONITOR_OBJECT_REG == obj_reg);
-#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
-       g_assert (MONO_ARCH_MONITOR_LOCK_TAKEN_REG == lock_taken_reg);
-#else
-       g_assert (!is_v4);
-#endif
-
-       mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset);
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32));
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (nest_offset) == sizeof (guint32));
-       status_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (status_offset);
-       nest_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (nest_offset);
-
-       tramp_size = 128;
-
-       code = buf = mono_global_codeman_reserve (tramp_size);
-
-       unwind_ops = mono_arch_get_cie_program ();
-
-       if (!aot && mono_thread_get_tls_offset () != -1) {
-               /* MonoObject* obj is in obj_reg */
-               /* is obj null? */
-               amd64_test_reg_reg (code, obj_reg, obj_reg);
-               /* if yes, jump to actual trampoline */
-               jump_obj_null = code;
-               amd64_branch8 (code, X86_CC_Z, -1, 1);
-
-               if (is_v4) {
-                       amd64_test_membase_imm (code, lock_taken_reg, 0, 1);
-                       /* if *lock_taken is 1, jump to actual trampoline */
-                       jump_lock_taken_true = code;
-                       x86_branch8 (code, X86_CC_NZ, -1, 1);
-               }
-
-               /* load obj->synchronization to sync_reg */
-               amd64_mov_reg_membase (code, sync_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, synchronisation), 8);
-
-               if (mono_gc_is_moving ()) {
-                       /*if bit zero is set it's a thin hash*/
-                       /*FIXME use testb encoding*/
-                       amd64_test_reg_imm (code, sync_reg, 0x01);
-                       jump_sync_thin_hash = code;
-                       amd64_branch8 (code, X86_CC_NE, -1, 1);
-
-                       /*clear bits used by the gc*/
-                       amd64_alu_reg_imm (code, X86_AND, sync_reg, ~0x3);
-               }
-
-               /* is synchronization null? */
-               amd64_test_reg_reg (code, sync_reg, sync_reg);
-               /* if yes, jump to actual trampoline */
-               jump_sync_null = code;
-               amd64_branch8 (code, X86_CC_Z, -1, 1);
-
-               /* load MonoInternalThread* into tid_reg */
-               code = mono_amd64_emit_tls_get (code, tid_reg, mono_thread_get_tls_offset ());
-               /* load TID into tid_reg */
-               amd64_mov_reg_membase (code, tid_reg, tid_reg, MONO_STRUCT_OFFSET (MonoInternalThread, small_id), 4);
-
-               /* is synchronization->owner free */
-               amd64_mov_reg_membase (code, status_reg, sync_reg, status_offset, 4);
-               amd64_test_reg_imm_size (code, status_reg, OWNER_MASK, 4);
-               /* if not, jump to next case */
-               jump_tid = code;
-               amd64_branch8 (code, X86_CC_NZ, -1, 1);
-
-               /* if yes, try a compare-exchange with the TID */
-               g_assert (tid_reg != X86_EAX);
-               /* Form new status in tid_reg */
-               amd64_alu_reg_reg_size (code, X86_OR, tid_reg, status_reg, 4);
-               /* compare and exchange */
-               amd64_prefix (code, X86_LOCK_PREFIX);
-               amd64_cmpxchg_membase_reg_size (code, sync_reg, status_offset, tid_reg, 4);
-               /* if not successful, jump to actual trampoline */
-               jump_cmpxchg_failed = code;
-               amd64_branch8 (code, X86_CC_NZ, -1, 1);
-               /* if successful, return */
-               if (is_v4)
-                       amd64_mov_membase_imm (code, lock_taken_reg, 0, 1, 1);
-               amd64_ret (code);
-
-               /* next case: synchronization->owner is not null */
-               x86_patch (jump_tid, code);
-               /* is synchronization->owner == TID? */
-               amd64_alu_reg_imm_size (code, X86_AND, status_reg, OWNER_MASK, 4);
-               amd64_alu_reg_reg_size (code, X86_CMP, status_reg, tid_reg, 4);
-               /* if not, jump to actual trampoline */
-               jump_other_owner = code;
-               amd64_branch8 (code, X86_CC_NZ, -1, 1);
-               /* if yes, increment nest */
-               amd64_inc_membase_size (code, sync_reg, nest_offset, 4);
-               /* return */
-               if (is_v4)
-                       amd64_mov_membase_imm (code, lock_taken_reg, 0, 1, 1);
-               amd64_ret (code);
-
-               x86_patch (jump_obj_null, code);
-               if (jump_sync_thin_hash)
-                       x86_patch (jump_sync_thin_hash, code);
-               x86_patch (jump_sync_null, code);
-               x86_patch (jump_cmpxchg_failed, code);
-               x86_patch (jump_other_owner, code);
-               if (is_v4)
-                       x86_patch (jump_lock_taken_true, code);
-       }
-
-       /* jump to the actual trampoline */
-       if (MONO_AMD64_ARG_REG1 != obj_reg)
-               amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, obj_reg, sizeof (mgreg_t));
-
-       if (aot) {
-               if (is_v4)
-                       code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "specific_trampoline_monitor_enter_v4");
-               else
-                       code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "specific_trampoline_monitor_enter");
-               amd64_jump_reg (code, AMD64_R11);
-       } else {
-               if (is_v4)
-                       tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER_V4, mono_get_root_domain (), NULL);
-               else
-                       tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER, mono_get_root_domain (), NULL);
-
-               /* jump to the actual trampoline */
-               amd64_jump_code (code, tramp);
-       }
-
-       nacl_global_codeman_validate (&buf, tramp_size, &code);
-
-       mono_arch_flush_icache (code, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_MONITOR, NULL);
-       g_assert (code - buf <= tramp_size);
-
-       if (is_v4)
-               *info = mono_tramp_info_create ("monitor_enter_v4_trampoline", buf, code - buf, ji, unwind_ops);
-       else
-               *info = mono_tramp_info_create ("monitor_enter_trampoline", buf, code - buf, ji, unwind_ops);
-
-       return buf;
-}
-
-gpointer
-mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot)
-{
-       guint8 *tramp;
-       guint8 *code, *buf;
-       guint8 *jump_obj_null, *jump_have_waiters, *jump_sync_null, *jump_not_owned, *jump_cmpxchg_failed;
-       guint8 *jump_next, *jump_sync_thin_hash = NULL;
-       int tramp_size;
-       int status_offset, nest_offset;
-       MonoJumpInfo *ji = NULL;
-       GSList *unwind_ops = NULL;
-       int obj_reg = MONO_AMD64_ARG_REG1;
-       int sync_reg = MONO_AMD64_ARG_REG2;
-       int status_reg = MONO_AMD64_ARG_REG3;
-
-       g_assert (obj_reg == MONO_ARCH_MONITOR_OBJECT_REG);
-
-       mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset);
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32));
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (nest_offset) == sizeof (guint32));
-       status_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (status_offset);
-       nest_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (nest_offset);
-
-       tramp_size = 112;
-
-       code = buf = mono_global_codeman_reserve (tramp_size);
-
-       unwind_ops = mono_arch_get_cie_program ();
-
-       if (!aot && mono_thread_get_tls_offset () != -1) {
-               /* MonoObject* obj is in obj_reg */
-               /* is obj null? */
-               amd64_test_reg_reg (code, obj_reg, obj_reg);
-               /* if yes, jump to actual trampoline */
-               jump_obj_null = code;
-               amd64_branch8 (code, X86_CC_Z, -1, 1);
-
-               /* load obj->synchronization to RCX */
-               amd64_mov_reg_membase (code, sync_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, synchronisation), 8);
-
-               if (mono_gc_is_moving ()) {
-                       /*if bit zero is set it's a thin hash*/
-                       /*FIXME use testb encoding*/
-                       amd64_test_reg_imm (code, sync_reg, 0x01);
-                       jump_sync_thin_hash = code;
-                       amd64_branch8 (code, X86_CC_NE, -1, 1);
-
-                       /*clear bits used by the gc*/
-                       amd64_alu_reg_imm (code, X86_AND, sync_reg, ~0x3);
-               }
-
-               /* is synchronization null? */
-               amd64_test_reg_reg (code, sync_reg, sync_reg);
-               /* if yes, jump to actual trampoline */
-               jump_sync_null = code;
-               amd64_branch8 (code, X86_CC_Z, -1, 1);
-
-               /* next case: synchronization is not null */
-               /* load MonoInternalThread* into RAX */
-               code = mono_amd64_emit_tls_get (code, AMD64_RAX, mono_thread_get_tls_offset ());
-               /* load TID into RAX */
-               amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, MONO_STRUCT_OFFSET (MonoInternalThread, small_id), 4);
-               /* is synchronization->owner == TID */
-               amd64_mov_reg_membase (code, status_reg, sync_reg, status_offset, 4);
-               amd64_alu_reg_reg_size (code, X86_XOR, AMD64_RAX, status_reg, 4);
-               amd64_test_reg_imm_size (code, AMD64_RAX, OWNER_MASK, 4);
-
-               /* if no, jump to actual trampoline */
-               jump_not_owned = code;
-               amd64_branch8 (code, X86_CC_NZ, -1, 1);
-
-               /* next case: synchronization->owner == TID */
-               /* is synchronization->nest == 1 */
-               amd64_alu_membase_imm_size (code, X86_CMP, sync_reg, nest_offset, 1, 4);
-               /* if not, jump to next case */
-               jump_next = code;
-               amd64_branch8 (code, X86_CC_NZ, -1, 1);
-               /* if yes, is synchronization->entry_count greater than zero */
-               amd64_test_reg_imm_size (code, status_reg, ENTRY_COUNT_WAITERS, 4);
-               /* if not, jump to actual trampoline */
-               jump_have_waiters = code;
-               amd64_branch8 (code, X86_CC_NZ, -1 , 1);
-               /* if yes, try to set synchronization->owner to null and return */
-               g_assert (status_reg != AMD64_RAX);
-               /* old status in RAX */
-               amd64_mov_reg_reg (code, AMD64_RAX, status_reg, 4);
-               /* form new status */
-               amd64_alu_reg_imm_size (code, X86_AND, status_reg, ENTRY_COUNT_MASK, 4);
-               /* compare and exchange */
-               amd64_prefix (code, X86_LOCK_PREFIX);
-               amd64_cmpxchg_membase_reg_size (code, sync_reg, status_offset, status_reg, 4);
-               /* if not successful, jump to actual trampoline */
-               jump_cmpxchg_failed = code;
-               amd64_branch8 (code, X86_CC_NZ, -1, 1);
-               amd64_ret (code);
-
-               /* next case: synchronization->nest is not 1 */
-               x86_patch (jump_next, code);
-               /* decrease synchronization->nest and return */
-               amd64_dec_membase_size (code, sync_reg, nest_offset, 4);
-               amd64_ret (code);
-
-               if (jump_sync_thin_hash)
-                       x86_patch (jump_sync_thin_hash, code);
-               x86_patch (jump_obj_null, code);
-               x86_patch (jump_have_waiters, code);
-               x86_patch (jump_not_owned, code);
-               x86_patch (jump_cmpxchg_failed, code);
-               x86_patch (jump_sync_null, code);
-       }
-
-       /* jump to the actual trampoline */
-       if (MONO_AMD64_ARG_REG1 != obj_reg)
-               amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, obj_reg, sizeof (mgreg_t));
-
-       if (aot) {
-               code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "specific_trampoline_monitor_exit");
-               amd64_jump_reg (code, AMD64_R11);
-       } else {
-               tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_EXIT, mono_get_root_domain (), NULL);
-               amd64_jump_code (code, tramp);
-       }
-
-       nacl_global_codeman_validate (&buf, tramp_size, &code);
-
-       mono_arch_flush_icache (code, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_MONITOR, NULL);
-       g_assert (code - buf <= tramp_size);
-
-       *info = mono_tramp_info_create ("monitor_exit_trampoline", buf, code - buf, ji, unwind_ops);
-
-       return buf;
-}
-
-#else
-
-gpointer
-mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot)
-{
-       g_assert_not_reached ();
-       return NULL;
-}
-
-gpointer
-mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot)
-{
-       g_assert_not_reached ();
-       return NULL;
-}
-
-#endif
-
 void
 mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg)
 {
@@ -1125,12 +828,14 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
        guint8 *code, *buf;
        int tramp_size = 64;
        MonoJumpInfo *ji = NULL;
-       GSList *unwind_ops = NULL;
+       GSList *unwind_ops;
 
        g_assert (!aot);
 
        code = buf = mono_global_codeman_reserve (tramp_size);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        /*
        This trampoline restore the call chain of the handler block then jumps into the code that deals with it.
        */
@@ -1139,13 +844,16 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
                amd64_mov_reg_membase (code, MONO_AMD64_ARG_REG1, MONO_AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoJitTlsData, handler_block_return_address), 8);
                /* Simulate a call */
                amd64_push_reg (code, AMD64_RAX);
+               mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, 16);
                amd64_jump_code (code, tramp);
        } else {
                /*Slow path uses a c helper*/
                amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, AMD64_RSP, 8);
                amd64_mov_reg_imm (code, AMD64_RAX, tramp);
                amd64_push_reg (code, AMD64_RAX);
+               mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, 16);
                amd64_push_reg (code, AMD64_RAX);
+               mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, 24);
                amd64_jump_code (code, handler_block_trampoline_helper);
        }
 
@@ -1211,7 +919,15 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo
 
        code = buf = mono_global_codeman_reserve (tramp_size);
 
-       framesize = sizeof (MonoContext);
+       framesize = 0;
+#ifdef TARGET_WIN32
+       /* Reserve space where the callee can save the argument registers */
+       framesize += 4 * sizeof (mgreg_t);
+#endif
+
+       ctx_offset = framesize;
+       framesize += sizeof (MonoContext);
+
        framesize = ALIGN_TO (framesize, MONO_ARCH_FRAME_ALIGNMENT);
 
        // CFA = sp + 8
@@ -1229,7 +945,6 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo
        mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, AMD64_RBP);
        amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, framesize);
 
-       ctx_offset = 0;
        gregs_offset = ctx_offset + MONO_STRUCT_OFFSET (MonoContext, gregs);
 
        /* Initialize a MonoContext structure on the stack */
@@ -1271,6 +986,8 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo
        amd64_mov_membase_reg (code, AMD64_RBP, sizeof (mgreg_t), AMD64_R11, sizeof (mgreg_t));
 
        amd64_leave (code);
+       cfa_offset -= sizeof (mgreg_t);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, AMD64_RSP, cfa_offset);
        amd64_ret (code);
 
        mono_arch_flush_icache (code, code - buf);
index 85b29242e57fe1c42ff37a779e75379378898dc8..156a5ee54fb561dc72c3573cd46e9de525c14eaa 100644 (file)
@@ -218,9 +218,6 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        /* The offset where lr was saved inside the regsave area */
        lr_offset = 13 * sizeof (mgreg_t);
 
-       // FIXME: Finish the unwind info, the current info allows us to unwind
-       // when the trampoline is not in the epilog
-
        // CFA = SP + (num registers pushed) * 4
        cfa_offset = 14 * sizeof (mgreg_t);
        mono_add_unwind_op_def_cfa (unwind_ops, code, buf, ARMREG_SP, cfa_offset);
@@ -425,10 +422,16 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
         * Note that IP has been conveniently set to the method addr.
         */
        ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, STACK - regsave_size);
+       cfa_offset -= STACK - regsave_size;
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
        ARM_POP_NWB (code, 0x5fff);
+       mono_add_unwind_op_same_value (unwind_ops, code, buf, ARMREG_LR);
        if (tramp_type == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH)
                ARM_MOV_REG_REG (code, ARMREG_R0, ARMREG_IP);
        ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, regsave_size);
+       cfa_offset -= regsave_size;
+       g_assert (cfa_offset == 0);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
        if (MONO_TRAMPOLINE_TYPE_MUST_RETURN (tramp_type))
                code = emit_bx (code, ARMREG_LR);
        else
@@ -571,6 +574,7 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
 {
        guint8 *code, *start;
        MonoDomain *domain = mono_domain_get ();
+       GSList *unwind_ops;
 #ifdef USE_JUMP_TABLES
        gpointer *jte;
        guint32 size = 20;
@@ -580,6 +584,8 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
 
        start = code = mono_domain_code_reserve (domain, size);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
 #ifdef USE_JUMP_TABLES
        jte = mono_jumptable_add_entry ();
        code = mono_arm_load_jumptable_entry (code, jte, ARMREG_IP);
@@ -599,6 +605,8 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
        /*g_print ("unbox trampoline at %d for %s:%s\n", this_pos, m->klass->name, m->name);
        g_print ("unbox code is at %p for method at %p\n", start, addr);*/
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
+
        return start;
 }
 
@@ -606,6 +614,7 @@ gpointer
 mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericContext *mrgctx, gpointer addr)
 {
        guint8 *code, *start;
+       GSList *unwind_ops;
 #ifdef USE_JUMP_TABLES
        int buf_len = 20;
        gpointer *jte;
@@ -616,6 +625,8 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo
 
        start = code = mono_domain_code_reserve (domain, buf_len);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
 #ifdef USE_JUMP_TABLES
        jte = mono_jumptable_add_entries (2);
        code = mono_arm_load_jumptable_entry_addr (code, jte, ARMREG_IP);
@@ -638,6 +649,8 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo
        mono_arch_flush_icache (start, code - start);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
+
        return start;
 }
 
@@ -674,7 +687,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
 
        code = buf = mono_global_codeman_reserve (tramp_size);
 
-       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, ARMREG_SP, 0);
+       unwind_ops = mono_arch_get_cie_program ();
 
        rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2));
        njumps = 0;
@@ -783,7 +796,7 @@ mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboo
 
        code = buf = mono_global_codeman_reserve (tramp_size);
 
-       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, ARMREG_SP, 0);
+       unwind_ops = mono_arch_get_cie_program ();
 
        // FIXME: Currently, we always go to the slow path.
        /* Load trampoline addr */
@@ -822,6 +835,8 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
 
        code = buf = mono_global_codeman_reserve (tramp_size);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD, NULL, NULL);
 
        /*
@@ -1100,6 +1115,8 @@ mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpoint
        mono_arch_flush_icache (buf, code - buf);
        mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, buf, code - buf, NULL, NULL), domain);
+
        return buf;
 }
 
index f0ca392d9c55c97355b605918d7d993562cdc802..2b4af7f8fe2ac613acd6667519fa76134d17d8a0 100644 (file)
@@ -67,6 +67,8 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
        desc [0] = buf;
        desc [1] = func_gp;
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, buf, code.buf - buf, NULL, NULL), domain);
+
        return desc;
 }
 
index bf35f84ff349c7a63835d1a305d054c73a012bae..37f17a47c89b3d7c20e638236364ae6fa25b4533 100644 (file)
@@ -53,6 +53,8 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
        /*g_print ("unbox trampoline at %d for %s:%s\n", this_pos, m->klass->name, m->name);
        g_print ("unbox code is at %p for method at %p\n", start, addr);*/
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return start;
 }
 
@@ -324,6 +326,8 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo
 
        mono_arch_flush_icache (start, code - start);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return start;
 }
 
index 1c723aa2ebb110ba89fd6870a2d377b2c6940988..32ab65ba8cda81118f2a16007cef51fda25a7b5a 100644 (file)
@@ -104,6 +104,8 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
        /*g_print ("unbox trampoline at %d for %s:%s\n", this_pos, m->klass->name, m->name);
        g_print ("unbox code is at %p for method at %p\n", start, addr);*/
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return start;
 }
 
@@ -149,6 +151,8 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo
        mono_arch_flush_icache (start, code - start);
        g_assert ((code - start) <= size);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return start;
 }
 
index a9ec6cf67e0996794db4ed67ad4268562c00dd12..e70f5c55c08a1142f9c4bef9ec9e30dacc25e675 100644 (file)
@@ -41,7 +41,6 @@
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/gc-internal.h>
 #include <mono/metadata/marshal.h>
-#include <mono/metadata/monitor.h>
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/arch/s390x/s390x-codegen.h>
@@ -109,6 +108,8 @@ mono_arch_get_unbox_trampoline (MonoMethod *method, gpointer addr)
        mono_arch_flush_icache (start, code - start);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, method);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return start;
 }
 
@@ -402,18 +403,7 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
        /*----------------------------------------------------------*/
        code = buf = mono_domain_code_reserve (domain, SPECIFIC_TRAMPOLINE_SIZE);
 
-       switch (tramp_type) {
-       /*
-        * Monitor tramps have the object in r2
-        */
-       case MONO_TRAMPOLINE_MONITOR_ENTER:
-       case MONO_TRAMPOLINE_MONITOR_ENTER_V4:
-       case MONO_TRAMPOLINE_MONITOR_EXIT:
-               s390_lgr (buf, s390_r1, s390_r2);
-               break;
-       default :
-               S390_SET  (buf, s390_r1, arg1);
-       }
+       S390_SET  (buf, s390_r1, arg1);
        displace = (tramp - buf) / 2;
        s390_jg   (buf, displace);
 
@@ -580,6 +570,8 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m,
        mono_arch_flush_icache (start, code - start);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return(start);
 }      
 
@@ -658,299 +650,3 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
 }
 
 /*========================= End of Function ========================*/
-
-#ifdef MONO_ARCH_MONITOR_OBJECT_REG
-/*------------------------------------------------------------------*/
-/*                                                                  */
-/* Name                - mono_arch_create_monitor_enter_trampoline         */
-/*                                                                  */
-/* Function    -                                                   */
-/*                                                                  */
-/*------------------------------------------------------------------*/
-
-gpointer
-mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot)
-{
-       guint8  *tramp,
-               *code, *buf;
-       gint16  *jump_obj_null, 
-               *jump_sync_null, 
-               *jump_cs_failed, 
-               *jump_other_owner, 
-               *jump_tid, 
-               *jump_sync_thin_hash = NULL,
-               *jump_lock_taken_true = NULL;
-       int tramp_size,
-           status_reg = s390_r0,
-           lock_taken_reg = s390_r1,
-           obj_reg = s390_r2,
-           sync_reg = s390_r3,
-           tid_reg = s390_r4,
-           status_offset,
-           nest_offset;
-       MonoJumpInfo *ji = NULL;
-       GSList *unwind_ops = NULL;
-
-       g_assert (MONO_ARCH_MONITOR_OBJECT_REG == obj_reg);
-#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
-       g_assert (MONO_ARCH_MONITOR_LOCK_TAKEN_REG == lock_taken_reg);
-#else
-       g_assert (!is_v4);
-#endif
-
-       mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset);
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32));
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (nest_offset) == sizeof (guint32));
-       status_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (status_offset);
-       nest_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (nest_offset);
-
-       tramp_size = 160;
-
-       code = buf = mono_global_codeman_reserve (tramp_size);
-
-       unwind_ops = mono_arch_get_cie_program ();
-
-       if (mono_thread_get_tls_offset () != -1) {
-               /* MonoObject* obj is in obj_reg */
-               /* is obj null? */
-               s390_ltgr (code, obj_reg, obj_reg);
-               /* if yes, jump to actual trampoline */
-               s390_jz (code, 0); CODEPTR(code, jump_obj_null);
-
-               if (is_v4) {
-                       s390_cli (code, lock_taken_reg, 0, 1);
-                       /* if *lock_taken is 1, jump to actual trampoline */
-                       s390_je (code, 0); CODEPTR(code, jump_lock_taken_true);
-               }
-
-               /* load obj->synchronization to sync_reg */
-               s390_lg (code, sync_reg, 0, obj_reg, MONO_STRUCT_OFFSET (MonoObject, synchronisation));
-
-               if (mono_gc_is_moving ()) {
-                       /*if bit zero is set it's a thin hash*/
-                       s390_tmll (code, sync_reg, 1);
-                       s390_jo  (code, 0); CODEPTR(code, jump_sync_thin_hash);
-
-                       /* Clear bits used by the gc */
-                       s390_nill (code, sync_reg, ~0x3);
-               }
-
-               /* is synchronization null? */
-               s390_ltgr (code, sync_reg, sync_reg);
-               /* if yes, jump to actual trampoline */
-               s390_jz (code, 0); CODEPTR(code, jump_sync_null);
-
-               /* load MonoInternalThread* into tid_reg */
-               s390_ear (code, s390_r5, 0);
-               s390_sllg(code, s390_r5, s390_r5, 0, 32);
-               s390_ear (code, s390_r5, 1);
-               /* load tid */
-               s390_lg  (code, tid_reg, 0, s390_r5, mono_thread_get_tls_offset ());
-               s390_lgf (code, tid_reg, 0, tid_reg, MONO_STRUCT_OFFSET (MonoInternalThread, small_id));
-
-               /* is synchronization->owner free */
-               s390_lgf  (code, status_reg, 0, sync_reg, status_offset);
-               s390_nilf (code, status_reg, OWNER_MASK);
-               /* if not, jump to next case */
-               s390_jnz  (code, 0); CODEPTR(code, jump_tid);
-
-               /* if yes, try a compare-exchange with the TID */
-               /* Form new status in tid_reg */
-               s390_xr (code, tid_reg, status_reg);
-               /* compare and exchange */
-               s390_cs (code, status_reg, tid_reg, sync_reg, status_offset);
-               s390_jnz (code, 0); CODEPTR(code, jump_cs_failed);
-               /* if successful, return */
-               if (is_v4)
-                       s390_mvi (code, lock_taken_reg, 0, 1);
-               s390_br (code, s390_r14);
-
-               /* next case: synchronization->owner is not null */
-               PTRSLOT(code, jump_tid);
-               /* is synchronization->owner == TID? */
-               s390_nilf (code, status_reg, OWNER_MASK);
-               s390_cr (code, status_reg, tid_reg);
-               /* if not, jump to actual trampoline */
-               s390_jnz (code, 0); CODEPTR(code, jump_other_owner);
-               /* if yes, increment nest */
-               s390_lgf (code, s390_r5, 0, sync_reg, nest_offset);
-               s390_ahi (code, s390_r5, 1);
-               s390_st  (code, s390_r5, 0, sync_reg, nest_offset);
-               /* return */
-               if (is_v4)
-                       s390_mvi (code, lock_taken_reg, 0, 1);
-               s390_br (code, s390_r14);
-
-               PTRSLOT (code, jump_obj_null);
-               if (jump_sync_thin_hash)
-                       PTRSLOT (code, jump_sync_thin_hash);
-               PTRSLOT (code, jump_sync_null);
-               PTRSLOT (code, jump_cs_failed);
-               PTRSLOT (code, jump_other_owner);
-               if (is_v4)
-                       PTRSLOT (code, jump_lock_taken_true);
-       }
-
-       /* jump to the actual trampoline */
-       if (is_v4)
-               tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER_V4, mono_get_root_domain (), NULL);
-       else
-               tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER, mono_get_root_domain (), NULL);
-
-       /* jump to the actual trampoline */
-       S390_SET (code, s390_r1, tramp);
-       s390_br (code, s390_r1);
-
-       mono_arch_flush_icache (code, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_MONITOR, NULL);
-       g_assert (code - buf <= tramp_size);
-
-       if (info) {
-               if (is_v4)
-                       *info = mono_tramp_info_create ("monitor_enter_v4_trampoline", buf, code - buf, ji, unwind_ops);
-               else
-                       *info = mono_tramp_info_create ("monitor_enter_trampoline", buf, code - buf, ji, unwind_ops);
-       }
-
-       return buf;
-}
-
-/*========================= End of Function ========================*/
-
-/*------------------------------------------------------------------*/
-/*                                                                  */
-/* Name                - mono_arch_create_monitor_exit_trampoline          */
-/*                                                                  */
-/* Function    -                                                   */
-/*                                                                  */
-/*------------------------------------------------------------------*/
-
-gpointer
-mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot)
-{
-       guint8  *tramp,
-               *code, *buf;
-       gint16  *jump_obj_null, 
-               *jump_have_waiters, 
-               *jump_sync_null, 
-               *jump_not_owned, 
-               *jump_cs_failed,
-               *jump_next,
-               *jump_sync_thin_hash = NULL;
-       int     tramp_size,
-               status_offset, nest_offset;
-       MonoJumpInfo *ji = NULL;
-       GSList *unwind_ops = NULL;
-       int     obj_reg = s390_r2,
-               sync_reg = s390_r3,
-               status_reg = s390_r4;
-
-       g_assert (obj_reg == MONO_ARCH_MONITOR_OBJECT_REG);
-
-       mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset);
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32));
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (nest_offset) == sizeof (guint32));
-       status_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (status_offset);
-       nest_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (nest_offset);
-
-       tramp_size = 160;
-
-       code = buf = mono_global_codeman_reserve (tramp_size);
-
-       unwind_ops = mono_arch_get_cie_program ();
-
-       if (mono_thread_get_tls_offset () != -1) {
-               /* MonoObject* obj is in obj_reg */
-               /* is obj null? */
-               s390_ltgr (code, obj_reg, obj_reg);
-               /* if yes, jump to actual trampoline */
-               s390_jz (code, 0); CODEPTR(code, jump_obj_null);
-
-               /* load obj->synchronization to RCX */
-               s390_lg (code, sync_reg, 0, obj_reg, MONO_STRUCT_OFFSET (MonoObject, synchronisation));
-
-               if (mono_gc_is_moving ()) {
-                       /*if bit zero is set it's a thin hash*/
-                       s390_tmll (code, sync_reg, 1);
-                       s390_jo   (code, 0); CODEPTR(code, jump_sync_thin_hash);
-
-                       /* Clear bits used by the gc */
-                       s390_nill (code, sync_reg, ~0x3);
-               }
-
-               /* is synchronization null? */
-               s390_ltgr (code, sync_reg, sync_reg);
-               /* if yes, jump to actual trampoline */
-               s390_jz (code, 0); CODEPTR(code, jump_sync_null);
-
-               /* next case: synchronization is not null */
-               /* load MonoInternalThread* into r5 */
-               s390_ear (code, s390_r5, 0);
-               s390_sllg(code, s390_r5, s390_r5, 0, 32);
-               s390_ear (code, s390_r5, 1);
-               /* load TID into r1 */
-               s390_lg  (code, s390_r1, 0, s390_r5, mono_thread_get_tls_offset ());
-               s390_lgf (code, s390_r1, 0, s390_r1, MONO_STRUCT_OFFSET (MonoInternalThread, small_id));
-               /* is synchronization->owner == TID */
-               s390_lgf (code, status_reg, 0, sync_reg, status_offset);
-               s390_xr  (code, s390_r1, status_reg);
-               s390_tmlh (code, s390_r1, OWNER_MASK);
-               /* if not, jump to actual trampoline */
-               s390_jno (code, 0); CODEPTR(code, jump_not_owned);
-
-               /* next case: synchronization->owner == TID */
-               /* is synchronization->nest == 1 */
-               s390_lgf (code, s390_r0, 0, sync_reg, nest_offset);
-               s390_chi (code, s390_r0, 1);
-               /* if not, jump to next case */
-               s390_jne (code, 0); CODEPTR(code, jump_next);
-               /* if yes, is synchronization->entry_count greater than zero */
-               s390_cfi (code, status_reg, ENTRY_COUNT_WAITERS);
-               /* if not, jump to actual trampoline */
-               s390_jnz (code, 0); CODEPTR(code, jump_have_waiters);
-               /* if yes, try to set synchronization->owner to null and return */
-               /* old status in s390_r0 */
-               s390_lgfr (code, s390_r0, status_reg);
-               /* form new status */
-               s390_nilf (code, status_reg, ENTRY_COUNT_MASK);
-               /* compare and exchange */
-               s390_cs (code, s390_r0, status_reg, sync_reg, status_offset);
-               /* if not successful, jump to actual trampoline */
-               s390_jnz (code, 0); CODEPTR(code, jump_cs_failed);
-               s390_br  (code, s390_r14);
-
-               /* next case: synchronization->nest is not 1 */
-               PTRSLOT (code, jump_next);
-               /* decrease synchronization->nest and return */
-               s390_lgf (code, s390_r0, 0, sync_reg, nest_offset);
-               s390_ahi (code, s390_r0, -1);
-               s390_st  (code, s390_r0, 0, sync_reg, nest_offset);
-               s390_br  (code, s390_r14);
-
-               PTRSLOT (code, jump_obj_null);
-               if (jump_sync_thin_hash)
-                       PTRSLOT (code, jump_sync_thin_hash);
-               PTRSLOT (code, jump_have_waiters);
-               PTRSLOT (code, jump_not_owned);
-               PTRSLOT (code, jump_cs_failed);
-               PTRSLOT (code, jump_sync_null);
-       }
-
-       /* jump to the actual trampoline */
-       tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_EXIT, mono_get_root_domain (), NULL);
-
-       S390_SET (code, s390_r1, tramp);
-       s390_br (code, s390_r1);
-
-       mono_arch_flush_icache (code, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_MONITOR, NULL);
-       g_assert (code - buf <= tramp_size);
-
-       if (info)
-               *info = mono_tramp_info_create ("monitor_exit_trampoline", buf, code - buf, ji, unwind_ops);
-
-       return buf;
-}
-
-/*========================= End of Function ========================*/
-#endif
index d390ed4dcc6be5714d2e07d9d5d8db6b61b9c53e..99143b723b30291f156655b305b3bc19b4135f81 100644 (file)
@@ -51,6 +51,8 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
 
        mono_arch_flush_icache (start, code - start);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), NULL);
+
        return start;
 }
 
index 9a887c435db9890aa5deed680b7d3e9d79ccefac..e13b422329ab29dd8213e995b7c6dd025caf40a9 100644 (file)
@@ -17,7 +17,6 @@
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/metadata/mono-debug-debugger.h>
-#include <mono/metadata/monitor.h>
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/gc-internal.h>
 #include <mono/arch/x86/x86-codegen.h>
@@ -26,6 +25,7 @@
 
 #include "mini.h"
 #include "mini-x86.h"
+#include "debugger-agent.h"
 
 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
 
@@ -44,9 +44,12 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
        guint8 *code, *start;
        int this_pos = 4, size = NACL_SIZE(16, 32);
        MonoDomain *domain = mono_domain_get ();
+       GSList *unwind_ops;
 
        start = code = mono_domain_code_reserve (domain, size);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        x86_alu_membase_imm (code, X86_ADD, X86_ESP, this_pos, sizeof (MonoObject));
        x86_jump_code (code, addr);
        g_assert ((code - start) < size);
@@ -54,6 +57,8 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
        nacl_domain_code_validate (domain, &start, size, &code);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
+
        return start;
 }
 
@@ -62,6 +67,7 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo
 {
        guint8 *code, *start;
        int buf_len;
+       GSList *unwind_ops;
 
        MonoDomain *domain = mono_domain_get ();
 
@@ -69,6 +75,8 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo
 
        start = code = mono_domain_code_reserve (domain, buf_len);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        x86_mov_reg_imm (code, MONO_ARCH_RGCTX_REG, mrgctx);
        x86_jump_code (code, addr);
        g_assert ((code - start) <= buf_len);
@@ -77,6 +85,8 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo
        mono_arch_flush_icache (start, code - start);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
+
        return start;
 }
 
@@ -247,8 +257,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        GSList *unwind_ops = NULL;
        MonoJumpInfo *ji = NULL;
        int i, offset, frame_size, regarray_offset, lmf_offset, caller_ip_offset, arg_offset;
-
-       unwind_ops = mono_arch_get_cie_program ();
+       int cfa_offset; /* cfa = cfa_reg + cfa_offset */
 
        code = buf = mono_global_codeman_reserve (256);
 
@@ -257,8 +266,6 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
         * the ret address is at: esp + (pushed_args + 1) * sizeof (gpointer)
         */
 
-       // FIXME: Unwind info
-
        /* Compute frame offsets relative to the frame pointer %ebp */
        arg_offset = sizeof (mgreg_t);
        caller_ip_offset = 2 * sizeof (mgreg_t);
@@ -271,9 +278,21 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        offset += 4 * sizeof (mgreg_t);
        frame_size = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
 
+       /* ret addr and arg are on the stack */
+       cfa_offset = 2 * sizeof (mgreg_t);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, X86_ESP, cfa_offset);
+       // IP saved at CFA - 4
+       mono_add_unwind_op_offset (unwind_ops, code, buf, X86_NREG, -4);
+
        /* Allocate frame */
        x86_push_reg (code, X86_EBP);
+       cfa_offset += sizeof (mgreg_t);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
+       mono_add_unwind_op_offset (unwind_ops, code, buf, X86_EBP, -cfa_offset);
+
        x86_mov_reg_reg (code, X86_EBP, X86_ESP, sizeof (mgreg_t));
+       mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, X86_EBP);
+
        /* There are three words on the stack, adding + 4 aligns the stack to 16, which is needed on osx */
        x86_alu_reg_imm (code, X86_SUB, X86_ESP, frame_size + sizeof (mgreg_t));
 
@@ -413,17 +432,24 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 
        /* Restore frame */
        x86_leave (code);
+       cfa_offset -= sizeof (mgreg_t);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, X86_ESP, cfa_offset);
+       mono_add_unwind_op_same_value (unwind_ops, code, buf, X86_EBP);
 
        if (MONO_TRAMPOLINE_TYPE_MUST_RETURN (tramp_type)) {
                /* Load the value returned by the trampoline */
                x86_mov_reg_membase (code, X86_EAX, X86_ESP, 0, 4);
                /* The trampoline returns normally, pop the trampoline argument */
                x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
+               cfa_offset -= sizeof (mgreg_t);
+               mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
                x86_ret (code);
        } else {
                /* The trampoline argument is at the top of the stack, and it contains the address we need to branch to */
                if (tramp_type == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD) {
                        x86_pop_reg (code, X86_EAX);
+                       cfa_offset -= sizeof (mgreg_t);
+                       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
                        x86_alu_reg_imm (code, X86_ADD, X86_ESP, 0x8);
                        x86_jump_reg (code, X86_EAX);
                } else {
@@ -613,342 +639,6 @@ mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboo
        return buf;
 }
 
-#ifdef MONO_ARCH_MONITOR_OBJECT_REG
-/*
- * The code produced by this trampoline is equivalent to this:
- *
- * if (obj) {
- *     if (obj->synchronisation) {
- *             if (obj->synchronisation->owner == 0) {
- *                     if (cmpxch (&obj->synchronisation->owner, TID, 0) == 0)
- *                             return;
- *             }
- *             if (obj->synchronisation->owner == TID) {
- *                     ++obj->synchronisation->nest;
- *                     return;
- *             }
- *     }
- * }
- * return full_monitor_enter ();
- *
- */
-gpointer
-mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot)
-{
-       guint8 *code, *buf;
-       guint8 *jump_obj_null, *jump_sync_null, *jump_other_owner, *jump_cmpxchg_failed, *jump_tid, *jump_sync_thin_hash = NULL;
-       guint8 *jump_lock_taken_true = NULL;
-       int tramp_size;
-       int status_offset, nest_offset;
-       MonoJumpInfo *ji = NULL;
-       GSList *unwind_ops = NULL;
-
-       g_assert (MONO_ARCH_MONITOR_OBJECT_REG == X86_EAX);
-#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
-       g_assert (MONO_ARCH_MONITOR_LOCK_TAKEN_REG == X86_EDX);
-#else
-       g_assert (!is_v4);
-#endif
-
-       mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset);
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32));
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (nest_offset) == sizeof (guint32));
-       status_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (status_offset);
-       nest_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (nest_offset);
-
-       tramp_size = NACL_SIZE (128, 192);
-
-       code = buf = mono_global_codeman_reserve (tramp_size);
-
-       x86_push_reg (code, X86_EAX);
-       if (mono_thread_get_tls_offset () != -1) {
-               if (is_v4) {
-                       x86_test_membase_imm (code, X86_EDX, 0, 1);
-                       /* if *lock_taken is 1, jump to actual trampoline */
-                       jump_lock_taken_true = code;
-                       x86_branch8 (code, X86_CC_NZ, -1, 1);
-                       x86_push_reg (code, X86_EDX);
-               }
-               /* MonoObject* obj is in EAX */
-               /* is obj null? */
-               x86_test_reg_reg (code, X86_EAX, X86_EAX);
-               /* if yes, jump to actual trampoline */
-               jump_obj_null = code;
-               x86_branch8 (code, X86_CC_Z, -1, 1);
-
-               /* load obj->synchronization to ECX */
-               x86_mov_reg_membase (code, X86_ECX, X86_EAX, MONO_STRUCT_OFFSET (MonoObject, synchronisation), 4);
-
-               if (mono_gc_is_moving ()) {
-                       /*if bit zero is set it's a thin hash*/
-                       /*FIXME use testb encoding*/
-                       x86_test_reg_imm (code, X86_ECX, 0x01);
-                       jump_sync_thin_hash = code;
-                       x86_branch8 (code, X86_CC_NE, -1, 1);
-
-                       /*clear bits used by the gc*/
-                       x86_alu_reg_imm (code, X86_AND, X86_ECX, ~0x3);
-               }
-
-               /* is synchronization null? */
-               x86_test_reg_reg (code, X86_ECX, X86_ECX);
-
-               /* if yes, jump to actual trampoline */
-               jump_sync_null = code;
-               x86_branch8 (code, X86_CC_Z, -1, 1);
-
-               /* load MonoInternalThread* into EDX */
-               if (aot) {
-                       /* load_aotconst () puts the result into EAX */
-                       x86_mov_reg_reg (code, X86_EDX, X86_EAX, sizeof (mgreg_t));
-                       code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_TLS_OFFSET, GINT_TO_POINTER (TLS_KEY_THREAD));
-                       code = mono_x86_emit_tls_get_reg (code, X86_EAX, X86_EAX);
-                       x86_xchg_reg_reg (code, X86_EAX, X86_EDX, sizeof (mgreg_t));
-               } else {
-                       code = mono_x86_emit_tls_get (code, X86_EDX, mono_thread_get_tls_offset ());
-               }
-               /* load TID into EDX */
-               x86_mov_reg_membase (code, X86_EDX, X86_EDX, MONO_STRUCT_OFFSET (MonoInternalThread, small_id), 4);
-
-               /* is synchronization->owner free */
-               x86_mov_reg_membase (code, X86_EAX, X86_ECX, status_offset, 4);
-               x86_test_reg_imm (code, X86_EAX, OWNER_MASK);
-               /* if not, jump to next case */
-               jump_tid = code;
-               x86_branch8 (code, X86_CC_NZ, -1, 1);
-
-               /* if yes, try a compare-exchange with the TID */
-               /* Form new status */
-               x86_alu_reg_reg (code, X86_OR, X86_EDX, X86_EAX);
-               /* compare and exchange */
-               x86_prefix (code, X86_LOCK_PREFIX);
-               x86_cmpxchg_membase_reg (code, X86_ECX, status_offset, X86_EDX);
-               /* if not successful, jump to actual trampoline */
-               jump_cmpxchg_failed = code;
-               x86_branch8 (code, X86_CC_NZ, -1, 1);
-               /* if successful, pop and return */
-               if (is_v4) {
-                       x86_pop_reg (code, X86_EDX);
-                       x86_mov_membase_imm (code, X86_EDX, 0, 1, 1);
-               }
-               x86_pop_reg (code, X86_EAX);
-               x86_ret (code);
-
-               /* next case: synchronization->owner is not null */
-               x86_patch (jump_tid, code);
-               /* is synchronization->owner == TID? */
-               x86_alu_reg_imm (code, X86_AND, X86_EAX, OWNER_MASK);
-               x86_alu_reg_reg (code, X86_CMP, X86_EAX, X86_EDX);
-               /* if not, jump to actual trampoline */
-               jump_other_owner = code;
-               x86_branch8 (code, X86_CC_NZ, -1, 1);
-               /* if yes, increment nest */
-               x86_inc_membase (code, X86_ECX, nest_offset);
-               if (is_v4) {
-                       x86_pop_reg (code, X86_EDX);
-                       x86_mov_membase_imm (code, X86_EDX, 0, 1, 1);
-               }
-               x86_pop_reg (code, X86_EAX);
-               /* return */
-               x86_ret (code);
-
-               /* obj is pushed, jump to the actual trampoline */
-               x86_patch (jump_obj_null, code);
-               if (jump_sync_thin_hash)
-                       x86_patch (jump_sync_thin_hash, code);
-               x86_patch (jump_sync_null, code);
-               x86_patch (jump_other_owner, code);
-               x86_patch (jump_cmpxchg_failed, code);
-
-               if (is_v4) {
-                       x86_pop_reg (code, X86_EDX);
-                       x86_patch (jump_lock_taken_true, code);
-               }
-       }
-
-       if (aot) {
-               /* We are calling the generic trampoline directly, the argument is pushed
-                * on the stack just like a specific trampoline.
-                */
-               if (is_v4)
-                       code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "generic_trampoline_monitor_enter_v4");
-               else
-                       code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "generic_trampoline_monitor_enter");
-               x86_jump_reg (code, X86_EAX);
-       } else {
-               if (is_v4)
-                       x86_jump_code (code, mono_get_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER_V4));
-               else
-                       x86_jump_code (code, mono_get_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER));
-       }
-
-       mono_arch_flush_icache (buf, code - buf);
-       g_assert (code - buf <= tramp_size);
-
-       nacl_global_codeman_validate (&buf, tramp_size, &code);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_MONITOR, NULL);
-
-       if (is_v4)
-               *info = mono_tramp_info_create ("monitor_enter_v4_trampoline", buf, code - buf, ji, unwind_ops);
-       else
-               *info = mono_tramp_info_create ("monitor_enter_trampoline", buf, code - buf, ji, unwind_ops);
-
-       return buf;
-}
-
-gpointer
-mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot)
-{
-       guint8 *tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_MONITOR_EXIT);
-       guint8 *code, *buf;
-       guint8 *jump_obj_null, *jump_have_waiters, *jump_sync_null, *jump_not_owned, *jump_sync_thin_hash = NULL;
-       guint8 *jump_next, *jump_cmpxchg_failed;
-       int tramp_size;
-       int status_offset, nest_offset;
-       MonoJumpInfo *ji = NULL;
-       GSList *unwind_ops = NULL;
-
-       g_assert (MONO_ARCH_MONITOR_OBJECT_REG == X86_EAX);
-
-       mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset);
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32));
-       g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (nest_offset) == sizeof (guint32));
-       status_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (status_offset);
-       nest_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (nest_offset);
-
-       tramp_size = NACL_SIZE (128, 192);
-
-       code = buf = mono_global_codeman_reserve (tramp_size);
-
-       x86_push_reg (code, X86_EAX);
-       if (mono_thread_get_tls_offset () != -1) {
-               /* MonoObject* obj is in EAX */
-               /* is obj null? */
-               x86_test_reg_reg (code, X86_EAX, X86_EAX);
-               /* if yes, jump to actual trampoline */
-               jump_obj_null = code;
-               x86_branch8 (code, X86_CC_Z, -1, 1);
-
-               /* load obj->synchronization to ECX */
-               x86_mov_reg_membase (code, X86_ECX, X86_EAX, MONO_STRUCT_OFFSET (MonoObject, synchronisation), 4);
-
-               if (mono_gc_is_moving ()) {
-                       /*if bit zero is set it's a thin hash*/
-                       /*FIXME use testb encoding*/
-                       x86_test_reg_imm (code, X86_ECX, 0x01);
-                       jump_sync_thin_hash = code;
-                       x86_branch8 (code, X86_CC_NE, -1, 1);
-
-                       /*clear bits used by the gc*/
-                       x86_alu_reg_imm (code, X86_AND, X86_ECX, ~0x3);
-               }
-
-               /* is synchronization null? */
-               x86_test_reg_reg (code, X86_ECX, X86_ECX);
-               /* if yes, jump to actual trampoline */
-               jump_sync_null = code;
-               x86_branch8 (code, X86_CC_Z, -1, 1);
-
-               /* next case: synchronization is not null */
-               /* load MonoInternalThread* into EDX */
-               if (aot) {
-                       /* load_aotconst () puts the result into EAX */
-                       x86_mov_reg_reg (code, X86_EDX, X86_EAX, sizeof (mgreg_t));
-                       code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_TLS_OFFSET, GINT_TO_POINTER (TLS_KEY_THREAD));
-                       code = mono_x86_emit_tls_get_reg (code, X86_EAX, X86_EAX);
-                       x86_xchg_reg_reg (code, X86_EAX, X86_EDX, sizeof (mgreg_t));
-               } else {
-                       code = mono_x86_emit_tls_get (code, X86_EDX, mono_thread_get_tls_offset ());
-               }
-               /* load TID into EDX */
-               x86_mov_reg_membase (code, X86_EDX, X86_EDX, MONO_STRUCT_OFFSET (MonoInternalThread, small_id), 4);
-               /* is synchronization->owner == TID */
-               x86_mov_reg_membase (code, X86_EAX, X86_ECX, status_offset, 4);
-               x86_alu_reg_reg (code, X86_XOR, X86_EDX, X86_EAX);
-               x86_test_reg_imm (code, X86_EDX, OWNER_MASK);
-               /* if no, jump to actual trampoline */
-               jump_not_owned = code;
-               x86_branch8 (code, X86_CC_NZ, -1, 1);
-
-               /* next case: synchronization->owner == TID */
-               /* is synchronization->nest == 1 */
-               x86_alu_membase_imm (code, X86_CMP, X86_ECX, nest_offset, 1);
-               /* if not, jump to next case */
-               jump_next = code;
-               x86_branch8 (code, X86_CC_NZ, -1, 1);
-               /* if yes, is synchronization->entry_count greater than zero? */
-               x86_test_reg_imm (code, X86_EAX, ENTRY_COUNT_WAITERS);
-               /* if yes, jump to actual trampoline */
-               jump_have_waiters = code;
-               x86_branch8 (code, X86_CC_NZ, -1 , 1);
-               /* if not, try to set synchronization->owner to null and return */
-               x86_mov_reg_reg (code, X86_EDX, X86_EAX, 4);
-               x86_alu_reg_imm (code, X86_AND, X86_EDX, ENTRY_COUNT_MASK); 
-               /* compare and exchange */
-               x86_prefix (code, X86_LOCK_PREFIX);
-               /* EAX contains the previous status */
-               x86_cmpxchg_membase_reg (code, X86_ECX, status_offset, X86_EDX);
-               /* if not successful, jump to actual trampoline */
-               jump_cmpxchg_failed = code;
-               x86_branch8 (code, X86_CC_NZ, -1, 1);
-
-               x86_pop_reg (code, X86_EAX);
-               x86_ret (code);
-
-               /* next case: synchronization->nest is not 1 */
-               x86_patch (jump_next, code);
-               /* decrease synchronization->nest and return */
-               x86_dec_membase (code, X86_ECX, nest_offset);
-               x86_pop_reg (code, X86_EAX);
-               x86_ret (code);
-
-               /* push obj and jump to the actual trampoline */
-               x86_patch (jump_obj_null, code);
-               if (jump_sync_thin_hash)
-                       x86_patch (jump_sync_thin_hash, code);
-               x86_patch (jump_have_waiters, code);
-               x86_patch (jump_cmpxchg_failed, code);
-               x86_patch (jump_not_owned, code);
-               x86_patch (jump_sync_null, code);
-       }
-
-       /* obj is pushed, jump to the actual trampoline */
-       if (aot) {
-               code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "generic_trampoline_monitor_exit");
-               x86_jump_reg (code, X86_EAX);
-       } else {
-               x86_jump_code (code, tramp);
-       }
-
-       nacl_global_codeman_validate (&buf, tramp_size, &code);
-
-       mono_arch_flush_icache (buf, code - buf);
-       g_assert (code - buf <= tramp_size);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_MONITOR, NULL);
-
-       *info = mono_tramp_info_create ("monitor_exit_trampoline", buf, code - buf, ji, unwind_ops);
-
-       return buf;
-}
-
-#else
-
-gpointer
-mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot)
-{
-       g_assert_not_reached ();
-       return NULL;
-}
-
-gpointer
-mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot)
-{
-       g_assert_not_reached ();
-       return NULL;
-}
-
-#endif
-
 void
 mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg)
 {
@@ -973,12 +663,15 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
        guint8 *code, *buf;
        int tramp_size = 64;
        MonoJumpInfo *ji = NULL;
+       int cfa_offset;
        GSList *unwind_ops = NULL;
 
        g_assert (!aot);
 
        code = buf = mono_global_codeman_reserve (tramp_size);
 
+       unwind_ops = mono_arch_get_cie_program ();
+       cfa_offset = sizeof (mgreg_t);
        /*
        This trampoline restore the call chain of the handler block then jumps into the code that deals with it.
        */
@@ -997,10 +690,18 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
        /* Simulate a call */
        /*Fix stack alignment*/
        x86_alu_reg_imm (code, X86_SUB, X86_ESP, 0x4);
+       cfa_offset += sizeof (mgreg_t);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
+
        /* This is the address the trampoline will return to */
        x86_push_reg (code, X86_EAX);
+       cfa_offset += sizeof (mgreg_t);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
+
        /* Dummy trampoline argument, since we call the generic trampoline directly */
        x86_push_imm (code, 0);
+       cfa_offset += sizeof (mgreg_t);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
        x86_jump_code (code, tramp);
 
        nacl_global_codeman_validate (&buf, tramp_size, &code);
@@ -1043,11 +744,15 @@ mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpoint
 {
        guint8 *code, *start;
        int buf_len;
+       GSList *unwind_ops;
+
 
        buf_len = 10;
 
        start = code = mono_domain_code_reserve (domain, buf_len);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        x86_mov_reg_imm (code, X86_EAX, arg);
        x86_jump_code (code, addr);
        g_assert ((code - start) <= buf_len);
@@ -1056,9 +761,111 @@ mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpoint
        mono_arch_flush_icache (start, code - start);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
+
        return start;
 }
 
+/*
+ * mono_arch_create_sdb_trampoline:
+ *
+ *   Return a trampoline which captures the current context, passes it to
+ * debugger_agent_single_step_from_context ()/debugger_agent_breakpoint_from_context (),
+ * then restores the (potentially changed) context.
+ */
+guint8*
+mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gboolean aot)
+{
+       int tramp_size = 256;
+       int framesize, ctx_offset, cfa_offset;
+       guint8 *code, *buf;
+       GSList *unwind_ops = NULL;
+       MonoJumpInfo *ji = NULL;
+
+       code = buf = mono_global_codeman_reserve (tramp_size);
+
+       framesize = 0;
+
+       /* Argument area */
+       framesize += sizeof (mgreg_t);
+
+       ctx_offset = framesize;
+       framesize += sizeof (MonoContext);
+
+       framesize = ALIGN_TO (framesize, MONO_ARCH_FRAME_ALIGNMENT);
+
+       // CFA = sp + 4
+       cfa_offset = 4;
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, X86_ESP, 4);
+       // IP saved at CFA - 4
+       mono_add_unwind_op_offset (unwind_ops, code, buf, X86_NREG, -cfa_offset);
+
+       x86_push_reg (code, X86_EBP);
+       cfa_offset += sizeof(mgreg_t);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
+       mono_add_unwind_op_offset (unwind_ops, code, buf, X86_EBP, - cfa_offset);
+
+       x86_mov_reg_reg (code, X86_EBP, X86_ESP, sizeof(mgreg_t));
+       mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, X86_EBP);
+       /* The + 8 makes the stack aligned */
+       x86_alu_reg_imm (code, X86_SUB, X86_ESP, framesize + 8);
+
+       /* Initialize a MonoContext structure on the stack */
+       x86_mov_membase_reg (code, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, eax), X86_EAX, sizeof (mgreg_t));
+       x86_mov_membase_reg (code, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, ebx), X86_EBX, sizeof (mgreg_t));
+       x86_mov_membase_reg (code, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, ecx), X86_ECX, sizeof (mgreg_t));
+       x86_mov_membase_reg (code, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, edx), X86_EDX, sizeof (mgreg_t));
+       x86_mov_reg_membase (code, X86_EAX, X86_EBP, 0, sizeof (mgreg_t));
+       x86_mov_membase_reg (code, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, ebp), X86_EAX, sizeof (mgreg_t));
+       x86_mov_reg_reg (code, X86_EAX, X86_EBP, sizeof (mgreg_t));
+       x86_alu_reg_imm (code, X86_ADD, X86_EAX, cfa_offset);
+       x86_mov_membase_reg (code, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, esp), X86_ESP, sizeof (mgreg_t));
+       x86_mov_membase_reg (code, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, esi), X86_ESI, sizeof (mgreg_t));
+       x86_mov_membase_reg (code, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, edi), X86_EDI, sizeof (mgreg_t));
+       x86_mov_reg_membase (code, X86_EAX, X86_EBP, 4, sizeof (mgreg_t));
+       x86_mov_membase_reg (code, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, eip), X86_EAX, sizeof (mgreg_t));
+
+       /* Call the single step/breakpoint function in sdb */
+       x86_lea_membase (code, X86_EAX, X86_ESP, ctx_offset);
+       x86_mov_membase_reg (code, X86_ESP, 0, X86_EAX, sizeof (mgreg_t));
+
+       if (aot) {
+               g_assert_not_reached ();
+       } else {
+               if (single_step)
+                       x86_call_code (code, debugger_agent_single_step_from_context);
+               else
+                       x86_call_code (code, debugger_agent_breakpoint_from_context);
+       }
+
+       /* Restore registers from ctx */
+       /* Overwrite the saved ebp */
+       x86_mov_reg_membase (code, X86_EAX, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, ebp), sizeof (mgreg_t));
+       x86_mov_membase_reg (code, X86_EBP, 0, X86_EAX, sizeof (mgreg_t));
+       /* Overwrite saved eip */
+       x86_mov_reg_membase (code, X86_EAX, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, eip), sizeof (mgreg_t));
+       x86_mov_membase_reg (code, X86_EBP, 4, X86_EAX, sizeof (mgreg_t));
+       x86_mov_reg_membase (code, X86_EAX, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, eax), sizeof (mgreg_t));
+       x86_mov_reg_membase (code, X86_EBX, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, ebx), sizeof (mgreg_t));
+       x86_mov_reg_membase (code, X86_ECX, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, ecx), sizeof (mgreg_t));
+       x86_mov_reg_membase (code, X86_EDX, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, edx), sizeof (mgreg_t));
+       x86_mov_reg_membase (code, X86_ESI, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, esi), sizeof (mgreg_t));
+       x86_mov_reg_membase (code, X86_EDI, X86_ESP, ctx_offset + G_STRUCT_OFFSET (MonoContext, edi), sizeof (mgreg_t));
+
+       x86_leave (code);
+       cfa_offset -= sizeof (mgreg_t);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, buf, X86_ESP, cfa_offset);
+       x86_ret (code);
+
+       mono_arch_flush_icache (code, code - buf);
+       g_assert (code - buf <= tramp_size);
+
+       const char *tramp_name = single_step ? "sdb_single_step_trampoline" : "sdb_breakpoint_trampoline";
+       *info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
+
+       return buf;
+}
+
 #if defined(ENABLE_GSHAREDVT)
 
 #include "../../../mono-extensions/mono/mini/tramp-x86-gsharedvt.c"
index 52b292ef0808a7d2b96920791df7d7584af5f6f7..1fbd5c9f63bbfed5c3b6bf580c31fb63a4770743 100644 (file)
@@ -338,13 +338,15 @@ mono_print_unwind_info (guint8 *unwind_info, int unwind_info_len)
 }
 
 /*
- * mono_unwind_ops_encode:
+ * mono_unwind_ops_encode_full:
  *
  *   Encode the unwind ops in UNWIND_OPS into the compact DWARF encoding.
  * Return a pointer to malloc'ed memory.
+ * If ENABLE_EXTENSIONS is FALSE, avoid encoding the mono extension
+ * opcode (DW_CFA_mono_advance_loc).
  */
 guint8*
-mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
+mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enable_extensions)
 {
        GSList *l;
        MonoUnwindOp *op;
@@ -430,6 +432,8 @@ mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
                        *p ++ = op->op;
                        break;
                case DW_CFA_mono_advance_loc:
+                       if (!enable_extensions)
+                               break;
                        /* Only one location is supported */
                        g_assert (op->val == 0);
                        *p ++ = op->op;
@@ -447,6 +451,12 @@ mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
        return res;
 }
 
+guint8*
+mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
+{
+       return mono_unwind_ops_encode_full (unwind_ops, out_len, TRUE);
+}
+
 #if 0
 #define UNW_DEBUG(stmt) do { stmt; } while (0)
 #else
@@ -1164,7 +1174,7 @@ mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8
 GSList*
 mono_unwind_get_cie_program (void)
 {
-#if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC)
+#if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC) || defined(TARGET_ARM)
        return mono_arch_get_cie_program ();
 #else
        return NULL;
index 7f629d6c356d07fb50b5aa15136d6f6669329cce..97ad6e34dfd6156a69bc9056e9f3788047fbdecf 100644 (file)
@@ -1,6 +1,6 @@
 SUBDIRS = assemblyresolve gc-descriptors
 
-check-local: assemblyresolve/test/asm.dll testjit test-generic-sharing test-type-load test-cattr-type-load test-reflection-load-with-context test_platform test-process-exit test-messages rm-empty-logs
+check-local: assemblyresolve/test/asm.dll testjit test-generic-sharing test-type-load test-cattr-type-load test-reflection-load-with-context test_platform test-process-exit test-messages test-unhandled-exception-2 rm-empty-logs
 check-full: test-sgen check-local
 check-parallel: compile-tests check-full
 
@@ -1349,10 +1349,23 @@ test-oom: $(OOM_TESTS)
                MONO_GC_PARAMS=max-heap-size=16m                                                  $(RUNTIME) $$fn > $$fn.stdout || exit 1;      \
        done
 
+if HOST_WIN32
+test-unhandled-exception-2:
+else
+test-unhandled-exception-2: unhandled-exception.exe
+       @echo "Testing unhandled-exception_1 ..."; $(RUNTIME) $+ 1 1> unhandled-exception_1.exe.stdout 2> unhandled-exception_1.exe.stderr; if test "x$$?" != "x1";   then exit 1; fi;  \
+        echo "Testing unhandled-exception_2 ..."; $(RUNTIME) $+ 2 1> unhandled-exception_2.exe.stdout 2> unhandled-exception_2.exe.stderr; if test "x$$?" != "x0";   then exit 2; fi;  \
+        echo "Testing unhandled-exception_3 ..."; $(RUNTIME) $+ 3 1> unhandled-exception_3.exe.stdout 2> unhandled-exception_3.exe.stderr; if test "x$$?" != "x0";   then exit 3; fi;  \
+        echo "Testing unhandled-exception_4 ..."; $(RUNTIME) $+ 4 1> unhandled-exception_4.exe.stdout 2> unhandled-exception_4.exe.stderr; if test "x$$?" != "x0";   then exit 4; fi;  \
+        echo "Testing unhandled-exception_5 ..."; $(RUNTIME) $+ 5 1> unhandled-exception_5.exe.stdout 2> unhandled-exception_5.exe.stderr; if test "x$$?" != "x255"; then exit 5; fi;  \
+        echo "Testing unhandled-exception_6 ..."; $(RUNTIME) $+ 6 1> unhandled-exception_6.exe.stdout 2> unhandled-exception_6.exe.stderr; if test "x$$?" != "x0";   then exit 6; fi;  \
+        echo "Testing unhandled-exception_7 ..."; $(RUNTIME) $+ 7 1> unhandled-exception_7.exe.stdout 2> unhandled-exception_7.exe.stderr; if test "x$$?" != "x0";   then exit 7; fi;  \
+        echo "Testing unhandled-exception_8 ..."; $(RUNTIME) $+ 8 1> unhandled-exception_8.exe.stdout 2> unhandled-exception_8.exe.stderr; if test "x$$?" != "x3";   then exit 8; fi
+endif
 
 noinst_LTLIBRARIES = libtest.la
 
-AM_CPPFLAGS = $(GLIB_CFLAGS) $(GMODULE_CFLAGS)
+AM_CPPFLAGS = $(GLIB_CFLAGS)
 
 if HOST_WIN32
 # gcc-3.4.4 emits incorrect code when making indirect calls to stdcall functions using a tail call
index 2ce4a3c4d78f7e9e00f22a0d81ab57292d22cc48..205d10ca16e98838c73ff9da01053e166f4ce530 100644 (file)
@@ -12,14 +12,26 @@ public class Foo  {
                resurrect = this;
        }
 
+       public static void EnterMonitor (object obj)
+       {
+               for (int i = 0; i < 257; i++)
+                       Monitor.Enter (obj);
+       }
+
+       public static void ExitMonitor (object obj)
+       {
+               for (int i = 0; i < 257; i++)
+                       Monitor.Exit (obj);
+       }
+
        public static void CreateFoo (int level)
        {
                if (level == 0) {
                        reference = new Foo ();
 
                        /* Allocate a MonoThreadsSync for the object */
-                       Monitor.Enter (reference);
-                       Monitor.Exit (reference);
+                       EnterMonitor (reference);
+                       ExitMonitor (reference);
                        reference = null;
                } else {
                        CreateFoo (level - 1);
@@ -52,7 +64,7 @@ public class Foo  {
                        /* Make sure these are not collected */
                        list.Add (foo);
 
-                       Monitor.Enter (foo);
+                       EnterMonitor (foo);
                }
        }
 } 
index b7ff6475d23cdb14ba9877754c6a53446d341625..2145f0561c00cfea150b74a07b4b78c70a1ce635 100644 (file)
@@ -54,10 +54,11 @@ class main {
                        b.test_exception ();
                }
                catch (SynchronizationLockException ex) {
-                       return 1;
+                       // OK
                }
                catch (Exception ex) {
-                       // OK
+                       // The other exception should be overwritten by the lock one
+                       return 1;
                }
 
                Console.WriteLine ("Test4...");
@@ -81,10 +82,10 @@ class main {
                        d ();
                }
                catch (SynchronizationLockException ex) {
-                       return 2;
+                       // OK
                }
                catch (Exception ex) {
-                       // OK
+                       return 2;
                }
 
                return 0;
index a63b63fa5c6d4c66262f59a661bbcc8710ac771e..9d56cd8c365a121503d886399b40ec3d2a5c5081 100644 (file)
@@ -76,10 +76,11 @@ class Tests {
                        b.test_exception ();
                }
                catch (SynchronizationLockException ex) {
-                       return 1;
+                       // OK
                }
                catch (Exception ex) {
-                       // OK
+                       // The other exception should be overwritten by the lock one
+                       return 1;
                }
                if (is_synchronized (b))
                        return 1;
@@ -113,10 +114,10 @@ class Tests {
                        d ();
                }
                catch (SynchronizationLockException ex) {
-                       return 2;
+                       // OK
                }
                catch (Exception ex) {
-                       // OK
+                       return 2;
                }
                if (is_synchronized (b))
                        return 1;
diff --git a/mono/tests/unhandled-exception.cs b/mono/tests/unhandled-exception.cs
new file mode 100644 (file)
index 0000000..7658e07
--- /dev/null
@@ -0,0 +1,193 @@
+using System;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+
+class CustomException : Exception
+{
+}
+
+class CustomException2 : Exception
+{
+}
+
+
+class CrossDomain : MarshalByRefObject
+{
+       public Action NewDelegateWithTarget ()
+       {
+               return new Action (Bar);
+       }
+
+       public Action NewDelegateWithoutTarget ()
+       {
+               return () => { throw new CustomException (); };
+       }
+
+       public void Bar ()
+       {
+               throw new CustomException ();
+       }
+}
+
+class Driver {
+       static ManualResetEvent mre = new ManualResetEvent (false);
+
+       static void DoTest1 ()
+       {
+               mre.Reset ();
+
+               var t = new Thread (new ThreadStart (() => { try { throw new CustomException (); } finally { mre.Set (); } }));
+               t.Start ();
+
+               if (!mre.WaitOne (5000))
+                       Environment.Exit (2);
+
+               t.Join ();
+       }
+
+       static void DoTest2 ()
+       {
+               mre.Reset ();
+
+               var a = new Action (() => { try { throw new CustomException (); } finally { mre.Set (); } });
+               var ares = a.BeginInvoke (null, null);
+
+               if (!mre.WaitOne (5000))
+                       Environment.Exit (2);
+
+               try {
+                       a.EndInvoke (ares);
+                       throw new Exception ();
+               } catch (CustomException) {                     
+               } catch (Exception) {
+                       Environment.Exit (3);
+               }
+       }
+
+       static void DoTest3 ()
+       {
+               mre.Reset ();
+
+               ThreadPool.QueueUserWorkItem (_ => { try { throw new CustomException (); } finally { mre.Set (); } });
+
+               if (!mre.WaitOne (5000))
+                       Environment.Exit (2);
+       }
+
+       static void DoTest4 ()
+       {
+               mre.Reset ();
+
+               var t = Task.Factory.StartNew (new Action (() => { try { throw new CustomException (); } finally { mre.Set (); } }));
+
+               if (!mre.WaitOne (5000))
+                       Environment.Exit (2);
+
+               try {
+                       t.Wait ();
+                       throw new Exception ();
+               } catch (AggregateException ae) {
+                       if (!(ae.InnerExceptions [0] is CustomException))
+                               Environment.Exit (4);
+               } catch (Exception) {
+                       Environment.Exit (3);
+               }
+       }
+       
+       class FinalizedClass
+       {
+               ~FinalizedClass ()
+               {
+                       try {
+                               throw new CustomException ();
+                       } finally {
+                               mre.Set ();
+                       }
+               }
+       }
+
+       static void DoTest5 ()
+       {
+               mre.Reset ();
+
+               new FinalizedClass();
+
+               GC.Collect ();
+               GC.WaitForPendingFinalizers ();
+
+               if (!mre.WaitOne (5000))
+                       Environment.Exit (2);
+       }
+
+       static void DoTest6 ()
+       {
+               ManualResetEvent mre2 = new ManualResetEvent (false);
+
+               mre.Reset ();
+
+               var a = new Action (() => { try { throw new CustomException (); } finally { mre.Set (); } });
+               var ares = a.BeginInvoke (_ => { mre2.Set (); throw new CustomException2 (); }, null);
+
+               if (!mre.WaitOne (5000))
+                       Environment.Exit (2);
+               if (!mre2.WaitOne (5000))
+                       Environment.Exit (22);
+
+               try {
+                       a.EndInvoke (ares);
+                       throw new Exception ();
+               } catch (CustomException) {
+               } catch (Exception) {
+                       Environment.Exit (3);
+               }
+       }
+
+       static void DoTest7 ()
+       {
+               var cd = (CrossDomain) AppDomain.CreateDomain ("ad").CreateInstanceAndUnwrap (typeof(CrossDomain).Assembly.FullName, "CrossDomain");
+
+               var a = cd.NewDelegateWithoutTarget ();
+               var ares = a.BeginInvoke (delegate { throw new CustomException2 (); }, null);
+
+               try {
+                       a.EndInvoke (ares);
+                       throw new Exception ();
+               } catch (CustomException) {
+               } catch (Exception) {
+                       Environment.Exit (3);
+               }
+       }
+
+       static void DoTest8 ()
+       {
+               var cd = (CrossDomain) AppDomain.CreateDomain ("ad").CreateInstanceAndUnwrap (typeof(CrossDomain).Assembly.FullName, "CrossDomain");
+
+               var a = cd.NewDelegateWithTarget ();
+               var ares = a.BeginInvoke (delegate { throw new CustomException2 (); }, null);
+
+               try {
+                       a.EndInvoke (ares);
+                       throw new Exception ();
+               } catch (CustomException) {
+               } catch (Exception) {
+                       Environment.Exit (3);
+               }
+       }
+
+       static void Main (string[] args)
+       {
+               switch (int.Parse (args [0])) {
+               case 1: DoTest1 (); break;
+               case 2: DoTest2 (); break;
+               case 3: DoTest3 (); break;
+               case 4: DoTest4 (); break;
+               case 5: DoTest5 (); break;
+               case 6: DoTest6 (); break;
+               case 7: DoTest7 (); break;
+               case 8: DoTest8 (); break;
+               default: throw new ArgumentOutOfRangeException ();
+               }
+               Environment.Exit (0);
+       }
+}
index 1f77f5463650053a83b8a4e0d467b0e83fd11bc8..a13c0b7798420c2ef1a533540960230c2ce96201 100644 (file)
 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
 #endif
 
-#elif defined(TARGET_MACH) && 0
+#elif defined(TARGET_MACH) && (defined(__i386__) || defined(__x86_64__))
 
-#define MONO_HAVE_FAST_TLS
+#define MONO_HAVE_FAST_TLS 1
 #define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
 #define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
 #define MONO_FAST_TLS_ADDR(x) (mono_mach_get_tls_address_from_thread (pthread_self (), x))
index d821f3c5e32b167c5b8c868668f0cb931da592da..cfeb19d31b9f5960698c4925ba8ecb13e711c757 100644 (file)
@@ -19,7 +19,8 @@ typedef enum {
        FRAME_TYPE_DEBUGGER_INVOKE = 1,
        /* Frame for transitioning to native code */
        FRAME_TYPE_MANAGED_TO_NATIVE = 2,
-       FRAME_TYPE_SENTINEL = 3
+       FRAME_TYPE_TRAMPOLINE = 3,
+       FRAME_TYPE_NUM = 4
 } MonoStackFrameType;
 
 typedef enum {
index b44719109ffc277ad377942a4b219b21a92d8408..0575605712b7dd53d16df1e471197ebcc382f4fc 100644 (file)
@@ -35,7 +35,7 @@ mono_threads_state_poll (void)
        if (!(info->thread_state & (STATE_ASYNC_SUSPEND_REQUESTED | STATE_SELF_SUSPEND_REQUESTED)))
                return;
 
-       g_assert (mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX], NULL));
+       mono_threads_get_runtime_callbacks ()->thread_state_init (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX]);
 
        /* commit the saved state and notify others if needed */
        switch (mono_threads_transition_state_poll (info)) {
@@ -64,11 +64,7 @@ mono_threads_prepare_blocking (void)
        }
 
 retry:
-       /*The JIT might not be able to save*/
-       if (!mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX], NULL)) {
-               THREADS_SUSPEND_DEBUG ("PREPARE-BLOCKING failed %p to save thread state\n", mono_thread_info_get_tid (info));
-               return NULL;
-       }
+       mono_threads_get_runtime_callbacks ()->thread_state_init (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX]);
 
        switch (mono_threads_transition_do_blocking (info)) {
        case DoBlockingContinue:
@@ -165,11 +161,7 @@ mono_threads_try_prepare_blocking (void)
        }
 
 retry:
-       /*The JIT might not be able to save*/
-       if (!mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX], NULL)) {
-               THREADS_SUSPEND_DEBUG ("PREPARE-TRY-BLOCKING failed %p to save thread state\n", mono_thread_info_get_tid (info));
-               return NULL;
-       }
+       mono_threads_get_runtime_callbacks ()->thread_state_init (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX]);
 
        switch (mono_threads_transition_do_blocking (info)) {
        case DoBlockingContinue:
index 6eca0266dcfb897f4fbef80bdfd1bc58f9ecdb01..88ae40aee8769cbf4005a79d8196d5ceaac6d88e 100644 (file)
@@ -17,7 +17,7 @@
 /* Runtime consumable API */
 
 #define MONO_SUSPEND_CHECK() do {      \
-       if (G_UNLIKELY (mono_threads_polling_required)) mono_threads_state_poll ();     \
+       if (G_UNLIKELY (mono_polling_required)) mono_threads_state_poll ();     \
 } while (0);
 
 #define MONO_PREPARE_BLOCKING  \
@@ -46,8 +46,6 @@
 
 /* Internal API */
 
-extern volatile size_t mono_threads_polling_required;
-
 void mono_threads_state_poll (void);
 void* mono_threads_prepare_blocking (void);
 void mono_threads_finish_blocking (void* cookie);
@@ -59,11 +57,11 @@ void* mono_threads_try_prepare_blocking (void);
 void mono_threads_finish_try_blocking (void* cookie);
 
 /* JIT specific interface */
-extern volatile size_t mono_polling_required ;
+extern volatile size_t mono_polling_required;
 
 #else
 
-#define MONO_SUSPEND_CHECK do {        } while (0);
+#define MONO_SUSPEND_CHECK() do {      } while (0);
 #define MONO_PREPARE_BLOCKING {
 #define MONO_FINISH_BLOCKING }
 #define MONO_PREPARE_RESET_BLOCKING {
index fc884e7a05584787d813ff2b241012da9a61eaa1..fbb78b498fa7d252b59e3b236bfa6772676d9a35 100644 (file)
@@ -31,12 +31,6 @@ mono_threads_init_platform (void)
        mono_threads_init_dead_letter ();
 }
 
-void
-mono_threads_core_interrupt (MonoThreadInfo *info)
-{
-       thread_abort (info->native_handle);
-}
-
 void
 mono_threads_core_abort_syscall (MonoThreadInfo *info)
 {
index e9ca1415c04eee3f37dfd855b451b738d72f7ab6..84e423ec1c29669da086d9d67df29af446f01504 100644 (file)
@@ -71,7 +71,7 @@ inner_start_thread (void *arg)
        start_info->handle = handle;
 
        info = mono_thread_info_attach (&result);
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
 
        info->runtime_thread = TRUE;
        info->handle = handle;
@@ -92,7 +92,7 @@ inner_start_thread (void *arg)
                MONO_SEM_DESTROY (&info->create_suspended_sem);
        }
 
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
        /* Run the actual main function of the thread */
        result = start_func (t_arg);
 
@@ -236,30 +236,6 @@ mono_threads_core_open_thread_handle (HANDLE handle, MonoNativeThreadId tid)
        return handle;
 }
 
-gpointer
-mono_threads_core_prepare_interrupt (HANDLE thread_handle)
-{
-       return wapi_prepare_interrupt_thread (thread_handle);
-}
-
-void
-mono_threads_core_finish_interrupt (gpointer wait_handle)
-{
-       wapi_finish_interrupt_thread (wait_handle);
-}
-
-void
-mono_threads_core_self_interrupt (void)
-{
-       wapi_self_interrupt ();
-}
-
-void
-mono_threads_core_clear_interruption (void)
-{
-       wapi_clear_interruption ();
-}
-
 int
 mono_threads_pthread_kill (MonoThreadInfo *info, int signum)
 {
old mode 100755 (executable)
new mode 100644 (file)
index 9f3581e..9e59810
@@ -395,26 +395,4 @@ mono_threads_core_set_name (MonoNativeThreadId tid, const char *name)
 #endif
 }
 
-
-gpointer
-mono_threads_core_prepare_interrupt (HANDLE thread_handle)
-{
-       return NULL;
-}
-
-void
-mono_threads_core_finish_interrupt (gpointer wait_handle)
-{
-}
-
-void
-mono_threads_core_self_interrupt (void)
-{
-}
-
-void
-mono_threads_core_clear_interruption (void)
-{
-}
-
 #endif
index 366f09468e952c5882802b4dd0edf07d8655bd73..5d4664369a172e207e06ef114002dfa4b5a094ff 100644 (file)
@@ -149,7 +149,7 @@ dump_threads (void)
        MonoThreadInfo *info;
        MonoThreadInfo *cur = mono_thread_info_current ();
 
-       MOSTLY_ASYNC_SAFE_PRINTF ("STATE CUE CARD: (? means a positive number, usually 1 or 2)\n");
+       MOSTLY_ASYNC_SAFE_PRINTF ("STATE CUE CARD: (? means a positive number, usually 1 or 2, * means any number)\n");
        MOSTLY_ASYNC_SAFE_PRINTF ("\t0x0\t- starting (GOOD, unless the thread is running managed code)\n");
        MOSTLY_ASYNC_SAFE_PRINTF ("\t0x1\t- running (BAD, unless it's the gc thread)\n");
        MOSTLY_ASYNC_SAFE_PRINTF ("\t0x2\t- detached (GOOD, unless the thread is running managed code)\n");
@@ -157,7 +157,7 @@ dump_threads (void)
        MOSTLY_ASYNC_SAFE_PRINTF ("\t0x?04\t- self suspended (GOOD)\n");
        MOSTLY_ASYNC_SAFE_PRINTF ("\t0x?05\t- async suspend requested (BAD)\n");
        MOSTLY_ASYNC_SAFE_PRINTF ("\t0x?06\t- self suspend requested (BAD)\n");
-       MOSTLY_ASYNC_SAFE_PRINTF ("\t0x07\t- blocking (GOOD)\n");
+       MOSTLY_ASYNC_SAFE_PRINTF ("\t0x*07\t- blocking (GOOD)\n");
        MOSTLY_ASYNC_SAFE_PRINTF ("\t0x?08\t- blocking with pending suspend (GOOD)\n");
 
        FOREACH_THREAD_SAFE (info) {
@@ -362,9 +362,9 @@ unregister_thread (void *arg)
        This ensures that we won't lose any suspend requests as a suspend initiator must hold the lock.
        Once we're holding the suspend lock, no threads can suspend us and once we unregister, no thread can find us. 
        */
-       MONO_PREPARE_BLOCKING
+       MONO_PREPARE_BLOCKING;
        mono_thread_info_suspend_lock ();
-       MONO_FINISH_BLOCKING
+       MONO_FINISH_BLOCKING;
 
        /*
        Now perform the callback that must be done under locks.
@@ -681,7 +681,7 @@ mono_thread_info_end_self_suspend (void)
                return;
        THREADS_SUSPEND_DEBUG ("FINISH SELF SUSPEND OF %p\n", info);
 
-       g_assert (mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX], NULL));
+       mono_threads_get_runtime_callbacks ()->thread_state_init (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX]);
 
        /* commit the saved state and notify others if needed */
        switch (mono_threads_transition_state_poll (info)) {
@@ -1153,42 +1153,204 @@ mono_thread_info_set_name (MonoNativeThreadId tid, const char *name)
        mono_threads_core_set_name (tid, name);
 }
 
+#define INTERRUPT_STATE ((MonoThreadInfoInterruptToken*) (size_t) -1)
+
+struct _MonoThreadInfoInterruptToken {
+       void (*callback) (gpointer data);
+       gpointer data;
+};
+
 /*
- * mono_thread_info_prepare_interrupt:
+ * mono_thread_info_install_interrupt: install an interruption token for the current thread.
  *
- *   See wapi_prepare_interrupt ().
+ *  - @callback: must be able to be called from another thread and always cancel the wait
+ *  - @data: passed to the callback
+ *  - @interrupted: will be set to TRUE if a token is already installed, FALSE otherwise
+ *     if set to TRUE, it must mean that the thread is in interrupted state
  */
-gpointer
-mono_thread_info_prepare_interrupt (HANDLE thread_handle)
+void
+mono_thread_info_install_interrupt (void (*callback) (gpointer data), gpointer data, gboolean *interrupted)
 {
-       return mono_threads_core_prepare_interrupt (thread_handle);
+       MonoThreadInfo *info;
+       MonoThreadInfoInterruptToken *previous_token, *token;
+
+       g_assert (callback);
+
+       g_assert (interrupted);
+       *interrupted = FALSE;
+
+       info = mono_thread_info_current ();
+       g_assert (info);
+
+       /* The memory of this token can be freed at 2 places:
+        *  - if the token is not interrupted: it will be freed in uninstall, as info->interrupt_token has not been replaced
+        *     by the INTERRUPT_STATE flag value, and it still contains the pointer to the memory location
+        *  - if the token is interrupted: it will be freed in finish, as the token is now owned by the prepare/finish
+        *     functions, and info->interrupt_token does not contains a pointer to the memory anymore */
+       token = g_new0 (MonoThreadInfoInterruptToken, 1);
+       token->callback = callback;
+       token->data = data;
+
+       previous_token = InterlockedCompareExchangePointer ((gpointer*) &info->interrupt_token, token, NULL);
+
+       if (previous_token) {
+               if (previous_token != INTERRUPT_STATE)
+                       g_error ("mono_thread_info_install_interrupt: previous_token should be INTERRUPT_STATE (%p), but it was %p", INTERRUPT_STATE, previous_token);
+
+               g_free (token);
+
+               *interrupted = TRUE;
+       }
+
+       THREADS_INTERRUPT_DEBUG ("interrupt install    tid %p token %p previous_token %p interrupted %s\n",
+               mono_thread_info_get_tid (info), token, previous_token, *interrupted ? "TRUE" : "FALSE");
 }
 
 void
-mono_thread_info_finish_interrupt (gpointer wait_handle)
+mono_thread_info_uninstall_interrupt (gboolean *interrupted)
+{
+       MonoThreadInfo *info;
+       MonoThreadInfoInterruptToken *previous_token;
+
+       g_assert (interrupted);
+       *interrupted = FALSE;
+
+       info = mono_thread_info_current ();
+       g_assert (info);
+
+       previous_token = InterlockedExchangePointer ((gpointer*) &info->interrupt_token, NULL);
+
+       /* only the installer can uninstall the token */
+       g_assert (previous_token);
+
+       if (previous_token == INTERRUPT_STATE) {
+               /* if it is interrupted, then it is going to be freed in finish interrupt */
+               *interrupted = TRUE;
+       } else {
+               g_free (previous_token);
+       }
+
+       THREADS_INTERRUPT_DEBUG ("interrupt uninstall  tid %p previous_token %p interrupted %s\n",
+               mono_thread_info_get_tid (info), previous_token, *interrupted ? "TRUE" : "FALSE");
+}
+
+static MonoThreadInfoInterruptToken*
+set_interrupt_state (MonoThreadInfo *info)
+{
+       MonoThreadInfoInterruptToken *token, *previous_token;
+
+       g_assert (info);
+
+       /* Atomically obtain the token the thread is
+       * waiting on, and change it to a flag value. */
+
+       do {
+               previous_token = info->interrupt_token;
+
+               /* Already interrupted */
+               if (previous_token == INTERRUPT_STATE) {
+                       token = NULL;
+                       break;
+               }
+
+               token = previous_token;
+       } while (InterlockedCompareExchangePointer ((gpointer*) &info->interrupt_token, INTERRUPT_STATE, previous_token) != previous_token);
+
+       return token;
+}
+
+/*
+ * mono_thread_info_prepare_interrupt:
+ *
+ * The state of the thread info interrupt token is set to 'interrupted' which means that :
+ *  - if the thread calls one of the WaitFor functions, the function will return with
+ *     WAIT_IO_COMPLETION instead of waiting
+ *  - if the thread was waiting when this function was called, the wait will be broken
+ *
+ * It is possible that the wait functions return WAIT_IO_COMPLETION, but the target thread
+ * didn't receive the interrupt signal yet, in this case it should call the wait function
+ * again. This essentially means that the target thread will busy wait until it is ready to
+ * process the interruption.
+ */
+MonoThreadInfoInterruptToken*
+mono_thread_info_prepare_interrupt (MonoThreadInfo *info)
 {
-       mono_threads_core_finish_interrupt (wait_handle);
+       MonoThreadInfoInterruptToken *token;
+
+       token = set_interrupt_state (info);
+
+       THREADS_INTERRUPT_DEBUG ("interrupt prepare    tid %p token %p\n",
+               mono_thread_info_get_tid (info), token);
+
+       return token;
 }
 
 void
-mono_thread_info_interrupt (HANDLE thread_handle)
+mono_thread_info_finish_interrupt (MonoThreadInfoInterruptToken *token)
 {
-       gpointer wait_handle;
+       THREADS_INTERRUPT_DEBUG ("interrupt finish     token %p\n", token);
 
-       wait_handle = mono_thread_info_prepare_interrupt (thread_handle);
-       mono_thread_info_finish_interrupt (wait_handle);
+       if (token == NULL)
+               return;
+
+       g_assert (token->callback);
+
+       token->callback (token->data);
+
+       g_free (token);
 }
-       
+
 void
 mono_thread_info_self_interrupt (void)
 {
-       mono_threads_core_self_interrupt ();
+       MonoThreadInfo *info;
+       MonoThreadInfoInterruptToken *token;
+
+       info = mono_thread_info_current ();
+       g_assert (info);
+
+       token = set_interrupt_state (info);
+       g_assert (!token);
+
+       THREADS_INTERRUPT_DEBUG ("interrupt self       tid %p\n",
+               mono_thread_info_get_tid (info));
+}
+
+/* Clear the interrupted flag of the current thread, set with
+ * mono_thread_info_self_interrupt, so it can wait again */
+void
+mono_thread_info_clear_self_interrupt ()
+{
+       MonoThreadInfo *info;
+       MonoThreadInfoInterruptToken *previous_token;
+
+       info = mono_thread_info_current ();
+       g_assert (info);
+
+       previous_token = InterlockedCompareExchangePointer ((gpointer*) &info->interrupt_token, NULL, INTERRUPT_STATE);
+       g_assert (previous_token == NULL || previous_token == INTERRUPT_STATE);
+
+       THREADS_INTERRUPT_DEBUG ("interrupt clear self tid %p previous_token %p\n", mono_thread_info_get_tid (info), previous_token);
+}
+
+gboolean
+mono_thread_info_is_interrupt_state (MonoThreadInfo *info)
+{
+       g_assert (info);
+       return InterlockedReadPointer ((gpointer*) &info->interrupt_token) == INTERRUPT_STATE;
 }
 
 void
-mono_thread_info_clear_interruption (void)
+mono_thread_info_describe_interrupt_token (MonoThreadInfo *info, GString *text)
 {
-       mono_threads_core_clear_interruption ();
+       g_assert (info);
+
+       if (!InterlockedReadPointer ((gpointer*) &info->interrupt_token))
+               g_string_append_printf (text, "not waiting");
+       else if (InterlockedReadPointer ((gpointer*) &info->interrupt_token) == INTERRUPT_STATE)
+               g_string_append_printf (text, "interrupted state");
+       else
+               g_string_append_printf (text, "waiting");
 }
 
 /* info must be self or be held in a hazard pointer. */
index edbf934ac9bf7321a524a47459231121c00d9f40..7e00c04659582cd3a6a99db597974827f95029e2 100644 (file)
@@ -117,6 +117,12 @@ and reduce the number of casts drastically.
 #define THREADS_STATE_MACHINE_DEBUG MOSTLY_ASYNC_SAFE_PRINTF
 #endif
 
+#if 1
+#define THREADS_INTERRUPT_DEBUG(...)
+#else
+#define THREADS_INTERRUPT_DEBUG MOSTLY_ASYNC_SAFE_PRINTF
+#endif
+
 /* If this is defined, use the signals backed on Mach. Debug only as signals can't be made usable on OSX. */
 // #define USE_SIGNALS_ON_MACH
 
@@ -170,6 +176,8 @@ typedef enum {
        MONO_SERVICE_REQUEST_SAMPLE = 1,
 } MonoAsyncJob;
 
+typedef struct _MonoThreadInfoInterruptToken MonoThreadInfoInterruptToken;
+
 typedef struct {
        MonoLinkedListSetNode node;
        guint32 small_id; /*Used by hazard pointers */
@@ -243,6 +251,8 @@ typedef struct {
        volatile gint32 service_requests;
 
        void *jit_data;
+
+       MonoThreadInfoInterruptToken *interrupt_token;
 } MonoThreadInfo;
 
 typedef struct {
@@ -270,6 +280,7 @@ typedef struct {
        void (*setup_async_callback) (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data);
        gboolean (*thread_state_init_from_sigctx) (MonoThreadUnwindState *state, void *sigctx);
        gboolean (*thread_state_init_from_handle) (MonoThreadUnwindState *tctx, MonoThreadInfo *info);
+       void (*thread_state_init) (MonoThreadUnwindState *tctx);
 } MonoThreadInfoRuntimeCallbacks;
 
 //Not using 0 and 1 to ensure callbacks are not returning bad data
@@ -401,20 +412,29 @@ mono_thread_info_exit (void);
 HANDLE
 mono_thread_info_open_handle (void);
 
-gpointer
-mono_thread_info_prepare_interrupt (HANDLE thread_handle);
+void
+mono_thread_info_install_interrupt (void (*callback) (gpointer data), gpointer data, gboolean *interrupted);
 
 void
-mono_thread_info_finish_interrupt (gpointer wait_handle);
+mono_thread_info_uninstall_interrupt (gboolean *interrupted);
+
+MonoThreadInfoInterruptToken*
+mono_thread_info_prepare_interrupt (THREAD_INFO_TYPE *info);
 
 void
-mono_thread_info_interrupt (HANDLE thread_handle);
+mono_thread_info_finish_interrupt (MonoThreadInfoInterruptToken *token);
 
 void
 mono_thread_info_self_interrupt (void);
 
 void
-mono_thread_info_clear_interruption (void);
+mono_thread_info_clear_self_interrupt (void);
+
+gboolean
+mono_thread_info_is_interrupt_state (THREAD_INFO_TYPE *info);
+
+void
+mono_thread_info_describe_interrupt_token (THREAD_INFO_TYPE *info, GString *text);
 
 gboolean
 mono_thread_info_is_live (THREAD_INFO_TYPE *info);
@@ -457,7 +477,6 @@ gboolean mono_threads_core_suspend (THREAD_INFO_TYPE *info, gboolean interrupt_k
 gboolean mono_threads_core_resume (THREAD_INFO_TYPE *info);
 void mono_threads_platform_register (THREAD_INFO_TYPE *info); //ok
 void mono_threads_platform_free (THREAD_INFO_TYPE *info);
-void mono_threads_core_interrupt (THREAD_INFO_TYPE *info);
 void mono_threads_core_abort_syscall (THREAD_INFO_TYPE *info);
 gboolean mono_threads_core_needs_abort_syscall (void);
 HANDLE mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid);
@@ -523,10 +542,6 @@ void mono_threads_core_unregister (THREAD_INFO_TYPE *info);
 HANDLE mono_threads_core_open_handle (void);
 HANDLE mono_threads_core_open_thread_handle (HANDLE handle, MonoNativeThreadId tid);
 void mono_threads_core_set_name (MonoNativeThreadId tid, const char *name);
-gpointer mono_threads_core_prepare_interrupt (HANDLE thread_handle);
-void mono_threads_core_finish_interrupt (gpointer wait_handle);
-void mono_threads_core_self_interrupt (void);
-void mono_threads_core_clear_interruption (void);
 
 MonoNativeThreadId mono_native_thread_id_get (void);