<p>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.
<p>In monodroid each bridged object has a corresponding Java
mirror object. In the bridge callback it reifies the Mono
<div class="mapi-header">
enum {
- SGEN_BRIDGE_VERSION = 4
+ SGEN_BRIDGE_VERSION = 5
};
typedef enum {
+++ /dev/null
-//
-// 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")]
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
- <PropertyGroup>\r
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
- <ProductVersion>9.0.30729</ProductVersion>\r
- <SchemaVersion>2.0</SchemaVersion>\r
- <ProjectGuid>{5D05F5E2-7378-4A35-B1A3-76ABEB4A71C3}</ProjectGuid>\r
- <OutputType>Library</OutputType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <OutputPath>./../../../class/lib/net_4_x/Facades</OutputPath>\r
- <IntermediateOutputPath>obj-Facades</IntermediateOutputPath>\r
- <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>\r
- <NoStdLib>True</NoStdLib>\r
- \r
- <NoConfig>True</NoConfig>\r
- \r
- <AppDesignerFolder>Properties</AppDesignerFolder>\r
- <RootNamespace>\r
- </RootNamespace>\r
- <AssemblyName>System.Private.CoreLib.InteropServices</AssemblyName>\r
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>\r
- <FileAlignment>512</FileAlignment>\r
- </PropertyGroup>\r
- <PropertyGroup>\r
- <SignAssembly>true</SignAssembly>\r
- <DelaySign>true</DelaySign>\r
- </PropertyGroup>\r
- <PropertyGroup>\r
- <AssemblyOriginatorKeyFile>../../msfinal.pub</AssemblyOriginatorKeyFile>\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
- <DebugSymbols>true</DebugSymbols>\r
- <DebugType>full</DebugType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <Optimize>false</Optimize>\r
- <DefineConstants>TRACE;NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE</DefineConstants>\r
- <ErrorReport>prompt</ErrorReport>\r
- <WarningLevel>4</WarningLevel>\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
- <DebugType>pdbonly</DebugType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <Optimize>true</Optimize>\r
- <DefineConstants>NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE</DefineConstants>\r
- <ErrorReport>prompt</ErrorReport>\r
- <WarningLevel>4</WarningLevel>\r
- </PropertyGroup>\r
- <!-- Set AddAdditionalExplicitAssemblyReferences to false, otherwise if targetting .NET4.0, \r
- Microsoft.NETFramework.props will force a dependency on the assembly System.Core. This\r
- is a problem to compile the Mono mscorlib.dll -->\r
- <PropertyGroup>\r
- <AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>\r
- </PropertyGroup>\r
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
- <ItemGroup>\r
- <Compile Include="AssemblyInfo.cs" />\r
- <Compile Include="TypeForwarders.cs" />\r </ItemGroup>\r
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
- Other similar extension points exist, see Microsoft.Common.targets.\r
- <Target Name="BeforeBuild">\r
- </Target>\r
- <Target Name="AfterBuild">\r
- </Target>\r
- -->\r
- <PropertyGroup>\r
- <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
-
- </PreBuildEvent>\r
- <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">\r
-\r
- </PreBuildEvent>\r
- <PostBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
-
- </PostBuildEvent>\r
- <PostBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">\r
-\r
- </PostBuildEvent>\r
- </PropertyGroup>\r
- <ItemGroup>\r
- <ProjectReference Include="../../corlib/corlib-net_4_x.csproj">\r
- <Project>{2CA6026B-2DC8-4C4C-A12C-1E8234049DB7}</Project>\r
- <Name>corlib-net_4_x</Name>\r
- </ProjectReference>\r
- <ProjectReference Include="../../System/System-net_4_x.csproj">\r
- <Project>{2762E921-91A8-4C87-91E9-BA628013F753}</Project>\r
- <Name>System-net_4_x</Name>\r
- </ProjectReference>\r
- </ItemGroup>\r
- <ItemGroup>\r
- <Folder Include="Properties\" />\r
- </ItemGroup>\r
-</Project>\r
-
+++ /dev/null
-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
-
-
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
- <PropertyGroup>\r
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
- <ProductVersion>9.0.30729</ProductVersion>\r
- <SchemaVersion>2.0</SchemaVersion>\r
- <ProjectGuid>{BE4A05DF-5630-4E80-9521-7B4216229A60}</ProjectGuid>\r
- <OutputType>Library</OutputType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <OutputPath>./../../../class/lib/net_4_x/Facades</OutputPath>\r
- <NoStdLib>True</NoStdLib>\r
- <NoConfig>True</NoConfig>\r
- \r
- <AppDesignerFolder>Properties</AppDesignerFolder>\r
- <RootNamespace>\r
- </RootNamespace>\r
- <AssemblyName>System.Private.CoreLib.InteropServices</AssemblyName>\r
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>\r
- <FileAlignment>512</FileAlignment>\r
- </PropertyGroup>\r
- <PropertyGroup>\r
- <SignAssembly>true</SignAssembly>\r
- <DelaySign>true</DelaySign>\r
- </PropertyGroup>\r
- <PropertyGroup>\r
- <AssemblyOriginatorKeyFile>../../msfinal.pub</AssemblyOriginatorKeyFile>\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
- <DebugSymbols>true</DebugSymbols>\r
- <DebugType>full</DebugType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <Optimize>false</Optimize>\r
- <DefineConstants>DEBUG;TRACE;NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE</DefineConstants>\r
- <ErrorReport>prompt</ErrorReport>\r
- <WarningLevel>4</WarningLevel>\r
- </PropertyGroup>\r
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
- <DebugType>pdbonly</DebugType>\r
- <NoWarn>1699,1616,1699</NoWarn>\r
- <Optimize>true</Optimize>\r
- <DefineConstants>NET_4_0;NET_4_5;NET_4_6;MONO;DISABLE_CAS_USE</DefineConstants>\r
- <ErrorReport>prompt</ErrorReport>\r
- <WarningLevel>4</WarningLevel>\r
- </PropertyGroup>\r
- <!-- Set AddAdditionalExplicitAssemblyReferences to false, otherwise if targetting .NET4.0, \r
- Microsoft.NETFramework.props will force a dependency on the assembly System.Core. This\r
- is a problem to compile the Mono mscorlib.dll -->\r
- <PropertyGroup>\r
- <AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>\r
- </PropertyGroup>\r
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
- <ItemGroup>\r
- <Compile Include="AssemblyInfo.cs" />\r
- <Compile Include="TypeForwarders.cs" />\r </ItemGroup>\r
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
- Other similar extension points exist, see Microsoft.Common.targets.\r
- <Target Name="BeforeBuild">\r
- </Target>\r
- <Target Name="AfterBuild">\r
- </Target>\r
- -->\r
- <PropertyGroup>\r
- <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">\r
-\r
- </PreBuildEvent>\r
- <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">\r
-\r
- </PreBuildEvent>\r
-\r
- <PostBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">\r
-\r
- </PostBuildEvent>\r
- <PostBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">\r
-\r
- </PostBuildEvent>\r
- </PropertyGroup>\r
- <ItemGroup>\r
- <ProjectReference Include="../../corlib/corlib-net_4_x.csproj">\r
- <Project>{2CA6026B-2DC8-4C4C-A12C-1E8234049DB7}</Project>\r
- <Name>corlib-net_4_x</Name>\r
- </ProjectReference>\r
- <ProjectReference Include="../../corlib/corlib-net_4_x.csproj">\r
- <Project>{2CA6026B-2DC8-4C4C-A12C-1E8234049DB7}</Project>\r
- <Name>corlib-net_4_x</Name>\r
- </ProjectReference>\r
- <ProjectReference Include="../../System/System-net_4_x.csproj">\r
- <Project>{2762E921-91A8-4C87-91E9-BA628013F753}</Project>\r
- <Name>System-net_4_x</Name>\r
- </ProjectReference>\r
- </ItemGroup>\r
- <ItemGroup>\r
- <Folder Include="Properties\" />\r
- </ItemGroup>\r
-</Project>\r
-
+++ /dev/null
-TypeForwarders.cs
-AssemblyInfo.cs
-
+++ /dev/null
-//
-// 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))]
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
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]
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;
}
parent = storey = sm;
}
}
+ } else if (src_block.ParametersBlock.HasReferenceToStoreyForInstanceLambdas) {
+ src_block.ParametersBlock.StateMachine.AddParentStoreyReference (ec, storey);
}
modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
AwaitBlock = 1 << 13,
FinallyBlock = 1 << 14,
CatchBlock = 1 << 15,
+ HasReferenceToStoreyForInstanceLambdas = 1 << 16,
Iterator = 1 << 20,
NoFlowAnalysis = 1 << 21,
InitializationEmitted = 1 << 22
break;
}
}
-
+
//
// We are the first storey on path and 'this' has to be hoisted
//
//
// 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) {
#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;
--- /dev/null
+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<Task> a4 = async () =>
+ {
+ await Foo ();
+ };
+ }
+
+ await Task.Yield ();
+ };
+
+ a3 ();
+ }
+ };
+
+ a ();
+ }
+
+ async Task Foo ()
+ {
+ await Task.FromResult (1);
+ }
+
+}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="test-async-89.cs">
+ <type name="X">
+ <method name="Void Main()" attrs="150">
+ <size>12</size>
+ </method>
+ <method name="Void Test()" attrs="129">
+ <size>41</size>
+ </method>
+ <method name="System.Threading.Tasks.Task Foo()" attrs="129">
+ <size>33</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="X+<Test>c__AnonStorey1">
+ <method name="Void <>m__0()" attrs="131">
+ <size>67</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="X+<Foo>c__async0">
+ <method name="Void MoveNext()" attrs="486">
+ <size>158</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ <type name="X+<Test>c__AnonStorey1+<Test>c__AnonStorey2">
+ <method name="Void <>m__0()" attrs="131">
+ <size>13</size>
+ </method>
+ <method name="Void <>m__1()" attrs="131">
+ <size>48</size>
+ </method>
+ <method name="System.Threading.Tasks.Task <>m__2()" attrs="131">
+ <size>46</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="X+<Test>c__AnonStorey1+<Test>c__AnonStorey2+<Test>c__async3">
+ <method name="Void MoveNext()" attrs="486">
+ <size>179</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ <type name="X+<Test>c__AnonStorey1+<Test>c__AnonStorey2+<Test>c__async4">
+ <method name="Void MoveNext()" attrs="486">
+ <size>167</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ </test>
<test name="test-cls-00.cs">
<type name="CLSCLass_6">
<method name="Void add_Disposed(Delegate)" attrs="2182">
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
{
No
}
+ public enum Platform {
+ AnyCPU,
+ AnyCPU32Preferred,
+ Arm,
+ X86,
+ X64,
+ IA64
+ }
+
public class AssemblyLinker {
ArrayList inputFiles = new ArrayList ();
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)
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);
}
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":
case "description":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyDescriptionAttribute), arg);
+ description = arg;
return true;
case "e":
if (arg == null)
ReportMissingText (opt);
- AddCattr (typeof (AssemblyFileVersionAttribute), arg);
+ AddCattr (typeof (System.Reflection.AssemblyFileVersionAttribute), arg);
return true;
case "flags":
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);
}
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":
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":
Version ();
break;
}
- AddCattr (typeof (AssemblyVersionAttribute), arg);
+ AddCattr (typeof (System.Reflection.AssemblyVersionAttribute), arg);
return true;
case "win32icon":
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);
}
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);
*/
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;
if (isAssembly)
ReportWarning (1020, "Ignoring included assembly '" + mod.fileName + "'");
else
- mi.Invoke (ab, new object [] { mod.fileName });
+ ab.__AddModule (universe.OpenRawModule(mod.fileName));
}
/*
MethodInfo mainMethodInfo = null;
try {
- Type mainType = ab.GetType (mainClass);
+ IKVM.Reflection.Type mainType = ab.GetType (mainClass);
if (mainType != null)
mainMethodInfo = mainType.GetMethod (mainMethod);
}
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);
}
}
+ ModuleBuilder mainModule = null;
+
foreach (ResourceInfo res in resources) {
if (res.name == null)
res.name = Path.GetFileName (res.fileName);
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) {
}
}
+ 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);
{
// 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<string> ();
- 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;
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;
}
}
" /main:<method> Specifies the method name of the entry point",
" /nologo Suppress the startup banner and copyright message",
" /out:<filename> Output file name for the assembly manifest",
+ " /platform:<text> Limit which platforms this code can run on; must be",
+ " one of x86, Itanium, x64, arm, anycpu32bitpreferred,",
+ " or anycpu (the default)",
" /prod[uct]:<text> Product name",
" /productv[ersion]:<text> Product version",
" /t[arget]:lib[rary] Create a library",
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);
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().
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;
}
}
+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)
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 ();
}
}
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;
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 */
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.");
* 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),
MONO_BEGIN_DECLS
enum {
- SGEN_BRIDGE_VERSION = 4
+ SGEN_BRIDGE_VERSION = 5
};
typedef enum {
} 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;
#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);
#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
}
#endif
-static char *dump_prefix = NULL;
-
static void
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)
{
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;
}
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
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;
}
#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"
* 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
//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<<API_INDEX_BITS)-1)
+#define INCOMING_COLORS_MAX ((1<<INCOMING_COLORS_BITS)-1)
+
// ScanData state
enum {
INITIAL,
/*
Optimizations:
We can split this data structure in two, those with bridges and those without
+ (and only bridgeless need to record incoming_colors)
*/
typedef struct {
- // Colors (ColorDatas) linked to by objects with this color
+ // Colors (ColorDatas) linked to by objects with this color
DynPtrArray other_colors;
- // Bridge objects (GCObjects) held by objects with this color
+ // Bridge objects (GCObjects) held by objects with this color
DynPtrArray bridges;
- int api_index : 31;
+ // Index of this color's MonoGCBridgeSCC in the array passed to the client (or -1 for none)
+ signed api_index : API_INDEX_BITS;
+ // Count of colors that list this color in their other_colors
+ unsigned incoming_colors : INCOMING_COLORS_BITS;
unsigned visited : 1;
} ColorData;
// Tarjan algorithm index (order visited)
int index;
// Tarjan index of lowest-index object known reachable from here
- int low_index : 27;
+ signed low_index : 27;
// See "ScanData state" enum above
unsigned state : 2;
unsigned obj_state : 2;
} ScanData;
+/* Should color be made visible to client even though it has no bridges?
+ * True if we predict the number of reduced edges to be enough to justify the extra node.
+ */
+static inline gboolean
+bridgeless_color_is_heavy (ColorData *data) {
+ int fanin = data->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,
// 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;
static ObjectBucket *cur_object_bucket;
static int object_data_count;
+// Arenas to allocate ScanData from
static ObjectBucket*
new_object_bucket (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;
//----------
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.
#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;
}
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)
{
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);
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;
+ }
}
}
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;
}
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;
}
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;
}
#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);
g_assert (cd->visited);
cd->visited = FALSE;
}
- dyn_array_ptr_empty (&color_merge_array);
+ color_merge_array_empty ();
found_bridge = FALSE;
}
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);
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);
if (!src->visited)
continue;
src->visited = FALSE;
- if (!dyn_array_ptr_size (&src->bridges))
+ if (!color_visible_to_client (src))
reset_xrefs (src);
}
}
static void
processing_build_callback_data (int generation)
{
- int j, api_index;
- MonoGCBridgeSCC **api_sccs;
- MonoGCBridgeXRef *api_xrefs;
+ int j;
gint64 curtime;
ColorBucket *cur;
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);
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);
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)
#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;
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);
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,
xref_setup_time / 10000.0f,
cleanup_time / 10000.0f);
- cache_hits = cache_misses = 0;
+ cache_hits = cache_semihits = cache_misses = 0;
ignored_objects = 0;
}
// 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)
{
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;
}
#include <mono/utils/mono-mmap.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-tls.h>
-#include <mono/utils/mono-hwcap-x86.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/utils/mono-threads.h>
#include "trace.h"
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-arm.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/metadata/threads.h>
#include <mono/metadata/profiler-private.h>
#include <mono/utils/mono-math.h>
-#include <mono/utils/mono-hwcap-ia64.h>
+#include <mono/utils/mono-hwcap.h>
#include "trace.h"
#include "mini-ia64.h"
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-mips.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/arch/mips/mips-codegen.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/utils/mono-proclib.h>
#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-ppc.h>
+#include <mono/utils/mono-hwcap.h>
#include "mini-ppc.h"
#ifdef TARGET_POWERPC64
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/mono-math.h>
#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-s390x.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/utils/mono-threads.h>
#include "mini-s390x.h"
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.
}
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);
}
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;
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);
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);
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);
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);
{
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 |
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/tokentype.h>
#include <mono/utils/mono-math.h>
-#include <mono/utils/mono-hwcap-sparc.h>
+#include <mono/utils/mono-hwcap.h>
#include "mini-sparc.h"
#include "trace.h"
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-mmap.h>
#include <mono/utils/mono-memory-model.h>
-#include <mono/utils/mono-hwcap-x86.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/utils/mono-threads.h>
#include "trace.h"
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-");
}
/*
atomic.c \
mono-hwcap.h \
mono-hwcap.c \
+ mono-hwcap-vars.h \
bsearch.h \
bsearch.c \
mono-signal-handler.h \
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)
* 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 <sys/auxv.h>
#include <stdio.h>
#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)
{
}
#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);
-}
+++ /dev/null
-#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__ */
/*
- * 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)
-{
-}
+++ /dev/null
-#ifndef __MONO_UTILS_HWCAP_ARM64_H__
-#define __MONO_UTILS_HWCAP_ARM64_H__
-
-#include "mono/utils/mono-hwcap.h"
-
-#endif
--- /dev/null
+/*
+ * 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)
+{
+}
* 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)
{
}
+++ /dev/null
-#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__ */
* 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)
{
}
+++ /dev/null
-#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__ */
* 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 <string.h>
#include <sys/auxv.h>
#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)
{
}
#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);
-}
+++ /dev/null
-#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__ */
* 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 <signal.h>
-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;
}
+++ /dev/null
-#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__ */
* 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 <string.h>
-
#if !defined(__linux__)
#include <sys/systeminfo.h>
#else
#include <unistd.h>
#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.
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);
-}
--- /dev/null
+#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
* 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 <unistd.h>
#endif
-
#if defined(_MSC_VER)
#include <intrin.h>
#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)
{
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);
-}
+++ /dev/null
-#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__ */
#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
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");
}
#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.
* 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