From 19f49f93f9ec66cfd54b458796c3b0800d6fb9c3 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 25 Apr 2014 16:57:01 +0200 Subject: [PATCH] Revert "Revert "Merge branch 'master' of https://github.com/mono/mono"" This reverts commit 8f09dad4353bb75afebf96ad58d08f7e7f3bf56d. 8f09dad4353bb75afebf96ad58d08f7e7f3bf56d is reverting a merge commit, which will not do what you think it does. It will revert much more, so revert the revert to get back the unintentionally reverted commits. It looks like the next commit (1a15d4ec541eaf20ed78eac53149b1b83e1450fe) is doing the original intention (reverting 164f9cbec4f79cc013c7b1cf674e70e4573f4b36), so this revert will leave the tree in a good state, with no pending reverts. --- acinclude.m4 | 2 +- configure.in | 30 +- eglib/configure.ac | 2 +- mcs/class/Mono.CSharp/monotouch.cs | 5 + .../Mono.Debugger.Soft/Connection.cs | 2 +- .../Mono.Debugger.Soft/StepEventRequest.cs | 3 + .../Mono.Debugger.Soft/Test/dtest-app.cs | 25 ++ mcs/class/Mono.Debugger.Soft/Test/dtest.cs | 17 + mcs/class/System.Core/System/TimeZoneInfo.cs | 60 ++- .../Test/System/TimeZoneInfoTest.cs | 107 +++++ .../System/System.Net/HttpWebResponse.cs | 29 +- mono/arch/Makefile.am | 2 +- mono/arch/arm64/Makefile.am | 0 mono/arch/arm64/arm64-codegen.h | 3 + mono/metadata/domain-internals.h | 2 + mono/metadata/mono-config.c | 3 + mono/metadata/sgen-archdep.h | 20 + mono/metadata/sgen-stw.c | 2 +- mono/mini/Makefile.am.in | 16 + mono/mini/aot-compiler.c | 61 ++- mono/mini/aot-runtime.c | 30 +- mono/mini/cpu-arm64.md | 424 ++++++++++++++++++ mono/mini/debugger-agent.c | 31 +- mono/mini/exceptions-arm64.c | 1 + mono/mini/genmdesc.pl | 5 +- mono/mini/helpers.c | 12 +- mono/mini/image-writer.c | 10 +- mono/mini/method-to-ir.c | 24 +- mono/mini/mini-arch.h | 2 + mono/mini/mini-arm64.c | 1 + mono/mini/mini-arm64.h | 1 + mono/mini/mini-codegen.c | 5 +- mono/mini/mini-gc.c | 3 + mono/mini/mini-ops.h | 13 +- mono/mini/mini-trampolines.c | 6 +- mono/mini/mini.c | 4 +- mono/mini/mini.h | 2 +- mono/mini/tramp-arm64.c | 1 + mono/mini/unwind.c | 9 + mono/tests/Makefile.am | 10 +- mono/utils/Makefile.am | 8 + mono/utils/mach-support-arm.c | 49 +- mono/utils/mach-support.h | 2 + mono/utils/mono-codeman.c | 3 + mono/utils/mono-compiler.h | 4 + mono/utils/mono-context.c | 32 ++ mono/utils/mono-context.h | 51 +++ mono/utils/mono-hwcap-arm64.c | 24 + mono/utils/mono-hwcap-arm64.h | 6 + mono/utils/mono-sigcontext.h | 24 + mono/utils/mono-threads-mach-helper.c | 25 +- mono/utils/mono-threads-mach.c | 4 + 52 files changed, 1146 insertions(+), 71 deletions(-) create mode 100644 mono/arch/arm64/Makefile.am create mode 100644 mono/arch/arm64/arm64-codegen.h create mode 100644 mono/mini/cpu-arm64.md create mode 100644 mono/mini/exceptions-arm64.c create mode 100644 mono/mini/mini-arm64.c create mode 100644 mono/mini/mini-arm64.h create mode 100644 mono/mini/tramp-arm64.c create mode 100644 mono/utils/mono-hwcap-arm64.c create mode 100644 mono/utils/mono-hwcap-arm64.h diff --git a/acinclude.m4 b/acinclude.m4 index 5b38b2fe3ef..16fecf7f860 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -23,7 +23,7 @@ if test x$GCC != xyes; then fi case $host in i?86-*-linux*|x86_64-*-linux*|powerpc-*-linux*|powerpc64-*-linux* \ -|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*) +|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*) pic_options='-fPIC' ;; ?86-pc-cygwin*|i?86-pc-cygwin*) diff --git a/configure.in b/configure.in index dd09f8fa3c7..1f1e4ffc1f4 100644 --- a/configure.in +++ b/configure.in @@ -237,6 +237,12 @@ case "$host" in # available during cross-compilation mono_cv_uscore=no fi + case "$host" in + aarch64-*) + support_boehm=no + with_gc=sgen + ;; + esac ;; *-*-nacl*) host_win32=no @@ -2507,6 +2513,7 @@ sizeof_register="SIZEOF_VOID_P" jit_wanted=true interp_wanted=false sgen_supported=false +boehm_supported=true case "$host" in mips*) TARGET=MIPS; @@ -2683,6 +2690,14 @@ case "$host" in # sgen_supported=true # AOT_SUPPORTED="no" # ;; + aarch64-*) + # https://lkml.org/lkml/2012/7/15/133 + TARGET=ARM64 + arch_target=arm64 + JIT_SUPPORTED=yes + sgen_supported=true + boehm_supported=false + ;; s390x-*-linux*) TARGET=S390X; arch_target=s390x; @@ -2788,6 +2803,11 @@ if test "x$host" != "x$target"; then ;; esac ;; + aarch64-*) + TARGET=ARM64 + JIT_SUPPORTED=yes + jit_wanted=true + ;; *) AC_MSG_ERROR([Cross compiling is not supported for target $target]) esac @@ -2803,6 +2823,9 @@ AMD64) ARM) AC_DEFINE(TARGET_ARM, 1, [...]) ;; +ARM64) + AC_DEFINE(TARGET_ARM64, 1, [...]) + ;; POWERPC) AC_DEFINE(TARGET_POWERPC, 1, [...]) ;; @@ -2830,14 +2853,14 @@ esac dnl Use GCC atomic ops if they work on the target. if test x$GCC = "xyes"; then case $TARGET in - X86 | AMD64 | ARM | POWERPC | POWERPC64 | MIPS | S390X | SPARC | SPARC64) + X86 | AMD64 | ARM | ARM64 | POWERPC | POWERPC64 | MIPS | S390X | SPARC | SPARC64) AC_DEFINE(USE_GCC_ATOMIC_OPS, 1, [...]) ;; esac fi if test "x$target_mach" = "xyes"; then - if test "x$TARGET" = "xARM"; then + if test "x$TARGET" = "xARM" -o "x$TARGET" = "xARM64"; then AC_DEFINE(TARGET_IOS,1,[The JIT/AOT targets iOS]) CPPFLAGS_FOR_LIBGC="$CPPFLAGS_FOR_LIBGC -DTARGET_IOS" CFLAGS_FOR_LIBGC="$CFLAGS_FOR_LIBGC -DTARGET_IOS" @@ -3304,10 +3327,12 @@ AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS) AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC) AM_CONDITIONAL(POWERPC64, test x$TARGET = xPOWERPC64) AM_CONDITIONAL(ARM, test x$TARGET = xARM) +AM_CONDITIONAL(ARM64, test x$TARGET = xARM64) AM_CONDITIONAL(S390X, test x$TARGET = xS390X) AM_CONDITIONAL(HOST_X86, test x$HOST = xX86) AM_CONDITIONAL(HOST_AMD64, test x$HOST = xAMD64) AM_CONDITIONAL(HOST_ARM, test x$HOST = xARM) +AM_CONDITIONAL(HOST_ARM64, test x$HOST = xARM64) AM_CONDITIONAL(CROSS_COMPILE, test "x$host" != "x$target") AM_CONDITIONAL(JIT_SUPPORTED, test x$JIT_SUPPORTED = xyes) @@ -3526,6 +3551,7 @@ mono/arch/ppc/Makefile mono/arch/sparc/Makefile mono/arch/s390x/Makefile mono/arch/arm/Makefile +mono/arch/arm64/Makefile mono/arch/ia64/Makefile mono/arch/mips/Makefile mono/interpreter/Makefile diff --git a/eglib/configure.ac b/eglib/configure.ac index fdbce134b97..f8853385a8d 100644 --- a/eglib/configure.ac +++ b/eglib/configure.ac @@ -88,7 +88,7 @@ case $host in esac case $target in -arm*-darwin*) +arm*-darwin*|aarch64*-*) CFLAGS="$CFLAGS -U_FORTIFY_SOURCE" ;; i*86-*-darwin*) diff --git a/mcs/class/Mono.CSharp/monotouch.cs b/mcs/class/Mono.CSharp/monotouch.cs index fed14757214..a8260819907 100644 --- a/mcs/class/Mono.CSharp/monotouch.cs +++ b/mcs/class/Mono.CSharp/monotouch.cs @@ -40,6 +40,11 @@ namespace System.Reflection.Emit throw new NotSupportedException (); } + public void BeginExceptFilterBlock () + { + throw new NotSupportedException (); + } + public void BeginFinallyBlock () { throw new NotSupportedException (); diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs index 7b69efb22b8..60b7e2c384c 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs @@ -411,7 +411,7 @@ namespace Mono.Debugger.Soft * with newer runtimes, and vice versa. */ internal const int MAJOR_VERSION = 2; - internal const int MINOR_VERSION = 29; + internal const int MINOR_VERSION = 30; enum WPSuspendPolicy { NONE = 0, diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs index 035fbcee56d..3bf93807ae5 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs @@ -28,6 +28,9 @@ namespace Mono.Debugger.Soft /* Since protocol version 2.26 */ /* Methods which have the [DebuggerStepThrough] attribute */ DebuggerStepThrough = 4, + /* Since protocol version 2.30 */ + /* Methods which have the [DebuggerNonUserCode] attribute */ + DebuggerNonUserCode = 8 } public sealed class StepEventRequest : EventRequest { diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs index 194b436f080..4397ab005bf 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs @@ -362,6 +362,7 @@ public class Tests : TestsBase, ITest2 ss_nested (); ss_regress_654694 (); ss_step_through (); + ss_non_user_code (); ss_recursive (1); ss_fp_clobber (); } @@ -481,6 +482,30 @@ public class Tests : TestsBase, ITest2 public static void step_through_3 () { } + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void ss_non_user_code () { + non_user_code_1 (); + StepNonUserCodeClass.non_user_code_2 (); + non_user_code_3 (); + } + + [DebuggerNonUserCode] + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void non_user_code_1 () { + } + + [DebuggerNonUserCode] + class StepNonUserCodeClass { + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void non_user_code_2 () { + } + } + + [DebuggerNonUserCode] + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void non_user_code_3 () { + } + [MethodImplAttribute (MethodImplOptions.NoInlining)] public static void ss_recursive (int n) { if (n == 10) diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs index 901d56adc92..86e533b4aea 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs @@ -542,6 +542,23 @@ public class DebuggerTests assert_location (e, "step_through_3"); req.Disable (); + // Check DebuggerNonUserCode support + e = run_until ("ss_non_user_code"); + req = create_step (e); + req.Filter = StepFilter.DebuggerNonUserCode; + e = step_into (); + // Step through non_user_code_1 () + e = step_into (); + assert_location (e, "ss_non_user_code"); + // Step through StepThroughClass.non_user_code_2 () + e = step_into (); + assert_location (e, "ss_non_user_code"); + req.Disable (); + req.Filter = StepFilter.None; + e = step_into (); + assert_location (e, "non_user_code_3"); + req.Disable (); + // Check that step-over doesn't stop at inner frames with recursive functions e = run_until ("ss_recursive"); req = create_step (e); diff --git a/mcs/class/System.Core/System/TimeZoneInfo.cs b/mcs/class/System.Core/System/TimeZoneInfo.cs index 4dbaf3eeb88..bdcda565469 100644 --- a/mcs/class/System.Core/System/TimeZoneInfo.cs +++ b/mcs/class/System.Core/System/TimeZoneInfo.cs @@ -227,36 +227,38 @@ namespace System public static DateTime ConvertTime (DateTime dateTime, TimeZoneInfo destinationTimeZone) { - return ConvertTime (dateTime, TimeZoneInfo.Local, destinationTimeZone); + return ConvertTime (dateTime, dateTime.Kind == DateTimeKind.Utc ? TimeZoneInfo.Utc : TimeZoneInfo.Local, destinationTimeZone); } public static DateTime ConvertTime (DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone) { + if (sourceTimeZone == null) + throw new ArgumentNullException ("sourceTimeZone"); + + if (destinationTimeZone == null) + throw new ArgumentNullException ("destinationTimeZone"); + if (dateTime.Kind == DateTimeKind.Local && sourceTimeZone != TimeZoneInfo.Local) throw new ArgumentException ("Kind property of dateTime is Local but the sourceTimeZone does not equal TimeZoneInfo.Local"); if (dateTime.Kind == DateTimeKind.Utc && sourceTimeZone != TimeZoneInfo.Utc) throw new ArgumentException ("Kind property of dateTime is Utc but the sourceTimeZone does not equal TimeZoneInfo.Utc"); - + if (sourceTimeZone.IsInvalidTime (dateTime)) throw new ArgumentException ("dateTime parameter is an invalid time"); - if (sourceTimeZone == null) - throw new ArgumentNullException ("sourceTimeZone"); - - if (destinationTimeZone == null) - throw new ArgumentNullException ("destinationTimeZone"); - if (dateTime.Kind == DateTimeKind.Local && sourceTimeZone == TimeZoneInfo.Local && destinationTimeZone == TimeZoneInfo.Local) return dateTime; DateTime utc = ConvertTimeToUtc (dateTime); - if (destinationTimeZone == TimeZoneInfo.Utc) - return utc; - - return ConvertTimeFromUtc (utc, destinationTimeZone); - + if (destinationTimeZone != TimeZoneInfo.Utc) { + utc = ConvertTimeFromUtc (utc, destinationTimeZone); + if (dateTime.Kind == DateTimeKind.Unspecified) + return DateTime.SpecifyKind (utc, DateTimeKind.Unspecified); + } + + return utc; } public static DateTimeOffset ConvertTime(DateTimeOffset dateTimeOffset, TimeZoneInfo destinationTimeZone) @@ -311,7 +313,6 @@ namespace System AdjustmentRule rule = GetApplicableRule (dateTime); - if (rule != null && IsDaylightSavingTime (DateTime.SpecifyKind (dateTime, DateTimeKind.Utc))) return DateTime.SpecifyKind (dateTime + BaseUtcOffset + rule.DaylightDelta , DateTimeKind.Unspecified); else @@ -754,6 +755,18 @@ namespace System throw new NotImplementedException (); } + bool IsInDSTForYear (AdjustmentRule rule, DateTime dateTime, int year) + { + DateTime DST_start = TransitionPoint (rule.DaylightTransitionStart, year); + DateTime DST_end = TransitionPoint (rule.DaylightTransitionEnd, year + ((rule.DaylightTransitionStart.Month < rule.DaylightTransitionEnd.Month) ? 0 : 1)); + if (dateTime.Kind == DateTimeKind.Utc) { + DST_start -= BaseUtcOffset; + DST_end -= (BaseUtcOffset + rule.DaylightDelta); + } + + return (dateTime >= DST_start && dateTime < DST_end); + } + public bool IsDaylightSavingTime (DateTime dateTime) { if (dateTime.Kind == DateTimeKind.Local && IsInvalidTime (dateTime)) @@ -761,29 +774,28 @@ namespace System if (this == TimeZoneInfo.Utc) return false; - + if (!SupportsDaylightSavingTime) return false; + //FIXME: do not rely on DateTime implementation ! if ((dateTime.Kind == DateTimeKind.Local || dateTime.Kind == DateTimeKind.Unspecified) && this == TimeZoneInfo.Local) return dateTime.IsDaylightSavingTime (); - + //FIXME: do not rely on DateTime implementation ! if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Utc) return IsDaylightSavingTime (DateTime.SpecifyKind (dateTime.ToUniversalTime (), DateTimeKind.Utc)); - + AdjustmentRule rule = GetApplicableRule (dateTime.Date); if (rule == null) return false; - DateTime DST_start = TransitionPoint (rule.DaylightTransitionStart, dateTime.Year); - DateTime DST_end = TransitionPoint (rule.DaylightTransitionEnd, dateTime.Year + ((rule.DaylightTransitionStart.Month < rule.DaylightTransitionEnd.Month) ? 0 : 1)); - if (dateTime.Kind == DateTimeKind.Utc) { - DST_start -= BaseUtcOffset; - DST_end -= (BaseUtcOffset + rule.DaylightDelta); - } + // Check whether we're in the dateTime year's DST period + if (IsInDSTForYear (rule, dateTime, dateTime.Year)) + return true; - return (dateTime >= DST_start && dateTime < DST_end); + // We might be in the dateTime previous year's DST period + return IsInDSTForYear (rule, dateTime, dateTime.Year - 1); } public bool IsDaylightSavingTime (DateTimeOffset dateTimeOffset) diff --git a/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs b/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs index d6a66d79ba7..f6ea66e98c6 100644 --- a/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs +++ b/mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs @@ -263,6 +263,30 @@ namespace MonoTests.System } } #endif + [Test (Description="Description xambug #17155")] + public void AdjustmentRuleAfterNewYears () + { + TimeZoneInfo tz; + if (Environment.OSVersion.Platform == PlatformID.Unix) + tz = TimeZoneInfo.FindSystemTimeZoneById ("Pacific/Auckland"); // *nix + else + tz = TimeZoneInfo.FindSystemTimeZoneById ("New Zealand Standard Time"); // Windows + + // DST start: 9/29/2013 2:00:00 AM + // DST end: 4/6/2014 3:00:00 AM + DateTime dt = new DateTime (2014, 1, 9, 23, 0, 0, DateTimeKind.Utc); + Assert.IsTrue (tz.IsDaylightSavingTime (dt), "#1.1"); + + // DST start: 9/29/2014 2:00:00 AM + // DST end: 4/6/2015 3:00:00 AM + dt = new DateTime (2014, 6, 9, 23, 0, 0, DateTimeKind.Utc); + Assert.IsFalse (tz.IsDaylightSavingTime (dt), "#2.1"); + + // DST start: 9/29/2014 2:00:00 AM + // DST end: 4/6/2015 3:00:00 AM + dt = new DateTime (2014, 10, 9, 23, 0, 0, DateTimeKind.Utc); + Assert.IsTrue (tz.IsDaylightSavingTime (dt), "#3.1"); + } } [TestFixture] @@ -412,6 +436,89 @@ namespace MonoTests.System TimeZoneInfo.ConvertTime (DateTime.Now, TimeZoneInfo.FindSystemTimeZoneById("Pacific/Auckland")); } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void ConvertTime_DateTime_TimeZoneInfo_DestinationTimeZoneIsNull () + { + TimeZoneInfo.ConvertTime (DateTime.Now, null); + } + + [Test] + public void ConvertTime_DateTime_TimeZoneInfo_DateTimeKindMatch () + { + var sdt = new DateTime (2014, 1, 9, 23, 0, 0, DateTimeKind.Utc); + var ddt = TimeZoneInfo.ConvertTime (sdt, TimeZoneInfo.Utc); + Assert.AreEqual (ddt.Kind, sdt.Kind, "#1.1"); + Assert.AreEqual (ddt.Kind, DateTimeKind.Utc, "#1.2"); + + sdt = new DateTime (2014, 1, 9, 23, 0, 0, DateTimeKind.Local); + ddt = TimeZoneInfo.ConvertTime (sdt, TimeZoneInfo.Local); + Assert.AreEqual (ddt.Kind, sdt.Kind, "#2.1"); + Assert.AreEqual (ddt.Kind, DateTimeKind.Local, "#2.2"); + + sdt = new DateTime (2014, 1, 9, 23, 0, 0); + ddt = TimeZoneInfo.ConvertTime (sdt, TimeZoneInfo.Local); + Assert.AreEqual (ddt.Kind, sdt.Kind, "#3.1"); + Assert.AreEqual (ddt.Kind, DateTimeKind.Unspecified, "#3.2"); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void ConverTime_DateTime_TimeZoneInfo_TimeZoneInfo_SourceTimeZoneIsNull () + { + TimeZoneInfo.ConvertTime (DateTime.Now, null, TimeZoneInfo.Local); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void ConverTime_DateTime_TimeZoneInfo_TimeZoneInfo_DestinationTimeZoneIsNull () + { + TimeZoneInfo.ConvertTime (DateTime.Now, TimeZoneInfo.Utc, null); + } + + [Test (Description="Fix for xambug https://bugzilla.xamarin.com/show_bug.cgi?id=17155")] + public void ConvertTime_AdjustmentRuleAfterNewYears () + { + TimeZoneInfo tz; + if (Environment.OSVersion.Platform == PlatformID.Unix) + tz = TimeZoneInfo.FindSystemTimeZoneById ("Pacific/Auckland"); // *nix + else + tz = TimeZoneInfo.FindSystemTimeZoneById ("New Zealand Standard Time"); // Windows + + // DST start: 9/29/2013 2:00:00 AM + // DST end: 4/6/2014 3:00:00 AM + DateTime sdt = new DateTime (2014, 1, 9, 23, 0, 0, DateTimeKind.Utc); + DateTime ddt = TimeZoneInfo.ConvertTime (sdt, tz); + Assert.AreEqual (10, ddt.Day, "#1.1"); + Assert.AreEqual (1, ddt.Month, "#1.2"); + Assert.AreEqual (2014, ddt.Year, "#1.3"); + Assert.AreEqual (12, ddt.Hour, "#1.4"); + Assert.AreEqual (0, ddt.Minute, "#1.5"); + Assert.AreEqual (0, ddt.Second, "#1.6"); + + // DST start: 9/29/2014 2:00:00 AM + // DST end: 4/6/2015 3:00:00 AM + sdt = new DateTime (2014, 6, 9, 23, 0, 0, DateTimeKind.Utc); + ddt = TimeZoneInfo.ConvertTime (sdt, tz); + Assert.AreEqual (10, ddt.Day, "#2.1"); + Assert.AreEqual (6, ddt.Month, "#2.2"); + Assert.AreEqual (2014, ddt.Year, "#2.3"); + Assert.AreEqual (11, ddt.Hour, "#2.4"); + Assert.AreEqual (0, ddt.Minute, "#2.5"); + Assert.AreEqual (0, ddt.Second, "#2.6"); + + // DST start: 9/29/2014 2:00:00 AM + // DST end: 4/6/2015 3:00:00 AM + sdt = new DateTime (2014, 10, 9, 23, 0, 0, DateTimeKind.Utc); + ddt = TimeZoneInfo.ConvertTime (sdt, tz); + Assert.AreEqual (10, ddt.Day, "#3.1"); + Assert.AreEqual (10, ddt.Month, "#3.2"); + Assert.AreEqual (2014, ddt.Year, "#3.3"); + Assert.AreEqual (12, ddt.Hour, "#3.4"); + Assert.AreEqual (0, ddt.Minute, "#3.5"); + Assert.AreEqual (0, ddt.Second, "#3.6"); + } } [TestFixture] diff --git a/mcs/class/System/System.Net/HttpWebResponse.cs b/mcs/class/System/System.Net/HttpWebResponse.cs index 2b756a97bd1..79e61a43624 100644 --- a/mcs/class/System/System.Net/HttpWebResponse.cs +++ b/mcs/class/System/System.Net/HttpWebResponse.cs @@ -347,22 +347,31 @@ namespace System.Net if (webHeaders == null) return; - string value = webHeaders.Get ("Set-Cookie"); - if (value != null) { - SetCookie (value); + // + // Don't terminate response reading on bad cookie value + // + string value; + try { + value = webHeaders.Get ("Set-Cookie"); + if (value != null && SetCookie (value)) + return; + } catch { } - value = webHeaders.Get ("Set-Cookie2"); - if (value != null) { - SetCookie (value); + try { + value = webHeaders.Get ("Set-Cookie2"); + if (value != null) + SetCookie (value); + } catch { } } - void SetCookie (string header) + bool SetCookie (string header) { if (cookieCollection == null) cookieCollection = new CookieCollection (); + bool at_least_one_set = false; var parser = new CookieParser (header); foreach (var cookie in parser.Parse ()) { if (cookie.Domain == "") { @@ -375,9 +384,13 @@ namespace System.Net continue; cookieCollection.Add (cookie); - if (cookie_container != null) + if (cookie_container != null) { cookie_container.Add (uri, cookie); + at_least_one_set = true; + } } + + return at_least_one_set; } } } diff --git a/mono/arch/Makefile.am b/mono/arch/Makefile.am index e7700ed3a61..3d687949f92 100644 --- a/mono/arch/Makefile.am +++ b/mono/arch/Makefile.am @@ -1,4 +1,4 @@ -DIST_SUBDIRS = x86 ppc sparc arm s390x amd64 ia64 mips +DIST_SUBDIRS = x86 ppc sparc arm arm64 s390x amd64 ia64 mips AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) diff --git a/mono/arch/arm64/Makefile.am b/mono/arch/arm64/Makefile.am new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mono/arch/arm64/arm64-codegen.h b/mono/arch/arm64/arm64-codegen.h new file mode 100644 index 00000000000..259ff967407 --- /dev/null +++ b/mono/arch/arm64/arm64-codegen.h @@ -0,0 +1,3 @@ +#include "../../../../mono-extensions/mono/arch/arm64/arm64-codegen.h" + + diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index a98b484b5ee..09c6479c03d 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -215,6 +215,8 @@ struct _MonoJitInfo { gboolean async:1; gboolean dbg_step_through_inited:1; gboolean dbg_step_through:1; + gboolean dbg_non_user_code_inited:1; + gboolean dbg_non_user_code:1; /* FIXME: Embed this after the structure later*/ gpointer gc_info; /* Currently only used by SGen */ diff --git a/mono/metadata/mono-config.c b/mono/metadata/mono-config.c index d0af8b07f61..5d7d9429b1d 100644 --- a/mono/metadata/mono-config.c +++ b/mono/metadata/mono-config.c @@ -75,6 +75,9 @@ #elif defined(__arm__) #define CONFIG_CPU "arm" #define CONFIG_WORDSIZE "32" +#elif defined(__aarch64__) +#define CONFIG_CPU "armv8" +#define CONFIG_WORDSIZE "64" #elif defined(__ia64__) #define CONFIG_CPU "ia64" #define CONFIG_WORDSIZE "64" diff --git a/mono/metadata/sgen-archdep.h b/mono/metadata/sgen-archdep.h index 5e7b5f8f1a3..b86ec318c7c 100755 --- a/mono/metadata/sgen-archdep.h +++ b/mono/metadata/sgen-archdep.h @@ -128,6 +128,26 @@ ((a)[13]) = (gpointer) (UCONTEXT_REG_LR((ctx))); \ } while (0) +#elif defined(TARGET_ARM64) + +#include + +#ifdef __linux__ +#define REDZONE_SIZE 0 +#elif defined(__APPLE__) +#define REDZONE_SIZE 128 +#else +#error "Not implemented." +#endif +#define USE_MONO_CTX +#define ARCH_NUM_REGS 31 + +#define ARCH_STORE_REGS(ptr) do { g_assert_not_reached (); } while (0) + +#define ARCH_SIGCTX_SP(ctx) UCONTEXT_REG_SP (ctx) +#define ARCH_SIGCTX_IP(ctx) UCONTEXT_REG_PC (ctx) +#define ARCH_COPY_SIGCTX_REGS(a,ctx) do { g_assert_not_reached (); } while (0) + #elif defined(__mips__) #define REDZONE_SIZE 0 diff --git a/mono/metadata/sgen-stw.c b/mono/metadata/sgen-stw.c index ed66db2ce5e..5a2ab0e9687 100755 --- a/mono/metadata/sgen-stw.c +++ b/mono/metadata/sgen-stw.c @@ -50,7 +50,7 @@ align_pointer (void *ptr) } #ifdef USE_MONO_CTX -static MonoContext cur_thread_ctx = {0}; +static MonoContext cur_thread_ctx; #else static mword cur_thread_regs [ARCH_NUM_REGS] = {0}; #endif diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index 55e5f14abf2..cd935b50bb7 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -317,6 +317,12 @@ arm_sources = \ exceptions-arm.c \ tramp-arm.c +arm64_sources = \ + mini-arm64.c \ + mini-arm64.h \ + exceptions-arm64.c \ + tramp-arm64.c + mips_sources = \ mini-mips.c \ mini-mips.h \ @@ -486,6 +492,12 @@ arch_built=cpu-arm.h arch_define=__arm__ endif +if ARM64 +arch_sources = $(arm64_sources) +arch_built=cpu-arm64.h +arch_define=__aarch64__ +endif + if SPARC arch_sources = $(sparc_sources) arch_built=cpu-sparc.h @@ -614,6 +626,9 @@ cpu-ppc64.h: cpu-ppc64.md genmdesc$(EXEEXT) cpu-arm.h: cpu-arm.md genmdesc$(EXEEXT) $(GENMDESC_PRG) cpu-arm.h arm_cpu_desc $(srcdir)/cpu-arm.md +cpu-arm64.h: cpu-arm64.md genmdesc$(EXEEXT) + $(GENMDESC_PRG) cpu-arm64.h arm64_cpu_desc $(srcdir)/cpu-arm64.md + cpu-sparc.h: cpu-sparc.md genmdesc$(EXEEXT) $(GENMDESC_PRG) cpu-sparc.h sparc_desc $(srcdir)/cpu-sparc.md @@ -718,6 +733,7 @@ EXTRA_DIST = TestDriver.cs ldscript ldscript.mono \ $(amd64_sources) cpu-amd64.md \ $(ppc_sources) cpu-ppc.md cpu-ppc64.md \ $(arm_sources) cpu-arm.md \ + $(arm64_sources) cpu-arm64.md \ $(mips_sources) cpu-mips.md \ $(sparc_sources) cpu-sparc.md \ $(s390x_sources) cpu-s390x.md \ diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index c28ec1d5b08..2cd4bb7311a 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -225,6 +225,7 @@ typedef struct MonoAotCompile { const char *temp_prefix; const char *user_symbol_prefix; const char *llvm_label_prefix; + const char *inst_directive; guint32 label_generator; gboolean llvm; MonoAotFileFlags flags; @@ -564,7 +565,16 @@ emit_set_arm_mode (MonoAotCompile *acfg) static inline void emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size) { +#ifdef TARGET_ARM64 + int i; + + g_assert (size % 4 == 0); + emit_unset_mode (acfg); + for (i = 0; i < size; i += 4) + fprintf (acfg->fp, "%s 0x%x\n", acfg->inst_directive, *(guint32*)(buf + i)); +#else emit_bytes (acfg, buf, size); +#endif } /* ARCHITECTURE SPECIFIC CODE */ @@ -603,6 +613,14 @@ emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size) #endif #endif +#ifdef TARGET_ARM64 +#ifdef TARGET_MACH +#define AOT_TARGET_STR "ARM64 (MACH)" +#else +#define AOT_TARGET_STR "ARM64 (!MACH)" +#endif +#endif + #ifdef TARGET_POWERPC64 #ifdef __mono_ilp32__ #define AOT_TARGET_STR "POWERPC64 (mono ilp32)" @@ -670,9 +688,16 @@ arch_init (MonoAotCompile *acfg) mono_arch_set_target (acfg->aot_opts.mtriple); #endif +#ifdef TARGET_ARM64 + acfg->inst_directive = ".inst"; + if (acfg->aot_opts.mtriple) + mono_arch_set_target (acfg->aot_opts.mtriple); +#endif + #ifdef TARGET_MACH acfg->user_symbol_prefix = "_"; acfg->llvm_label_prefix = "_"; + acfg->inst_directive = ".word"; acfg->need_no_dead_strip = TRUE; acfg->aot_opts.gnu_asm = TRUE; #endif @@ -687,6 +712,12 @@ arch_init (MonoAotCompile *acfg) #endif } +#ifdef TARGET_ARM64 + +#include "../../../mono-extensions/mono/mini/aot-compiler-arm64.c" + +#endif + #ifdef MONO_ARCH_AOT_SUPPORTED /* * arch_emit_direct_call: @@ -725,6 +756,8 @@ arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean extern fprintf (acfg->fp, "bl %s\n", target); } *call_size = 4; +#elif defined(TARGET_ARM64) + arm64_emit_direct_call (acfg, target, external, thumb, ji, call_size); #elif defined(TARGET_POWERPC) if (acfg->use_bin_writer) { g_assert_not_reached (); @@ -836,6 +869,8 @@ arch_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *cod #elif defined(TARGET_ARM) emit_symbol_diff (acfg, acfg->got_symbol, ".", (unsigned int) ((got_slot * sizeof (gpointer))) - 12); *code_size = mono_arch_get_patch_offset (code) + 4; +#elif defined(TARGET_ARM64) + arm64_emit_got_access (acfg, code, got_slot, code_size); #elif defined(TARGET_POWERPC) { guint8 buf [32]; @@ -879,6 +914,8 @@ arch_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int fprintf (acfg->fp, ".long %s-(%s+12)", symbol2, symbol1); *code_size = 12; +#elif defined(TARGET_ARM64) + arm64_emit_objc_selector_ref (acfg, code, index, code_size); #else g_assert_not_reached (); #endif @@ -961,6 +998,8 @@ arch_emit_plt_entry (MonoAotCompile *acfg, int index) emit_symbol_diff (acfg, acfg->got_symbol, ".", ((acfg->plt_got_offset_base + index) * sizeof (gpointer)) - 4); /* Used by mono_aot_get_plt_info_offset */ emit_int32 (acfg, acfg->plt_got_info_offsets [index]); +#elif defined(TARGET_ARM64) + arm64_emit_plt_entry (acfg, index); #elif defined(TARGET_POWERPC) guint32 offset = (acfg->plt_got_offset_base + index) * sizeof (gpointer); @@ -1195,6 +1234,8 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg) g_assert (code - buf == 8); emit_bytes (acfg, buf, code - buf); } +#elif defined(TARGET_ARM64) + arm64_emit_specific_trampoline_pages (acfg); #endif } @@ -1309,6 +1350,8 @@ arch_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size */ emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4 + 4); //emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (gpointer)) - 4 + 8); +#elif defined(TARGET_ARM64) + arm64_emit_specific_trampoline (acfg, offset, tramp_size); #elif defined(TARGET_POWERPC) guint8 buf [128]; guint8 *code; @@ -1456,6 +1499,8 @@ arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoCompile *cfg, MonoMethod * else fprintf (acfg->fp, "\n\tb %s\n", call_target); } +#elif defined(TARGET_ARM64) + arm64_emit_unbox_trampoline (acfg, cfg, method, call_target); #elif defined(TARGET_POWERPC) int this_pos = 3; @@ -1541,6 +1586,8 @@ arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_ emit_bytes (acfg, buf, code - buf); emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4 + 8); emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (gpointer)) - 4 + 4); +#elif defined(TARGET_ARM64) + arm64_emit_static_rgctx_trampoline (acfg, offset, tramp_size); #elif defined(TARGET_POWERPC) guint8 buf [128]; guint8 *code; @@ -1845,6 +1892,8 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size) emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) + (code - (labels [0] + 8)) - 4); *tramp_size = code - buf + 4; +#elif defined(TARGET_ARM64) + arm64_emit_imt_thunk (acfg, offset, tramp_size); #elif defined(TARGET_POWERPC) guint8 buf [128]; guint8 *code, *labels [16]; @@ -1960,6 +2009,8 @@ arch_emit_gsharedvt_arg_trampoline (MonoAotCompile *acfg, int offset, int *tramp /* Emit it */ emit_bytes (acfg, buf, code - buf); emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) + 4); +#elif defined(TARGET_ARM64) + arm64_emit_gsharedvt_arg_trampoline (acfg, offset, tramp_size); #else g_assert_not_reached (); #endif @@ -4494,7 +4545,11 @@ get_file_index (MonoAotCompile *acfg, const char *source_file) return findex; } +#ifdef TARGET_ARM64 +#define INST_LEN 4 +#else #define INST_LEN 1 +#endif /* * emit_and_reloc_code: @@ -6274,7 +6329,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) opts->direct_pinvoke = TRUE; } else if (str_begins_with (arg, "direct-icalls")) { opts->direct_icalls = TRUE; -#if defined(TARGET_ARM) +#if defined(TARGET_ARM) || defined(TARGET_ARM64) } else if (str_begins_with (arg, "iphone-abi")) { // older full-aot users did depend on this. #endif @@ -8268,7 +8323,7 @@ emit_objc_selectors (MonoAotCompile *acfg) img_writer_emit_unset_mode (acfg->w); g_assert (acfg->fp); fprintf (acfg->fp, ".section __DATA,__objc_selrefs,literal_pointers,no_dead_strip\n"); - fprintf (acfg->fp, ".align 2\n"); + fprintf (acfg->fp, ".align 3\n"); for (i = 0; i < acfg->objc_selectors->len; ++i) { fprintf (acfg->fp, "L_OBJC_SELECTOR_REFERENCES_%d:\n", i); fprintf (acfg->fp, ".long L_OBJC_METH_VAR_NAME_%d\n", i); @@ -8280,7 +8335,7 @@ emit_objc_selectors (MonoAotCompile *acfg) } fprintf (acfg->fp, ".section __DATA,__objc_imageinfo,regular,no_dead_strip\n"); - fprintf (acfg->fp, ".align 2\n"); + fprintf (acfg->fp, ".align 3\n"); fprintf (acfg->fp, "L_OBJC_IMAGE_INFO:\n"); fprintf (acfg->fp, ".long 0\n"); fprintf (acfg->fp, ".long 16\n"); diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index abf214f405c..f2a417faf86 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1549,6 +1549,8 @@ get_arm_bl_target (guint32 *ins_addr) offset = (((int)ins & 0xffffff) << 8) >> 8; return (char*)ins_addr + (offset * 4) + 8; } +#elif defined(TARGET_ARM64) + return mono_arch_get_call_target (((guint8*)ins_addr) + 4); #else g_assert_not_reached (); return NULL; @@ -1778,7 +1780,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) /* method_addresses () contains a table of branches, since the ios linker can update those correctly */ void *addr = NULL; -#ifdef TARGET_ARM +#if defined(TARGET_ARM) || defined(TARGET_ARM64) addr = get_arm_bl_target ((guint32*)amodule->method_addresses + i); #elif defined(TARGET_X86) || defined(TARGET_AMD64) addr = mono_arch_get_call_target ((guint8*)amodule->method_addresses + (i * 5) + 5); @@ -3880,16 +3882,24 @@ find_aot_module (guint8 *code) } void -mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr) +mono_aot_patch_plt_entry (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_t *regs, guint8 *addr) { + MonoAotModule *amodule; + /* * Since AOT code is only used in the root domain, * mono_domain_get () != mono_get_root_domain () means the calling method * is AppDomain:InvokeInDomain, so this is the same check as in * mono_method_same_domain () but without loading the metadata for the method. */ - if (mono_domain_get () == mono_get_root_domain ()) - mono_arch_patch_plt_entry (code, got, regs, addr); + if (mono_domain_get () == mono_get_root_domain ()) { + if (!got) { + amodule = find_aot_module (code); + if (amodule) + got = amodule->got; + } + mono_arch_patch_plt_entry (plt_entry, got, regs, addr); + } } /* @@ -3968,7 +3978,7 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code /* Patch the PLT entry with target which might be the actual method not a trampoline */ plt_entry = mono_aot_get_plt_entry (code); g_assert (plt_entry); - mono_aot_patch_plt_entry (plt_entry, module->got, NULL, target); + mono_aot_patch_plt_entry (code, plt_entry, module->got, NULL, target); return target; #else @@ -4378,10 +4388,14 @@ get_new_trampoline_from_page (int tramp_type) page = (TrampolinePage*)addr; page->next = trampoline_pages [tramp_type]; trampoline_pages [tramp_type] = page; +#ifdef TARGET_ARM64 + page->trampolines = (void*)(taddr + amodule->info.tramp_page_code_offsets [tramp_type]); +#else page->trampolines = (void*)(taddr + trampolines_pages_code_offsets [tramp_type]); - page->trampolines_end = (void*)(taddr + psize); +#endif + page->trampolines_end = (void*)(taddr + psize - 64); code = page->trampolines; - page->trampolines += 8; + page->trampolines += specific_trampoline_size; mono_aot_page_unlock (); return code; } @@ -4879,7 +4893,7 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code } void -mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr) +mono_aot_patch_plt_entry (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_t *regs, guint8 *addr) { } diff --git a/mono/mini/cpu-arm64.md b/mono/mini/cpu-arm64.md new file mode 100644 index 00000000000..d57b6eeda2b --- /dev/null +++ b/mono/mini/cpu-arm64.md @@ -0,0 +1,424 @@ +# Copyright 2011-2013 Xamarin, Inc (http://www.xamarin.com) +# Copyright 2003-2011 Novell, Inc (http://www.novell.com) +# arm64 cpu description file +# this file is read by genmdesc to pruduce a table with all the relevant information +# about the cpu instructions that may be used by the regsiter allocator, the scheduler +# and other parts of the arch-dependent part of mini. +# +# An opcode name is followed by a colon and optional specifiers. +# A specifier has a name, a colon and a value. Specifiers are separated by white space. +# Here is a description of the specifiers valid for this file and their possible values. +# +# dest:register describes the destination register of an instruction +# src1:register describes the first source register of an instruction +# src2:register describes the second source register of an instruction +# +# register may have the following values: +# i integer register +# a r3 register (output from calls) +# b base register (used in address references) +# f floating point register +# g floating point register returned in r0:r1 for soft-float mode +# +# len:number describe the maximun length in bytes of the instruction +# number is a positive integer +# +# cost:number describe how many cycles are needed to complete the instruction (unused) +# +# clob:spec describe if the instruction clobbers registers or has special needs +# +# spec can be one of the following characters: +# c clobbers caller-save registers +# r 'reserves' the destination register until a later instruction unreserves it +# used mostly to set output registers in function calls +# +# flags:spec describe if the instruction uses or sets the flags (unused) +# +# spec can be one of the following chars: +# s sets the flags +# u uses the flags +# m uses and modifies the flags +# +# res:spec describe what units are used in the processor (unused) +# +# delay: describe delay slots (unused) +# +# the required specifiers are: len, clob (if registers are clobbered), the registers +# specifiers if the registers are actually used, flags (when scheduling is implemented). +# +# See the code in mini-x86.c for more details on how the specifiers are used. +# +memory_barrier: len:8 clob:a +nop: len:4 +relaxed_nop: len:4 +break: len:20 +jmp: len:92 +br: len:16 +switch: src1:i len:12 +# See the comment in resume_from_signal_handler, we can't copy the fp regs from sigctx to MonoContext on linux, +# since the corresponding sigctx structures are not well defined. +seq_point: len:38 clob:c + +throw: src1:i len:24 +rethrow: src1:i len:20 +start_handler: len:32 +endfinally: len:32 +call_handler: len:16 clob:c +endfilter: src1:i len:32 + +ckfinite: dest:f src1:f len:64 +ceq: dest:i len:12 +cgt: dest:i len:12 +cgt.un: dest:i len:12 +clt: dest:i len:12 +clt.un: dest:i len:12 +localloc: dest:i src1:i len:96 +compare: src1:i src2:i len:4 +compare_imm: src1:i len:20 +fcompare: src1:f src2:f len:12 +oparglist: src1:i len:12 +setlret: src1:i src2:i len:12 +checkthis: src1:b len:4 +call: dest:a clob:c len:32 +call_reg: dest:a src1:i len:32 clob:c +call_membase: dest:a src1:b len:32 clob:c +voidcall: len:32 clob:c +voidcall_reg: src1:i len:32 clob:c +voidcall_membase: src1:b len:32 clob:c +fcall: dest:f len:32 clob:c +fcall_reg: dest:f src1:i len:32 clob:c +fcall_membase: dest:f src1:b len:32 clob:c +lcall: dest:l len:32 clob:c +lcall_reg: dest:l src1:i len:32 clob:c +lcall_membase: dest:l src1:b len:32 clob:c +vcall: len:32 clob:c +vcall_reg: src1:i len:32 clob:c +vcall_membase: src1:b len:32 clob:c +tailcall: len:64 +iconst: dest:i len:16 +r4const: dest:f len:24 +r8const: dest:f len:20 +label: len:0 +store_membase_imm: dest:b len:20 +store_membase_reg: dest:b src1:i len:20 +storei1_membase_imm: dest:b len:20 +storei1_membase_reg: dest:b src1:i len:12 +storei2_membase_imm: dest:b len:20 +storei2_membase_reg: dest:b src1:i len:12 +storei4_membase_imm: dest:b len:20 +storei4_membase_reg: dest:b src1:i len:20 +storer4_membase_reg: dest:b src1:f len:20 +storer8_membase_reg: dest:b src1:f len:24 +store_memindex: dest:b src1:i src2:i len:4 +storei1_memindex: dest:b src1:i src2:i len:4 +storei2_memindex: dest:b src1:i src2:i len:4 +storei4_memindex: dest:b src1:i src2:i len:4 +load_membase: dest:i src1:b len:20 +loadi1_membase: dest:i src1:b len:32 +loadu1_membase: dest:i src1:b len:32 +loadi2_membase: dest:i src1:b len:32 +loadu2_membase: dest:i src1:b len:32 +loadi4_membase: dest:i src1:b len:32 +loadu4_membase: dest:i src1:b len:32 +loadr4_membase: dest:f src1:b len:32 +loadr8_membase: dest:f src1:b len:32 +load_memindex: dest:i src1:b src2:i len:4 +loadi1_memindex: dest:i src1:b src2:i len:4 +loadu1_memindex: dest:i src1:b src2:i len:4 +loadi2_memindex: dest:i src1:b src2:i len:4 +loadu2_memindex: dest:i src1:b src2:i len:4 +loadi4_memindex: dest:i src1:b src2:i len:4 +loadu4_memindex: dest:i src1:b src2:i len:4 +loadu4_mem: dest:i len:8 +move: dest:i src1:i len:4 +fmove: dest:f src1:f len:4 +add_imm: dest:i src1:i len:12 +sub_imm: dest:i src1:i len:12 +mul_imm: dest:i src1:i len:12 +and_imm: dest:i src1:i len:12 +or_imm: dest:i src1:i len:12 +xor_imm: dest:i src1:i len:12 +shl_imm: dest:i src1:i len:8 +shr_imm: dest:i src1:i len:8 +shr_un_imm: dest:i src1:i len:8 +cond_exc_eq: len:8 +cond_exc_ne_un: len:8 +cond_exc_lt: len:8 +cond_exc_lt_un: len:8 +cond_exc_gt: len:8 +cond_exc_gt_un: len:8 +cond_exc_ge: len:8 +cond_exc_ge_un: len:8 +cond_exc_le: len:8 +cond_exc_le_un: len:8 +cond_exc_ov: len:12 +cond_exc_no: len:8 +cond_exc_c: len:12 +cond_exc_nc: len:8 +#float_beq: src1:f src2:f len:20 +#float_bne_un: src1:f src2:f len:20 +#float_blt: src1:f src2:f len:20 +#float_blt_un: src1:f src2:f len:20 +#float_bgt: src1:f src2:f len:20 +#float_bgt_un: src1:f src2:f len:20 +#float_bge: src1:f src2:f len:20 +#float_bge_un: src1:f src2:f len:20 +#float_ble: src1:f src2:f len:20 +#float_ble_un: src1:f src2:f len:20 +float_add: dest:f src1:f src2:f len:4 +float_sub: dest:f src1:f src2:f len:4 +float_mul: dest:f src1:f src2:f len:4 +float_div: dest:f src1:f src2:f len:4 +float_div_un: dest:f src1:f src2:f len:4 +float_rem: dest:f src1:f src2:f len:16 +float_rem_un: dest:f src1:f src2:f len:16 +float_neg: dest:f src1:f len:4 +float_not: dest:f src1:f len:4 +float_conv_to_i1: dest:i src1:f len:40 +float_conv_to_i2: dest:i src1:f len:40 +float_conv_to_i4: dest:i src1:f len:40 +float_conv_to_i8: dest:l src1:f len:40 +float_conv_to_r4: dest:f src1:f len:8 +float_conv_to_u4: dest:i src1:f len:40 +float_conv_to_u8: dest:l src1:f len:40 +float_conv_to_u2: dest:i src1:f len:40 +float_conv_to_u1: dest:i src1:f len:40 +float_conv_to_i: dest:i src1:f len:40 +float_ceq: dest:i src1:f src2:f len:16 +float_cgt: dest:i src1:f src2:f len:16 +float_cgt_un: dest:i src1:f src2:f len:20 +float_clt: dest:i src1:f src2:f len:16 +float_clt_un: dest:i src1:f src2:f len:20 +float_cneq: dest:i src1:f src2:f len:20 +float_cge: dest:i src1:f src2:f len:20 +float_cle: dest:i src1:f src2:f len:20 +float_conv_to_u: dest:i src1:f len:36 +setfret: src1:f len:12 +aot_const: dest:i len:16 +objc_get_selector: dest:i len:32 +sqrt: dest:f src1:f len:4 +adc: dest:i src1:i src2:i len:4 +addcc: dest:i src1:i src2:i len:4 +subcc: dest:i src1:i src2:i len:4 +adc_imm: dest:i src1:i len:12 +addcc_imm: dest:i src1:i len:12 +subcc_imm: dest:i src1:i len:12 +sbb: dest:i src1:i src2:i len:4 +sbb_imm: dest:i src1:i len:12 +br_reg: src1:i len:8 +bigmul: len:8 dest:l src1:i src2:i +bigmul_un: len:8 dest:l src1:i src2:i +tls_get: dest:i len:32 +tls_get_reg: dest:i src1:i len:32 +tls_set: src1:i len:32 +tls_set_reg: src1:i src2:i len:32 + +# 32 bit opcodes +int_add: dest:i src1:i src2:i len:4 +int_sub: dest:i src1:i src2:i len:4 +int_mul: dest:i src1:i src2:i len:4 +int_div: dest:i src1:i src2:i len:72 +int_div_un: dest:i src1:i src2:i len:72 +int_rem: dest:i src1:i src2:i len:72 +int_rem_un: dest:i src1:i src2:i len:72 +int_and: dest:i src1:i src2:i len:4 +int_or: dest:i src1:i src2:i len:4 +int_xor: dest:i src1:i src2:i len:4 +int_shl: dest:i src1:i src2:i len:4 +int_shr: dest:i src1:i src2:i len:4 +int_shr_un: dest:i src1:i src2:i len:4 +int_neg: dest:i src1:i len:4 +int_not: dest:i src1:i len:4 +int_conv_to_i1: dest:i src1:i len:8 +int_conv_to_i2: dest:i src1:i len:8 +int_conv_to_i4: dest:i src1:i len:4 +int_conv_to_r4: dest:f src1:i len:36 +int_conv_to_r8: dest:f src1:i len:36 +int_conv_to_u4: dest:i src1:i +int_conv_to_r_un: dest:f src1:i len:56 +int_conv_to_u2: dest:i src1:i len:8 +int_conv_to_u1: dest:i src1:i len:4 +int_beq: len:16 +int_bge: len:16 +int_bgt: len:16 +int_ble: len:16 +int_blt: len:16 +int_bne_un: len:16 +int_bge_un: len:16 +int_bgt_un: len:16 +int_ble_un: len:16 +int_blt_un: len:16 +int_add_ovf: dest:i src1:i src2:i len:16 +int_add_ovf_un: dest:i src1:i src2:i len:16 +int_mul_ovf: dest:i src1:i src2:i len:16 +int_mul_ovf_un: dest:i src1:i src2:i len:16 +int_sub_ovf: dest:i src1:i src2:i len:16 +int_sub_ovf_un: dest:i src1:i src2:i len:16 +add_ovf_carry: dest:i src1:i src2:i len:16 +sub_ovf_carry: dest:i src1:i src2:i len:16 +add_ovf_un_carry: dest:i src1:i src2:i len:16 +sub_ovf_un_carry: dest:i src1:i src2:i len:16 + +arm_rsbs_imm: dest:i src1:i len:4 +arm_rsc_imm: dest:i src1:i len:4 + +# Linear IR opcodes +dummy_use: src1:i len:0 +dummy_store: len:0 +not_reached: len:0 +not_null: src1:i len:0 + +int_adc: dest:i src1:i src2:i len:4 +int_addcc: dest:i src1:i src2:i len:4 +int_subcc: dest:i src1:i src2:i len:4 +int_sbb: dest:i src1:i src2:i len:4 +int_adc_imm: dest:i src1:i len:12 +int_sbb_imm: dest:i src1:i len:12 + +int_add_imm: dest:i src1:i len:12 +int_sub_imm: dest:i src1:i len:12 +int_mul_imm: dest:i src1:i len:12 +int_div_imm: dest:i src1:i len:20 +int_div_un_imm: dest:i src1:i len:12 +int_rem_imm: dest:i src1:i len:28 +int_rem_un_imm: dest:i src1:i len:16 +int_and_imm: dest:i src1:i len:12 +int_or_imm: dest:i src1:i len:12 +int_xor_imm: dest:i src1:i len:12 +int_shl_imm: dest:i src1:i len:8 +int_shr_imm: dest:i src1:i len:8 +int_shr_un_imm: dest:i src1:i len:8 + +int_ceq: dest:i len:12 +int_cgt: dest:i len:12 +int_cgt_un: dest:i len:12 +int_clt: dest:i len:12 +int_clt_un: dest:i len:12 + +int_cneq: dest:i len:12 +int_cge: dest:i len:12 +int_cle: dest:i len:12 +int_cge_un: dest:i len:12 +int_cle_un: dest:i len:12 + +cond_exc_ieq: len:16 +cond_exc_ine_un: len:16 +cond_exc_ilt: len:16 +cond_exc_ilt_un: len:16 +cond_exc_igt: len:16 +cond_exc_igt_un: len:16 +cond_exc_ige: len:16 +cond_exc_ige_un: len:16 +cond_exc_ile: len:16 +cond_exc_ile_un: len:16 +cond_exc_iov: len:20 +cond_exc_ino: len:16 +cond_exc_ic: len:20 +cond_exc_inc: len:16 + +icompare: src1:i src2:i len:4 +icompare_imm: src1:i len:12 + +long_conv_to_ovf_i4_2: dest:i src1:i src2:i len:36 + +vcall2: len:32 clob:c +vcall2_reg: src1:i len:32 clob:c +vcall2_membase: src1:b len:32 clob:c +dyn_call: src1:i src2:i len:120 clob:c + +# This is different from the original JIT opcodes +float_beq: len:32 +float_bne_un: len:32 +float_blt: len:32 +float_blt_un: len:32 +float_bgt: len:32 +float_bgt_un: len:32 +float_bge: len:32 +float_bge_un: len:32 +float_ble: len:32 +float_ble_un: len:32 + +liverange_start: len:0 +liverange_end: len:0 +gc_liveness_def: len:0 +gc_liveness_use: len:0 +gc_spill_slot_liveness_def: len:0 +gc_param_slot_liveness_def: len:0 + +# 64 bit opcodes +i8const: dest:i len:16 +sext_i4: dest:i src1:i len:4 +zext_i4: dest:i src1:i len:4 +jump_table: dest:i len:16 +long_add: dest:i src1:i src2:i len:4 +long_sub: dest:i src1:i src2:i len:4 +long_mul: dest:i src1:i src2:i len:4 +long_div: dest:i src1:i src2:i len:80 +long_div_un: dest:i src1:i src2:i len:64 +long_rem: dest:i src1:i src2:i len:80 +long_rem_un: dest:i src1:i src2:i len:64 +long_and: dest:i src1:i src2:i len:4 +long_or: dest:i src1:i src2:i len:4 +long_xor: dest:i src1:i src2:i len:4 +long_shl: dest:i src1:i src2:i len:4 +long_shr: dest:i src1:i src2:i len:4 +long_shr_un: dest:i src1:i src2:i len:4 +long_neg: dest:i src1:i len:4 +long_not: dest:i src1:i len:4 +long_add_imm: dest:i src1:i len:12 +long_sub_imm: dest:i src1:i len:12 +long_mul_imm: dest:i src1:i len:12 +long_and_imm: dest:i src1:i len:12 +long_or_imm: dest:i src1:i len:12 +long_xor_imm: dest:i src1:i len:12 +long_shl_imm: dest:i src1:i len:12 +long_shr_imm: dest:i src1:i len:12 +long_shr_un_imm: dest:i src1:i len:12 +long_add_ovf: dest:i src1:i src2:i len:16 +long_add_ovf_un: dest:i src1:i src2:i len:16 +long_mul_ovf: dest:i src1:i src2:i len:16 +long_mul_ovf_un: dest:i src1:i src2:i len:16 +long_sub_ovf: dest:i src1:i src2:i len:16 +long_sub_ovf_un: dest:i src1:i src2:i len:16 +lcompare: src1:i src2:i len:4 +lcompare_imm: src1:i len:20 +long_beq: len:4 +long_bge: len:4 +long_bgt: len:4 +long_ble: len:4 +long_blt: len:4 +long_bne_un: len:4 +long_bge_un: len:4 +long_bgt_un: len:4 +long_ble_un: len:4 +long_blt_un: len:4 +long_ceq: dest:i len:12 +long_cgt: dest:i len:12 +long_cgt_un: dest:i len:12 +long_clt: dest:i len:12 +long_clt_un: dest:i len:12 +long_conv_to_i1: dest:i src1:i len:4 +long_conv_to_i2: dest:i src1:i len:4 +long_conv_to_u1: dest:i src1:i len:4 +long_conv_to_u2: dest:i src1:i len:4 +long_conv_to_r8: dest:f src1:i len:8 +long_conv_to_r4: dest:f src1:i len:12 +loadi8_membase: dest:i src1:b len:12 +storei8_membase_imm: dest:b len:20 +storei8_membase_reg: dest:b src1:i len:12 +long_conv_to_r_un: dest:f src1:i len:8 +arm_setfreg_r4: dest:f src1:f len:8 +localloc_imm: dest:i len:64 +arm64_cbzw: src1:i len:16 +arm64_cbzx: src1:i len:16 +arm64_cbnzw: src1:i len:16 +arm64_cbnzx: src1:i len:16 + +atomic_add_new_i4: dest:i src1:i src2:i len:32 +atomic_add_new_i8: dest:i src1:i src2:i len:32 +atomic_exchange_i4: dest:i src1:i src2:i len:32 +atomic_exchange_i8: dest:i src1:i src2:i len:32 +atomic_cas_i4: dest:i src1:i src2:i src3:i len:32 +atomic_cas_i8: dest:i src1:i src2:i src3:i len:32 + + diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 9eb0c294976..16ccadc9aa6 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -285,7 +285,7 @@ typedef struct { #define HEADER_LENGTH 11 #define MAJOR_VERSION 2 -#define MINOR_VERSION 29 +#define MINOR_VERSION 30 typedef enum { CMD_SET_VM = 1, @@ -371,7 +371,8 @@ typedef enum { STEP_FILTER_NONE = 0, STEP_FILTER_STATIC_CTOR = 1, STEP_FILTER_DEBUGGER_HIDDEN = 2, - STEP_FILTER_DEBUGGER_STEP_THROUGH = 4 + STEP_FILTER_DEBUGGER_STEP_THROUGH = 4, + STEP_FILTER_DEBUGGER_NON_USER_CODE = 8 } StepFilter; typedef enum { @@ -3498,6 +3499,32 @@ create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo if (ji->dbg_step_through) filtered = TRUE; } + if ((mod->data.filter & STEP_FILTER_DEBUGGER_NON_USER_CODE) && ji) { + MonoCustomAttrInfo *ainfo; + static MonoClass *klass; + + if (!klass) { + klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerNonUserCodeAttribute"); + g_assert (klass); + } + if (!ji->dbg_non_user_code_inited) { + ainfo = mono_custom_attrs_from_method (jinfo_get_method (ji)); + if (ainfo) { + if (mono_custom_attrs_has_attr (ainfo, klass)) + ji->dbg_non_user_code = TRUE; + mono_custom_attrs_free (ainfo); + } + ainfo = mono_custom_attrs_from_class (jinfo_get_method (ji)->klass); + if (ainfo) { + if (mono_custom_attrs_has_attr (ainfo, klass)) + ji->dbg_non_user_code = TRUE; + mono_custom_attrs_free (ainfo); + } + ji->dbg_non_user_code_inited = TRUE; + } + if (ji->dbg_non_user_code) + filtered = TRUE; + } } } diff --git a/mono/mini/exceptions-arm64.c b/mono/mini/exceptions-arm64.c new file mode 100644 index 00000000000..333fd13b754 --- /dev/null +++ b/mono/mini/exceptions-arm64.c @@ -0,0 +1 @@ +#include "../../../mono-extensions/mono/mini/exceptions-arm64.c" diff --git a/mono/mini/genmdesc.pl b/mono/mini/genmdesc.pl index 8c13a6171dd..b3a4cc8b78b 100644 --- a/mono/mini/genmdesc.pl +++ b/mono/mini/genmdesc.pl @@ -20,7 +20,7 @@ sub INST_MAX () {return 6;} # this must include all the #defines used in mini-ops.h my @defines = qw (__i386__ __x86_64__ __ppc__ __powerpc__ __ppc64__ __arm__ - __sparc__ sparc __s390__ s390 __ia64__ __alpha__ __mips__); + __sparc__ sparc __s390__ s390 __ia64__ __alpha__ __mips__ __aarch64__); my %table =(); my %template_table =(); my @opcodes = (); @@ -85,6 +85,9 @@ sub load_opcodes if ($arch =~ "__arm__") { $arch_define = "TARGET_ARM"; } + if ($arch =~ "__aarch64__") { + $arch_define = "TARGET_ARM64"; + } parse_file ($arch_define, "$srcdir/mini-ops.h"); return; diff --git a/mono/mini/helpers.c b/mono/mini/helpers.c index d945a39b8f2..43bd17e2fa4 100644 --- a/mono/mini/helpers.c +++ b/mono/mini/helpers.c @@ -66,10 +66,14 @@ opnames[] = { #endif /* DISABLE_LOGGING */ #if defined(__i386__) || defined(__x86_64__) +#ifndef TARGET_ARM64 #define emit_debug_info TRUE #else #define emit_debug_info FALSE #endif +#else +#define emit_debug_info FALSE +#endif /*This enables us to use the right tooling when building the cross compiler for iOS.*/ #if defined (__APPLE__) && defined (TARGET_ARM) && (defined(__i386__) || defined(__x86_64__)) @@ -237,6 +241,12 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id) # else # define AS_CMD "as -gstabs" # endif +#elif defined (TARGET_ARM64) +# if defined (__APPLE__) +# define AS_CMD "clang -c -arch arm64 -g -x assembler" +# else +# define AS_CMD "as -gstabs" +# endif #elif defined(__mips__) && (_MIPS_SIM == _ABIO32) #define AS_CMD "as -mips32" #elif defined(__ppc64__) @@ -275,7 +285,7 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id) cmd = g_strdup_printf (ARCH_PREFIX DIS_CMD " %s %s", objdump_args, o_file); unused = system (cmd); g_free (cmd); - + #ifndef HOST_WIN32 unlink (o_file); unlink (as_file); diff --git a/mono/mini/image-writer.c b/mono/mini/image-writer.c index a5d7488da85..62b2b3525a5 100644 --- a/mono/mini/image-writer.c +++ b/mono/mini/image-writer.c @@ -74,6 +74,14 @@ #if (defined(TARGET_AMD64) || defined(TARGET_POWERPC64)) && !defined(__mono_ilp32__) #define AS_POINTER_DIRECTIVE ".quad" +#elif defined(TARGET_ARM64) + +#ifdef TARGET_ASM_APPLE +#define AS_POINTER_DIRECTIVE ".quad" +#else +#define AS_POINTER_DIRECTIVE ".xword" +#endif + #else #define AS_POINTER_DIRECTIVE ".long" #endif @@ -1713,7 +1721,7 @@ asm_writer_emit_section_change (MonoImageWriter *acfg, const char *section_name, fprintf (acfg->fp, ".section __DWARF, __%s,regular,debug\n", section_name + 1); } else fprintf (acfg->fp, "%s\n", section_name); -#elif defined(TARGET_ARM) || defined(TARGET_POWERPC) +#elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_POWERPC) /* ARM gas doesn't seem to like subsections of .bss */ if (!strcmp (section_name, ".text") || !strcmp (section_name, ".data")) { fprintf (acfg->fp, "%s %d\n", section_name, subsection_index); diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 2e35b7ab17f..1ecf79c9ac3 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -1953,10 +1953,26 @@ emit_push_lmf (MonoCompile *cfg) } #else lmf_ins = mono_get_lmf_addr_intrinsic (cfg); - if (lmf_ins) + if (lmf_ins) { MONO_ADD_INS (cfg->cbb, lmf_ins); - else + } else { +#ifdef TARGET_IOS + MonoInst *args [16], *jit_tls_ins, *ins; + + /* Inline mono_get_lmf_addr () */ + /* jit_tls = pthread_getspecific (mono_jit_tls_id); lmf_addr = &jit_tls->lmf; */ + + /* Load mono_jit_tls_id */ + EMIT_NEW_AOTCONST (cfg, args [0], MONO_PATCH_INFO_JIT_TLS_ID, NULL); + /* call pthread_getspecific () */ + jit_tls_ins = mono_emit_jit_icall (cfg, pthread_getspecific, args); + /* lmf_addr = &jit_tls->lmf */ + EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, cfg->lmf_addr_var->dreg, jit_tls_ins->dreg, G_STRUCT_OFFSET (MonoJitTlsData, lmf)); + lmf_ins = ins; +#else lmf_ins = mono_emit_jit_icall (cfg, mono_get_lmf_addr, NULL); +#endif + } #endif lmf_ins->dreg = cfg->lmf_addr_var->dreg; @@ -5686,10 +5702,10 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign if (args [0]->opcode == OP_GOT_ENTRY) { pi = args [0]->inst_p1; g_assert (pi->opcode == OP_PATCH_INFO); - g_assert ((int)pi->inst_p1 == MONO_PATCH_INFO_LDSTR); + g_assert (GPOINTER_TO_INT (pi->inst_p1) == MONO_PATCH_INFO_LDSTR); ji = pi->inst_p0; } else { - g_assert ((int)args [0]->inst_p1 == MONO_PATCH_INFO_LDSTR); + g_assert (GPOINTER_TO_INT (args [0]->inst_p1) == MONO_PATCH_INFO_LDSTR); ji = args [0]->inst_p0; } diff --git a/mono/mini/mini-arch.h b/mono/mini/mini-arch.h index a005fc98ad4..6d52aecf6da 100644 --- a/mono/mini/mini-arch.h +++ b/mono/mini/mini-arch.h @@ -19,6 +19,8 @@ #include "mini-ia64.h" #elif defined(TARGET_ARM) #include "mini-arm.h" +#elif defined(TARGET_ARM64) +#include "mini-arm64.h" #elif defined(__mips__) #include "mini-mips.h" #else diff --git a/mono/mini/mini-arm64.c b/mono/mini/mini-arm64.c new file mode 100644 index 00000000000..517f6c68a9d --- /dev/null +++ b/mono/mini/mini-arm64.c @@ -0,0 +1 @@ +#include "../../../mono-extensions/mono/mini/mini-arm64.c" diff --git a/mono/mini/mini-arm64.h b/mono/mini/mini-arm64.h new file mode 100644 index 00000000000..a963c75d51c --- /dev/null +++ b/mono/mini/mini-arm64.h @@ -0,0 +1 @@ +#include "../../../mono-extensions/mono/mini/mini-arm64.h" diff --git a/mono/mini/mini-codegen.c b/mono/mini/mini-codegen.c index 48fac064cbd..6e5bf2f8586 100644 --- a/mono/mini/mini-codegen.c +++ b/mono/mini/mini-codegen.c @@ -1065,8 +1065,9 @@ assign_reg (MonoCompile *cfg, MonoRegState *rs, int reg, int hreg, int bank) else { g_assert (reg >= MONO_MAX_IREGS); g_assert (hreg < MONO_MAX_IREGS); -#ifndef TARGET_ARM +#if !defined(TARGET_ARM) && !defined(TARGET_ARM64) /* this seems to trigger a gcc compilation bug sometime (hreg is 0) */ + /* On arm64, rgctx_reg is a global hreg, and it is used to pass an argument */ g_assert (! is_global_ireg (hreg)); #endif @@ -1124,7 +1125,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) desc_to_fixed_reg_inited = TRUE; /* Validate the cpu description against the info in mini-ops.h */ -#if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM) +#if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM) || defined(TARGET_ARM64) for (i = OP_LOAD; i < OP_LAST; ++i) { const char *ispec; diff --git a/mono/mini/mini-gc.c b/mono/mini/mini-gc.c index bc6a1aabb6c..a2e1f2f6029 100644 --- a/mono/mini/mini-gc.c +++ b/mono/mini/mini-gc.c @@ -436,6 +436,9 @@ static int callee_saved_regs [] = { AMD64_RBP, AMD64_RBX, AMD64_R12, AMD64_R13, static int callee_saved_regs [] = { X86_EBX, X86_ESI, X86_EDI }; #elif defined(TARGET_ARM) static int callee_saved_regs [] = { ARMREG_V1, ARMREG_V2, ARMREG_V3, ARMREG_V4, ARMREG_V5, ARMREG_V7, ARMREG_FP }; +#elif defined(TARGET_ARM64) +// FIXME: +static int callee_saved_regs [] = { }; #elif defined(TARGET_S390X) static int callee_saved_regs [] = { s390_r6, s390_r7, s390_r8, s390_r9, s390_r10, s390_r11, s390_r12, s390_r13, s390_r14 }; #endif diff --git a/mono/mini/mini-ops.h b/mono/mini/mini-ops.h index bccdb295d44..b1a31ee16d7 100644 --- a/mono/mini/mini-ops.h +++ b/mono/mini/mini-ops.h @@ -1033,9 +1033,11 @@ MINI_OP(OP_PPC_SUBFZE, "ppc_subfze", IREG, IREG, NONE) MINI_OP(OP_CHECK_FINITE, "ppc_check_finite", NONE, IREG, NONE) #endif -#if defined(TARGET_ARM) +#if defined(TARGET_ARM) || defined(TARGET_ARM64) MINI_OP(OP_ARM_RSBS_IMM, "arm_rsbs_imm", IREG, IREG, NONE) MINI_OP(OP_ARM_RSC_IMM, "arm_rsc_imm", IREG, IREG, NONE) +/* Set dreg to an r4 value */ +MINI_OP(OP_ARM_SETFREG_R4, "arm_setfreg_r4", FREG, FREG, NONE) #endif #if defined(__sparc__) || defined(sparc) @@ -1238,6 +1240,15 @@ MINI_OP(OP_MIPS_COND_EXC_INC, "mips_cond_exc_inc", NONE, IREG, IREG) #endif +#if defined(TARGET_ARM64) +/* Branch if sreg1 == 0 */ +MINI_OP(OP_ARM64_CBZW, "arm64_cbzw", NONE, IREG, NONE) +MINI_OP(OP_ARM64_CBZX, "arm64_cbzx", NONE, IREG, NONE) +/* Branch if sreg1 != 0 */ +MINI_OP(OP_ARM64_CBNZW, "arm64_cbnzw", NONE, IREG, NONE) +MINI_OP(OP_ARM64_CBNZX, "arm64_cbnzx", NONE, IREG, NONE) +#endif + /* Same as OUTARG_VT, but has a dreg */ #ifdef ENABLE_LLVM MINI_OP(OP_LLVM_OUTARG_VT, "llvm_outarg_vt", IREG, VREG, NONE) diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index 09183038c99..537a0bbfdcc 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -673,7 +673,7 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, guint8* tram } } if (!no_patch) - mono_aot_patch_plt_entry (plt_entry, NULL, regs, addr); + mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, addr); } else { if (generic_shared) { if (m->wrapper_type != MONO_WRAPPER_NONE) @@ -869,7 +869,7 @@ mono_aot_trampoline (mgreg_t *regs, guint8 *code, guint8 *token_info, plt_entry = mono_aot_get_plt_entry (code); g_assert (plt_entry); - mono_aot_patch_plt_entry (plt_entry, NULL, regs, addr); + mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, addr); return addr; } @@ -917,7 +917,7 @@ mono_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, gui if (vtable->initialized) { if (plt_entry) - mono_arch_patch_plt_entry (plt_entry, NULL, regs, mini_get_nullified_class_init_trampoline ()); + mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, mini_get_nullified_class_init_trampoline ()); else mono_arch_nullify_class_init_trampoline (code, regs); } diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 110540968a2..3a9ff6b7c27 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -2405,6 +2405,8 @@ register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpo /* * For JIT icalls implemented in C. * NAME should be the same as the name of the C function whose address is FUNC. + * If SAVE is TRUE, no wrapper is generated. This is for perf critical icalls which + * can't throw exceptions. */ static void register_icall (gpointer func, const char *name, const char *sigstr, gboolean save) @@ -7622,7 +7624,7 @@ mini_init (const char *filename, const char *runtime_version) #endif #ifdef TARGET_IOS - register_icall (pthread_getspecific, "pthread_getspecific", NULL, TRUE); + register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE); #endif mono_generic_sharing_init (); diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 3870d7b65c3..664788b5f5b 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2126,7 +2126,7 @@ gboolean mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassIn gboolean mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const char *name, MonoClass **klass) MONO_INTERNAL; MonoJitInfo* mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr) MONO_INTERNAL; gpointer mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code) MONO_INTERNAL; -void mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr) MONO_INTERNAL; +void mono_aot_patch_plt_entry (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_t *regs, guint8 *addr) MONO_INTERNAL; gpointer mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot) MONO_INTERNAL; gpointer mono_aot_create_specific_trampoline (MonoImage *image, gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len) MONO_INTERNAL; gpointer mono_aot_get_trampoline (const char *name) MONO_INTERNAL; diff --git a/mono/mini/tramp-arm64.c b/mono/mini/tramp-arm64.c new file mode 100644 index 00000000000..16504375d84 --- /dev/null +++ b/mono/mini/tramp-arm64.c @@ -0,0 +1 @@ +#include "../../../mono-extensions/mono/mini/tramp-arm64.c" diff --git a/mono/mini/unwind.c b/mono/mini/unwind.c index 018ad903e40..87b71984b50 100644 --- a/mono/mini/unwind.c +++ b/mono/mini/unwind.c @@ -56,6 +56,15 @@ static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, #define NUM_REGS 272 #define DWARF_DATA_ALIGN (-4) #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (ARMREG_LR)) +#elif defined(TARGET_ARM64) +/* +1 is for pc */ +#define NUM_REGS (32 + 1) +#define DWARF_DATA_ALIGN (-8) +#define DWARF_PC_REG 32 +static int map_hw_reg_to_dwarf_reg [] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +}; #elif defined (TARGET_X86) #ifdef __APPLE__ /* diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 997dac1d896..0bf8f486bc6 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -914,7 +914,12 @@ SGEN_CONFIGURATIONS = \ "major=marksweep-conc|ms-conc" \ "major=marksweep-conc,minor=split|ms-conc-split" \ "minor=split|ms-split" \ - "minor=split,alloc-ratio=95|ms-split-95" + "minor=split,alloc-ratio=95|ms-split-95" \ + "|plain-clear-at-gc|clear-at-gc" \ + "major=marksweep-par|ms-par-clear-at-gc|clear-at-gc" \ + "major=marksweep-conc|ms-conc-clear-at-gc|clear-at-gc" \ + "minor=split|ms-split-clear-at-gc|clear-at-gc" + #FIXME We should move to use SGEN_CONFIGURATIONS once sgen supports trailling commas or its argument list. SGEN_BRIDGE_CONFIGURATIONS = \ @@ -935,8 +940,9 @@ sgen-regular-tests: $(SGEN_TESTS) for conf in $(SGEN_CONFIGURATIONS); do \ name=`echo $$conf | cut -d\| -f 2`; \ params=`echo $$conf | cut -d\| -f 1`; \ + debug_opt=`echo $$conf | cut -d\| -f 3`; \ test_name="$${test}|$${name}"; \ - if MONO_GC_PARAMS="$$params" MONO_ENV_OPTIONS="--gc=sgen" $(srcdir)/test-driver '$(with_mono_path) $(JITTEST_PROG_RUN)' $$test_name "$(DISABLED_TESTS_SGEN)" "$${dump_action}" $(RUNTIME_ARGS); \ + if MONO_GC_PARAMS="$$params" MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="$$debug_opt" $(srcdir)/test-driver '$(with_mono_path) $(JITTEST_PROG_RUN)' $$test_name "$(DISABLED_TESTS_SGEN)" "$${dump_action}" $(RUNTIME_ARGS); \ then \ passed=`expr $${passed} + 1`; \ else \ diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am index 9af5b9128f0..c67434d7b4b 100644 --- a/mono/utils/Makefile.am +++ b/mono/utils/Makefile.am @@ -128,6 +128,10 @@ if ARM arch_sources += mach-support-arm.c endif +if ARM64 +arch_sources += mach-support-arm.c +endif + else arch_sources += mach-support-unknown.c @@ -146,6 +150,10 @@ if ARM arch_sources += mono-hwcap-arm.c mono-hwcap-arm.h endif +if ARM64 +arch_sources += mono-hwcap-arm64.c mono-hwcap-arm64.h +endif + if MIPS arch_sources += mono-hwcap-mips.c mono-hwcap-mips.h endif diff --git a/mono/utils/mach-support-arm.c b/mono/utils/mach-support-arm.c index 5f242752ef7..eb1e009bfc2 100644 --- a/mono/utils/mach-support-arm.c +++ b/mono/utils/mach-support-arm.c @@ -45,66 +45,113 @@ static int tls_vector_offset; void * mono_mach_arch_get_ip (thread_state_t state) { + /* Can't use unified_thread_state on !ARM64 since this has to compile on armv6 too */ +#ifdef TARGET_ARM64 + arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; + + return (void *) arch_state->ts_64.__pc; +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; return (void *) arch_state->__pc; +#endif } void * mono_mach_arch_get_sp (thread_state_t state) { +#ifdef TARGET_ARM64 + arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; + + return (void *) arch_state->ts_64.__sp; +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; return (void *) arch_state->__sp; +#endif } int mono_mach_arch_get_mcontext_size () { +#ifdef TARGET_ARM64 + return sizeof (struct __darwin_mcontext64); +#else return sizeof (struct __darwin_mcontext); +#endif } void mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context) { +#ifdef TARGET_ARM64 + arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; + struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context; + + ctx->__ss = arch_state->ts_64; +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context; ctx->__ss = *arch_state; +#endif } void mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state) { +#ifdef TARGET_ARM64 + arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; + struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context; + + arch_state->ts_64 = ctx->__ss; +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context; *arch_state = ctx->__ss; +#endif } int mono_mach_arch_get_thread_state_size () { +#ifdef TARGET_ARM64 + return sizeof (arm_unified_thread_state_t); +#else return sizeof (arm_thread_state_t); +#endif } kern_return_t mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count) { +#ifdef TARGET_ARM64 + arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; + kern_return_t ret; + + *count = ARM_UNIFIED_THREAD_STATE_COUNT; + + ret = thread_get_state (thread, ARM_UNIFIED_THREAD_STATE, (thread_state_t) arch_state, count); +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; kern_return_t ret; *count = ARM_THREAD_STATE_COUNT; ret = thread_get_state (thread, ARM_THREAD_STATE, (thread_state_t) arch_state, count); - +#endif return ret; } kern_return_t mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count) { +#ifdef TARGET_ARM64 + return thread_set_state (thread, ARM_UNIFIED_THREAD_STATE_COUNT, state, count); +#else return thread_set_state (thread, ARM_THREAD_STATE_COUNT, state, count); +#endif } void * diff --git a/mono/utils/mach-support.h b/mono/utils/mach-support.h index 55fd9850fc2..8d8bb1e9037 100644 --- a/mono/utils/mach-support.h +++ b/mono/utils/mach-support.h @@ -15,6 +15,8 @@ #define MONO_MACH_ARCH_SUPPORTED 1 #if defined(__arm__) typedef _STRUCT_MCONTEXT *mcontext_t; +#elif defined(__aarch64__) +typedef _STRUCT_MCONTEXT64 *mcontext_t; #endif // We need to define this here since we need _XOPEN_SOURCE for mono diff --git a/mono/utils/mono-codeman.c b/mono/utils/mono-codeman.c index af2d9fbff5a..9e468bfd6e0 100644 --- a/mono/utils/mono-codeman.c +++ b/mono/utils/mono-codeman.c @@ -489,6 +489,9 @@ mono_code_manager_foreach (MonoCodeManager *cman, MonoCodeManagerFunc func, void #if defined(__arm__) #define BIND_ROOM 8 #endif +#if defined(TARGET_ARM64) +#define BIND_ROOM 8 +#endif static CodeChunk* new_codechunk (CodeChunk *last, int dynamic, int size) diff --git a/mono/utils/mono-compiler.h b/mono/utils/mono-compiler.h index a533a9f01e3..22623d074fb 100644 --- a/mono/utils/mono-compiler.h +++ b/mono/utils/mono-compiler.h @@ -83,6 +83,10 @@ #endif #elif defined(__arm__) && defined(__ARM_EABI__) && !defined(PIC) #define MONO_THREAD_VAR_OFFSET(var,offset) __asm (" ldr %0, 1f; b 2f; 1: .word " #var "(tpoff); 2:" : "=r" (offset)) +#elif defined(__aarch64__) && !defined(PIC) +#define MONO_THREAD_VAR_OFFSET(var,offset) \ + __asm ( "mov %0, #0\n add %0, %0, #:tprel_hi12:" #var "\n add %0, %0, #:tprel_lo12_nc:" #var "\n" \ + : "=r" (offset)) #elif defined(__mono_ppc__) && defined(__GNUC__) #if defined(PIC) #ifdef PIC_INITIAL_EXEC diff --git a/mono/utils/mono-context.c b/mono/utils/mono-context.c index 81f3ca84ec3..bc0286485fc 100644 --- a/mono/utils/mono-context.c +++ b/mono/utils/mono-context.c @@ -288,6 +288,38 @@ mono_monoctx_to_sigctx (MonoContext *mctx, void *ctx) #endif } +#elif (defined(__aarch64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM64)) + +#include + +void +mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) +{ +#ifdef MONO_CROSS_COMPILE + g_assert_not_reached (); +#else + memcpy (mctx->regs, UCONTEXT_GREGS (sigctx), sizeof (mgreg_t) * 31); + mctx->pc = UCONTEXT_REG_PC (sigctx); + mctx->regs [ARMREG_SP] = UCONTEXT_REG_SP (sigctx); + /* + * We don't handle fp regs, this is not currrently a + * problem, since we don't allocate them globally. + */ +#endif +} + +void +mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) +{ +#ifdef MONO_CROSS_COMPILE + g_assert_not_reached (); +#else + memcpy (UCONTEXT_GREGS (sigctx), mctx->regs, sizeof (mgreg_t) * 31); + UCONTEXT_REG_PC (sigctx) = mctx->pc; + UCONTEXT_REG_SP (sigctx) = mctx->regs [ARMREG_SP]; +#endif +} + #elif (defined(__mips__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_MIPS)) #include diff --git a/mono/utils/mono-context.h b/mono/utils/mono-context.h index 84409cf1e77..a4d29461ca6 100755 --- a/mono/utils/mono-context.h +++ b/mono/utils/mono-context.h @@ -274,6 +274,57 @@ typedef struct { ctx.pc = ctx.regs [15]; \ } while (0) +#elif (defined(__aarch64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM64)) + +#include + +typedef struct { + mgreg_t regs [32]; + double fregs [32]; + mgreg_t pc; +} MonoContext; + +#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->pc = (mgreg_t)ip; } while (0) +#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->regs [ARMREG_FP] = (mgreg_t)bp; } while (0); +#define MONO_CONTEXT_SET_SP(ctx,bp) do { (ctx)->regs [ARMREG_SP] = (mgreg_t)bp; } while (0); + +#define MONO_CONTEXT_GET_IP(ctx) (gpointer)((ctx)->pc) +#define MONO_CONTEXT_GET_BP(ctx) (gpointer)((ctx)->regs [ARMREG_FP]) +#define MONO_CONTEXT_GET_SP(ctx) (gpointer)((ctx)->regs [ARMREG_SP]) + +#define MONO_CONTEXT_GET_CURRENT(ctx) do { \ + __asm__ __volatile__( \ + "mov x16, %0\n" \ + "stp x0, x1, [x16], #16\n" \ + "stp x2, x3, [x16], #16\n" \ + "stp x4, x5, [x16], #16\n" \ + "stp x6, x7, [x16], #16\n" \ + "stp x8, x9, [x16], #16\n" \ + "stp x10, x11, [x16], #16\n" \ + "stp x12, x13, [x16], #16\n" \ + "stp x14, x15, [x16], #16\n" \ + "stp xzr, x17, [x16], #16\n" \ + "stp x18, x19, [x16], #16\n" \ + "stp x20, x21, [x16], #16\n" \ + "stp x22, x23, [x16], #16\n" \ + "stp x24, x25, [x16], #16\n" \ + "stp x26, x27, [x16], #16\n" \ + "stp x28, x29, [x16], #16\n" \ + "stp x30, xzr, [x16]\n" \ + "mov x30, sp\n" \ + "str x30, [x16, #8]\n" \ + : \ + : "r" (&ctx.regs) \ + : "x30", "memory" \ + ); \ + __asm__ __volatile__( \ + "adr %0, L0\n" \ + "L0:\n" \ + : "=r" (ctx.pc) \ + : \ + : "memory" \ + ); \ +} while (0) #elif defined(__mono_ppc__) /* defined(__arm__) */ diff --git a/mono/utils/mono-hwcap-arm64.c b/mono/utils/mono-hwcap-arm64.c new file mode 100644 index 00000000000..5149cc06943 --- /dev/null +++ b/mono/utils/mono-hwcap-arm64.c @@ -0,0 +1,24 @@ +/* + * mono-hwcap-arm64.c: ARM hardware feature detection + * + * Copyright 2013 Xamarin Inc + */ + +#include "mono/utils/mono-hwcap-arm64.h" + +#if defined(MONO_CROSS_COMPILE) +void +mono_hwcap_arch_init (void) +{ +} +#else +void +mono_hwcap_arch_init (void) +{ +} +#endif + +void +mono_hwcap_print(FILE *f) +{ +} diff --git a/mono/utils/mono-hwcap-arm64.h b/mono/utils/mono-hwcap-arm64.h new file mode 100644 index 00000000000..2d4120957cf --- /dev/null +++ b/mono/utils/mono-hwcap-arm64.h @@ -0,0 +1,6 @@ +#ifndef __MONO_UTILS_HWCAP_ARM64_H__ +#define __MONO_UTILS_HWCAP_ARM64_H__ + +#include "mono/utils/mono-hwcap.h" + +#endif diff --git a/mono/utils/mono-sigcontext.h b/mono/utils/mono-sigcontext.h index 03247cf02a6..daa82bbef37 100644 --- a/mono/utils/mono-sigcontext.h +++ b/mono/utils/mono-sigcontext.h @@ -355,6 +355,30 @@ typedef struct ucontext { #define UCONTEXT_REG_R12(ctx) (((arm_ucontext*)(ctx))->sig_ctx.arm_ip) #define UCONTEXT_REG_CPSR(ctx) (((arm_ucontext*)(ctx))->sig_ctx.arm_cpsr) #endif + +#elif defined(TARGET_ARM64) + +#if defined(MONO_CROSS_COMPILE) + #define UCONTEXT_REG_PC(ctx) NULL + #define UCONTEXT_REG_SP(ctx) NULL + #define UCONTEXT_REG_R0(ctx) NULL + #define UCONTEXT_GREGS(ctx) NULL +#elif defined(__APPLE__) +#include +#include + /* mach/arm/_structs.h */ + #define UCONTEXT_REG_PC(ctx) (((ucontext64_t*)(ctx))->uc_mcontext64->__ss.__pc) + #define UCONTEXT_REG_SP(ctx) (((ucontext64_t*)(ctx))->uc_mcontext64->__ss.__sp) + #define UCONTEXT_REG_R0(ctx) (((ucontext64_t*)(ctx))->uc_mcontext64->__ss.__x [ARMREG_R0]) + #define UCONTEXT_GREGS(ctx) (&(((ucontext64_t*)(ctx))->uc_mcontext64->__ss.__x)) +#else +#include + #define UCONTEXT_REG_PC(ctx) (((ucontext_t*)(ctx))->uc_mcontext.pc) + #define UCONTEXT_REG_SP(ctx) (((ucontext_t*)(ctx))->uc_mcontext.sp) + #define UCONTEXT_REG_R0(ctx) (((ucontext_t*)(ctx))->uc_mcontext.regs [ARMREG_R0]) + #define UCONTEXT_GREGS(ctx) (&(((ucontext_t*)(ctx))->uc_mcontext.regs)) +#endif + #elif defined(__mips__) # if HAVE_UCONTEXT_H diff --git a/mono/utils/mono-threads-mach-helper.c b/mono/utils/mono-threads-mach-helper.c index ec4220838f2..0e95d4e878e 100644 --- a/mono/utils/mono-threads-mach-helper.c +++ b/mono/utils/mono-threads-mach-helper.c @@ -72,7 +72,20 @@ mono_threads_install_dead_letter (void) dict = objc_msgSend (cur, threadDictionary); if (dict && objc_msgSend (dict, objectForKey, mono_dead_letter_key) == nil) { id value = objc_msgSend (objc_msgSend ((id)mono_dead_letter_class, alloc), init); + +#ifdef TARGET_ARM64 + /* + * See the 'Dispatch Objective-C Messages Using the Method Function’s Prototype' section in + * the '64-Bit Transition Guide for Cocoa Touch' as to why this is required. + */ + { + void (*action)(id, SEL, id, id) = (void (*)(id, SEL, id, id)) objc_msgSend; + action (dict, setObjectForKey, value, mono_dead_letter_key); + } +#else objc_msgSend (dict, setObjectForKey, value, mono_dead_letter_key); +#endif + objc_msgSend (value, release); } } @@ -84,6 +97,7 @@ mono_threads_init_dead_letter (void) id nsautoreleasepool = objc_getClass ("NSAutoreleasePool"); SEL stringWithUTF8String = sel_registerName ("stringWithUTF8String:"); SEL retain = sel_registerName ("retain"); + id pool; nsthread = (Class)objc_getClass ("NSThread"); nsobject = (Class)objc_getClass ("NSObject"); @@ -105,8 +119,17 @@ mono_threads_init_dead_letter (void) objc_registerClassPair (mono_dead_letter_class); // create the dict key - id pool = objc_msgSend (objc_msgSend (nsautoreleasepool, alloc), init); + pool = objc_msgSend (objc_msgSend (nsautoreleasepool, alloc), init); + +#ifdef TARGET_ARM64 + { + id (*action)(id, SEL, char*) = (id (*)(id, SEL, char*)) objc_msgSend; + mono_dead_letter_key = action(nsstring, stringWithUTF8String, "mono-dead-letter"); + } +#else mono_dead_letter_key = objc_msgSend (nsstring, stringWithUTF8String, "mono-dead-letter"); +#endif + objc_msgSend (mono_dead_letter_key, retain); objc_msgSend (pool, release); } diff --git a/mono/utils/mono-threads-mach.c b/mono/utils/mono-threads-mach.c index e8011d350f9..2f0e3ad5916 100644 --- a/mono/utils/mono-threads-mach.c +++ b/mono/utils/mono-threads-mach.c @@ -87,7 +87,11 @@ mono_threads_core_resume (MonoThreadInfo *info) return FALSE; mono_mach_arch_thread_state_to_mcontext (state, mctx); +#ifdef TARGET_ARM64 + g_assert_not_reached (); +#else uctx.uc_mcontext = mctx; +#endif mono_monoctx_to_sigctx (&tmp, &uctx); mono_mach_arch_mcontext_to_thread_state (mctx, state); -- 2.25.1