net_4_0_SUBDIRS := build class
net_4_5_SUBDIRS := build mcs class nunit24 ilasm tools tests errors docs
xbuild_12_SUBDIRS := build class tools/xbuild
+xbuild_14_SUBDIRS := build class tools/xbuild
# List of test subdirs that should pass 100%
centum_tests := \
# fun specialty targets
-PROFILES = net_2_0 net_3_5 net_4_0 net_4_5 xbuild_12
+PROFILES = net_2_0 net_3_5 net_4_0 net_4_5 xbuild_12 xbuild_14
.PHONY: all-profiles $(STD_TARGETS:=-profiles)
all-profiles $(STD_TARGETS:=-profiles): %-profiles: profiles-do--%
# Orchestrate the bootstrap here.
_boot_ = all clean install
+$(_boot_:%=profile-do--xbuild_14--%): profile-do--xbuild_14--%: profile-do--net_4_5--%
$(_boot_:%=profile-do--xbuild_12--%): profile-do--xbuild_12--%: profile-do--net_4_5--%
$(_boot_:%=profile-do--net_4_5--%): profile-do--net_4_5--%: profile-do--build--%
$(_boot_:%=profile-do--net_4_0--%): profile-do--net_4_0--%: profile-do--build--%
net_3_5 \
net_4_0 \
net_4_5 \
- xbuild_12
+ xbuild_12 \
+ xbuild_14
COMMON_SRCS = \
Consts.cs.in \
--- /dev/null
+# -*- makefile -*-
+
+include $(topdir)/build/profiles/net_4_5.make
+
+PROFILE_MCS_FLAGS := $(PROFILE_MCS_FLAGS) -d:XBUILD_12 -d:XBUILD_14 -lib:$(topdir)/class/lib/net_4_5
+
+XBUILD_VERSION = 14.0
net_4_0_SUBDIRS := $(net_2_0_dirs) $(net_4_0_dirs) $(net_4_0_only_dirs) $(xbuild_4_0_dirs)
net_4_5_SUBDIRS := $(net_2_0_dirs) $(net_4_0_dirs) $(net_4_5_dirs) $(xbuild_4_0_dirs) aot-compiler
xbuild_12_SUBDIRS := $(xbuild_4_0_dirs)
+xbuild_14_SUBDIRS := $(xbuild_4_0_dirs)
include ../build/rules.make
get {
// This is used as the fall back version if the
// project can't find a version to use
- // Hard-coded to 2.0, so it allows even vs2005 projects
- // to build correctly, as they won't have a ToolsVersion
- // set!
return String.IsNullOrEmpty (defaultToolsVersion)
- ? "2.0"
+ ? "4.0"
: defaultToolsVersion;
}
set {
public static string BinPath {
get {
if (RunningOnMono ()) {
-#if XBUILD_12
+#if XBUILD_14
+ string profile = "xbuild_14";
+#elif XBUILD_12
string profile = "xbuild_12";
#elif NET_4_5
string profile = "net_4_5";
var lib = Path.GetDirectoryName (Path.GetDirectoryName (corlib));
return Path.Combine (lib, profile);
} else {
-#if XBUILD_12
+#if XBUILD_14
+ return ToolLocationHelper.GetPathToBuildTools ("14.0");
+#elif XBUILD_12
return ToolLocationHelper.GetPathToBuildTools ("12.0");
#elif NET_4_5
return ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version45);
public static string ToolsVersionString {
get {
-#if XBUILD_12
+#if XBUILD_14
+ return " ToolsVersion='14.0'";
+#elif XBUILD_12
return " ToolsVersion='12.0'";
#elif NET_4_0
return " ToolsVersion='4.0'";
public static string GetTasksAsmPath ()
{
-#if XBUILD_12
+#if XBUILD_14
+ return Path.Combine (BinPath, "Microsoft.Build.Tasks.Core.dll");
+#elif XBUILD_12
return Path.Combine (BinPath, "Microsoft.Build.Tasks.v12.0.dll");
#elif NET_4_0
return Path.Combine (BinPath, "Microsoft.Build.Tasks.v4.0.dll");
#if XBUILD_12
Version451,
#endif
+#if XBUILD_14
+ Version453,
+#endif
-#if XBUILD_12
+#if XBUILD_14
+ VersionLatest = Version453
+#elif XBUILD_12
VersionLatest = Version451
#elif NET_4_5
VersionLatest = Version45
public static string GetPathToBuildTools (string toolsVersion)
{
- if (toolsVersion != "12.0")
+ string path;
+ switch (toolsVersion) {
+ case "12.0":
+ path = "xbuild_12";
+ break;
+ case "14.0":
+ path = "xbuild_14";
+ break;
+ default:
return null;
+ }
if (Environment.GetEnvironmentVariable ("TESTING_MONO") != null)
- return Path.Combine (lib_mono_dir, "xbuild_12");
+ return Path.Combine (lib_mono_dir, path);
if (runningOnDotNet) {
//see http://msdn.microsoft.com/en-us/library/vstudio/bb397428(v=vs.120).aspx
#endif
#if XBUILD_12
AddToolset (new Toolset ("12.0", ToolLocationHelper.GetPathToBuildTools ("12.0"), this, null));
+#endif
+#if XBUILD_14
+ AddToolset (new Toolset ("14.0", ToolLocationHelper.GetPathToBuildTools ("14.0"), this, null));
#endif
default_tools_version = toolsets.First ().ToolsVersion;
}
{
Evaluator.Run ("class A { class B { } }");
Evaluator.Run ("var x = new A ();");
+ }
+ [Test]
+ public void DelegateType ()
+ {
+ Evaluator.Run ("public delegate int D();");
+ Evaluator.Run ("D d = delegate () { return 7; };");
+ object res = Evaluator.Evaluate ("d();");
+ Assert.AreEqual (7, res);
}
}
}
\ No newline at end of file
return FromTimeT (time);
}
+ public static DateTime ToDateTime (long time, long nanoTime)
+ {
+ return FromTimeT (time).AddMilliseconds (nanoTime / 1000);
+ }
+
public static long FromDateTime (DateTime time)
{
return ToTimeT (time);
}
public DateTime LastAccessTime {
- get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_atime);}
+ get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_atime, stat.st_atime_nsec);}
}
public DateTime LastAccessTimeUtc {
}
public DateTime LastWriteTime {
- get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_mtime);}
+ get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_mtime, stat.st_mtime_nsec);}
}
public DateTime LastWriteTimeUtc {
}
public DateTime LastStatusChangeTime {
- get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_ctime);}
+ get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_ctime, stat.st_ctime_nsec);}
}
public DateTime LastStatusChangeTimeUtc {
else if (n2 == null)
return 1;
else if (n1.Prefix == n2.Prefix)
- return string.Compare (n1.LocalName, n2.LocalName);
+ return string.CompareOrdinal (n1.LocalName, n2.LocalName);
// Attributes in the default namespace are first
// because the default namespace is not applied to
Assert.IsTrue (vrfy.CheckSignature (), "RSA-Compute/Verify");
}
+ // The same as MSDNSample(), but adding a few attributes
+ public SignedXml MSDNSampleMixedCaseAttributes ()
+ {
+ // Create example data to sign.
+ XmlDocument document = new XmlDocument ();
+ XmlNode node = document.CreateNode (XmlNodeType.Element, "", "MyElement", "samples");
+ node.InnerText = "This is some text";
+ XmlAttribute a1 = document.CreateAttribute ("Aa");
+ XmlAttribute a2 = document.CreateAttribute ("Bb");
+ XmlAttribute a3 = document.CreateAttribute ("aa");
+ XmlAttribute a4 = document.CreateAttribute ("bb");
+ a1.Value = "one";
+ a2.Value = "two";
+ a3.Value = "three";
+ a4.Value = "four";
+ node.Attributes.Append (a1);
+ node.Attributes.Append (a2);
+ node.Attributes.Append (a3);
+ node.Attributes.Append (a4);
+ document.AppendChild (node);
+
+ // Create the SignedXml message.
+ SignedXml signedXml = new SignedXml ();
+
+ // Create a data object to hold the data to sign.
+ DataObject dataObject = new DataObject ();
+ dataObject.Data = document.ChildNodes;
+ dataObject.Id = "MyObjectId";
+
+ // Add the data object to the signature.
+ signedXml.AddObject (dataObject);
+
+ // Create a reference to be able to package everything into the
+ // message.
+ Reference reference = new Reference ();
+ reference.Uri = "#MyObjectId";
+
+ // Add it to the message.
+ signedXml.AddReference (reference);
+
+ return signedXml;
+ }
+
+ public string AsymmetricRSAMixedCaseAttributes ()
+ {
+ SignedXml signedXml = MSDNSampleMixedCaseAttributes ();
+
+ RSA key = RSA.Create ();
+ signedXml.SigningKey = key;
+
+ // Add a KeyInfo.
+ KeyInfo keyInfo = new KeyInfo ();
+ keyInfo.AddClause (new RSAKeyValue (key));
+ signedXml.KeyInfo = keyInfo;
+
+ // Compute the signature.
+ signedXml.ComputeSignature ();
+
+ // Get the XML representation of the signature.
+ XmlElement xmlSignature = signedXml.GetXml ();
+
+ StringWriter sw = new StringWriter ();
+ XmlWriter w = new XmlTextWriter (sw);
+ xmlSignature.WriteTo (w);
+ return sw.ToString ();
+ }
+
+ // Example output from Windows for AsymmetricRSAMixedCaseAttributes()
+ private const string AsymmetricRSAMixedCaseAttributesResult = "<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\" /><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\" /><Reference URI=\"#MyObjectId\"><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>0j1xLsePFtuRHfXEnVdTSLWtAm4=</DigestValue></Reference></SignedInfo><SignatureValue>hmrEBgns5Xx14aDhzqOyIh0qLNMUldtW8+fNPcvtD/2KtEhNZQGctnhs90CRa1NZ08TqzW2pUaEwmqvMAtF4v8KtWzC/zTuc1jH6nxQvQSQo0ABhuXdu7/hknZkXJ4yKBbdgbKjAsKfULwbWrP/PacLPoYfCO+wXSrt+wLMTTWU=</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>4h/rHDr54r6SZWk2IPCeHX7N+wR1za0VBLshuS6tq3RSWap4PY2BM8VdbKH2T9RzyZoiHufjng+1seUx430iMsXisOLUkPP+yGtMQOSZ3CQHAa+IYA+fplXipixI0rV1J1wJNXQm3HxXQqKWpIv5fkwBtj8o2k6CWMgPNgFCnxc=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue></KeyInfo><Object Id=\"MyObjectId\"><MyElement Aa=\"one\" Bb=\"two\" aa=\"three\" bb=\"four\" xmlns=\"samples\">This is some text</MyElement></Object></Signature>";
+
+ [Test]
+ public void AsymmetricRSAMixedCaseAttributesVerifyWindows ()
+ {
+ XmlDocument doc = new XmlDocument ();
+ doc.LoadXml (AsymmetricRSAMixedCaseAttributesResult);
+
+ SignedXml v1 = new SignedXml ();
+ v1.LoadXml (doc.DocumentElement);
+ Assert.IsTrue (v1.CheckSignature ());
+ }
+
[Test]
public void AsymmetricDSASignature ()
{
Assert.AreEqual (new StreamReader (s, Encoding.UTF8).ReadToEnd (), expected);
}
+ [Test]
+ public void OrdinalSortForAttributes ()
+ {
+ XmlDocument doc = new XmlDocument ();
+ string xml = "<foo Aa=\"one\" Bb=\"two\" aa=\"three\" bb=\"four\"><bar></bar></foo>";
+ doc.LoadXml (xml);
+
+ transform.LoadInput (doc);
+ Stream s = (Stream) transform.GetOutput ();
+ string output = Stream2String (s);
+ Assert.AreEqual (xml, output);
+ }
+
#if NET_2_0
[Test]
public void PrefixlessNamespaceOutput ()
XmlTextReader xmlReader = new XmlTextReader (value, XmlNodeType.Element, ctx);
xmlReader.XmlResolver = OwnerDocument.Resolver;
- do {
- XmlNode n = OwnerDocument.ReadNode (xmlReader);
- if(n == null) break;
- AppendChild (n);
- } while (true);
+ bool pw = OwnerDocument.PreserveWhitespace;
+ OwnerDocument.PreserveWhitespace = true;
+ try {
+ do {
+ XmlNode n = OwnerDocument.ReadNode (xmlReader);
+ if(n == null) break;
+ AppendChild (n);
+ } while (true);
+ } finally {
+ OwnerDocument.PreserveWhitespace = pw;
+ }
}
}
#else
if (runningOnUnix) {
try {
- if (Platform.IsMacOS)
+ if (Platform.IsMacOS || Platform.IsFreeBSD)
return MacOsNetworkInterface.ImplGetAllNetworkInterfaces ();
else
return LinuxNetworkInterface.ImplGetAllNetworkInterfaces ();
var opCode = MessageTypeToWire (type);
var length = buffer.Count;
- headerBuffer[0] = (byte)(opCode | (endOfMessage ? 0 : 0x80));
+ headerBuffer[0] = (byte)(opCode | (endOfMessage ? 0x80 : 0));
if (length < 126) {
headerBuffer[1] = (byte)length;
} else if (length <= ushort.MaxValue) {
namespace System {
internal static class Platform {
+ static bool checkedOS;
+ static bool isMacOS;
+ static bool isFreeBSD;
+
#if MONOTOUCH || XAMMAC
- public static bool IsMacOS {
- get { return true; }
+ private static void CheckOS() {
+ isMacOS = true;
+ checkedOS = true;
}
#else
[DllImport ("libc")]
static extern int uname (IntPtr buf);
-
- static bool checkedIsMacOS;
- static bool isMacOS;
-
- public static bool IsMacOS {
- get {
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- return false;
- if (!checkedIsMacOS) {
- IntPtr buf = Marshal.AllocHGlobal (8192);
- if (uname (buf) == 0) {
- string os = Marshal.PtrToStringAnsi (buf);
- if (os == "Darwin")
- isMacOS = true;
- }
- Marshal.FreeHGlobal (buf);
- checkedIsMacOS = true;
+ private static void CheckOS() {
+ if (Environment.OSVersion.Platform != PlatformID.Unix) {
+ checkedOS = true;
+ return;
+ }
+
+ IntPtr buf = Marshal.AllocHGlobal (8192);
+ if (uname (buf) == 0) {
+ string os = Marshal.PtrToStringAnsi (buf);
+ switch (os) {
+ case "Darwin":
+ isMacOS = true;
+ break;
+ case "FreeBSD":
+ isFreeBSD = true;
+ break;
}
-
- return isMacOS;
}
+ Marshal.FreeHGlobal (buf);
+ checkedOS = true;
}
#endif
+
+ public static bool IsMacOS {
+ get {
+ if (!checkedOS)
+ CheckOS();
+ return isMacOS;
+ }
+ }
+
+ public static bool IsFreeBSD {
+ get {
+ if (!checkedOS)
+ CheckOS();
+ return isFreeBSD;
+ }
+ }
}
}
}
[Test]
+ [Ignore ("See bug #24340")]
public void EchoTest ()
{
const string Payload = "This is a websocket test";
}
[Test]
+ [Ignore ("See bug #24340")]
public void CloseOutputAsyncTest ()
{
Assert.IsTrue (socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (5000));
Assert.Fail ("Should have thrown");
}
+ [Test]
+ [Category ("NotWorking")] // FIXME: test relies on unimplemented HttpListenerContext.AcceptWebSocketAsync (), reenable it when the method is implemented
+ public void SendAsyncEndOfMessageTest ()
+ {
+ var cancellationToken = new CancellationTokenSource (TimeSpan.FromSeconds (30)).Token;
+ SendAsyncEndOfMessageTest (false, WebSocketMessageType.Text, cancellationToken).Wait (5000);
+ SendAsyncEndOfMessageTest (true, WebSocketMessageType.Text, cancellationToken).Wait (5000);
+ SendAsyncEndOfMessageTest (false, WebSocketMessageType.Binary, cancellationToken).Wait (5000);
+ SendAsyncEndOfMessageTest (true, WebSocketMessageType.Binary, cancellationToken).Wait (5000);
+ }
+
+ public async Task SendAsyncEndOfMessageTest (bool expectedEndOfMessage, WebSocketMessageType webSocketMessageType, CancellationToken cancellationToken)
+ {
+ using (var client = new ClientWebSocket ()) {
+ // Configure the listener.
+ var serverReceive = HandleHttpWebSocketRequestAsync<WebSocketReceiveResult> (async socket => await socket.ReceiveAsync (new ArraySegment<byte> (new byte[32]), cancellationToken), cancellationToken);
+
+ // Connect to the listener and make the request.
+ await client.ConnectAsync (new Uri ("ws://localhost:" + Port + "/"), cancellationToken);
+ await client.SendAsync (new ArraySegment<byte> (Encoding.UTF8.GetBytes ("test")), webSocketMessageType, expectedEndOfMessage, cancellationToken);
+
+ // Wait for the listener to handle the request and return its result.
+ var result = await serverReceive;
+
+ // Cleanup and check results.
+ await client.CloseAsync (WebSocketCloseStatus.NormalClosure, "Finished", cancellationToken);
+ Assert.AreEqual (expectedEndOfMessage, result.EndOfMessage, "EndOfMessage should be " + expectedEndOfMessage);
+ }
+ }
+
+ async Task<T> HandleHttpWebSocketRequestAsync<T> (Func<WebSocket, Task<T>> action, CancellationToken cancellationToken)
+ {
+ var ctx = await this.listener.GetContextAsync ();
+ var wsContext = await ctx.AcceptWebSocketAsync (null);
+ var result = await action (wsContext.WebSocket);
+ await wsContext.WebSocket.CloseOutputAsync (WebSocketCloseStatus.NormalClosure, "Finished", cancellationToken);
+ return result;
+ }
+
async Task HandleHttpRequestAsync (Action<HttpListenerRequest, HttpListenerResponse> handler)
{
var ctx = await listener.GetContextAsync ();
//
// Be careful not to cause recursive CultureInfo initialization
//
- var msg = string.Format (InvariantCulture, "Culture ID {0} (0x{0:X4}) is not a supported culture.", culture.ToString (InvariantCulture));
+ var msg = string.Format (InvariantCulture, "Culture ID {0} (0x{1}) is not a supported culture.", culture.ToString (InvariantCulture), culture.ToString ("X4", InvariantCulture));
#if NET_4_0
throw new CultureNotFoundException ("culture", msg);
#else
public static Exception GetExceptionForHR (int errorCode, IntPtr errorInfo)
{
+#if !MOBILE
IErrorInfo info = null;
if (errorInfo != (IntPtr)(-1)) {
if (errorInfo == IntPtr.Zero) {
}
}
return e;
+#else
+ return ConvertHrToException (errorCode);
+#endif
}
#if !FULL_AOT_RUNTIME
--- /dev/null
+// CS0121: The call is ambiguous between the following methods or properties: `A.B.X.Test(this int)' and `A.C.X.Test(this int)'
+// Line: 37
+
+using System;
+
+namespace A.B
+{
+ static class X
+ {
+ public static int Test (this int o)
+ {
+ return 1;
+ }
+ }
+}
+
+namespace A.C
+{
+ static class X
+ {
+ public static int Test (this int o)
+ {
+ return 2;
+ }
+ }
+}
+
+namespace C
+{
+ using A.B;
+ using A.C.X;
+
+ class M
+ {
+ public static int Main ()
+ {
+ if (1.Test () != 1)
+ return 1;
+
+ return 0;
+ }
+ }
+}
\ No newline at end of file
// CS0170: Use of possibly unassigned field `a'
-// Line: 23
-
-using System;
+// Line: 21
namespace CS0170
{
Foo f;
Bar b = new Bar();
b.Inc (f.a);
- Console.WriteLine (f.a);
}
}
}
+++ /dev/null
-// CS0188: The `this' object cannot be used before all of its fields are assigned to
-// Line: 11
-
-using System;
-
-public struct S
-{
- public int A { get; private set;}
- public event EventHandler eh;
-
- public S (int a)
- {
- this.eh = null;
- A = a;
- }
-}
--- /dev/null
+// CS0200: Property or indexer `A.X' cannot be assigned to (it is read-only)
+// Line: 13
+
+public class A
+{
+ public int X { get; }
+}
+
+public class B : A
+{
+ public B ()
+ {
+ base.X = 1;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0200: Property or indexer `C.S' cannot be assigned to (it is read-only)
+// Line: 10
+
+class C
+{
+ public static int S { get; }
+
+ public C ()
+ {
+ S = 3;
+ }
+}
--- /dev/null
+// CS0200: Property or indexer `C.P' cannot be assigned to (it is read-only)
+// Line: 10
+
+class C
+{
+ public int P { get; }
+
+ public void Foo ()
+ {
+ P = 10;
+ }
+}
+++ /dev/null
-// CS0843: An automatically implemented property `S.A' must be fully assigned before control leaves the constructor. Consider calling the default struct contructor from a constructor initializer
-// Line: 8
-
-public struct S
-{
- public int A { get; set;}
-
- public S (int a)
- {
- this.A = a;
- }
-}
+++ /dev/null
-// CS0843: An automatically implemented property `S.A' must be fully assigned before control leaves the constructor. Consider calling the default struct contructor from a constructor initializer
-// Line: 11
-
-using System;
-
-public struct S
-{
- public int A { get; set;}
- event EventHandler eh;
-
- public S (int a)
- {
- this.eh = null;
- A = a;
- }
-}
// Line: 5
// Compiler options: -warnaserror
-#pragma warning disable AAA
+#pragma warning disable 1AAA
class MainClass {
}
-// CS8051: Auto-implemented property `Test.Property' must have set accessor or initializer
+// CS8051: Auto-implemented property `V.P' must have get accessor
// Line: 6
-public abstract class Test
+class V
{
- public string Property { get; }
-}
+ public object P { set; } = 1;
+}
\ No newline at end of file
-// CS8052: Auto-implemented property `V.P' must have get accessor
+// CS8052: `I.P': Properties inside interfaces cannot have initializers
// Line: 6
-class V
+interface I
{
- public object P { set; } = 1;
+ int P { get; } = 4;
}
\ No newline at end of file
+++ /dev/null
-// CS8053: `I.P': Properties inside interfaces cannot have initializers
-// Line: 6
-
-interface I
-{
- int P { get; } = 4;
-}
\ No newline at end of file
--- /dev/null
+// CS8079: Use of possibly unassigned auto-implemented property `X'
+// Line: 11
+
+public struct S
+{
+ public int X { get; set; }
+ public int Y;
+
+ public S ()
+ {
+ Y = X;
+ X = 0;
+ }
+}
\ No newline at end of file
vi_product = a.GetString ();
} else if (a.Type == pa.AssemblyCompany) {
vi_company = a.GetString ();
- } else if (a.Type == pa.AssemblyDescription) {
- // TODO: Needs extra api
} else if (a.Type == pa.AssemblyCopyright) {
vi_copyright = a.GetString ();
} else if (a.Type == pa.AssemblyTrademark) {
has_user_debuggable = true;
}
+ //
+ // Win32 version info attributes AssemblyDescription and AssemblyTitle cannot be
+ // set using public API and because we have blob like attributes we need to use
+ // special option DecodeVersionInfoAttributeBlobs to support values extraction
+ //
+
SetCustomAttribute (ctor, cdata);
}
{
source.FlowAnalysis (fc);
- if (target is ArrayAccess || target is IndexerExpr || target is PropertyExpr)
+ if (target is ArrayAccess || target is IndexerExpr) {
+ target.FlowAnalysis (fc);
+ return;
+ }
+
+ var pe = target as PropertyExpr;
+ if (pe != null && !pe.IsAutoPropertyAccess)
target.FlowAnalysis (fc);
}
fe.SetFieldAssigned (fc);
return;
}
+
+ var pe = target as PropertyExpr;
+ if (pe != null) {
+ pe.SetBackingFieldAssigned (fc);
+ return;
+ }
}
public override void MarkReachable (Reachability rc)
public readonly PredefinedAttribute FieldOffset;
public readonly PredefinedAttribute AssemblyProduct;
public readonly PredefinedAttribute AssemblyCompany;
- public readonly PredefinedAttribute AssemblyDescription;
public readonly PredefinedAttribute AssemblyCopyright;
public readonly PredefinedAttribute AssemblyTrademark;
public readonly PredefinedAttribute CallerMemberNameAttribute;
FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
AssemblyProduct = new PredefinedAttribute (module, "System.Reflection", "AssemblyProductAttribute");
AssemblyCompany = new PredefinedAttribute (module, "System.Reflection", "AssemblyCompanyAttribute");
- AssemblyDescription = new PredefinedAttribute (module, "System.Reflection", "AssemblyDescriptionAttribute");
AssemblyCopyright = new PredefinedAttribute (module, "System.Reflection", "AssemblyCopyrightAttribute");
AssemblyTrademark = new PredefinedAttribute (module, "System.Reflection", "AssemblyTrademarkAttribute");
return current_token;
}
- int TokenizePreprocessorIdentifier (out int c)
+ int TokenizePreprocessorKeyword (out int c)
{
// skip over white space
do {
tokens_seen = false;
arg = "";
- var cmd = GetPreprocessorDirective (id_builder, TokenizePreprocessorIdentifier (out c));
+ var cmd = GetPreprocessorDirective (id_builder, TokenizePreprocessorKeyword (out c));
if ((cmd & PreprocessorDirective.CustomArgumentsParsing) != 0)
return cmd;
int c;
- int length = TokenizePreprocessorIdentifier (out c);
+ int length = TokenizePreprocessorKeyword (out c);
if (length == line_default.Length) {
if (!IsTokenIdentifierEqual (line_default))
return false;
return string_builder.ToString ();
}
- int TokenizePragmaNumber (ref int c)
+ int TokenizePragmaWarningIdentifier (ref int c, ref bool identifier)
{
- number_pos = 0;
- int number;
+ if ((c >= '0' && c <= '9') || is_identifier_start_character (c)) {
+ int number;
- if (c >= '0' && c <= '9') {
- number = TokenizeNumber (c);
+ if (c >= '0' && c <= '9') {
+ number_pos = 0;
+ number = TokenizeNumber (c);
- c = get_char ();
+ c = get_char ();
+
+ if (c != ' ' && c != '\t' && c != ',' && c != '\n' && c != -1 && c != UnicodeLS && c != UnicodePS) {
+ return ReadPragmaWarningComment (c);
+ }
+ } else {
+ //
+ // LAMESPEC v6: No spec what identifier really is in this context, it seems keywords are allowed too
+ //
+ int pos = 0;
+ number = -1;
+ id_builder [pos++] = (char)c;
+ while (c < MaxIdentifierLength) {
+ c = reader.Read ();
+ id_builder [pos] = (char)c;
+
+ if (c >= '0' && c <= '9') {
+ if (pos == 6 && id_builder [0] == 'C' && id_builder [1] == 'S') {
+ // Recognize CSXXXX as C# XXXX warning
+ number = 0;
+ int pow = 1000;
+ for (int i = 0; i < 4; ++i) {
+ var ch = id_builder [i + 2];
+ if (ch < '0' || ch > '9') {
+ number = -1;
+ break;
+ }
+
+ number += (ch - '0') * pow;
+ pow /= 10;
+ }
+ }
+ } else if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && c != '_') {
+ break;
+ }
+
+ ++pos;
+ }
+
+ if (number < 0) {
+ identifier = true;
+ number = pos;
+ }
+ }
// skip over white space
while (c == ' ' || c == '\t')
// skip over white space
while (c == ' ' || c == '\t')
c = get_char ();
+
+ return number;
+ }
+
+ return ReadPragmaWarningComment (c);
+ }
+
+ int ReadPragmaWarningComment (int c)
+ {
+ if (c == '/') {
+ ReadSingleLineComment ();
} else {
- number = -1;
- if (c == '/') {
- ReadSingleLineComment ();
- } else {
- Report.Warning (1692, 1, Location, "Invalid number");
+ Report.Warning (1692, 1, Location, "Invalid number");
- // Read everything till the end of the line or file
- ReadToEndOfLine ();
- }
+ // Read everything till the end of the line or file
+ ReadToEndOfLine ();
}
- return number;
+ return -1;
}
void ReadToEndOfLine ()
void ParsePragmaDirective ()
{
int c;
- int length = TokenizePreprocessorIdentifier (out c);
+ int length = TokenizePreprocessorKeyword (out c);
if (length == pragma_warning.Length && IsTokenIdentifierEqual (pragma_warning)) {
- length = TokenizePreprocessorIdentifier (out c);
+ length = TokenizePreprocessorKeyword (out c);
//
// #pragma warning disable
//
int code;
do {
- code = TokenizePragmaNumber (ref c);
+ bool identifier = false;
+ code = TokenizePragmaWarningIdentifier (ref c, ref identifier);
if (code > 0) {
- if (disable) {
+ if (identifier) {
+ // no-op, custom warnings cannot occur in mcs
+ } else if (disable) {
Report.RegisterWarningRegion (loc).WarningDisable (loc, code, context.Report);
} else {
Report.RegisterWarningRegion (loc).WarningEnable (loc, code, context);
public virtual string GetSignatureForError ()
{
- var bf = MemberDefinition as Property.BackingField;
+ var bf = MemberDefinition as Property.BackingFieldDeclaration;
string name;
if (bf == null) {
name = Name;
public override void PrepareEmit ()
{
+ if ((caching_flags & Flags.CloseTypeCreated) != 0)
+ return;
+
if (!Parameters.IsEmpty) {
parameters.ResolveDefaultValues (this);
}
{
return ns.LookupTypeOrNamespace (ctx, name, arity, mode, loc);
}
+
+ public override string ToString ()
+ {
+ return Namespace.Name;
+ }
}
/// <summary>
sealed class PropertyExpr : PropertyOrIndexerExpr<PropertySpec>
{
Arguments arguments;
+ FieldExpr backing_field;
public PropertyExpr (PropertySpec spec, Location l)
: base (l)
}
}
+ public bool IsAutoPropertyAccess {
+ get {
+ var prop = best_candidate.MemberDefinition as Property;
+ return prop != null && prop.BackingField != null;
+ }
+ }
+
public override bool IsInstance {
get {
return !IsStatic;
public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
{
+ if (backing_field != null) {
+ backing_field.EmitAssign (ec, source, false, false);
+ return;
+ }
+
Arguments args;
LocalTemporary await_source_arg = null;
public override void FlowAnalysis (FlowAnalysisContext fc)
{
+ var prop = best_candidate.MemberDefinition as Property;
+ if (prop != null && prop.BackingField != null) {
+ var var = InstanceExpression as IVariableReference;
+ if (var != null) {
+ var vi = var.VariableInfo;
+ if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, prop.BackingField.Name)) {
+ fc.Report.Error (8079, loc, "Use of possibly unassigned auto-implemented property `{0}'", Name);
+ return;
+ }
+
+ if (TypeSpec.IsValueType (InstanceExpression.Type) && InstanceExpression is VariableReference)
+ return;
+ }
+ }
+
base.FlowAnalysis (fc);
if (conditional_access_receiver)
return this;
}
+ protected override bool ResolveAutopropertyAssignment (ResolveContext rc, Expression rhs)
+ {
+ var prop = best_candidate.MemberDefinition as Property;
+ if (prop == null)
+ return false;
+
+ if (!rc.HasSet (ResolveContext.Options.ConstructorScope))
+ return false;
+
+ var spec = prop.BackingField;
+ if (spec == null)
+ return false;
+
+ if (rc.IsStatic != spec.IsStatic)
+ return false;
+
+ if (!spec.IsStatic && (!(InstanceExpression is This) || InstanceExpression is BaseThis))
+ return false;
+
+ backing_field = new FieldExpr (prop.BackingField, loc);
+ backing_field.ResolveLValue (rc, rhs);
+ return true;
+ }
+
+ public void SetBackingFieldAssigned (FlowAnalysisContext fc)
+ {
+ if (backing_field != null) {
+ backing_field.SetFieldAssigned (fc);
+ return;
+ }
+
+ if (!IsAutoPropertyAccess)
+ return;
+
+ var prop = best_candidate.MemberDefinition as Property;
+ if (prop != null && prop.BackingField != null) {
+ bool lvalue_instance = best_candidate.DeclaringType.IsStruct;
+ if (lvalue_instance) {
+ var var = InstanceExpression as IVariableReference;
+ if (var != null && var.VariableInfo != null) {
+ fc.SetStructFieldAssigned (var.VariableInfo, prop.BackingField.Name);
+ }
+ }
+ }
+ }
+
public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
{
Error_TypeArgumentsCannotBeUsed (ec, "property", GetSignatureForError (), loc);
return this;
}
- public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
+ public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
{
if (ConditionalAccess)
throw new NotSupportedException ("null propagating operator assignment");
if (right_side == EmptyExpression.OutAccess) {
// TODO: best_candidate can be null at this point
INamedBlockVariable variable = null;
- if (best_candidate != null && ec.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, ec.CurrentBlock, ref variable) && variable is Linq.RangeVariable) {
- ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
+ if (best_candidate != null && rc.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, rc.CurrentBlock, ref variable) && variable is Linq.RangeVariable) {
+ rc.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
best_candidate.Name);
} else {
- right_side.DoResolveLValue (ec, this);
+ right_side.DoResolveLValue (rc, this);
}
return null;
}
if (eclass == ExprClass.Unresolved) {
- var expr = OverloadResolve (ec, right_side);
+ var expr = OverloadResolve (rc, right_side);
if (expr == null)
return null;
if (expr != this)
- return expr.ResolveLValue (ec, right_side);
+ return expr.ResolveLValue (rc, right_side);
} else {
- ResolveInstanceExpression (ec, right_side);
+ ResolveInstanceExpression (rc, right_side);
}
- if (!ResolveSetter (ec))
+ if (!best_candidate.HasSet) {
+ if (ResolveAutopropertyAssignment (rc, right_side))
+ return this;
+
+ rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)",
+ GetSignatureForError ());
return null;
+ }
+
+ if (!best_candidate.Set.IsAccessible (rc) || !best_candidate.Set.DeclaringType.IsAccessible (rc)) {
+ if (best_candidate.HasDifferentAccessibility) {
+ rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
+ rc.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
+ GetSignatureForError ());
+ } else {
+ rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
+ ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc);
+ }
+ }
+ if (best_candidate.HasDifferentAccessibility)
+ CheckProtectedMemberAccess (rc, best_candidate.Set);
+
+ setter = CandidateToBaseOverride (rc, best_candidate.Set);
return this;
}
return true;
}
- bool ResolveSetter (ResolveContext rc)
+ protected virtual bool ResolveAutopropertyAssignment (ResolveContext rc, Expression rhs)
{
- if (!best_candidate.HasSet) {
- rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)",
- GetSignatureForError ());
- return false;
- }
-
- if (!best_candidate.Set.IsAccessible (rc) || !best_candidate.Set.DeclaringType.IsAccessible (rc)) {
- if (best_candidate.HasDifferentAccessibility) {
- rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
- rc.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
- GetSignatureForError ());
- } else {
- rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
- ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc);
- }
- }
-
- if (best_candidate.HasDifferentAccessibility)
- CheckProtectedMemberAccess (rc, best_candidate.Set);
-
- setter = CandidateToBaseOverride (rc, best_candidate.Set);
- return true;
+ return false;
}
}
public string GetUsing ()
{
+ if (source_file == null || source_file.Usings == null)
+ return string.Empty;
+
StringBuilder sb = new StringBuilder ();
// TODO:
//foreach (object x in ns.using_alias_list)
// sb.AppendFormat ("using {0};\n", x);
foreach (var ue in source_file.Usings) {
- sb.AppendFormat ("using {0};", ue.ToString ());
+ if (ue.Alias != null || ue.ResolvedExpression == null)
+ continue;
+
+ sb.AppendFormat("using {0};", ue.ToString ());
sb.Append (Environment.NewLine);
}
{
var res = new List<string> ();
- foreach (var ue in source_file.Usings) {
+ if (source_file == null || source_file.Usings == null)
+ return res;
+
+ foreach (var ue in source_file.Usings)
+ {
if (ue.Alias != null || ue.ResolvedExpression == null)
continue;
var field = struct_info.Fields[i];
if (!fc.IsStructFieldDefinitelyAssigned (vi, field.Name)) {
- var bf = field.MemberDefinition as Property.BackingField;
+ var bf = field.MemberDefinition as Property.BackingFieldDeclaration;
if (bf != null) {
if (bf.Initializer != null)
continue;
: base (compiler)
{
this.importer = importer;
- domain = new Universe (UniverseOptions.MetadataOnly | UniverseOptions.ResolveMissingMembers | UniverseOptions.DisableFusion);
+ domain = new Universe (UniverseOptions.MetadataOnly | UniverseOptions.ResolveMissingMembers | UniverseOptions.DisableFusion | UniverseOptions.DecodeVersionInfoAttributeBlobs);
domain.AssemblyResolve += AssemblyReferenceResolver;
loaded_names = new List<Tuple<AssemblyName, string, Assembly>> ();
candidates.AddRange (a);
}
- if (candidates != null)
- return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
- }
+ if (types_using_table != null) {
+ foreach (var t in types_using_table) {
- // LAMESPEC: TODO no spec about priority over normal extension methods yet
- if (types_using_table != null) {
- foreach (var t in types_using_table) {
-
- var res = t.MemberCache.FindExtensionMethods (invocationContext, name, arity);
- if (res == null)
- continue;
+ var res = t.MemberCache.FindExtensionMethods (invocationContext, name, arity);
+ if (res == null)
+ continue;
- if (candidates == null)
- candidates = res;
- else
- candidates.AddRange (res);
+ if (candidates == null)
+ candidates = res;
+ else
+ candidates.AddRange (res);
+ }
}
if (candidates != null)
public class Property : PropertyBase
{
- public sealed class BackingField : Field
+ public sealed class BackingFieldDeclaration : Field
{
readonly Property property;
const Modifiers DefaultModifiers = Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | Modifiers.DEBUGGER_HIDDEN;
- public BackingField (Property p, bool readOnly)
+ public BackingFieldDeclaration (Property p, bool readOnly)
: base (p.Parent, p.type_expr, DefaultModifiers | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
{
static readonly string[] attribute_target_auto = new string[] { "property", "field" };
- Field backing_field;
-
public Property (TypeDefinition parent, FullNamedExpression type, Modifiers mod,
MemberName name, Attributes attrs)
: base (parent, type, mod,
{
}
+ public BackingFieldDeclaration BackingField { get; private set; }
+
public Expression Initializer { get; set; }
public override void Accept (StructuralVisitor visitor)
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
if (a.Target == AttributeTargets.Field) {
- backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa);
+ BackingField.ApplyAttributeBuilder (a, ctor, cdata, pa);
return;
}
void CreateAutomaticProperty ()
{
// Create backing field
- backing_field = new BackingField (this, Initializer != null && Set == null);
- if (!backing_field.Define ())
+ BackingField = new BackingFieldDeclaration (this, Initializer == null && Set == null);
+ if (!BackingField.Define ())
return;
if (Initializer != null) {
- backing_field.Initializer = Initializer;
- Parent.RegisterFieldForInitialization (backing_field, new FieldInitializer (backing_field, Initializer, Location));
- backing_field.ModFlags |= Modifiers.READONLY;
+ BackingField.Initializer = Initializer;
+ Parent.RegisterFieldForInitialization (BackingField, new FieldInitializer (BackingField, Initializer, Location));
+ BackingField.ModFlags |= Modifiers.READONLY;
}
- Parent.PartialContainer.Members.Add (backing_field);
+ Parent.PartialContainer.Members.Add (BackingField);
- FieldExpr fe = new FieldExpr (backing_field, Location);
- if ((backing_field.ModFlags & Modifiers.STATIC) == 0)
+ FieldExpr fe = new FieldExpr (BackingField, Location);
+ if ((BackingField.ModFlags & Modifiers.STATIC) == 0)
fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
//
GetSignatureForError ());
if (IsInterface)
- Report.Error (8053, Location, "`{0}': Properties inside interfaces cannot have initializers",
+ Report.Error (8052, Location, "`{0}': Properties inside interfaces cannot have initializers",
GetSignatureForError ());
if (Compiler.Settings.Version < LanguageVersion.V_6)
if (auto) {
if (Get == null) {
- Report.Error (8052, Location, "Auto-implemented property `{0}' must have get accessor",
+ Report.Error (8051, Location, "Auto-implemented property `{0}' must have get accessor",
GetSignatureForError ());
return false;
}
- if (Initializer == null && AccessorSecond == null) {
- Report.Error (8051, Location, "Auto-implemented property `{0}' must have set accessor or initializer",
- GetSignatureForError ());
- }
-
if (Compiler.Settings.Version < LanguageVersion.V_3 && Initializer == null)
Report.FeatureIsNotAvailable (Compiler, Location, "auto-implemented properties");
--- /dev/null
+using System;
+using System.Reflection;
+
+public class Test
+{
+ public string Property1 { get; }
+
+ public int Property2 { get; }
+
+ public static int Main ()
+ {
+ var t = new Test ();
+ if (t.Property1 != null)
+ return 1;
+
+ if (t.Property2 != 0)
+ return 2;
+
+ var fields = typeof (Test).GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
+ if (fields.Length != 2)
+ return 3;
+
+ foreach (var fi in fields) {
+ if ((fi.Attributes & FieldAttributes.InitOnly) == 0)
+ return 4;
+ }
+
+ return 0;
+ }
+}
--- /dev/null
+using System;
+
+public class A
+{
+ public int X { get; }
+ public virtual int Y { get; }
+
+ public A ()
+ {
+ X = 4;
+ X++;
+
+ Y = 2;
+ Y++;
+ }
+}
+
+class B : A
+{
+ int i_get;
+
+ public override int Y { get { ++i_get; return base.Y; } }
+
+ public static int Main ()
+ {
+ var a = new A ();
+ if (a.X != 5)
+ return 1;
+
+ if (a.Y != 3)
+ return 2;
+
+ var b = new B ();
+ if (b.X != 5)
+ return 3;
+
+ if (b.i_get != 1)
+ return 4;
+
+ if (b.Y != 3)
+ return 5;
+
+ if (b.i_get != 2)
+ return 6;
+
+ return 0;
+ }
+}
--- /dev/null
+using System;
+
+public struct S
+{
+ public int X { get; }
+ public int Y { get; }
+
+ public S ()
+ {
+ X = 4;
+ Y = X;
+ }
+
+ public static int Main()
+ {
+ var s = new S ();
+ if (s.Y != 4)
+ return 1;
+
+ return 0;
+ }
+}
--- /dev/null
+public struct S
+{
+ public int A { get; set;}
+
+ public S (int a)
+ {
+ this.A = a;
+ }
+
+ public static void Main ()
+ {
+
+ }
+}
\ No newline at end of file
[assembly: AssemblyTrademark ("Trademark")]
[assembly: AssemblyVersion ("5.4.3.1")]
[assembly: AssemblyFileVersion ("8.9")]
+[assembly: AssemblyTitle ("Title")]
class C
{
if (fv.CompanyName != "Company")
return 2;
-// if (fv.Comments != "Description")
-// return 3;
+ if (fv.Comments != "Description")
+ return 3;
if (fv.LegalCopyright != "Copyright")
return 4;
if (fv.ProductVersion != "8.9")
return 6;
+ if (fv.FileDescription != "Title")
+ return 7;
+
return 0;
}
}
\ No newline at end of file
--- /dev/null
+// Compiler options: -warnaserror
+
+public class Test
+{
+#pragma warning disable public
+#pragma warning disable CS1685
+#pragma warning disable CS1700, 1701
+
+ public static void Main ()
+ {
+ }
+#pragma warning restore CS1685
+#pragma warning restore public, 1701
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+public struct S
+{
+ public int A { get; private set;}
+ public event EventHandler eh;
+
+ public S (int a)
+ {
+ this.eh = null;
+ A = a;
+ }
+
+ public static void Main ()
+ {
+ }
+}
</method>\r
</type>\r
</test>\r
+ <test name="gtest-autoproperty-11.cs">\r
+ <type name="Test">\r
+ <method name="System.String get_Property1()" attrs="2182">\r
+ <size>14</size>\r
+ </method>\r
+ <method name="Int32 get_Property2()" attrs="2182">\r
+ <size>14</size>\r
+ </method>\r
+ <method name="Int32 Main()" attrs="150">\r
+ <size>144</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="gtest-autoproperty-12.cs">\r
+ <type name="A">\r
+ <method name="Int32 get_X()" attrs="2182">\r
+ <size>14</size>\r
+ </method>\r
+ <method name="Int32 get_Y()" attrs="2502">\r
+ <size>14</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>50</size>\r
+ </method>\r
+ </type>\r
+ <type name="B">\r
+ <method name="Int32 get_Y()" attrs="2246">\r
+ <size>29</size>\r
+ </method>\r
+ <method name="Int32 Main()" attrs="150">\r
+ <size>136</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="gtest-autoproperty-13.cs">\r
+ <type name="S">\r
+ <method name="Int32 get_X()" attrs="2182">\r
+ <size>14</size>\r
+ </method>\r
+ <method name="Int32 get_Y()" attrs="2182">\r
+ <size>14</size>\r
+ </method>\r
+ <method name="Int32 Main()" attrs="150">\r
+ <size>37</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>21</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="gtest-autoproperty-14.cs">\r
+ <type name="S">\r
+ <method name="Int32 get_A()" attrs="2182">\r
+ <size>14</size>\r
+ </method>\r
+ <method name="Void set_A(Int32)" attrs="2182">\r
+ <size>8</size>\r
+ </method>\r
+ <method name="Void Main()" attrs="150">\r
+ <size>2</size>\r
+ </method>\r
+ <method name="Void .ctor(Int32)" attrs="6278">\r
+ <size>9</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
<test name="gtest-collectioninit-01.cs">\r
<type name="Test">\r
<method name="Void TestList(System.Collections.Generic.List`1[System.Int32], Int32)" attrs="145">\r
<test name="test-868.cs">\r
<type name="C">\r
<method name="Int32 Main()" attrs="150">\r
- <size>168</size>\r
+ <size>224</size>\r
</method>\r
<method name="Void .ctor()" attrs="6278">\r
<size>7</size>\r
</method>\r
</type>\r
</test>\r
+ <test name="test-908.cs">\r
+ <type name="Test">\r
+ <method name="Void Main()" attrs="150">\r
+ <size>2</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="test-909.cs">\r
+ <type name="S">\r
+ <method name="Int32 get_A()" attrs="2182">\r
+ <size>14</size>\r
+ </method>\r
+ <method name="Void set_A(Int32)" attrs="2177">\r
+ <size>8</size>\r
+ </method>\r
+ <method name="Void add_eh(System.EventHandler)" attrs="2182">\r
+ <size>42</size>\r
+ </method>\r
+ <method name="Void remove_eh(System.EventHandler)" attrs="2182">\r
+ <size>42</size>\r
+ </method>\r
+ <method name="Void Main()" attrs="150">\r
+ <size>2</size>\r
+ </method>\r
+ <method name="Void .ctor(Int32)" attrs="6278">\r
+ <size>16</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
<test name="test-91.cs">\r
<type name="Abstract">\r
<method name="Void .ctor()" attrs="6276">\r
get { return ignoreRemoved; }
}
+ public static bool IgnoreParameterNameChanges { get; set; }
+ public static bool IgnoreVirtualChanges { get; set; }
+ public static bool IgnoreAddedPropertySetters { get; set; }
+
public static bool Lax;
}
{ "n|ignore-new=", "Ignore new namespaces and types whose description matches a given C# regular expression (see below).",
v => State.IgnoreNew.Add (new Regex (v))
},
+ { "ignore-changes-parameter-names", "Ignore changes to parameter names for identically prototyped methods.",
+ v => State.IgnoreParameterNameChanges = v != null
+ },
+ { "ignore-changes-property-setters", "Ignore adding setters to properties.",
+ v => State.IgnoreAddedPropertySetters = v != null
+ },
+ { "ignore-changes-virtual", "Ignore changing non-`virtual` to `virtual` or adding `override`.",
+ v => State.IgnoreVirtualChanges = v != null
+ },
{ "x|lax", "Ignore duplicate XML entries", v => State.Lax = true }
};
if (parameters != null) {
var list = new List<string> ();
foreach (var p in parameters.Elements ("parameter")) {
- list.Add (p.GetTypeName ("type") + " " + p.GetAttribute ("name"));
+ var pTypeName = p.GetTypeName ("type");
+ list.Add (State.IgnoreParameterNameChanges
+ ? pTypeName
+ : pTypeName + " " + p.GetAttribute ("name"));
}
sb.Append (String.Join (", ", list));
}
if (base.Equals (source, target))
return true;
- return GetDescription (source) == GetDescription (target);
+ string sourceDescription = GetDescription (source);
+ string targetDescription = GetDescription (target);
+
+ return CheckVirtualChanges (sourceDescription, targetDescription) ||
+ (State.IgnoreAddedPropertySetters &&
+ CheckVirtualChanges (sourceDescription, targetDescription.Replace (" set; ", " ")));
+ }
+
+ static bool CheckVirtualChanges (string sourceDescription, string targetDescription)
+ {
+ return (sourceDescription == targetDescription) ||
+ // *adding* virtual or override to target is acceptable; *removing* them is NOT
+ (State.IgnoreVirtualChanges &&
+ // non-virtual to virtual is fine
+ (sourceDescription == targetDescription.Replace ("virtual ", "")) ||
+ // non-virtual to override is fine
+ (sourceDescription == targetDescription.Replace ("override ", "")) ||
+ // virtual to override is fine
+ (sourceDescription.Replace (" virtual ", " override ") == targetDescription));
}
bool IsNowObsoleted (XElement source, XElement target)
var sb = new StringBuilder ();
sb.Append (family ? "protected " : "public ");
- if (virt)
+ if (virt && !State.IgnoreVirtualChanges)
sb.Append (over ? "override " : "virtual ");
else if (stat)
sb.Append ("static ");
<typeparam name="T">To be added.</typeparam>
<param name="obj">The object on which to perform an action.</param>
<summary>
- <para> Represents the method that performs an action on the specified object.</para>
- </summary>
+ <para> Represents the method that performs an action on the specified object.</para>
+ </summary>
<remarks>
- <block subset="none" type="note">
- <para>This delegate is used by the method <see cref="M:System.Array.ForEach" /><see langword="(T[], Action<T>)" />, and in <see cref="T:System.Collections.Generic.List<T>" /> to perform an action on each element of the collection.</para>
- </block>
- </remarks>
+ <block subset="none" type="note">
+ <para>This delegate is used by the method <see cref="M:System.Array.ForEach" />
+ <see langword="(T[], Action<T>)" />, and in <see cref="T:System.Collections.Generic.List<T>" /> to perform an action on each element of the collection.</para>
+ </block>
+ </remarks>
</Docs>
</Type>
<Interfaces />
<Docs>
<summary>
- <para> Serves as the base class for arrays. Provides methods for creating,
+ <para> Serves as the base class for arrays. Provides methods for creating,
copying, manipulating, searching, and sorting arrays.</para>
- </summary>
+ </summary>
<remarks>
- <para>This class is intended to be used as a base class by
+ <para>This class is intended to be used as a base class by
language implementations that support arrays. Only the system can derive from
this type: derived classes of <see cref="T:System.Array" /> are not to be created by the developer.</para>
- <block subset="none" type="note">
- <para>An array is a collection of
+ <block subset="none" type="note">
+ <para>An array is a collection of
identically typed data <paramref name="elements" /> that are accessed and referenced by
sets of integral <paramref name="indices" />. </para>
- <para>The <paramref name="rank" /> of an array is the number
+ <para>The <paramref name="rank" /> of an array is the number
of dimensions in the array. Each dimension has its own set of indices. An array
with a rank greater than one can have a different lower
bound and a different number of elements for each dimension. Multidimensional
arrays (i.e. arrays with a rank greater than one) are processed in row-major
order. </para>
- <para>The <paramref name="lower bound" /> of a dimension
+ <para>The <paramref name="lower bound" /> of a dimension
is the starting index of that dimension. </para>
- <para>The <paramref name="length" /> of an array is the total number of elements contained in all of its
+ <para>The <paramref name="length" /> of an array is the total number of elements contained in all of its
dimensions. </para>
- <para>A <paramref name="vector" /> is a
+ <para>A <paramref name="vector" /> is a
one-dimensional array with a <paramref name="lower bound" /> of '0'. </para>
- <para>If the implementer creates a derived class of <see cref="T:System.Array" />, expected <see cref="T:System.Array" /> behavior
+ <para>If the implementer creates a derived class of <see cref="T:System.Array" />, expected <see cref="T:System.Array" /> behavior
cannot be guaranteed. For information on array-like objects with increased
functionality, see the <see cref="T:System.Collections.IList" /> and <see cref="T:System.Collections.Generic.IList<T>" /> interfaces. For more information regarding the use of arrays versus the use
of collections, see Partition V of the CLI Specification. </para>
- </block>
- <para>Every specific <see cref="T:System.Array" /> type has three instance methods defined on it.
+ </block>
+ <para>Every specific <see cref="T:System.Array" /> type has three instance methods defined on it.
While some programming languages allow direct access to these methods, they are
primarily intended to be called by the output of compilers based on language
syntax that deals with arrays. </para>
- <list type="bullet">
- <item>
- <term>
- <para>
- <c>Get</c>: Takes as many <see cref="T:System.Int32" /> arguments as the array
+ <list type="bullet">
+ <item>
+ <term>
+ <para>
+ <c>Get</c>: Takes as many <see cref="T:System.Int32" /> arguments as the array
has dimensions and returns the value stored at the given index. It throws a
<see cref="T:System.IndexOutOfRangeException" />
exception for invalid indices. </para>
- </term>
- </item>
- <item>
- <term>
- <para>
- <c>Set</c>: Takes as many <see cref="T:System.Int32" /> arguments as the array
+ </term>
+ </item>
+ <item>
+ <term>
+ <para>
+ <c>Set</c>: Takes as many <see cref="T:System.Int32" /> arguments as the array
has dimensions, plus one additional argument (the last argument) which has the
same type as an array element. It stores the final value in the specified
index of the array. It throws a <see cref="T:System.IndexOutOfRangeException" />
exception for invalid indices. </para>
- </term>
- </item>
- <item>
- <term>
- <para>
- <c>Address</c>: Takes as many <see cref="T:System.Int32" /> arguments as the
+ </term>
+ </item>
+ <item>
+ <term>
+ <para>
+ <c>Address</c>: Takes as many <see cref="T:System.Int32" /> arguments as the
array has dimensions and returns the address of the element at the given index.
It throws a <see cref="T:System.IndexOutOfRangeException" />
exception for invalid indices. </para>
- </term>
- </item>
- </list>
- <para>In addition, every specific <see cref="T:System.Array" /> type has a constructor on it that takes as many non-negative
+ </term>
+ </item>
+ </list>
+ <para>In addition, every specific <see cref="T:System.Array" /> type has a constructor on it that takes as many non-negative
<see cref="T:System.Int32" />
arguments as the array has dimensions. The arguments specify the
number of elements in each dimension, and a lower bound of 0. Thus, a
two-dimensional array of <see cref="T:System.Int32" /> objects would have a constructor that could be called with
<c>(2, 4)</c> as its arguments to create an array of eight zeros with the first dimension indexed
with 0 and 1 and the second dimension indexed with 0, 1, 2, and 3. </para>
- <para>For all specific array types except vectors (i.e. those
+ <para>For all specific array types except vectors (i.e. those
permitted to have non-zero lower bounds and those with more than one dimension)
there is an additional constructor. It takes twice as many arguments as the
array has dimensions. The arguments are considered in pairs, with the first of
objects would also have a constructor that could be called with <c>(-1, 2, 1, 3)</c> as its arguments,
specifying an array of 6 zeros, with the first dimension indexed by -1 and 0,
and the second dimension indexed by 1, 2, and 3. </para>
- <para>Enumeration over an array occurs in ascending row-major order, starting from the first element. (For example, a 2x3 array is traversed in the order [0,0], [0,1], [0,2], [1,0], [1,1], and [1,2].)</para>
- <para>Parallel implementation of methods taking a <see cref="T:System.Predicate" /> argument are not permitted.</para>
- </remarks>
+ <para>Enumeration over an array occurs in ascending row-major order, starting from the first element. (For example, a 2x3 array is traversed in the order [0,0], [0,1], [0,2], [1,0], [1,1], and [1,2].)</para>
+ <para>Parallel implementation of methods taking a <see cref="T:System.Predicate" /> argument are not permitted.</para>
+ </remarks>
</Docs>
<Members>
<Member MemberName=".ctor">
<typeparam name="TOutput">To be added.</typeparam>
<param name="array">The one-dimensional array to convert.</param>
<param name="converter">
- <para>A <see cref="T:System.Converter<T,U>" /> that converts each element from one type to another type.</para>
- </param>
+ <para>A <see cref="T:System.Converter<T,U>" /> that converts each element from one type to another type.</para>
+ </param>
<summary>
- <para>Converts an array of one type to an array of another type.</para>
- </summary>
+ <para>Converts an array of one type to an array of another type.</para>
+ </summary>
<returns>
- <para>A new array of the target type containing the converted elements from <paramref name="array" />.</para>
- </returns>
+ <para>A new array of the target type containing the converted elements from <paramref name="array" />.</para>
+ </returns>
<remarks>
- <para>The <see cref="T:System.Converter<T,U>" /> is a delegate that converts an array element to the target type. The elements of <paramref name="array" /> are individually passed to this converter, and the converted elements are saved in the new array. The source array remains unchanged.</para>
- </remarks>
+ <para>The <see cref="T:System.Converter<T,U>" /> is a delegate that converts an array element to the target type. The elements of <paramref name="array" /> are individually passed to this converter, and the converted elements are saved in the new array. The source array remains unchanged.</para>
+ </remarks>
<exception cref="T:System.InvalidOperationException">To be added; from:
<see cref="M:System.Array.ConvertAll``2(``0[],System.Converter{``0,``1})" /></exception>
<exception cref="T:System.ArgumentNullException">
- <paramref name="array" /> is <see langword="null" /> or <paramref name="converter" /> is <see langword="null" />.</exception>
+ <paramref name="array" /> is <see langword="null" /> or <paramref name="converter" /> is <see langword="null" />.</exception>
</Docs>
</Member>
<Member MemberName="Resize<T>">
<Docs>
<param name="ar">A <see cref="T:System.IAsyncResult" /> object containing information about the asynchronous operation that has completed.</param>
<summary>
- <para> References one or more methods called when an asynchronous operation completes.</para>
- </summary>
+ <para> References one or more methods called when an asynchronous operation completes.</para>
+ </summary>
<remarks>To be added.</remarks>
</Docs>
</Type>
<Interfaces />
<Docs>
<summary>
- <para> Provides the current settings for, and information about, the execution environment.</para>
- </summary>
+ <para> Provides the current settings for, and information about, the execution environment.</para>
+ </summary>
<remarks>
- <block subset="none" type="note">
- <para>Use this class to retrieve the following
+ <block subset="none" type="note">
+ <para>Use this class to retrieve the following
information:</para>
- <list type="bullet">
- <item>
- <term>Command line arguments</term>
- </item>
- <item>
- <term>Exit codes</term>
- </item>
- <item>
- <term>Environment variable settings</term>
- </item>
- <item>
- <term>Contents of the call stack</term>
- </item>
- <item>
- <term>Time since last system boot</term>
- </item>
- <item>
- <term>Version of the execution engine</term>
- </item>
- </list>
- </block>
- </remarks>
+ <list type="bullet">
+ <item>
+ <term>Command line arguments</term>
+ </item>
+ <item>
+ <term>Exit codes</term>
+ </item>
+ <item>
+ <term>Environment variable settings</term>
+ </item>
+ <item>
+ <term>Contents of the call stack</term>
+ </item>
+ <item>
+ <term>Time since last system boot</term>
+ </item>
+ <item>
+ <term>Version of the execution engine</term>
+ </item>
+ </list>
+ </block>
+ </remarks>
</Docs>
<Members>
<Member MemberName="GetFolderPath">
</Parameters>
<Docs>
<param name="folder">
- <para>A <see cref="T:System.Environment+SpecialFolder" />.</para>
- </param>
+ <para>A <see cref="T:System.Environment+SpecialFolder" />.</para>
+ </param>
<summary>
- <para> Returns the arguments specified on the command
+ <para> Returns the arguments specified on the command
line.</para>
- </summary>
+ </summary>
<returns>
- <para> Returns a <see cref="T:System.String" /> array. Each <see cref="T:System.String" /> in the array
+ <para> Returns a <see cref="T:System.String" /> array. Each <see cref="T:System.String" /> in the array
contains a single command line argument.</para>
- </returns>
+ </returns>
<remarks>
- <para>The first element in the array contains the filename of
+ <para>The first element in the array contains the filename of
the executing program. If the filename is not available, the first element is
equal to <see cref="F:System.String.Empty" />. The remaining elements contain any additional tokens
entered on the command line.</para>
- <block subset="none" type="note">
- <para>The program filename can, but is not required to,
+ <block subset="none" type="note">
+ <para>The program filename can, but is not required to,
include path information.</para>
- <para>To obtain the command line as a single <see cref="T:System.String" />, use the <see cref="P:System.Environment.CommandLine" />
+ <para>To obtain the command line as a single <see cref="T:System.String" />, use the <see cref="P:System.Environment.CommandLine" />
property.</para>
- </block>
- </remarks>
+ </block>
+ </remarks>
<exception cref="T:System.NotSupportedException">To be added; from:
<see cref="M:System.Environment.GetFolderPath(System.Environment.SpecialFolder)" /></exception>
<exception cref="T:System.ArgumentException">foo</exception>
data/3.5/Microsoft.Common.tasks \
data/4.0/Microsoft.Common.tasks \
data/12.0/Microsoft.Common.tasks \
+ data/14.0/Microsoft.Common.tasks \
data/2.0/Microsoft.Common.targets \
data/3.5/Microsoft.Common.targets \
data/4.0/Microsoft.Common.targets \
data/12.0/Microsoft.Common.targets \
+ data/14.0/Microsoft.Common.targets \
data/2.0/Microsoft.CSharp.targets \
data/3.5/Microsoft.CSharp.targets \
data/4.0/Microsoft.CSharp.targets \
data/12.0/Microsoft.CSharp.targets \
+ data/14.0/Microsoft.CSharp.targets \
data/Microsoft.VisualBasic.targets \
data/MSBuild/Microsoft.Build.CommonTypes.xsd \
data/MSBuild/Microsoft.Build.Core.xsd \
string slnVersion = GetSlnFileVersion (reader);
if (slnVersion == "12.00")
-#if XBUILD_12
+#if XBUILD_14
+ p.DefaultToolsVersion = "14.0";
+#elif XBUILD_12
p.DefaultToolsVersion = "12.0";
#else
p.DefaultToolsVersion = "4.0";
-class XBuildConsts
+static class XBuildConsts
{
-#if XBUILD_12
+#if XBUILD_14
+ public const string Version = "14.0";
+ public const string AssemblyVersion = "14.0.0.0";
+ public const string FileVersion = "14.0.22310.1";
+#elif XBUILD_12
public const string Version = "12.0";
public const string AssemblyVersion = "12.0.0.0";
public const string FileVersion = "12.0.21005.1";
--- /dev/null
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <DefaultLanguageSourceExtension>.cs</DefaultLanguageSourceExtension>
+ <Language>C#</Language>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <DebugSymbols Condition=" '$(DebugType)' == 'none' ">false</DebugSymbols>
+ <DebugType Condition=" '$(DebugType)' == 'none' "></DebugType>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <CreateManifestResourceNamesDependsOn></CreateManifestResourceNamesDependsOn>
+ <CoreCompileDependsOn></CoreCompileDependsOn>
+
+ <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildToolsPath)\Microsoft.CSharp.targets</MSBuildAllProjects>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <NoCompilerStandardLib Condition="'$(NoCompilerStandardLib)'==''">true</NoCompilerStandardLib>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <DocFileItem Include="$(DocumentationFile)" Condition="'$(DocumentationFile)' != ''"/>
+ </ItemGroup>
+
+ <Target Name="_AddCorlibReference" DependsOnTargets="GetReferenceAssemblyPaths">
+ <!--
+ HACK: We don't yet support property functions, so can't calculate FrameworkPathOverride
+ by calling ToolLocationHelper.GetPathToStandardLibraries. Instead, we search the framework
+ directories for mscorlib.dll by constructing a filtered item set, and assume it only has
+ one item.
+ -->
+ <ItemGroup Condition="'$(MonoUseMicrosoftBuildDll)' != 'True'">
+ <_ExplicitReference Include="@(_TargetFrameworkDirectories->'%(FullPath)\mscorlib.dll')" Condition="Exists('%(FullPath)\mscorlib.dll')">
+ <Private>false</Private>
+ </_ExplicitReference>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(MonoUseMicrosoftBuildDll)' == 'True'">
+ <_ExplicitMSCorlibPath>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToStandardLibraries ('$(TargetFrameworkIdentifier)', '$(TargetFrameworkVersion)', '$(TargetFrameworkProfile)'))\mscorlib.dll</_ExplicitMSCorlibPath>
+ </PropertyGroup>
+ <ItemGroup Condition="'$(MonoUseMicrosoftBuildDll)' == 'True'">
+ <_ExplicitReference Include="@(_TargetFrameworkDirectories->'%(FullPath)\mscorlib.dll')" Condition="Exists('%(FullPath)\mscorlib.dll')">
+ <Private>false</Private>
+ </_ExplicitReference>
+ </ItemGroup>
+ <ItemGroup Condition="'$(MonoUseMicrosoftBuildDll)' == 'True'">
+ <_ExplicitReference Include="$(_ExplicitMSCorlibPath)" Condition="Exists('$(_ExplicitMSCorlibPath)')">
+ <Private>false</Private>
+ </_ExplicitReference>
+ </ItemGroup>
+ </Target>
+
+ <Target
+ Name="CoreCompile"
+ Inputs="$(MSBuildAllProjects);@(Compile);@(ManifestResourceWithNoCulture);@(ManifestNonResxWithNoCultureOnDisk);@(CompiledLicenseFile);
+ $(KeyOriginatorFile);@(ReferencePath);$(Win32Icon);$(Win32Resource)"
+ Outputs="@(DocFileItem);@(IntermediateAssembly)"
+ DependsOnTargets="$(CoreCompileDependsOn)"
+ >
+ <Csc
+ AdditionalLibPaths="$(AdditionalLibPaths)"
+ AddModules="@(AddModules)"
+ AllowUnsafeBlocks="$(AllowUnsafeBlocks)"
+ BaseAddress="$(BaseAddress)"
+ CheckForOverflowUnderflow="$(CheckForOverflowUnderflow)"
+ CodePage="$(CodePage)"
+ DebugType="$(DebugType)"
+ DefineConstants="$(DefineConstants)"
+ DelaySign="$(DelaySign)"
+ DisabledWarnings="$(NoWarn)"
+ DocumentationFile="@(DocFileItem)"
+ EmitDebugInformation="$(DebugSymbols)"
+ ErrorReport="$(ErrorReport)"
+ FileAlignment="$(FileAlignment)"
+ GenerateFullPaths="$(GenerateFullPaths)"
+ KeyContainer="$(KeyContainerName)"
+ KeyFile="$(KeyOriginatorFile)"
+ LangVersion="$(LangVersion)"
+ MainEntryPoint="$(StartupObject)"
+ ModuleAssemblyName="$(ModuleAssemblyName)"
+ NoConfig="true"
+ NoLogo="$(NoLogo)"
+ NoStandardLib="$(NoCompilerStandardLib)"
+ Optimize="$(Optimize)"
+ OutputAssembly="@(IntermediateAssembly)"
+ PdbFile="$(PdbFile)"
+ Platform="$(PlatformTarget)"
+ References="@(ReferencePath)"
+ ResponseFiles="$(CompilerResponseFile)"
+ Sources="@(Compile)"
+ TargetType="$(OutputType)"
+ TreatWarningsAsErrors="$(TreatWarningsAsErrors)"
+ UseHostCompilerIfAvailable="$(UseHostCompilerIfAvailable)"
+ Utf8Output="$(Utf8Output)"
+ WarningLevel="$(WarningLevel)"
+ WarningsAsErrors="$(WarningsAsErrors)"
+ WarningsNotAsErrors="$(WarningsNotAsErrors)"
+ Win32Icon="$(Win32Icon)"
+ Win32Resource="$(Win32Resource)"
+ Resources="@(ManifestResourceWithNoCulture);@(ManifestNonResxWithNoCultureOnDisk);@(CompiledLicenseFile)"
+ ToolExe="$(CscToolExe)"
+ ToolPath="$(CscToolPath)" />
+
+ </Target>
+
+ <Target Name="CreateManifestResourceNames">
+ <CreateCSharpManifestResourceName Condition="'@(ResxWithNoCulture)' != ''"
+ ResourceFiles="@(ResxWithNoCulture)" RootNamespace="$(RootNamespace)">
+ <Output TaskParameter = "ManifestResourceNames" ItemName = "ManifestResourceWithNoCultureName" />
+ </CreateCSharpManifestResourceName>
+
+ <CreateCSharpManifestResourceName Condition="'@(NonResxWithNoCulture)' != ''"
+ ResourceFiles="@(NonResxWithNoCulture)" RootNamespace="$(RootNamespace)">
+ <Output TaskParameter = "ManifestResourceNames" ItemName = "ManifestNonResxWithNoCulture" />
+ </CreateCSharpManifestResourceName>
+
+ <CreateCSharpManifestResourceName Condition="'@(ResxWithCulture)' != ''"
+ ResourceFiles="@(ResxWithCulture)" RootNamespace="$(RootNamespace)">
+ <Output TaskParameter = "ManifestResourceNames" ItemName = "ManifestResourceWithCultureName" />
+ </CreateCSharpManifestResourceName>
+
+ <CreateCSharpManifestResourceName Condition="'@(NonResxWithCulture)' != ''"
+ ResourceFiles="@(NonResxWithCulture)" RootNamespace="$(RootNamespace)">
+ <Output TaskParameter = "ManifestResourceNames" ItemName = "ManifestNonResxWithCulture" />
+ </CreateCSharpManifestResourceName>
+ </Target>
+
+ <Import Project="Microsoft.Common.targets" />
+
+ <PropertyGroup Condition="'$(NoCompilerStandardLib)'=='true' and '$(NoStdLib)'!='true'">
+ <ResolveAssemblyReferencesDependsOn>$(ResolveAssemblyReferencesDependsOn);_AddCorlibReference</ResolveAssemblyReferencesDependsOn>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <TargetFrameworkMonikerAssemblyAttributeText Condition="'$(TargetFrameworkMoniker)' != '' and '$(TargetingClr2Framework)' != 'true'">
+// <autogenerated />
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute("$(TargetFrameworkMoniker)", FrameworkDisplayName = "$(TargetFrameworkMonikerDisplayName)")]
+ </TargetFrameworkMonikerAssemblyAttributeText>
+ </PropertyGroup>
+
+</Project>
--- /dev/null
+<Project DefaultTargets="Build" InitialTargets="_ValidateEssentialProperties" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <ImportByWildcardBeforeMicrosoftCommonTargets Condition="'$(ImportByWildcardBeforeMicrosoftCommonTargets)' == ''">true</ImportByWildcardBeforeMicrosoftCommonTargets>
+ <ImportByWildcardAfterMicrosoftCommonTargets Condition="'$(ImportByWildcardAfterMicrosoftCommonTargets)' == ''">true</ImportByWildcardAfterMicrosoftCommonTargets>
+ </PropertyGroup>
+
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\$(MSBuildThisFile)\ImportBefore\*"
+ Condition="'$(ImportByWildcardBeforeMicrosoftCommonTargets)' == 'true' and Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\$(MSBuildThisFile)\ImportBefore')"/>
+
+ <Import Project="$(MSBuildProjectFullPath).user" Condition="Exists('$(MSBuildProjectFullPath).user')"/>
+
+ <PropertyGroup>
+ <OutputType Condition="'$(OutputType)' == ''">Exe</OutputType>
+ <TargetExt Condition="'$(OutputType)' == 'Winexe'">.exe</TargetExt>
+ <TargetExt Condition="'$(OutputType)' == 'Exe'">.exe</TargetExt>
+ <TargetExt Condition="'$(OutputType)' == 'Library'">.dll</TargetExt>
+ <TargetExt Condition="'$(OutputType)' == 'Netmodule'">.netmodule</TargetExt>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <ProjectDir Condition="'$(ProjectDir)' == ''">$(MSBuildProjectDirectory)\</ProjectDir>
+ </PropertyGroup>
+
+ <!-- MSBuild defines this even outside of VS, and F# projects depend on it -->
+ <PropertyGroup>
+ <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <AssemblyName Condition="'$(AssemblyName)' == ''">$(MSBuildProjectName)</AssemblyName>
+ <OutputPath Condition="'$(OutputPath)' != '' and !HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
+ <OutputPath Condition=" '$(Platform)'=='' and '$(Configuration)'=='' and '$(OutputPath)'=='' ">bin\Debug\</OutputPath>
+ <WarningLevel Condition="'$(WarningLevel)' == ''" >2</WarningLevel>
+
+ <TargetFrameworkIdentifier Condition="'$(TargetFrameworkIdentifier)' == ''">.NETFramework</TargetFrameworkIdentifier>
+ <TargetFrameworkVersion Condition="'$(TargetFrameworkVersion)' == ''">v4.0</TargetFrameworkVersion>
+
+ <TargetFrameworkMoniker Condition="'$(TargetFrameworkMoniker)' == '' and '$(TargetFrameworkProfile)' != ''">$(TargetFrameworkIdentifier),Version=$(TargetFrameworkVersion),Profile=$(TargetFrameworkProfile)</TargetFrameworkMoniker>
+ <TargetFrameworkMoniker Condition="'$(TargetFrameworkMoniker)' == ''">$(TargetFrameworkIdentifier),Version=$(TargetFrameworkVersion)</TargetFrameworkMoniker>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <OutDir Condition="'$(OutDir)' == ''">$(OutputPath)</OutDir>
+ <OutDir Condition="'$(OutDir)' != '' and !HasTrailingSlash('$(OutDir)')">$(OutDir)\</OutDir>
+
+ <_OriginalConfiguration>$(Configuration)</_OriginalConfiguration>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <ConfigurationName Condition="'$(ConfigurationName)' == ''">$(Configuration)</ConfigurationName>
+
+ <_OriginalPlatform>$(Platform)</_OriginalPlatform>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <PlatformName Condition="'$(PlatformName)' == ''">$(Platform)</PlatformName>
+
+ <AddAdditionalExplicitAssemblyReferences Condition="'$(AddAdditionalExplicitAssemblyReferences)' == ''">true</AddAdditionalExplicitAssemblyReferences>
+ <AdditionalExplicitAssemblyReferences Condition="'$(AddAdditionalExplicitAssemblyReferences)' == 'true' and '$(TargetFrameworkVersion)' != 'v2.0' and '$(TargetFrameworkVersion)' != 'v3.0'">System.Core;$(AdditionalExplicitAssemblyReferences)</AdditionalExplicitAssemblyReferences>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <SkipCopyUnchangedFiles Condition="'$(SkipCopyUnchangedFiles)' == ''">true</SkipCopyUnchangedFiles>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)' == ''">obj\</BaseIntermediateOutputPath>
+ <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)' != '' and !HasTrailingSlash('$(BaseIntermediateOutputPath)')">$(BaseIntermediateOutputPath)\</BaseIntermediateOutputPath>
+ <CleanFile Condition="'$(CleanFile)'==''">$(MSBuildProjectFile).FilesWrittenAbsolute.txt</CleanFile>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(IntermediateOutputPath)' == ''">
+ <IntermediateOutputPath Condition=" '$(PlatformName)' == 'AnyCPU'">$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
+ <IntermediateOutputPath Condition=" '$(PlatformName)' != 'AnyCPU'">$(BaseIntermediateOutputPath)$(PlatformName)\$(Configuration)\</IntermediateOutputPath>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <IntermediateOutputPath Condition="'$(IntermediateOutputPath)' != '' and !HasTrailingSlash('$(IntermediateOutputPath)')">$(IntermediateOutputPath)\</IntermediateOutputPath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <IntermediateAssembly Include="$(IntermediateOutputPath)$(AssemblyName)$(TargetExt)" />
+
+ <!-- creating this as a item to use FullPath on it, to build TargetPath -->
+ <_OutDirItem Include="$(OutDir)"/>
+ </ItemGroup>
+
+ <PropertyGroup>
+ <TargetName Condition="'$(TargetName)' == '' ">$(AssemblyName)</TargetName>
+ <TargetFileName Condition="'$(TargetFileName)' == '' ">$(TargetName)$(TargetExt)</TargetFileName>
+ <TargetDir Condition=" '$(TargetDir)' == '' ">@(_OutDirItem->'%(FullPath)')</TargetDir>
+ <TargetPath Condition=" '$(TargetPath)' == '' ">@(_OutDirItem->'%(FullPath)\$(TargetFileName)')</TargetPath>
+ <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildProjectFullPath);$(MSBuildToolsPath)\Microsoft.Common.targets</MSBuildAllProjects>
+ <KeyOriginatorFile Condition=" '$(SignAssembly)' == 'true' ">$(AssemblyOriginatorKeyFile)</KeyOriginatorFile>
+ <TargetingClr2Framework Condition="('$(TargetFrameworkIdentifier)' == '.NETFramework') and ('$(TargetFrameworkVersion)' == 'v2.0' or '$(TargetFrameworkVersion)' == 'v3.0' or '$(TargetFrameworkVersion)' == 'v3.5')">true</TargetingClr2Framework>
+ </PropertyGroup>
+
+ <Target Name="_ValidateEssentialProperties">
+ <Error Condition=" '$(OutputPath)' == '' and '$(SkipInvalidConfigurations)' != 'true'"
+ Text="'OutputPath' property is not set for this project. Usually this is caused by invalid Configuration/Platform combination. Original values: Configuration: $(_OriginalConfiguration) Platform: $(_OriginalPlatform)."/>
+
+ <Warning Condition=" '$(OutputPath)' == '' and '$(SkipInvalidConfigurations)' == 'true'"
+ Text="'OutputPath' property is not set for this project. Usually this is caused by invalid Configuration/Platform combination. Original values: Configuration: $(_OriginalConfiguration) Platform: $(_OriginalPlatform)."/>
+
+ <!-- If OutDir is specified via the command line, then the earlier check
+ to add a trailing slash won't have any affect, so error here. -->
+ <Error
+ Condition="'$(OutDir)' != '' and !HasTrailingSlash('$(OutDir)')"
+ Text="OutDir property must end with a slash."/>
+ </Target>
+
+ <Target Name="PrepareForBuild">
+ <Message Importance="High" Text="Configuration: $(Configuration) Platform: $(Platform)"/>
+
+ <!-- Look for app.config, if $(AppConfig) is specified, then use that. Else look in
+ @(None) and @(Content) -->
+ <CreateItem Include="$(AppConfig)" Condition="'$(AppConfig)' != ''"
+ AdditionalMetadata="TargetPath=$(TargetFileName).config">
+ <Output TaskParameter="Include" ItemName="AppConfigWithTargetPath" />
+ </CreateItem>
+
+ <FindAppConfigFile PrimaryList="@(None)" SecondaryList="@(Content)" TargetPath="$(TargetFileName).config"
+ Condition="'$(AppConfig)' == ''">
+ <Output TaskParameter="AppConfigFile" ItemName="AppConfigWithTargetPath"/>
+ </FindAppConfigFile>
+
+ <MakeDir
+ Directories="$(OutDir);$(IntermediateOutputPath);@(DocFileItem->'%(RelativeDir)')"
+ />
+ </Target>
+
+ <PropertyGroup>
+ <GetFrameworkPathsDependsOn />
+ </PropertyGroup>
+ <Target Name="GetFrameworkPaths"
+ Condition="'$(TargetFrameworkIdentifier)' == '' or '$(TargetFrameworkIdentifier)' == '.NETFramework'"
+ DependsOnTargets="$(GetFrameworkPathsDependsOn)">
+ <GetFrameworkPath>
+ <Output Condition="'$(TargetFrameworkVersion)' == 'v4.5' and '$(TargetFrameworkVersion)' == 'v4.5.1'"
+ TaskParameter="FrameworkVersion45Path"
+ ItemName="_CombinedTargetFrameworkDirectoriesItem"/>
+ <Output Condition="'$(TargetFrameworkVersion)' == 'v4.0'"
+ TaskParameter="FrameworkVersion40Path"
+ ItemName="_CombinedTargetFrameworkDirectoriesItem"/>
+ <Output Condition="'$(TargetFrameworkVersion)' == 'v3.5'"
+ TaskParameter="FrameworkVersion35Path"
+ ItemName="_CombinedTargetFrameworkDirectoriesItem"/>
+ <Output Condition="'$(TargetFrameworkVersion)' == 'v3.0' or '$(TargetFrameworkVersion)' == 'v3.5'"
+ TaskParameter="FrameworkVersion30Path"
+ ItemName="_CombinedTargetFrameworkDirectoriesItem"/>
+ <Output Condition="'$(TargetFrameworkVersion)' == 'v2.0' or '$(TargetFrameworkVersion)' == 'v3.0' or '$(TargetFrameworkVersion)' == 'v3.5'"
+ TaskParameter="FrameworkVersion20Path"
+ ItemName="_CombinedTargetFrameworkDirectoriesItem"/>
+ </GetFrameworkPath>
+ <CreateProperty Value="@(_CombinedTargetFrameworkDirectoriesItem)">
+ <Output TaskParameter="Value" PropertyName="TargetFrameworkDirectory"/>
+ </CreateProperty>
+
+ <Warning Text="TargetFrameworkVersion '$(TargetFrameworkVersion)' not supported by this toolset (ToolsVersion: $(MSBuildToolsVersion))."
+ Condition="'$(TargetFrameworkVersion)' != 'v4.5.1' and '$(TargetFrameworkVersion)' != 'v4.5' and '$(TargetFrameworkVersion)' != 'v4.0' and '$(TargetFrameworkVersion)' != 'v3.5' and '$(TargetFrameworkVersion)' != 'v3.0' and '$(TargetFrameworkVersion)' != 'v2.0'"/>
+ </Target>
+
+ <PropertyGroup>
+ <GetReferenceAssemblyPathsDependsOn />
+ </PropertyGroup>
+ <Target Name="GetReferenceAssemblyPaths" DependsOnTargets="$(GetReferenceAssemblyPathsDependsOn)">
+ <!-- in case of .NETFramework, $(TargetFrameworkDirectory) would have been set by
+ GetFrameworkPaths, if it hasn't been changed, then clear it, to avoid duplicates -->
+ <CreateProperty Value="" Condition="'@(_CombinedTargetFrameworkDirectoriesItem)' == '$(TargetFrameworkDirectory)'">
+ <Output TaskParameter="Value" PropertyName="TargetFrameworkDirectory"/>
+ </CreateProperty>
+
+ <GetReferenceAssemblyPaths
+ Condition="'$(TargetFrameworkMoniker)' != '' and '$(_TargetFrameworkDirectories)' == ''"
+ TargetFrameworkMoniker="$(TargetFrameworkMoniker)"
+ RootPath="$(TargetFrameworkRootPath)">
+
+ <Output TaskParameter="ReferenceAssemblyPaths" PropertyName="_TargetFrameworkDirectories"/>
+ <Output TaskParameter="FullFrameworkReferenceAssemblyPaths" PropertyName="_FullFrameworkReferenceAssemblyPaths"/>
+ <Output TaskParameter="TargetFrameworkMonikerDisplayName" PropertyName="TargetFrameworkMonikerDisplayName"/>
+ </GetReferenceAssemblyPaths>
+
+
+ <!-- Remove duplicates. -->
+ <ItemGroup>
+ <_TargetFrameworkDirectories Include="$(_TargetFrameworkDirectories);$(TargetFrameworkDirectory)" KeepDuplicates="false" />
+ </ItemGroup>
+ <PropertyGroup>
+ <TargetFrameworkDirectory>@(_TargetFrameworkDirectories)</TargetFrameworkDirectory>
+ </PropertyGroup>
+
+ <ItemGroup Condition="'$(ImplicitlyExpandDesignTimeFacades)' == 'true'">
+ <DesignTimeFacadeDirectoryRoots Include="$(TargetFrameworkDirectory)" />
+ <DesignTimeFacadeDirectories Include="%(DesignTimeFacadeDirectoryRoots.Identity)\Facades\" Condition="Exists('%(DesignTimeFacadeDirectoryRoots.Identity)\Facades\')" />
+ <_DesignTimeFacadeAssemblies Include="%(DesignTimeFacadeDirectories.Identity)\*.dll"/>
+ </ItemGroup>
+
+ <PropertyGroup Condition="'@(DesignTimeFacadeDirectories)' != ''">
+ <TargetFrameworkDirectory>$(TargetFrameworkDirectory);@(DesignTimeFacadeDirectories)</TargetFrameworkDirectory>
+ </PropertyGroup>
+
+ </Target>
+
+ <PropertyGroup>
+ <AllowedReferenceAssemblyFileExtensions Condition=" '$(AllowedReferenceAssemblyFileExtensions)' == '' ">
+ .exe;
+ .dll
+ </AllowedReferenceAssemblyFileExtensions>
+
+ <AllowedReferenceRelatedFileExtensions Condition=" '$(AllowedReferenceRelatedFileExtensions)' == '' ">
+ .exe.mdb;
+ .dll.mdb;
+ .xml
+ </AllowedReferenceRelatedFileExtensions>
+
+ <AssemblySearchPaths Condition="'$(AssemblySearchPaths)' == ''">
+ {CandidateAssemblyFiles};
+ $(ReferencePath);
+ @(AdditionalReferencePath);
+ {HintPathFromItem};
+ {TargetFrameworkDirectory};
+ {PkgConfig};
+ {GAC};
+ {RawFileName};
+ $(OutDir)
+ </AssemblySearchPaths>
+
+ <ResolveReferencesDependsOn>
+ BeforeResolveReferences;
+ ResolveProjectReferences;
+ ResolveAssemblyReferences;
+ AfterResolveReferences
+ </ResolveReferencesDependsOn>
+
+ <ResolveAssemblyReferencesDependsOn>
+ GetFrameworkPaths;
+ GetReferenceAssemblyPaths;
+ PrepareForBuild
+ </ResolveAssemblyReferencesDependsOn>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(TargetFrameworkMoniker)' != ''">
+ <TargetFrameworkMonikerAssemblyAttributesPath Condition="'$(TargetFrameworkMonikerAssemblyAttributesPath)' == ''">$(IntermediateOutputPath)$(TargetFrameworkMoniker).AssemblyAttribute$(DefaultLanguageSourceExtension)</TargetFrameworkMonikerAssemblyAttributesPath>
+ <GenerateTargetFrameworkAttribute Condition="'$(GenerateTargetFrameworkAttribute)' == '' and '$(TargetFrameworkMoniker)'
+ != '' and '$(TargetingClr2Framework)' != 'true'">true</GenerateTargetFrameworkAttribute>
+ </PropertyGroup>
+
+ <ItemGroup Condition="'$(GenerateTargetFrameworkAttribute)' == 'true'">
+ <FileWrites Include="$(TargetFrameworkMonikerAssemblyAttributesPath)" />
+ </ItemGroup>
+
+ <Target Name="GenerateTargetFrameworkMonikerAttribute"
+ DependsOnTargets="PrepareForBuild;GetReferenceAssemblyPaths"
+ Inputs="$(MSBuildToolsPath)\Microsoft.Common.targets"
+ Outputs="$(TargetFrameworkMonikerAssemblyAttributesPath)"
+ Condition="'$(GenerateTargetFrameworkAttribute)' == 'true'">
+
+ <WriteLinesToFile
+ File="$(TargetFrameworkMonikerAssemblyAttributesPath)"
+ Lines="$(TargetFrameworkMonikerAssemblyAttributeText)"
+ Overwrite="true"
+ ContinueOnError="true"
+ Condition="'@(Compile)' != '' and '$(TargetFrameworkMonikerAssemblyAttributeText)' != ''"
+ />
+
+ <ItemGroup Condition="'@(Compile)' != '' and '$(TargetFrameworkMonikerAssemblyAttributeText)' != ''">
+ <Compile Include="$(TargetFrameworkMonikerAssemblyAttributesPath)"/>
+ </ItemGroup>
+ </Target>
+
+ <Target Name="ResolveReferences" DependsOnTargets="$(ResolveReferencesDependsOn)"/>
+
+ <Target Name="BeforeResolveReferences" />
+ <Target Name="AfterResolveReferences" />
+
+ <Target Name="ResolveAssemblyReferences" DependsOnTargets="$(ResolveAssemblyReferencesDependsOn)">
+ <CreateItem Include="@(Reference)" Exclude="$(AdditionalExplicitAssemblyReferences)">
+ <Output TaskParameter="Include" ItemName="_Reference"/>
+ </CreateItem>
+
+ <CreateItem Include="$(AdditionalExplicitAssemblyReferences)">
+ <Output TaskParameter="Include" ItemName="_Reference"/>
+ </CreateItem>
+
+ <ResolveAssemblyReference
+ Assemblies="@(_Reference)"
+ AssemblyFiles="@(ChildProjectReferences);@(_ExplicitReference)"
+ SearchPaths="$(AssemblySearchPaths)"
+ CandidateAssemblyFiles="@(Content);@(None)"
+ TargetFrameworkDirectories="$(TargetFrameworkDirectory)"
+ AllowedAssemblyExtensions="$(AllowedReferenceAssemblyFileExtensions)"
+ AllowedRelatedFileExtensions="$(AllowedReferenceRelatedFileExtensions)"
+ FindDependencies="true"
+ FindSatellites="true"
+ FindRelatedFiles="true"
+ TargetFrameworkMoniker="$(TargetFrameworkMoniker)"
+ TargetFrameworkMonikerDisplayName="$(TargetFrameworkMonikerDisplayName)"
+ TargetFrameworkVersion="$(TargetFrameworkVersion)"
+ >
+ <Output TaskParameter="ResolvedFiles" ItemName="ResolvedFiles"/>
+ <Output TaskParameter="ResolvedFiles" ItemName="ReferencePath"/>
+ <Output TaskParameter="ResolvedDependencyFiles" ItemName="ReferenceDependencyPaths"/>
+ <Output TaskParameter="RelatedFiles" ItemName="_ReferenceRelatedPaths"/>
+ <Output TaskParameter="SatelliteFiles" ItemName="ReferenceSatellitePaths"/>
+ <Output TaskParameter="CopyLocalFiles" ItemName="ReferenceCopyLocalPaths"/>
+
+ <!-- FIXME: backwards compatibility -->
+ <Output TaskParameter="ResolvedDependencyFiles" ItemName="_ResolvedDependencyFiles"/>
+ </ResolveAssemblyReference>
+ </Target>
+
+ <Target
+ Name="AssignProjectConfiguration"
+ Condition="'@(ProjectReference)' != ''">
+
+ <!-- assign configs if building a solution file -->
+ <AssignProjectConfiguration
+ ProjectReferences = "@(ProjectReference)"
+ SolutionConfigurationContents = "$(CurrentSolutionConfigurationContents)"
+ Condition="'$(BuildingSolutionFile)' == 'true'">
+
+ <Output TaskParameter = "AssignedProjects" ItemName = "ProjectReferenceWithConfiguration"/>
+ </AssignProjectConfiguration>
+
+ <!-- Else, just -->
+ <CreateItem Include="@(ProjectReference)" Condition="'$(BuildingSolutionFile)' != 'true'">
+ <Output TaskParameter="Include" ItemName="ProjectReferenceWithConfiguration"/>
+ </CreateItem>
+
+ </Target>
+
+ <!-- Split projects into 2 lists
+ ProjectReferenceWithConfigurationExistent: Projects existent on disk
+ ProjectReferenceWithConfigurationNonExistent: Projects non-existent on disk -->
+
+ <Target Name="SplitProjectReferencesByExistent"
+ DependsOnTargets="AssignProjectConfiguration">
+
+ <CreateItem Include="@(ProjectReferenceWithConfiguration)" Condition="'@(ProjectReferenceWithConfiguration)' != ''">
+ <Output TaskParameter="Include" ItemName="ProjectReferenceWithConfigurationExistent"
+ Condition="Exists ('%(ProjectReferenceWithConfiguration.Identity)')"/>
+
+ <Output TaskParameter="Include" ItemName="ProjectReferenceWithConfigurationNonExistent"
+ Condition="!Exists ('%(ProjectReferenceWithConfiguration.Identity)')"/>
+ </CreateItem>
+ </Target>
+
+ <Target
+ Name="ResolveProjectReferences"
+ DependsOnTargets="SplitProjectReferencesByExistent"
+ >
+ <!-- If building from a .sln.proj or from IDE, then referenced projects have already
+ been built, so just get the target paths -->
+ <MSBuild
+ Projects="@(ProjectReferenceWithConfigurationExistent)"
+ Targets="GetTargetPath"
+ Properties="%(ProjectReferenceWithConfigurationExistent.SetConfiguration); %(ProjectReferenceWithConfigurationExistent.SetPlatform)"
+ Condition="'@(ProjectReferenceWithConfigurationExistent)' != '' and ('$(BuildingSolutionFile)' == 'true' or '$(BuildingInsideVisualStudio)' == 'true')">
+
+ <Output TaskParameter="TargetOutputs" ItemName="ChildProjectReferences" Condition="'%(ProjectReferenceWithConfigurationExistent.ReferenceOutputAssembly)' != 'false'"/>
+ </MSBuild>
+
+ <!-- Building a project directly, build the referenced the projects also -->
+ <MSBuild
+ Projects="@(ProjectReferenceWithConfigurationExistent)"
+ Properties="%(ProjectReferenceWithConfigurationExistent.SetConfiguration); %(ProjectReferenceWithConfigurationExistent.SetPlatform)"
+ Condition="'@(ProjectReferenceWithConfigurationExistent)' != '' and '$(BuildingSolutionFile)' != 'true' and '$(BuildingInsideVisualStudio)' != 'true' ">
+
+ <Output TaskParameter="TargetOutputs" ItemName="ChildProjectReferences" Condition="'%(ProjectReferenceWithConfigurationExistent.ReferenceOutputAssembly)' != 'false'"/>
+ </MSBuild>
+
+ <Warning Text="Referenced Project %(ProjectReferenceWithConfigurationNonExistent.Identity) not found, ignoring."
+ Condition="'@(ProjectReferenceWithConfigurationNonExistent)' != ''"/>
+ </Target>
+
+ <Target Name = "CopyFilesMarkedCopyLocal">
+ <Copy
+ SourceFiles="@(ReferenceCopyLocalPaths)"
+ DestinationFiles="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')"
+ SkipUnchangedFiles="$(SkipCopyUnchangedFiles)">
+ <Output TaskParameter = "DestinationFiles" ItemName = "FileWritesShareable"/>
+ </Copy>
+ </Target>
+
+ <Target Name="_ComputeNonExistentFileProperty" Condition='false'>
+ <CreateProperty Value="__NonExistentSubDir__\__NonExistentFile__">
+ <Output TaskParameter="Value" PropertyName="NonExistentFile"/>
+ </CreateProperty>
+ </Target>
+
+ <PropertyGroup>
+ <BuildDependsOn>
+ BuildOnlySettings;
+ BeforeBuild;
+ CoreBuild;
+ AfterBuild
+ </BuildDependsOn>
+ </PropertyGroup>
+
+ <Target Name="BuildOnlySettings"/>
+ <Target Name="BeforeBuild"/>
+ <Target Name="AfterBuild"/>
+
+ <Target Name="Build" DependsOnTargets="$(BuildDependsOn)" Outputs="$(TargetPath)"/>
+
+ <PropertyGroup>
+ <CoreBuildDependsOn>
+ PrepareForBuild;
+ GetFrameworkPaths;
+ GetReferenceAssemblyPaths;
+ PreBuildEvent;
+ ResolveReferences;
+ CopyFilesMarkedCopyLocal;
+ PrepareResources;
+ Compile;
+ PrepareForRun;
+ DeployOutputFiles;
+ _RecordCleanFile;
+ PostBuildEvent
+ </CoreBuildDependsOn>
+ </PropertyGroup>
+
+ <Target
+ Name="CoreBuild"
+ DependsOnTargets="$(CoreBuildDependsOn)"
+ Outputs="$(OutDir)$(AssemblyName)$(TargetExt)">
+
+ <OnError ExecuteTargets="_TimestampAfterCompile;PostBuildEvent"
+ Condition=" '$(RunPostBuildEvent)' == 'Always' or '$(RunPostBuildEvent)' == 'OnOutputUpdated'"/>
+
+ <OnError ExecuteTargets="_RecordCleanFile" />
+ </Target>
+
+ <PropertyGroup>
+ <CompileDependsOn>
+ ResolveReferences;
+ GenerateTargetFrameworkMonikerAttribute;
+ BeforeCompile;
+ _TimestampBeforeCompile;
+ CoreCompile;
+ _TimestampAfterCompile;
+ AfterCompile
+ </CompileDependsOn>
+ </PropertyGroup>
+
+ <Target Name="BeforeCompile" />
+ <Target Name="AfterCompile" />
+
+ <Target Name="Compile" DependsOnTargets="$(CompileDependsOn)"/>
+
+ <PropertyGroup>
+ <PrepareForRunDependsOn>
+ DeployOutputFiles
+ </PrepareForRunDependsOn>
+ </PropertyGroup>
+ <Target Name="PrepareForRun" DependsOnTargets="$(PrepareForRunDependsOn)"/>
+
+ <PropertyGroup>
+ <PrepareResourcesDependsOn>
+ AssignTargetPaths;
+ SplitResourcesByCulture;
+ CreateManifestResourceNames;
+ CopyNonResxEmbeddedResources;
+ GenerateResources;
+ GenerateSatelliteAssemblies;
+ CompileLicxFiles
+ </PrepareResourcesDependsOn>
+ </PropertyGroup>
+ <Target Name="PrepareResources" DependsOnTargets="$(PrepareResourcesDependsOn)" />
+
+ <Target Name="SplitResourcesByCulture" DependsOnTargets="AssignTargetPaths">
+ <!-- Extract .licx files into @(LicxFiles) -->
+ <CreateItem Include="@(EmbeddedResourceWithTargetPath)" Condition="'%(Extension)' == '.licx'">
+ <Output TaskParameter="Include" ItemName="LicxFiles"/>
+ </CreateItem>
+
+ <!-- Split *remaining* resource files into various groups.. -->
+ <AssignCulture Files="@(EmbeddedResourceWithTargetPath)" Condition="'%(Extension)' != '.licx'">
+ <Output TaskParameter="AssignedFilesWithNoCulture" ItemName="ResourcesWithNoCulture"/>
+ <Output TaskParameter="AssignedFilesWithCulture" ItemName="ResourcesWithCulture"/>
+ </AssignCulture>
+
+ <CreateItem Include="@(ResourcesWithNoCulture)" Condition="'%(Extension)' == '.resx'">
+ <Output TaskParameter="Include" ItemName="ResxWithNoCulture"/>
+ </CreateItem>
+
+ <CreateItem Include="@(ResourcesWithNoCulture)" Condition="'%(Extension)' != '.resx'">
+ <Output TaskParameter="Include" ItemName="NonResxWithNoCulture"/>
+ </CreateItem>
+
+ <CreateItem Include="@(ResourcesWithCulture)" Condition="'%(Extension)' == '.resx'">
+ <Output TaskParameter="Include" ItemName="ResxWithCulture"/>
+ </CreateItem>
+
+ <CreateItem Include="@(ResourcesWithCulture)" Condition="'%(Extension)' != '.resx'">
+ <Output TaskParameter="Include" ItemName="NonResxWithCulture"/>
+ </CreateItem>
+ </Target>
+
+ <!-- Copy non-resx resources to their manifest resource names, this is what the compiler expects -->
+ <Target Name = "CopyNonResxEmbeddedResources"
+ Condition = "'@(NonResxWithCulture)' != '' or '@(NonResxWithNoCulture)' != '' or '@(ManifestNonResxWithCulture)' != '' or '@(ManifestNonResxWithNoCulture)' != ''">
+
+ <MakeDir Directories="$(IntermediateOutputPath)%(ManifestNonResxWithCulture.Culture)"/>
+ <Copy SourceFiles = "@(NonResxWithCulture)"
+ DestinationFiles = "@(ManifestNonResxWithCulture->'$(IntermediateOutputPath)%(Identity)')"
+ SkipUnchangedFiles="$(SkipCopyUnchangedFiles)">
+ <Output TaskParameter = "DestinationFiles" ItemName = "ManifestNonResxWithCultureOnDisk"/>
+ <Output TaskParameter = "DestinationFiles" ItemName = "FileWrites"/>
+ </Copy>
+
+ <Copy SourceFiles = "@(NonResxWithNoCulture)"
+ DestinationFiles = "@(ManifestNonResxWithNoCulture->'$(IntermediateOutputPath)%(Identity)')"
+ SkipUnchangedFiles="$(SkipCopyUnchangedFiles)">
+ <Output TaskParameter = "DestinationFiles" ItemName = "ManifestNonResxWithNoCultureOnDisk"/>
+ <Output TaskParameter = "DestinationFiles" ItemName = "FileWrites"/>
+ </Copy>
+ </Target>
+
+ <Target Name = "GenerateResources">
+ <GenerateResource
+ Sources = "@(ResxWithNoCulture)"
+ UseSourcePath = "true"
+ OutputResources = "@(ManifestResourceWithNoCultureName->'$(IntermediateOutputPath)%(Identity).resources')"
+ Condition = "'@(ResxWithNoCulture)' != '' ">
+
+ <Output TaskParameter = "OutputResources" ItemName = "ManifestResourceWithNoCulture"/>
+ <Output TaskParameter = "FilesWritten" ItemName = "FileWrites"/>
+ </GenerateResource>
+
+ <GenerateResource
+ Sources = "@(ResxWithCulture)"
+ UseSourcePath = "true"
+ OutputResources = "@(ManifestResourceWithCultureName->'$(IntermediateOutputPath)%(Identity).resources')"
+ Condition = "'@(ResxWithCulture)' != '' ">
+
+ <Output TaskParameter = "OutputResources" ItemName = "ManifestResourceWithCulture"/>
+ <Output TaskParameter = "FilesWritten" ItemName = "FileWrites"/>
+ </GenerateResource>
+ </Target>
+
+ <Target Name="GenerateSatelliteAssemblies"
+ Inputs="@(ManifestResourceWithCulture);@(ManifestNonResxWithCultureOnDisk)"
+ Outputs="$(IntermediateOutputPath)%(Culture)\$(AssemblyName).resources.dll" >
+ <!-- @(NonResxWithCulture) - rename files to ManifestNon.. and then use for AL -->
+ <MakeDir Directories = "$(IntermediateOutputPath)%(ManifestResourceWithCulture.Culture)" Condition = "'@(ManifestResourceWithCulture)' != ''" />
+ <MakeDir Directories = "$(IntermediateOutputPath)%(ManifestNonResxWithCultureOnDisk.Culture)" Condition = "'@(ManifestNonResxWithCultureOnDisk)' != ''" />
+
+ <AL
+ Culture = "%(Culture)"
+ DelaySign="$(DelaySign)"
+ EmbedResources = "@(ManifestResourceWithCulture);@(ManifestNonResxWithCultureOnDisk)"
+ KeyFile="$(KeyOriginatorFile)"
+ ToolExe="$(AlToolExe)"
+ ToolPath="$(AlToolPath)"
+ OutputAssembly = "$(IntermediateOutputPath)%(Culture)\$(AssemblyName).resources.dll" >
+ <Output TaskParameter="OutputAssembly" ItemName="FileWrites"/>
+ </AL>
+
+
+ <CreateItem
+ Include = "$(IntermediateOutputPath)%(Culture)\$(AssemblyName).resources.dll"
+ AdditionalMetadata = "Culture=%(Culture)"
+ Condition = "'@(ManifestResourceWithCulture)' != '' or '@(ManifestNonResxWithCultureOnDisk)' != ''">
+ <Output TaskParameter = "Include" ItemName = "IntermediateSatelliteAssemblies" />
+ </CreateItem>
+ </Target>
+
+ <PropertyGroup>
+ <CompileLicxFilesDependsOn></CompileLicxFilesDependsOn>
+ </PropertyGroup>
+
+ <Target Name = "CompileLicxFiles"
+ Condition = "'@(LicxFiles)' != ''"
+ DependsOnTargets = "$(CompileLicxFilesDependsOn)"
+ Outputs = "$(IntermediateOutputPath)$(TargetFileName).licenses">
+ <LC
+ Sources = "@(LicxFiles)"
+ LicenseTarget = "$(TargetFileName)"
+ OutputDirectory = "$(IntermediateOutputPath)"
+ OutputLicense = "$(IntermediateOutputPath)$(TargetFileName).licenses"
+ ReferencedAssemblies = "@(ReferencePath);@(ReferenceDependencyPaths)"
+ ToolPath = "$(LCToolPath)"
+ ToolExe = "$(LCToolExe)">
+
+ <Output TaskParameter="OutputLicense" ItemName="CompiledLicenseFile"/>
+ <Output TaskParameter="OutputLicense" ItemName="FileWrites"/>
+ </LC>
+ </Target>
+
+ <!-- Assign target paths to files that will need to be copied along with the project -->
+ <Target Name = "AssignTargetPaths">
+ <AssignTargetPath Files="@(None)" RootFolder="$(MSBuildProjectDirectory)">
+ <Output TaskParameter="AssignedFiles" ItemName="NoneWithTargetPath"/>
+ </AssignTargetPath>
+
+ <AssignTargetPath Files="@(Content)" RootFolder="$(MSBuildProjectDirectory)">
+ <Output TaskParameter="AssignedFiles" ItemName="ContentWithTargetPath"/>
+ </AssignTargetPath>
+
+ <AssignTargetPath Files="@(EmbeddedResource)" RootFolder="$(MSBuildProjectDirectory)">
+ <Output TaskParameter="AssignedFiles" ItemName="EmbeddedResourceWithTargetPath"/>
+ </AssignTargetPath>
+ </Target>
+
+ <Target Name="DeployOutputFiles"
+ DependsOnTargets="PrepareResources;CoreCompile;_CopyDeployFilesToOutputDirectory;_CopyAppConfigFile">
+
+ <Copy
+ SourceFiles="$(IntermediateOutputPath)$(AssemblyName)$(TargetExt).mdb"
+ Condition="'$(OutDir)' != '' and Exists('$(IntermediateOutputPath)$(AssemblyName)$(TargetExt).mdb')"
+ DestinationFolder="$(OutDir)"
+ SkipUnchangedFiles="$(SkipCopyUnchangedFiles)" >
+ <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
+ </Copy>
+
+ <Copy SourceFiles="@(IntermediateAssembly)" Condition="'$(OutDir)' != '' and Exists ('@(IntermediateAssembly)')" DestinationFolder="$(OutDir)" SkipUnchangedFiles="$(SkipCopyUnchangedFiles)">
+ <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
+ </Copy>
+
+ <Copy
+ SourceFiles = "@(IntermediateSatelliteAssemblies)"
+ DestinationFiles = "@(IntermediateSatelliteAssemblies->'$(OutDir)\%(Culture)\$(AssemblyName).resources.dll')"
+ Condition = "'@(IntermediateSatelliteAssemblies)' != ''"
+ SkipUnchangedFiles="$(SkipCopyUnchangedFiles)">
+ <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
+ </Copy>
+ </Target>
+
+ <Target Name="_CopyDeployFilesToOutputDirectory"
+ DependsOnTargets="GetCopyToOutputDirectoryItems;
+ _CopyDeployFilesToOutputDirectoryAlways;
+ _CopyDeployFilesToOutputDirectoryPreserveNewest"/>
+
+ <Target Name="_CopyDeployFilesToOutputDirectoryPreserveNewest"
+ Condition="'@(ItemsToCopyToOutputDirectoryPreserveNewest)' != ''"
+ Inputs="@(ItemsToCopyToOutputDirectoryPreserveNewest)"
+ Outputs="@(ItemsToCopyToOutputDirectoryPreserveNewest->'$(OutDir)%(TargetPath)')">
+
+ <Copy SourceFiles="@(ItemsToCopyToOutputDirectoryPreserveNewest)"
+ DestinationFiles="@(ItemsToCopyToOutputDirectoryPreserveNewest->'$(OutDir)%(TargetPath)')"
+ SkipUnchangedFiles="$(SkipCopyUnchangedFiles)">
+ <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
+ </Copy>
+ </Target>
+
+ <!-- Copy if newer -->
+ <Target Name="_CopyDeployFilesToOutputDirectoryAlways"
+ Condition="'@(ItemsToCopyToOutputDirectoryAlways)' != ''">
+
+ <Copy SourceFiles="@(ItemsToCopyToOutputDirectoryAlways)"
+ DestinationFiles="@(ItemsToCopyToOutputDirectoryAlways->'$(OutDir)%(TargetPath)')">
+ <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
+ </Copy>
+ </Target>
+
+
+ <Target Name="_CopyAppConfigFile" Condition="'@(AppConfigWithTargetPath)' != ''"
+ Inputs="@(AppConfigWithTargetPath)"
+ Outputs="@(AppConfigWithTargetPath->'$(OutDir)%(TargetPath)')">
+
+ <Copy SourceFiles="@(AppConfigWithTargetPath)"
+ DestinationFiles="@(AppConfigWithTargetPath->'$(OutDir)%(TargetPath)')">
+ <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
+ </Copy>
+ </Target>
+
+ <Target Name="GetTargetPath" Outputs="$(TargetPath)"/>
+
+ <Target Name="GetCopyToOutputDirectoryItems"
+ Outputs="@(AllItemsFullPathWithTargetPath)"
+ DependsOnTargets="AssignTargetPaths;SplitProjectReferencesByExistent">
+
+ <!-- FIXME: handle .vcproj
+ FIXME: Private ProjectReferences are honored only in 3.5
+ -->
+ <MSBuild
+ Projects="@(ProjectReferenceWithConfigurationExistent)"
+ Targets="GetCopyToOutputDirectoryItems"
+ Condition="'@(ProjectReferenceWithConfigurationExistent)' != '' and '%(ProjectReferenceWithConfigurationExistent.Private)' != 'false'">
+
+ <Output TaskParameter="TargetOutputs" ItemName="AllChildProjectItemsWithTargetPath"/>
+ </MSBuild>
+
+ <!-- Process items from child project. The outputs need to have full path
+ as they'll be used from other projects -->
+
+ <CreateItem
+ Include="@(AllChildProjectItemsWithTargetPath->'%(FullPath)')"
+ Condition="'%(AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)' == 'Always' or '%(AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)' == 'PreserveNewest'">
+
+ <Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
+ <Output TaskParameter="Include" ItemName="ItemsToCopyToOutputDirectoryAlways"
+ Condition="'%(AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
+ <Output TaskParameter="Include" ItemName="ItemsToCopyToOutputDirectoryPreserveNewest"
+ Condition="'%(AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
+
+ </CreateItem>
+
+ <!-- Process _this_ project's items -->
+
+ <CreateItem
+ Include="@(NoneWithTargetPath->'%(FullPath)')"
+ Condition="'%(NoneWithTargetPath.CopyToOutputDirectory)' == 'Always' or '%(NoneWithTargetPath.CopyToOutputDirectory)' == 'PreserveNewest'">
+ <Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
+ <Output TaskParameter="Include" ItemName="ItemsToCopyToOutputDirectoryAlways"
+ Condition="'%(NoneWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
+ <Output TaskParameter="Include" ItemName="ItemsToCopyToOutputDirectoryPreserveNewest"
+ Condition="'%(NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
+ </CreateItem>
+
+ <CreateItem
+ Include="@(ContentWithTargetPath->'%(FullPath)')"
+ Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)' == 'Always' or '%(ContentWithTargetPath.CopyToOutputDirectory)' == 'PreserveNewest'">
+ <Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
+ <Output TaskParameter="Include" ItemName="ItemsToCopyToOutputDirectoryAlways"
+ Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
+ <Output TaskParameter="Include" ItemName="ItemsToCopyToOutputDirectoryPreserveNewest"
+ Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
+ </CreateItem>
+
+ <CreateItem
+ Include="@(EmbeddedResourceWithTargetPath->'%(FullPath)')"
+ Condition="'%(EmbeddedResourceWithTargetPath.CopyToOutputDirectory)' == 'Always' or '%(EmbeddedResourceWithTargetPath.CopyToOutputDirectory)' == 'PreserveNewest'">
+ <Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
+ <Output TaskParameter="Include" ItemName="ItemsToCopyToOutputDirectoryAlways"
+ Condition="'%(EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
+ <Output TaskParameter="Include" ItemName="ItemsToCopyToOutputDirectoryPreserveNewest"
+ Condition="'%(EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
+ </CreateItem>
+
+ </Target>
+
+ <!-- Pre/Post BuildEvents -->
+ <PropertyGroup>
+ <PreBuildEventDependsOn />
+ </PropertyGroup>
+
+ <Target Name="PreBuildEvent"
+ Condition="'$(PreBuildEvent)' != ''"
+ DependsOnTargets="$(PreBuildEventDependsOn)">
+
+ <Exec WorkingDirectory="$(OutDir)" Command="$(PreBuildEvent)" />
+ </Target>
+
+ <!-- PostBuildEvent depends on $(RunPostBuildEvent)
+
+ Default: OnBuildSuccess
+ OnBuildSuccess: Run after a successful build
+ OnOutputUpdated: Run only if the output assembly got updates
+ Always: Run always
+ -->
+ <PropertyGroup>
+ <PostBuildEventDependsOn />
+ </PropertyGroup>
+
+ <!-- this gets invoked in two cases, from CoreBuildDependsOn, if the build completes
+ successfully, OR from OnError in CoreBuild, if the build failed and $(RunPostBuildEvent)
+ is 'Always' or 'OnOutputUpdated'. Invoke $(PostBuildEvent) if its either Empty (== OnBuildSuccess)
+ or OnBuildSuccess or Always OR (OnOutputUpdated and output assembly got updated) -->
+ <Target Name="PostBuildEvent"
+ Condition="'$(PostBuildEvent)' != '' and
+ ('$(RunPostBuildEvent)' != 'OnOutputUpdated' or
+ '$(_AssemblyModifiedTimeBeforeCompile)' != '$(_AssemblyModifiedTimeAfterCompile)')"
+ DependsOnTargets="$(PostBuildEventDependsOn)">
+
+ <Exec WorkingDirectory="$(OutDir)" Command="$(PostBuildEvent)" />
+ </Target>
+
+ <!-- Timestamp the output assemblies, required for PostBuildEvent -->
+ <Target Name="_TimestampBeforeCompile" Condition="'$(RunPostBuildEvent)' == 'OnOutputUpdated'">
+ <CreateItem Include="%(IntermediateAssembly.ModifiedTime)">
+ <Output TaskParameter="Include" PropertyName="_AssemblyModifiedTimeBeforeCompile" />
+ </CreateItem>
+ </Target>
+ <Target Name="_TimestampAfterCompile" Condition="'$(RunPostBuildEvent)' == 'OnOutputUpdated'">
+ <CreateItem Include="%(IntermediateAssembly.ModifiedTime)">
+ <Output TaskParameter="Include" PropertyName="_AssemblyModifiedTimeAfterCompile" />
+ </CreateItem>
+ </Target>
+
+ <!-- Rebuild -->
+ <PropertyGroup>
+ <RebuildDependsOn>
+ BeforeRebuild;
+ Clean;
+ $(MSBuildProjectDefaultTargets);
+ AfterRebuild;
+ </RebuildDependsOn>
+
+ <RebuildDependsOn Condition="'$(MSBuildProjectDefaultTargets)' == 'Rebuild'">
+ BeforeRebuild;
+ Clean;
+ Build;
+ AfterRebuild;
+ </RebuildDependsOn>
+ </PropertyGroup>
+
+ <Target Name="BeforeRebuild" />
+ <Target Name="AfterRebuild" />
+
+ <Target Name="Rebuild"
+ DependsOnTargets="$(RebuildDependsOn)"
+ Outputs="$(TargetPath)"/>
+
+ <!-- Clean -->
+ <Target Name="_RecordCleanFile"
+ DependsOnTargets="_GetCompileOutputsForClean">
+
+ <!-- add to list of previous writes for this platform/config -->
+
+ <ReadLinesFromFile File="$(IntermediateOutputPath)$(CleanFile)">
+ <Output TaskParameter="Lines" ItemName="PreviousFileWrites"/>
+ </ReadLinesFromFile>
+
+ <!-- CopyLocal files: In case all the projects build to common output
+ directory, then other projects might depend on some of these
+ CopyLocal files, so delete only the ones under *this* project
+ directory -->
+ <FindUnderPath Path="$(MSBuildProjectDirectory)" Files="@(FileWritesShareable)">
+ <Output TaskParameter="InPath" ItemName="FileWrites"/>
+ </FindUnderPath>
+
+ <RemoveDuplicates Inputs="@(PreviousFileWrites);@(FileWrites->'%(FullPath)')">
+ <Output TaskParameter="Filtered" ItemName="CombinedFileWrites"/>
+ </RemoveDuplicates>
+
+ <WriteLinesToFile
+ File="$(IntermediateOutputPath)$(CleanFile)"
+ Lines="@(CombinedFileWrites)"
+ Overwrite="true"/>
+ </Target>
+
+ <PropertyGroup>
+ <CleanDependsOn>
+ BeforeClean;
+ CleanReferencedProjects;
+ CoreClean;
+ AfterClean
+ </CleanDependsOn>
+ </PropertyGroup>
+
+ <Target Name="_GetCompileOutputsForClean">
+ <!-- assembly and debug file in the *intermediate output path* -->
+ <CreateItem Include="@(IntermediateAssembly)" Condition="Exists('@(IntermediateAssembly)')">
+ <Output TaskParameter="Include" ItemName="FileWrites"/>
+ </CreateItem>
+
+ <CreateItem Include="$(IntermediateOutputPath)$(AssemblyName)$(TargetExt).mdb"
+ Condition="Exists('$(IntermediateOutputPath)$(AssemblyName)$(TargetExt).mdb')">
+ <Output TaskParameter="Include" ItemName="FileWrites"/>
+ </CreateItem>
+ </Target>
+
+ <!-- Get the list of files written, for clean -->
+ <Target Name="_GetCleanFileWrites"
+ DependsOnTargets="_GetCompileOutputsForClean">
+ <ReadLinesFromFile File="$(IntermediateOutputPath)$(CleanFile)">
+ <Output TaskParameter="Lines" ItemName="PreviousFileWrites"/>
+ </ReadLinesFromFile>
+ </Target>
+
+ <Target Name="CleanReferencedProjects"
+ DependsOnTargets="AssignProjectConfiguration">
+
+ <!-- If building from .sln.proj or from IDE, clean will get handled by them,
+ else we are building a project directly, from the command line, so
+ clean the referenced projects -->
+ <MSBuild Projects="@(ProjectReferenceWithConfigurationExistent)"
+ Targets="Clean"
+ Condition=" '$(BuildingSolutionFile)' != 'true' and '$(BuildingInsideVisualStudio)' != 'true' and '@(ProjectReferenceWithConfigurationExistent)' != ''" />
+
+ </Target>
+
+ <Target Name="Clean" DependsOnTargets="$(CleanDependsOn)"/>
+
+ <!-- Override in project to run before/after clean tasks -->
+ <Target Name="BeforeClean" />
+ <Target Name="AfterClean" />
+
+ <Target Name="CoreClean" DependsOnTargets="_GetCleanFileWrites">
+ <Delete Files="@(PreviousFileWrites);@(FileWrites)" TreatErrorsAsWarnings="true"/>
+
+ <!-- all previous files written for this platform/config have been deleted,
+ we can safely remove the file list now -->
+ <Delete Files="$(IntermediateOutputPath)$(CleanFile)" TreatErrorsAsWarnings="true" />
+ </Target>
+
+ <PropertyGroup>
+ <ImplicitlyExpandDesignTimeFacades>true</ImplicitlyExpandDesignTimeFacades>
+
+ <ResolveReferencesDependsOn>
+ $(ResolveReferencesDependsOn);
+ ImplicitlyExpandDesignTimeFacades
+ </ResolveReferencesDependsOn>
+
+ <ImplicitlyExpandDesignTimeFacadesDependsOn>
+ $(ImplicitlyExpandDesignTimeFacadesDependsOn);
+ GetReferenceAssemblyPaths
+ </ImplicitlyExpandDesignTimeFacadesDependsOn>
+ </PropertyGroup>
+
+ <Target Name="ImplicitlyExpandDesignTimeFacades" Condition="'$(ImplicitlyExpandDesignTimeFacades)' == 'true'" DependsOnTargets="$(ImplicitlyExpandDesignTimeFacadesDependsOn)">
+
+ <PropertyGroup>
+ <_HasReferenceToSystemRuntime Condition="'%(_ResolvedDependencyFiles.Filename)' == 'System.Runtime'">true</_HasReferenceToSystemRuntime>
+ </PropertyGroup>
+
+ <ItemGroup Condition="'$(_HasReferenceToSystemRuntime)' == 'true'">
+ <!-- If the user has manually referenced these assemblies, remove them so we don't end up with duplicates -->
+ <ReferencePath Remove="@(_DesignTimeFacadeAssemblies)"/>
+ <ReferencePath Include="%(_DesignTimeFacadeAssemblies.Identity)">
+ <WinMDFile>false</WinMDFile>
+ <CopyLocal>false</CopyLocal>
+ <ResolvedFrom>ImplicitlyExpandDesignTimeFacades</ResolvedFrom>
+ </ReferencePath>
+ <_ResolveAssemblyReferenceResolvedFiles Include="@(ReferencePath)" Condition="'%(ReferencePath.ResolvedFrom)' == 'ImplicitlyExpandDesignTimeFacades'" />
+ </ItemGroup>
+
+ <Message Importance="Low" Text="Including @(ReferencePath)" Condition="'%(ReferencePath.ResolvedFrom)' == 'ImplicitlyExpandDesignTimeFacades'" />
+
+ </Target>
+
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\$(MSBuildThisFile)\ImportAfter\*"
+ Condition="'$(ImportByWildcardAfterMicrosoftCommonTargets)' == 'true' and Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\$(MSBuildThisFile)\ImportAfter')"/>
+</Project>
--- /dev/null
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
+ <UsingTask TaskName="Microsoft.Build.Tasks.AL" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.AssignTargetPath" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.AssignCulture" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.AssignProjectConfiguration" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.CallTarget" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.CombinePath" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.Copy" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.CreateCSharpManifestResourceName" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
+ <UsingTask TaskName="Microsoft.Build.Tasks.CreateItem" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.CreateProperty" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.Csc" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.Delete" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.Error" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.Exec" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.FindAppConfigFile" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.FindUnderPath" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.GenerateResource" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.GetAssemblyIdentity" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.GetFrameworkPath" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.GetFrameworkSdkPath" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.GetReferenceAssemblyPaths" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.LC" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.MakeDir" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.Message" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.MSBuild" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.ReadLinesFromFile" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.RemoveDir" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.RemoveDuplicates" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.ResolveAssemblyReference" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.SignFile" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.Touch" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.Vbc" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.Warning" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <UsingTask TaskName="Microsoft.Build.Tasks.WriteCodeFragment" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
+ <UsingTask TaskName="Microsoft.Build.Tasks.WriteLinesToFile" AssemblyName="Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+</Project>
NAME_SUFFIX = .v$(XBUILD_VERSION)
endif
+ifeq (14.0, $(XBUILD_VERSION))
+NAME_SUFFIX = .Core
+endif
+
XBUILD_FRAMEWORK := $(topdir)/class/lib/$(PROFILE)/Microsoft.Build.Framework.dll
XBUILD_ENGINE := $(topdir)/class/lib/$(PROFILE)/Microsoft.Build.Engine.dll
XBUILD_UTILITIES := $(topdir)/class/lib/$(PROFILE)/Microsoft.Build.Utilities$(NAME_SUFFIX).dll
XBUILD_3_5_PROFILE_DIR=$(topdir)/class/lib/net_3_5
XBUILD_4_0_PROFILE_DIR=$(topdir)/class/lib/net_4_5
XBUILD_12_0_PROFILE_DIR=$(topdir)/class/lib/xbuild_12
+XBUILD_14_0_PROFILE_DIR=$(topdir)/class/lib/xbuild_14
copy-targets-2.0:
cp $(XBUILD_DATA_DIR)/2.0/Microsoft.Common.targets $(XBUILD_2_0_PROFILE_DIR)
cp $(XBUILD_DATA_DIR)/12.0/Microsoft.CSharp.targets $(XBUILD_12_0_PROFILE_DIR)
cp $(XBUILD_DATA_DIR)/Microsoft.VisualBasic.targets $(XBUILD_12_0_PROFILE_DIR)
+copy-targets-14.0:
+ cp $(XBUILD_DATA_DIR)/14.0/Microsoft.Common.targets $(XBUILD_14_0_PROFILE_DIR)
+ cp $(XBUILD_DATA_DIR)/14.0/Microsoft.Common.tasks $(XBUILD_14_0_PROFILE_DIR)
+ cp $(XBUILD_DATA_DIR)/14.0/Microsoft.CSharp.targets $(XBUILD_14_0_PROFILE_DIR)
+ cp $(XBUILD_DATA_DIR)/Microsoft.VisualBasic.targets $(XBUILD_14_0_PROFILE_DIR)
+
clean-targets-2.0:
rm -f $(XBUILD_2_0_PROFILE_DIR)/Microsoft.Common.targets
rm -f $(XBUILD_2_0_PROFILE_DIR)/Microsoft.Common.tasks
rm -f $(XBUILD_12_0_PROFILE_DIR)/Microsoft.CSharp.targets
rm -f $(XBUILD_12_0_PROFILE_DIR)/Microsoft.VisualBasic.targets
+clean-targets-14.0:
+ rm -f $(XBUILD_14_0_PROFILE_DIR)/Microsoft.Common.targets
+ rm -f $(XBUILD_14_0_PROFILE_DIR)/Microsoft.Common.tasks
+ rm -f $(XBUILD_14_0_PROFILE_DIR)/Microsoft.CSharp.targets
+ rm -f $(XBUILD_14_0_PROFILE_DIR)/Microsoft.VisualBasic.targets
+
#allow tests to find older versions of libs and targets
ifneq (2.0, $(XBUILD_VERSION))
TEST_MONO_PATH := $(topdir)/class/lib/net_2_0
* class->runtime_info.
*/
- mono_loader_lock ();
+ mono_loader_lock (); //FIXME why do we need the loader lock here?
mono_domain_lock (domain);
#ifdef HAVE_SGEN_GC
/*
#include <mono/utils/dtrace.h>
#include <mono/utils/gc_wrapper.h>
#include <mono/utils/mono-mutex.h>
+#include <mono/utils/mono-counters.h>
#if HAVE_BOEHM_GC
if (gc_initialized)
return;
+ mono_counters_init ();
+
/*
* Handle the case when we are called from a thread different from the main thread,
* confusing libgc.
iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
}
- mono_loader_lock ();
cached = mono_method_inflated_lookup (iresult, FALSE);
if (cached) {
- mono_loader_unlock ();
g_free (iresult);
return (MonoMethod*)cached;
}
* is_generic_method_definition().
*/
- mono_method_inflated_lookup (iresult, TRUE);
- mono_loader_unlock ();
- return result;
+ return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
fail:
- mono_loader_unlock ();
g_free (iresult);
return NULL;
}
* mono_method_set_generic_container:
*
* Sets the generic container of METHOD to CONTAINER.
- * LOCKING: Acquires the loader lock.
+ * LOCKING: Acquires the image lock.
*/
void
mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
#define FAST_CACHE_SIZE 16
+/*
+ * LOCKING: Takes the image lock depending on @take_lock.
+ */
static MonoClass *
-get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
+get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
{
int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
MonoImage *image = param->image;
else
return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
} else {
+ MonoClass *klass = NULL;
ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
- return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
+ if (ht) {
+ if (take_lock)
+ mono_image_lock (image);
+ klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
+ if (take_lock)
+ mono_image_unlock (image);
+ }
+ return klass;
}
}
/*
- * LOCKING: Acquires the loader lock.
+ * LOCKING: Image lock (param->image) must be held
*/
static void
set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
{
int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
MonoImage *image = param->image;
- GHashTable *ht;
g_assert (image);
if (n < FAST_CACHE_SIZE) {
if (is_mvar) {
- /* No locking needed */
+ /* Requires locking to avoid droping an already published class */
if (!image->mvar_cache_fast)
image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
image->mvar_cache_fast [n] = klass;
image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
image->var_cache_fast [n] = klass;
}
- return;
- }
- ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
- if (!ht) {
- mono_image_lock (image);
- ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
+ } else {
+ GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
if (!ht) {
- ht = g_hash_table_new (NULL, NULL);
- mono_memory_barrier ();
- if (is_mvar)
- image->mvar_cache_slow = ht;
- else
- image->var_cache_slow = ht;
+ ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
+ if (!ht) {
+ ht = g_hash_table_new (NULL, NULL);
+ mono_memory_barrier ();
+ if (is_mvar)
+ image->mvar_cache_slow = ht;
+ else
+ image->var_cache_slow = ht;
+ }
}
- mono_image_unlock (image);
+ g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
}
-
- g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
}
/*
- * LOCKING: Acquires the loader lock.
+ * LOCKING: Acquires the image lock (@image).
*/
MonoClass *
mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
{
MonoGenericContainer *container = mono_generic_param_owner (param);
- MonoGenericParamInfo *pinfo;
- MonoClass *klass;
-
- mono_loader_lock ();
+ MonoGenericParamInfo *pinfo = NULL;
+ MonoClass *klass, *klass2;
if (container) {
pinfo = mono_generic_param_info (param);
- if (pinfo->pklass) {
- mono_loader_unlock ();
- return pinfo->pklass;
- }
+ klass = pinfo->pklass;
} else {
- pinfo = NULL;
image = NULL;
-
- klass = get_anon_gparam_class (param, is_mvar);
- if (klass) {
- mono_loader_unlock ();
- return klass;
- }
+ klass = get_anon_gparam_class (param, is_mvar, TRUE);
}
+ if (klass)
+ return klass;
if (!image && container) {
if (is_mvar) {
mono_memory_barrier ();
+ if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
+ image = mono_defaults.corlib;
+
+ mono_image_lock (image);
if (container)
- pinfo->pklass = klass;
+ klass2 = pinfo->pklass;
else
- set_anon_gparam_class (param, is_mvar, klass);
+ klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
- mono_loader_unlock ();
+ if (klass2) {
+ klass = klass2;
+ } else {
+ if (container)
+ pinfo->pklass = klass;
+ else
+ set_anon_gparam_class (param, is_mvar, klass);
+ }
+ mono_image_unlock (image);
/* FIXME: Should this go inside 'make_generic_param_klass'? */
- mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+ if (klass2)
+ mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
+ else
+ mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
return klass;
}
el_class = mono_class_from_mono_type (type);
image = el_class->image;
- mono_loader_lock ();
-
- if (!image->ptr_cache)
- image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
-
- if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
- mono_loader_unlock ();
- return result;
+ mono_image_lock (image);
+ if (image->ptr_cache) {
+ if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
+ mono_image_unlock (image);
+ return result;
+ }
}
+ mono_image_unlock (image);
+
result = mono_image_alloc0 (image, sizeof (MonoClass));
classes_size += sizeof (MonoClass);
mono_class_setup_supertypes (result);
+ mono_image_lock (image);
+ if (image->ptr_cache) {
+ MonoClass *result2;
+ if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
+ mono_image_unlock (image);
+ mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
+ return result2;
+ }
+ } else {
+ image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
+ }
g_hash_table_insert (image->ptr_cache, el_class, result);
-
- mono_loader_unlock ();
+ mono_image_unlock (image);
mono_profiler_class_loaded (result, MONO_PROFILE_OK);
if (fileidx < 1 || fileidx > t->rows)
return NULL;
- mono_loader_lock ();
+ mono_image_lock (image);
if (image->files && image->files [fileidx - 1]) {
- mono_loader_unlock ();
+ mono_image_unlock (image);
return image->files [fileidx - 1];
}
- if (!image->files)
- image->files = g_new0 (MonoImage*, t->rows);
-
fname_id = mono_metadata_decode_row_col (t, fileidx - 1, MONO_FILE_NAME);
fname = mono_metadata_string_heap (image, fname_id);
base_dir = g_path_get_dirname (image->name);
name = g_build_filename (base_dir, fname, NULL);
res = mono_image_open (name, NULL);
- if (res) {
+ if (!res)
+ goto done;
+
+ mono_image_lock (image);
+ if (image->files && image->files [fileidx - 1]) {
+ MonoImage *old = res;
+ res = image->files [fileidx - 1];
+ mono_loader_unlock ();
+ mono_image_close (old);
+ } else {
int i;
/* g_print ("loaded file %s from %s (%p)\n", name, image->name, image->assembly); */
res->assembly = image->assembly;
res->modules [i]->assembly = image->assembly;
}
+ if (!image->files)
+ image->files = g_new0 (MonoImage*, t->rows);
image->files [fileidx - 1] = res;
+ mono_loader_unlock ();
+ /* vtable fixup can't happen with the image lock held */
#ifdef HOST_WIN32
if (res->is_module_handle)
mono_image_fixup_vtable (res);
#endif
}
- mono_loader_unlock ();
+
+done:
g_free (name);
g_free (base_dir);
return res;
* See domain-internals.h for locking policy in combination with the
* domain lock.
*/
-static mono_mutex_t loader_mutex;
+static mono_mutex_t loader_mutex, global_loader_data_mutex;
static gboolean loader_lock_inited;
/* Statistics */
static void dllmap_cleanup (void);
+
+static void
+global_loader_data_lock (void)
+{
+ mono_locks_acquire (&global_loader_data_mutex, LoaderGlobalDataLock);
+}
+
+static void
+global_loader_data_unlock (void)
+{
+ mono_locks_release (&global_loader_data_mutex, LoaderGlobalDataLock);
+}
+
void
mono_loader_init ()
{
if (!inited) {
mono_mutex_init_recursive (&loader_mutex);
+ mono_mutex_init_recursive (&global_loader_data_mutex);
loader_lock_inited = TRUE;
mono_native_tls_alloc (&loader_error_thread_id, NULL);
mono_native_tls_free (loader_lock_nest_id);
mono_mutex_destroy (&loader_mutex);
+ mono_mutex_destroy (&global_loader_data_mutex);
loader_lock_inited = FALSE;
}
if (!dll_map)
return 0;
- mono_loader_lock ();
+ global_loader_data_lock ();
/*
* we use the first entry we find that matches, since entries from
}
}
- mono_loader_unlock ();
+ global_loader_data_unlock ();
return found;
}
entry->func = func? g_strdup (func): NULL;
entry->target_func = tfunc? g_strdup (tfunc): NULL;
- mono_loader_lock ();
+ global_loader_data_lock ();
entry->next = global_dll_map;
global_dll_map = entry;
- mono_loader_unlock ();
+ global_loader_data_unlock ();
} else {
entry = mono_image_alloc0 (assembly, sizeof (MonoDllMap));
entry->dll = dll? mono_image_strdup (assembly, dll): NULL;
if (err)
*err = NULL;
- mono_loader_lock ();
+ global_loader_data_lock ();
if (!global_module_map)
global_module_map = g_hash_table_new (g_str_hash, g_str_equal);
res = g_hash_table_lookup (global_module_map, name);
if (res) {
- mono_loader_unlock ();
+ global_loader_data_unlock ();
return res;
}
res = mono_dl_open (name, flags, err);
if (res)
g_hash_table_insert (global_module_map, g_strdup (name), res);
- mono_loader_unlock ();
+ global_loader_data_unlock ();
return res;
}
mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (stack_walk_adapter, NULL, MONO_UNWIND_DEFAULT, &ud);
}
+typedef struct {
+ MonoStackWalkAsyncSafe func;
+ gpointer user_data;
+} AsyncStackWalkUserData;
+
+
+static gboolean
+async_stack_walk_adapter (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data)
+{
+ AsyncStackWalkUserData *d = data;
+
+ switch (frame->type) {
+ case FRAME_TYPE_DEBUGGER_INVOKE:
+ case FRAME_TYPE_MANAGED_TO_NATIVE:
+ return FALSE;
+ case FRAME_TYPE_MANAGED:
+ if (!frame->ji)
+ return FALSE;
+ if (frame->ji->async)
+ return d->func (NULL, frame->domain, frame->ji->code_start, frame->native_offset, d->user_data);
+ else
+ return d->func (mono_jit_info_get_method (frame->ji), frame->domain, frame->ji->code_start, frame->native_offset, d->user_data);
+ break;
+ default:
+ g_assert_not_reached ();
+ return FALSE;
+ }
+}
+
+
/*
* mono_stack_walk_async_safe:
*
* Async safe version callable from signal handlers.
*/
void
-mono_stack_walk_async_safe (MonoStackWalk func, gpointer user_data)
+mono_stack_walk_async_safe (MonoStackWalkAsyncSafe func, void *initial_sig_context, void *user_data)
{
- StackWalkUserData ud = { func, user_data };
- mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (stack_walk_adapter, NULL, MONO_UNWIND_NONE, &ud);
+ MonoContext ctx;
+ AsyncStackWalkUserData ud = { func, user_data };
+
+ mono_sigctx_to_monoctx (initial_sig_context, &ctx);
+ mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (async_stack_walk_adapter, NULL, MONO_UNWIND_SIGNAL_SAFE, &ud);
}
static gboolean
MONO_API void
mono_stack_walk_no_il (MonoStackWalk func, void* user_data);
+typedef mono_bool (*MonoStackWalkAsyncSafe) (MonoMethod *method, MonoDomain *domain, void *base_address, int offset, void* data);
MONO_API void
-mono_stack_walk_async_safe (MonoStackWalk func, void* user_data);
+mono_stack_walk_async_safe (MonoStackWalkAsyncSafe func, void *initial_sig_context, void* user_data);
MONO_END_DECLS
DomainJitCodeHashLock,
IcallLock,
AssemblyBindingLock,
- MarshalLock
+ MarshalLock,
+ LoaderGlobalDataLock,
} RuntimeLocks;
#ifdef LOCK_TRACER
#ifndef DISABLE_COM
return mono_cominterop_get_native_wrapper (method);
#else
+ if (aot)
+ return method;
g_assert_not_reached ();
#endif
}
guint32 module_count;
gboolean *modules_loaded;
- MonoImage **files;
+ MonoImage **files; /*protected by the image lock*/
gpointer aot_module;
g_free (sig);
}
-/*
- * LOCKING: assumes the loader lock is held.
- */
MonoMethodInflated*
mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache)
{
collect_data_free (&data);
- if (cache) {
- mono_image_set_lock (set);
+ mono_image_set_lock (set);
+ res = g_hash_table_lookup (set->gmethod_cache, method);
+ if (!res && cache) {
g_hash_table_insert (set->gmethod_cache, method, method);
- mono_image_set_unlock (set);
-
- return method;
- } else {
- mono_image_set_lock (set);
- res = g_hash_table_lookup (set->gmethod_cache, method);
- mono_image_set_unlock (set);
-
- return res;
+ res = method;
}
+
+ mono_image_set_unlock (set);
+ return res;
}
/*
int num_instances;
/* variable length data follows */
char name [1];
+ // string name
+ // string help
+ // SharedCounter counters_info [num_counters]
} SharedCategory;
typedef struct {
unsigned int category_offset;
/* variable length data follows */
char instance_name [1];
+ // string name
} SharedInstance;
typedef struct {
guint8 seq_num;
/* variable length data follows */
char name [1];
+ // string name
+ // string help
} SharedCounter;
typedef struct {
return 2;
}
-static unsigned char*
-shared_data_find_room (int size)
+static SharedHeader*
+shared_data_reserve_room (int size, int ftype)
{
+ SharedHeader* header;
unsigned char *p = (unsigned char *)shared_area + shared_area->data_start;
unsigned char *end = (unsigned char *)shared_area + shared_area->size;
unsigned short *next;
if (*p == FTYPE_END) {
if (size < (end - p))
- return p;
+ goto res;
return NULL;
}
if (p + 4 > end)
if (*p == FTYPE_DELETED) {
/* we reuse only if it's the same size */
if (*next == size) {
- return p;
+ goto res;
}
}
p += *next;
}
return NULL;
+
+res:
+ header = (SharedHeader*)p;
+ header->ftype = ftype;
+ header->extra = 0; /* data_offset could overflow here, so we leave this field unused */
+ header->size = size;
+
+ return header;
}
typedef gboolean (*SharedFunc) (SharedHeader *header, void *data);
SharedCounter *counter = (SharedCounter*)p;
if (mono_string_compare_ascii (name, counter->name) == 0)
return counter;
- p += 1 + strlen (p + 1) + 1; /* skip counter type and name */
+ p += 2; /* skip counter type */
+ p += strlen (p) + 1; /* skip counter name */
p += strlen (p) + 1; /* skip counter help */
}
return NULL;
typedef struct {
unsigned int cat_offset;
SharedCategory* cat;
- MonoString *instance;
+ char *name;
SharedInstance* result;
GSList *list;
} InstanceSearch;
if (header->ftype == FTYPE_INSTANCE) {
SharedInstance *ins = (SharedInstance*)header;
if (search->cat_offset == ins->category_offset) {
- if (search->instance) {
- if (mono_string_compare_ascii (search->instance, ins->instance_name) == 0) {
+ if (search->name) {
+ if (strcmp (search->name, ins->instance_name) == 0) {
search->result = ins;
return FALSE;
}
}
static SharedInstance*
-find_custom_instance (SharedCategory* cat, MonoString *instance)
+find_custom_instance (SharedCategory* cat, char *name)
{
InstanceSearch search;
search.cat_offset = (char*)cat - (char*)shared_area;
search.cat = cat;
- search.instance = instance;
+ search.name = name;
search.list = NULL;
search.result = NULL;
foreach_shared_item (instance_search, &search);
InstanceSearch search;
search.cat_offset = (char*)cat - (char*)shared_area;
search.cat = cat;
- search.instance = NULL;
+ search.name = NULL;
search.list = NULL;
search.result = NULL;
foreach_shared_item (instance_search, &search);
}
static SharedInstance*
-custom_get_instance (SharedCategory *cat, SharedCounter *scounter, MonoString* instance)
+custom_get_instance (SharedCategory *cat, SharedCounter *scounter, char* name)
{
SharedInstance* inst;
- unsigned char *ptr;
char *p;
int size, data_offset;
- char *name;
- inst = find_custom_instance (cat, instance);
+ inst = find_custom_instance (cat, name);
if (inst)
return inst;
- name = mono_string_to_utf8 (instance);
size = sizeof (SharedInstance) + strlen (name);
size += 7;
size &= ~7;
data_offset = size;
size += (sizeof (guint64) * cat->num_counters);
perfctr_lock ();
- ptr = shared_data_find_room (size);
- if (!ptr) {
+ inst = (SharedInstance*) shared_data_reserve_room (size, FTYPE_INSTANCE);
+ if (!inst) {
perfctr_unlock ();
g_free (name);
return NULL;
}
- inst = (SharedInstance*)ptr;
- inst->header.extra = 0; /* data_offset could overflow here, so we leave this field unused */
- inst->header.size = size;
inst->category_offset = (char*)cat - (char*)shared_area;
cat->num_instances++;
/* now copy the variable data */
p = inst->instance_name;
strcpy (p, name);
p += strlen (name) + 1;
- inst->header.ftype = FTYPE_INSTANCE;
perfctr_unlock ();
- g_free (name);
return inst;
}
return (ImplVtable*)vtable;
}
+static gpointer
+custom_get_value_address (SharedCounter *scounter, SharedInstance* sinst)
+{
+ int offset = sizeof (SharedInstance) + strlen (sinst->instance_name);
+ offset += 7;
+ offset &= ~7;
+ offset += scounter->seq_num * sizeof (guint64);
+ return (char*)sinst + offset;
+}
+
static void*
custom_get_impl (SharedCategory *cat, MonoString* counter, MonoString* instance, int *type)
{
SharedCounter *scounter;
SharedInstance* inst;
- int size;
+ char *name;
scounter = find_custom_counter (cat, counter);
if (!scounter)
return NULL;
*type = simple_type_to_type [scounter->type];
- inst = custom_get_instance (cat, scounter, instance);
+ name = mono_string_to_utf8 (counter);
+ inst = custom_get_instance (cat, scounter, name);
+ g_free (name);
if (!inst)
return NULL;
- size = sizeof (SharedInstance) + strlen (inst->instance_name);
- size += 7;
- size &= ~7;
- return custom_vtable (scounter, inst, (char*)inst + size + scounter->seq_num * sizeof (guint64));
+ return custom_vtable (scounter, inst, custom_get_value_address (scounter, inst));
}
static const CategoryDesc*
char *name = NULL;
char *chelp = NULL;
char **counter_info = NULL;
- unsigned char *ptr;
char *p;
SharedCategory *cat;
if (size > 65535)
goto failure;
perfctr_lock ();
- ptr = shared_data_find_room (size);
- if (!ptr) {
+ cat = (SharedCategory*) shared_data_reserve_room (size, FTYPE_CATEGORY);
+ if (!cat) {
perfctr_unlock ();
goto failure;
}
- cat = (SharedCategory*)ptr;
- cat->header.extra = type;
- cat->header.size = size;
cat->num_counters = num_counters;
cat->counters_data_size = counters_data_size;
/* now copy the vaiable data */
strcpy (p, counter_info [i * 2 + 1]);
p += strlen (counter_info [i * 2 + 1]) + 1;
}
- cat->header.ftype = FTYPE_CATEGORY;
perfctr_unlock ();
result = TRUE;
mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, MonoString *machine)
{
const CategoryDesc *cdesc;
+ SharedInstance *sinst;
+ char *name;
/* no support for counters on other machines */
/*FIXME: machine appears to be wrong
if (mono_string_compare_ascii (machine, "."))
scat = find_custom_category (category);
if (!scat)
return FALSE;
- if (find_custom_instance (scat, instance))
+ name = mono_string_to_utf8 (instance);
+ sinst = find_custom_instance (scat, name);
+ g_free (name);
+ if (sinst)
return TRUE;
} else {
/* FIXME: search instance */
res = mono_array_new (domain, mono_get_string_class (), scat->num_counters);
for (i = 0; i < scat->num_counters; ++i) {
mono_array_setref (res, i, mono_string_new (domain, p + 1));
- p += 1 + strlen (p + 1) + 1; /* skip counter type and name */
+ p += 2; /* skip counter type */
+ p += strlen (p) + 1; /* skip counter name */
p += strlen (p) + 1; /* skip counter help */
}
perfctr_unlock ();
return mono_array_new (mono_domain_get (), mono_get_string_class (), 0);
}
}
+
+typedef struct {
+ PerfCounterEnumCallback cb;
+ void *data;
+} PerfCounterForeachData;
+
+static gboolean
+mono_perfcounter_foreach_shared_item (SharedHeader *header, gpointer data)
+{
+ int i;
+ char *p, *name, *help;
+ unsigned char type;
+ int seq_num;
+ void *addr;
+ SharedCategory *cat;
+ SharedCounter *counter;
+ SharedInstance *inst;
+ PerfCounterForeachData *foreach_data = data;
+
+ if (header->ftype == FTYPE_CATEGORY) {
+ cat = (SharedCategory*)header;
+
+ p = cat->name;
+ p += strlen (p) + 1; /* skip category name */
+ p += strlen (p) + 1; /* skip category help */
+
+ for (i = 0; i < cat->num_counters; ++i) {
+ counter = (SharedCounter*) p;
+ type = (unsigned char)*p++;
+ seq_num = (int)*p++;
+ name = p;
+ p += strlen (p) + 1;
+ help = p;
+ p += strlen (p) + 1;
+
+ inst = custom_get_instance (cat, counter, name);
+ if (!inst)
+ return FALSE;
+ addr = custom_get_value_address (counter, inst);
+ if (!foreach_data->cb (cat->name, name, type, addr ? *(gint64*)addr : 0, foreach_data->data))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+void
+mono_perfcounter_foreach (PerfCounterEnumCallback cb, gpointer data)
+{
+ PerfCounterForeachData foreach_data = { cb, data };
+
+ perfctr_lock ();
+
+ foreach_shared_item (mono_perfcounter_foreach_shared_item, &foreach_data);
+
+ perfctr_unlock ();
+}
+
#else
void*
mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString* instance, MonoString* machine, int *type, MonoBoolean *custom)
#define __MONO_PERFCOUNTERS_H__
#include <glib.h>
-#include <metadata/object.h>
-#include <utils/mono-compiler.h>
+#include <mono/metadata/object.h>
+#include <mono/utils/mono-compiler.h>
typedef struct _MonoCounterSample MonoCounterSample;
MonoArray* mono_perfcounter_counter_names (MonoString *category, MonoString *machine) MONO_INTERNAL;
MonoArray* mono_perfcounter_instance_names (MonoString *category, MonoString *machine) MONO_INTERNAL;
+typedef gboolean (*PerfCounterEnumCallback) (char *category_name, char *name, unsigned char type, gint64 value, gpointer user_data);
+MONO_API void mono_perfcounter_foreach (PerfCounterEnumCallback cb, gpointer user_data);
#endif /* __MONO_PERFCOUNTERS_H__ */
#include <mono/metadata/runtime.h>
#include <mono/utils/atomic.h>
#include <mono/utils/mono-threads.h>
+#include <mono/utils/mono-counters.h>
#ifdef HAVE_NULL_GC
MonoThreadInfoCallbacks cb;
int dummy;
+ mono_counters_init ();
+
memset (&cb, 0, sizeof (cb));
/* TODO: This casts away an incompatible pointer type warning in the same
manner that boehm-gc does it. This is probably worth investigating
#include "metadata/sgen-gc.h"
#include "metadata/sgen-gray.h"
#include "metadata/sgen-protocol.h"
+#include "metadata/sgen-pointer-queue.h"
#include "utils/dtrace.h"
#include "utils/mono-counters.h"
static int
tagged_object_hash (MonoObject *o)
{
- return mono_object_hash (tagged_object_get_object (o));
+ return mono_aligned_addr_hash (tagged_object_get_object (o));
}
static gboolean
MonoObject *object;
gpointer dummy;
char *copy;
+ SgenPointerQueue moved_fin_objects;
+
+ sgen_pointer_queue_init (&moved_fin_objects, INTERNAL_MEM_TEMPORARY);
if (no_finalize)
return;
SGEN_LOG (5, "Promoting finalization of object %p (%s) (was at %p) to major table", copy, sgen_safe_name (copy), object);
continue;
- } else {
+ } else if (copy != (char*)object) {
/* update pointer */
+ SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
+
+ /* register for reinsertion */
+ sgen_pointer_queue_add (&moved_fin_objects, tagged_object_apply (copy, tag));
+
SGEN_LOG (5, "Updating object for finalization: %p (%s) (was at %p)", copy, sgen_safe_name (copy), object);
- SGEN_HASH_TABLE_FOREACH_SET_KEY (tagged_object_apply (copy, tag));
+
+ continue;
}
} SGEN_HASH_TABLE_FOREACH_END;
+
+ while (!sgen_pointer_queue_is_empty (&moved_fin_objects)) {
+ sgen_hash_table_replace (hash_table, sgen_pointer_queue_pop (&moved_fin_objects), NULL, NULL);
+ }
+
+ sgen_pointer_queue_free (&moved_fin_objects);
}
SgenHashTable *hash_table = get_finalize_entry_hash_table (generation);
MonoObject *object;
gpointer dummy;
+ SgenPointerQueue moved_fin_objects;
+
+ sgen_pointer_queue_init (&moved_fin_objects, INTERNAL_MEM_TEMPORARY);
if (no_finalize)
return;
SGEN_LOG (5, "Promoting finalization of object %p (%s) (was at %p) to major table", copy, sgen_safe_name (copy), object);
continue;
- } else {
+ } else if (copy != object) {
/* update pointer */
+ SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
+
+ /* register for reinsertion */
+ sgen_pointer_queue_add (&moved_fin_objects, tagged_object_apply (copy, tag));
+
SGEN_LOG (5, "Updating object for finalization: %p (%s) (was at %p)", copy, sgen_safe_name (copy), object);
- SGEN_HASH_TABLE_FOREACH_SET_KEY (tagged_object_apply (copy, tag));
+
+ continue;
}
}
}
} SGEN_HASH_TABLE_FOREACH_END;
+
+ while (!sgen_pointer_queue_is_empty (&moved_fin_objects)) {
+ sgen_hash_table_replace (hash_table, sgen_pointer_queue_pop (&moved_fin_objects), NULL, NULL);
+ }
+
+ sgen_pointer_queue_free (&moved_fin_objects);
}
/* LOCKING: requires that the GC lock is held */
gboolean have_split_nursery = FALSE;
gboolean cement_enabled = TRUE;
+ mono_counters_init ();
+
do {
result = InterlockedCompareExchange (&gc_initialized, -1, 0);
switch (result) {
INTERNAL_MEM_TOGGLEREF_DATA,
INTERNAL_MEM_CARDTABLE_MOD_UNION,
INTERNAL_MEM_BINARY_PROTOCOL,
+ INTERNAL_MEM_TEMPORARY,
INTERNAL_MEM_MAX
};
case INTERNAL_MEM_TOGGLEREF_DATA: return "toggleref-data";
case INTERNAL_MEM_CARDTABLE_MOD_UNION: return "cardtable-mod-union";
case INTERNAL_MEM_BINARY_PROTOCOL: return "binary-protocol";
+ case INTERNAL_MEM_TEMPORARY: return "temporary";
default:
g_assert_not_reached ();
}
sgen_init_pinning (void)
{
memset (pin_hash_filter, 0, sizeof (pin_hash_filter));
+ pin_queue.mem_type = INTERNAL_MEM_PIN_QUEUE;
}
void
queue->next_slot = 0;
}
+void
+sgen_pointer_queue_init (SgenPointerQueue *queue, int mem_type)
+{
+ queue->next_slot = 0;
+ queue->size = 0;
+ queue->data = NULL;
+ queue->mem_type = mem_type;
+}
+
static void
realloc_queue (SgenPointerQueue *queue)
{
size_t new_size = queue->size ? queue->size + queue->size/2 : 1024;
- void **new_data = sgen_alloc_internal_dynamic (sizeof (void*) * new_size, INTERNAL_MEM_PIN_QUEUE, TRUE);
+ void **new_data = sgen_alloc_internal_dynamic (sizeof (void*) * new_size, queue->mem_type, TRUE);
+
memcpy (new_data, queue->data, sizeof (void*) * queue->next_slot);
- sgen_free_internal_dynamic (queue->data, sizeof (void*) * queue->size, INTERNAL_MEM_PIN_QUEUE);
+ sgen_free_internal_dynamic (queue->data, sizeof (void*) * queue->size, queue->mem_type);
queue->data = new_data;
queue->size = new_size;
SGEN_LOG (4, "Reallocated pointer queue to size: %lu", new_size);
queue->data [queue->next_slot++] = ptr;
}
+void*
+sgen_pointer_queue_pop (SgenPointerQueue *queue)
+{
+ g_assert (queue->next_slot);
+
+ return queue->data [--queue->next_slot];
+}
+
size_t
sgen_pointer_queue_search (SgenPointerQueue *queue, void *addr)
{
return (size_t)-1;
}
+gboolean
+sgen_pointer_queue_is_empty (SgenPointerQueue *queue)
+{
+ return !queue->next_slot;
+}
+
+void
+sgen_pointer_queue_free (SgenPointerQueue *queue)
+{
+ sgen_free_internal_dynamic (queue->data, sizeof (void*) * queue->size, queue->mem_type);
+}
+
#endif
#ifndef __MONO_SGEN_POINTER_QUEUE_H__
#define __MONO_SGEN_POINTER_QUEUE_H__
+#include <glib.h>
+
typedef struct {
void **data;
size_t size;
size_t next_slot;
+ int mem_type;
} SgenPointerQueue;
void sgen_pointer_queue_add (SgenPointerQueue *queue, void *ptr) MONO_INTERNAL;
void sgen_pointer_queue_sort_uniq (SgenPointerQueue *queue) MONO_INTERNAL;
size_t sgen_pointer_queue_search (SgenPointerQueue *queue, void *addr) MONO_INTERNAL;
size_t sgen_pointer_queue_find (SgenPointerQueue *queue, void *ptr) MONO_INTERNAL;
+void sgen_pointer_queue_init (SgenPointerQueue *queue, int mem_type) MONO_INTERNAL;
+void* sgen_pointer_queue_pop (SgenPointerQueue *queue) MONO_INTERNAL;
+gboolean sgen_pointer_queue_is_empty (SgenPointerQueue *queue) MONO_INTERNAL;
+void sgen_pointer_queue_free (SgenPointerQueue *queue) MONO_INTERNAL;
#endif
#ifndef DISABLE_SOCKETS
-#ifdef __APPLE__
+#if defined(__APPLE__) || defined(__FreeBSD__)
#define __APPLE_USE_RFC_3542
#endif
#define AI_ADDRCONFIG 0
#endif
-#ifdef __APPLE__
+#if defined(__APPLE__) || defined(__FreeBSD__)
/*
* We remove this until we have a Darwin implementation
* that can walk the result of struct ifconf. The current
#endif /* AF_INET6 */
#endif
-#if defined(__APPLE__)
+#if defined(__APPLE__) || defined(__FreeBSD__)
#if defined(HAVE_GETIFADDRS) && defined(HAVE_IF_NAMETOINDEX)
static int
}
#endif
-#endif /* __APPLE__ */
+#endif /* defined(__APPLE__) || defined(__FreeBSD__) */
void ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal(SOCKET sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val, gint32 *error)
{
field=mono_class_get_field_from_name(obj_val->vtable->klass, "ifIndex");
mreq6.ipv6mr_interface =*(guint64 *)(((char *)obj_val)+field->offset);
-#if defined(__APPLE__)
+#if defined(__APPLE__) || defined(__FreeBSD__)
/*
* Bug #5504:
*
*/
data.last_frame_set = FALSE;
if (sigctx) {
- mono_arch_sigctx_to_monoctx (sigctx, &ctx);
+ mono_sigctx_to_monoctx (sigctx, &ctx);
/*
* Don't pass MONO_UNWIND_ACTUAL_METHOD, its not signal safe, and
* get_last_frame () doesn't need it, the last frame cannot be a ginst
// clobbered by a single step/breakpoint event. If this turns out to be a problem,
// clob:c could be added to op_seq_point.
- mono_arch_sigctx_to_monoctx (sigctx, &ctx);
+ mono_sigctx_to_monoctx (sigctx, &ctx);
memcpy (&tls->handler_ctx, &ctx, sizeof (MonoContext));
#ifdef MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX
mono_arch_setup_resume_sighandler_ctx (&ctx, func);
#else
MONO_CONTEXT_SET_IP (&ctx, func);
#endif
- mono_arch_monoctx_to_sigctx (&ctx, sigctx);
+ mono_monoctx_to_sigctx (&ctx, sigctx);
#ifdef PPC_USES_FUNCTION_DESCRIPTOR
mono_ppc_set_func_into_sigctx (sigctx, func);
*/
MonoContext ctx;
- mono_arch_sigctx_to_monoctx (sigctx, &ctx);
+ mono_sigctx_to_monoctx (sigctx, &ctx);
mono_arch_skip_single_step (&ctx);
- mono_arch_monoctx_to_sigctx (&ctx, sigctx);
+ mono_monoctx_to_sigctx (&ctx, sigctx);
return;
}
g_set_prgname (argv[i]);
}
+ mono_counters_init ();
+
if (enable_profile)
mono_profiler_load (profile_options);
MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
/* Pass the ctx parameter in TLS */
- mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
+ mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
mctx = jit_tls->ex_ctx;
mono_arch_setup_async_callback (&mctx, handle_signal_exception, obj);
#else
MonoContext mctx;
- mono_arch_sigctx_to_monoctx (sigctx, &mctx);
+ mono_sigctx_to_monoctx (sigctx, &mctx);
mono_handle_exception (&mctx, obj);
- mono_arch_monoctx_to_sigctx (&mctx, sigctx);
+ mono_monoctx_to_sigctx (&mctx, sigctx);
return TRUE;
#endif
}
-void
-mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
-{
- mono_sigctx_to_monoctx (sigctx, mctx);
-}
-
-void
-mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
-{
- mono_monoctx_to_sigctx (mctx, sigctx);
-}
-
gpointer
mono_arch_ip_from_context (void *sigctx)
{
return FALSE;
}
-#if MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
-void
-mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
-{
- mono_sigctx_to_monoctx (sigctx, mctx);
-}
-
-void
-mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx)
-{
- mono_monoctx_to_sigctx (mctx, ctx);
-}
-#endif /* MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX */
-
/*
* handle_exception:
*
guint64 sp = UCONTEXT_REG_SP (sigctx);
/* Pass the ctx parameter in TLS */
- mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
+ mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
/* The others in registers */
UCONTEXT_REG_R0 (sigctx) = (gsize)obj;
MonoContext mctx;
gboolean result;
- mono_arch_sigctx_to_monoctx (ctx, &mctx);
+ mono_sigctx_to_monoctx (ctx, &mctx);
result = mono_handle_exception (&mctx, obj);
/* restore the context so that returning from the signal handler will invoke
* the catch clause
*/
- mono_arch_monoctx_to_sigctx (&mctx, ctx);
+ mono_monoctx_to_sigctx (&mctx, ctx);
return result;
#endif
}
return FALSE;
}
-void
-mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
-{
- mono_sigctx_to_monoctx (sigctx, mctx);
-}
-
-void
-mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
-{
- mono_monoctx_to_sigctx (mctx, sigctx);
-}
-
gpointer
mono_arch_ip_from_context (void *sigctx)
{
guint64 sp = UCONTEXT_GREGS (sigctx) [mips_sp];
/* Pass the ctx parameter in TLS */
- mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
+ mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
/* The others in registers */
UCONTEXT_GREGS (sigctx)[mips_a0] = (gsize)obj;
MonoContext mctx;
gboolean result;
- mono_arch_sigctx_to_monoctx (ctx, &mctx);
+ mono_sigctx_to_monoctx (ctx, &mctx);
result = mono_handle_exception (&mctx, obj);
/* restore the context so that returning from the signal handler will invoke
* the catch clause
*/
- mono_arch_monoctx_to_sigctx (&mctx, ctx);
+ mono_monoctx_to_sigctx (&mctx, ctx);
return result;
#endif
}
return FALSE;
}
-/*
- * This is the function called from the signal handler
- */
-void
-mono_arch_sigctx_to_monoctx (void *ctx, MonoContext *mctx)
-{
-#ifdef MONO_CROSS_COMPILE
- g_assert_not_reached ();
-#else
- os_ucontext *uc = ctx;
-
- mctx->sc_ir = UCONTEXT_REG_NIP(uc);
- mctx->sc_sp = UCONTEXT_REG_Rn(uc, 1);
- memcpy (&mctx->regs, &UCONTEXT_REG_Rn(uc, 13), sizeof (mgreg_t) * MONO_SAVED_GREGS);
- memcpy (&mctx->fregs, &UCONTEXT_REG_FPRn(uc, 14), sizeof (double) * MONO_SAVED_FREGS);
-#endif
-}
-
-void
-mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx)
-{
-#ifdef MONO_CROSS_COMPILE
- g_assert_not_reached ();
-#else
- os_ucontext *uc = ctx;
-
- UCONTEXT_REG_NIP(uc) = mctx->sc_ir;
- UCONTEXT_REG_Rn(uc, 1) = mctx->sc_sp;
- memcpy (&UCONTEXT_REG_Rn(uc, 13), &mctx->regs, sizeof (mgreg_t) * MONO_SAVED_GREGS);
- memcpy (&UCONTEXT_REG_FPRn(uc, 14), &mctx->fregs, sizeof (double) * MONO_SAVED_FREGS);
-#endif
-}
-
gpointer
mono_arch_ip_from_context (void *sigctx)
{
{
MonoContext mctx;
- mono_arch_sigctx_to_monoctx (sigctx, &mctx);
+ mono_sigctx_to_monoctx (sigctx, &mctx);
mono_handle_exception (&mctx, obj);
mono_restore_context (&mctx);
}
void *uc = sigctx;
/* Pass the ctx parameter in TLS */
- mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
+ mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
/* The others in registers */
UCONTEXT_REG_Rn (sigctx, PPC_FIRST_ARG_REG) = (gsize)obj;
MonoContext mctx;
gboolean result;
- mono_arch_sigctx_to_monoctx (ctx, &mctx);
+ mono_sigctx_to_monoctx (ctx, &mctx);
result = mono_handle_exception (&mctx, obj);
/* restore the context so that returning from the signal handler will invoke
* the catch clause
*/
- mono_arch_monoctx_to_sigctx (&mctx, ctx);
+ mono_monoctx_to_sigctx (&mctx, ctx);
return result;
#endif
}
/*========================= End of Function ========================*/
-/*------------------------------------------------------------------*/
-/* */
-/* Name - mono_arch_sigctx_to_monoctx. */
-/* */
-/* Function - Called from the signal handler to convert signal */
-/* context to MonoContext. */
-/* */
-/*------------------------------------------------------------------*/
-
-void
-mono_arch_sigctx_to_monoctx (void *ctx, MonoContext *mctx)
-{
- mono_sigctx_to_monoctx(ctx, mctx);
-}
-
-/*========================= End of Function ========================*/
-
-/*------------------------------------------------------------------*/
-/* */
-/* Name - mono_arch_monoctx_to_sigctx. */
-/* */
-/* Function - Convert MonoContext structure to signal context. */
-/* */
-/*------------------------------------------------------------------*/
-
-void
-mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx)
-{
- mono_monoctx_to_sigctx(mctx, ctx);
-}
-
-/*========================= End of Function ========================*/
-
/*------------------------------------------------------------------*/
/* */
/* Name - mono_arch_ip_from_context */
guint32 free_stack = 0;
StackFrameInfo frame;
- /* convert sigcontext to MonoContext (due to reuse of stack walking helpers */
- mono_arch_sigctx_to_monoctx (sctx, &ctx);
+ mono_sigctx_to_monoctx (sctx, &ctx);
/* get our os page size */
GetSystemInfo(&si);
ctx = new_ctx;
} while (free_stack < 64 * 1024 && frame.ji != (gpointer) -1);
- /* convert into sigcontext to be used in mono_arch_handle_exception */
- mono_arch_monoctx_to_sigctx (&ctx, sctx);
+ mono_monoctx_to_sigctx (&ctx, sctx);
/* todo: install new stack-guard page */
if ((guint32)((*lmf)->previous_lmf) & 1) {
/* lmf->esp is set by the trampoline code */
new_ctx->esp = (*lmf)->esp;
-
- /* Pop arguments off the stack */
- /* FIXME: Handle the delegate case too ((*lmf)->method == NULL) */
- /* FIXME: Handle the IMT/vtable case too */
-#if 0
-#ifndef ENABLE_LLVM
- if ((*lmf)->method) {
- MonoMethod *method = (*lmf)->method;
- MonoJitArgumentInfo *arg_info = g_newa (MonoJitArgumentInfo, mono_method_signature (method)->param_count + 1);
-
- guint32 stack_to_pop = mono_arch_get_argument_info (NULL, mono_method_signature (method), mono_method_signature (method)->param_count, arg_info);
- new_ctx->esp += stack_to_pop;
- }
-#endif
-#endif
}
else
/* the lmf is always stored on the stack, so the following
return FALSE;
}
-void
-mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
-{
- mono_sigctx_to_monoctx (sigctx, mctx);
-}
-
-void
-mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
-{
- mono_monoctx_to_sigctx (mctx, sigctx);
-}
-
gpointer
mono_arch_ip_from_context (void *sigctx)
{
MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
/* Pass the ctx parameter in TLS */
- mono_arch_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx);
+ mono_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx);
mctx = jit_tls->ex_ctx;
mono_setup_async_callback (&mctx, handle_signal_exception, obj);
MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
struct sigcontext *ctx = (struct sigcontext *)sigctx;
- mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
+ mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
mctx = jit_tls->ex_ctx;
mono_setup_async_callback (&mctx, handle_signal_exception, obj);
#else
MonoContext mctx;
- mono_arch_sigctx_to_monoctx (sigctx, &mctx);
+ mono_sigctx_to_monoctx (sigctx, &mctx);
mono_handle_exception (&mctx, obj);
- mono_arch_monoctx_to_sigctx (&mctx, sigctx);
+ mono_monoctx_to_sigctx (&mctx, sigctx);
return TRUE;
#endif
save_cast_details (MonoCompile *cfg, MonoClass *klass, int obj_reg, gboolean null_check, MonoBasicBlock **out_bblock)
{
if (mini_get_debug_options ()->better_cast_details) {
- int to_klass_reg = alloc_preg (cfg);
int vtable_reg = alloc_preg (cfg);
int klass_reg = alloc_preg (cfg);
MonoBasicBlock *is_null_bb = NULL;
MonoInst *tls_get;
+ int to_klass_reg, context_used;
if (null_check) {
NEW_BBLOCK (cfg, is_null_bb);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, tls_get->dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, class_cast_from), klass_reg);
- MONO_EMIT_NEW_PCONST (cfg, to_klass_reg, klass);
+
+ context_used = mini_class_check_context_used (cfg, klass);
+ if (context_used) {
+ MonoInst *class_ins;
+
+ class_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
+ to_klass_reg = class_ins->dreg;
+ } else {
+ to_klass_reg = alloc_preg (cfg);
+ MONO_EMIT_NEW_CLASSCONST (cfg, to_klass_reg, klass);
+ }
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, tls_get->dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, class_cast_to), to_klass_reg);
if (null_check) {
save_cast_details (cfg, klass, args [0]->dreg, TRUE, out_bblock);
res = mono_emit_method_call (cfg, mono_castclass, args, NULL);
reset_cast_details (cfg);
+ *out_bblock = cfg->cbb;
return res;
}
/* cache */
args [2] = cache_ins;
- return emit_castclass_with_cache (cfg, klass, args, NULL);
+ return emit_castclass_with_cache (cfg, klass, args, out_bb);
}
klass_inst = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
typeof(Gen<>). */
context_used = 0;
} else if (handle_class == mono_defaults.typehandle_class) {
- /* If we get a MONO_TYPE_CLASS
- then we need to provide the
- open type, not an
- instantiation of it. */
- if (mono_type_get_type (handle) == MONO_TYPE_CLASS)
- context_used = 0;
- else
- context_used = mini_class_check_context_used (cfg, mono_class_from_mono_type (handle));
+ context_used = mini_class_check_context_used (cfg, mono_class_from_mono_type (handle));
} else if (handle_class == mono_defaults.fieldhandle_class)
context_used = mini_class_check_context_used (cfg, ((MonoClassField*)handle)->parent);
else if (handle_class == mono_defaults.methodhandle_class)
break;
case OP_STORER4_MEMBASE_REG:
/* This requires a double->single conversion */
- amd64_sse_cvtsd2ss_reg_reg (code, AMD64_XMM15, ins->sreg1);
- amd64_sse_movss_membase_reg (code, ins->inst_destbasereg, ins->inst_offset, AMD64_XMM15);
+ amd64_sse_cvtsd2ss_reg_reg (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
+ amd64_sse_movss_membase_reg (code, ins->inst_destbasereg, ins->inst_offset, MONO_ARCH_FP_SCRATCH_REG);
break;
case OP_LOADR4_MEMBASE:
amd64_sse_movss_reg_membase (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
break;
case OP_EXTRACT_I8:
if (ins->inst_c0) {
- amd64_movhlps_reg_reg (code, AMD64_XMM15, ins->sreg1);
- amd64_movd_reg_xreg_size (code, ins->dreg, AMD64_XMM15, 8);
+ amd64_movhlps_reg_reg (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
+ amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
} else {
amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
}
amd64_sse_pinsrw_reg_reg_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
break;
case OP_INSERTX_I8_SLOW:
- amd64_movd_xreg_reg_size(code, AMD64_XMM15, ins->sreg2, 8);
+ amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
if (ins->inst_c0)
- amd64_movlhps_reg_reg (code, ins->dreg, AMD64_XMM15);
+ amd64_movlhps_reg_reg (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
else
- amd64_sse_movsd_reg_reg (code, ins->dreg, AMD64_XMM15);
+ amd64_sse_movsd_reg_reg (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
break;
case OP_INSERTX_R4_SLOW:
int reg;
gint64 value;
- mono_arch_sigctx_to_monoctx (sigctx, &ctx);
+ mono_sigctx_to_monoctx (sigctx, &ctx);
rip = (guint8*)ctx.rip;
#define MONO_ARCH_FP_RETURN_REG AMD64_XMM0
-/* xmm15 is reserved for use by some opcodes */
+#ifdef TARGET_WIN32
+/* xmm5 is used as a scratch register */
+#define MONO_ARCH_CALLEE_FREGS 0x1f
+/* xmm6:xmm15 */
+#define MONO_ARCH_CALLEE_SAVED_FREGS (0xffff - 0x3f)
+#define MONO_ARCH_FP_SCRATCH_REG AMD64_XMM5
+#else
+/* xmm15 is used as a scratch register */
#define MONO_ARCH_CALLEE_FREGS 0x7fff
#define MONO_ARCH_CALLEE_SAVED_FREGS 0
+#define MONO_ARCH_FP_SCRATCH_REG AMD64_XMM15
+#endif
#define MONO_MAX_XREGS MONO_MAX_FREGS
-#define MONO_ARCH_CALLEE_XREGS 0x7fff
-#define MONO_ARCH_CALLEE_SAVED_XREGS 0
+#define MONO_ARCH_CALLEE_XREGS MONO_ARCH_CALLEE_FREGS
+#define MONO_ARCH_CALLEE_SAVED_XREGS MONO_ARCH_CALLEE_SAVED_FREGS
#define MONO_ARCH_CALLEE_REGS AMD64_CALLEE_REGS
#ifdef MONO_CROSS_COMPILE
#elif __APPLE__
sys_icache_invalidate (code, size);
+#elif __GNUC_PREREQ(4, 3)
+ __builtin___clear_cache (code, code + size);
#elif __GNUC_PREREQ(4, 1)
__clear_cache (code, code + size);
#elif defined(PLATFORM_ANDROID)
mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
- mono_arch_sigctx_to_monoctx (ctx, &mctx);
+ mono_sigctx_to_monoctx (ctx, &mctx);
mono_runtime_printf_err ("Stacktrace:");
#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
MonoContext ctx;
#endif
- GString* text = g_string_new (0);
+ GString* text;
char *name;
#ifndef HOST_WIN32
char *wapi_desc;
#endif
GError *error = NULL;
+ if (!thread)
+ return;
+
+ text = g_string_new (0);
if (thread->name) {
name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
g_assert (!error);
} else if (!sigctx)
MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
else
- mono_arch_sigctx_to_monoctx (sigctx, &ctx);
+ mono_sigctx_to_monoctx (sigctx, &ctx);
mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
#else
}
if (sigctx)
- mono_arch_sigctx_to_monoctx (sigctx, &ctx->ctx);
+ mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
else
#if MONO_ARCH_HAS_MONO_CONTEXT && !defined(MONO_CROSS_COMPILE)
MONO_CONTEXT_GET_CURRENT (ctx->ctx);
tls->unwind_state.unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
if (sigctx) {
#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
- mono_arch_sigctx_to_monoctx (sigctx, &tls->unwind_state.ctx);
+ mono_sigctx_to_monoctx (sigctx, &tls->unwind_state.ctx);
tls->unwind_state.valid = TRUE;
#else
tls->unwind_state.valid = FALSE;
#else
-static int
-get_stage2_signal_handler (void)
-{
-#if defined(PLATFORM_ANDROID)
- return SIGINFO;
-#elif !defined (SIGRTMIN)
-#ifdef SIGUSR2
- return SIGUSR2;
-#else
- return -1;
-#endif /* SIGUSR2 */
-#else
- static int prof2_signum = -1;
- int i;
- if (prof2_signum != -1)
- return prof2_signum;
- /* we try to avoid SIGRTMIN and any one that might have been set already */
- for (i = SIGRTMIN + 2; i < SIGRTMAX; ++i) {
- struct sigaction sinfo;
- sigaction (i, NULL, &sinfo);
- if (sinfo.sa_handler == SIG_DFL && (void*)sinfo.sa_sigaction == (void*)SIG_DFL) {
- prof2_signum = i;
- return i;
- }
- }
- /* fallback to the old way */
- return SIGRTMIN + 2;
-#endif
-}
-
+static int profiling_signal_in_use;
static void
per_thread_profiler_hit (void *ctx)
MonoContext mono_context;
guchar *ips [call_chain_depth + 1];
- mono_arch_sigctx_to_monoctx (ctx, &mono_context);
+ mono_sigctx_to_monoctx (ctx, &mono_context);
ips [0] = MONO_CONTEXT_GET_IP (&mono_context);
if (jit_tls != NULL) {
}
}
-MONO_SIG_HANDLER_FUNC (static, sigprof_stage2_signal_handler)
-{
- MONO_SIG_HANDLER_GET_CONTEXT;
-
- per_thread_profiler_hit (ctx);
-
- mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
-}
-
MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
{
MonoThreadInfo *info;
int old_errno = errno;
- int hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
+ int hp_save_index;
MONO_SIG_HANDLER_GET_CONTEXT;
- FOREACH_THREAD_SAFE (info) {
- if (mono_thread_info_get_tid (info) == mono_native_thread_id_get ())
- continue;
- mono_threads_pthread_kill (info, get_stage2_signal_handler ());
- } END_FOREACH_THREAD_SAFE;
+ if (mono_thread_info_get_small_id () == -1)
+ return; //an non-attached thread got the signal
+
+ hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
+
+ /* If we can't consume a profiling request it means we're the initiator. */
+ if (!(mono_threads_consume_async_jobs () & MONO_SERVICE_REQUEST_SAMPLE)) {
+ FOREACH_THREAD_SAFE (info) {
+ if (mono_thread_info_get_tid (info) == mono_native_thread_id_get ())
+ continue;
+
+ mono_threads_add_async_job (info, MONO_SERVICE_REQUEST_SAMPLE);
+ mono_threads_pthread_kill (info, profiling_signal_in_use);
+ } END_FOREACH_THREAD_SAFE;
+ }
+ mono_thread_info_set_is_async_context (TRUE);
per_thread_profiler_hit (ctx);
+ mono_thread_info_set_is_async_context (FALSE);
mono_hazard_pointer_restore_for_signal_handler (hp_save_index);
errno = old_errno;
perror ("open /dev/rtc");
return;
}
- add_signal_handler (SIGPROF, sigprof_signal_handler);
+ profiling_signal_in_use = SIGPROF;
+ add_signal_handler (profiling_signal_in_use, sigprof_signal_handler);
if (ioctl (rtc_fd, RTC_IRQP_SET, freq) == -1) {
perror ("set rtc freq");
return;
if (inited)
return;
inited = 1;
- add_signal_handler (get_itimer_signal (), sigprof_signal_handler);
- add_signal_handler (get_stage2_signal_handler (), sigprof_stage2_signal_handler);
+ profiling_signal_in_use = get_itimer_signal ();
+ add_signal_handler (profiling_signal_in_use, sigprof_signal_handler);
setitimer (get_itimer_mode (), &itval, NULL);
#endif
}
MonoContext ctx;
guint8* ip;
- mono_arch_sigctx_to_monoctx (sigctx, &ctx);
+ mono_sigctx_to_monoctx (sigctx, &ctx);
ip = (guint8*)ctx.eip;
if (fault_addr == NULL) {
MonoContext mctx;
- mono_arch_sigctx_to_monoctx (ctx, &mctx);
+ mono_sigctx_to_monoctx (ctx, &mctx);
fault_addr = MONO_CONTEXT_GET_SP (&mctx);
}
gboolean mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr) MONO_INTERNAL;
void mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr) MONO_INTERNAL;
gpointer mono_arch_ip_from_context (void *sigctx) MONO_INTERNAL;
-void mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *ctx) MONO_INTERNAL;
-void mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx) MONO_INTERNAL;
mgreg_t mono_arch_context_get_int_reg (MonoContext *ctx, int reg) MONO_INTERNAL;
void mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val) MONO_INTERNAL;
void mono_arch_flush_register_windows (void) MONO_INTERNAL;
mono_domain_unlock (domain);
} else {
code = buf = mono_global_codeman_reserve (size);
+ short_branch = FALSE;
}
#ifdef USE_JUMP_TABLES
typedef struct _Counter Counter;
struct _Counter {
int index;
- int section;
+ const char *section;
const char *name;
int type;
int unit;
typedef struct _CounterSection CounterSection;
struct _CounterSection {
- int value;
+ const char *value;
CounterList *counters;
CounterList *counters_last;
CounterSection *next;
clist->counter = counter;
for (csection = counters_sections; csection; csection = csection->next) {
- if (csection->value == counter->section) {
+ if (strcmp (csection->value, counter->section) == 0) {
/* If section exist */
if (!csection->counters)
csection->counters = clist;
}
static void
-add_counter (int section, const char *name, int type, int unit, int variance, int index)
+add_counter (const char *section, const char *name, int type, int unit, int variance, int index)
{
CounterList *list, *l;
Counter *counter;
for (ctimestamp = counters_timestamps; ctimestamp; ctimestamp = ctimestamp->next) {
if (ctimestamp->value == timestamp) {
for (csection = ctimestamp->sections; csection; csection = csection->next) {
- if (csection->value == counter->section) {
+ if (strcmp (csection->value, counter->section) == 0) {
/* if timestamp exist and section exist */
if (!csection->counters)
csection->counters = clist;
for (i = 0; counters_to_print [i][0] != 0; i++) {
if (strcmp (counters_to_print [i], counter->name) == 0) {
if (!section_printed) {
- fprintf (outfile, "\t%s:\n", section_name (csection->value));
+ fprintf (outfile, "\t%s:\n", csection->value);
section_printed = 1;
}
(unsigned long long) (ctimestamp->value % 1000));
for (csection = ctimestamp->sections; csection; csection = csection->next) {
- fprintf (outfile, "\t\t%s:\n", section_name (csection->value));
+ fprintf (outfile, "\t\t%s:\n", csection->value);
for (clist = csection->counters; clist; clist = clist->next) {
counter = clist->counter;
}
} else if (counters_sort_mode == COUNTERS_SORT_CATEGORY) {
for (csection = counters_sections; csection; csection = csection->next) {
- fprintf (outfile, "\t%s:\n", section_name (csection->value));
+ fprintf (outfile, "\t%s:\n", csection->value);
for (clist = csection->counters; clist; clist = clist->next) {
counter = clist->counter;
for (i = 0; i < len; i++) {
uint64_t type, unit, variance, index;
uint64_t section = decode_uleb128 (p, &p);
- char *name = pstrdup ((char*)p);
+ char *section_str, *name;
+ if (section != MONO_COUNTER_PERFCOUNTERS) {
+ section_str = (char*) section_name (section);
+ } else {
+ section_str = pstrdup ((char*)p);
+ while (*p++);
+ }
+ name = pstrdup ((char*)p);
while (*p++);
type = decode_uleb128 (p, &p);
unit = decode_uleb128 (p, &p);
variance = decode_uleb128 (p, &p);
index = decode_uleb128 (p, &p);
- add_counter ((int)section, name, (int)type, (int)unit, (int)variance, (int)index);
+ add_counter (section_str, name, (int)type, (int)unit, (int)variance, (int)index);
}
} else if (subtype == TYPE_SAMPLE_COUNTERS) {
int i;
#include <mono/metadata/threads.h>
#include <mono/metadata/mono-gc.h>
#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/mono-perfcounters.h>
#include <mono/utils/atomic.h>
#include <mono/utils/mono-membar.h>
#include <mono/utils/mono-counters.h>
+#include <mono/utils/mono-mutex.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
* if exinfo == TYPE_SAMPLE_COUNTERS_DESC
* [len: uleb128] number of counters
* for i = 0 to len
- * [section: uleb128] section name of counter
+ * [section: uleb128] section of counter
+ * if section == MONO_COUNTER_PERFCOUNTERS:
+ * [section_name: string] section name of counter
* [name: string] name of counter
- * [type: uleb128] type name of counter
- * [unit: uleb128] unit name of counter
- * [variance: uleb128] variance name of counter
+ * [type: uleb128] type of counter
+ * [unit: uleb128] unit of counter
+ * [variance: uleb128] variance of counter
* [index: uleb128] unique index of counter
* if exinfo == TYPE_SAMPLE_COUNTERS
* [timestamp: uleb128] sampling timestamp
}
static void counters_init (MonoProfiler *profiler);
+static void counters_sample (MonoProfiler *profiler, uint64_t timestamp);
static void
runtime_initialized (MonoProfiler *profiler)
runtime_inited = 1;
#ifndef DISABLE_HELPER_THREAD
counters_init (profiler);
+ counters_sample (profiler, 0);
#endif
/* ensure the main thread data and startup are available soon */
safe_dump (profiler, ensure_logbuf (0));
* event, hence the collect_bt/emit_bt split.
*/
static void
-collect_bt (FrameData *data, gboolean async_safe)
+collect_bt (FrameData *data)
{
data->count = 0;
- if (async_safe)
- mono_stack_walk_async_safe (walk_stack, data);
- else
- mono_stack_walk_no_il (walk_stack, data);
+ mono_stack_walk_no_il (walk_stack, data);
}
static void
len += 7;
len &= ~7;
if (do_bt)
- collect_bt (&data, FALSE);
+ collect_bt (&data);
logbuffer = ensure_logbuf (32 + MAX_FRAMES * 8);
now = current_time ();
ENTER_LOG (logbuffer, "gcalloc");
FrameData data;
LogBuffer *logbuffer;
if (do_bt)
- collect_bt (&data, FALSE);
+ collect_bt (&data);
logbuffer = ensure_logbuf (16 + MAX_FRAMES * 8);
now = current_time ();
ENTER_LOG (logbuffer, "throw");
FrameData data;
LogBuffer *logbuffer;
if (do_bt)
- collect_bt (&data, FALSE);
+ collect_bt (&data);
logbuffer = ensure_logbuf (16 + MAX_FRAMES * 8);
now = current_time ();
ENTER_LOG (logbuffer, "monitor");
EXIT_LOG (logbuffer);
}
+typedef struct {
+ MonoMethod *method;
+ MonoDomain *domain;
+ void *base_address;
+ int offset;
+} AsyncFrameInfo;
+
+typedef struct {
+ int count;
+ AsyncFrameInfo *data;
+} AsyncFrameData;
+
+static mono_bool
+async_walk_stack (MonoMethod *method, MonoDomain *domain, void *base_address, int offset, void *data)
+{
+ AsyncFrameData *frame = data;
+ if (frame->count < num_frames) {
+ frame->data [frame->count].method = method;
+ frame->data [frame->count].domain = domain;
+ frame->data [frame->count].base_address = base_address;
+ frame->data [frame->count].offset = offset;
+ // printf ("In %d at %p (dom %p) (native: %p)\n", frame->count, method, domain, base_address);
+ frame->count++;
+ }
+ return frame->count == num_frames;
+}
+
+/*
+(type | frame count), tid, time, ip, [method, domain, base address, offset] * frames
+*/
+#define SAMPLE_EVENT_SIZE_IN_SLOTS(FRAMES) (4 + (FRAMES) * 4)
+
static void
mono_sample_hit (MonoProfiler *profiler, unsigned char *ip, void *context)
{
StatBuffer *sbuf;
- FrameData bt_data;
+ AsyncFrameInfo frames [num_frames];
+ AsyncFrameData bt_data = { 0, &frames [0]};
uint64_t now;
uintptr_t *data, *new_data, *old_data;
uintptr_t elapsed;
if (in_shutdown)
return;
now = current_time ();
- collect_bt (&bt_data, TRUE);
+
+ mono_stack_walk_async_safe (&async_walk_stack, context, &bt_data);
+
elapsed = (now - profiler->startup_time) / 10000;
if (do_debug) {
int len;
}
do {
old_data = sbuf->data;
- new_data = old_data + 4 + bt_data.count * 3;
+ new_data = old_data + SAMPLE_EVENT_SIZE_IN_SLOTS (bt_data.count);
data = InterlockedCompareExchangePointer ((void * volatile*)&sbuf->data, new_data, old_data);
} while (data != old_data);
if (old_data >= sbuf->data_end)
old_data [2] = elapsed;
old_data [3] = (uintptr_t)ip;
for (i = 0; i < bt_data.count; ++i) {
- old_data [4+3*i] = (uintptr_t)bt_data.methods [i];
- old_data [4+3*i+1] = (uintptr_t)bt_data.il_offsets [i];
- old_data [4+3*i+2] = (uintptr_t)bt_data.native_offsets [i];
+ old_data [4 + 4 * i + 0] = (uintptr_t)frames [i].method;
+ old_data [4 + 4 * i + 1] = (uintptr_t)frames [i].domain;
+ old_data [4 + 4 * i + 2] = (uintptr_t)frames [i].base_address;
+ old_data [4 + 4 * i + 3] = (uintptr_t)frames [i].offset;
}
}
int count = sample [0] & 0xff;
int mbt_count = (sample [0] & 0xff00) >> 8;
int type = sample [0] >> 16;
- if (sample + count + 3 + mbt_count * 3 > sbuf->data)
+ uintptr_t *managed_sample_base = sample + count + 3;
+
+ if (sample + SAMPLE_EVENT_SIZE_IN_SLOTS (mbt_count) > sbuf->data)
break;
+
+ for (i = 0; i < mbt_count; ++i) {
+ MonoMethod *method = (MonoMethod*)managed_sample_base [i * 4 + 0];
+ MonoDomain *domain = (MonoDomain*)managed_sample_base [i * 4 + 1];
+ void *address = (void*)managed_sample_base [i * 4 + 2];
+
+ if (!method) {
+ MonoJitInfo *ji = mono_jit_info_table_find (domain, address);
+ if (ji)
+ managed_sample_base [i * 4 + 0] = (uintptr_t)mono_jit_info_get_method (ji);
+ }
+ }
logbuffer = ensure_logbuf (20 + count * 8);
emit_byte (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_HIT);
emit_value (logbuffer, type);
emit_ptr (logbuffer, (void*)sample [i + 3]);
add_code_pointer (sample [i + 3]);
}
+
sample += count + 3;
/* new in data version 6 */
emit_uvalue (logbuffer, mbt_count);
for (i = 0; i < mbt_count; ++i) {
- emit_method (logbuffer, (void*)sample [i * 3]); /* method */
- emit_svalue (logbuffer, sample [i * 3 + 1]); /* il offset */
- emit_svalue (logbuffer, sample [i * 3 + 2]); /* native offset */
+ emit_method (logbuffer, (void*)sample [i * 4]); /* method */
+ emit_svalue (logbuffer, 0); /* il offset will always be 0 from now on */
+ emit_svalue (logbuffer, sample [i * 4 + 3]); /* native offset */
}
- sample += 3 * mbt_count;
+ sample += 4 * mbt_count;
}
dump_unmanaged_coderefs (prof);
}
void *value;
size_t value_size;
short index;
+ short emitted;
struct MonoCounterAgent *next;
} MonoCounterAgent;
static MonoCounterAgent* counters;
static gboolean counters_initialized = FALSE;
static int counters_index = 1;
+static mono_mutex_t counters_mutex;
-static mono_bool
-counters_init_add_counter (MonoCounter *counter, gpointer data)
+static void
+counters_add_agent (MonoCounter *counter)
{
MonoCounterAgent *agent, *item;
+ if (!counters_initialized)
+ return;
+
+ mono_mutex_lock (&counters_mutex);
+
for (agent = counters; agent; agent = agent->next) {
- if (agent->counter == counter)
- return TRUE;
+ if (agent->counter == counter) {
+ agent->value_size = 0;
+ if (agent->value) {
+ free (agent->value);
+ agent->value = NULL;
+ }
+ mono_mutex_unlock (&counters_mutex);
+ return;
+ }
}
agent = malloc (sizeof (MonoCounterAgent));
agent->value = NULL;
agent->value_size = 0;
agent->index = counters_index++;
+ agent->emitted = 0;
agent->next = NULL;
if (!counters) {
item->next = agent;
}
+ mono_mutex_unlock (&counters_mutex);
+}
+
+static mono_bool
+counters_init_foreach_callback (MonoCounter *counter, gpointer data)
+{
+ counters_add_agent (counter);
return TRUE;
}
static void
counters_init (MonoProfiler *profiler)
+{
+ assert (!counters_initialized);
+
+ mono_mutex_init (&counters_mutex);
+
+ counters_initialized = TRUE;
+
+ mono_counters_on_register (&counters_add_agent);
+ mono_counters_foreach (counters_init_foreach_callback, NULL);
+}
+
+static void
+counters_emit (MonoProfiler *profiler)
{
MonoCounterAgent *agent;
LogBuffer *logbuffer;
int size = 1 + 5, len = 0;
- mono_counters_foreach (counters_init_add_counter, NULL);
+ if (!counters_initialized)
+ return;
+
+ mono_mutex_lock (&counters_mutex);
for (agent = counters; agent; agent = agent->next) {
+ if (agent->emitted)
+ continue;
+
size += strlen (mono_counter_get_name (agent->counter)) + 1 + 5 * 5;
len += 1;
}
+ if (!len) {
+ mono_mutex_unlock (&counters_mutex);
+ return;
+ }
+
logbuffer = ensure_logbuf (size);
ENTER_LOG (logbuffer, "counters");
emit_byte (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
emit_value (logbuffer, len);
for (agent = counters; agent; agent = agent->next) {
+ if (agent->emitted)
+ continue;
+
const char *name = mono_counter_get_name (agent->counter);
emit_value (logbuffer, mono_counter_get_section (agent->counter));
emit_string (logbuffer, name, strlen (name) + 1);
emit_value (logbuffer, mono_counter_get_unit (agent->counter));
emit_value (logbuffer, mono_counter_get_variance (agent->counter));
emit_value (logbuffer, agent->index);
+
+ agent->emitted = 1;
}
EXIT_LOG (logbuffer);
- counters_initialized = TRUE;
+ safe_dump (profiler, ensure_logbuf (0));
+
+ mono_mutex_unlock (&counters_mutex);
}
static void
if (!counters_initialized)
return;
+ counters_emit (profiler);
+
buffer_size = 8;
buffer = calloc (1, buffer_size);
+ mono_mutex_lock (&counters_mutex);
+
size = 1 + 10 + 5;
for (agent = counters; agent; agent = agent->next)
size += 10 * 2 + mono_counter_get_size (agent->counter);
EXIT_LOG (logbuffer);
safe_dump (profiler, ensure_logbuf (0));
+
+ mono_mutex_unlock (&counters_mutex);
+}
+
+typedef struct _PerfCounterAgent PerfCounterAgent;
+struct _PerfCounterAgent {
+ PerfCounterAgent *next;
+ int index;
+ char *category_name;
+ char *name;
+ int type;
+ gint64 value;
+ guint8 emitted;
+ guint8 updated;
+ guint8 deleted;
+};
+
+static PerfCounterAgent *perfcounters = NULL;
+
+static void
+perfcounters_emit (MonoProfiler *profiler)
+{
+ PerfCounterAgent *pcagent;
+ LogBuffer *logbuffer;
+ int size = 1 + 5, len = 0;
+
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ if (pcagent->emitted)
+ continue;
+
+ size += strlen (pcagent->name) + 1 + 5 * 5;
+ len += 1;
+ }
+
+ if (!len)
+ return;
+
+ logbuffer = ensure_logbuf (size);
+
+ ENTER_LOG (logbuffer, "perfcounters");
+ emit_byte (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
+ emit_value (logbuffer, len);
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ if (pcagent->emitted)
+ continue;
+
+ emit_value (logbuffer, MONO_COUNTER_PERFCOUNTERS);
+ emit_string (logbuffer, pcagent->category_name, strlen (pcagent->category_name) + 1);
+ emit_string (logbuffer, pcagent->name, strlen (pcagent->name) + 1);
+ emit_value (logbuffer, MONO_COUNTER_LONG);
+ emit_value (logbuffer, MONO_COUNTER_RAW);
+ emit_value (logbuffer, MONO_COUNTER_VARIABLE);
+ emit_value (logbuffer, pcagent->index);
+
+ pcagent->emitted = 1;
+ }
+ EXIT_LOG (logbuffer);
+
+ safe_dump (profiler, ensure_logbuf (0));
+}
+
+static gboolean
+perfcounters_foreach (char *category_name, char *name, unsigned char type, gint64 value, gpointer user_data)
+{
+ PerfCounterAgent *pcagent;
+
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ if (strcmp (pcagent->category_name, category_name) != 0 || strcmp (pcagent->name, name) != 0)
+ continue;
+ if (pcagent->value == value)
+ return TRUE;
+
+ pcagent->value = value;
+ pcagent->updated = 1;
+ pcagent->deleted = 0;
+ return TRUE;
+ }
+
+ pcagent = g_new0 (PerfCounterAgent, 1);
+ pcagent->next = perfcounters;
+ pcagent->index = counters_index++;
+ pcagent->category_name = g_strdup (category_name);
+ pcagent->name = g_strdup (name);
+ pcagent->type = (int) type;
+ pcagent->value = value;
+ pcagent->emitted = 0;
+ pcagent->updated = 1;
+ pcagent->deleted = 0;
+
+ perfcounters = pcagent;
+
+ return TRUE;
+}
+
+static void
+perfcounters_sample (MonoProfiler *profiler, uint64_t timestamp)
+{
+ PerfCounterAgent *pcagent;
+ LogBuffer *logbuffer;
+ int size;
+
+ if (!counters_initialized)
+ return;
+
+ mono_mutex_lock (&counters_mutex);
+
+ /* mark all perfcounters as deleted, foreach will unmark them as necessary */
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next)
+ pcagent->deleted = 1;
+
+ mono_perfcounter_foreach (perfcounters_foreach, perfcounters);
+
+ perfcounters_emit (profiler);
+
+
+ size = 1 + 10 + 5;
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ if (pcagent->deleted || !pcagent->updated)
+ continue;
+ size += 10 * 2 + sizeof (gint64);
+ }
+
+ logbuffer = ensure_logbuf (size);
+
+ ENTER_LOG (logbuffer, "perfcounters");
+ emit_byte (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE);
+ emit_uvalue (logbuffer, timestamp);
+ for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ if (pcagent->deleted || !pcagent->updated)
+ continue;
+ emit_uvalue (logbuffer, pcagent->index);
+ emit_uvalue (logbuffer, MONO_COUNTER_LONG);
+ emit_svalue (logbuffer, pcagent->value);
+
+ pcagent->updated = 0;
+ }
+
+ emit_value (logbuffer, 0);
+ EXIT_LOG (logbuffer);
+
+ safe_dump (profiler, ensure_logbuf (0));
+
+ mono_mutex_unlock (&counters_mutex);
+}
+
+static void
+counters_and_perfcounters_sample (MonoProfiler *prof)
+{
+ static uint64_t start = -1;
+ uint64_t now;
+
+ if (start == -1)
+ start = current_time ();
+
+ now = current_time ();
+ counters_sample (prof, (now - start) / 1000/ 1000);
+ perfcounters_sample (prof, (now - start) / 1000/ 1000);
}
#endif /* DISABLE_HELPER_THREAD */
{
in_shutdown = 1;
#ifndef DISABLE_HELPER_THREAD
+ counters_and_perfcounters_sample (prof);
+
if (prof->command_port) {
char c = 1;
void *res;
int len;
char buf [64];
MonoThread *thread = NULL;
- uint64_t start, now;
//fprintf (stderr, "Server listening\n");
- start = current_time ();
command_socket = -1;
while (1) {
fd_set rfds;
}
}
#endif
- now = current_time ();
- counters_sample (prof, (now - start) / 1000/ 1000);
+
+ counters_and_perfcounters_sample (prof);
tv.tv_sec = 1;
tv.tv_usec = 0;
sbufbase->next->next = NULL;
if (do_debug)
fprintf (stderr, "stat buffer dump\n");
- dump_sample_hits (prof, sbuf, 1);
- free_buffer (sbuf, sbuf->size);
- safe_dump (prof, ensure_logbuf (0));
+ if (sbuf) {
+ dump_sample_hits (prof, sbuf, 1);
+ free_buffer (sbuf, sbuf->size);
+ safe_dump (prof, ensure_logbuf (0));
+ }
continue;
}
/* time to shut down */
int fast_time = 0;
int calls_enabled = 0;
int allocs_enabled = 0;
+ int only_counters = 0;
int events = MONO_PROFILE_GC|MONO_PROFILE_ALLOCATIONS|
MONO_PROFILE_GC_MOVES|MONO_PROFILE_CLASS_EVENTS|MONO_PROFILE_THREADS|
MONO_PROFILE_ENTER_LEAVE|MONO_PROFILE_JIT_COMPILATION|MONO_PROFILE_EXCEPTIONS|
do_counters = 1;
continue;
}
+ if ((opt = match_option (p, "countersonly", NULL)) != p) {
+ only_counters = 1;
+ continue;
+ }
if (opt == p) {
usage (0);
exit (0);
}
if (allocs_enabled)
events |= MONO_PROFILE_ALLOCATIONS;
+ if (only_counters)
+ events = 0;
utils_init (fast_time);
prof = create_profiler (filename);
mono_profiler_install_runtime_initialized (runtime_initialized);
- if (do_mono_sample && sample_type == SAMPLE_CYCLES) {
+ if (do_mono_sample && sample_type == SAMPLE_CYCLES && !only_counters) {
events |= MONO_PROFILE_STATISTICAL;
mono_profiler_set_statistical_mode (sampling_mode, 1000000 / sample_freq);
mono_profiler_install_statistical (mono_sample_hit);
#define LOG_HEADER_ID 0x4D505A01
#define LOG_VERSION_MAJOR 0
#define LOG_VERSION_MINOR 4
-#define LOG_DATA_VERSION 6
+#define LOG_DATA_VERSION 7
/*
* Changes in data versions:
* version 2: added offsets in heap walk
return true;
}
+ class Gen<T>
+ {
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ public static void Run ()
+ {
+ }
+ }
+
public delegate int Delegate1 ();
static public int Main (String[] args) {
if (is_synchronized (b))
return 1;
+ Monitor.Enter (typeof (Gen<>));
+ Thread t = new Thread (() =>
+ {
+ Gen<object>.Run ();
+ });
+ t.Start ();
+ t.Join ();
+ Monitor.Exit (typeof (Gen<>));
+
return 0;
}
}
}
}
+#elif (((defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__)) && !defined(MONO_CROSS_COMPILE))) || (defined(TARGET_POWERPC))
+
+#include <mono/utils/mono-context.h>
+
+void
+mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
+{
+ os_ucontext *uc = sigctx;
+
+ mctx->sc_ir = UCONTEXT_REG_NIP(uc);
+ mctx->sc_sp = UCONTEXT_REG_Rn(uc, 1);
+ memcpy (&mctx->regs, &UCONTEXT_REG_Rn(uc, 13), sizeof (mgreg_t) * MONO_SAVED_GREGS);
+ memcpy (&mctx->fregs, &UCONTEXT_REG_FPRn(uc, 14), sizeof (double) * MONO_SAVED_FREGS);
+}
+
+void
+mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
+{
+ os_ucontext *uc = sigctx;
+
+ UCONTEXT_REG_NIP(uc) = mctx->sc_ir;
+ UCONTEXT_REG_Rn(uc, 1) = mctx->sc_sp;
+ memcpy (&UCONTEXT_REG_Rn(uc, 13), &mctx->regs, sizeof (mgreg_t) * MONO_SAVED_GREGS);
+ memcpy (&UCONTEXT_REG_FPRn(uc, 14), &mctx->fregs, sizeof (double) * MONO_SAVED_FREGS);
+}
+
#endif /* #if defined(__i386__) */
#include "config.h"
#include "mono-counters.h"
#include "mono-proclib.h"
+#include "mono-mutex.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
};
static MonoCounter *counters = NULL;
+static mono_mutex_t counters_mutex;
+
+static volatile gboolean initialized = FALSE;
+
static int valid_mask = 0;
static int set_mask = 0;
+static GSList *register_callbacks = NULL;
+
+static void initialize_system_counters (void);
+
/**
* mono_counter_get_variance:
* @counter: counter to get the variance
valid_mask = section_mask & MONO_COUNTER_SECTION_MASK;
}
+void
+mono_counters_init (void)
+{
+ if (initialized)
+ return;
+
+ mono_mutex_init (&counters_mutex);
+
+ initialize_system_counters ();
+
+ initialized = TRUE;
+}
+
+static void
+register_internal (const char *name, int type, void *addr, int size)
+{
+ MonoCounter *counter;
+ GSList *register_callback;
+
+ g_assert (size >= 0);
+ if ((type & MONO_COUNTER_VARIANCE_MASK) == 0)
+ type |= MONO_COUNTER_MONOTONIC;
+
+ mono_mutex_lock (&counters_mutex);
+
+ for (counter = counters; counter; counter = counter->next) {
+ if (counter->addr == addr) {
+ g_warning ("you are registering twice the same counter address");
+ mono_mutex_unlock (&counters_mutex);
+ return;
+ }
+ }
+
+ counter = malloc (sizeof (MonoCounter));
+ if (!counter) {
+ mono_mutex_unlock (&counters_mutex);
+ return;
+ }
+ counter->name = g_strdup (name);
+ counter->type = type;
+ counter->addr = addr;
+ counter->next = NULL;
+ counter->size = size;
+
+ set_mask |= type;
+
+ /* Append */
+ if (counters) {
+ MonoCounter *item = counters;
+ while (item->next)
+ item = item->next;
+ item->next = counter;
+ } else {
+ counters = counter;
+ }
+
+ for (register_callback = register_callbacks; register_callback; register_callback = register_callback->next)
+ ((MonoCounterRegisterCallback)register_callback->data) (counter);
+
+ mono_mutex_unlock (&counters_mutex);
+}
+
/**
* mono_counters_register:
* @name: The name for this counters.
default:
g_assert_not_reached ();
}
- mono_counters_register_with_size (name, type, addr, size);
+
+ if (!initialized)
+ g_warning ("counters not enabled");
+ else
+ register_internal (name, type, addr, size);
}
/**
void
mono_counters_register_with_size (const char *name, int type, void *addr, int size)
{
- MonoCounter *counter;
-
- if ((type & MONO_COUNTER_VARIANCE_MASK) == 0)
- type |= MONO_COUNTER_MONOTONIC;
- if (size < 0)
- size = 0;
+ if (!initialized)
+ g_warning ("counters not enabled");
+ else
+ register_internal (name, type, addr, size);
+}
- counter = malloc (sizeof (MonoCounter));
- if (!counter)
+/**
+ * mono_counters_on_register
+ * @callback : function to callback when a counter is registered
+ *
+ * Add a callback that is going to be called when a counter is registered
+ */
+void
+mono_counters_on_register (MonoCounterRegisterCallback callback)
+{
+ if (!initialized) {
+ g_warning ("counters not enabled");
return;
- counter->name = name;
- counter->type = type;
- counter->addr = addr;
- counter->next = NULL;
- counter->size = size;
-
- set_mask |= type;
-
- /* Append */
- if (counters) {
- MonoCounter *item = counters;
- while (item->next)
- item = item->next;
- item->next = counter;
- } else {
- counters = counter;
}
+
+ mono_mutex_lock (&counters_mutex);
+ register_callbacks = g_slist_append (register_callbacks, callback);
+ mono_mutex_unlock (&counters_mutex);
}
typedef int (*IntFunc) (void);
typedef double (*DoubleFunc) (void);
typedef char* (*StrFunc) (void);
-#define ENTRY_FMT "%-36s: "
-static void
-dump_counter (MonoCounter *counter, FILE *outfile) {
- void *buffer = g_malloc0 (counter->size);
- mono_counters_sample (counter, buffer, counter->size);
-
- switch (counter->type & MONO_COUNTER_TYPE_MASK) {
- case MONO_COUNTER_INT:
- fprintf (outfile, ENTRY_FMT "%d\n", counter->name, *(int*)buffer);
- break;
- case MONO_COUNTER_UINT:
- fprintf (outfile, ENTRY_FMT "%u\n", counter->name, *(guint*)buffer);
- break;
- case MONO_COUNTER_LONG:
- if ((counter->type & MONO_COUNTER_UNIT_MASK) == MONO_COUNTER_TIME)
- fprintf (outfile, ENTRY_FMT "%.2f ms\n", counter->name, (double)(*(gint64*)buffer) / 10000.0);
- else
- fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, *(long long *)buffer);
- break;
- case MONO_COUNTER_ULONG:
- fprintf (outfile, ENTRY_FMT "%llu\n", counter->name, *(unsigned long long *)buffer);
- break;
- case MONO_COUNTER_WORD:
- fprintf (outfile, ENTRY_FMT "%zd\n", counter->name, *(gssize*)buffer);
- break;
- case MONO_COUNTER_DOUBLE:
- fprintf (outfile, ENTRY_FMT "%.4f\n", counter->name, *(double*)buffer);
- break;
- case MONO_COUNTER_STRING:
- fprintf (outfile, ENTRY_FMT "%s\n", counter->name, (counter->size == 0) ? "(null)" : (char*)buffer);
- break;
- case MONO_COUNTER_TIME_INTERVAL:
- fprintf (outfile, ENTRY_FMT "%.2f ms\n", counter->name, (double)(*(gint64*)buffer) / 1000.0);
- break;
- }
-
- g_free (buffer);
-}
-
static gint64
user_time (void)
{
return cpu_load (2);
}
-static gboolean system_counters_initialized = FALSE;
-
#define SYSCOUNTER_TIME (MONO_COUNTER_SYSTEM | MONO_COUNTER_LONG | MONO_COUNTER_TIME | MONO_COUNTER_MONOTONIC | MONO_COUNTER_CALLBACK)
#define SYSCOUNTER_BYTES (MONO_COUNTER_SYSTEM | MONO_COUNTER_LONG | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE | MONO_COUNTER_CALLBACK)
#define SYSCOUNTER_COUNT (MONO_COUNTER_SYSTEM | MONO_COUNTER_LONG | MONO_COUNTER_COUNT | MONO_COUNTER_MONOTONIC | MONO_COUNTER_CALLBACK)
static void
initialize_system_counters (void)
{
- mono_counters_register ("User Time", SYSCOUNTER_TIME, &user_time);
- mono_counters_register ("System Time", SYSCOUNTER_TIME, &system_time);
- mono_counters_register ("Total Time", SYSCOUNTER_TIME, &total_time);
- mono_counters_register ("Working Set", SYSCOUNTER_BYTES, &working_set);
- mono_counters_register ("Private Bytes", SYSCOUNTER_BYTES, &private_bytes);
- mono_counters_register ("Virtual Bytes", SYSCOUNTER_BYTES, &virtual_bytes);
- mono_counters_register ("Page Faults", SYSCOUNTER_COUNT, &page_faults);
- mono_counters_register ("CPU Load Average - 1min", SYSCOUNTER_LOAD, &cpu_load_1min);
- mono_counters_register ("CPU Load Average - 5min", SYSCOUNTER_LOAD, &cpu_load_5min);
- mono_counters_register ("CPU Load Average - 15min", SYSCOUNTER_LOAD, &cpu_load_15min);
-
- system_counters_initialized = TRUE;
+ register_internal ("User Time", SYSCOUNTER_TIME, &user_time, sizeof (gint64));
+ register_internal ("System Time", SYSCOUNTER_TIME, &system_time, sizeof (gint64));
+ register_internal ("Total Time", SYSCOUNTER_TIME, &total_time, sizeof (gint64));
+ register_internal ("Working Set", SYSCOUNTER_BYTES, &working_set, sizeof (gint64));
+ register_internal ("Private Bytes", SYSCOUNTER_BYTES, &private_bytes, sizeof (gint64));
+ register_internal ("Virtual Bytes", SYSCOUNTER_BYTES, &virtual_bytes, sizeof (gint64));
+ register_internal ("Page Faults", SYSCOUNTER_COUNT, &page_faults, sizeof (gint64));
+ register_internal ("CPU Load Average - 1min", SYSCOUNTER_LOAD, &cpu_load_1min, sizeof (double));
+ register_internal ("CPU Load Average - 5min", SYSCOUNTER_LOAD, &cpu_load_5min, sizeof (double));
+ register_internal ("CPU Load Average - 15min", SYSCOUNTER_LOAD, &cpu_load_15min, sizeof (double));
}
/**
{
MonoCounter *counter;
- if (!system_counters_initialized)
- initialize_system_counters ();
+ if (!initialized) {
+ g_warning ("counters not enabled");
+ return;
+ }
+
+ mono_mutex_lock (&counters_mutex);
for (counter = counters; counter; counter = counter->next) {
- if (!cb (counter, user_data))
+ if (!cb (counter, user_data)) {
+ mono_mutex_unlock (&counters_mutex);
return;
+ }
}
+
+ mono_mutex_unlock (&counters_mutex);
}
#define COPY_COUNTER(type,functype) do { \
size = sizeof (type); \
if (buffer_size < size) \
- return -1; \
- *(type*)buffer = cb ? ((functype)counter->addr) () : *(type*)counter->addr; \
+ size = -1; \
+ else \
+ *(type*)buffer = cb ? ((functype)counter->addr) () : *(type*)counter->addr; \
} while (0);
-int
-mono_counters_sample (MonoCounter *counter, void *buffer, int buffer_size)
+/* lockless */
+static int
+sample_internal (MonoCounter *counter, void *buffer, int buffer_size)
{
int cb = counter->type & MONO_COUNTER_CALLBACK;
int size = -1;
COPY_COUNTER (double, DoubleFunc);
break;
case MONO_COUNTER_STRING:
- if (buffer_size < counter->size)
- return -1;
- if (counter->size == 0)
- return 0;
- strval = cb ? ((StrFunc)counter->addr) () : (char*)counter->addr;
- if (!strval)
- return 0;
- size = counter->size;
- strncpy (buffer, strval, size - 1);
- ((char*)buffer)[size - 1] = '\0';
+ if (buffer_size < counter->size) {
+ size = -1;
+ } else if (counter->size == 0) {
+ size = 0;
+ } else {
+ strval = cb ? ((StrFunc)counter->addr) () : (char*)counter->addr;
+ if (!strval) {
+ size = 0;
+ } else {
+ size = counter->size;
+ strncpy (buffer, strval, size - 1);
+ ((char*)buffer)[size - 1] = '\0';
+ }
+ }
}
return size;
}
+int
+mono_counters_sample (MonoCounter *counter, void *buffer, int buffer_size)
+{
+ if (!initialized) {
+ g_warning ("counters not enabled");
+ return -1;
+ }
+
+ return sample_internal (counter, buffer, buffer_size);
+}
+
+#define ENTRY_FMT "%-36s: "
+static void
+dump_counter (MonoCounter *counter, FILE *outfile) {
+ void *buffer = g_malloc0 (counter->size);
+ int size = sample_internal (counter, buffer, counter->size);
+
+ switch (counter->type & MONO_COUNTER_TYPE_MASK) {
+ case MONO_COUNTER_INT:
+ fprintf (outfile, ENTRY_FMT "%d\n", counter->name, *(int*)buffer);
+ break;
+ case MONO_COUNTER_UINT:
+ fprintf (outfile, ENTRY_FMT "%u\n", counter->name, *(guint*)buffer);
+ break;
+ case MONO_COUNTER_LONG:
+ if ((counter->type & MONO_COUNTER_UNIT_MASK) == MONO_COUNTER_TIME)
+ fprintf (outfile, ENTRY_FMT "%.2f ms\n", counter->name, (double)(*(gint64*)buffer) / 10000.0);
+ else
+ fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, *(long long *)buffer);
+ break;
+ case MONO_COUNTER_ULONG:
+ fprintf (outfile, ENTRY_FMT "%llu\n", counter->name, *(unsigned long long *)buffer);
+ break;
+ case MONO_COUNTER_WORD:
+ fprintf (outfile, ENTRY_FMT "%zd\n", counter->name, *(gssize*)buffer);
+ break;
+ case MONO_COUNTER_DOUBLE:
+ fprintf (outfile, ENTRY_FMT "%.4f\n", counter->name, *(double*)buffer);
+ break;
+ case MONO_COUNTER_STRING:
+ fprintf (outfile, ENTRY_FMT "%s\n", counter->name, (size == 0) ? "(null)" : (char*)buffer);
+ break;
+ case MONO_COUNTER_TIME_INTERVAL:
+ fprintf (outfile, ENTRY_FMT "%.2f ms\n", counter->name, (double)(*(gint64*)buffer) / 1000.0);
+ break;
+ }
+
+ g_free (buffer);
+}
+
static const char
section_names [][10] = {
"JIT",
int i, j;
int variance;
section_mask &= valid_mask;
- if (!counters)
+
+ if (!initialized)
return;
+ mono_mutex_lock (&counters_mutex);
+
+ if (!counters) {
+ mono_mutex_unlock (&counters_mutex);
+ return;
+ }
+
variance = section_mask & MONO_COUNTER_VARIANCE_MASK;
/* If no variance mask is supplied, we default to all kinds. */
}
fflush (outfile);
+ mono_mutex_unlock (&counters_mutex);
}
/**
void
mono_counters_cleanup (void)
{
+ if (!initialized)
+ return;
+
+ mono_mutex_lock (&counters_mutex);
+
MonoCounter *counter = counters;
counters = NULL;
while (counter) {
MonoCounter *tmp = counter;
counter = counter->next;
+ free ((void*)tmp->name);
free (tmp);
}
+
+ mono_mutex_unlock (&counters_mutex);
}
static MonoResourceCallback limit_reached = NULL;
MONO_COUNTER_SECURITY = 1 << 12,
MONO_COUNTER_RUNTIME = 1 << 13,
MONO_COUNTER_SYSTEM = 1 << 14,
+ MONO_COUNTER_PERFCOUNTERS = 1 << 15,
MONO_COUNTER_LAST_SECTION,
/* Unit, bits 24-27 (4 bits) */
typedef struct _MonoCounter MonoCounter;
-
MONO_API void mono_counters_enable (int section_mask);
+MONO_API void mono_counters_init (void);
/*
* register addr as the address of a counter of type type.
MONO_API void mono_counters_register (const char* descr, int type, void *addr);
MONO_API void mono_counters_register_with_size (const char *name, int type, void *addr, int size);
+typedef void (*MonoCounterRegisterCallback) (MonoCounter*);
+MONO_API void mono_counters_on_register (MonoCounterRegisterCallback callback);
+
/*
* Create a readable dump of the counters for section_mask sections (ORed section values)
*/
}
gboolean
-mono_threads_core_suspend (MonoThreadInfo *info)
+mono_threads_core_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
{
kern_return_t ret;
gboolean res;
HANDLE handle;
} StartInfo;
+#ifdef PLATFORM_ANDROID
+static int no_interrupt_signo;
+#endif
+
static void*
inner_start_thread (void *arg)
{
#endif
static void
-mono_posix_add_signal_handler (int signo, gpointer handler)
+mono_posix_add_signal_handler (int signo, gpointer handler, int flags)
{
#if !defined(__native_client__)
/*FIXME, move the code from mini to utils and do the right thing!*/
sa.sa_sigaction = handler;
sigemptyset (&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
+ sa.sa_flags = SA_SIGINFO | flags;
ret = sigaction (signo, &sa, &previous_sa);
g_assert (ret != -1);
mono_threads_init_platform (void)
{
#if !defined(__native_client__)
+ int abort_signo;
+
/*
FIXME we should use all macros from mini to make this more portable
FIXME it would be very sweet if sgen could end up using this too.
*/
- if (mono_thread_info_new_interrupt_enabled ())
- mono_posix_add_signal_handler (mono_thread_get_abort_signal (), suspend_signal_handler);
+ if (!mono_thread_info_new_interrupt_enabled ())
+ return;
+ abort_signo = mono_thread_get_abort_signal ();
+ mono_posix_add_signal_handler (abort_signo, suspend_signal_handler, 0);
+
+#ifdef PLATFORM_ANDROID
+ /*
+ * Lots of android native code can't handle the EINTR caused by
+ * the normal abort signal, so use a different signal for the
+ * no interruption case, which is used by sdb.
+ * FIXME: Use this on all platforms.
+ * SIGUSR1 is used by dalvik/art.
+ */
+ no_interrupt_signo = SIGUSR2;
+ g_assert (abort_signo != no_interrupt_signo);
+ mono_posix_add_signal_handler (no_interrupt_signo, suspend_signal_handler, SA_RESTART);
+#endif
#endif
}
-/*nothing to be done here since suspend always abort syscalls due using signals*/
void
mono_threads_core_interrupt (MonoThreadInfo *info)
{
+ /* Handled in mono_threads_core_suspend () */
}
void
}
gboolean
-mono_threads_core_suspend (MonoThreadInfo *info)
+mono_threads_core_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
{
/*FIXME, check return value*/
- mono_threads_pthread_kill (info, mono_thread_get_abort_signal ());
+#ifdef PLATFORM_ANDROID
+ if (!interrupt_kernel)
+ mono_threads_pthread_kill (info, no_interrupt_signo);
+ else
+ mono_threads_pthread_kill (info, mono_thread_get_abort_signal ());
+#else
+ mono_threads_pthread_kill (info, mono_thread_get_abort_signal ());
+#endif
while (MONO_SEM_WAIT (&info->begin_suspend_semaphore) != 0) {
/* g_assert (errno == EINTR); */
}
MONO_SEM_INIT (&info->begin_suspend_semaphore, 0);
#if defined (PLATFORM_ANDROID)
- info->native_handle = (gpointer) gettid ();
+ info->native_handle = gettid ();
#endif
}
}
gboolean
-mono_threads_core_suspend (MonoThreadInfo *info)
+mono_threads_core_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
{
DWORD id = mono_thread_info_get_tid (info);
HANDLE handle;
#include <mono/utils/hazard-pointer.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-mmap.h>
+#include <mono/utils/atomic.h>
#include <errno.h>
return info;
}
- if (!mono_threads_core_suspend (info)) {
+ if (!mono_threads_core_suspend (info, interrupt_kernel)) {
MONO_SEM_POST (&info->suspend_semaphore);
mono_hazard_pointer_clear (hp, 1);
*error_condition = "Could not suspend thread";
{
mono_threads_core_clear_interruption ();
}
+
+/* info must be self or be held in a hazard pointer. */
+gboolean
+mono_threads_add_async_job (MonoThreadInfo *info, MonoAsyncJob job)
+{
+ MonoAsyncJob old_job;
+ do {
+ old_job = info->service_requests;
+ if (old_job & job)
+ return FALSE;
+ } while (InterlockedCompareExchange (&info->service_requests, old_job | job, old_job) != old_job);
+ return TRUE;
+}
+
+MonoAsyncJob
+mono_threads_consume_async_jobs (void)
+{
+ MonoThreadInfo *info = (MonoThreadInfo*)mono_native_tls_get_value (thread_info_key);
+
+ if (!info)
+ return 0;
+
+ return InterlockedExchange (&info->service_requests, 0);
+}
SUSPEND_STATE_MASK = 0xF0,
};
+/*
+ * This enum tells which async thread service corresponds to which bit.
+ */
+typedef enum {
+ MONO_SERVICE_REQUEST_SAMPLE = 1,
+} MonoAsyncJob;
+
#define mono_thread_info_run_state(info) (((MonoThreadInfo*)info)->thread_state & RUN_STATE_MASK)
#define mono_thread_info_suspend_state(info) (((MonoThreadInfo*)info)->thread_state & SUSPEND_STATE_MASK)
/* IO layer handle for this thread */
/* Set when the thread is started, or in _wapi_thread_duplicate () */
HANDLE handle;
+
+ /* Asynchronous service request. This flag is meant to be consumed by the multiplexing signal handlers to discover what sort of work they need to do.
+ * Use the mono_threads_add_async_job and mono_threads_consume_async_jobs APIs to modify this flag.
+ * In the future the signaling should be part of the API, but for now, it's only for massaging the bits.
+ */
+ volatile gint32 service_requests;
} MonoThreadInfo;
typedef struct {
HANDLE
mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) MONO_INTERNAL;
+/*
+This is the async job submission/consumption API.
+XXX: This is a PROVISIONAL API only meant to be used by the statistical profiler.
+If you want to use/extend it anywhere else, understand that you'll have to do some API design work to better fit this puppy.
+*/
+gboolean
+mono_threads_add_async_job (THREAD_INFO_TYPE *info, MonoAsyncJob job) MONO_INTERNAL;
+
+MonoAsyncJob
+mono_threads_consume_async_jobs (void) MONO_INTERNAL;
+
+
#if !defined(HOST_WIN32)
/*Use this instead of pthread_kill */
/* Plartform specific functions DON'T use them */
void mono_threads_init_platform (void) MONO_INTERNAL; //ok
-gboolean mono_threads_core_suspend (THREAD_INFO_TYPE *info) MONO_INTERNAL;
+gboolean mono_threads_core_suspend (THREAD_INFO_TYPE *info, gboolean interrupt_kernel) MONO_INTERNAL;
gboolean mono_threads_core_resume (THREAD_INFO_TYPE *info) MONO_INTERNAL;
void mono_threads_platform_register (THREAD_INFO_TYPE *info) MONO_INTERNAL; //ok
void mono_threads_platform_free (THREAD_INFO_TYPE *info) MONO_INTERNAL;
endif
if INSTALL_4_5
-build_profiles += net_4_5 xbuild_12
+build_profiles += net_4_5 xbuild_12 xbuild_14
al_profile = net_4_5
endif
MONO_PATH="$$mcs_topdir/class/lib/$$profile$(PLATFORM_PATH_SEPARATOR)$$mcs_topdir/class/lib/net_2_0$(PLATFORM_PATH_SEPARATOR)$$save_MONO_PATH"; \
elif [ "xbuild_12" = "$$profile" ]; then \
MONO_PATH="$$mcs_topdir/class/lib/$$profile$(PLATFORM_PATH_SEPARATOR)$$mcs_topdir/class/lib/net_4_5$(PLATFORM_PATH_SEPARATOR)$$save_MONO_PATH"; \
+ elif [ "xbuild_14" = "$$profile" ]; then \
+ MONO_PATH="$$mcs_topdir/class/lib/$$profile$(PLATFORM_PATH_SEPARATOR)$$mcs_topdir/class/lib/net_4_5$(PLATFORM_PATH_SEPARATOR)$$save_MONO_PATH"; \
else \
MONO_PATH="$$mcs_topdir/class/lib/$$profile$(PLATFORM_PATH_SEPARATOR)$$save_MONO_PATH"; \
fi; \