# default install location
libgdiplus_install_loc=libgdiplus${libsuffix}
+case "$host" in
+ *-*-*linux*)
+ libgdiplus_install_loc=libgdiplus${libsuffix}.0
+ ;;
+esac
+
case $with_libgdiplus in
no|installed)
libgdiplus_loc=
-Subproject commit df1c00441047e7cc439608aa1aa083f585f5ace0
+Subproject commit 6c6e36218c4a0b6dfb85bd27fa6746467761e8a0
rm -f $outfile.inc
-if test -n "$excfile"; then
+if test -n "$excfile" -a -f "$excfile"; then
process_includes $excfile $outfile.exc
fi
} else {
var typeHandleValue = Type.GetTypeHandle (memberValue);
var isDeclaredType = typeHandleValue.Equals (CodeInterpreter.ConvertValue (memberValue, memberType, Globals.TypeOfObject));
- if (isNullableOfT)
+ if (isNullableOfT) {
ctx.InternalSerialize (writer, memberValue, isDeclaredType, writeXsiType, DataContract.GetId (memberType.TypeHandle), memberType.TypeHandle);
- else
- ctx.InternalSerializeReference (writer, memberValue, isDeclaredType, writeXsiType, DataContract.GetId (memberType.TypeHandle), memberType.TypeHandle);
- //InternalSerialize((isNullableOfT ? XmlFormatGeneratorStatics.InternalSerializeMethod : XmlFormatGeneratorStatics.InternalSerializeReferenceMethod), () => memberValue, memberType, writeXsiType);
+ } else if (memberType == Globals.TypeOfObject) {
+ var dataContract = DataContract.GetDataContract (memberValue.GetType());
+ writer.WriteAttributeQualifiedName (Globals.XsiPrefix, DictionaryGlobals.XsiTypeLocalName, DictionaryGlobals.SchemaInstanceNamespace, dataContract.Name, dataContract.Namespace);
+ ctx.InternalSerializeReference (writer, memberValue, false, false, -1, typeHandleValue);
+ } else {
+ ctx.InternalSerializeReference (writer, memberValue, isDeclaredType, writeXsiType, DataContract.GetId (memberType.TypeHandle), memberType.TypeHandle);
+ }
}
}
}
Assert.IsTrue (s.Contains ("<Flags>All</Flags>"));
}
}
+
+ // Bug #37116
+ [Test]
+ public void KeyPairOfAny ()
+ {
+ var dict = new Dictionary<string, object> ();
+ dict.Add ("test", new List<string> () { "test entry" });
+
+ var dcs = new DataContractSerializer (typeof(Dictionary<string, object>));
+ dcs.WriteObject (new MemoryStream (), dict);
+ // Should not throw exception.
+ }
}
}
return new EndpointAddress10 (address);
}
-#if !NET_2_1
public static XmlQualifiedName GetSchema (XmlSchemaSet xmlSchemaSet)
{
if (xmlSchemaSet == null)
xmlSchemaSet.Add (XmlSchema.Read (typeof (EndpointAddress10).Assembly.GetManifestResourceStream ("ws-addr.xsd"), null));
return new XmlQualifiedName ("EndpointReferenceType", AddressingVersion.WSAddressing10.Namespace);
}
-#endif
public EndpointAddress ToEndpointAddress ()
{
System.ServiceModel.Security/TransportSecurityBindingElementTest.cs
System.ServiceModel.Security/WSSecurityTokenSerializerTest.cs
System.ServiceModel/BasicHttpBindingTest.cs
+System.ServiceModel/Bug36080Test.cs
System.ServiceModel/CallbackBehaviorAttributeTest.cs
System.ServiceModel/ChannelFactoryTest.cs
System.ServiceModel/ChannelFactory_1Test.cs
--- /dev/null
+//
+// Author:
+// Marcos Henrich <marcos.henrich@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.ServiceModel;
+using System.ServiceModel.Description;
+using System.Threading;
+using System.ServiceModel.Channels;
+using System.Text;
+using NUnit.Framework;
+
+using MonoTests.Helpers;
+
+namespace MonoTests.System.ServiceModel
+{
+ [TestFixture]
+ public class Bug36080
+ {
+ [Test]
+ public void Bug36080Test ()
+ {
+ int port = NetworkHelpers.FindFreePort ();
+ var url = "http://localhost:" + port + "/HelloWorldService";
+
+ TransportBindingElement element = new HttpTransportBindingElement { MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue };
+ Binding binding = new CustomBinding(new BindingElement[]
+ {
+ new TextMessageEncodingBindingElement (MessageVersion.Default, Encoding.UTF8),
+ element
+ });
+
+#if !MOBILE
+ // Init service
+ ServiceHost serviceHost = new ServiceHost (typeof (HelloWorldServiceImpl), new Uri (url));
+ serviceHost.AddServiceEndpoint (typeof (IHelloWorldService), binding, string.Empty);
+
+ serviceHost.Open ();
+#endif
+ // In Mobile we still run this tests without any server.
+ // Issue reported in #36080 was occuring before the connections fails.
+ var wait = new ManualResetEvent (false);
+
+ Exception error = null;
+ string result = null;
+
+ try {
+ var client = new HelloWorldServiceClient (binding, new EndpointAddress(url));
+ client.SayHelloToCompleted += delegate (object o, SayHelloToCompletedEventArgs e) {
+ try {
+ error = e.Error;
+ result = e.Error == null ? e.Result : null;
+ } finally {
+ wait.Set ();
+ }
+ };
+
+ var str = "Xamarin";
+ client.SayHelloToAsync(str);
+
+ Assert.IsTrue (wait.WaitOne (TimeSpan.FromSeconds (20)), "timeout");
+#if MOBILE
+ if (error.GetType() == typeof(EndpointNotFoundException))
+ return;
+#endif
+
+ Assert.IsNull (error, "#1, inner exception: {0}", error);
+ Assert.AreEqual (str, result, "#2");
+ } finally {
+#if !MOBILE
+ serviceHost.Close ();
+#endif
+ }
+ }
+ }
+
+ public class HelloWorldServiceImpl : IHelloWorldService
+ {
+ Func<string, string> sayHelloToFunc = SayHelloTo;
+
+ static string SayHelloTo (string name)
+ {
+ return name;
+ }
+
+ public IAsyncResult BeginSayHelloTo(string name, AsyncCallback callback, object asyncState)
+ {
+ return sayHelloToFunc.BeginInvoke (name, callback, asyncState);
+ }
+
+ public string EndSayHelloTo(IAsyncResult result)
+ {
+ return sayHelloToFunc.EndInvoke(result);
+ }
+
+ public IAsyncResult BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, AsyncCallback callback, object asyncState)
+ {
+ return null;
+ }
+
+ public TestXamarin4WCFService.HelloWorldData EndGetHelloData(IAsyncResult result)
+ {
+ return null;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.18444
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+//
+// This code was auto-generated by SlSvcUtil, version 5.0.61118.0
+//
+namespace TestXamarin4WCFService
+{
+ using System.Runtime.Serialization;
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+ [System.Runtime.Serialization.DataContractAttribute(Name = "HelloWorldData", Namespace = "http://schemas.datacontract.org/2004/07/TestXamarin4WCFService")]
+ public partial class HelloWorldData : object
+ {
+
+ private string NameField;
+
+ private bool SayHelloField;
+
+ [System.Runtime.Serialization.DataMemberAttribute()]
+ public string Name
+ {
+ get
+ {
+ return this.NameField;
+ }
+ set
+ {
+ this.NameField = value;
+ }
+ }
+
+ [System.Runtime.Serialization.DataMemberAttribute()]
+ public bool SayHello
+ {
+ get
+ {
+ return this.SayHelloField;
+ }
+ set
+ {
+ this.SayHelloField = value;
+ }
+ }
+ }
+}
+
+
+[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
+[System.ServiceModel.ServiceContractAttribute(ConfigurationName="IHelloWorldService")]
+public interface IHelloWorldService
+{
+
+ [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://tempuri.org/IHelloWorldService/SayHelloTo", ReplyAction="http://tempuri.org/IHelloWorldService/SayHelloToResponse")]
+ System.IAsyncResult BeginSayHelloTo(string name, System.AsyncCallback callback, object asyncState);
+
+ string EndSayHelloTo(System.IAsyncResult result);
+
+ [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://tempuri.org/IHelloWorldService/GetHelloData", ReplyAction="http://tempuri.org/IHelloWorldService/GetHelloDataResponse")]
+ System.IAsyncResult BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, System.AsyncCallback callback, object asyncState);
+
+ TestXamarin4WCFService.HelloWorldData EndGetHelloData(System.IAsyncResult result);
+}
+
+[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
+public interface IHelloWorldServiceChannel : IHelloWorldService, System.ServiceModel.IClientChannel
+{
+}
+
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
+public partial class SayHelloToCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
+{
+
+ private object[] results;
+
+ public SayHelloToCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState)
+ {
+ this.results = results;
+ }
+
+ public string Result
+ {
+ get
+ {
+ base.RaiseExceptionIfNecessary();
+ return ((string)(this.results[0]));
+ }
+ }
+}
+
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
+public partial class GetHelloDataCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
+{
+
+ private object[] results;
+
+ public GetHelloDataCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState)
+ {
+ this.results = results;
+ }
+
+ public TestXamarin4WCFService.HelloWorldData Result
+ {
+ get
+ {
+ base.RaiseExceptionIfNecessary();
+ return ((TestXamarin4WCFService.HelloWorldData)(this.results[0]));
+ }
+ }
+}
+
+[System.Diagnostics.DebuggerStepThroughAttribute()]
+[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
+public partial class HelloWorldServiceClient : System.ServiceModel.ClientBase<IHelloWorldService>, IHelloWorldService
+{
+
+ private BeginOperationDelegate onBeginSayHelloToDelegate;
+
+ private EndOperationDelegate onEndSayHelloToDelegate;
+
+ private System.Threading.SendOrPostCallback onSayHelloToCompletedDelegate;
+
+ private BeginOperationDelegate onBeginGetHelloDataDelegate;
+
+ private EndOperationDelegate onEndGetHelloDataDelegate;
+
+ private System.Threading.SendOrPostCallback onGetHelloDataCompletedDelegate;
+
+ private BeginOperationDelegate onBeginOpenDelegate;
+
+ private EndOperationDelegate onEndOpenDelegate;
+
+ private System.Threading.SendOrPostCallback onOpenCompletedDelegate;
+
+ private BeginOperationDelegate onBeginCloseDelegate;
+
+ private EndOperationDelegate onEndCloseDelegate;
+
+ private System.Threading.SendOrPostCallback onCloseCompletedDelegate;
+
+ public HelloWorldServiceClient()
+ {
+ }
+
+ public HelloWorldServiceClient(string endpointConfigurationName) :
+ base(endpointConfigurationName)
+ {
+ }
+
+ public HelloWorldServiceClient(string endpointConfigurationName, string remoteAddress) :
+ base(endpointConfigurationName, remoteAddress)
+ {
+ }
+
+ public HelloWorldServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
+ base(endpointConfigurationName, remoteAddress)
+ {
+ }
+
+ public HelloWorldServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
+ base(binding, remoteAddress)
+ {
+ }
+
+ public System.Net.CookieContainer CookieContainer
+ {
+ get
+ {
+ System.ServiceModel.Channels.IHttpCookieContainerManager httpCookieContainerManager = this.InnerChannel.GetProperty<System.ServiceModel.Channels.IHttpCookieContainerManager>();
+ if ((httpCookieContainerManager != null))
+ {
+ return httpCookieContainerManager.CookieContainer;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ set
+ {
+ System.ServiceModel.Channels.IHttpCookieContainerManager httpCookieContainerManager = this.InnerChannel.GetProperty<System.ServiceModel.Channels.IHttpCookieContainerManager>();
+ if ((httpCookieContainerManager != null))
+ {
+ httpCookieContainerManager.CookieContainer = value;
+ }
+ else
+ {
+ throw new System.InvalidOperationException("Unable to set the CookieContainer. Please make sure the binding contains an HttpC" +
+ "ookieContainerBindingElement.");
+ }
+ }
+ }
+
+ public event System.EventHandler<SayHelloToCompletedEventArgs> SayHelloToCompleted;
+
+ public event System.EventHandler<GetHelloDataCompletedEventArgs> GetHelloDataCompleted;
+
+ public event System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs> OpenCompleted;
+
+ public event System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs> CloseCompleted;
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ System.IAsyncResult IHelloWorldService.BeginSayHelloTo(string name, System.AsyncCallback callback, object asyncState)
+ {
+ return base.Channel.BeginSayHelloTo(name, callback, asyncState);
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ string IHelloWorldService.EndSayHelloTo(System.IAsyncResult result)
+ {
+ return base.Channel.EndSayHelloTo(result);
+ }
+
+ private System.IAsyncResult OnBeginSayHelloTo(object[] inValues, System.AsyncCallback callback, object asyncState)
+ {
+ string name = ((string)(inValues[0]));
+ return ((IHelloWorldService)(this)).BeginSayHelloTo(name, callback, asyncState);
+ }
+
+ private object[] OnEndSayHelloTo(System.IAsyncResult result)
+ {
+ string retVal = ((IHelloWorldService)(this)).EndSayHelloTo(result);
+ return new object[] {
+ retVal};
+ }
+
+ private void OnSayHelloToCompleted(object state)
+ {
+ if ((this.SayHelloToCompleted != null))
+ {
+ InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
+ this.SayHelloToCompleted(this, new SayHelloToCompletedEventArgs(e.Results, e.Error, e.Cancelled, e.UserState));
+ }
+ }
+
+ public void SayHelloToAsync(string name)
+ {
+ this.SayHelloToAsync(name, null);
+ }
+
+ public void SayHelloToAsync(string name, object userState)
+ {
+ if ((this.onBeginSayHelloToDelegate == null))
+ {
+ this.onBeginSayHelloToDelegate = new BeginOperationDelegate(this.OnBeginSayHelloTo);
+ }
+ if ((this.onEndSayHelloToDelegate == null))
+ {
+ this.onEndSayHelloToDelegate = new EndOperationDelegate(this.OnEndSayHelloTo);
+ }
+ if ((this.onSayHelloToCompletedDelegate == null))
+ {
+ this.onSayHelloToCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnSayHelloToCompleted);
+ }
+ base.InvokeAsync(this.onBeginSayHelloToDelegate, new object[] {
+ name}, this.onEndSayHelloToDelegate, this.onSayHelloToCompletedDelegate, userState);
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ System.IAsyncResult IHelloWorldService.BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, System.AsyncCallback callback, object asyncState)
+ {
+ return base.Channel.BeginGetHelloData(helloWorldData, callback, asyncState);
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ TestXamarin4WCFService.HelloWorldData IHelloWorldService.EndGetHelloData(System.IAsyncResult result)
+ {
+ return base.Channel.EndGetHelloData(result);
+ }
+
+ private System.IAsyncResult OnBeginGetHelloData(object[] inValues, System.AsyncCallback callback, object asyncState)
+ {
+ TestXamarin4WCFService.HelloWorldData helloWorldData = ((TestXamarin4WCFService.HelloWorldData)(inValues[0]));
+ return ((IHelloWorldService)(this)).BeginGetHelloData(helloWorldData, callback, asyncState);
+ }
+
+ private object[] OnEndGetHelloData(System.IAsyncResult result)
+ {
+ TestXamarin4WCFService.HelloWorldData retVal = ((IHelloWorldService)(this)).EndGetHelloData(result);
+ return new object[] {
+ retVal};
+ }
+
+ private void OnGetHelloDataCompleted(object state)
+ {
+ if ((this.GetHelloDataCompleted != null))
+ {
+ InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
+ this.GetHelloDataCompleted(this, new GetHelloDataCompletedEventArgs(e.Results, e.Error, e.Cancelled, e.UserState));
+ }
+ }
+
+ public void GetHelloDataAsync(TestXamarin4WCFService.HelloWorldData helloWorldData)
+ {
+ this.GetHelloDataAsync(helloWorldData, null);
+ }
+
+ public void GetHelloDataAsync(TestXamarin4WCFService.HelloWorldData helloWorldData, object userState)
+ {
+ if ((this.onBeginGetHelloDataDelegate == null))
+ {
+ this.onBeginGetHelloDataDelegate = new BeginOperationDelegate(this.OnBeginGetHelloData);
+ }
+ if ((this.onEndGetHelloDataDelegate == null))
+ {
+ this.onEndGetHelloDataDelegate = new EndOperationDelegate(this.OnEndGetHelloData);
+ }
+ if ((this.onGetHelloDataCompletedDelegate == null))
+ {
+ this.onGetHelloDataCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnGetHelloDataCompleted);
+ }
+ base.InvokeAsync(this.onBeginGetHelloDataDelegate, new object[] {
+ helloWorldData}, this.onEndGetHelloDataDelegate, this.onGetHelloDataCompletedDelegate, userState);
+ }
+
+ private System.IAsyncResult OnBeginOpen(object[] inValues, System.AsyncCallback callback, object asyncState)
+ {
+ return ((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(callback, asyncState);
+ }
+
+ private object[] OnEndOpen(System.IAsyncResult result)
+ {
+ ((System.ServiceModel.ICommunicationObject)(this)).EndOpen(result);
+ return null;
+ }
+
+ private void OnOpenCompleted(object state)
+ {
+ if ((this.OpenCompleted != null))
+ {
+ InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
+ this.OpenCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(e.Error, e.Cancelled, e.UserState));
+ }
+ }
+
+ public void OpenAsync()
+ {
+ this.OpenAsync(null);
+ }
+
+ public void OpenAsync(object userState)
+ {
+ if ((this.onBeginOpenDelegate == null))
+ {
+ this.onBeginOpenDelegate = new BeginOperationDelegate(this.OnBeginOpen);
+ }
+ if ((this.onEndOpenDelegate == null))
+ {
+ this.onEndOpenDelegate = new EndOperationDelegate(this.OnEndOpen);
+ }
+ if ((this.onOpenCompletedDelegate == null))
+ {
+ this.onOpenCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnOpenCompleted);
+ }
+ base.InvokeAsync(this.onBeginOpenDelegate, null, this.onEndOpenDelegate, this.onOpenCompletedDelegate, userState);
+ }
+
+ private System.IAsyncResult OnBeginClose(object[] inValues, System.AsyncCallback callback, object asyncState)
+ {
+ return ((System.ServiceModel.ICommunicationObject)(this)).BeginClose(callback, asyncState);
+ }
+
+ private object[] OnEndClose(System.IAsyncResult result)
+ {
+ ((System.ServiceModel.ICommunicationObject)(this)).EndClose(result);
+ return null;
+ }
+
+ private void OnCloseCompleted(object state)
+ {
+ if ((this.CloseCompleted != null))
+ {
+ InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
+ this.CloseCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(e.Error, e.Cancelled, e.UserState));
+ }
+ }
+
+ public void CloseAsync()
+ {
+ this.CloseAsync(null);
+ }
+
+ public void CloseAsync(object userState)
+ {
+ if ((this.onBeginCloseDelegate == null))
+ {
+ this.onBeginCloseDelegate = new BeginOperationDelegate(this.OnBeginClose);
+ }
+ if ((this.onEndCloseDelegate == null))
+ {
+ this.onEndCloseDelegate = new EndOperationDelegate(this.OnEndClose);
+ }
+ if ((this.onCloseCompletedDelegate == null))
+ {
+ this.onCloseCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnCloseCompleted);
+ }
+ base.InvokeAsync(this.onBeginCloseDelegate, null, this.onEndCloseDelegate, this.onCloseCompletedDelegate, userState);
+ }
+
+ protected override IHelloWorldService CreateChannel()
+ {
+ return new HelloWorldServiceClientChannel(this);
+ }
+
+ private class HelloWorldServiceClientChannel : ChannelBase<IHelloWorldService>, IHelloWorldService
+ {
+
+ public HelloWorldServiceClientChannel(System.ServiceModel.ClientBase<IHelloWorldService> client) :
+ base(client)
+ {
+ }
+
+ public System.IAsyncResult BeginSayHelloTo(string name, System.AsyncCallback callback, object asyncState)
+ {
+ object[] _args = new object[1];
+ _args[0] = name;
+ System.IAsyncResult _result = base.BeginInvoke("SayHelloTo", _args, callback, asyncState);
+ return _result;
+ }
+
+ public string EndSayHelloTo(System.IAsyncResult result)
+ {
+ object[] _args = new object[0];
+ string _result = ((string)(base.EndInvoke("SayHelloTo", _args, result)));
+ return _result;
+ }
+
+ public System.IAsyncResult BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, System.AsyncCallback callback, object asyncState)
+ {
+ object[] _args = new object[1];
+ _args[0] = helloWorldData;
+ System.IAsyncResult _result = base.BeginInvoke("GetHelloData", _args, callback, asyncState);
+ return _result;
+ }
+
+ public TestXamarin4WCFService.HelloWorldData EndGetHelloData(System.IAsyncResult result)
+ {
+ object[] _args = new object[0];
+ TestXamarin4WCFService.HelloWorldData _result = ((TestXamarin4WCFService.HelloWorldData)(base.EndInvoke("GetHelloData", _args, result)));
+ return _result;
+ }
+ }
+}
if (!hashAlg.CanReuseTransform) {
canReuseHashAlg = false;
hashAlg = null;
+ return null;
}
+ hashAlg.Key = MachineKeySectionUtils.GetValidationKey (mks);
}
if (hashAlg != null)
WritePrefix ();
}
- WriteDebugString (message);
-
if (Debugger.IsLogging())
Debugger.Log (0, null, message);
+ else
+ WriteDebugString (message);
WriteLogFile (message, LogFileName);
}
#pragma warning restore 649
#endregion
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- extern static int GetILOffsetFromFile (string path, int methodToken, uint methodIndex, int nativeOffset);
-
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static bool get_frame_info (int skip, bool needFileInfo, out MethodBase method,
out int iloffset, out int native_offset,
else
sb.AppendFormat ("<0x{0:x5} + 0x{1:x5}> {2}", frame.GetMethodAddress (), frame.GetNativeOffset (), unknown);
} else {
- GetFullNameForStackTrace (sb, frame.GetMethod ());
+ StackTraceHelper.GetFullNameForStackTrace (sb, frame.GetMethod ());
if (frame.GetILOffset () == -1) {
sb.AppendFormat (" <0x{0:x5} + 0x{1:x5}>", frame.GetMethodAddress (), frame.GetNativeOffset ());
return i != 0;
}
- // This method is also used with reflection by mono-symbolicate tool.
- // mono-symbolicate tool uses this method to check which method matches
- // the stack frame method signature.
- static void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
- {
- var declaringType = mi.DeclaringType;
- if (declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition)
- declaringType = declaringType.GetGenericTypeDefinition ();
-
- // Get generic definition
- var bindingflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
- foreach (var m in declaringType.GetMethods (bindingflags)) {
- if (m.MetadataToken == mi.MetadataToken) {
- mi = m;
- break;
- }
- }
-
- sb.Append (declaringType.ToString ());
-
- sb.Append (".");
- sb.Append (mi.Name);
-
- if (mi.IsGenericMethod) {
- Type[] gen_params = mi.GetGenericArguments ();
- sb.Append ("[");
- for (int j = 0; j < gen_params.Length; j++) {
- if (j > 0)
- sb.Append (",");
- sb.Append (gen_params [j].Name);
- }
- sb.Append ("]");
- }
-
- ParameterInfo[] p = mi.GetParametersInternal ();
-
- sb.Append (" (");
- for (int i = 0; i < p.Length; ++i) {
- if (i > 0)
- sb.Append (", ");
-
- Type pt = p[i].ParameterType;
- if (pt.IsGenericType && ! pt.IsGenericTypeDefinition)
- pt = pt.GetGenericTypeDefinition ();
-
- if (pt.IsClass && !String.IsNullOrEmpty (pt.Namespace)) {
- sb.Append (pt.Namespace);
- sb.Append (".");
- }
- sb.Append (pt.Name);
- if (p [i].Name != null) {
- sb.Append (" ");
- sb.Append (p [i].Name);
- }
- }
- sb.Append (")");
- }
-
public override string ToString ()
{
StringBuilder sb = new StringBuilder ();
--- /dev/null
+//
+// System.Diagnostics.StackTraceHelper.cs
+//
+// Author:
+// Marcos Henrich (marcos.henrich@xamarin.com)
+//
+// Copyright (C) Xamarin, Inc (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Text;
+using System.Reflection;
+
+namespace System.Diagnostics {
+
+ // This class exists so tools such as mono-symbolicate can use it directly.
+ class StackTraceHelper {
+
+ public static void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
+ {
+ var declaringType = mi.DeclaringType;
+ if (declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition)
+ declaringType = declaringType.GetGenericTypeDefinition ();
+
+ // Get generic definition
+ var bindingflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+ foreach (var m in declaringType.GetMethods (bindingflags)) {
+ if (m.MetadataToken == mi.MetadataToken) {
+ mi = m;
+ break;
+ }
+ }
+
+ sb.Append (declaringType.ToString ());
+
+ sb.Append (".");
+ sb.Append (mi.Name);
+
+ if (mi.IsGenericMethod) {
+ Type[] gen_params = mi.GetGenericArguments ();
+ sb.Append ("[");
+ for (int j = 0; j < gen_params.Length; j++) {
+ if (j > 0)
+ sb.Append (",");
+ sb.Append (gen_params [j].Name);
+ }
+ sb.Append ("]");
+ }
+
+ ParameterInfo[] p = mi.GetParameters ();
+
+ sb.Append (" (");
+ for (int i = 0; i < p.Length; ++i) {
+ if (i > 0)
+ sb.Append (", ");
+
+ Type pt = p[i].ParameterType;
+ if (pt.IsGenericType && ! pt.IsGenericTypeDefinition)
+ pt = pt.GetGenericTypeDefinition ();
+
+ if (pt.IsClass && !String.IsNullOrEmpty (pt.Namespace)) {
+ sb.Append (pt.Namespace);
+ sb.Append (".");
+ }
+ sb.Append (pt.Name);
+ if (p [i].Name != null) {
+ sb.Append (" ");
+ sb.Append (p [i].Name);
+ }
+ }
+ sb.Append (")");
+ }
+ }
+}
//
using System;
+using System.Threading;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
public void Free()
{
- FreeHandle(handle);
- handle = 0;
+ // Copy the handle instance member to a local variable. This is required to prevent
+ // race conditions releasing the handle.
+ int local_handle = handle;
+
+ // Free the handle if it hasn't already been freed.
+ if (local_handle != 0 && Interlocked.CompareExchange (ref handle, 0, local_handle) == local_handle) {
+ FreeHandle (local_handle);
+ }
+ else {
+ throw new InvalidOperationException ("Handle is not initialized.");
+ }
}
public static explicit operator IntPtr (GCHandle value)
public static explicit operator GCHandle(IntPtr value)
{
if (value == IntPtr.Zero)
- throw new ArgumentException ("GCHandle value cannot be zero");
+ throw new InvalidOperationException ("GCHandle value cannot be zero");
if (!CheckCurrentDomain ((int)value))
throw new ArgumentException ("GCHandle value belongs to a different domain");
return new GCHandle (value);
static Console ()
{
-#if NET_2_1
- Encoding inputEncoding;
- Encoding outputEncoding;
-#endif
-
if (Environment.IsRunningOnWindows) {
//
// On Windows, follow the Windows tradition
#endif
-#if !NET_2_1
// FIXME: Console should use these encodings when changed
static Encoding inputEncoding;
static Encoding outputEncoding;
}
}
+#if !NET_2_1
public static ConsoleColor BackgroundColor {
get { return ConsoleDriver.BackgroundColor; }
set { ConsoleDriver.BackgroundColor = value; }
System.Diagnostics/Debugger.cs
System.Diagnostics/StackFrame.cs
System.Diagnostics/StackTrace.cs
+System.Diagnostics/StackTraceHelper.cs
System.Diagnostics.Tracing/EventAttribute.cs
System.Diagnostics.Tracing/EventCommand.cs
System.Diagnostics.Tracing/EventSource.cs
using System.Collections.Generic;
using Mono.Cecil;
using Mono.CompilerServices.SymbolWriter;
+using System.Runtime.InteropServices;
namespace Symbolicate
{
return true;
}
- static MethodInfo methodGetIL;
+ SeqPointInfo seqPointInfo;
private int GetILOffsetFromFile (int methodToken, uint methodIndex, int nativeOffset)
{
- if (string.IsNullOrEmpty (seqPointDataPath))
- return -1;
+ if (seqPointInfo == null)
+ seqPointInfo = SeqPointInfo.Read (seqPointDataPath);
- if (methodGetIL == null)
- methodGetIL = typeof (StackFrame).GetMethod ("GetILOffsetFromFile", BindingFlags.NonPublic | BindingFlags.Static);
-
- if (methodGetIL == null)
- throw new Exception ("System.Diagnostics.StackFrame.GetILOffsetFromFile could not be found, make sure you have an updated mono installed.");
-
- return (int) methodGetIL.Invoke (null, new object[] {seqPointDataPath, methodToken, methodIndex, nativeOffset});
+ return seqPointInfo.GetILOffset (methodToken, methodIndex, nativeOffset);
}
- static MethodInfo methodGetMethodFullName;
private string GetMethodFullName (MethodBase m)
{
-
- if (methodGetMethodFullName == null)
- methodGetMethodFullName = typeof (StackTrace).GetMethod ("GetFullNameForStackTrace", BindingFlags.NonPublic | BindingFlags.Static);
-
- if (methodGetMethodFullName == null)
- throw new Exception ("System.Exception.GetFullNameForStackTrace could not be found, make sure you have an updated mono installed.");
-
StringBuilder sb = new StringBuilder ();
- methodGetMethodFullName.Invoke (null, new object[] {sb, m});
+
+ StackTraceHelper.GetFullNameForStackTrace (sb, m);
return sb.ToString ();
}
if (!File.Exists (assemblyPath))
throw new ArgumentException ("assemblyPath does not exist: "+ assemblyPath);
- var assembly = Assembly.LoadFrom (assemblyPath);
+ var assembly = Assembly.ReflectionOnlyLoadFrom (assemblyPath);
MonoSymbolFile symbolFile = null;
var symbolPath = assemblyPath + ".mdb";
--- /dev/null
+using System;
+using System.IO;
+using System.Collections.Generic;
+
+namespace Symbolicate
+{
+ static class BinaryReaderExtensions
+ {
+ public static int ReadVariableInt (this BinaryReader reader)
+ {
+ int val = 0;
+ for (var i = 0; i < 4; i++) {
+ var b = reader.ReadByte ();
+ val |= (b & 0x7f) << (7 * i);
+ if ((b & 0x80) == 0)
+ return val;
+ }
+
+ throw new Exception ("Invalid variable int");
+ }
+
+ public static int ReadVariableZigZagInt (this BinaryReader reader)
+ {
+ int enc = ReadVariableInt (reader);
+ int val = enc >> 1;
+ return ((enc & 1) == 0)? val : -val;
+ }
+ }
+
+ class SeqPointInfo
+ {
+ class MethodData
+ {
+ List<SeqPoint> seqPoints;
+
+ public static MethodData Read (BinaryReader reader)
+ {
+ var hasDebugData = reader.ReadVariableInt () != 0;
+ var dataSize = reader.ReadVariableInt ();
+ var dataEnd = reader.BaseStream.Position + dataSize;
+
+ var seqPoints = new List<SeqPoint> ();
+ SeqPoint prev = null;
+ while (reader.BaseStream.Position < dataEnd) {
+ var seqPoint = SeqPoint.Read (reader, prev, hasDebugData);
+ seqPoints.Add (seqPoint);
+ prev = seqPoint;
+ }
+
+ if (reader.BaseStream.Position != dataEnd)
+ throw new Exception ("Read more seq point than expected.");
+
+ return new MethodData () { seqPoints = seqPoints };
+ }
+
+ public bool TryGetILOffset (int nativeOffset, out int ilOffset)
+ {
+ ilOffset = 0;
+ SeqPoint prev = null;
+ foreach (var seqPoint in seqPoints) {
+ if (seqPoint.NativeOffset > nativeOffset)
+ break;
+ prev = seqPoint;
+ }
+
+ if (prev == null)
+ return false;
+
+ ilOffset = prev.ILOffset;
+ return true;
+ }
+ }
+
+ class SeqPoint
+ {
+ public readonly int ILOffset;
+ public readonly int NativeOffset;
+
+ public SeqPoint (int ilOffset, int nativeOffset)
+ {
+ ILOffset = ilOffset;
+ NativeOffset = nativeOffset;
+ }
+
+ public static SeqPoint Read (BinaryReader reader, SeqPoint prev, bool hasDebug)
+ {
+ var ilOffset = reader.ReadVariableZigZagInt ();
+ var nativeOffset = reader.ReadVariableZigZagInt ();
+
+ // Respect delta encoding
+ if (prev != null) {
+ ilOffset += prev.ILOffset;
+ nativeOffset += prev.NativeOffset;
+ }
+
+ //Read everything to ensure the buffer position is at the end of the seq point data.
+ if (hasDebug) {
+ reader.ReadVariableInt (); // flags
+
+ var next_length = reader.ReadVariableInt ();
+ for (var i = 0; i < next_length; ++i)
+ reader.ReadVariableInt ();
+ }
+
+ return new SeqPoint (ilOffset, nativeOffset);
+ }
+ };
+
+ Dictionary<Tuple<int,int>, MethodData> dataByIds;
+ Dictionary<int, MethodData> dataByTokens;
+
+ public static SeqPointInfo Read (string path)
+ {
+ using (var reader = new BinaryReader (File.Open (path, FileMode.Open)))
+ {
+ var dataByIds = new Dictionary<Tuple<int,int>, MethodData> ();
+ var dataByTokens = new Dictionary<int, MethodData> ();
+
+ var methodCount = reader.ReadVariableInt ();
+
+ for (var i = 0; i < methodCount; ++i) {
+ var methodToken = reader.ReadVariableInt ();
+ var methodIndex = reader.ReadVariableInt ();
+ var methodId = new Tuple<int, int> (methodToken, methodIndex);
+
+ var methodData = MethodData.Read (reader);
+
+ dataByIds.Add (methodId, methodData);
+ if (!dataByTokens.ContainsKey (methodToken))
+ dataByTokens.Add (methodToken, methodData);
+ }
+
+ return new SeqPointInfo { dataByIds = dataByIds, dataByTokens = dataByTokens };
+ }
+ }
+
+ public int GetILOffset (int methodToken, uint methodIndex, int nativeOffset)
+ {
+ MethodData methodData;
+ if (methodIndex == 0xffffff) {
+ if (!dataByTokens.TryGetValue (methodToken, out methodData))
+ throw new Exception (string.Format ("Could not find data for method token {0:X}", methodToken));
+ } else {
+ var methodId = new Tuple<int, int> (methodToken, (int)methodIndex);
+ if (!dataByIds.TryGetValue (methodId, out methodData))
+ throw new Exception (string.Format ("Could not find data for method token {0:X} with index {1:X}", methodToken, methodIndex));
+ }
+
+ int ilOffset;
+ if (!methodData.TryGetILOffset (nativeOffset, out ilOffset))
+ throw new Exception ("Could not retrieve IL offset");
+
+ return ilOffset;
+ }
+ }
+}
symbolicate.cs
-LocationProvider.cs
\ No newline at end of file
+LocationProvider.cs
+SeqPointInfo.cs
+../../class/corlib/System.Diagnostics/StackTraceHelper.cs
mono_install_assembly_postload_search_hook ((MonoAssemblySearchFunc)mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE));
mono_install_assembly_postload_refonly_search_hook ((MonoAssemblySearchFunc)mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE));
mono_install_assembly_load_hook (mono_domain_fire_assembly_load, NULL);
- mono_install_lookup_dynamic_token (mono_reflection_lookup_dynamic_token);
mono_thread_init (start_cb, attach_cb);
MonoMethod method;
MonoMethodPInvoke pinvoke;
} method;
- MonoMethodHeader *header;
MonoMethod *declaring; /* the generic method definition. */
MonoGenericContext context; /* The current instantiation */
MonoImageSet *owner; /* The image set that the inflated method belongs to. */
typedef gpointer (*MonoRemotingTrampoline) (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target);
typedef gpointer (*MonoDelegateTrampoline) (MonoDomain *domain, MonoClass *klass);
-typedef gpointer (*MonoLookupDynamicToken) (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context);
-
typedef gboolean (*MonoGetCachedClassInfo) (MonoClass *klass, MonoCachedClassInfo *res);
typedef gboolean (*MonoGetClassFromName) (MonoImage *image, const char *name_space, const char *name, MonoClass **res);
mono_install_delegate_trampoline (MonoDelegateTrampoline func);
gpointer
-mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context);
+mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error);
gpointer
-mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean check_token, MonoClass **handle_class, MonoGenericContext *context);
-
-void
-mono_install_lookup_dynamic_token (MonoLookupDynamicToken func);
+mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean check_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
gpointer
mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper);
mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
return NULL;
}
- klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
+ klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
goto done;
}
mono_error_init (error);
//FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
- if (image_is_dynamic (image))
- return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
+ if (image_is_dynamic (image)) {
+ MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
+ return_val_if_nok (error, NULL);
+ return mono_class_get_type (klass);
+ }
if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
MonoClass *klass = mono_class_get_checked (image, type_token, error);
if (image_is_dynamic (image)) {
MonoClass *tmp_handle_class;
- gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
+ gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
+ mono_error_assert_ok (error);
g_assert (tmp_handle_class);
if (handle_class)
*handle_class = tmp_handle_class;
return NULL;
}
-/**
- * This function might need to call runtime functions so it can't be part
- * of the metadata library.
- */
-static MonoLookupDynamicToken lookup_dynamic = NULL;
-
-void
-mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
-{
- lookup_dynamic = func;
-}
-
gpointer
-mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
+mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
{
MonoClass *handle_class;
-
- return lookup_dynamic (image, token, TRUE, &handle_class, context);
+ mono_error_init (error);
+ return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
}
gpointer
-mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
+mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
{
- return lookup_dynamic (image, token, valid_token, handle_class, context);
+ return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
}
static MonoGetCachedClassInfo get_cached_class_info = NULL;
ICALL(PROCESS_13, "ShellExecuteEx_internal(System.Diagnostics.ProcessStartInfo,System.Diagnostics.Process/ProcInfo&)", ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal)
#endif /* !DISABLE_PROCESS_HANDLING */
-ICALL_TYPE(SFRAME, "System.Diagnostics.StackFrame", SFRAME_1)
-ICALL(SFRAME_1, "GetILOffsetFromFile", ves_icall_System_StackFrame_GetILOffsetFromFile)
-
ICALL_TYPE(STOPWATCH, "System.Diagnostics.Stopwatch", STOPWATCH_1)
ICALL(STOPWATCH_1, "GetTimestamp", mono_100ns_ticks)
return NULL;
}
- if (mono_security_core_clr_enabled ())
- mono_security_core_clr_ensure_reflection_access_field (cf);
+ if (mono_security_core_clr_enabled () &&
+ !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
mono_error_set_pending_exception (&error);
return;
}
- if (mono_security_core_clr_enabled ())
- mono_security_core_clr_ensure_reflection_access_field (cf);
+ if (mono_security_core_clr_enabled () &&
+ !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
+ mono_error_set_pending_exception (&error);
+ return;
+ }
type = mono_field_get_type_checked (cf, &error);
if (!mono_error_ok (&error)) {
*exc = NULL;
- if (mono_security_core_clr_enabled ())
- mono_security_core_clr_ensure_reflection_access_method (m);
+ if (mono_security_core_clr_enabled () &&
+ !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
mono_metadata_decode_blob_size (sig, &sig);
return (*sig != 0x6);
} else {
+ MonoError error;
MonoClass *handle_class;
- if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
+ if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
+ mono_error_cleanup (&error); /* just probing, ignore error */
return FALSE;
+ }
return mono_defaults.methodhandle_class == handle_class;
}
if (image_is_dynamic (image)) {
if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
- klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+ klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+ mono_error_cleanup (&error);
return klass ? &klass->byval_arg : NULL;
}
init_generic_context_from_args (&context, type_args, method_args);
- klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
+ klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
+ mono_error_cleanup (&error);
return klass ? &klass->byval_arg : NULL;
}
}
if (image_is_dynamic (image)) {
- if (table == MONO_TABLE_METHOD)
- return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+ if (table == MONO_TABLE_METHOD) {
+ method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+ mono_error_cleanup (&error);
+ return method;
+ }
if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
*resolve_error = ResolveTokenError_BadTable;
}
init_generic_context_from_args (&context, type_args, method_args);
- return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
+ method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
+ mono_error_cleanup (&error);
+ return method;
}
if ((index <= 0) || (index > image->tables [table].rows)) {
}
ICALL_EXPORT MonoString*
-ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
+ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
{
+ MonoError error;
int index = mono_metadata_token_index (token);
- *error = ResolveTokenError_Other;
+ *resolve_error = ResolveTokenError_Other;
/* Validate token */
if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
- *error = ResolveTokenError_BadTable;
+ *resolve_error = ResolveTokenError_BadTable;
return NULL;
}
- if (image_is_dynamic (image))
- return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+ if (image_is_dynamic (image)) {
+ MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+ mono_error_cleanup (&error);
+ return result;
+ }
if ((index <= 0) || (index >= image->heap_us.size)) {
- *error = ResolveTokenError_OutOfRange;
+ *resolve_error = ResolveTokenError_OutOfRange;
return NULL;
}
}
if (image_is_dynamic (image)) {
- if (table == MONO_TABLE_FIELD)
- return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+ if (table == MONO_TABLE_FIELD) {
+ field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+ mono_error_cleanup (&error);
+ return field;
+ }
if (mono_memberref_is_method (image, token)) {
*resolve_error = ResolveTokenError_BadTable;
}
init_generic_context_from_args (&context, type_args, method_args);
- return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
+ field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
+ mono_error_cleanup (&error);
+ return field;
}
if ((index <= 0) || (index > image->tables [table].rows)) {
}
if (mono_security_core_clr_enabled ()) {
- if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
+ if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
+ if (throwOnBindFailure)
+ mono_error_set_pending_exception (&error);
+ else
+ mono_error_cleanup (&error);
return NULL;
+ }
}
delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
return message;
}
-ICALL_EXPORT int
-ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
-{
- guint32 il_offset;
- char *path_str = mono_string_to_utf8 (path);
-
- if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
- il_offset = -1;
-
- g_free (path_str);
-
- return il_offset;
-}
-
ICALL_EXPORT gpointer
ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
{
MonoClass *handle_class;
*retklass = NULL;
- result = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context);
+ MonoError inner_error;
+ result = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context, &inner_error);
+ mono_error_cleanup (&inner_error);
// This checks the memberref type as well
if (!result || handle_class != mono_defaults.fieldhandle_class) {
mono_error_set_bad_image (error, image, "Bad field token 0x%08x", token);
static MonoMethodHeader*
inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context, MonoError *error)
{
- MonoMethodHeader *res;
- int i;
- res = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + sizeof (gpointer) * header->num_locals);
+ size_t locals_size = sizeof (gpointer) * header->num_locals;
+ size_t clauses_size = header->num_clauses * sizeof (MonoExceptionClause);
+ size_t header_size = MONO_SIZEOF_METHOD_HEADER + locals_size + clauses_size;
+ MonoMethodHeader *res = (MonoMethodHeader *)g_malloc0 (header_size);
+ res->num_locals = header->num_locals;
+ res->clauses = (MonoExceptionClause *) &res->locals [res->num_locals] ;
+ memcpy (res->clauses, header->clauses, clauses_size);
+
res->code = header->code;
res->code_size = header->code_size;
res->max_stack = header->max_stack;
res->num_clauses = header->num_clauses;
res->init_locals = header->init_locals;
- res->num_locals = header->num_locals;
- res->clauses = header->clauses;
+
+ res->is_transient = TRUE;
mono_error_init (error);
- for (i = 0; i < header->num_locals; ++i) {
+ for (int i = 0; i < header->num_locals; ++i) {
res->locals [i] = mono_class_inflate_generic_type_checked (header->locals [i], context, error);
if (!is_ok (error))
goto fail;
}
if (res->num_clauses) {
- res->clauses = (MonoExceptionClause *)g_memdup (header->clauses, sizeof (MonoExceptionClause) * res->num_clauses);
- for (i = 0; i < header->num_clauses; ++i) {
+ for (int i = 0; i < header->num_clauses; ++i) {
MonoExceptionClause *clause = &res->clauses [i];
if (clause->flags != MONO_EXCEPTION_CLAUSE_NONE)
continue;
if (image_is_dynamic (image)) {
MonoClass *handle_class;
- result = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context);
+ result = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context, error);
+ mono_error_assert_ok (error);
mono_loader_assert_no_error ();
// This checks the memberref type as well
return NULL;
}
- mono_image_lock (img);
-
- if (imethod->header) {
- mono_metadata_free_mh (iheader);
- mono_image_unlock (img);
- return imethod->header;
- }
-
- mono_memory_barrier ();
- imethod->header = iheader;
-
- mono_image_unlock (img);
-
- return imethod->header;
+ return iheader;
}
if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) {
}
static void
-register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
+register_icall (gpointer func, const char *name, const char *sigstr, gboolean no_wrapper)
{
MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
- mono_register_jit_icall (func, name, sig, save);
+ mono_register_jit_icall (func, name, sig, no_wrapper);
}
MonoMethodSignature*
guint32 sig;
const char *ptr;
- if (image_is_dynamic (image))
- return (MonoMethodSignature *)mono_lookup_dynamic_token (image, token, NULL);
+ if (image_is_dynamic (image)) {
+ ret = (MonoMethodSignature *)mono_lookup_dynamic_token (image, token, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ return ret;
+ }
g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
if (method->signature)
mono_metadata_free_inflated_signature (method->signature);
- if (!((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))) {
- MonoMethodHeader *header = imethod->header;
-
- if (header) {
- /* Allocated in inflate_generic_header () */
- for (i = 0; i < header->num_locals; ++i)
- mono_metadata_free_type (header->locals [i]);
- g_free (header->clauses);
- g_free (header);
- }
- }
-
g_free (method);
}
return FALSE;
type->data.klass = mono_class_from_mono_type (etype);
+
+ if (transient)
+ mono_metadata_free_type (etype);
+
g_assert (type->data.klass); //This was previously a check for NULL, but mcfmt should never fail. It can return a borken MonoClass, but should return at least something.
break;
}
* Return the list of basic blocks of method. Return NULL on failure and set @error.
*/
MonoSimpleBasicBlock*
-mono_basic_block_split (MonoMethod *method, MonoError *error)
+mono_basic_block_split (MonoMethod *method, MonoError *error, MonoMethodHeader *header)
{
MonoError inner_error;
MonoSimpleBasicBlock *bb, *root;
const unsigned char *start, *end;
- MonoMethodHeader *header = mono_method_get_header_checked (method, &inner_error);
-
- mono_error_init (error);
-
- if (!header) {
- mono_error_set_not_verifiable (error, method, "Could not decode header due to %s", mono_error_get_message (&inner_error));
- mono_error_cleanup (&inner_error);
- return NULL;
- }
start = header->code;
end = start + header->code_size;
dump_bb_list (bb, &root, g_strdup_printf("AFTER LIVENESS %s", mono_method_full_name (method, TRUE)));
#endif
- mono_metadata_free_mh (header);
return bb;
fail:
- mono_metadata_free_mh (header);
mono_basic_block_free (bb);
return NULL;
}
};
MonoSimpleBasicBlock*
-mono_basic_block_split (MonoMethod *method, MonoError *error);
+mono_basic_block_split (MonoMethod *method, MonoError *error, MonoMethodHeader *header);
void
mono_basic_block_free (MonoSimpleBasicBlock *bb);
MonoReflectionMarshalAsAttribute* mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass, MonoMarshalSpec *spec, MonoError *error);
gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context);
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
gboolean
mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error);
mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
if (image->dynamic) {
- MonoString *str = (MonoString *)mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL);
+ MonoString *str = (MonoString *)mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
return str;
} else {
if (!mono_verifier_verify_string_signature (image, idx, NULL))
* LOCKING: Take the loader lock
*/
gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
{
- MonoError error;
MonoDynamicImage *assembly = (MonoDynamicImage*)image;
MonoObject *obj;
MonoClass *klass;
+ mono_error_init (error);
+
obj = lookup_dyn_token (assembly, token);
if (!obj) {
if (valid_token)
g_error ("Could not find required dynamic token 0x%08x", token);
- else
+ else {
+ mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
return NULL;
+ }
}
if (!handle_class)
handle_class = &klass;
- gpointer result = resolve_object (image, obj, handle_class, context, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ gpointer result = resolve_object (image, obj, handle_class, context, error);
return result;
}
* Transparent code cannot access to Critical fields and can only use
* them if they are visible from it's point of view.
*
- * A FieldAccessException is thrown if the field is cannot be accessed.
+ * Returns TRUE if acess is allowed. Otherwise returns FALSE and sets @error to a FieldAccessException if the field is cannot be accessed.
*/
-void
-mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field)
+gboolean
+mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field, MonoError *error)
{
+ mono_error_init (error);
MonoMethod *caller = get_reflection_caller ();
/* CoreCLR restrictions applies to Transparent code/caller */
if (mono_security_core_clr_method_level (caller, TRUE) != MONO_SECURITY_CORE_CLR_TRANSPARENT)
- return;
+ return TRUE;
if (mono_security_core_clr_get_options () & MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_REFLECTION) {
if (!mono_security_core_clr_is_platform_image (mono_field_get_parent(field)->image))
- return;
+ return TRUE;
}
/* Transparent code cannot [get|set]value on Critical fields */
if (mono_security_core_clr_class_level (mono_field_get_parent (field)) == MONO_SECURITY_CORE_CLR_CRITICAL) {
- mono_raise_exception (get_field_access_exception (
+ mono_error_set_exception_instance (error, get_field_access_exception (
"Transparent method %s cannot get or set Critical field %s.",
caller, field));
+ return FALSE;
}
/* also it cannot access a fields that is not visible from it's (caller) point of view */
if (!check_field_access (caller, field)) {
- mono_raise_exception (get_field_access_exception (
+ mono_error_set_exception_instance (error, get_field_access_exception (
"Transparent method %s cannot get or set private/internal field %s.",
caller, field));
+ return FALSE;
}
+ return TRUE;
}
/*
* Transparent code cannot call Critical methods and can only call them
* if they are visible from it's point of view.
*
- * A MethodAccessException is thrown if the field is cannot be accessed.
+ * If access is allowed returns TRUE. Returns FALSE and sets @error to a MethodAccessException if the field is cannot be accessed.
*/
-void
-mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method)
+gboolean
+mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method, MonoError *error)
{
+ mono_error_init (error);
MonoMethod *caller = get_reflection_caller ();
/* CoreCLR restrictions applies to Transparent code/caller */
if (mono_security_core_clr_method_level (caller, TRUE) != MONO_SECURITY_CORE_CLR_TRANSPARENT)
- return;
+ return TRUE;
if (mono_security_core_clr_get_options () & MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_REFLECTION) {
if (!mono_security_core_clr_is_platform_image (method->klass->image))
- return;
+ return TRUE;
}
/* Transparent code cannot invoke, even using reflection, Critical code */
if (mono_security_core_clr_method_level (method, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL) {
- mono_raise_exception (get_method_access_exception (
+ mono_error_set_exception_instance (error, get_method_access_exception (
"Transparent method %s cannot invoke Critical method %s.",
caller, method));
+ return FALSE;
}
/* also it cannot invoke a method that is not visible from it's (caller) point of view */
if (!check_method_access (caller, method)) {
- mono_raise_exception (get_method_access_exception (
+ mono_error_set_exception_instance (error, get_method_access_exception (
"Transparent method %s cannot invoke private/internal method %s.",
caller, method));
+ return FALSE;
}
+ return TRUE;
}
/*
/*
* mono_security_core_clr_ensure_delegate_creation:
*
- * Return TRUE if a delegate can be created on the specified method.
- * CoreCLR also affect the binding, so throwOnBindFailure must be
- * FALSE to let this function return (FALSE) normally, otherwise (if
- * throwOnBindFailure is TRUE) it will throw an ArgumentException.
+ * Return TRUE if a delegate can be created on the specified
+ * method. CoreCLR can also affect the binding, this function may
+ * return (FALSE) and set @error to an ArgumentException.
*
- * A MethodAccessException is thrown if the specified method is not
+ * @error is set to a MethodAccessException if the specified method is not
* visible from the caller point of view.
*/
gboolean
-mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, gboolean throwOnBindFailure)
+mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, MonoError *error)
{
MonoMethod *caller;
+ mono_error_init (error);
+
/* note: mscorlib creates delegates to avoid reflection (optimization), we ignore those cases */
if (can_avoid_corlib_reflection_delegate_optimization (method))
return TRUE;
/* otherwise it (as a Transparent caller) cannot create a delegate on a Critical method... */
if (mono_security_core_clr_method_level (method, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL) {
- /* but this throws only if 'throwOnBindFailure' is TRUE */
- if (!throwOnBindFailure)
- return FALSE;
-
- mono_raise_exception (get_argument_exception (
+ mono_error_set_exception_instance (error, get_argument_exception (
"Transparent method %s cannot create a delegate on Critical method %s.",
caller, method));
+ return FALSE;
}
if (mono_security_core_clr_get_options () & MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_DELEGATE) {
/* also it cannot create the delegate on a method that is not visible from it's (caller) point of view */
if (!check_method_access (caller, method)) {
- mono_raise_exception (get_method_access_exception (
+ mono_error_set_exception_instance (error, get_method_access_exception (
"Transparent method %s cannot create a delegate on private/internal method %s.",
caller, method));
+ return FALSE;
}
return TRUE;
return FALSE;
}
-void
-mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field)
+gboolean
+mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field, MonoError *error)
{
+ mono_error_init (error);
+ return TRUE;
}
void
-mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method)
+mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method, MonoError *error)
{
+ mono_error_init (error);
+ return TRUE;
}
gboolean
-mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, gboolean throwOnBindFailure)
+mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, MonoError *error)
{
+ mono_error_init (error);
return TRUE;
}
extern void mono_security_core_clr_check_inheritance (MonoClass *klass);
extern void mono_security_core_clr_check_override (MonoClass *klass, MonoMethod *override, MonoMethod *base);
-extern void mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field);
-extern void mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method);
-extern gboolean mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, gboolean throwOnBindFailure);
+extern gboolean
+mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field, MonoError *error);
+extern gboolean
+mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method, MonoError *error);
+extern gboolean mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, MonoError *error);
extern MonoException* mono_security_core_clr_ensure_dynamic_method_resolved_object (gpointer ref, MonoClass *handle_class);
extern gboolean mono_security_core_clr_can_access_internals (MonoImage *accessing, MonoImage* accessed);
#define SGEN_TV_DECLARE(name) gint64 name
#define SGEN_TV_GETTIME(tv) tv = mono_100ns_ticks ()
-#define SGEN_TV_ELAPSED(start,end) ((long)(end-start))
+#define SGEN_TV_ELAPSED(start,end) ((gint64)(end-start))
typedef MonoSemType SgenSemaphore;
#include "metadata/handle.h"
#include "utils/mono-memory-model.h"
#include "utils/mono-logger-internals.h"
+#include "sgen/sgen-thread-pool.h"
#ifdef HEAVY_STATISTICS
static guint64 stat_wbarrier_set_arrayref = 0;
void
mono_gc_base_cleanup (void)
{
+ sgen_thread_pool_shutdown ();
}
gboolean
DEF_QSORT_INLINE(hash_entries, HashEntry*, compare_hash_entries)
-static unsigned long step_1, step_2, step_3, step_4, step_5, step_6;
+static gint64 step_1, step_2, step_3, step_4, step_5, step_6;
static int fist_pass_links, second_pass_links, sccs_links;
static int max_sccs_links = 0;
DEF_QSORT_INLINE(hash_entries, HashEntry*, compare_hash_entries)
-static unsigned long step_1, step_2, step_3, step_4, step_5, step_6;
+static gint64 step_1, step_2, step_3, step_4, step_5, step_6;
static int fist_pass_links, second_pass_links, sccs_links;
static int max_sccs_links = 0;
if (interrupted)
goto done;
- if (mono_coop_cond_timedwait (&threadpool->parked_threads_cond, &threadpool->active_threads_lock, rand_next ((void **)rand_handle, 5 * 1000, 60 * 1000)) != 0)
+ if (mono_coop_cond_timedwait (&threadpool->parked_threads_cond, &threadpool->active_threads_lock, rand_next (&rand_handle, 5 * 1000, 60 * 1000)) != 0)
timeout = TRUE;
mono_thread_info_uninstall_interrupt (&interrupted);
if (!ctx.valid)
goto cleanup;
- original_bb = bb = mono_basic_block_split (method, &error);
+ original_bb = bb = mono_basic_block_split (method, &error, ctx.header);
if (!mono_error_ok (&error)) {
ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid branch target: %s", mono_error_get_message (&error)));
mono_error_cleanup (&error);
fullaotcheck: $(mono) $(fullaot_regtests)
rm -rf fullaot-tmp
mkdir fullaot-tmp
- $(MAKE) fullaot-libs AOT_FLAGS=full GSHAREDVT=$(GSHAREDVT)
+ $(MAKE) fullaot-libs AOT_FLAGS="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" GSHAREDVT=$(GSHAREDVT)
cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
- MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot=full fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
+ MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
ln -s $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),$$PWD/mono) fullaot-tmp/
for i in $(fullaot_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --full-aot fullaot-tmp/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done
llvmonlycheck: mono $(llvmonly_regtests)
rm -rf fullaot-tmp
mkdir fullaot-tmp
- $(MAKE) fullaot-libs AOT_FLAGS=llvmonly
+ $(MAKE) fullaot-libs AOT_FLAGS="llvmonly,$(MONO_FULLAOT_ADDITIONAL_ARGS)"
cp $(llvmonly_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --aot=llvmonly fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
ln -s $$PWD/mono fullaot-tmp/
return clean;
}
+// Duplicate a char range and add it to a ptrarray, but only if it is nonempty
+static void
+ptr_array_add_range_if_nonempty(GPtrArray *args, gchar const *start, gchar const *end)
+{
+ ptrdiff_t len = end-start;
+ if (len > 0)
+ g_ptr_array_add (args, g_strndup (start, len));
+}
+
static GPtrArray *
mono_aot_split_options (const char *aot_options)
{
next:
aot_options++;
+ restart:
// If the next character is end of string, then process the last option.
if (*(aot_options) == '\0') {
end_of_string = TRUE;
continue;
new_opt:
- g_ptr_array_add (args, g_strndup (opt_start, aot_options - opt_start));
+ ptr_array_add_range_if_nonempty (args, opt_start, aot_options);
opt_start = ++aot_options;
if (end_of_string)
break;
- goto next;
+ goto restart; // Check for null and continue loop
}
return args;
#define AS_OPTIONS "--64"
#elif defined(TARGET_POWERPC64)
#define AS_OPTIONS "-a64 -mppc64"
-#define LD_OPTIONS "-m elf64ppc"
#elif defined(sparc) && SIZEOF_VOID_P == 8
#define AS_OPTIONS "-xarch=v9"
#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
#define AS_NAME "as"
#endif
-#ifndef LD_OPTIONS
-#define LD_OPTIONS ""
-#endif
-
#if defined(sparc)
-#define LD_NAME "ld -shared -G"
+#define LD_NAME "ld"
+#define LD_OPTIONS "-shared -G"
#elif defined(__ppc__) && defined(TARGET_MACH)
-#define LD_NAME "gcc -dynamiclib"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "-dynamiclib"
#elif defined(TARGET_AMD64) && defined(TARGET_MACH)
-#define LD_NAME "clang --shared"
+#define LD_NAME "clang"
+#define LD_OPTIONS "--shared"
#elif defined(TARGET_WIN32) && !defined(TARGET_ANDROID)
-#define LD_NAME "gcc -shared --dll"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "-shared"
#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
-#define LD_NAME "clang -m32 -dynamiclib"
+#define LD_NAME "clang"
+#define LD_OPTIONS "-m32 -dynamiclib"
#elif defined(TARGET_ARM) && !defined(TARGET_ANDROID)
-#define LD_NAME "gcc --shared"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "--shared"
+#elif defined(TARGET_POWERPC64)
+#define LD_OPTIONS "-m elf64ppc"
+#endif
+
+#ifndef LD_OPTIONS
+#define LD_OPTIONS ""
#endif
if (acfg->aot_opts.asm_only) {
ld_flags = g_strdup_printf ("%s %s", ld_flags, "-lstdc++");
#ifdef LD_NAME
- command = g_strdup_printf ("%s -o %s %s %s %s", LD_NAME,
+ command = g_strdup_printf ("%s%s %s -o %s %s %s %s", tool_prefix, LD_NAME, LD_OPTIONS,
wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
#else
+ // Default (linux)
command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, stack_size + sizeof(mgreg_t));
amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (AMD64_RSP * sizeof(mgreg_t)), X86_EAX, sizeof(mgreg_t));
/* Save IP */
- if (llvm_abs)
- amd64_alu_reg_reg (code, X86_XOR, AMD64_RAX, AMD64_RAX);
- else
- amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, stack_size, sizeof(mgreg_t));
+ amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, stack_size, sizeof(mgreg_t));
amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (AMD64_RIP * sizeof(mgreg_t)), AMD64_RAX, sizeof(mgreg_t));
/* Set arg1 == ctx */
amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, ctx_offset);
if (resume_unwind) {
amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], 0, sizeof(mgreg_t));
} else if (corlib) {
- amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG2, sizeof(mgreg_t));
if (llvm_abs)
- /*
- * The caller is LLVM code which passes the absolute address not a pc offset,
- * so compensate by passing 0 as 'rip' and passing the negated abs address as
- * the pc offset.
+ /*
+ * The caller doesn't pass in a pc/pc offset, instead we simply use the
+ * caller ip. Negate the pc adjustment done in mono_amd64_throw_corlib_exception ().
*/
- amd64_neg_membase (code, AMD64_RSP, arg_offsets [2]);
+ amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], 1, sizeof(mgreg_t));
+ else
+ amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG2, sizeof(mgreg_t));
} else {
amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], rethrow, sizeof(mgreg_t));
}
}
void
-mono_arm_throw_exception_by_token (guint32 type_token, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
+mono_arm_throw_exception_by_token (guint32 ex_token_index, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
{
+ guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
/* Clear thumb bit */
pc &= ~1;
- mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, type_token), pc, sp, int_regs, fp_regs);
+ mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token), pc, sp, int_regs, fp_regs);
}
void
/* exc is already in place in r0 */
if (corlib) {
/* The caller ip is already in R1 */
- if (llvm)
- /* Negate the ip adjustment done in mono_arm_throw_exception */
- ARM_ADD_REG_IMM8 (code, ARMREG_R1, ARMREG_R1, 4);
+ if (llvm) {
+ /*
+ * The address passed by llvm might point to before the call,
+ * thus outside the eh range recorded by llvm. Use the return
+ * address instead.
+ * FIXME: Do this on more platforms.
+ */
+ ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
+ }
} else {
ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
}
unw_word_t ip, sp;
int res;
- if (mono_object_isinst (exc, mono_defaults.exception_class, &error)) {
+ if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
MonoException *mono_ex = (MonoException*)exc;
if (!rethrow) {
mono_ex->stack_trace = NULL;
memcpy (&ctx.regs, int_regs, sizeof (mgreg_t) * MONO_SAVED_GREGS);
memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_SAVED_FREGS);
- if (mono_object_isinst (exc, mono_defaults.exception_class, &error)) {
+ if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
MonoException *mono_ex = (MonoException*)exc;
if (!rethrow) {
mono_ex->stack_trace = NULL;
#define eat_whitespace(s) while (*(s) && isspace (*(s))) s++;
+// Per spec isalnum() expects input in the range 0-255
+// and can misbehave if you pass in a signed char.
+static int
+isalnum_char(char c)
+{
+ return isalnum ((unsigned char)c);
+}
+
static int
load_file (const char *name) {
FILE *f;
OpDesc *tdesc;
p += 9;
tname = p;
- while (*p && isalnum (*p)) ++p;
+ while (*p && isalnum_char (*p)) ++p;
*p++ = 0;
tdesc = (OpDesc *)g_hash_table_lookup (template_table, tname);
if (!tdesc)
g_error ("Duplicated name tag in template %s at '%s' at line %d in %s\n", desc->name, p, line, name);
p += 5;
tname = p;
- while (*p && isalnum (*p)) ++p;
+ while (*p && isalnum_char (*p)) ++p;
*p++ = 0;
if (g_hash_table_lookup (template_table, tname))
g_error ("Duplicated template %s at line %d in %s\n", tname, line, name);
static void
output_char (FILE *f, char c) {
- if (isalnum (c))
+ if (isalnum_char (c))
fprintf (f, "%c", c);
else
fprintf (f, "\\x%x\" \"", (guint8)c);
stype = "object";
asm_writer_emit_unset_mode (acfg);
+
#if defined(TARGET_ASM_APPLE)
+#elif defined(TARGET_WIN32)
+ if (func)
+ fprintf (acfg->fp, "\t.def %s; .scl 2; .type 32; .endef\n", name);
+ else
+ fprintf (acfg->fp, "\t.data\n");
#elif defined(TARGET_ARM)
fprintf (acfg->fp, "\t.type %s,#%s\n", name, stype);
#else
{
asm_writer_emit_unset_mode (acfg);
-#ifndef TARGET_ASM_APPLE
+#if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
fprintf (acfg->fp, "\t.local %s\n", name);
#endif
{
asm_writer_emit_unset_mode (acfg);
-#ifndef TARGET_ASM_APPLE
+
+#if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
fprintf (acfg->fp, "\t.size %s,%s-%s\n", name, end_label, name);
#endif
}
skip_dead_blocks = !dont_verify;
if (skip_dead_blocks) {
- original_bb = bb = mono_basic_block_split (method, &cfg->error);
+ original_bb = bb = mono_basic_block_split (method, &cfg->error, header);
CHECK_CFG_ERROR;
g_assert (bb);
}
patch_info->ip.i = code - cfg->native_code;
ARM_BL (code, 0);
cfg->thunk_area += THUNK_SIZE;
- *(guint32*)(gpointer)code = exc_class->type_token;
+ *(guint32*)(gpointer)code = exc_class->type_token - MONO_TOKEN_TYPE_DEF;
code += 4;
#endif
break;
MonoClass *exc_class;
LLVMValueRef args [2];
LLVMValueRef callee;
+ gboolean no_pc = FALSE;
+
+ if (IS_TARGET_AMD64)
+ /* Some platforms don't require the pc argument */
+ no_pc = TRUE;
ex_bb = gen_bb (ctx, "EX_BB");
if (ctx->llvm_only)
LLVMTypeRef sig;
const char *icall_name;
- sig = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), LLVMPointerType (LLVMInt8Type (), 0), FALSE);
+ if (no_pc)
+ sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
+ else
+ sig = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), LLVMPointerType (LLVMInt8Type (), 0), FALSE);
icall_name = "llvm_throw_corlib_exception_abs_trampoline";
if (ctx->cfg->compile_aot) {
}
}
- if (IS_TARGET_X86 || IS_TARGET_AMD64)
- args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
- else
- args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token, FALSE);
+ args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
/*
* The LLVM mono branch contains changes so a block address can be passed as an
* argument to a call.
*/
- args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
- emit_call (ctx, bb, &builder, callee, args, 2);
+ if (no_pc) {
+ emit_call (ctx, bb, &builder, callee, args, 1);
+ } else {
+ args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
+ emit_call (ctx, bb, &builder, callee, args, 2);
+ }
LLVMBuildUnreachable (builder);
mono_runtime_install_handlers (void)
{
#ifndef MONO_CROSS_COMPILE
- win32_seh_init();
- win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
- win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
- win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
- if (mini_get_debug_options ()->handle_sigint)
- win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
+ if (!mono_aot_only) {
+ win32_seh_init();
+ win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
+ win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
+ win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
+ if (mini_get_debug_options ()->handle_sigint)
+ win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
+ }
#endif
}
mono_runtime_cleanup_handlers (void)
{
#ifndef MONO_CROSS_COMPILE
- win32_seh_cleanup();
+ if (!mono_aot_only) {
+ win32_seh_cleanup();
+ }
#endif
}
sgen_client_clear_togglerefs (start_addr, end_addr, ctx);
TV_GETTIME (btv);
- SGEN_LOG (2, "Finalize queue handling scan for %s generation: %ld usecs %d ephemeron rounds", generation_name (generation), TV_ELAPSED (atv, btv), ephemeron_rounds);
+ SGEN_LOG (2, "Finalize queue handling scan for %s generation: %lld usecs %d ephemeron rounds", generation_name (generation), TV_ELAPSED (atv, btv), ephemeron_rounds);
/*
* handle disappearing links
TV_GETTIME (atv);
time_minor_pinning += TV_ELAPSED (btv, atv);
- SGEN_LOG (2, "Finding pinned pointers: %zd in %ld usecs", sgen_get_pinned_count (), TV_ELAPSED (btv, atv));
+ SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), TV_ELAPSED (btv, atv));
SGEN_LOG (4, "Start scan with %zd pinned objects", sgen_get_pinned_count ());
sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan remset", job_remembered_set_scan, sizeof (ScanJob));
/* we don't have complete write barrier yet, so we scan all the old generation sections */
TV_GETTIME (btv);
time_minor_scan_remsets += TV_ELAPSED (atv, btv);
- SGEN_LOG (2, "Old generation scan: %ld usecs", TV_ELAPSED (atv, btv));
+ SGEN_LOG (2, "Old generation scan: %lld usecs", TV_ELAPSED (atv, btv));
sgen_pin_stats_print_class_stats ();
sgen_client_binary_protocol_reclaim_end (GENERATION_NURSERY);
TV_GETTIME (btv);
time_minor_fragment_creation += TV_ELAPSED (atv, btv);
- SGEN_LOG (2, "Fragment creation: %ld usecs, %lu bytes available", TV_ELAPSED (atv, btv), (unsigned long)fragment_total);
+ SGEN_LOG (2, "Fragment creation: %lld usecs, %lu bytes available", TV_ELAPSED (atv, btv), (unsigned long)fragment_total);
if (consistency_check_at_minor_collection)
sgen_check_major_refs ();
sgen_client_pre_collection_checks ();
- if (!concurrent) {
+ if (mode != COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
/* Remsets are not useful for a major collection */
remset.clear_cards ();
}
sgen_init_pinning ();
SGEN_LOG (6, "Collecting pinned addresses");
pin_from_roots ((void*)lowest_heap_address, (void*)highest_heap_address, ctx);
-
+ if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
+ /* Pin cemented objects that were forced */
+ sgen_pin_cemented_objects ();
+ }
sgen_optimize_pin_queue ();
+ if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
+ /*
+ * Cemented objects that are in the pinned list will be marked. When
+ * marking concurrently we won't mark mod-union cards for these objects.
+ * Instead they will remain cemented until the next major collection,
+ * when we will recheck if they are still pinned in the roots.
+ */
+ sgen_cement_force_pinned ();
+ }
sgen_client_collecting_major_1 ();
TV_GETTIME (btv);
time_major_pinning += TV_ELAPSED (atv, btv);
- SGEN_LOG (2, "Finding pinned pointers: %zd in %ld usecs", sgen_get_pinned_count (), TV_ELAPSED (atv, btv));
+ SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), TV_ELAPSED (atv, btv));
SGEN_LOG (4, "Start scan with %zd pinned objects", sgen_get_pinned_count ());
major_collector.init_to_space ();
SGEN_ASSERT (0, sgen_workers_all_done (), "Why are the workers not done when we start or finish a major collection?");
- /*
- * The concurrent collector doesn't move objects, neither on
- * the major heap nor in the nursery, so we can mark even
- * before pinning has finished. For the non-concurrent
- * collector we start the workers after pinning.
- */
- if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
- if (precleaning_enabled) {
- ScanJob *sj;
- /* Mod union preclean job */
- sj = (ScanJob*)sgen_thread_pool_job_alloc ("preclean mod union cardtable", job_mod_union_preclean, sizeof (ScanJob));
- sj->ops = object_ops;
- sgen_workers_start_all_workers (object_ops, &sj->job);
- } else {
- sgen_workers_start_all_workers (object_ops, NULL);
- }
- gray_queue_enable_redirect (WORKERS_DISTRIBUTE_GRAY_QUEUE);
- } else if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
+ if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
if (sgen_workers_have_idle_work ()) {
+ /*
+ * We force the finish of the worker with the new object ops context
+ * which can also do copying. We need to have finished pinning.
+ */
sgen_workers_start_all_workers (object_ops, NULL);
sgen_workers_join ();
}
sgen_client_collecting_major_3 (&fin_ready_queue, &critical_fin_queue);
- /*
- * FIXME: is this the right context? It doesn't seem to contain a copy function
- * unless we're concurrent.
- */
- enqueue_scan_from_roots_jobs (heap_start, heap_end, object_ops, mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT);
+ enqueue_scan_from_roots_jobs (heap_start, heap_end, object_ops, FALSE);
TV_GETTIME (btv);
time_major_scan_roots += TV_ELAPSED (atv, btv);
+ /*
+ * We start the concurrent worker after pinning and after we scanned the roots
+ * in order to make sure that the worker does not finish before handling all
+ * the roots.
+ */
+ if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
+ if (precleaning_enabled) {
+ ScanJob *sj;
+ /* Mod union preclean job */
+ sj = (ScanJob*)sgen_thread_pool_job_alloc ("preclean mod union cardtable", job_mod_union_preclean, sizeof (ScanJob));
+ sj->ops = object_ops;
+ sgen_workers_start_all_workers (object_ops, &sj->job);
+ } else {
+ sgen_workers_start_all_workers (object_ops, NULL);
+ }
+ gray_queue_enable_redirect (WORKERS_DISTRIBUTE_GRAY_QUEUE);
+ }
+
if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
ScanJob *sj;
major_finish_copy_or_mark (CopyOrMarkFromRootsMode mode)
{
if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
- /*
- * Prepare the pin queue for the next collection. Since pinning runs on the worker
- * threads we must wait for the jobs to finish before we can reset it.
- */
- sgen_workers_wait_for_jobs_finished ();
sgen_finish_pinning ();
sgen_pin_stats_reset ();
COPY_OR_MARK_FUNCTION_NAME ((ptr), __old, queue); \
} \
} else { \
- if (G_UNLIKELY (sgen_ptr_in_nursery (__old) && !sgen_ptr_in_nursery ((ptr)))) \
+ if (G_UNLIKELY (sgen_ptr_in_nursery (__old) && !sgen_ptr_in_nursery ((ptr)) && !sgen_cement_is_forced (__old))) \
mark_mod_union_card ((full_object), (void**)(ptr), __old); \
} \
} while (0)
PREFETCH_READ (__old); \
COPY_OR_MARK_FUNCTION_NAME ((ptr), __old, queue); \
} else { \
- if (G_UNLIKELY (sgen_ptr_in_nursery (__old) && !sgen_ptr_in_nursery ((ptr)))) \
+ if (G_UNLIKELY (sgen_ptr_in_nursery (__old) && !sgen_ptr_in_nursery ((ptr)) && !sgen_cement_is_forced (__old))) \
mark_mod_union_card ((full_object), (void**)(ptr), __old); \
} \
} while (0)
struct _CementHashEntry {
GCObject *obj;
unsigned int count;
+ gboolean forced; /* if it should stay cemented after the finishing pause */
};
static CementHashEntry cement_hash [SGEN_CEMENT_HASH_SIZE];
void
sgen_cement_reset (void)
{
- memset (cement_hash, 0, sizeof (cement_hash));
+ int i;
+ for (i = 0; i < SGEN_CEMENT_HASH_SIZE; i++) {
+ if (cement_hash [i].forced) {
+ cement_hash [i].forced = FALSE;
+ } else {
+ cement_hash [i].obj = NULL;
+ cement_hash [i].count = 0;
+ }
+ }
binary_protocol_cement_reset ();
}
+
+/*
+ * The pin_queue should be full and sorted, without entries from the cemented
+ * objects. We traverse the cement hash and check if each object is pinned in
+ * the pin_queue (the pin_queue contains entries between obj and obj+obj_len)
+ */
+void
+sgen_cement_force_pinned (void)
+{
+ int i;
+
+ if (!cement_enabled)
+ return;
+
+ for (i = 0; i < SGEN_CEMENT_HASH_SIZE; i++) {
+ GCObject *obj = cement_hash [i].obj;
+ size_t index;
+ if (!obj)
+ continue;
+ if (cement_hash [i].count < SGEN_CEMENT_THRESHOLD)
+ continue;
+ SGEN_ASSERT (0, !cement_hash [i].forced, "Why do we have a forced cemented object before forcing ?");
+
+ /* Returns the index of the target or of the first element greater than it */
+ index = sgen_pointer_queue_search (&pin_queue, obj);
+ if (index == pin_queue.next_slot)
+ continue;
+ SGEN_ASSERT (0, pin_queue.data [index] >= (gpointer)obj, "Binary search should return a pointer greater than the search target");
+ if (pin_queue.data [index] < (gpointer)((char*)obj + sgen_safe_object_get_size (obj)))
+ cement_hash [i].forced = TRUE;
+ }
+}
+
+gboolean
+sgen_cement_is_forced (GCObject *obj)
+{
+ guint hv = sgen_aligned_addr_hash (obj);
+ int i = SGEN_CEMENT_HASH (hv);
+
+ SGEN_ASSERT (5, sgen_ptr_in_nursery (obj), "Looking up cementing for non-nursery objects makes no sense");
+
+ if (!cement_enabled)
+ return FALSE;
+
+ if (!cement_hash [i].obj)
+ return FALSE;
+ if (cement_hash [i].obj != obj)
+ return FALSE;
+
+ return cement_hash [i].forced;
+}
+
gboolean
sgen_cement_lookup (GCObject *obj)
{
void sgen_cement_init (gboolean enabled);
void sgen_cement_reset (void);
+void sgen_cement_force_pinned (void);
+gboolean sgen_cement_is_forced (GCObject *obj);
gboolean sgen_cement_lookup (GCObject *obj);
gboolean sgen_cement_lookup_or_register (GCObject *obj);
void sgen_pin_cemented_objects (void);
static SgenThreadPoolIdleJobFunc idle_job_func;
static SgenThreadPoolContinueIdleJobFunc continue_idle_job_func;
+static volatile gboolean threadpool_shutdown;
+static volatile gboolean thread_finished;
+
enum {
STATE_WAITING,
STATE_IN_PROGRESS,
gboolean do_idle = continue_idle_job ();
SgenThreadPoolJob *job = get_job_and_set_in_progress ();
- if (!job && !do_idle) {
+ if (!job && !do_idle && !threadpool_shutdown) {
/*
* pthread_cond_wait() can return successfully despite the condition
* not being signalled, so we have to run this in a loop until we
* have to broadcast.
*/
mono_os_cond_signal (&done_cond);
- } else {
- SGEN_ASSERT (0, do_idle, "Why did we unlock if we still have to wait for idle?");
+ } else if (do_idle) {
SGEN_ASSERT (0, idle_job_func, "Why do we have idle work when there's no idle job function?");
do {
idle_job_func (thread_data);
if (!do_idle)
mono_os_cond_signal (&done_cond);
+ } else {
+ SGEN_ASSERT (0, threadpool_shutdown, "Why did we unlock if no jobs and not shutting down?");
+ mono_os_mutex_lock (&lock);
+ thread_finished = TRUE;
+ mono_os_cond_signal (&done_cond);
+ mono_os_mutex_unlock (&lock);
+ return 0;
}
}
mono_native_thread_create (&thread, thread_func, thread_datas ? thread_datas [0] : NULL);
}
+void
+sgen_thread_pool_shutdown (void)
+{
+ if (!thread)
+ return;
+
+ mono_os_mutex_lock (&lock);
+ threadpool_shutdown = TRUE;
+ mono_os_cond_signal (&work_cond);
+ while (!thread_finished)
+ mono_os_cond_wait (&done_cond, &lock);
+ mono_os_mutex_unlock (&lock);
+
+ mono_os_mutex_destroy (&lock);
+ mono_os_cond_destroy (&work_cond);
+ mono_os_cond_destroy (&done_cond);
+}
+
SgenThreadPoolJob*
sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size)
{
void sgen_thread_pool_init (int num_threads, SgenThreadPoolThreadInitFunc init_func, SgenThreadPoolIdleJobFunc idle_func, SgenThreadPoolContinueIdleJobFunc continue_idle_func, void **thread_datas);
+void sgen_thread_pool_shutdown (void);
+
SgenThreadPoolJob* sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size);
/* This only needs to be called on jobs that are not enqueued. */
void sgen_thread_pool_job_free (SgenThreadPoolJob *job);
$(ILASM) -out:$@ $<
%.exe: %.cs TestDriver.dll
- $(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll -out:$@ $<
+ $(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll -r:Mono.Posix.dll -out:$@ $<
# mkbundle works on ppc, but the pkg-config POC doesn't when run with make test
if POWERPC
using System.Globalization;
using System.Xml;
using System.Text.RegularExpressions;
+using Mono.Unix.Native;
//
// This is a simple test runner with support for parallel execution
timedout.Add (data);
}
+ // Force the process to print a thread dump
+ try {
+ Syscall.kill (p.Id, Signum.SIGQUIT);
+ Thread.Sleep (1000);
+ } catch {
+ }
+
output.Write ("timed out");
p.Kill ();