From: Rodrigo Kumpera Date: Mon, 29 Aug 2016 21:51:30 +0000 (-0400) Subject: Merge pull request #3478 from vargaz/fix-pedump X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=770ca46e080aecbcbaccc0be03346709c49c41cf;hp=a9c75b075ceb62e0036a940b8220cc4d1b719448;p=mono.git Merge pull request #3478 from vargaz/fix-pedump [runtime] Fix pedump by using the normal embedding APIs instead of in… --- diff --git a/docs/sources/mono-api-gc.html b/docs/sources/mono-api-gc.html index 20d6cb9dc9b..cddef0364cb 100644 --- a/docs/sources/mono-api-gc.html +++ b/docs/sources/mono-api-gc.html @@ -40,9 +40,8 @@

The output of the SCC analysis is passed to the `cross_references()` callback. It is expected to set the `is_alive` flag on those strongly connected components that it - wishes to be kept alive. Only bridged objects will be - reported to the callback, i.e., non-bridged objects are - removed from the callback graph. + wishes to be kept alive. The value of `is_alive` will be + ignored on any SCCs which lack bridges.

In monodroid each bridged object has a corresponding Java mirror object. In the bridge callback it reifies the Mono @@ -63,7 +62,7 @@

enum { - SGEN_BRIDGE_VERSION = 4 + SGEN_BRIDGE_VERSION = 5 }; typedef enum { diff --git a/mcs/class/Facades/System.Private.CoreLib.InteropServices/AssemblyInfo.cs b/mcs/class/Facades/System.Private.CoreLib.InteropServices/AssemblyInfo.cs deleted file mode 100644 index 833904b6d64..00000000000 --- a/mcs/class/Facades/System.Private.CoreLib.InteropServices/AssemblyInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -using System; -using System.Reflection; -using System.Runtime.CompilerServices; - -[assembly: AssemblyTitle ("System.Private.CoreLib.InteropServices.dll")] -[assembly: AssemblyDescription ("System.Private.CoreLib.InteropServices.dll")] -[assembly: AssemblyDefaultAlias ("System.Private.CoreLib.InteropServices.dll")] -[assembly: AssemblyCompany ("Xamarin, Inc.")] -[assembly: AssemblyProduct ("Mono Common Language Infrastructure")] -[assembly: AssemblyCopyright ("Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com)")] -[assembly: AssemblyVersion ("4.0.0.0")] -[assembly: AssemblyInformationalVersion ("4.0.0.0")] -[assembly: AssemblyFileVersion ("4.0.0.0")] -[assembly: AssemblyDelaySign (true)] -[assembly: AssemblyKeyFile ("../../msfinal.pub")] diff --git a/mcs/class/Facades/System.Private.CoreLib.InteropServices/Facades_System.Private.CoreLib.InteropServices-net_4_x.csproj b/mcs/class/Facades/System.Private.CoreLib.InteropServices/Facades_System.Private.CoreLib.InteropServices-net_4_x.csproj deleted file mode 100644 index c81a0356846..00000000000 --- a/mcs/class/Facades/System.Private.CoreLib.InteropServices/Facades_System.Private.CoreLib.InteropServices-net_4_x.csproj +++ /dev/null @@ -1,94 +0,0 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {5D05F5E2-7378-4A35-B1A3-76ABEB4A71C3} - Library - 1699,1616,1699 - ./../../../class/lib/net_4_x/Facades - obj-Facades - false - True - - True - - Properties - - - System.Private.CoreLib.InteropServices - v4.5 - 512 - - - true - true - - - ../../msfinal.pub - - - true - full - 1699,1616,1699 - false - TRACE;NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE - prompt - 4 - - - pdbonly - 1699,1616,1699 - true - NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE - prompt - 4 - - - - false - - - - - - - - - - - - - - - - - - - - - - - {2CA6026B-2DC8-4C4C-A12C-1E8234049DB7} - corlib-net_4_x - - - {2762E921-91A8-4C87-91E9-BA628013F753} - System-net_4_x - - - - - - - diff --git a/mcs/class/Facades/System.Private.CoreLib.InteropServices/Makefile b/mcs/class/Facades/System.Private.CoreLib.InteropServices/Makefile deleted file mode 100644 index 7b03ca8fdb0..00000000000 --- a/mcs/class/Facades/System.Private.CoreLib.InteropServices/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -MCS_BUILD_DIR = ../../../build - -thisdir = class/Facades/System.Private.CoreLib.InteropServices -SUBDIRS = -include $(MCS_BUILD_DIR)/rules.make - -LIBRARY_SUBDIR = Facades -LIBRARY_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)/Facades - -LIBRARY = System.Private.CoreLib.InteropServices.dll - -KEY_FILE = ../../msfinal.pub -SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 -LIB_REFS = System -LIB_MCS_FLAGS = $(SIGN_FLAGS) - -PLATFORM_DEBUG_FLAGS = - -NO_TEST = yes - -include $(MCS_BUILD_DIR)/library.make - - diff --git a/mcs/class/Facades/System.Private.CoreLib.InteropServices/System.Private.CoreLib.InteropServices-net_4_x.csproj b/mcs/class/Facades/System.Private.CoreLib.InteropServices/System.Private.CoreLib.InteropServices-net_4_x.csproj deleted file mode 100644 index 48133309056..00000000000 --- a/mcs/class/Facades/System.Private.CoreLib.InteropServices/System.Private.CoreLib.InteropServices-net_4_x.csproj +++ /dev/null @@ -1,96 +0,0 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {BE4A05DF-5630-4E80-9521-7B4216229A60} - Library - 1699,1616,1699 - ./../../../class/lib/net_4_x/Facades - True - True - - Properties - - - System.Private.CoreLib.InteropServices - v4.5 - 512 - - - true - true - - - ../../msfinal.pub - - - true - full - 1699,1616,1699 - false - DEBUG;TRACE;NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE - prompt - 4 - - - pdbonly - 1699,1616,1699 - true - NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE - prompt - 4 - - - - false - - - - - - - - - - - - - - - - - - - - - - - - {2CA6026B-2DC8-4C4C-A12C-1E8234049DB7} - corlib-net_4_x - - - {2CA6026B-2DC8-4C4C-A12C-1E8234049DB7} - corlib-net_4_x - - - {2762E921-91A8-4C87-91E9-BA628013F753} - System-net_4_x - - - - - - - diff --git a/mcs/class/Facades/System.Private.CoreLib.InteropServices/System.Private.CoreLib.InteropServices.dll.sources b/mcs/class/Facades/System.Private.CoreLib.InteropServices/System.Private.CoreLib.InteropServices.dll.sources deleted file mode 100644 index 8e33d4ddeae..00000000000 --- a/mcs/class/Facades/System.Private.CoreLib.InteropServices/System.Private.CoreLib.InteropServices.dll.sources +++ /dev/null @@ -1,3 +0,0 @@ -TypeForwarders.cs -AssemblyInfo.cs - diff --git a/mcs/class/Facades/System.Private.CoreLib.InteropServices/TypeForwarders.cs b/mcs/class/Facades/System.Private.CoreLib.InteropServices/TypeForwarders.cs deleted file mode 100644 index 7a1269d2c14..00000000000 --- a/mcs/class/Facades/System.Private.CoreLib.InteropServices/TypeForwarders.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.CallingConvention))] -[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.DllImportAttribute))] -[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.GCHandle))] -[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.GCHandleType))] -[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.SafeHandle))] - -//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(Internal.Reflection.Execution.PayForPlayExperience.MissingMetadataExceptionCreator))] -//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.CompilerServices.DependencyReductionTypeRemoved))] -//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.CompilerServices.PreInitializedAttribute))] -//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.InteropExtensions))] -//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.NativeCallableAttributes))] -//Missing: [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.RuntimeImportAttribute))] diff --git a/mcs/class/Facades/subdirs.make b/mcs/class/Facades/subdirs.make index df1dd020404..c980d70840d 100644 --- a/mcs/class/Facades/subdirs.make +++ b/mcs/class/Facades/subdirs.make @@ -24,7 +24,7 @@ System.Security.Cryptography.Encryption.Aes System.Security.Cryptography.Encrypt System.Security.Cryptography.Hashing.Algorithms System.Security.Cryptography.RSA System.Security.Cryptography.RandomNumberGenerator \ System.Security.Principal.Windows System.Threading.Thread System.Threading.ThreadPool \ System.Xml.XPath System.Xml.XmlDocument System.Xml.Xsl.Primitives Microsoft.Win32.Registry.AccessControl System.Diagnostics.StackTrace System.Globalization.Extensions \ -System.IO.FileSystem.AccessControl System.Private.CoreLib.InteropServices System.Reflection.TypeExtensions \ +System.IO.FileSystem.AccessControl System.Reflection.TypeExtensions \ System.Security.SecureString System.Threading.AccessControl System.Threading.Overlapped System.Xml.XPath.XDocument \ System.Security.Cryptography.Primitives System.Text.Encoding.CodePages System.IO.FileSystem.Watcher \ System.Security.Cryptography.ProtectedData System.ServiceProcess.ServiceController System.IO.Pipes diff --git a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs index e406357204f..f4e8a9705f7 100644 --- a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs +++ b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs @@ -1055,24 +1055,21 @@ namespace MonoTests.System.Threading.Tasks var token = source.Token; var evt = new ManualResetEventSlim (); bool result = false; - bool thrown = false; - var task = Task.Factory.StartNew (() => evt.Wait (100)); + var task = Task.Factory.StartNew (() => { Assert.IsTrue (evt.Wait (2000), "#1"); }); var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); source.Cancel(); evt.Set (); - task.Wait (100); + Assert.IsTrue (task.Wait (2000), "#2"); try { - cont.Wait (100); - } catch (Exception ex) { - thrown = true; + Assert.IsFalse (cont.Wait (4000), "#3"); + } catch (AggregateException ex) { } - Assert.IsTrue (task.IsCompleted); - Assert.IsTrue (cont.IsCanceled); - Assert.IsFalse (result); - Assert.IsTrue (thrown); + Assert.IsTrue (task.IsCompleted, "#4"); + Assert.IsTrue (cont.IsCanceled, "#5"); + Assert.IsFalse (result, "#6"); } [Test] diff --git a/mcs/mcs/anonymous.cs b/mcs/mcs/anonymous.cs index 80481ed2091..d27fe806048 100644 --- a/mcs/mcs/anonymous.cs +++ b/mcs/mcs/anonymous.cs @@ -1595,6 +1595,15 @@ namespace Mono.CSharp { if (res && errors != ec.Report.Errors) return null; + if (block.IsAsync && block.Original.ParametersBlock.HasCapturedThis && ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.block.IsAsync) { + // + // We'll do ldftn to load the fabricated m_X method but + // because we are inside struct the method can be hoisted + // anywhere in the parent scope + // + ec.CurrentBlock.ParametersBlock.HasReferenceToStoreyForInstanceLambdas = true; + } + return res ? this : null; } @@ -1798,6 +1807,8 @@ namespace Mono.CSharp { parent = storey = sm; } } + } else if (src_block.ParametersBlock.HasReferenceToStoreyForInstanceLambdas) { + src_block.ParametersBlock.StateMachine.AddParentStoreyReference (ec, storey); } modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE; diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs index d7105592ebb..7f54b33eeb5 100644 --- a/mcs/mcs/statement.cs +++ b/mcs/mcs/statement.cs @@ -2657,6 +2657,7 @@ namespace Mono.CSharp { AwaitBlock = 1 << 13, FinallyBlock = 1 << 14, CatchBlock = 1 << 15, + HasReferenceToStoreyForInstanceLambdas = 1 << 16, Iterator = 1 << 20, NoFlowAnalysis = 1 << 21, InitializationEmitted = 1 << 22 @@ -3281,7 +3282,7 @@ namespace Mono.CSharp { break; } } - + // // We are the first storey on path and 'this' has to be hoisted // @@ -3349,7 +3350,7 @@ namespace Mono.CSharp { // // If we are state machine with no parent. We can hook into parent without additional - // reference and capture this directly + // reference and capture this directly // ExplicitBlock parent_storey_block = pb; while (parent_storey_block.Parent != null) { @@ -3666,6 +3667,15 @@ namespace Mono.CSharp { #region Properties + public bool HasReferenceToStoreyForInstanceLambdas { + get { + return (flags & Flags.HasReferenceToStoreyForInstanceLambdas) != 0; + } + set { + flags = value ? flags | Flags.HasReferenceToStoreyForInstanceLambdas : flags & ~Flags.HasReferenceToStoreyForInstanceLambdas; + } + } + public bool IsAsync { get { return (flags & Flags.HasAsyncModifier) != 0; diff --git a/mcs/tests/test-async-89.cs b/mcs/tests/test-async-89.cs new file mode 100644 index 00000000000..5a69685ca94 --- /dev/null +++ b/mcs/tests/test-async-89.cs @@ -0,0 +1,51 @@ +using System; +using System.Threading.Tasks; + +class X +{ + public static void Main () + { + new X ().Test (); + } + + void Test () + { + object v1 = null; + + Action a = () => + { + if (v1 == null) + { + object v2 = null; + + Action a2 = () => + { + Console.WriteLine (v2); + }; + + Action a3 = async () => + { + // This scope needs to access to Scope which can do ldftn on instance method + { + Func a4 = async () => + { + await Foo (); + }; + } + + await Task.Yield (); + }; + + a3 (); + } + }; + + a (); + } + + async Task Foo () + { + await Task.FromResult (1); + } + +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_x.xml b/mcs/tests/ver-il-net_4_x.xml index 270fe53c92f..cde4e9e70d6 100644 --- a/mcs/tests/ver-il-net_4_x.xml +++ b/mcs/tests/ver-il-net_4_x.xml @@ -66190,6 +66190,68 @@ + + + + 12 + + + 41 + + + 33 + + + 7 + + + + + 67 + + + 7 + + + + + 158 + + + 13 + + + + + 13 + + + 48 + + + 46 + + + 7 + + + + + 179 + + + 13 + + + + + 167 + + + 13 + + + diff --git a/mcs/tools/al/Al.cs b/mcs/tools/al/Al.cs index bdc741144ea..3670d2f2eb9 100644 --- a/mcs/tools/al/Al.cs +++ b/mcs/tools/al/Al.cs @@ -13,14 +13,13 @@ using System.Globalization; using System.IO; using System.Collections; using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; using System.Security.Cryptography; using System.Text; using System.Configuration.Assemblies; +using IKVM.Reflection; +using IKVM.Reflection.Emit; using Mono.Security.Cryptography; -using IKR = IKVM.Reflection; namespace Mono.AssemblyLinker { @@ -49,6 +48,15 @@ namespace Mono.AssemblyLinker No } + public enum Platform { + AnyCPU, + AnyCPU32Preferred, + Arm, + X86, + X64, + IA64 + } + public class AssemblyLinker { ArrayList inputFiles = new ArrayList (); @@ -59,24 +67,35 @@ namespace Mono.AssemblyLinker string entryPoint; string win32IconFile; string win32ResFile; + string title; + string description; + string company; + string product; + string copyright; + string trademark; string templateFile; bool isTemplateFile = false; Target target = Target.Dll; + Platform platform = Platform.AnyCPU; DelaySign delaysign = DelaySign.NotSet; string keyfile; string keyname; string culture; + Universe universe; public static int Main (String[] args) { return new AssemblyLinker ().DynMain (args); } private int DynMain (String[] args) { - ParseArgs (args); + using (universe = new Universe (UniverseOptions.MetadataOnly)) { + universe.LoadFile (typeof (object).Assembly.Location); + ParseArgs (args); - DoIt (); + DoIt (); - return 0; + return 0; + } } private void ParseArgs (string[] args) @@ -211,7 +230,7 @@ namespace Mono.AssemblyLinker if (realArg.StartsWith ("0x")) realArg = realArg.Substring (2); uint val = Convert.ToUInt32 (realArg, 16); - AddCattr (typeof (AssemblyAlgorithmIdAttribute), typeof (uint), val); + AddCattr (typeof (System.Reflection.AssemblyAlgorithmIdAttribute), typeof (uint), val); } catch (Exception) { ReportInvalidArgument (opt, arg); } @@ -233,21 +252,21 @@ namespace Mono.AssemblyLinker case "company": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyCompanyAttribute), arg); + company = arg; return true; case "config": case "configuration": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyConfigurationAttribute), arg); + AddCattr (typeof (System.Reflection.AssemblyConfigurationAttribute), arg); return true; case "copy": case "copyright": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyCopyrightAttribute), arg); + copyright = arg; return true; case "c": @@ -273,7 +292,7 @@ namespace Mono.AssemblyLinker case "description": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyDescriptionAttribute), arg); + description = arg; return true; case "e": @@ -292,7 +311,7 @@ namespace Mono.AssemblyLinker if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyFileVersionAttribute), arg); + AddCattr (typeof (System.Reflection.AssemblyFileVersionAttribute), arg); return true; case "flags": @@ -303,7 +322,7 @@ namespace Mono.AssemblyLinker if (realArg.StartsWith ("0x")) realArg = realArg.Substring (2); uint val = Convert.ToUInt32 (realArg, 16); - AddCattr (typeof (AssemblyFlagsAttribute), typeof (uint), val); + AddCattr (typeof (System.Reflection.AssemblyFlagsAttribute), typeof (uint), val); } catch (Exception) { ReportInvalidArgument (opt, arg); } @@ -342,18 +361,46 @@ namespace Mono.AssemblyLinker outFile = arg; return true; + case "platform": + if (arg == null) + ReportMissingText (opt); + switch (arg.ToLowerInvariant ()) { + case "arm": + platform = Platform.Arm; + break; + case "anycpu": + platform = Platform.AnyCPU; + break; + case "x86": + platform = Platform.X86; + break; + case "x64": + platform = Platform.X64; + break; + case "itanium": + platform = Platform.IA64; + break; + case "anycpu32bitpreferred": + platform = Platform.AnyCPU32Preferred; + break; + default: + ReportInvalidArgument (opt, arg); + break; + } + return true; + case "prod": case "product": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyProductAttribute), arg); + product = arg; return true; case "productv": case "productversion": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyInformationalVersionAttribute), arg); + AddCattr (typeof (System.Reflection.AssemblyInformationalVersionAttribute), arg); return true; case "t": @@ -388,14 +435,14 @@ namespace Mono.AssemblyLinker case "title": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyTitleAttribute), arg); + title = arg; return true; case "trade": case "trademark": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyTrademarkAttribute), arg); + trademark = arg; return true; case "v": @@ -405,7 +452,7 @@ namespace Mono.AssemblyLinker Version (); break; } - AddCattr (typeof (AssemblyVersionAttribute), arg); + AddCattr (typeof (System.Reflection.AssemblyVersionAttribute), arg); return true; case "win32icon": @@ -461,11 +508,14 @@ namespace Mono.AssemblyLinker return command.ToLower (); } - private void AddCattr (Type attrType, Type arg, object value) { - cattrs.Add (new CustomAttributeBuilder (attrType.GetConstructor (new Type [] { arg }), new object [] { value })); + private void AddCattr (System.Type attrType, System.Type arg, object value) { + var importedAttrType = universe.Import(attrType); + var importedArg = universe.Import(arg); + + cattrs.Add (new CustomAttributeBuilder (importedAttrType.GetConstructor (new [] { importedArg }), new [] { value })); } - private void AddCattr (Type attrType, object value) { + private void AddCattr (System.Type attrType, object value) { AddCattr (attrType, typeof (string), value); } @@ -596,12 +646,25 @@ namespace Mono.AssemblyLinker if (isTemplateFile) aname = ReadCustomAttributesFromTemplateFile (templateFile, aname); + if (!String.IsNullOrEmpty (title)) + AddCattr (typeof (System.Reflection.AssemblyTitleAttribute), title); + if (!String.IsNullOrEmpty (description)) + AddCattr (typeof (System.Reflection.AssemblyDescriptionAttribute), description); + if (!String.IsNullOrEmpty (company)) + AddCattr (typeof (System.Reflection.AssemblyCompanyAttribute), company); + if (!String.IsNullOrEmpty (product)) + AddCattr (typeof (System.Reflection.AssemblyProductAttribute), product); + if (!String.IsNullOrEmpty (copyright)) + AddCattr (typeof (System.Reflection.AssemblyCopyrightAttribute), copyright); + if (!String.IsNullOrEmpty (trademark)) + AddCattr (typeof (System.Reflection.AssemblyTrademarkAttribute), trademark); + SetKeyPair (aname); if (fileName != outFile) - ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save, Path.GetDirectoryName (outFile)); + ab = universe.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save, Path.GetDirectoryName (outFile)); else - ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save); + ab = universe.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save); foreach (CustomAttributeBuilder cb in cattrs) ab.SetCustomAttribute (cb); @@ -611,10 +674,6 @@ namespace Mono.AssemblyLinker */ foreach (ModuleInfo mod in inputFiles) { - MethodInfo mi = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic); - if (mi == null) - Report (0, "Cannot add modules on this runtime: try the Mono runtime instead."); - if (mod.target != null) { File.Copy (mod.fileName, mod.target, true); mod.fileName = mod.target; @@ -631,7 +690,7 @@ namespace Mono.AssemblyLinker if (isAssembly) ReportWarning (1020, "Ignoring included assembly '" + mod.fileName + "'"); else - mi.Invoke (ab, new object [] { mod.fileName }); + ab.__AddModule (universe.OpenRawModule(mod.fileName)); } /* @@ -645,7 +704,7 @@ namespace Mono.AssemblyLinker MethodInfo mainMethodInfo = null; try { - Type mainType = ab.GetType (mainClass); + IKVM.Reflection.Type mainType = ab.GetType (mainClass); if (mainType != null) mainMethodInfo = mainType.GetMethod (mainMethod); } @@ -666,10 +725,7 @@ namespace Mono.AssemblyLinker if (win32IconFile != null) { try { - MethodInfo mi = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic); - if (mi == null) - Report (0, "Cannot embed win32 icons on this runtime: try the Mono runtime instead."); - mi.Invoke (ab, new object [] { win32IconFile }); + ab.__DefineIconResource (File.ReadAllBytes (win32IconFile)); } catch (Exception ex) { Report (1031, "Error reading icon '" + win32IconFile + "' --" + ex); @@ -685,6 +741,8 @@ namespace Mono.AssemblyLinker } } + ModuleBuilder mainModule = null; + foreach (ResourceInfo res in resources) { if (res.name == null) res.name = Path.GetFileName (res.fileName); @@ -694,11 +752,13 @@ namespace Mono.AssemblyLinker Report (1046, String.Format ("Resource identifier '{0}' has already been used in this assembly", res.name)); if (res.isEmbedded) { - MethodInfo mi = typeof (AssemblyBuilder).GetMethod ("EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic, - null, CallingConventions.Any, new Type [] { typeof (string), typeof (string) }, null); - if (mi == null) - Report (0, "Cannot embed resources on this runtime: try the Mono runtime instead."); - mi.Invoke (ab, new object [] { res.name, res.fileName }); + if (mainModule == null) { + mainModule = ab.DefineDynamicModule (fileName, fileName, false); + } + + Stream stream = new MemoryStream (File.ReadAllBytes (res.fileName)); + + mainModule.DefineManifestResource (res.name, stream, res.isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public); } else { if (res.target != null) { @@ -721,8 +781,36 @@ namespace Mono.AssemblyLinker } } + PortableExecutableKinds pekind = PortableExecutableKinds.ILOnly; + ImageFileMachine machine; + + switch (platform) { + case Platform.X86: + pekind |= PortableExecutableKinds.Required32Bit; + machine = ImageFileMachine.I386; + break; + case Platform.X64: + pekind |= PortableExecutableKinds.PE32Plus; + machine = ImageFileMachine.AMD64; + break; + case Platform.IA64: + machine = ImageFileMachine.IA64; + break; + case Platform.AnyCPU32Preferred: + pekind |= PortableExecutableKinds.Preferred32Bit; + machine = ImageFileMachine.I386; + break; + case Platform.Arm: + machine = ImageFileMachine.ARM; + break; + case Platform.AnyCPU: + default: + machine = ImageFileMachine.I386; + break; + } + try { - ab.Save (fileName); + ab.Save (fileName, pekind, machine); } catch (Exception ex) { Report (1019, "Metadata failure creating assembly -- " + ex); @@ -733,17 +821,14 @@ namespace Mono.AssemblyLinker { // LAMESPEC: according to MSDN, the template assembly must have a // strong name but this is not enforced - const IKR.UniverseOptions options = IKR.UniverseOptions.MetadataOnly; - - var universe = new IKR.Universe (options); var asm = universe.LoadFile (templateFile); // Create missing assemblies, we don't want to load them! // Code taken from ikdasm var names = new HashSet (); - IKR.AssemblyName[] assembly_refs = asm.ManifestModule.__GetReferencedAssemblies (); + AssemblyName[] assembly_refs = asm.ManifestModule.__GetReferencedAssemblies (); - var resolved_assemblies = new IKR.Assembly [assembly_refs.Length]; + var resolved_assemblies = new Assembly [assembly_refs.Length]; for (int i = 0; i < resolved_assemblies.Length; i++) { string name = assembly_refs [i].Name; @@ -798,6 +883,85 @@ namespace Mono.AssemblyLinker keyname = key_name_value; } break; + + case "System.Reflection.AssemblyTitleAttribute": { + if (title != null) + // ignore if specified on command line + continue; + + // AssemblyTitleAttribute .ctor(string title) + string title_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (title_value)) + title = title_value; + } + break; + + case "System.Reflection.AssemblyDescriptionAttribute": { + if (description != null) + // ignore if specified on command line + continue; + + // AssemblyDescriptionAttribute .ctor(string description) + string description_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (description_value)) + description = description_value; + } + break; + + case "System.Reflection.AssemblyProductAttribute": { + if (product != null) + // ignore if specified on command line + continue; + + // AssemblyProductAttribute .ctor(string product) + string product_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (product_value)) + product = product_value; + } + break; + + case "System.Reflection.AssemblyCompanyAttribute": { + if (company != null) + // ignore if specified on command line + continue; + + // AssemblyCompanyAttribute .ctor(string company) + string company_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (company_value)) + company = company_value; + + } + break; + + case "System.Reflection.AssemblyCopyrightAttribute": { + if (copyright != null) + // ignore if specified on command line + continue; + + // AssemblyCopyrightAttribute .ctor(string copyright) + string copyright_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (copyright_value)) + copyright = copyright_value; + } + break; + + case "System.Reflection.AssemblyTrademarkAttribute": { + if (trademark != null) + // ignore if specified on command line + continue; + + // AssemblyTrademarkAttribute .ctor(string trademark) + string trademark_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (trademark_value)) + trademark = trademark_value; + } + break; } } @@ -877,6 +1041,9 @@ namespace Mono.AssemblyLinker " /main: Specifies the method name of the entry point", " /nologo Suppress the startup banner and copyright message", " /out: Output file name for the assembly manifest", + " /platform: Limit which platforms this code can run on; must be", + " one of x86, Itanium, x64, arm, anycpu32bitpreferred,", + " or anycpu (the default)", " /prod[uct]: Product name", " /productv[ersion]: Product version", " /t[arget]:lib[rary] Create a library", diff --git a/mono/metadata/sgen-bridge-internals.h b/mono/metadata/sgen-bridge-internals.h index 0597bdd7882..09224b2f15b 100644 --- a/mono/metadata/sgen-bridge-internals.h +++ b/mono/metadata/sgen-bridge-internals.h @@ -33,9 +33,16 @@ void sgen_bridge_describe_pointer (GCObject *object); gboolean sgen_is_bridge_object (GCObject *obj); void sgen_mark_bridge_object (GCObject *obj); +gboolean sgen_bridge_handle_gc_param (const char *opt); gboolean sgen_bridge_handle_gc_debug (const char *opt); void sgen_bridge_print_gc_debug_usage (void); +typedef struct { + char *dump_prefix; + gboolean accounting; + gboolean scc_precise_merge; // Used by Tarjan +} SgenBridgeProcessorConfig; + typedef struct { void (*reset_data) (void); void (*processing_stw_step) (void); @@ -44,10 +51,9 @@ typedef struct { MonoGCBridgeObjectKind (*class_kind) (MonoClass *klass); void (*register_finalized_object) (GCObject *object); void (*describe_pointer) (GCObject *object); - void (*enable_accounting) (void); - // Optional-- used for debugging - void (*set_dump_prefix) (const char *prefix); + /* Should be called once, immediately after init */ + void (*set_config) (const SgenBridgeProcessorConfig *); /* * These are set by processing_build_callback_data(). diff --git a/mono/metadata/sgen-bridge.c b/mono/metadata/sgen-bridge.c index 006e68c5012..7ec2d4386df 100644 --- a/mono/metadata/sgen-bridge.c +++ b/mono/metadata/sgen-bridge.c @@ -33,6 +33,8 @@ typedef enum { static BridgeProcessorSelection bridge_processor_selection = BRIDGE_PROCESSOR_DEFAULT; // Most recently requested callbacks static MonoGCBridgeCallbacks pending_bridge_callbacks; +// Configuration to be passed to bridge processor after init +static SgenBridgeProcessorConfig bridge_processor_config; // Currently-in-use callbacks MonoGCBridgeCallbacks bridge_callbacks; @@ -84,6 +86,12 @@ bridge_processor_name (const char *name) } } +static gboolean +bridge_processor_started () +{ + return bridge_processor.reset_data != NULL; +} + // Initialize a single bridge processor static void init_bridge_processor (SgenBridgeProcessor *processor, BridgeProcessorSelection selection) @@ -133,9 +141,17 @@ sgen_init_bridge () bridge_callbacks = pending_bridge_callbacks; // If a bridge was registered but there is no bridge processor yet - if (bridge_callbacks.cross_references && !bridge_processor.reset_data) + if (bridge_callbacks.cross_references && !bridge_processor_started ()) { init_bridge_processor (&bridge_processor, bridge_processor_selection); + if (bridge_processor.set_config) + bridge_processor.set_config (&bridge_processor_config); + + // Config is no longer needed so free its memory + free (bridge_processor_config.dump_prefix); + bridge_processor_config.dump_prefix = NULL; + } + sgen_gc_unlock (); } } @@ -147,7 +163,7 @@ sgen_set_bridge_implementation (const char *name) if (selection == BRIDGE_PROCESSOR_INVALID) g_warning ("Invalid value for bridge processor implementation, valid values are: 'new', 'old' and 'tarjan'."); - else if (bridge_processor.reset_data) + else if (bridge_processor_started ()) g_warning ("Cannot set bridge processor implementation once bridge has already started"); else bridge_processor_selection = selection; @@ -480,12 +496,9 @@ sgen_bridge_describe_pointer (GCObject *obj) static void set_dump_prefix (const char *prefix) { - if (!bridge_processor.set_dump_prefix) { - fprintf (stderr, "Warning: Bridge implementation does not support dumping - ignoring.\n"); - return; - } - - bridge_processor.set_dump_prefix (prefix); + if (bridge_processor_config.dump_prefix) + free (bridge_processor_config.dump_prefix); + bridge_processor_config.dump_prefix = strdup (prefix); } /* Test support code */ @@ -652,22 +665,39 @@ register_test_bridge_callbacks (const char *bridge_class_name) mono_gc_register_bridge_callbacks (&callbacks); } +gboolean +sgen_bridge_handle_gc_param (const char *opt) +{ + g_assert (!bridge_processor_started ()); + + if (!strcmp (opt, "bridge-require-precise-merge")) { + bridge_processor_config.scc_precise_merge = TRUE; + } else { + return FALSE; + } + + return TRUE; +} + gboolean sgen_bridge_handle_gc_debug (const char *opt) { + g_assert (!bridge_processor_started ()); + if (g_str_has_prefix (opt, "bridge=")) { opt = strchr (opt, '=') + 1; register_test_bridge_callbacks (g_strdup (opt)); } else if (!strcmp (opt, "enable-bridge-accounting")) { - bridge_processor.enable_accounting (); + bridge_processor_config.accounting = TRUE; } else if (g_str_has_prefix (opt, "bridge-dump=")) { char *prefix = strchr (opt, '=') + 1; - set_dump_prefix (prefix); + set_dump_prefix(prefix); } else if (g_str_has_prefix (opt, "bridge-compare-to=")) { const char *name = strchr (opt, '=') + 1; BridgeProcessorSelection selection = bridge_processor_name (name); if (selection != BRIDGE_PROCESSOR_INVALID) { + // Compare processor doesn't get config init_bridge_processor (&compare_to_bridge_processor, selection); } else { g_warning ("Invalid bridge implementation to compare against - ignoring."); diff --git a/mono/metadata/sgen-bridge.h b/mono/metadata/sgen-bridge.h index b11df8a17b5..a03b0a81bfd 100644 --- a/mono/metadata/sgen-bridge.h +++ b/mono/metadata/sgen-bridge.h @@ -17,8 +17,8 @@ * When SGen is done marking, it puts together a list of all dead bridged * objects. This is passed to the bridge processor, which does an analysis to * simplify the graph: It replaces strongly-connected components with single - * nodes, and then removes any nodes corresponding to components which do not - * contain bridged objects. + * nodes, and may remove nodes corresponding to components which do not contain + * bridged objects. * * The output of the SCC analysis is passed to the client's `cross_references()` * callback. This consists of 2 arrays, an array of SCCs (MonoGCBridgeSCC), @@ -54,7 +54,7 @@ MONO_BEGIN_DECLS enum { - SGEN_BRIDGE_VERSION = 4 + SGEN_BRIDGE_VERSION = 5 }; typedef enum { diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index 19265f57ef4..f80cc360319 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -2896,7 +2896,7 @@ sgen_client_handle_gc_param (const char *opt) } else if (g_str_has_prefix (opt, "toggleref-test")) { /* FIXME: This should probably in MONO_GC_DEBUG */ sgen_register_test_toggleref_callback (); - } else { + } else if (!sgen_bridge_handle_gc_param (opt)) { return FALSE; } return TRUE; diff --git a/mono/metadata/sgen-new-bridge.c b/mono/metadata/sgen-new-bridge.c index 4631c0c5430..501ceb76d5b 100644 --- a/mono/metadata/sgen-new-bridge.c +++ b/mono/metadata/sgen-new-bridge.c @@ -101,6 +101,8 @@ typedef struct _SCC { #endif } SCC; +static char *dump_prefix = NULL; + // Maps managed objects to corresponding HashEntry stricts static SgenHashTable hash_table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntry), mono_aligned_addr_hash, NULL); @@ -161,11 +163,16 @@ dyn_array_int_contains (DynIntArray *da, int x) #endif static void -enable_accounting (void) +set_config (const SgenBridgeProcessorConfig *config) { - SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL); - bridge_accounting_enabled = TRUE; - hash_table = table; + if (config->accounting) { + SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL); + bridge_accounting_enabled = TRUE; + hash_table = table; + } + if (config->dump_prefix) { + dump_prefix = strdup (config->dump_prefix); + } } static MonoGCBridgeObjectKind @@ -604,8 +611,6 @@ reset_flags (SCC *scc) } #endif -static char *dump_prefix = NULL; - static void dump_graph (void) { @@ -657,12 +662,6 @@ dump_graph (void) fclose (file); } -static void -set_dump_prefix (const char *prefix) -{ - dump_prefix = strdup (prefix); -} - static int compare_hash_entries (const HashEntry *e1, const HashEntry *e2) { @@ -1087,8 +1086,7 @@ sgen_new_bridge_init (SgenBridgeProcessor *collector) collector->class_kind = class_kind; collector->register_finalized_object = register_finalized_object; collector->describe_pointer = describe_pointer; - collector->enable_accounting = enable_accounting; - collector->set_dump_prefix = set_dump_prefix; + collector->set_config = set_config; bridge_processor = collector; } diff --git a/mono/metadata/sgen-old-bridge.c b/mono/metadata/sgen-old-bridge.c index d33d5d86815..346e4b0aeb5 100644 --- a/mono/metadata/sgen-old-bridge.c +++ b/mono/metadata/sgen-old-bridge.c @@ -372,11 +372,13 @@ dyn_array_int_merge_one (DynIntArray *array, int value) static void -enable_accounting (void) +set_config (const SgenBridgeProcessorConfig *config) { - SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL); - bridge_accounting_enabled = TRUE; - hash_table = table; + if (config->accounting) { + SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL); + bridge_accounting_enabled = TRUE; + hash_table = table; + } } static MonoGCBridgeObjectKind @@ -922,7 +924,7 @@ sgen_old_bridge_init (SgenBridgeProcessor *collector) collector->class_kind = class_kind; collector->register_finalized_object = register_finalized_object; collector->describe_pointer = describe_pointer; - collector->enable_accounting = enable_accounting; + collector->set_config = set_config; bridge_processor = collector; } diff --git a/mono/metadata/sgen-tarjan-bridge.c b/mono/metadata/sgen-tarjan-bridge.c index 76c5ac64a90..daa983e64ac 100644 --- a/mono/metadata/sgen-tarjan-bridge.c +++ b/mono/metadata/sgen-tarjan-bridge.c @@ -19,8 +19,6 @@ #include "sgen/sgen-gc.h" #include "sgen-bridge-internals.h" -#include "sgen/sgen-hash-table.h" -#include "sgen/sgen-qsort.h" #include "tabledefs.h" #include "utils/mono-logger-internals.h" @@ -41,13 +39,6 @@ * which colors. The color graph then becomes the reduced SCC graph. */ -static void -enable_accounting (void) -{ - // bridge_accounting_enabled = TRUE; - // hash_table = (SgenHashTable)SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL); -} - // Is this class bridged or not, and should its dependencies be scanned or not? // The result of this callback will be cached for use by is_opaque_object later. static MonoGCBridgeObjectKind @@ -83,6 +74,36 @@ class_kind (MonoClass *klass) //enable usage logging // #define DUMP_GRAPH 1 +/* Used in bridgeless_color_is_heavy: + * The idea here is as long as the reference fanin and fanout on a node are both 2 or greater, then + * removing that node will result in a net increase in edge count. So the question is which node + * removals are counterproductive (i.e., how many edges saved balances out one node added). + * The number of edges saved by preserving a node is (fanin*fanout - fanin - fanout). + * + * With all that in mind: + * + * - HEAVY_REFS_MIN is the number that *both* fanin and fanout must meet to preserve the node. + * - HEAVY_COMBINED_REFS_MIN is the number (fanin*fanout) must meet to preserve the node. + * + * Note HEAVY_COMBINED_REFS_MIN must be <= 2*INCOMING_COLORS_MAX, or we won't know the true fanin. + */ + +#define HEAVY_REFS_MIN 2 +#define HEAVY_COMBINED_REFS_MIN 60 + +/* Used in ColorData: + * The higher INCOMING_COLORS_BITS is the higher HEAVY_COMBINED_REFS_MIN can be (see above). + * However, API_INDEX_BITS + INCOMING_COLORS_BITS must be equal to 31, and if API_INDEX_BITS is too + * low then terrible things will happen if too many colors are generated. (The number of colors we + * will ever attempt to generate is currently naturally limited by the JNI GREF limit.) + */ + +#define API_INDEX_BITS 26 +#define INCOMING_COLORS_BITS 5 + +#define API_INDEX_MAX ((1<incoming_colors; + int fanout = dyn_array_ptr_size (&data->other_colors); + return fanin > HEAVY_REFS_MIN && fanout > HEAVY_REFS_MIN + && fanin*fanout >= HEAVY_COMBINED_REFS_MIN; +} +// Should color be made visible to client? +static inline gboolean +color_visible_to_client (ColorData *data) { + return dyn_array_ptr_size (&data->bridges) || bridgeless_color_is_heavy (data); +} // Stacks of ScanData objects used for tarjan algorithm. // The Tarjan algorithm is normally defined recursively; here scan_stack simulates the call stack of a recursive algorithm, @@ -134,12 +174,21 @@ static DynPtrArray scan_stack, loop_stack; // GCObjects on which register_finalized_object has been called static DynPtrArray registered_bridges; -// ColorData objects +// As we traverse the graph, which ColorData objects are accessible from our current position? static DynPtrArray color_merge_array; +// Running hash of the contents of the color_merge_array. +static unsigned int color_merge_array_hash; + +static void color_merge_array_empty () +{ + dyn_array_ptr_empty (&color_merge_array); + color_merge_array_hash = 0; +} static int ignored_objects; static int object_index; static int num_colors_with_bridges; +static int num_sccs; static int xref_count; static size_t setup_time, tarjan_time, scc_setup_time, gather_xref_time, xref_setup_time, cleanup_time; @@ -161,6 +210,7 @@ static ObjectBucket *root_object_bucket; static ObjectBucket *cur_object_bucket; static int object_data_count; +// Arenas to allocate ScanData from static ObjectBucket* new_object_bucket (void) { @@ -213,7 +263,7 @@ free_object_buckets (void) //ColorData buckets #define NUM_COLOR_ENTRIES ((BUCKET_SIZE - SIZEOF_VOID_P * 2) / sizeof (ColorData)) -// Same as ObjectBucket except NUM_COLOR_ENTRIES and NUM_SCAN_ENTRIES differ +// Arenas for ColorDatas, same as ObjectBucket except items-per-bucket differs typedef struct _ColorBucket ColorBucket; struct _ColorBucket { ColorBucket *next; @@ -356,11 +406,13 @@ find_or_create_data (GCObject *obj) //---------- typedef struct { ColorData *color; - int hash; + unsigned int hash; } HashEntry; /* -We tried 2/32, 2/128, 4/32, 4/128, 6/128 and 8/128. +The merge cache maps an ordered list of ColorDatas [the color_merge_array] to a single ColorData. + +About cache bucket tuning: We tried 2/32, 2/128, 4/32, 4/128, 6/128 and 8/128. The performance cost between 4/128 and 8/128 is so small since cache movement happens completely in the same cacheline, making the extra space pretty much free. @@ -373,17 +425,39 @@ Memory wise, 4/32 takes 512 and 8/128 takes 8k, so it's quite reasonable. #define ELEMENTS_PER_BUCKET 8 #define COLOR_CACHE_SIZE 128 static HashEntry merge_cache [COLOR_CACHE_SIZE][ELEMENTS_PER_BUCKET]; +static unsigned int hash_perturb; + +// If true, disable an optimization where sometimes SCC nodes are merged without a perfect check +static gboolean scc_precise_merge; -static int -mix_hash (size_t hash) +static unsigned int +mix_hash (uintptr_t source) { - return (int)(((hash * 215497) >> 16) ^ ((hash * 1823231) + hash)); + unsigned int hash = source; + + // The full hash determines whether two colors can be merged-- sometimes exclusively. + // This value changes every GC, so XORing it in before performing the hash will make the + // chance that two different colors will produce the same hash on successive GCs very low. + hash = hash ^ hash_perturb; + + // Actual hash + hash = (((hash * 215497) >> 16) ^ ((hash * 1823231) + hash)); + + // Mix in highest bits on 64-bit systems only + if (sizeof (source) > 4) + hash = hash ^ (source >> 32); + + return hash; } static void reset_cache (void) { memset (merge_cache, 0, sizeof (merge_cache)); + + // When using the precise merge debug option, we do not want the inconsistency caused by hash_perturb. + if (!scc_precise_merge) + ++hash_perturb; } @@ -397,6 +471,13 @@ dyn_array_ptr_contains (DynPtrArray *da, void *x) return FALSE; } +static gboolean +match_colors_estimate (DynPtrArray *a, DynPtrArray *b) +{ + return dyn_array_ptr_size (a) == dyn_array_ptr_size (b); +} + + static gboolean match_colors (DynPtrArray *a, DynPtrArray *b) { @@ -411,23 +492,36 @@ match_colors (DynPtrArray *a, DynPtrArray *b) return TRUE; } -static int cache_hits, cache_misses; +// If scc_precise_merge, "semihits" refers to find_in_cache calls aborted because the merge array was too large. +// Otherwise "semihits" refers to cache hits where the match was only estimated. +static int cache_hits, cache_semihits, cache_misses; +// The cache contains only non-bridged colors. static ColorData* find_in_cache (int *insert_index) { HashEntry *bucket; - int i, hash, size, index; + int i, size, index; size = dyn_array_ptr_size (&color_merge_array); - /* Cache checking is very ineficient with a lot of elements*/ - if (size > 3) + + /* Color equality checking is very expensive with a lot of elements, so when there are many + * elements we switch to a cheap comparison method which allows false positives. When false + * positives occur the worst that can happen is two items will be inappropriately merged + * and memory will be retained longer than it should be. We assume that will correct itself + * on the next GC (the hash_perturb mechanism increases the probability of this). + * + * Because this has *some* potential to create problems, if the user set the debug option + * 'enable-tarjan-precise-merge' we bail out early (and never merge SCCs with >3 colors). + */ + gboolean color_merge_array_large = size > 3; + if (scc_precise_merge && color_merge_array_large) { + ++cache_semihits; return NULL; + } - hash = 0; - for (i = 0 ; i < size; ++i) - hash += mix_hash ((size_t)dyn_array_ptr_get (&color_merge_array, i)); - if (!hash) + unsigned int hash = color_merge_array_hash; + if (!hash) // 0 is used to indicate an empty bucket entry hash = 1; index = hash & (COLOR_CACHE_SIZE - 1); @@ -435,9 +529,17 @@ find_in_cache (int *insert_index) for (i = 0; i < ELEMENTS_PER_BUCKET; ++i) { if (bucket [i].hash != hash) continue; - if (match_colors (&bucket [i].color->other_colors, &color_merge_array)) { - ++cache_hits; - return bucket [i].color; + + if (color_merge_array_large) { + if (match_colors_estimate (&bucket [i].color->other_colors, &color_merge_array)) { + ++cache_semihits; + return bucket [i].color; + } + } else { + if (match_colors (&bucket [i].color->other_colors, &color_merge_array)) { + ++cache_hits; + return bucket [i].color; + } } } @@ -450,14 +552,16 @@ find_in_cache (int *insert_index) return NULL; } +// A color is needed for an SCC. If the SCC has bridges, the color MUST be newly allocated. +// If the SCC lacks bridges, the allocator MAY use the cache to merge it with an existing one. static ColorData* -new_color (gboolean force_new) +new_color (gboolean has_bridges) { - int i = -1; + int cacheSlot = -1; ColorData *cd; /* XXX Try to find an equal one and return it */ - if (!force_new) { - cd = find_in_cache (&i); + if (!has_bridges) { + cd = find_in_cache (&cacheSlot); if (cd) return cd; } @@ -465,9 +569,16 @@ new_color (gboolean force_new) cd = alloc_color_data (); cd->api_index = -1; dyn_array_ptr_set_all (&cd->other_colors, &color_merge_array); - /* if i >= 0, it means we prepared a given slot to receive the new color */ - if (i >= 0) - merge_cache [i][0].color = cd; + + // Inform targets + for (int i = 0; i < dyn_array_ptr_size (&color_merge_array); ++i) { + ColorData *points_to = (ColorData *)dyn_array_ptr_get (&color_merge_array, i); + points_to->incoming_colors = MIN (points_to->incoming_colors + 1, INCOMING_COLORS_MAX); + } + + /* if cacheSlot >= 0, it means we prepared a given slot to receive the new color */ + if (cacheSlot >= 0) + merge_cache [cacheSlot][0].color = cd; return cd; } @@ -587,6 +698,7 @@ compute_low_index (ScanData *data, GCObject *obj) cd = other->color; if (!cd->visited) { + color_merge_array_hash += mix_hash ((uintptr_t) other->color); dyn_array_ptr_add (&color_merge_array, other->color); cd->visited = TRUE; } @@ -608,16 +720,24 @@ compute_low (ScanData *data) #include "sgen/sgen-scan-object.h" } +// A non-bridged object needs a single color describing the current merge array. static ColorData* reduce_color (void) { ColorData *color = NULL; int size = dyn_array_ptr_size (&color_merge_array); + // Merge array is empty-- this SCC points to no bridged colors. + // This SCC can be ignored completely. if (size == 0) color = NULL; + + // Merge array has one item-- this SCC points to a single bridged color. + // This SCC can be forwarded to the pointed-to color. else if (size == 1) { color = (ColorData *)dyn_array_ptr_get (&color_merge_array, 0); + + // This SCC gets to talk to the color allocator. } else color = new_color (FALSE); @@ -694,7 +814,7 @@ create_scc (ScanData *data) g_assert (cd->visited); cd->visited = FALSE; } - dyn_array_ptr_empty (&color_merge_array); + color_merge_array_empty (); found_bridge = FALSE; } @@ -704,7 +824,7 @@ dfs (void) g_assert (dyn_array_ptr_size (&scan_stack) == 1); g_assert (dyn_array_ptr_size (&loop_stack) == 0); - dyn_array_ptr_empty (&color_merge_array); + color_merge_array_empty (); while (dyn_array_ptr_size (&scan_stack) > 0) { ScanData *data = (ScanData *)dyn_array_ptr_pop (&scan_stack); @@ -891,7 +1011,7 @@ gather_xrefs (ColorData *color) if (src->visited) continue; src->visited = TRUE; - if (dyn_array_ptr_size (&src->bridges)) + if (color_visible_to_client (src)) dyn_array_ptr_add (&color_merge_array, src); else gather_xrefs (src); @@ -907,7 +1027,7 @@ reset_xrefs (ColorData *color) if (!src->visited) continue; src->visited = FALSE; - if (!dyn_array_ptr_size (&src->bridges)) + if (!color_visible_to_client (src)) reset_xrefs (src); } } @@ -915,9 +1035,7 @@ reset_xrefs (ColorData *color) static void processing_build_callback_data (int generation) { - int j, api_index; - MonoGCBridgeSCC **api_sccs; - MonoGCBridgeXRef *api_xrefs; + int j; gint64 curtime; ColorBucket *cur; @@ -936,15 +1054,27 @@ processing_build_callback_data (int generation) printf ("number of SCCs %d\n", num_colors_with_bridges); #endif + // Count the number of SCCs visible to the client + num_sccs = 0; + for (cur = root_color_bucket; cur; cur = cur->next) { + ColorData *cd; + for (cd = &cur->data [0]; cd < cur->next_data; ++cd) { + if (color_visible_to_client (cd)) + num_sccs++; + } + } + /* This is a straightforward translation from colors to the bridge callback format. */ - api_sccs = (MonoGCBridgeSCC **)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC*) * num_colors_with_bridges, INTERNAL_MEM_BRIDGE_DATA, TRUE); - api_index = xref_count = 0; + MonoGCBridgeSCC **api_sccs = (MonoGCBridgeSCC **)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC*) * num_sccs, INTERNAL_MEM_BRIDGE_DATA, TRUE); + int api_index = 0; + xref_count = 0; + // Convert visible SCCs, along with their bridged object list, to MonoGCBridgeSCCs in the client's SCC list for (cur = root_color_bucket; cur; cur = cur->next) { ColorData *cd; for (cd = &cur->data [0]; cd < cur->next_data; ++cd) { int bridges = dyn_array_ptr_size (&cd->bridges); - if (!bridges) + if (!(bridges || bridgeless_color_is_heavy (cd))) continue; api_sccs [api_index] = (MonoGCBridgeSCC *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC) + sizeof (MonoObject*) * bridges, INTERNAL_MEM_BRIDGE_DATA, TRUE); @@ -955,20 +1085,22 @@ processing_build_callback_data (int generation) for (j = 0; j < bridges; ++j) api_sccs [api_index]->objs [j] = (MonoObject *)dyn_array_ptr_get (&cd->bridges, j); + + g_assert(api_index < API_INDEX_MAX); api_index++; } } scc_setup_time = step_timer (&curtime); + // Eliminate non-visible SCCs from the SCC list and redistribute xrefs for (cur = root_color_bucket; cur; cur = cur->next) { ColorData *cd; for (cd = &cur->data [0]; cd < cur->next_data; ++cd) { - int bridges = dyn_array_ptr_size (&cd->bridges); - if (!bridges) + if (!color_visible_to_client (cd)) continue; - dyn_array_ptr_empty (&color_merge_array); + color_merge_array_empty (); gather_xrefs (cd); reset_xrefs (cd); dyn_array_ptr_set_all (&cd->other_colors, &color_merge_array); @@ -983,27 +1115,28 @@ processing_build_callback_data (int generation) dump_color_table (" after xref pass", TRUE); #endif - api_xrefs = (MonoGCBridgeXRef *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * xref_count, INTERNAL_MEM_BRIDGE_DATA, TRUE); - api_index = 0; + // Write out xrefs array + MonoGCBridgeXRef *api_xrefs = (MonoGCBridgeXRef *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * xref_count, INTERNAL_MEM_BRIDGE_DATA, TRUE); + int xref_index = 0; for (cur = root_color_bucket; cur; cur = cur->next) { ColorData *src; for (src = &cur->data [0]; src < cur->next_data; ++src) { - int bridges = dyn_array_ptr_size (&src->bridges); - if (!bridges) + if (!color_visible_to_client (src)) continue; for (j = 0; j < dyn_array_ptr_size (&src->other_colors); ++j) { ColorData *dest = (ColorData *)dyn_array_ptr_get (&src->other_colors, j); - g_assert (dyn_array_ptr_size (&dest->bridges)); /* We flattened the color graph, so this must never happen. */ + g_assert (color_visible_to_client (dest)); /* Supposedly we already eliminated all xrefs to non-visible objects. */ + + api_xrefs [xref_index].src_scc_index = src->api_index; + api_xrefs [xref_index].dst_scc_index = dest->api_index; - api_xrefs [api_index].src_scc_index = src->api_index; - api_xrefs [api_index].dst_scc_index = dest->api_index; - ++api_index; + ++xref_index; } } } - g_assert (xref_count == api_index); + g_assert (xref_count == xref_index); xref_setup_time = step_timer (&curtime); #if defined (DUMP_GRAPH) @@ -1013,7 +1146,7 @@ processing_build_callback_data (int generation) #endif //FIXME move half of the cleanup to before the bridge callback? - bridge_processor->num_sccs = num_colors_with_bridges; + bridge_processor->num_sccs = num_sccs; bridge_processor->api_sccs = api_sccs; bridge_processor->num_xrefs = xref_count; bridge_processor->api_xrefs = api_xrefs; @@ -1026,7 +1159,7 @@ processing_after_callback (int generation) int bridge_count = dyn_array_ptr_size (®istered_bridges); int object_count = object_data_count; int color_count = color_data_count; - int scc_count = num_colors_with_bridges; + int colors_with_bridges_count = num_colors_with_bridges; SGEN_TV_GETTIME (curtime); @@ -1035,10 +1168,10 @@ processing_after_callback (int generation) cleanup_time = step_timer (&curtime); - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "GC_TAR_BRIDGE bridges %d objects %d colors %d ignored %d sccs %d xref %d cache %d/%d setup %.2fms tarjan %.2fms scc-setup %.2fms gather-xref %.2fms xref-setup %.2fms cleanup %.2fms", - bridge_count, object_count, color_count, - ignored_objects, scc_count, xref_count, - cache_hits, cache_misses, + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "GC_TAR_BRIDGE bridges %d objects %d opaque %d colors %d colors-bridged %d colors-visible %d xref %d cache-hit %d cache-%s %d cache-miss %d setup %.2fms tarjan %.2fms scc-setup %.2fms gather-xref %.2fms xref-setup %.2fms cleanup %.2fms", + bridge_count, object_count, ignored_objects, + color_count, colors_with_bridges_count, num_sccs, xref_count, + cache_hits, (scc_precise_merge ? "abstain" : "semihit"), cache_semihits, cache_misses, setup_time / 10000.0f, tarjan_time / 10000.0f, scc_setup_time / 10000.0f, @@ -1046,7 +1179,7 @@ processing_after_callback (int generation) xref_setup_time / 10000.0f, cleanup_time / 10000.0f); - cache_hits = cache_misses = 0; + cache_hits = cache_semihits = cache_misses = 0; ignored_objects = 0; } @@ -1072,6 +1205,15 @@ describe_pointer (GCObject *obj) // printf (" is visited: %d\n", (int)entry->is_visited); } +static void +set_config (const SgenBridgeProcessorConfig *config) +{ + if (config->scc_precise_merge) { + hash_perturb = 0; + scc_precise_merge = TRUE; + } +} + void sgen_tarjan_bridge_init (SgenBridgeProcessor *collector) { @@ -1082,12 +1224,12 @@ sgen_tarjan_bridge_init (SgenBridgeProcessor *collector) collector->class_kind = class_kind; collector->register_finalized_object = register_finalized_object; collector->describe_pointer = describe_pointer; - collector->enable_accounting = enable_accounting; - // collector->set_dump_prefix = set_dump_prefix; + collector->set_config = set_config; sgen_register_fixed_internal_mem_type (INTERNAL_MEM_TARJAN_OBJ_BUCKET, BUCKET_SIZE); g_assert (sizeof (ObjectBucket) <= BUCKET_SIZE); g_assert (sizeof (ColorBucket) <= BUCKET_SIZE); + g_assert (API_INDEX_BITS + INCOMING_COLORS_BITS <= 31); bridge_processor = collector; } diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 5a662802771..f9a0d5adc8b 100644 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include "trace.h" diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index 6983398027a..7b2e1fa7b48 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/mono/mini/mini-ia64.c b/mono/mini/mini-ia64.c index d88a6c99a8f..357e2607998 100644 --- a/mono/mini/mini-ia64.c +++ b/mono/mini/mini-ia64.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "trace.h" #include "mini-ia64.h" diff --git a/mono/mini/mini-mips.c b/mono/mini/mini-mips.c index 5d6ebc7b6bc..783896f1568 100644 --- a/mono/mini/mini-mips.c +++ b/mono/mini/mini-mips.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include diff --git a/mono/mini/mini-ppc.c b/mono/mini/mini-ppc.c index 3089a8546b1..7d2c0d8b8cf 100644 --- a/mono/mini/mini-ppc.c +++ b/mono/mini/mini-ppc.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include "mini-ppc.h" #ifdef TARGET_POWERPC64 diff --git a/mono/mini/mini-s390x.c b/mono/mini/mini-s390x.c index 3fe40d2cfc2..a1094afa173 100644 --- a/mono/mini/mini-s390x.c +++ b/mono/mini/mini-s390x.c @@ -268,7 +268,7 @@ if (ins->inst_target_bb->native_offset) { \ #include #include #include -#include +#include #include #include "mini-s390x.h" @@ -399,8 +399,6 @@ pthread_key_t lmf_addr_key; gboolean lmf_addr_key_inited = FALSE; -facilityList_t facs; - /* * The code generated for sequence points reads from this location, * which is made read-only when single stepping is enabled. @@ -4370,7 +4368,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } break; case OP_ICONV_TO_R_UN: { - if (facs.fpe) { + if (mono_hwcap_s390x_has_fpe) { s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0); } else { s390_llgfr (code, s390_r0, ins->sreg1); @@ -4379,7 +4377,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } break; case OP_LCONV_TO_R_UN: { - if (facs.fpe) { + if (mono_hwcap_s390x_has_fpe) { s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0); } else { short int *jump; @@ -4416,7 +4414,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_ngr (code, ins->dreg, s390_r0); break; case OP_FCONV_TO_U1: - if (facs.fpe) { + if (mono_hwcap_s390x_has_fpe) { s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0); s390_lghi (code, s390_r0, 0xff); s390_ngr (code, ins->dreg, s390_r0); @@ -4433,7 +4431,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_ngr (code, ins->dreg, s390_r0); break; case OP_FCONV_TO_U2: - if (facs.fpe) { + if (mono_hwcap_s390x_has_fpe) { s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0); s390_llill (code, s390_r0, 0xffff); s390_ngr (code, ins->dreg, s390_r0); @@ -4447,7 +4445,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_FCONV_TO_U4: case OP_FCONV_TO_U: - if (facs.fpe) { + if (mono_hwcap_s390x_has_fpe) { s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0); } else { code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE); @@ -4457,7 +4455,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_cgdbr (code, ins->dreg, 5, ins->sreg1); break; case OP_FCONV_TO_U8: - if (facs.fpe) { + if (mono_hwcap_s390x_has_fpe) { s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0); } else { code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE); @@ -7077,7 +7075,7 @@ mono_arch_cpu_enumerate_simd_versions (void) { guint32 sseOpts = 0; - if (facs.vec != 0) + if (mono_hwcap_s390x_has_vec) sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 | SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 | SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 | diff --git a/mono/mini/mini-sparc.c b/mono/mini/mini-sparc.c index 022f8a5e790..5003bfe0254 100644 --- a/mono/mini/mini-sparc.c +++ b/mono/mini/mini-sparc.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include "mini-sparc.h" #include "trace.h" diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index 9e1702be17c..288af652434 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include "trace.h" diff --git a/mono/tests/sgen-bridge-pathologies.cs b/mono/tests/sgen-bridge-pathologies.cs index 68fc0a5d060..7c8dbc08731 100644 --- a/mono/tests/sgen-bridge-pathologies.cs +++ b/mono/tests/sgen-bridge-pathologies.cs @@ -111,13 +111,29 @@ class Driver { var heads = new Bridge [FAN_OUT]; for (int i = 0; i < FAN_OUT; ++i) heads [i] = new Bridge (); - var multiplexer = new Bridge [FAN_OUT]; - for (int i = 0; i < FAN_OUT; ++i) - { - heads [i].Links.Add (multiplexer); - multiplexer [i] = new Bridge (); + + // We make five identical multiplexers to verify Tarjan-bridge can merge them together correctly. + var MULTIPLEXER_COUNT = 5; + Bridge[] multiplexer0 = null; + for(int m = 0; m < MULTIPLEXER_COUNT; m++) { + var multiplexer = new Bridge [FAN_OUT]; + if (m == 0) { + multiplexer0 = multiplexer; + for (int i = 0; i < FAN_OUT; ++i) + { + heads [i].Links.Add (multiplexer); + multiplexer [i] = new Bridge (); + } + } else { + for (int i = 0; i < FAN_OUT; ++i) + { + heads [i].Links.Add (multiplexer); + multiplexer [i] = multiplexer0 [i]; + } + } } - Console.WriteLine ("-double fan done-"); + + Console.WriteLine ("-double fan x5 done-"); } /* diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am index 2e873cde798..d67b9ff1fed 100644 --- a/mono/utils/Makefile.am +++ b/mono/utils/Makefile.am @@ -130,6 +130,7 @@ monoutils_sources = \ atomic.c \ mono-hwcap.h \ mono-hwcap.c \ + mono-hwcap-vars.h \ bsearch.h \ bsearch.c \ mono-signal-handler.h \ @@ -182,48 +183,56 @@ arch_sources += mach-support-unknown.c endif +if !CROSS_COMPILE + if X86 -arch_sources += mono-hwcap-x86.c mono-hwcap-x86.h +arch_sources += mono-hwcap-x86.c endif if AMD64 -arch_sources += mono-hwcap-x86.c mono-hwcap-x86.h +arch_sources += mono-hwcap-x86.c endif if ARM -arch_sources += mono-hwcap-arm.c mono-hwcap-arm.h +arch_sources += mono-hwcap-arm.c endif if ARM64 -arch_sources += mono-hwcap-arm64.c mono-hwcap-arm64.h +arch_sources += mono-hwcap-arm64.c endif if MIPS -arch_sources += mono-hwcap-mips.c mono-hwcap-mips.h +arch_sources += mono-hwcap-mips.c endif if POWERPC -arch_sources += mono-hwcap-ppc.c mono-hwcap-ppc.h +arch_sources += mono-hwcap-ppc.c endif if POWERPC64 -arch_sources += mono-hwcap-ppc.c mono-hwcap-ppc.h +arch_sources += mono-hwcap-ppc.c endif if SPARC -arch_sources += mono-hwcap-sparc.c mono-hwcap-sparc.h +arch_sources += mono-hwcap-sparc.c endif if SPARC64 -arch_sources += mono-hwcap-sparc.c mono-hwcap-sparc.h +arch_sources += mono-hwcap-sparc.c endif if IA64 -arch_sources += mono-hwcap-ia64.c mono-hwcap-ia64.h +arch_sources += mono-hwcap-ia64.c endif if S390X -arch_sources += mono-hwcap-s390x.c mono-hwcap-s390x.h +arch_sources += mono-hwcap-s390x.c +endif + +else + +arch_sources += mono-hwcap-cross.c + endif libmonoutils_la_SOURCES = $(monoutils_sources) $(arch_sources) diff --git a/mono/utils/mono-hwcap-arm.c b/mono/utils/mono-hwcap-arm.c index 758c3dc6fc2..e51387776b9 100644 --- a/mono/utils/mono-hwcap-arm.c +++ b/mono/utils/mono-hwcap-arm.c @@ -19,7 +19,7 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-arm.h" +#include "mono/utils/mono-hwcap.h" #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID) #include @@ -34,15 +34,6 @@ #include #endif -gboolean mono_hwcap_arm_is_v5 = FALSE; -gboolean mono_hwcap_arm_is_v6 = FALSE; -gboolean mono_hwcap_arm_is_v7 = FALSE; -gboolean mono_hwcap_arm_has_vfp = FALSE; -gboolean mono_hwcap_arm_has_vfp3 = FALSE; -gboolean mono_hwcap_arm_has_vfp3_d16 = FALSE; -gboolean mono_hwcap_arm_has_thumb = FALSE; -gboolean mono_hwcap_arm_has_thumb2 = FALSE; - void mono_hwcap_arch_init (void) { @@ -202,16 +193,3 @@ mono_hwcap_arch_init (void) } #endif } - -void -mono_hwcap_print(FILE *f) -{ - g_fprintf (f, "mono_hwcap_arm_is_v5 = %i\n", mono_hwcap_arm_is_v5); - g_fprintf (f, "mono_hwcap_arm_is_v6 = %i\n", mono_hwcap_arm_is_v6); - g_fprintf (f, "mono_hwcap_arm_is_v7 = %i\n", mono_hwcap_arm_is_v7); - g_fprintf (f, "mono_hwcap_arm_has_vfp = %i\n", mono_hwcap_arm_has_vfp); - g_fprintf (f, "mono_hwcap_arm_has_vfp3 = %i\n", mono_hwcap_arm_has_vfp3); - g_fprintf (f, "mono_hwcap_arm_has_vfp3_d16 = %i\n", mono_hwcap_arm_has_vfp3_d16); - g_fprintf (f, "mono_hwcap_arm_has_thumb = %i\n", mono_hwcap_arm_has_thumb); - g_fprintf (f, "mono_hwcap_arm_has_thumb2 = %i\n", mono_hwcap_arm_has_thumb2); -} diff --git a/mono/utils/mono-hwcap-arm.h b/mono/utils/mono-hwcap-arm.h deleted file mode 100644 index 29adf7bb799..00000000000 --- a/mono/utils/mono-hwcap-arm.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_ARM_H__ -#define __MONO_UTILS_HWCAP_ARM_H__ - -#include "mono/utils/mono-hwcap.h" - -extern gboolean mono_hwcap_arm_is_v5; -extern gboolean mono_hwcap_arm_is_v6; -extern gboolean mono_hwcap_arm_is_v7; -extern gboolean mono_hwcap_arm_has_vfp; -extern gboolean mono_hwcap_arm_has_vfp3; -extern gboolean mono_hwcap_arm_has_vfp3_d16; -extern gboolean mono_hwcap_arm_has_thumb; -extern gboolean mono_hwcap_arm_has_thumb2; - -#endif /* __MONO_UTILS_HWCAP_ARM_H__ */ diff --git a/mono/utils/mono-hwcap-arm64.c b/mono/utils/mono-hwcap-arm64.c index 5491cff96cf..f541ea3df2b 100644 --- a/mono/utils/mono-hwcap-arm64.c +++ b/mono/utils/mono-hwcap-arm64.c @@ -1,25 +1,13 @@ /* - * mono-hwcap-arm64.c: ARM hardware feature detection + * mono-hwcap-arm64.c: ARM64 hardware feature detection * * Copyright 2013 Xamarin Inc * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-arm64.h" +#include "mono/utils/mono-hwcap.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 deleted file mode 100644 index 2d4120957cf..00000000000 --- a/mono/utils/mono-hwcap-arm64.h +++ /dev/null @@ -1,6 +0,0 @@ -#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-hwcap-cross.c b/mono/utils/mono-hwcap-cross.c new file mode 100644 index 00000000000..4311a99a18d --- /dev/null +++ b/mono/utils/mono-hwcap-cross.c @@ -0,0 +1,16 @@ +/* + * mono-hwcap-cross.c: No-op hardware feature detection + * + * Author: + * Alex Rønne Petersen (alexrp@xamarin.com) + * + * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + +#include "mono/utils/mono-hwcap.h" + +void +mono_hwcap_arch_init (void) +{ +} diff --git a/mono/utils/mono-hwcap-ia64.c b/mono/utils/mono-hwcap-ia64.c index b5979862208..dd1edbd8d40 100644 --- a/mono/utils/mono-hwcap-ia64.c +++ b/mono/utils/mono-hwcap-ia64.c @@ -19,15 +19,9 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-ia64.h" +#include "mono/utils/mono-hwcap.h" void mono_hwcap_arch_init (void) -{ - /* Nothing needed here yet. */ -} - -void -mono_hwcap_print (FILE *f) { } diff --git a/mono/utils/mono-hwcap-ia64.h b/mono/utils/mono-hwcap-ia64.h deleted file mode 100644 index 15b64a83c65..00000000000 --- a/mono/utils/mono-hwcap-ia64.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_IA64_H__ -#define __MONO_UTILS_HWCAP_IA64_H__ - -#include "mono/utils/mono-hwcap.h" - -/* Nothing needed here yet. */ - -#endif /* __MONO_UTILS_HWCAP_IA64_H__ */ diff --git a/mono/utils/mono-hwcap-mips.c b/mono/utils/mono-hwcap-mips.c index 6d809a79ac5..119f930a685 100644 --- a/mono/utils/mono-hwcap-mips.c +++ b/mono/utils/mono-hwcap-mips.c @@ -19,15 +19,9 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-mips.h" +#include "mono/utils/mono-hwcap.h" void mono_hwcap_arch_init (void) -{ - /* Nothing needed here yet. */ -} - -void -mono_hwcap_print (FILE *f) { } diff --git a/mono/utils/mono-hwcap-mips.h b/mono/utils/mono-hwcap-mips.h deleted file mode 100644 index dd0622ab1ae..00000000000 --- a/mono/utils/mono-hwcap-mips.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_MIPS_H__ -#define __MONO_UTILS_HWCAP_MIPS_H__ - -#include "mono/utils/mono-hwcap.h" - -/* Nothing needed here yet. */ - -#endif /* __MONO_UTILS_HWCAP_MIPS_H__ */ diff --git a/mono/utils/mono-hwcap-ppc.c b/mono/utils/mono-hwcap-ppc.c index 174cc620a20..af36c4d5473 100644 --- a/mono/utils/mono-hwcap-ppc.c +++ b/mono/utils/mono-hwcap-ppc.c @@ -19,19 +19,13 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-ppc.h" +#include "mono/utils/mono-hwcap.h" #if defined(__linux__) && defined(HAVE_SYS_AUXV_H) #include #include #endif -gboolean mono_hwcap_ppc_has_icache_snoop = FALSE; -gboolean mono_hwcap_ppc_is_isa_2x = FALSE; -gboolean mono_hwcap_ppc_is_isa_64 = FALSE; -gboolean mono_hwcap_ppc_has_move_fpr_gpr = FALSE; -gboolean mono_hwcap_ppc_has_multiple_ls_units = FALSE; - void mono_hwcap_arch_init (void) { @@ -66,13 +60,3 @@ mono_hwcap_arch_init (void) } #endif } - -void -mono_hwcap_print (FILE* f) -{ - g_fprintf (f, "mono_hwcap_ppc_has_icache_snoop = %i\n", mono_hwcap_ppc_has_icache_snoop); - g_fprintf (f, "mono_hwcap_ppc_is_isa_2x = %i\n", mono_hwcap_ppc_is_isa_2x); - g_fprintf (f, "mono_hwcap_ppc_is_isa_64 = %i\n", mono_hwcap_ppc_is_isa_64); - g_fprintf (f, "mono_hwcap_ppc_has_move_fpr_gpr = %i\n", mono_hwcap_ppc_has_move_fpr_gpr); - g_fprintf (f, "mono_hwcap_ppc_has_multiple_ls_units = %i\n", mono_hwcap_ppc_has_multiple_ls_units); -} diff --git a/mono/utils/mono-hwcap-ppc.h b/mono/utils/mono-hwcap-ppc.h deleted file mode 100644 index 0ae2578e62c..00000000000 --- a/mono/utils/mono-hwcap-ppc.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_PPC_H__ -#define __MONO_UTILS_HWCAP_PPC_H__ - -#include "mono/utils/mono-hwcap.h" - -extern gboolean mono_hwcap_ppc_has_icache_snoop; -extern gboolean mono_hwcap_ppc_is_isa_2x; -extern gboolean mono_hwcap_ppc_is_isa_64; -extern gboolean mono_hwcap_ppc_has_move_fpr_gpr; -extern gboolean mono_hwcap_ppc_has_multiple_ls_units; - -#endif /* __MONO_UTILS_HWCAP_PPC_H__ */ diff --git a/mono/utils/mono-hwcap-s390x.c b/mono/utils/mono-hwcap-s390x.c index 19a7fba1101..c578a620d92 100644 --- a/mono/utils/mono-hwcap-s390x.c +++ b/mono/utils/mono-hwcap-s390x.c @@ -19,22 +19,117 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-s390x.h" +#include "mono/utils/mono-hwcap.h" + #include -facilityList_t facs; +typedef struct { + uint8_t n3:1; // 000 - N3 instructions + uint8_t zi:1; // 001 - z/Arch installed + uint8_t za:1; // 002 - z/Arch active + uint8_t date:1; // 003 - DAT-enhancement + uint8_t idtes:1; // 004 - IDTE-segment tables + uint8_t idter:1; // 005 - IDTE-region tables + uint8_t asnlx:1; // 006 - ASN-LX reuse + uint8_t stfle:1; // 007 - STFLE + uint8_t edat1:1; // 008 - EDAT 1 + uint8_t srs:1; // 009 - Sense-Running-Status + uint8_t csske:1; // 010 - Conditional SSKE + uint8_t ctf:1; // 011 - Configuration-topology + uint8_t ibm01:1; // 012 - Assigned to IBM + uint8_t ipter:1; // 013 - IPTE-range + uint8_t nqks:1; // 014 - Nonquiescing key-setting + uint8_t ibm02:1; // 015 - Assigned to IBM + uint8_t etf2:1; // 016 - Extended translation 2 + uint8_t msa:1; // 017 - Message security assist 1 + uint8_t ld:1; // 018 - Long displacement + uint8_t ldh:1; // 019 - Long displacement high perf + uint8_t mas:1; // 020 - HFP multiply-add-subtract + uint8_t eif:1; // 021 - Extended immediate + uint8_t etf3:1; // 022 - Extended translation 3 + uint8_t hux:1; // 023 - HFP unnormalized extension + uint8_t etf2e:1; // 024 - Extended translation enhanced 2 + uint8_t stckf:1; // 025 - Store clock fast + uint8_t pe:1; // 026 - Parsing enhancement + uint8_t mvcos:1; // 027 - Move with optional specs + uint8_t tods:1; // 028 - TOD steering + uint8_t x000:1; // 029 - Undefined + uint8_t etf3e:1; // 030 - ETF3 enhancement + uint8_t ecput:1; // 031 - Extract CPU time + uint8_t csst:1; // 032 - Compare swap and store + uint8_t csst2:1; // 033 - Compare swap and store 2 + uint8_t gie:1; // 034 - General instructions extension + uint8_t ee:1; // 035 - Execute extensions + uint8_t em:1; // 036 - Enhanced monitor + uint8_t fpe:1; // 037 - Floating point extension + uint8_t x001:1; // 038 - Undefined + uint8_t ibm03:1; // 039 - Assigned to IBM + uint8_t spp:1; // 040 - Set program parameters + uint8_t fpse:1; // 041 - FP support enhancement + uint8_t dfp:1; // 042 - DFP + uint8_t dfph:1; // 043 - DFP high performance + uint8_t pfpo:1; // 044 - PFPO instruction + uint8_t multi:1; // 045 - Multiple inc load/store on CC 1 + uint8_t ibm04:1; // 046 - Assigned to IBM + uint8_t cmpsce:1; // 047 - CMPSC enhancement + uint8_t dfpzc:1; // 048 - DFP zoned conversion + uint8_t misc:1; // 049 - Multiple inc load and trap + uint8_t ctx:1; // 050 - Constrained transactional-execution + uint8_t ltlb:1; // 051 - Local TLB clearing + uint8_t ia:1; // 052 - Interlocked access + uint8_t lsoc2:1; // 053 - Load/store on CC 2 + uint8_t x002:1; // 054 - Undefined + uint8_t ibm05:1; // 055 - Assigned to IBM + uint8_t x003:1; // 056 - Undefined + uint8_t msa5:1; // 057 - Message security assist 5 + uint8_t x004:1; // 058 - Undefined + uint8_t x005:1; // 059 - Undefined + uint8_t x006:1; // 060 - Undefined + uint8_t x007:1; // 061 - Undefined + uint8_t ibm06:1; // 062 - Assigned to IBM + uint8_t x008:1; // 063 - Undefined + uint8_t x009:1; // 064 - Undefined + uint8_t ibm07:1; // 065 - Assigned to IBM + uint8_t rrbm:1; // 066 - Reset reference bits multiple + uint8_t cmc:1; // 067 - CPU measurement counter + uint8_t cms:1; // 068 - CPU Measurement sampling + uint8_t ibm08:1; // 069 - Assigned to IBM + uint8_t ibm09:1; // 070 - Assigned to IBM + uint8_t ibm10:1; // 071 - Assigned to IBM + uint8_t ibm11:1; // 072 - Assigned to IBM + uint8_t txe:1; // 073 - Transactional execution + uint8_t sthy:1; // 074 - Store hypervisor information + uint8_t aefsi:1; // 075 - Access exception fetch/store indication + uint8_t msa3:1; // 076 - Message security assist 3 + uint8_t msa4:1; // 077 - Message security assist 4 + uint8_t edat2:1; // 078 - Enhanced DAT 2 + uint8_t x010:1; // 079 - Undefined + uint8_t dfppc:1; // 080 - DFP packed conversion + uint8_t x011:7; // 081-87 - Undefined + uint8_t x012[5]; // 088-127 - Undefined + uint8_t ibm12:1; // 128 - Assigned to IBM + uint8_t vec:1; // 129 - Vector facility + uint8_t x013:6; // 130-135 - Undefined + uint8_t x014:6; // 136-141 - Undefined + uint8_t sccm:1; // 142 - Store CPU counter multiple + uint8_t ibm13:1; // 143 - Assigned to IBM + uint8_t x015[14]; // 144-256 Undefined +} __attribute__ ((packed)) __attribute__ ((aligned(8))) facilityList_t; void mono_hwcap_arch_init (void) { - int lFacs = sizeof(facs) / 8; + facilityList_t facs; + int lFacs = sizeof (facs) / 8; - __asm__ (" lgfr 0,%1\n" - " .insn s,0xb2b00000,%0\n" - : "=m" (facs) : "r" (lFacs) : "0", "cc"); -} + __asm__ __volatile__ ( + "lgfr\t0,%1\n\t" + ".insn\ts,0xb2b00000,%0\n\t" + : "=m" (facs) + : "r" (lFacs) + : "0", "cc" + ); -void -mono_hwcap_print (FILE *f) -{ + mono_hwcap_s390x_has_fpe = facs.fpe; + mono_hwcap_s390x_has_vec = facs.vec; } diff --git a/mono/utils/mono-hwcap-s390x.h b/mono/utils/mono-hwcap-s390x.h deleted file mode 100644 index 7a4522f8db9..00000000000 --- a/mono/utils/mono-hwcap-s390x.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_S390X_H__ -#define __MONO_UTILS_HWCAP_S390X_H__ - -#include "mono/utils/mono-hwcap.h" - -typedef struct __FACLIST__ { - uint8_t n3:1; // 000 - N3 instructions - uint8_t zi:1; // 001 - z/Arch installed - uint8_t za:1; // 002 - z/Arch active - uint8_t date:1; // 003 - DAT-enhancement - uint8_t idtes:1; // 004 - IDTE-segment tables - uint8_t idter:1; // 005 - IDTE-region tables - uint8_t asnlx:1; // 006 - ASN-LX reuse - uint8_t stfle:1; // 007 - STFLE - uint8_t edat1:1; // 008 - EDAT 1 - uint8_t srs:1; // 009 - Sense-Running-Status - uint8_t csske:1; // 010 - Conditional SSKE - uint8_t ctf:1; // 011 - Configuration-topology - uint8_t ibm01:1; // 012 - Assigned to IBM - uint8_t ipter:1; // 013 - IPTE-range - uint8_t nqks:1; // 014 - Nonquiescing key-setting - uint8_t ibm02:1; // 015 - Assigned to IBM - uint8_t etf2:1; // 016 - Extended translation 2 - uint8_t msa:1; // 017 - Message security assist 1 - uint8_t ld:1; // 018 - Long displacement - uint8_t ldh:1; // 019 - Long displacement high perf - uint8_t mas:1; // 020 - HFP multiply-add-subtract - uint8_t eif:1; // 021 - Extended immediate - uint8_t etf3:1; // 022 - Extended translation 3 - uint8_t hux:1; // 023 - HFP unnormalized extension - uint8_t etf2e:1; // 024 - Extended translation enhanced 2 - uint8_t stckf:1; // 025 - Store clock fast - uint8_t pe:1; // 026 - Parsing enhancement - uint8_t mvcos:1; // 027 - Move with optional specs - uint8_t tods:1; // 028 - TOD steering - uint8_t x000:1; // 029 - Undefined - uint8_t etf3e:1; // 030 - ETF3 enhancement - uint8_t ecput:1; // 031 - Extract CPU time - uint8_t csst:1; // 032 - Compare swap and store - uint8_t csst2:1; // 033 - Compare swap and store 2 - uint8_t gie:1; // 034 - General instructions extension - uint8_t ee:1; // 035 - Execute extensions - uint8_t em:1; // 036 - Enhanced monitor - uint8_t fpe:1; // 037 - Floating point extension - uint8_t x001:1; // 038 - Undefined - uint8_t ibm03:1; // 039 - Assigned to IBM - uint8_t spp:1; // 040 - Set program parameters - uint8_t fpse:1; // 041 - FP support enhancement - uint8_t dfp:1; // 042 - DFP - uint8_t dfph:1; // 043 - DFP high performance - uint8_t pfpo:1; // 044 - PFPO instruction - uint8_t multi:1; // 045 - Multiple inc load/store on CC 1 - uint8_t ibm04:1; // 046 - Assigned to IBM - uint8_t cmpsce:1; // 047 - CMPSC enhancement - uint8_t dfpzc:1; // 048 - DFP zoned conversion - uint8_t misc:1; // 049 - Multiple inc load and trap - uint8_t ctx:1; // 050 - Constrained transactional-execution - uint8_t ltlb:1; // 051 - Local TLB clearing - uint8_t ia:1; // 052 - Interlocked access - uint8_t lsoc2:1; // 053 - Load/store on CC 2 - uint8_t x002:1; // 054 - Undefined - uint8_t ibm05:1; // 055 - Assigned to IBM - uint8_t x003:1; // 056 - Undefined - uint8_t msa5:1; // 057 - Message security assist 5 - uint8_t x004:1; // 058 - Undefined - uint8_t x005:1; // 059 - Undefined - uint8_t x006:1; // 060 - Undefined - uint8_t x007:1; // 061 - Undefined - uint8_t ibm06:1; // 062 - Assigned to IBM - uint8_t x008:1; // 063 - Undefined - uint8_t x009:1; // 064 - Undefined - uint8_t ibm07:1; // 065 - Assigned to IBM - uint8_t rrbm:1; // 066 - Reset reference bits multiple - uint8_t cmc:1; // 067 - CPU measurement counter - uint8_t cms:1; // 068 - CPU Measurement sampling - uint8_t ibm08:1; // 069 - Assigned to IBM - uint8_t ibm09:1; // 070 - Assigned to IBM - uint8_t ibm10:1; // 071 - Assigned to IBM - uint8_t ibm11:1; // 072 - Assigned to IBM - uint8_t txe:1; // 073 - Transactional execution - uint8_t sthy:1; // 074 - Store hypervisor information - uint8_t aefsi:1; // 075 - Access exception fetch/store indication - uint8_t msa3:1; // 076 - Message security assist 3 - uint8_t msa4:1; // 077 - Message security assist 4 - uint8_t edat2:1; // 078 - Enhanced DAT 2 - uint8_t x010:1; // 079 - Undefined - uint8_t dfppc:1; // 080 - DFP packed conversion - uint8_t x011:7; // 081-87 - Undefined - uint8_t x012[5]; // 088-127 - Undefined - uint8_t ibm12:1; // 128 - Assigned to IBM - uint8_t vec:1; // 129 - Vector facility - uint8_t x013:6; // 130-135 - Undefined - uint8_t x014:6; // 136-141 - Undefined - uint8_t sccm:1; // 142 - Store CPU counter multiple - uint8_t ibm13:1; // 143 - Assigned to IBM - uint8_t x015[14]; // 144-256 Undefined -} __attribute__ ((packed)) __attribute__ ((aligned(8))) facilityList_t; - -extern facilityList_t facs; - -#endif /* __MONO_UTILS_HWCAP_S390X_H__ */ diff --git a/mono/utils/mono-hwcap-sparc.c b/mono/utils/mono-hwcap-sparc.c index ba849873632..75208bdeff7 100644 --- a/mono/utils/mono-hwcap-sparc.c +++ b/mono/utils/mono-hwcap-sparc.c @@ -19,26 +19,22 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-sparc.h" +#include "mono/utils/mono-hwcap.h" #include - #if !defined(__linux__) #include #else #include #endif -gboolean mono_hwcap_sparc_is_v9 = FALSE; - void mono_hwcap_arch_init (void) { char buf [1024]; #if !defined(__linux__) - if (!sysinfo (SI_ISALIST, buf, 1024)) - g_assert_not_reached (); + g_assert (sysinfo (SI_ISALIST, buf, 1024)); #else /* If the page size is 8192, we're on a 64-bit SPARC, which * in turn means a v9 or better. @@ -51,9 +47,3 @@ mono_hwcap_arch_init (void) mono_hwcap_sparc_is_v9 = strstr (buf, "sparcv9"); } - -void -mono_hwcap_print (FILE *f) -{ - g_fprintf (f, "mono_hwcap_sparc_is_v9 = %i\n", mono_hwcap_sparc_is_v9); -} diff --git a/mono/utils/mono-hwcap-vars.h b/mono/utils/mono-hwcap-vars.h new file mode 100644 index 00000000000..620a3d43e42 --- /dev/null +++ b/mono/utils/mono-hwcap-vars.h @@ -0,0 +1,56 @@ +#include "config.h" + +#if defined (TARGET_ARM) + +MONO_HWCAP_VAR(arm_is_v5) +MONO_HWCAP_VAR(arm_is_v6) +MONO_HWCAP_VAR(arm_is_v7) +MONO_HWCAP_VAR(arm_has_vfp) +MONO_HWCAP_VAR(arm_has_vfp3) +MONO_HWCAP_VAR(arm_has_vfp3_d16) +MONO_HWCAP_VAR(arm_has_thumb) +MONO_HWCAP_VAR(arm_has_thumb2) + +#elif defined (TARGET_ARM64) + +// Nothing here yet. + +#elif defined (TARGET_IA64) + +// Nothing here yet. + +#elif defined (TARGET_MIPS) + +// Nothing here yet. + +#elif defined (TARGET_POWERPC) || defined (TARGET_POWERPC64) + +MONO_HWCAP_VAR(ppc_has_icache_snoop) +MONO_HWCAP_VAR(ppc_is_isa_2x) +MONO_HWCAP_VAR(ppc_is_isa_64) +MONO_HWCAP_VAR(ppc_has_move_fpr_gpr) +MONO_HWCAP_VAR(ppc_has_multiple_ls_units) + +#elif defined (TARGET_S390X) + +MONO_HWCAP_VAR(s390x_has_fpe) +MONO_HWCAP_VAR(s390x_has_vec) + +#elif defined (TARGET_SPARC) || defined (TARGET_SPARC64) + +MONO_HWCAP_VAR(sparc_is_v9) + +#elif defined (TARGET_X86) || defined (TARGET_AMD64) + +MONO_HWCAP_VAR(x86_is_xen) +MONO_HWCAP_VAR(x86_has_cmov) +MONO_HWCAP_VAR(x86_has_fcmov) +MONO_HWCAP_VAR(x86_has_sse1) +MONO_HWCAP_VAR(x86_has_sse2) +MONO_HWCAP_VAR(x86_has_sse3) +MONO_HWCAP_VAR(x86_has_ssse3) +MONO_HWCAP_VAR(x86_has_sse41) +MONO_HWCAP_VAR(x86_has_sse42) +MONO_HWCAP_VAR(x86_has_sse4a) + +#endif diff --git a/mono/utils/mono-hwcap-x86.c b/mono/utils/mono-hwcap-x86.c index 4a96aa3a088..5d72a4c7e20 100644 --- a/mono/utils/mono-hwcap-x86.c +++ b/mono/utils/mono-hwcap-x86.c @@ -19,27 +19,15 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "mono/utils/mono-hwcap-x86.h" +#include "mono/utils/mono-hwcap.h" #if defined(HAVE_UNISTD_H) #include #endif - #if defined(_MSC_VER) #include #endif -gboolean mono_hwcap_x86_is_xen = FALSE; -gboolean mono_hwcap_x86_has_cmov = FALSE; -gboolean mono_hwcap_x86_has_fcmov = FALSE; -gboolean mono_hwcap_x86_has_sse1 = FALSE; -gboolean mono_hwcap_x86_has_sse2 = FALSE; -gboolean mono_hwcap_x86_has_sse3 = FALSE; -gboolean mono_hwcap_x86_has_ssse3 = FALSE; -gboolean mono_hwcap_x86_has_sse41 = FALSE; -gboolean mono_hwcap_x86_has_sse42 = FALSE; -gboolean mono_hwcap_x86_has_sse4a = FALSE; - static gboolean cpuid (int id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx) { @@ -162,18 +150,3 @@ mono_hwcap_arch_init (void) mono_hwcap_x86_is_xen = !access ("/proc/xen", F_OK); #endif } - -void -mono_hwcap_print (FILE *f) -{ - g_fprintf (f, "mono_hwcap_x86_is_xen = %i\n", mono_hwcap_x86_is_xen); - g_fprintf (f, "mono_hwcap_x86_has_cmov = %i\n", mono_hwcap_x86_has_cmov); - g_fprintf (f, "mono_hwcap_x86_has_fcmov = %i\n", mono_hwcap_x86_has_fcmov); - g_fprintf (f, "mono_hwcap_x86_has_sse1 = %i\n", mono_hwcap_x86_has_sse1); - g_fprintf (f, "mono_hwcap_x86_has_sse2 = %i\n", mono_hwcap_x86_has_sse2); - g_fprintf (f, "mono_hwcap_x86_has_sse3 = %i\n", mono_hwcap_x86_has_sse3); - g_fprintf (f, "mono_hwcap_x86_has_ssse3 = %i\n", mono_hwcap_x86_has_ssse3); - g_fprintf (f, "mono_hwcap_x86_has_sse41 = %i\n", mono_hwcap_x86_has_sse41); - g_fprintf (f, "mono_hwcap_x86_has_sse42 = %i\n", mono_hwcap_x86_has_sse42); - g_fprintf (f, "mono_hwcap_x86_has_sse4a = %i\n", mono_hwcap_x86_has_sse4a); -} diff --git a/mono/utils/mono-hwcap-x86.h b/mono/utils/mono-hwcap-x86.h deleted file mode 100644 index 5e1f4f7b47d..00000000000 --- a/mono/utils/mono-hwcap-x86.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __MONO_UTILS_HWCAP_X86_H__ -#define __MONO_UTILS_HWCAP_X86_H__ - -#include "mono/utils/mono-hwcap.h" - -extern gboolean mono_hwcap_x86_is_xen; -extern gboolean mono_hwcap_x86_has_cmov; -extern gboolean mono_hwcap_x86_has_fcmov; -extern gboolean mono_hwcap_x86_has_sse1; -extern gboolean mono_hwcap_x86_has_sse2; -extern gboolean mono_hwcap_x86_has_sse3; -extern gboolean mono_hwcap_x86_has_ssse3; -extern gboolean mono_hwcap_x86_has_sse41; -extern gboolean mono_hwcap_x86_has_sse42; -extern gboolean mono_hwcap_x86_has_sse4a; - -#endif /* __MONO_UTILS_HWCAP_X86_H__ */ diff --git a/mono/utils/mono-hwcap.c b/mono/utils/mono-hwcap.c index a3d2b6078bf..00fad690193 100644 --- a/mono/utils/mono-hwcap.c +++ b/mono/utils/mono-hwcap.c @@ -24,6 +24,10 @@ #include "mono/utils/mono-hwcap.h" +#define MONO_HWCAP_VAR(NAME) gboolean mono_hwcap_ ## NAME = FALSE; +#include "mono/utils/mono-hwcap-vars.h" +#undef MONO_HWCAP_VAR + static gboolean hwcap_inited = FALSE; void @@ -35,19 +39,21 @@ mono_hwcap_init (void) if (hwcap_inited) return; -#ifdef MONO_CROSS_COMPILE - /* - * If we're cross-compiling, we want to be as - * conservative as possible so that we produce - * code that's portable. Default to that. - */ - if (!conservative) - conservative = "1"; -#endif - if (!conservative || strncmp (conservative, "1", 1)) mono_hwcap_arch_init (); if (verbose && !strncmp (verbose, "1", 1)) - mono_hwcap_print (stdout); + mono_hwcap_print (); +} + +void +mono_hwcap_print (void) +{ + g_print ("[mono-hwcap] Detected following hardware capabilities:\n\n"); + +#define MONO_HWCAP_VAR(NAME) g_print ("\t" #NAME " = %s\n", mono_hwcap_ ## NAME ? "yes" : "no"); +#include "mono/utils/mono-hwcap-vars.h" +#undef MONO_HWCAP_VAR + + g_print ("\n"); } diff --git a/mono/utils/mono-hwcap.h b/mono/utils/mono-hwcap.h index af5d6654269..1867d3d258a 100644 --- a/mono/utils/mono-hwcap.h +++ b/mono/utils/mono-hwcap.h @@ -8,6 +8,10 @@ #include "mono/utils/mono-compiler.h" +#define MONO_HWCAP_VAR(NAME) extern gboolean mono_hwcap_ ## NAME; +#include "mono/utils/mono-hwcap-vars.h" +#undef MONO_HWCAP_VAR + /* Call this function to perform hardware feature detection. Until * this function has been called, all feature variables will be * FALSE as a default. @@ -17,17 +21,14 @@ * result in an inconsistent state of the variables. Further, * feature variables should not be read *while* this function is * executing. - * - * To get at feature variables, include the appropriate header, - * e.g. mono-hwcap-x86.h for x86(-64). */ void mono_hwcap_init (void); /* Implemented in mono-hwcap-$TARGET.c. Do not call. */ void mono_hwcap_arch_init (void); -/* Print detected features to the given file. */ -void mono_hwcap_print (FILE *f); +/* Print detected features to stdout. */ +void mono_hwcap_print (void); /* Please note: If you're going to use the Linux auxiliary vector * to detect CPU features, don't use any of the constant names in