diff options
44 files changed, 1093 insertions, 567 deletions
diff --git a/configure.ac b/configure.ac index 600ad4c6d28..33c4d28a82c 100644 --- a/configure.ac +++ b/configure.ac @@ -3651,6 +3651,9 @@ AC_SUBST(CFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) +#This must always be defined when building the runtime +AC_DEFINE(MONO_INSIDE_RUNTIME,1, [Disable banned functions from being used by the runtime]) + mono_build_root=`pwd` AC_SUBST(mono_build_root) diff --git a/mcs/build/profiles/mobile_static.make b/mcs/build/profiles/mobile_static.make index f68e07be883..0c3c8125cfd 100644 --- a/mcs/build/profiles/mobile_static.make +++ b/mcs/build/profiles/mobile_static.make @@ -48,7 +48,7 @@ ifndef MONO_DISABLE_GSHAREDVT GSHAREDVT_FLAG = -O=gsharedvt endif -ifeq ($(MONO_LLVMONLY),TRUE) +ifneq ($(MONO_LLVMONLY),) AOT_BUILD_FLAGS_PREFIX = --aot=llvmonly, AOT_RUN_FLAGS = --llvmonly else diff --git a/mcs/build/rules.make b/mcs/build/rules.make index 7ff27755ec1..b79132991eb 100644 --- a/mcs/build/rules.make +++ b/mcs/build/rules.make @@ -143,7 +143,7 @@ endif # Set the options for building and running AOT # The trampoline numbers are provisional, they are what is required # to run the corlib test suite. They should be considered a lower bound. -INVARIANT_AOT_OPTIONS=bind-to-runtime-version,nimt-trampolines=900,ntrampolines=8000 +INVARIANT_AOT_OPTIONS=nimt-trampolines=900,ntrampolines=8000 ifndef MONO_DISABLE_GSHAREDVT INVARIANT_AOT_OPTIONS:=$(INVARIANT_AOT_OPTIONS),ngsharedvt-trampolines=900 diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs index aded011e986..f70bd99464b 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs @@ -646,8 +646,15 @@ namespace System.Xml.Serialization { if (memberValue == null) return null; Type type = memberValue.GetType(); - foreach (XmlTypeMapElementInfo elem in _itemInfo) - if (elem.TypeData.Type == type) return elem; + XmlTypeMapElementInfo bestMatch = null; + foreach (XmlTypeMapElementInfo elem in _itemInfo) { + if (elem.TypeData.Type == type) + return elem; + if (elem.TypeData.Type.IsAssignableFrom (type) && + (bestMatch == null || elem.TypeData.Type.IsAssignableFrom (bestMatch.TypeData.Type))) + bestMatch = elem; + } + return bestMatch; } return null; } diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs index 597acd1df54..116bbe323ad 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs @@ -711,6 +711,13 @@ namespace MonoTests.System.Xml.TestClasses public object data; } + public class SubclassTestList + { + [XmlElement ("a", typeof (SimpleClass))] + [XmlElement ("b", typeof (SubclassTestBase))] + public List<object> Items; + } + public class DictionaryWithIndexer : DictionaryBase { public TimeSpan this[int index] diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs index 4e51eceae03..bdd08aa7c69 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTests.cs @@ -1939,6 +1939,17 @@ namespace MonoTests.System.XmlSerialization Assert.AreEqual (Infoset (res), WriterText); } + [Test] // Covers #36829 + public void TestSubclassElementList () + { + var o = new SubclassTestList () { Items = new List<object> () { new SubclassTestSub () } }; + Serialize (o); + + string res = "<SubclassTestList xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>"; + res += "<b xsi:type=\"SubclassTestSub\"/></SubclassTestList>"; + Assert.AreEqual (Infoset (res), WriterText); + } + [Test] [ExpectedException (typeof (InvalidOperationException))] public void TestArrayAttributeWithWrongDataType () diff --git a/mcs/class/reference-assemblies/Makefile b/mcs/class/reference-assemblies/Makefile index dc8c9988fc9..20ff20005ca 100644 --- a/mcs/class/reference-assemblies/Makefile +++ b/mcs/class/reference-assemblies/Makefile @@ -7,13 +7,13 @@ all-local: PROFILE_DIR=$(DESTDIR)$(mono_libdir)/mono install-local: - $(MKINSTALLDIRS) $(PROFILE_DIR)/2.0 - $(MKINSTALLDIRS) $(PROFILE_DIR)/3.5 - $(MKINSTALLDIRS) $(PROFILE_DIR)/4.0 + $(MKINSTALLDIRS) $(PROFILE_DIR)/2.0-api + $(MKINSTALLDIRS) $(PROFILE_DIR)/3.5-api + $(MKINSTALLDIRS) $(PROFILE_DIR)/4.0-api $(MKINSTALLDIRS) $(PROFILE_DIR)/4.5-api - $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v2.0/* $(PROFILE_DIR)/2.0 - $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v3.5/* $(PROFILE_DIR)/3.5 - $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.0/* $(PROFILE_DIR)/4.0 + $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v2.0/* $(PROFILE_DIR)/2.0-api + $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v3.5/* $(PROFILE_DIR)/3.5-api + $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.0/* $(PROFILE_DIR)/4.0-api $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.5/* $(PROFILE_DIR)/4.5-api DISTFILES = $(wildcard ../../../external/binary-reference-assemblies/v4.5/*) $(wildcard ../../../external/binary-reference-assemblies/v4.0/*) $(wildcard ../../../external/binary-reference-assemblies/v3.5/*) $(wildcard ../../../external/binary-reference-assemblies/v2.0/*) Makefile diff --git a/mcs/tools/corcompare/Util.cs b/mcs/tools/corcompare/Util.cs index 782280535dd..fa643ed20f8 100644 --- a/mcs/tools/corcompare/Util.cs +++ b/mcs/tools/corcompare/Util.cs @@ -83,5 +83,112 @@ namespace CorCompare { { return att.AttributeType.Resolve (); } + + static bool IsOverride (MethodDefinition method) + { + return method.IsVirtual && !method.IsNewSlot; + } + + public static MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method) + { + if (!IsOverride (method)) + return method; + + var @base = GetBaseType (method.DeclaringType); + while (@base != null) { + MethodDefinition base_method = TryMatchMethod (@base.Resolve (), method); + if (base_method != null) + return GetBaseMethodInTypeHierarchy (base_method) ?? base_method; + + @base = GetBaseType (@base); + } + + return method; + } + + static MethodDefinition TryMatchMethod (TypeDefinition type, MethodDefinition method) + { + if (!type.HasMethods) + return null; + + foreach (MethodDefinition candidate in type.Methods) + if (MethodMatch (candidate, method)) + return candidate; + + return null; + } + + static bool MethodMatch (MethodDefinition candidate, MethodDefinition method) + { + if (!candidate.IsVirtual) + return false; + + if (candidate.Name != method.Name) + return false; + + if (!TypeMatch (candidate.ReturnType, method.ReturnType)) + return false; + + if (candidate.Parameters.Count != method.Parameters.Count) + return false; + + for (int i = 0; i < candidate.Parameters.Count; i++) + if (!TypeMatch (candidate.Parameters [i].ParameterType, method.Parameters [i].ParameterType)) + return false; + + return true; + } + + public static bool TypeMatch (IModifierType a, IModifierType b) + { + if (!TypeMatch (a.ModifierType, b.ModifierType)) + return false; + + return TypeMatch (a.ElementType, b.ElementType); + } + + public static bool TypeMatch (TypeSpecification a, TypeSpecification b) + { + if (a is GenericInstanceType) + return TypeMatch ((GenericInstanceType) a, (GenericInstanceType) b); + + if (a is IModifierType) + return TypeMatch ((IModifierType) a, (IModifierType) b); + + return TypeMatch (a.ElementType, b.ElementType); + } + + public static bool TypeMatch (GenericInstanceType a, GenericInstanceType b) + { + if (!TypeMatch (a.ElementType, b.ElementType)) + return false; + + if (a.GenericArguments.Count != b.GenericArguments.Count) + return false; + + if (a.GenericArguments.Count == 0) + return true; + + for (int i = 0; i < a.GenericArguments.Count; i++) + if (!TypeMatch (a.GenericArguments [i], b.GenericArguments [i])) + return false; + + return true; + } + + public static bool TypeMatch (TypeReference a, TypeReference b) + { + if (a is GenericParameter) + return true; + + if (a is TypeSpecification || b is TypeSpecification) { + if (a.GetType () != b.GetType ()) + return false; + + return TypeMatch ((TypeSpecification) a, (TypeSpecification) b); + } + + return a.FullName == b.FullName; + } } } diff --git a/mcs/tools/corcompare/WellFormedXmlWriter.cs b/mcs/tools/corcompare/WellFormedXmlWriter.cs index 334c57fab33..8f663c657c1 100644 --- a/mcs/tools/corcompare/WellFormedXmlWriter.cs +++ b/mcs/tools/corcompare/WellFormedXmlWriter.cs @@ -15,11 +15,6 @@ namespace CorCompare { public class WellFormedXmlWriter : DefaultXmlWriter { - public static bool IsValid (int ch) - { - return !IsInvalid (ch); - } - public static bool IsInvalid (int ch) { switch (ch) { diff --git a/mcs/tools/corcompare/mono-api-html/ApiChange.cs b/mcs/tools/corcompare/mono-api-html/ApiChange.cs index 72e905b8c58..1d902cacfad 100644 --- a/mcs/tools/corcompare/mono-api-html/ApiChange.cs +++ b/mcs/tools/corcompare/mono-api-html/ApiChange.cs @@ -21,15 +21,9 @@ namespace Xamarin.ApiDiff public ApiChange AppendAdded (string text, bool breaking = false) { - if (breaking) - Member.Append ("<span style='text-decoration: underline'>"); - if (State.Colorize) - Member.Append ("<span style='color:green'>"); + Member.Append ("<span class='added ").Append (breaking ? "added-breaking-inline" : string.Empty).Append ("'>"); Member.Append (text); - if (State.Colorize) - Member.Append ("</span>"); - if (breaking) - Member.Append ("</span>"); + Member.Append ("</span>"); Breaking |= breaking; AnyChange = true; return this; @@ -37,12 +31,8 @@ namespace Xamarin.ApiDiff public ApiChange AppendRemoved (string text, bool breaking = true) { - Member.Append ("<span style='text-decoration: line-through'>"); - if (State.Colorize && breaking) - Member.Append ("<span style='color:red'>"); + Member.Append ("<span class='removed removed-inline ").Append (breaking ? "removed-breaking-inline" : string.Empty).Append ("'>"); Member.Append (text); - if (State.Colorize && breaking) - Member.Append ("</span>"); Member.Append ("</span>"); Breaking |= breaking; AnyChange = true; diff --git a/mcs/tools/corcompare/mono-api-html/ApiDiff.cs b/mcs/tools/corcompare/mono-api-html/ApiDiff.cs index 69454e1184c..8fe27844852 100644 --- a/mcs/tools/corcompare/mono-api-html/ApiDiff.cs +++ b/mcs/tools/corcompare/mono-api-html/ApiDiff.cs @@ -168,12 +168,98 @@ namespace Xamarin.ApiDiff { } if (diffHtml.Length > 0) { using (var file = new StreamWriter (diff)) { + file.WriteLine ("<div>"); + if (State.Colorize) { + file.WriteLine ("<style scoped>"); + file.WriteLine ("\t.obsolete { color: gray; }"); + file.WriteLine ("\t.added { color: green; }"); + file.WriteLine ("\t.removed-inline { text-decoration: line-through; }"); + file.WriteLine ("\t.removed-breaking-inline { color: red;}"); + file.WriteLine ("\t.added-breaking-inline { text-decoration: underline; }"); + file.WriteLine ("\t.nonbreaking { color: black; }"); + file.WriteLine ("\t.breaking { color: red; }"); + file.WriteLine ("</style>"); + } + file.WriteLine ( +@"<script type=""text/javascript""> + // Only some elements have 'data-is-[non-]breaking' attributes. Here we + // iterate over all descendents elements, and set 'data-is-[non-]breaking' + // depending on whether there are any descendents with that attribute. + function propagateDataAttribute (element) + { + if (element.hasAttribute ('data-is-propagated')) + return; + + var i; + var any_breaking = element.hasAttribute ('data-is-breaking'); + var any_non_breaking = element.hasAttribute ('data-is-non-breaking'); + for (i = 0; i < element.children.length; i++) { + var el = element.children [i]; + propagateDataAttribute (el); + any_breaking |= el.hasAttribute ('data-is-breaking'); + any_non_breaking |= el.hasAttribute ('data-is-non-breaking'); + } + + if (any_breaking) + element.setAttribute ('data-is-breaking', null); + else if (any_non_breaking) + element.setAttribute ('data-is-non-breaking', null); + element.setAttribute ('data-is-propagated', null); + } + + function hideNonBreakingChanges () + { + var topNodes = document.querySelectorAll ('[data-is-topmost]'); + var n; + var i; + for (n = 0; n < topNodes.length; n++) { + propagateDataAttribute (topNodes [n]); + var elements = topNodes [n].querySelectorAll ('[data-is-non-breaking]'); + for (i = 0; i < elements.length; i++) { + var el = elements [i]; + if (!el.hasAttribute ('data-original-display')) + el.setAttribute ('data-original-display', el.style.display); + el.style.display = 'none'; + } + } + + var links = document.getElementsByClassName ('hide-nonbreaking'); + for (i = 0; i < links.length; i++) + links [i].style.display = 'none'; + links = document.getElementsByClassName ('restore-nonbreaking'); + for (i = 0; i < links.length; i++) + links [i].style.display = ''; + } + + function showNonBreakingChanges () + { + var elements = document.querySelectorAll ('[data-original-display]'); + var i; + for (i = 0; i < elements.length; i++) { + var el = elements [i]; + el.style.display = el.getAttribute ('data-original-display'); + } + + var links = document.getElementsByClassName ('hide-nonbreaking'); + for (i = 0; i < links.length; i++) + links [i].style.display = ''; + links = document.getElementsByClassName ('restore-nonbreaking'); + for (i = 0; i < links.length; i++) + links [i].style.display = 'none'; + } +</script>"); if (ac.SourceAssembly == ac.TargetAssembly) { file.WriteLine ("<h1>{0}.dll</h1>", ac.SourceAssembly); } else { file.WriteLine ("<h1>{0}.dll vs {1}.dll</h1>", ac.SourceAssembly, ac.TargetAssembly); } + file.WriteLine ("<a href='javascript: hideNonBreakingChanges (); ' class='hide-nonbreaking'>Hide non-breaking changes</a>"); + file.WriteLine ("<a href='javascript: showNonBreakingChanges (); ' class='restore-nonbreaking' style='display: none;'>Show non-breaking changes</a>"); + file.WriteLine ("<br/>"); + file.WriteLine ("<div data-is-topmost>"); file.Write (diffHtml); + file.WriteLine ("</div> <!-- end topmost div -->"); + file.WriteLine ("</div>"); } } } else { diff --git a/mcs/tools/corcompare/mono-api-html/AssemblyComparer.cs b/mcs/tools/corcompare/mono-api-html/AssemblyComparer.cs index ff5326d9c8b..adbd862eb92 100644 --- a/mcs/tools/corcompare/mono-api-html/AssemblyComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/AssemblyComparer.cs @@ -57,7 +57,7 @@ namespace Xamarin.ApiDiff { State.Assembly = current.GetAttribute ("name"); } - public override void Added (XElement target) + public override void Added (XElement target, bool wasParentAdded) { // one assembly per xml file } diff --git a/mcs/tools/corcompare/mono-api-html/ClassComparer.cs b/mcs/tools/corcompare/mono-api-html/ClassComparer.cs index 761f87a5552..a3399fbef04 100644 --- a/mcs/tools/corcompare/mono-api-html/ClassComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/ClassComparer.cs @@ -67,16 +67,18 @@ namespace Xamarin.ApiDiff { Compare (s.Elements ("class"), t.Elements ("class")); } - public override void Added (XElement target) + public override void Added (XElement target, bool wasParentAdded) { string name = target.Attribute ("name").Value; if (State.IgnoreNew.Any (re => re.IsMatch (name))) return; + Output.WriteLine ("<div> <!-- start type {0} -->", name); Output.WriteLine ("<h3>New Type {0}.{1}</h3>", State.Namespace, name); - Output.WriteLine (State.Colorize ? "<pre style='color: green'>" : "<pre>"); + Output.WriteLine ("<pre class='added' data-is-non-breaking>"); State.Indent = 0; AddedInner (target); Output.WriteLine ("</pre>"); + Output.WriteLine ("</div> <!-- end type {0} -->", name); } public void AddedInner (XElement target) @@ -149,7 +151,7 @@ namespace Xamarin.ApiDiff { if (t != null) { Indent ().WriteLine ("\t// constructors"); foreach (var ctor in t.Elements ("constructor")) - ccomparer.Added (ctor); + ccomparer.Added (ctor, true); } t = target.Element ("fields"); @@ -159,28 +161,28 @@ namespace Xamarin.ApiDiff { else SetContext (target); foreach (var field in t.Elements ("field")) - fcomparer.Added (field); + fcomparer.Added (field, true); } t = target.Element ("properties"); if (t != null) { Indent ().WriteLine ("\t// properties"); foreach (var property in t.Elements ("property")) - pcomparer.Added (property); + pcomparer.Added (property, true); } t = target.Element ("events"); if (t != null) { Indent ().WriteLine ("\t// events"); foreach (var evnt in t.Elements ("event")) - ecomparer.Added (evnt); + ecomparer.Added (evnt, true); } t = target.Element ("methods"); if (t != null) { Indent ().WriteLine ("\t// methods"); foreach (var method in t.Elements ("method")) - mcomparer.Added (method); + mcomparer.Added (method, true); } t = target.Element ("classes"); @@ -226,17 +228,17 @@ namespace Xamarin.ApiDiff { var s = (Output as StringWriter).ToString (); State.Output = output; if (s.Length > 0) { + var tn = GetTypeName (target); + Output.WriteLine ("<!-- start type {0} --> <div>", tn); Output.WriteLine ("<h3>Type Changed: {0}.{1}</h3>", State.Namespace, GetTypeName (target)); Output.WriteLine (s); + Output.WriteLine ("</div> <!-- end type {0} -->", tn); } } public override void Removed (XElement source) { - var style = string.Empty; - if (State.Colorize) - style = "style='color: red'"; - Output.Write ("<h3>Removed Type <span {0}>{1}.{2}</span></h3>", style, State.Namespace, GetTypeName (source)); + Output.Write ("<h3>Removed Type <span class='breaking' data-is-breaking>{0}.{1}</span></h3>", State.Namespace, GetTypeName (source)); } public virtual string GetTypeName (XElement type) diff --git a/mcs/tools/corcompare/mono-api-html/Comparer.cs b/mcs/tools/corcompare/mono-api-html/Comparer.cs index 8c692a03a9a..4210b9b95fb 100644 --- a/mcs/tools/corcompare/mono-api-html/Comparer.cs +++ b/mcs/tools/corcompare/mono-api-html/Comparer.cs @@ -48,7 +48,7 @@ namespace Xamarin.ApiDiff { return State.Output; } - public abstract void Added (XElement target); + public abstract void Added (XElement target, bool wasParentAdded); public abstract void Modified (XElement source, XElement target, ApiChanges changes); public abstract void Removed (XElement source); @@ -90,7 +90,7 @@ namespace Xamarin.ApiDiff { if (target != null) { foreach (var item in target) { SetContext (item); - Added (item); + Added (item, false); } } } diff --git a/mcs/tools/corcompare/mono-api-html/FieldComparer.cs b/mcs/tools/corcompare/mono-api-html/FieldComparer.cs index bb4f6c6b075..a2b0225b448 100644 --- a/mcs/tools/corcompare/mono-api-html/FieldComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/FieldComparer.cs @@ -189,8 +189,9 @@ namespace Xamarin.ApiDiff { { first = true; if (State.BaseType == "System.Enum") { + Output.WriteLine ("<div>"); Output.WriteLine ("<p>Added value{0}:</p>", list.Count () > 1 ? "s" : String.Empty); - Output.WriteLine (State.Colorize ? "<pre style='color: green'>" : "<pre>"); + Output.WriteLine ("<pre class='added' data-is-non-breaking>"); } else { base.BeforeAdding (list); } @@ -201,7 +202,7 @@ namespace Xamarin.ApiDiff { first = true; if (State.BaseType == "System.Enum") { Output.WriteLine ("<p>Removed value{0}:</p>", list.Count () > 1 ? "s" : String.Empty); - Output.WriteLine (State.Colorize ? "<pre style='color: red'>" : "<pre>"); + Output.WriteLine ("<pre class='removed' data-is-breaking>"); } else { base.BeforeRemoving (list); } diff --git a/mcs/tools/corcompare/mono-api-html/MemberComparer.cs b/mcs/tools/corcompare/mono-api-html/MemberComparer.cs index dee528ebc7a..d12d86625c2 100644 --- a/mcs/tools/corcompare/mono-api-html/MemberComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/MemberComparer.cs @@ -41,6 +41,11 @@ namespace Xamarin.ApiDiff { public abstract string GroupName { get; } public abstract string ElementName { get; } + protected virtual bool IsBreakingRemoval (XElement e) + { + return true; + } + public void Compare (XElement source, XElement target) { var s = source.Element (GroupName); @@ -124,7 +129,7 @@ namespace Xamarin.ApiDiff { BeforeAdding (elements); a = true; } - Added (item); + Added (item, false); } if (a) AfterAdding (); @@ -136,8 +141,10 @@ namespace Xamarin.ApiDiff { Output.WriteLine ("<p>{0}:</p>", changes.Key); Output.WriteLine ("<pre>"); foreach (var element in changes.Value) { + Output.Write ("<div {0}>", element.Breaking ? "data-is-breaking" : "data-is-non-breaking"); foreach (var line in element.Member.ToString ().Split ('\n')) Output.WriteLine ("\t{0}", line); + Output.Write ("</div>"); } Output.WriteLine ("</pre>"); @@ -192,24 +199,28 @@ namespace Xamarin.ApiDiff { public virtual void BeforeAdding (IEnumerable<XElement> list) { first = true; + Output.WriteLine ("<div>"); Output.WriteLine ("<p>Added {0}:</p>", list.Count () > 1 ? GroupName : ElementName); - - bool isInterface = list.Count () > 0 && IsInInterface (list.First ()); - Output.WriteLine (State.Colorize ? string.Format ("<pre style='color: {0}'>", isInterface ? "red" : "green") : "<pre>"); + Output.WriteLine ("<pre>"); } - public override void Added (XElement target) + public override void Added (XElement target, bool wasParentAdded) { var o = GetObsoleteMessage (target); if (!first && (o.Length > 0)) Output.WriteLine (); - Indent ().WriteLine ("\t{0}{1}", o, GetDescription (target)); + Indent (); + bool isInterfaceBreakingChange = !wasParentAdded && IsInInterface (target); + Output.Write ("\t<span class='added added-{0} {1}' {2}>", ElementName, isInterfaceBreakingChange ? "breaking" : string.Empty, isInterfaceBreakingChange ? "data-is-breaking" : "data-is-non-breaking"); + Output.Write ("{0}{1}", o, GetDescription (target)); + Output.WriteLine ("</span>"); first = false; } public virtual void AfterAdding () { - Output.WriteLine ("</pre>");; + Output.WriteLine ("</pre>"); + Output.WriteLine ("</div>"); } public override void Modified (XElement source, XElement target, ApiChanges change) @@ -220,7 +231,7 @@ namespace Xamarin.ApiDiff { { first = true; Output.WriteLine ("<p>Removed {0}:</p>\n", list.Count () > 1 ? GroupName : ElementName); - Output.WriteLine (State.Colorize ? "<pre style='color: red'>" : "<pre>"); + Output.WriteLine ("<pre>"); } public override void Removed (XElement source) @@ -228,7 +239,13 @@ namespace Xamarin.ApiDiff { var o = GetObsoleteMessage (source); if (!first && (o.Length > 0)) Output.WriteLine (); - Indent ().WriteLine ("\t{0}{1}", o, GetDescription (source)); + + bool is_breaking = IsBreakingRemoval (source); + + Indent (); + Output.Write ("\t<span class='removed removed-{0} {2}' {1}>", ElementName, is_breaking ? "data-is-breaking" : "data-is-non-breaking", is_breaking ? "breaking" : string.Empty); + Output.Write ("{0}{1}", o, GetDescription (source)); + Output.WriteLine ("</span>"); first = false; } @@ -558,15 +575,13 @@ namespace Xamarin.ApiDiff { return; // neither is obsolete var change = new ApiChange (); change.Header = "Obsoleted " + GroupName; - if (State.Colorize) - change.Append ("<span style='color:gray'>"); + change.Append (string.Format ("<span class='obsolete obsolete-{0}' data-is-non-breaking>", ElementName)); change.Append ("[Obsolete ("); if (tgtObsolete != string.Empty) change.Append ("\"").Append (tgtObsolete).Append ("\""); change.Append (")]\n"); change.Append (GetDescription (target)); - if (State.Colorize) - change.Append ("</span>"); + change.Append ("</span>"); change.AnyChange = true; changes.Add (source, target, change); } else if (tgtObsolete == null) { diff --git a/mcs/tools/corcompare/mono-api-html/MethodComparer.cs b/mcs/tools/corcompare/mono-api-html/MethodComparer.cs index 1dffa17dfcc..4c893e757ec 100644 --- a/mcs/tools/corcompare/mono-api-html/MethodComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/MethodComparer.cs @@ -26,6 +26,7 @@ using System; using System.Linq; +using System.Reflection; using System.Xml.Linq; namespace Xamarin.ApiDiff { @@ -62,5 +63,15 @@ namespace Xamarin.ApiDiff { return eGPs.Count () == sGPs.Count (); } } + + protected override bool IsBreakingRemoval (XElement e) + { + // Removing virtual methods that override another method is not a breaking change. + var is_override = e.Attribute ("is-override"); + if (is_override != null) + return is_override.Value != "true"; + + return true; // all other removals are breaking changes + } } }
\ No newline at end of file diff --git a/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs b/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs index 258374c6b9d..063e34ecbf7 100644 --- a/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs @@ -55,17 +55,19 @@ namespace Xamarin.ApiDiff { State.Namespace = current.Attribute ("name").Value; } - public override void Added (XElement target) + public override void Added (XElement target, bool wasParentAdded) { string name = target.Attribute ("name").Value; if (State.IgnoreNew.Any (re => re.IsMatch (name))) return; + Output.WriteLine ("<!-- start namespace {0} --> <div> ", name); Output.WriteLine ("<h2>New Namespace {0}</h2>", name); Output.WriteLine (); // list all new types foreach (var addedType in target.Element ("classes").Elements ("class")) - comparer.Added (addedType); + comparer.Added (addedType, true); + Output.WriteLine ("</div> <!-- end namespace {0} -->", name); Output.WriteLine (); } @@ -78,18 +80,24 @@ namespace Xamarin.ApiDiff { var s = Output.ToString (); State.Output = output; if (s.Length > 0) { - Output.WriteLine ("<h2>Namespace {0}</h2>", target.Attribute ("name").Value); + var name = target.Attribute ("name").Value; + Output.WriteLine ("<!-- start namespace {0} --> <div> ", name); + Output.WriteLine ("<h2>Namespace {0}</h2>", name); Output.WriteLine (s); + Output.WriteLine ("</div> <!-- end namespace {0} -->", name); } } public override void Removed (XElement source) { - Output.WriteLine ("<h2>Removed Namespace {0}</h2>", source.Attribute ("name").Value); + var name = source.Attribute ("name").Value; + Output.WriteLine ("<!-- start namespace {0} --> <div>", name); + Output.WriteLine ("<h2>Removed Namespace {0}</h2>", name); Output.WriteLine (); // list all removed types foreach (var removedType in source.Element ("classes").Elements ("class")) comparer.Removed (removedType); + Output.WriteLine ("</div> <!-- end namespace {0} -->", name); Output.WriteLine (); } } diff --git a/mcs/tools/corcompare/mono-api-html/mono-api-html.csproj b/mcs/tools/corcompare/mono-api-html/mono-api-html.csproj index 286a4d0192a..6ac0f241ade 100644 --- a/mcs/tools/corcompare/mono-api-html/mono-api-html.csproj +++ b/mcs/tools/corcompare/mono-api-html/mono-api-html.csproj @@ -19,7 +19,6 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <ConsolePause>false</ConsolePause> - <Commandlineparameters>/Developer/MonoTouch/Source/monotouch/tools/apidiff/references/compat/monotouch.xml /Developer/MonoTouch/Source/monotouch/tools/apidiff/temp/compat/monotouch.xml -i INSObjectProtocol /tmp/diff.html</Commandlineparameters> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>full</DebugType> diff --git a/mcs/tools/corcompare/mono-api-info.cs b/mcs/tools/corcompare/mono-api-info.cs index 0886d14b3bd..8b1ad945095 100644 --- a/mcs/tools/corcompare/mono-api-info.cs +++ b/mcs/tools/corcompare/mono-api-info.cs @@ -93,18 +93,20 @@ namespace CorCompare } } - XmlDocument doc = new XmlDocument (); - acoll.Document = doc; - acoll.DoOutput (); - - TextWriter outputStream = null; + StreamWriter outputStream = null; if (!string.IsNullOrEmpty (output)) outputStream = new StreamWriter (output); try { - var writer = new WellFormedXmlWriter (new XmlTextWriter (outputStream ?? Console.Out) { Formatting = Formatting.Indented }); - XmlNode decl = doc.CreateXmlDeclaration ("1.0", "utf-8", null); - doc.InsertBefore (decl, doc.DocumentElement); - doc.WriteTo (writer); + TextWriter outStream = outputStream ?? Console.Out; + var settings = new XmlWriterSettings (); + settings.Indent = true; + var textWriter = XmlWriter.Create (outStream, settings); + var writer = new WellFormedXmlWriter (textWriter); + writer.WriteStartDocument (); + acoll.Writer = writer; + acoll.DoOutput (); + writer.WriteEndDocument (); + writer.Flush (); } finally { if (outputStream != null) outputStream.Dispose (); @@ -117,6 +119,7 @@ namespace CorCompare } public class Utils { + static char[] CharsToCleanup = new char[] { '<', '>', '/' }; public static string CleanupTypeName (TypeReference type) { @@ -125,13 +128,33 @@ namespace CorCompare public static string CleanupTypeName (string t) { - return t.Replace ('<', '[').Replace ('>', ']').Replace ('/', '+'); + if (t.IndexOfAny (CharsToCleanup) == -1) + return t; + var sb = new StringBuilder (t.Length); + for (int i = 0; i < t.Length; i++) { + var ch = t [i]; + switch (ch) { + case '<': + sb.Append ('['); + break; + case '>': + sb.Append (']'); + break; + case '/': + sb.Append ('+'); + break; + default: + sb.Append (ch); + break; + } + } + return sb.ToString (); } } class AssemblyCollection { - XmlDocument document; + XmlWriter writer; List<AssemblyDefinition> assemblies = new List<AssemblyDefinition> (); public AssemblyCollection () @@ -152,19 +175,19 @@ namespace CorCompare public void DoOutput () { - if (document == null) + if (writer == null) throw new InvalidOperationException ("Document not set"); - XmlNode nassemblies = document.CreateElement ("assemblies", null); - document.AppendChild (nassemblies); + writer.WriteStartElement ("assemblies"); foreach (AssemblyDefinition a in assemblies) { - AssemblyData data = new AssemblyData (document, nassemblies, a); + AssemblyData data = new AssemblyData (writer, a); data.DoOutput (); } + writer.WriteEndElement (); } - public XmlDocument Document { - set { document = value; } + public XmlWriter Writer { + set { writer = value; } } AssemblyDefinition LoadAssembly (string assembly) @@ -183,22 +206,18 @@ namespace CorCompare abstract class BaseData { - protected XmlDocument document; - protected XmlNode parent; + protected XmlWriter writer; - protected BaseData (XmlDocument doc, XmlNode parent) + protected BaseData (XmlWriter writer) { - this.document = doc; - this.parent = parent; + this.writer = writer; } public abstract void DoOutput (); - protected void AddAttribute (XmlNode node, string name, string value) + protected void AddAttribute (string name, string value) { - XmlAttribute attr = document.CreateAttribute (name); - attr.Value = value; - node.Attributes.Append (attr); + writer.WriteAttributeString (name, value); } } @@ -206,38 +225,34 @@ namespace CorCompare { AssemblyDefinition ass; - public TypeForwardedToData (XmlDocument document, XmlNode parent, AssemblyDefinition ass) - : base (document, parent) + public TypeForwardedToData (XmlWriter writer, AssemblyDefinition ass) + : base (writer) { this.ass = ass; } public override void DoOutput () { - XmlNode natts = parent.SelectSingleNode("attributes"); - if (natts == null) { - natts = document.CreateElement ("attributes", null); - parent.AppendChild (natts); - } - foreach (ExportedType type in ass.MainModule.ExportedTypes) { if (((uint)type.Attributes & 0x200000u) == 0) continue; - XmlNode node = document.CreateElement ("attribute"); - AddAttribute (node, "name", typeof (TypeForwardedToAttribute).FullName); - XmlNode properties = node.AppendChild (document.CreateElement ("properties")); - XmlNode property = properties.AppendChild (document.CreateElement ("property")); - AddAttribute (property, "name", "Destination"); - AddAttribute (property, "value", Utils.CleanupTypeName (type.FullName)); - natts.AppendChild (node); + writer.WriteStartElement ("attribute"); + AddAttribute ("name", typeof (TypeForwardedToAttribute).FullName); + writer.WriteStartElement ("properties"); + writer.WriteStartElement ("property"); + AddAttribute ("name", "Destination"); + AddAttribute ("value", Utils.CleanupTypeName (type.FullName)); + writer.WriteEndElement (); // properties + writer.WriteEndElement (); // properties + writer.WriteEndElement (); // attribute } } - public static void OutputForwarders (XmlDocument document, XmlNode parent, AssemblyDefinition ass) + public static void OutputForwarders (XmlWriter writer, AssemblyDefinition ass) { - TypeForwardedToData tftd = new TypeForwardedToData (document, parent, ass); + TypeForwardedToData tftd = new TypeForwardedToData (writer, ass); tftd.DoOutput (); } } @@ -246,28 +261,23 @@ namespace CorCompare { AssemblyDefinition ass; - public AssemblyData (XmlDocument document, XmlNode parent, AssemblyDefinition ass) - : base (document, parent) + public AssemblyData (XmlWriter writer, AssemblyDefinition ass) + : base (writer) { this.ass = ass; } public override void DoOutput () { - if (document == null) + if (writer == null) throw new InvalidOperationException ("Document not set"); - XmlNode nassembly = document.CreateElement ("assembly", null); + writer.WriteStartElement ("assembly"); AssemblyNameDefinition aname = ass.Name; - AddAttribute (nassembly, "name", aname.Name); - AddAttribute (nassembly, "version", aname.Version.ToString ()); - parent.AppendChild (nassembly); - - if (!Driver.FollowForwarders) { - TypeForwardedToData.OutputForwarders (document, nassembly, ass); - } + AddAttribute ("name", aname.Name); + AddAttribute ("version", aname.Version.ToString ()); - AttributeData.OutputAttributes (document, nassembly, ass); + AttributeData.OutputAttributes (writer, ass); var types = new List<TypeDefinition> (); if (ass.MainModule.Types != null) { @@ -285,17 +295,16 @@ namespace CorCompare } if (types.Count == 0) { + writer.WriteEndElement (); // assembly return; } types.Sort (TypeReferenceComparer.Default); - XmlNode nss = document.CreateElement ("namespaces", null); - nassembly.AppendChild (nss); + writer.WriteStartElement ("namespaces"); string current_namespace = "$%&$&"; - XmlNode ns = null; - XmlNode classes = null; + bool in_namespace = false; foreach (TypeDefinition t in types) { if (string.IsNullOrEmpty (t.Namespace)) continue; @@ -308,16 +317,30 @@ namespace CorCompare if (t.Namespace != current_namespace) { current_namespace = t.Namespace; - ns = document.CreateElement ("namespace", null); - AddAttribute (ns, "name", current_namespace); - nss.AppendChild (ns); - classes = document.CreateElement ("classes", null); - ns.AppendChild (classes); + if (in_namespace) { + writer.WriteEndElement (); // classes + writer.WriteEndElement (); // namespace + } else { + in_namespace = true; + } + writer.WriteStartElement ("namespace"); + AddAttribute ("name", current_namespace); + writer.WriteStartElement ("classes"); } - TypeData bd = new TypeData (document, classes, t); + TypeData bd = new TypeData (writer, t); bd.DoOutput (); + } + + if (in_namespace) { + writer.WriteEndElement (); // classes + writer.WriteEndElement (); // namespace + } + + writer.WriteEndElement (); // namespaces + + writer.WriteEndElement (); // assembly } } @@ -325,31 +348,42 @@ namespace CorCompare { MemberReference [] members; - public MemberData (XmlDocument document, XmlNode parent, MemberReference [] members) - : base (document, parent) + public MemberData (XmlWriter writer, MemberReference [] members) + : base (writer) { this.members = members; } + protected virtual ICustomAttributeProvider GetAdditionalCustomAttributeProvider (MemberReference member) + { + return null; + } + public override void DoOutput () { - XmlNode mclass = document.CreateElement (ParentTag, null); - parent.AppendChild (mclass); + writer.WriteStartElement (ParentTag); foreach (MemberReference member in members) { - XmlNode mnode = document.CreateElement (Tag, null); - mclass.AppendChild (mnode); - AddAttribute (mnode, "name", GetName (member)); + writer.WriteStartElement (Tag); + AddAttribute ("name", GetName (member)); if (!NoMemberAttributes) - AddAttribute (mnode, "attrib", GetMemberAttributes (member)); + AddAttribute ("attrib", GetMemberAttributes (member)); + AddExtraAttributes (member); - AttributeData.OutputAttributes (document, mnode, (ICustomAttributeProvider) member); + AttributeData.OutputAttributes (writer, (ICustomAttributeProvider) member, GetAdditionalCustomAttributeProvider (member)); - AddExtraData (mnode, member); + AddExtraData (member); + writer.WriteEndElement (); // Tag } + + writer.WriteEndElement (); // ParentTag + } + + protected virtual void AddExtraData (MemberReference memberDefenition) + { } - protected virtual void AddExtraData (XmlNode p, MemberReference memberDefenition) + protected virtual void AddExtraAttributes (MemberReference memberDefinition) { } @@ -376,39 +410,42 @@ namespace CorCompare get { return "NoTAG"; } } - public static void OutputGenericParameters (XmlDocument document, XmlNode nclass, IGenericParameterProvider provider) + public static void OutputGenericParameters (XmlWriter writer, IGenericParameterProvider provider) { if (provider.GenericParameters.Count == 0) return; var gparameters = provider.GenericParameters; - XmlElement ngeneric = document.CreateElement ("generic-parameters"); - nclass.AppendChild (ngeneric); + writer.WriteStartElement ("generic-parameters"); foreach (GenericParameter gp in gparameters) { - XmlElement nparam = document.CreateElement ("generic-parameter"); - nparam.SetAttribute ("name", gp.Name); - nparam.SetAttribute ("attributes", ((int) gp.Attributes).ToString ()); + writer.WriteStartElement ("generic-parameter"); + writer.WriteAttributeString ("name", gp.Name); + writer.WriteAttributeString ("attributes", ((int) gp.Attributes).ToString ()); - AttributeData.OutputAttributes (document, nparam, gp); - - ngeneric.AppendChild (nparam); + AttributeData.OutputAttributes (writer, gp); var constraints = gp.Constraints; - if (constraints.Count == 0) + if (constraints.Count == 0) { + writer.WriteEndElement (); // generic-parameter continue; + } - XmlElement nconstraint = document.CreateElement ("generic-parameter-constraints"); + writer.WriteStartElement ("generic-parameter-constraints"); foreach (TypeReference constraint in constraints) { - XmlElement ncons = document.CreateElement ("generic-parameter-constraint"); - ncons.SetAttribute ("name", Utils.CleanupTypeName (constraint)); - nconstraint.AppendChild (ncons); + writer.WriteStartElement ("generic-parameter-constraint"); + writer.WriteAttributeString ("name", Utils.CleanupTypeName (constraint)); + writer.WriteEndElement (); // generic-parameter-constraint } - nparam.AppendChild (nconstraint); + writer.WriteEndElement (); // generic-parameter-constraints + + writer.WriteEndElement (); // generic-parameter } + + writer.WriteEndElement (); // generic-parameters } } @@ -416,112 +453,107 @@ namespace CorCompare { TypeDefinition type; - public TypeData (XmlDocument document, XmlNode parent, TypeDefinition type) - : base (document, parent, null) + public TypeData (XmlWriter writer, TypeDefinition type) + : base (writer, null) { this.type = type; } public override void DoOutput () { - if (document == null) + if (writer == null) throw new InvalidOperationException ("Document not set"); - XmlNode nclass = document.CreateElement ("class", null); - AddAttribute (nclass, "name", type.Name); + writer.WriteStartElement ("class"); + AddAttribute ("name", type.Name); string classType = GetClassType (type); - AddAttribute (nclass, "type", classType); + AddAttribute ("type", classType); if (type.BaseType != null) - AddAttribute (nclass, "base", Utils.CleanupTypeName (type.BaseType)); + AddAttribute ("base", Utils.CleanupTypeName (type.BaseType)); if (type.IsSealed) - AddAttribute (nclass, "sealed", "true"); + AddAttribute ("sealed", "true"); if (type.IsAbstract) - AddAttribute (nclass, "abstract", "true"); + AddAttribute ("abstract", "true"); if ( (type.Attributes & TypeAttributes.Serializable) != 0 || type.IsEnum) - AddAttribute (nclass, "serializable", "true"); + AddAttribute ("serializable", "true"); string charSet = GetCharSet (type); - AddAttribute (nclass, "charset", charSet); + AddAttribute ("charset", charSet); string layout = GetLayout (type); if (layout != null) - AddAttribute (nclass, "layout", layout); + AddAttribute ("layout", layout); if (type.PackingSize >= 0) { - AddAttribute (nclass, "pack", type.PackingSize.ToString ()); + AddAttribute ("pack", type.PackingSize.ToString ()); } if (type.ClassSize >= 0) { - AddAttribute (nclass, "size", type.ClassSize.ToString ()); + AddAttribute ("size", type.ClassSize.ToString ()); } - parent.AppendChild (nclass); + if (type.IsEnum) { + var value_type = GetEnumValueField (type); + if (value_type == null) + throw new NotSupportedException (); - AttributeData.OutputAttributes (document, nclass, type); + AddAttribute ("enumtype", Utils.CleanupTypeName (value_type.FieldType)); + } - XmlNode ifaces = null; + AttributeData.OutputAttributes (writer, type); - foreach (TypeReference iface in TypeHelper.GetInterfaces (type).OrderBy (s => s.FullName)) { - if (!TypeHelper.IsPublic (iface)) - // we're only interested in public interfaces - continue; + var ifaces = TypeHelper.GetInterfaces (type). + Where ((iface) => TypeHelper.IsPublic (iface)). // we're only interested in public interfaces + OrderBy (s => s.FullName, StringComparer.Ordinal); - if (ifaces == null) { - ifaces = document.CreateElement ("interfaces", null); - nclass.AppendChild (ifaces); + if (ifaces.Any ()) { + writer.WriteStartElement ("interfaces"); + foreach (TypeReference iface in ifaces) { + writer.WriteStartElement ("interface"); + AddAttribute ("name", Utils.CleanupTypeName (iface)); + writer.WriteEndElement (); // interface } - - XmlNode iface_node = document.CreateElement ("interface", null); - AddAttribute (iface_node, "name", Utils.CleanupTypeName (iface)); - ifaces.AppendChild (iface_node); + writer.WriteEndElement (); // interfaces } - MemberData.OutputGenericParameters (document, nclass, type); + MemberData.OutputGenericParameters (writer, type); ArrayList members = new ArrayList (); FieldDefinition [] fields = GetFields (type); if (fields.Length > 0) { Array.Sort (fields, MemberReferenceComparer.Default); - FieldData fd = new FieldData (document, nclass, fields); + FieldData fd = new FieldData (writer, fields); members.Add (fd); } - if (type.IsEnum) { - var value_type = GetEnumValueField (type); - if (value_type == null) - throw new NotSupportedException (); - - AddAttribute (nclass, "enumtype", Utils.CleanupTypeName (value_type.FieldType)); - } - if (!Driver.AbiMode) { MethodDefinition [] ctors = GetConstructors (type); if (ctors.Length > 0) { Array.Sort (ctors, MethodDefinitionComparer.Default); - members.Add (new ConstructorData (document, nclass, ctors)); + members.Add (new ConstructorData (writer, ctors)); } PropertyDefinition[] properties = GetProperties (type); if (properties.Length > 0) { Array.Sort (properties, PropertyDefinitionComparer.Default); - members.Add (new PropertyData (document, nclass, properties)); + members.Add (new PropertyData (writer, properties)); } EventDefinition [] events = GetEvents (type); if (events.Length > 0) { Array.Sort (events, MemberReferenceComparer.Default); - members.Add (new EventData (document, nclass, events)); + members.Add (new EventData (writer, events)); } MethodDefinition [] methods = GetMethods (type); if (methods.Length > 0) { Array.Sort (methods, MethodDefinitionComparer.Default); - members.Add (new MethodData (document, nclass, methods)); + members.Add (new MethodData (writer, methods)); } } @@ -547,13 +579,15 @@ namespace CorCompare var nestedArray = nested.ToArray (); Array.Sort (nestedArray, TypeReferenceComparer.Default); - XmlNode classes = document.CreateElement ("classes", null); - nclass.AppendChild (classes); + writer.WriteStartElement ("classes"); foreach (TypeDefinition t in nestedArray) { - TypeData td = new TypeData (document, classes, t); + TypeData td = new TypeData (writer, t); td.DoOutput (); } + writer.WriteEndElement (); // classes } + + writer.WriteEndElement (); // class } static FieldReference GetEnumValueField (TypeDefinition type) @@ -686,7 +720,7 @@ namespace CorCompare var methods = type.Methods;//type.GetMethods (flags); foreach (MethodDefinition method in methods) { - if (method.IsSpecialName && !method.Name.StartsWith ("op_")) + if (method.IsSpecialName && !method.Name.StartsWith ("op_", StringComparison.Ordinal)) continue; // we're only interested in public or protected members @@ -758,8 +792,8 @@ namespace CorCompare class FieldData : MemberData { - public FieldData (XmlDocument document, XmlNode parent, FieldDefinition [] members) - : base (document, parent, members) + public FieldData (XmlWriter writer, FieldDefinition [] members) + : base (writer, members) { } @@ -775,11 +809,12 @@ namespace CorCompare return ((int) field.Attributes).ToString (CultureInfo.InvariantCulture); } - protected override void AddExtraData (XmlNode p, MemberReference memberDefenition) + protected override void AddExtraAttributes (MemberReference memberDefinition) { - base.AddExtraData (p, memberDefenition); - FieldDefinition field = (FieldDefinition) memberDefenition; - AddAttribute (p, "fieldtype", Utils.CleanupTypeName (field.FieldType)); + base.AddExtraAttributes (memberDefinition); + + FieldDefinition field = (FieldDefinition) memberDefinition; + AddAttribute ("fieldtype", Utils.CleanupTypeName (field.FieldType)); if (field.IsLiteral) { object value = field.Constant;//object value = field.GetValue (null); @@ -791,11 +826,11 @@ namespace CorCompare // stringValue = ((Enum) value).ToString ("D", CultureInfo.InvariantCulture); //} //else { - stringValue = Convert.ToString (value, CultureInfo.InvariantCulture); + stringValue = Convert.ToString (value, CultureInfo.InvariantCulture); //} if (stringValue != null) - AddAttribute (p, "value", stringValue); + AddAttribute ("value", stringValue); } } @@ -810,8 +845,8 @@ namespace CorCompare class PropertyData : MemberData { - public PropertyData (XmlDocument document, XmlNode parent, PropertyDefinition [] members) - : base (document, parent, members) + public PropertyData (XmlWriter writer, PropertyDefinition [] members) + : base (writer, members) { } @@ -821,15 +856,13 @@ namespace CorCompare return prop.Name; } - protected override void AddExtraData (XmlNode p, MemberReference memberDefenition) + MethodDefinition [] GetMethods (PropertyDefinition prop, out bool haveParameters) { - base.AddExtraData (p, memberDefenition); - PropertyDefinition prop = (PropertyDefinition) memberDefenition; - AddAttribute (p, "ptype", Utils.CleanupTypeName (prop.PropertyType)); MethodDefinition _get = prop.GetMethod; MethodDefinition _set = prop.SetMethod; bool haveGet = (_get != null && TypeData.MustDocumentMethod(_get)); bool haveSet = (_set != null && TypeData.MustDocumentMethod(_set)); + haveParameters = haveGet || (haveSet && _set.Parameters.Count > 1); MethodDefinition [] methods; if (haveGet && haveSet) { @@ -840,16 +873,41 @@ namespace CorCompare methods = new MethodDefinition [] { _set }; } else { //odd - return; + return null; } - if (haveGet || _set.Parameters.Count > 1) { + return methods; + } + + protected override void AddExtraAttributes (MemberReference memberDefinition) + { + base.AddExtraAttributes (memberDefinition); + + PropertyDefinition prop = (PropertyDefinition) memberDefinition; + AddAttribute ("ptype", Utils.CleanupTypeName (prop.PropertyType)); + + bool haveParameters; + MethodDefinition [] methods = GetMethods ((PropertyDefinition) memberDefinition, out haveParameters); + + if (methods != null && haveParameters) { string parms = Parameters.GetSignature (methods [0].Parameters); if (!string.IsNullOrEmpty (parms)) - AddAttribute (p, "params", parms); + AddAttribute ("params", parms); } - MethodData data = new MethodData (document, p, methods); + } + + protected override void AddExtraData (MemberReference memberDefenition) + { + base.AddExtraData (memberDefenition); + + bool haveParameters; + MethodDefinition [] methods = GetMethods ((PropertyDefinition) memberDefenition, out haveParameters); + + if (methods == null) + return; + + MethodData data = new MethodData (writer, methods); //data.NoMemberAttributes = true; data.DoOutput (); } @@ -871,8 +929,8 @@ namespace CorCompare class EventData : MemberData { - public EventData (XmlDocument document, XmlNode parent, EventDefinition [] members) - : base (document, parent, members) + public EventData (XmlWriter writer, EventDefinition [] members) + : base (writer, members) { } @@ -888,11 +946,12 @@ namespace CorCompare return ((int) evt.Attributes).ToString (CultureInfo.InvariantCulture); } - protected override void AddExtraData (XmlNode p, MemberReference memberDefenition) + protected override void AddExtraAttributes (MemberReference memberDefinition) { - base.AddExtraData (p, memberDefenition); - EventDefinition evt = (EventDefinition) memberDefenition; - AddAttribute (p, "eventtype", Utils.CleanupTypeName (evt.EventType)); + base.AddExtraAttributes (memberDefinition); + + EventDefinition evt = (EventDefinition) memberDefinition; + AddAttribute ("eventtype", Utils.CleanupTypeName (evt.EventType)); } public override string ParentTag { @@ -908,8 +967,8 @@ namespace CorCompare { bool noAtts; - public MethodData (XmlDocument document, XmlNode parent, MethodDefinition [] members) - : base (document, parent, members) + public MethodData (XmlWriter writer, MethodDefinition [] members) + : base (writer, members) { } @@ -928,34 +987,59 @@ namespace CorCompare return ((int)( method.Attributes)).ToString (CultureInfo.InvariantCulture); } - protected override void AddExtraData (XmlNode p, MemberReference memberDefenition) + protected override ICustomAttributeProvider GetAdditionalCustomAttributeProvider (MemberReference member) { - base.AddExtraData (p, memberDefenition); + var mbase = (MethodDefinition) member; + return mbase.MethodReturnType; + } - if (!(memberDefenition is MethodDefinition)) - return; + protected override void AddExtraAttributes (MemberReference memberDefinition) + { + base.AddExtraAttributes (memberDefinition); - MethodDefinition mbase = (MethodDefinition) memberDefenition; + if (!(memberDefinition is MethodDefinition)) + return; - ParameterData parms = new ParameterData (document, p, mbase.Parameters); - parms.DoOutput (); + MethodDefinition mbase = (MethodDefinition) memberDefinition; if (mbase.IsAbstract) - AddAttribute (p, "abstract", "true"); + AddAttribute ("abstract", "true"); if (mbase.IsVirtual) - AddAttribute (p, "virtual", "true"); + AddAttribute ("virtual", "true"); if (mbase.IsFinal && mbase.IsVirtual && mbase.IsReuseSlot) - AddAttribute (p, "sealed", "true"); + AddAttribute ("sealed", "true"); if (mbase.IsStatic) - AddAttribute (p, "static", "true"); - + AddAttribute ("static", "true"); + var baseMethod = TypeHelper.GetBaseMethodInTypeHierarchy (mbase); + if (baseMethod != null && baseMethod != mbase) { + // This indicates whether this method is an override of another method. + // This information is not necessarily available in the api info for any + // particular assembly, because a method is only overriding another if + // there is a base virtual function with the same signature, and that + // base method can come from another assembly. + AddAttribute ("is-override", "true"); + } string rettype = Utils.CleanupTypeName (mbase.MethodReturnType.ReturnType); if (rettype != "System.Void" || !mbase.IsConstructor) - AddAttribute (p, "returntype", (rettype)); + AddAttribute ("returntype", (rettype)); +// +// if (mbase.MethodReturnType.HasCustomAttributes) +// AttributeData.OutputAttributes (writer, mbase.MethodReturnType); + } + + protected override void AddExtraData (MemberReference memberDefenition) + { + base.AddExtraData (memberDefenition); + + if (!(memberDefenition is MethodDefinition)) + return; + + MethodDefinition mbase = (MethodDefinition) memberDefenition; - AttributeData.OutputAttributes (document, p, mbase.MethodReturnType); + ParameterData parms = new ParameterData (writer, mbase.Parameters); + parms.DoOutput (); - MemberData.OutputGenericParameters (document, p, mbase); + MemberData.OutputGenericParameters (writer, mbase); } public override bool NoMemberAttributes { @@ -974,8 +1058,8 @@ namespace CorCompare class ConstructorData : MethodData { - public ConstructorData (XmlDocument document, XmlNode parent, MethodDefinition [] members) - : base (document, parent, members) + public ConstructorData (XmlWriter writer, MethodDefinition [] members) + : base (writer, members) { } @@ -992,23 +1076,20 @@ namespace CorCompare { private IList<ParameterDefinition> parameters; - public ParameterData (XmlDocument document, XmlNode parent, IList<ParameterDefinition> parameters) - : base (document, parent) + public ParameterData (XmlWriter writer, IList<ParameterDefinition> parameters) + : base (writer) { this.parameters = parameters; } public override void DoOutput () { - XmlNode parametersNode = document.CreateElement ("parameters"); - parent.AppendChild (parametersNode); - + writer.WriteStartElement ("parameters"); foreach (ParameterDefinition parameter in parameters) { - XmlNode paramNode = document.CreateElement ("parameter"); - parametersNode.AppendChild (paramNode); - AddAttribute (paramNode, "name", parameter.Name); - AddAttribute (paramNode, "position", parameter.Method.Parameters.IndexOf(parameter).ToString(CultureInfo.InvariantCulture)); - AddAttribute (paramNode, "attrib", ((int) parameter.Attributes).ToString()); + writer.WriteStartElement ("parameter"); + AddAttribute ("name", parameter.Name); + AddAttribute ("position", parameter.Method.Parameters.IndexOf(parameter).ToString(CultureInfo.InvariantCulture)); + AddAttribute ("attrib", ((int) parameter.Attributes).ToString()); string direction = "in"; @@ -1016,102 +1097,111 @@ namespace CorCompare direction = parameter.IsOut ? "out" : "ref"; TypeReference t = parameter.ParameterType; - AddAttribute (paramNode, "type", Utils.CleanupTypeName (t)); + AddAttribute ("type", Utils.CleanupTypeName (t)); if (parameter.IsOptional) { - AddAttribute (paramNode, "optional", "true"); + AddAttribute ("optional", "true"); if (parameter.HasConstant) - AddAttribute (paramNode, "defaultValue", parameter.Constant == null ? "NULL" : parameter.Constant.ToString ()); + AddAttribute ("defaultValue", parameter.Constant == null ? "NULL" : parameter.Constant.ToString ()); } if (direction != "in") - AddAttribute (paramNode, "direction", direction); + AddAttribute ("direction", direction); - AttributeData.OutputAttributes (document, paramNode, parameter); + AttributeData.OutputAttributes (writer, parameter); + writer.WriteEndElement (); // parameter } + writer.WriteEndElement (); // parameters } } - class AttributeData : BaseData + class AttributeData { - IList<CustomAttribute> atts; - - AttributeData (XmlDocument doc, XmlNode parent, IList<CustomAttribute> attributes) - : base (doc, parent) - { - atts = attributes; - } - - public override void DoOutput () + public static void DoOutput (XmlWriter writer, IList<ICustomAttributeProvider> providers) { - if (document == null) + if (writer == null) throw new InvalidOperationException ("Document not set"); - if (atts == null || atts.Count == 0) + if (providers == null || providers.Count == 0) + return; + + if (!providers.Any ((provider) => provider != null && provider.HasCustomAttributes)) return; - XmlNode natts = parent.SelectSingleNode("attributes"); - if (natts == null) { - natts = document.CreateElement ("attributes", null); - parent.AppendChild (natts); - } + writer.WriteStartElement ("attributes"); - foreach (var att in atts.OrderBy ((a) => a.Constructor.DeclaringType.FullName)) { - string attName = Utils.CleanupTypeName (att.Constructor.DeclaringType); - if (SkipAttribute (att)) + foreach (var provider in providers) { + if (provider == null) + continue; + + if (!provider.HasCustomAttributes) continue; - XmlNode node = document.CreateElement ("attribute"); - AddAttribute (node, "name", attName); - - XmlNode properties = null; - - Dictionary<string, object> attribute_mapping = CreateAttributeMapping (att); - - foreach (string name in attribute_mapping.Keys) { - if (name == "TypeId") - continue; - - if (properties == null) { - properties = node.AppendChild (document.CreateElement ("properties")); - } - - object o = attribute_mapping [name]; - - XmlNode n = properties.AppendChild (document.CreateElement ("property")); - AddAttribute (n, "name", name); - if (o == null) { - AddAttribute (n, "value", "null"); - continue; + var ass = provider as AssemblyDefinition; + if (ass != null && !Driver.FollowForwarders) + TypeForwardedToData.OutputForwarders (writer, ass); + + var attributes = provider.CustomAttributes. + Where ((att) => !SkipAttribute (att)). + OrderBy ((a) => a.Constructor.DeclaringType.FullName, StringComparer.Ordinal); + + foreach (var att in attributes) { + string attName = Utils.CleanupTypeName (att.Constructor.DeclaringType); + + writer.WriteStartElement ("attribute"); + writer.WriteAttributeString ("name", attName); + + var attribute_mapping = CreateAttributeMapping (att); + + if (attribute_mapping != null) { + var mapping = attribute_mapping.Where ((attr) => attr.Key != "TypeId"); + if (mapping.Any ()) { + writer.WriteStartElement ("properties"); + foreach (var kvp in mapping) { + string name = kvp.Key; + object o = kvp.Value; + + writer.WriteStartElement ("property"); + writer.WriteAttributeString ("name", name); + + if (o == null) { + writer.WriteAttributeString ("value", "null"); + } else { + string value = o.ToString (); + if (attName.EndsWith ("GuidAttribute", StringComparison.Ordinal)) + value = value.ToUpper (); + writer.WriteAttributeString ("value", value); + } + + writer.WriteEndElement (); // property + } + writer.WriteEndElement (); // properties + } } - - string value = o.ToString (); - if (attName.EndsWith ("GuidAttribute")) - value = value.ToUpper (); - AddAttribute (n, "value", value); + writer.WriteEndElement (); // attribute } - - natts.AppendChild (node); } + + writer.WriteEndElement (); // attributes } static Dictionary<string, object> CreateAttributeMapping (CustomAttribute attribute) { - var mapping = new Dictionary<string, object> (); + Dictionary<string, object> mapping = null; - PopulateMapping (mapping, attribute); + PopulateMapping (ref mapping, attribute); var constructor = attribute.Constructor.Resolve (); if (constructor == null || !constructor.HasParameters) return mapping; - PopulateMapping (mapping, constructor, attribute); + PopulateMapping (ref mapping, constructor, attribute); return mapping; } - static void PopulateMapping (Dictionary<string, object> mapping, CustomAttribute attribute) + static void PopulateMapping (ref Dictionary<string, object> mapping, CustomAttribute attribute) { if (!attribute.HasProperties) return; @@ -1123,13 +1213,15 @@ namespace CorCompare if (arg.Value is CustomAttributeArgument) arg = (CustomAttributeArgument) arg.Value; + if (mapping == null) + mapping = new Dictionary<string, object> (StringComparer.Ordinal); mapping.Add (name, GetArgumentValue (arg.Type, arg.Value)); } } static Dictionary<FieldReference, int> CreateArgumentFieldMapping (MethodDefinition constructor) { - Dictionary<FieldReference, int> field_mapping = new Dictionary<FieldReference, int> (); + Dictionary<FieldReference, int> field_mapping = null; int? argument = null; @@ -1157,6 +1249,9 @@ namespace CorCompare if (!argument.HasValue) break; + if (field_mapping == null) + field_mapping = new Dictionary<FieldReference, int> (); + if (!field_mapping.ContainsKey (field)) field_mapping.Add (field, (int) argument - 1); @@ -1170,7 +1265,7 @@ namespace CorCompare static Dictionary<PropertyDefinition, FieldReference> CreatePropertyFieldMapping (TypeDefinition type) { - Dictionary<PropertyDefinition, FieldReference> property_mapping = new Dictionary<PropertyDefinition, FieldReference> (); + Dictionary<PropertyDefinition, FieldReference> property_mapping = null; foreach (PropertyDefinition property in type.Properties) { if (property.GetMethod == null) @@ -1186,6 +1281,8 @@ namespace CorCompare if (field.DeclaringType.FullName != type.FullName) continue; + if (property_mapping == null) + property_mapping = new Dictionary<PropertyDefinition, FieldReference> (); property_mapping.Add (property, field); break; } @@ -1194,7 +1291,7 @@ namespace CorCompare return property_mapping; } - static void PopulateMapping (Dictionary<string, object> mapping, MethodDefinition constructor, CustomAttribute attribute) + static void PopulateMapping (ref Dictionary<string, object> mapping, MethodDefinition constructor, CustomAttribute attribute) { if (!constructor.HasBody) return; @@ -1207,6 +1304,8 @@ namespace CorCompare new DecimalConstantAttribute ((byte) ca[0].Value, (byte) ca[1].Value, (int) ca[2].Value, (int) ca[3].Value, (int) ca[4].Value) : new DecimalConstantAttribute ((byte) ca[0].Value, (byte) ca[1].Value, (uint) ca[2].Value, (uint) ca[3].Value, (uint) ca[4].Value); + if (mapping == null) + mapping = new Dictionary<string, object> (StringComparer.Ordinal); mapping.Add ("Value", dca.Value); return; case "System.ComponentModel.BindableAttribute": @@ -1214,6 +1313,8 @@ namespace CorCompare break; if (constructor.Parameters[0].ParameterType == constructor.Module.TypeSystem.Boolean) { + if (mapping == null) + mapping = new Dictionary<string, object> (StringComparer.Ordinal); mapping.Add ("Bindable", ca[0].Value); } else { throw new NotImplementedException (); @@ -1223,18 +1324,24 @@ namespace CorCompare } var field_mapping = CreateArgumentFieldMapping (constructor); - var property_mapping = CreatePropertyFieldMapping ((TypeDefinition) constructor.DeclaringType); - - foreach (var pair in property_mapping) { - int argument; - if (!field_mapping.TryGetValue (pair.Value, out argument)) - continue; - - var ca_arg = ca [argument]; - if (ca_arg.Value is CustomAttributeArgument) - ca_arg = (CustomAttributeArgument) ca_arg.Value; - - mapping.Add (pair.Key.Name, GetArgumentValue (ca_arg.Type, ca_arg.Value)); + if (field_mapping != null) { + var property_mapping = CreatePropertyFieldMapping ((TypeDefinition) constructor.DeclaringType); + + if (property_mapping != null) { + foreach (var pair in property_mapping) { + int argument; + if (!field_mapping.TryGetValue (pair.Value, out argument)) + continue; + + var ca_arg = ca [argument]; + if (ca_arg.Value is CustomAttributeArgument) + ca_arg = (CustomAttributeArgument)ca_arg.Value; + + if (mapping == null) + mapping = new Dictionary<string, object> (StringComparer.Ordinal); + mapping.Add (pair.Key.Name, GetArgumentValue (ca_arg.Type, ca_arg.Value)); + } + } } } @@ -1342,19 +1449,15 @@ namespace CorCompare static bool SkipAttribute (CustomAttribute attribute) { - var type_name = Utils.CleanupTypeName (attribute.Constructor.DeclaringType); - - return !TypeHelper.IsPublic (attribute) - || type_name.EndsWith ("TODOAttribute"); + if (!TypeHelper.IsPublic (attribute)) + return true; + + return attribute.Constructor.DeclaringType.Name.EndsWith ("TODOAttribute", StringComparison.Ordinal); } - public static void OutputAttributes (XmlDocument doc, XmlNode parent, ICustomAttributeProvider provider) + public static void OutputAttributes (XmlWriter writer, params ICustomAttributeProvider[] providers) { - if (!provider.HasCustomAttributes) - return; - - AttributeData ad = new AttributeData (doc, parent, provider.CustomAttributes); - ad.DoOutput (); + AttributeData.DoOutput (writer, providers); } } @@ -1426,7 +1529,7 @@ namespace CorCompare public int Compare (PropertyDefinition ma, PropertyDefinition mb) { - int res = String.Compare (ma.Name, mb.Name); + int res = String.Compare (ma.Name, mb.Name, StringComparison.Ordinal); if (res != 0) return res; @@ -1451,7 +1554,7 @@ namespace CorCompare { MethodDefinition ma = (MethodDefinition) a; MethodDefinition mb = (MethodDefinition) b; - int res = String.Compare (ma.Name, mb.Name); + int res = String.Compare (ma.Name, mb.Name, StringComparison.Ordinal); if (res != 0) return res; @@ -1480,7 +1583,7 @@ namespace CorCompare string siga = Parameters.GetSignature (pia); string sigb = Parameters.GetSignature (pib); - return String.Compare (siga, sigb); + return String.Compare (siga, sigb, StringComparison.Ordinal); } } } diff --git a/mcs/tools/xbuild/frameworks/net_2.0.xml b/mcs/tools/xbuild/frameworks/net_2.0.xml index 2b8bd9b1dff..4265fcc50ee 100644 --- a/mcs/tools/xbuild/frameworks/net_2.0.xml +++ b/mcs/tools/xbuild/frameworks/net_2.0.xml @@ -1,3 +1,3 @@ <?xml version="1.0" encoding="utf-8"?> -<FileList Name=".NET Framework 2.0" TargetFrameworkDirectory="..\..\..\..\2.0"> +<FileList Name=".NET Framework 2.0" TargetFrameworkDirectory="..\..\..\..\2.0-api"> </FileList> diff --git a/mcs/tools/xbuild/frameworks/net_3.0.xml b/mcs/tools/xbuild/frameworks/net_3.0.xml index ae06c8818c1..1a56750d51b 100644 --- a/mcs/tools/xbuild/frameworks/net_3.0.xml +++ b/mcs/tools/xbuild/frameworks/net_3.0.xml @@ -1,3 +1,3 @@ <?xml version="1.0" encoding="utf-8"?> -<FileList Name=".NET Framework 3.0" TargetFrameworkDirectory="..\..\..\..\2.0"> +<FileList Name=".NET Framework 3.0" TargetFrameworkDirectory="..\..\..\..\2.0-api"> </FileList> diff --git a/mcs/tools/xbuild/frameworks/net_3.5.xml b/mcs/tools/xbuild/frameworks/net_3.5.xml index 122584299a1..3e711014768 100644 --- a/mcs/tools/xbuild/frameworks/net_3.5.xml +++ b/mcs/tools/xbuild/frameworks/net_3.5.xml @@ -1,3 +1,3 @@ <?xml version="1.0" encoding="utf-8"?> -<FileList Name=".NET Framework 3.5" TargetFrameworkDirectory="..\..\..\..\3.5" IncludeFramework="v3.0"> +<FileList Name=".NET Framework 3.5" TargetFrameworkDirectory="..\..\..\..\3.5-api" IncludeFramework="v3.0"> </FileList> diff --git a/mcs/tools/xbuild/frameworks/net_4.0.xml b/mcs/tools/xbuild/frameworks/net_4.0.xml index 701279497fd..841cc536e62 100644 --- a/mcs/tools/xbuild/frameworks/net_4.0.xml +++ b/mcs/tools/xbuild/frameworks/net_4.0.xml @@ -1,3 +1,3 @@ <?xml version="1.0" encoding="utf-8"?> -<FileList Name=".NET Framework 4" TargetFrameworkDirectory="..\..\..\..\4.0"> +<FileList Name=".NET Framework 4" TargetFrameworkDirectory="..\..\..\..\4.0-api"> </FileList> diff --git a/mcs/tools/xbuild/frameworks/net_4.0_client.xml b/mcs/tools/xbuild/frameworks/net_4.0_client.xml index 951933a2f9a..d3fd85ccc0b 100644 --- a/mcs/tools/xbuild/frameworks/net_4.0_client.xml +++ b/mcs/tools/xbuild/frameworks/net_4.0_client.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<FileList Name=".NET Framework 4 Client Profile" TargetFrameworkDirectory="..\..\..\..\..\..\4.0"> +<FileList Name=".NET Framework 4 Client Profile" TargetFrameworkDirectory="..\..\..\..\..\..\4.0-api"> <File AssemblyName="System" Version="4.0.0.0" PublicKeyToken="b77a5c561934e089" /> <File AssemblyName="System.Activities" Version="4.0.0.0" PublicKeyToken="31bf3856ad364e35" /> <File AssemblyName="System.Dynamic" Version="4.0.0.0" PublicKeyToken="b03f5f7f11d50a3a" /> diff --git a/mono/metadata/cominterop.c b/mono/metadata/cominterop.c index 162e7436406..15007be0d5b 100644 --- a/mono/metadata/cominterop.c +++ b/mono/metadata/cominterop.c @@ -170,6 +170,22 @@ mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpointer static void mono_marshal_safearray_free_indices (gpointer indices); +MonoClass* +mono_class_try_get_com_object_class (void) +{ + static MonoClass *tmp_class; + static gboolean inited; + MonoClass *klass; + if (!inited) { + klass = mono_class_from_name (mono_defaults.corlib, "System", "__ComObject"); + mono_memory_barrier (); + tmp_class = klass; + mono_memory_barrier (); + inited = TRUE; + } + return tmp_class; +} + /** * cominterop_method_signature: * @method: a method diff --git a/mono/metadata/cominterop.h b/mono/metadata/cominterop.h index 6a15374f16c..1338bd3b5bc 100644 --- a/mono/metadata/cominterop.h +++ b/mono/metadata/cominterop.h @@ -53,4 +53,7 @@ mono_string_from_bstr (gpointer bstr); MONO_API void mono_free_bstr (gpointer bstr); +MonoClass* +mono_class_try_get_com_object_class (void); + #endif /* __MONO_COMINTEROP_H__ */ diff --git a/mono/metadata/coree.c b/mono/metadata/coree.c index 7c4be6afe7e..c2e47b9ca7b 100644 --- a/mono/metadata/coree.c +++ b/mono/metadata/coree.c @@ -143,7 +143,7 @@ __int32 STDMETHODCALLTYPE _CorExeMain(void) MonoMethod* method; guint32 entry; gchar* file_name; - gchar* error; + gchar* corlib_version_error; int argc; gunichar2** argvw; gchar** argv; @@ -153,9 +153,9 @@ __int32 STDMETHODCALLTYPE _CorExeMain(void) init_from_coree = TRUE; domain = mono_runtime_load (file_name, NULL); - error = (gchar*) mono_check_corlib_version (); - if (error) { - g_free (error); + corlib_version_error = (gchar*) mono_check_corlib_version (); + if (corlib_version_error) { + g_free (corlib_version_error); g_free (file_name); MessageBox (NULL, L"Corlib not in sync with this runtime.", NULL, MB_ICONERROR); mono_runtime_quit (); diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index 55a02988f30..142a56e7b18 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -1970,7 +1970,10 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, MonoMethod * mono_get_method (MonoImage *image, guint32 token, MonoClass *klass) { - return mono_get_method_full (image, token, klass, NULL); + MonoError error; + MonoMethod *result = mono_get_method_checked (image, token, klass, NULL, &error); + mono_error_cleanup (&error); + return result; } MonoMethod * @@ -1979,11 +1982,7 @@ mono_get_method_full (MonoImage *image, guint32 token, MonoClass *klass, { MonoError error; MonoMethod *result = mono_get_method_checked (image, token, klass, context, &error); - mono_loader_assert_no_error (); - if (!mono_error_ok (&error)) { - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); - } + mono_error_cleanup (&error); return result; } @@ -2126,12 +2125,7 @@ mono_get_method_constrained (MonoImage *image, guint32 token, MonoClass *constra { MonoError error; MonoMethod *result = mono_get_method_constrained_checked (image, token, constrained_class, context, cil_method, &error); - - mono_loader_assert_no_error (); - if (!mono_error_ok (&error)) { - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); - } + mono_error_cleanup (&error); return result; } diff --git a/mono/metadata/loader.h b/mono/metadata/loader.h index 74d82817bb8..6999f81961d 100644 --- a/mono/metadata/loader.h +++ b/mono/metadata/loader.h @@ -8,14 +8,14 @@ MONO_BEGIN_DECLS typedef mono_bool (*MonoStackWalk) (MonoMethod *method, int32_t native_offset, int32_t il_offset, mono_bool managed, void* data); -MONO_API MonoMethod * +MONO_RT_EXTERNAL_ONLY MONO_API MonoMethod * mono_get_method (MonoImage *image, uint32_t token, MonoClass *klass); -MONO_API MonoMethod * +MONO_RT_EXTERNAL_ONLY MONO_API MonoMethod * mono_get_method_full (MonoImage *image, uint32_t token, MonoClass *klass, MonoGenericContext *context); -MONO_API MonoMethod * +MONO_RT_EXTERNAL_ONLY MONO_API MonoMethod * mono_get_method_constrained (MonoImage *image, uint32_t token, MonoClass *constrained_class, MonoGenericContext *context, MonoMethod **cil_method); diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index 3700043213c..d82bf5dc072 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -618,6 +618,8 @@ typedef struct { gboolean (*debug_log_is_enabled) (void); gboolean (*tls_key_supported) (MonoTlsKey key); void (*init_delegate) (MonoDelegate *del); + MonoObject* (*runtime_invoke) (MonoMethod *method, void *obj, void **params, MonoError *error, MonoObject **exc); + void* (*compile_method) (MonoMethod *method, MonoError *error); } MonoRuntimeCallbacks; typedef gboolean (*MonoInternalStackWalk) (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data); @@ -632,12 +634,8 @@ typedef struct { gboolean (*mono_install_handler_block_guard) (MonoThreadUnwindState *unwind_state); } MonoRuntimeExceptionHandlingCallbacks; - /* used to free a dynamic method */ -typedef void (*MonoFreeMethodFunc) (MonoDomain *domain, MonoMethod *method); - -/* Used to initialize the method pointers inside vtables */ -typedef gboolean (*MonoInitVTableFunc) (MonoVTable *vtable); +typedef void (*MonoFreeMethodFunc) (MonoDomain *domain, MonoMethod *method); MONO_COLD void mono_set_pending_exception (MonoException *exc); @@ -683,12 +681,6 @@ mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *p void mono_runtime_free_method (MonoDomain *domain, MonoMethod *method); -void -mono_install_runtime_invoke (MonoInvokeFunc func); - -void -mono_install_compile_method (MonoCompileFunc func); - void mono_install_free_method (MonoFreeMethodFunc func); diff --git a/mono/metadata/object.c b/mono/metadata/object.c index bd31aaa2a8b..94c29712f16 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -584,20 +584,6 @@ mono_set_always_build_imt_thunks (gboolean value) always_build_imt_thunks = value; } -static MonoCompileFunc default_mono_compile_method = NULL; - -/** - * mono_install_compile_method: - * @func: function to install - * - * This is a VM internal routine - */ -void -mono_install_compile_method (MonoCompileFunc func) -{ - default_mono_compile_method = func; -} - /** * mono_compile_method: * @method: The method to compile. @@ -608,13 +594,19 @@ mono_install_compile_method (MonoCompileFunc func) gpointer mono_compile_method (MonoMethod *method) { + gpointer res; + MonoError error; + MONO_REQ_GC_NEUTRAL_MODE - if (!default_mono_compile_method) { + if (!callbacks.compile_method) { g_error ("compile method called on uninitialized runtime"); return NULL; } - return default_mono_compile_method (method); + res = callbacks.compile_method (method, &error); + if (!mono_error_ok (&error)) + mono_error_raise_exception (&error); + return res; } gpointer @@ -2846,13 +2838,24 @@ mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) } static MonoObject* -dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc) +do_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc) { - g_error ("runtime invoke called on uninitialized runtime"); - return NULL; -} + MonoObject *result = NULL; + MonoError error; -static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke; + g_assert (callbacks.runtime_invoke); + result = callbacks.runtime_invoke (method, obj, params, &error, exc); + if (!mono_error_ok (&error)) { + if (exc) { + *exc = (MonoObject*)mono_error_convert_to_exception (&error); + return NULL; + } else { + mono_error_raise_exception (&error); + } + } + + return result; +} /** * mono_runtime_invoke: @@ -2901,7 +2904,7 @@ mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject ** if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS) mono_profiler_method_start_invoke (method); - result = default_mono_runtime_invoke (method, obj, params, exc); + result = do_runtime_invoke (method, obj, params, exc); if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS) mono_profiler_method_end_invoke (method); @@ -3473,7 +3476,7 @@ mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObjec { MONO_REQ_GC_UNSAFE_MODE; - default_mono_runtime_invoke (prop->set, obj, params, exc); + do_runtime_invoke (prop->set, obj, params, exc); } /** @@ -3498,7 +3501,7 @@ mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObjec { MONO_REQ_GC_UNSAFE_MODE; - return default_mono_runtime_invoke (prop->get, obj, params, exc); + return do_runtime_invoke (prop->get, obj, params, exc); } /* @@ -4254,19 +4257,6 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc) } /** - * mono_install_runtime_invoke: - * @func: Function to install - * - * This is a VM internal routine - */ -void -mono_install_runtime_invoke (MonoInvokeFunc func) -{ - default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke; -} - - -/** * mono_runtime_invoke_array: * @method: method to invoke * @obJ: object instance diff --git a/mono/metadata/remoting.c b/mono/metadata/remoting.c index 8ca8ae62fdb..6e84ab7c0c4 100644 --- a/mono/metadata/remoting.c +++ b/mono/metadata/remoting.c @@ -408,7 +408,7 @@ mono_marshal_get_remoting_invoke (MonoMethod *method) /* this seems to be the best plase to put this, as all remoting invokes seem to get filtered through here */ #ifndef DISABLE_COM - if (mono_class_is_com_object (method->klass) || method->klass == mono_class_get_com_object_class ()) { + if (mono_class_is_com_object (method->klass) || method->klass == mono_class_try_get_com_object_class ()) { MonoVTable *vtable = mono_class_vtable (mono_domain_get (), method->klass); g_assert (vtable); /*FIXME do proper error handling*/ diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 437d82f05f8..98c346de4cd 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -4607,6 +4607,7 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code MonoAotModule *module = (MonoAotModule*)aot_module; gboolean res, no_ftnptr = FALSE; MonoMemPool *mp; + MonoError error; gboolean using_gsharedvt = FALSE; //printf ("DYN: %p %d\n", aot_module, plt_info_offset); @@ -4635,7 +4636,9 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code */ if (mono_aot_only && ji.type == MONO_PATCH_INFO_METHOD && !ji.data.method->is_generic && !mono_method_check_context_used (ji.data.method) && !(ji.data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && !mono_method_needs_static_rgctx_invoke (ji.data.method, FALSE) && !using_gsharedvt) { - target = (guint8 *)mono_jit_compile_method (ji.data.method); + target = (guint8 *)mono_jit_compile_method (ji.data.method, &error); + if (!mono_error_ok (&error)) + mono_error_raise_exception (&error); no_ftnptr = TRUE; } else { target = (guint8 *)mono_resolve_patch_target (NULL, mono_domain_get (), NULL, &ji, TRUE); diff --git a/mono/mini/jit-icalls.c b/mono/mini/jit-icalls.c index f049daca1ca..79fb7d74e1b 100644 --- a/mono/mini/jit-icalls.c +++ b/mono/mini/jit-icalls.c @@ -1372,13 +1372,29 @@ mono_generic_class_init (MonoVTable *vtable) gpointer mono_fill_class_rgctx (MonoVTable *vtable, int index) { - return mono_class_fill_runtime_generic_context (vtable, index); + MonoError error; + gpointer res; + + res = mono_class_fill_runtime_generic_context (vtable, index, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + return res; } gpointer mono_fill_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, int index) { - return mono_method_fill_runtime_generic_context (mrgctx, index); + MonoError error; + gpointer res; + + res = mono_method_fill_runtime_generic_context (mrgctx, index, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + return res; } /* @@ -1735,16 +1751,75 @@ mono_llvmonly_set_calling_assembly (MonoImage *image) jit_tls->calling_image = image; } + +static gboolean +get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data) +{ + MonoMethod **dest = (MonoMethod **)data; + + /* skip unmanaged frames */ + if (!managed) + return FALSE; + + if (!(*dest)) { + if (!strcmp (m->klass->name_space, "System.Reflection")) + return FALSE; + *dest = m; + return TRUE; + } + return FALSE; +} + +static gboolean +get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data) +{ + MonoMethod **dest = (MonoMethod **)data; + + /* skip unmanaged frames */ + if (!managed) + return FALSE; + + if (m->wrapper_type != MONO_WRAPPER_NONE) + return FALSE; + + if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection")) + return FALSE; + + if (m == *dest) { + *dest = NULL; + return FALSE; + } + if (!(*dest)) { + *dest = m; + return TRUE; + } + return FALSE; +} + MonoObject* mono_llvmonly_get_calling_assembly (void) { MonoJitTlsData *jit_tls = NULL; + MonoMethod *m; + MonoMethod *dest; + MonoAssembly *assembly; - jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id); - g_assert (jit_tls); - if (!jit_tls->calling_image) { - mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform.")); - return NULL; + dest = NULL; + mono_stack_walk_no_il (get_executing, &dest); + m = dest; + mono_stack_walk_no_il (get_caller_no_reflection, &dest); + + if (!dest) { + /* Fall back to TLS */ + jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id); + g_assert (jit_tls); + if (!jit_tls->calling_image) { + mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform.")); + return NULL; + } + assembly = jit_tls->calling_image->assembly; + } else { + assembly = dest->klass->image->assembly; } return (MonoObject*)mono_assembly_get_object (mono_domain_get (), jit_tls->calling_image->assembly); } diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 2ff04067b88..130c62165ba 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -7084,12 +7084,12 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, cheader = mono_method_get_header (cmethod); if (cheader == NULL || mono_loader_get_last_error ()) { - MonoLoaderError *error = mono_loader_get_last_error (); - if (cheader) mono_metadata_free_mh (cheader); - if (inline_always && error) - mono_cfg_set_exception (cfg, error->exception_type); + if (inline_always && mono_loader_get_last_error ()) { + mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR); + mono_error_set_from_loader_error (&cfg->error); + } mono_loader_clear_error (); return 0; @@ -8152,10 +8152,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b image = method->klass->image; header = mono_method_get_header (method); if (!header) { - MonoLoaderError *error; - - if ((error = mono_loader_get_last_error ())) { - mono_cfg_set_exception (cfg, error->exception_type); + if (mono_loader_get_last_error ()) { + mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR); + mono_error_set_from_loader_error (&cfg->error); } else { mono_cfg_set_exception_invalid_program (cfg, g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name)); } @@ -9220,8 +9219,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } } - if (!cmethod || mono_loader_get_last_error ()) - LOAD_ERROR; + if (!cmethod || mono_loader_get_last_error ()) { + if (mono_loader_get_last_error ()) { + mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR); + mono_error_set_from_loader_error (&cfg->error); + CHECK_CFG_ERROR; + } else { + LOAD_ERROR; + } + } if (!dont_verify && !cfg->skip_visibility) { MonoMethod *target_method = cil_method; if (method->is_inflated) { diff --git a/mono/mini/mini-generic-sharing.c b/mono/mini/mini-generic-sharing.c index 94312a18f43..af1c8f5a0b6 100644 --- a/mono/mini/mini-generic-sharing.c +++ b/mono/mini/mini-generic-sharing.c @@ -840,13 +840,17 @@ class_get_rgctx_template_oti (MonoClass *klass, int type_argc, guint32 slot, gbo } static gpointer -class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_type) +class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_type, MonoError *error) { + mono_error_init (error); + switch (info_type) { case MONO_RGCTX_INFO_STATIC_DATA: { MonoVTable *vtable = mono_class_vtable (domain, klass); - if (!vtable) - mono_raise_exception (mono_class_get_exception_for_failure (klass)); + if (!vtable) { + mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass)); + return NULL; + } return mono_vtable_get_static_field_data (vtable); } case MONO_RGCTX_INFO_KLASS: @@ -855,8 +859,10 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty return klass->element_class; case MONO_RGCTX_INFO_VTABLE: { MonoVTable *vtable = mono_class_vtable (domain, klass); - if (!vtable) - mono_raise_exception (mono_class_get_exception_for_failure (klass)); + if (!vtable) { + mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass)); + return NULL; + } return vtable; } case MONO_RGCTX_INFO_CAST_CACHE: { @@ -960,7 +966,9 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty else method = mono_class_get_method_from_name (klass, "Unbox", 1); - addr = mono_compile_method (method); + addr = mono_jit_compile_method (method, error); + if (!mono_error_ok (error)) + return NULL; // The caller uses the gsharedvt call signature @@ -1465,14 +1473,20 @@ mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSign return addr; } +/* + * instantiate_info: + * + * Instantiate the info given by OTI for context CONTEXT. + */ static gpointer instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti, - MonoGenericContext *context, MonoClass *klass) + MonoGenericContext *context, MonoClass *klass, MonoError *error) { - MonoError error; gpointer data; gboolean temporary; + mono_error_init (error); + if (!oti->data) return NULL; @@ -1514,13 +1528,12 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti if (oti->info_type == MONO_RGCTX_INFO_KLASS) mono_class_compute_gc_descriptor (arg_class); - return class_type_info (domain, arg_class, oti->info_type); + return class_type_info (domain, arg_class, oti->info_type, error); } case MONO_RGCTX_INFO_TYPE: return data; case MONO_RGCTX_INFO_REFLECTION_TYPE: { - MonoReflectionType *ret = mono_type_get_object_checked (domain, (MonoType *)data, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + MonoReflectionType *ret = mono_type_get_object_checked (domain, (MonoType *)data, error); return ret; } @@ -1573,7 +1586,6 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti MonoJumpInfoVirtMethod *info = (MonoJumpInfoVirtMethod *)data; MonoClass *iface_class = info->method->klass; MonoMethod *method; - MonoError error; int ioffset, slot; gpointer addr; @@ -1590,8 +1602,9 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti g_assert (info->klass->vtable); method = info->klass->vtable [ioffset + slot]; - method = mono_class_inflate_generic_method_checked (method, context, &error); - + method = mono_class_inflate_generic_method_checked (method, context, error); + if (!mono_error_ok (error)) + return NULL; addr = mono_compile_method (method); return mini_add_method_trampoline (method, addr, mono_method_needs_static_rgctx_invoke (method, FALSE), FALSE); } @@ -1648,8 +1661,10 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti g_assert (method->context.method_inst); vtable = mono_class_vtable (domain, method->method.method.klass); - if (!vtable) - mono_raise_exception (mono_class_get_exception_for_failure (method->method.method.klass)); + if (!vtable) { + mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (method->method.method.klass)); + return NULL; + } return mono_method_lookup_rgctx (vtable, method->context.method_inst); } @@ -1860,7 +1875,9 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti offset += size; break; default: - res->entries [i] = instantiate_info (domain, template_, context, klass); + res->entries [i] = instantiate_info (domain, template_, context, klass, error); + if (!mono_error_ok (error)) + return NULL; break; } } @@ -2231,7 +2248,7 @@ alloc_rgctx_array (MonoDomain *domain, int n, gboolean is_mrgctx) static gpointer fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContext *rgctx, guint32 slot, - MonoGenericInst *method_inst) + MonoGenericInst *method_inst, MonoError *error) { gpointer info; int i, first_slot, size; @@ -2243,6 +2260,8 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex int rgctx_index; gboolean do_free; + mono_error_init (error); + g_assert (rgctx); mono_domain_lock (domain); @@ -2285,7 +2304,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex oti = class_get_rgctx_template_oti (get_shared_class (klass), method_inst ? method_inst->type_argc : 0, slot, TRUE, TRUE, &do_free); /* This might take the loader lock */ - info = instantiate_info (domain, &oti, &context, klass); + info = instantiate_info (domain, &oti, &context, klass, error); g_assert (info); /* @@ -2319,7 +2338,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex * Instantiates a slot in the RGCTX, returning its value. */ gpointer -mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot) +mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot, MonoError *error) { static gboolean inited = FALSE; static int num_alloced = 0; @@ -2328,6 +2347,8 @@ mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot) MonoRuntimeGenericContext *rgctx; gpointer info; + mono_error_init (error); + mono_domain_lock (domain); if (!inited) { @@ -2344,7 +2365,7 @@ mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot) mono_domain_unlock (domain); - info = fill_runtime_generic_context (class_vtable, rgctx, slot, 0); + info = fill_runtime_generic_context (class_vtable, rgctx, slot, 0, error); DEBUG (printf ("get rgctx slot: %s %d -> %p\n", mono_type_full_name (&class_vtable->klass->byval_arg), slot, info)); @@ -2359,11 +2380,11 @@ mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot) * Instantiates a slot in the MRGCTX. */ gpointer -mono_method_fill_runtime_generic_context (MonoMethodRuntimeGenericContext *mrgctx, guint32 slot) +mono_method_fill_runtime_generic_context (MonoMethodRuntimeGenericContext *mrgctx, guint32 slot, MonoError *error) { gpointer info; - info = fill_runtime_generic_context (mrgctx->class_vtable, (MonoRuntimeGenericContext*)mrgctx, slot, mrgctx->method_inst); + info = fill_runtime_generic_context (mrgctx->class_vtable, (MonoRuntimeGenericContext*)mrgctx, slot, mrgctx->method_inst, error); return info; } diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index 159e3e4affb..4640672dd54 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -1846,7 +1846,7 @@ no_gsharedvt_in_wrapper (void) } static gpointer -mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException **ex) +mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *error) { MonoDomain *target_domain, *domain = mono_domain_get (); MonoJitInfo *info; @@ -1855,6 +1855,8 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException MonoJitICallInfo *callinfo = NULL; WrapperInfo *winfo = NULL; + mono_error_init (error); + /* * ICALL wrappers are handled specially, since there is only one copy of them * shared by all appdomains. @@ -1887,9 +1889,8 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException ctx = mono_method_get_context (method); method = info->d.synchronized_inner.method; if (ctx) { - MonoError error; - method = mono_class_inflate_generic_method_checked (method, ctx, &error); - g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ + method = mono_class_inflate_generic_method_checked (method, ctx, error); + g_assert (mono_error_ok (error)); /* FIXME don't swallow the error */ } } } @@ -1904,9 +1905,9 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException mono_jit_stats.methods_lookups++; vtable = mono_class_vtable (domain, method->klass); g_assert (vtable); - tmpEx = mono_runtime_class_init_full (vtable, ex == NULL); + tmpEx = mono_runtime_class_init_full (vtable, FALSE); if (tmpEx) { - *ex = tmpEx; + mono_error_set_exception_instance (error, tmpEx); return NULL; } return mono_create_ftnptr (target_domain, info->code_start); @@ -1937,7 +1938,9 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException #endif if (!code) - code = mono_jit_compile_method_inner (method, target_domain, opt, ex); + code = mono_jit_compile_method_inner (method, target_domain, opt, error); + if (!mono_error_ok (error)) + return NULL; if (!code && mono_llvm_only) { if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) { @@ -1988,17 +1991,11 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException } gpointer -mono_jit_compile_method (MonoMethod *method) +mono_jit_compile_method (MonoMethod *method, MonoError *error) { - MonoException *ex = NULL; gpointer code; - code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), &ex); - if (!code) { - g_assert (ex); - mono_raise_exception (ex); - } - + code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), error); return code; } @@ -2199,7 +2196,7 @@ typedef struct { } RuntimeInvokeInfo; static RuntimeInvokeInfo* -create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt) +create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt, MonoError *error) { MonoMethod *invoke; RuntimeInvokeInfo *info; @@ -2302,7 +2299,11 @@ create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer com invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig); g_free (wrapper_sig); - info->compiled_method = mono_jit_compile_method (wrapper); + info->compiled_method = mono_jit_compile_method (wrapper, error); + if (!mono_error_ok (error)) { + g_free (info); + return NULL; + } } else { /* Gsharedvt methods can be invoked the same way */ /* The out wrapper has the same signature as the compiled gsharedvt method */ @@ -2314,7 +2315,11 @@ create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer com g_free (wrapper_sig); } } - info->runtime_invoke = mono_jit_compile_method (invoke); + info->runtime_invoke = mono_jit_compile_method (invoke, error); + if (!mono_error_ok (error)) { + g_free (info); + return NULL; + } } return info; @@ -2396,10 +2401,11 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void * @method: the method to invoke * @obj: this pointer * @params: array of parameter values. + * @error: error * @exc: used to catch exceptions objects */ static MonoObject* -mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc) +mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoError *error, MonoObject **exc) { MonoMethod *invoke, *callee; MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method); @@ -2409,6 +2415,8 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec MonoJitInfo *ji = NULL; gboolean callee_gsharedvt = FALSE; + mono_error_init (error); + if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) { g_warning ("Ignoring invocation of an instance method on a NULL instance.\n"); return NULL; @@ -2458,18 +2466,10 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec } if (callee) { - MonoException *jit_ex = NULL; - - compiled_method = mono_jit_compile_method_with_opt (callee, mono_get_optimizations_for_method (callee, default_opt), &jit_ex); + compiled_method = mono_jit_compile_method_with_opt (callee, mono_get_optimizations_for_method (callee, default_opt), error); if (!compiled_method) { - g_assert (jit_ex); - if (exc) { - *exc = (MonoObject*)jit_ex; - return NULL; - } else { - mono_raise_exception (jit_ex); - /* coverity[unreachable] */ - } + g_assert (!mono_error_ok (error)); + return NULL; } if (mono_llvm_only) { @@ -2485,7 +2485,9 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec compiled_method = NULL; } - info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt); + info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt, error); + if (!mono_error_ok (error)) + return NULL; mono_domain_lock (domain); info2 = (RuntimeInvokeInfo *)mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info); @@ -2523,7 +2525,9 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec if (!dyn_runtime_invoke) { invoke = mono_marshal_get_runtime_invoke_dynamic (); - dyn_runtime_invoke = (RuntimeInvokeDynamicFunction)mono_jit_compile_method (invoke); + dyn_runtime_invoke = (RuntimeInvokeDynamicFunction)mono_jit_compile_method (invoke, error); + if (!mono_error_ok (error)) + return NULL; } /* Convert the arguments to the format expected by start_dyn_call () */ @@ -3491,6 +3495,14 @@ mini_init (const char *filename, const char *runtime_version) callbacks.get_imt_trampoline = mini_get_imt_trampoline; callbacks.imt_entry_inited = mini_imt_entry_inited; callbacks.init_delegate = mini_init_delegate; +#define JIT_INVOKE_WORKS +#ifdef JIT_INVOKE_WORKS + callbacks.runtime_invoke = mono_jit_runtime_invoke; +#endif +#define JIT_TRAMPOLINES_WORK +#ifdef JIT_TRAMPOLINES_WORK + callbacks.compile_method = mono_jit_compile_method; +#endif mono_install_callbacks (&callbacks); @@ -3560,9 +3572,7 @@ mini_init (const char *filename, const char *runtime_version) #endif mono_threads_install_cleanup (mini_thread_cleanup); -#define JIT_TRAMPOLINES_WORK #ifdef JIT_TRAMPOLINES_WORK - mono_install_compile_method (mono_jit_compile_method); mono_install_free_method (mono_jit_free_method); mono_install_trampoline (mono_create_jit_trampoline); mono_install_jump_trampoline (mono_create_jump_trampoline); @@ -3573,10 +3583,6 @@ mini_init (const char *filename, const char *runtime_version) mono_install_create_domain_hook (mini_create_jit_domain_info); mono_install_free_domain_hook (mini_free_jit_domain_info); #endif -#define JIT_INVOKE_WORKS -#ifdef JIT_INVOKE_WORKS - mono_install_runtime_invoke (mono_jit_runtime_invoke); -#endif mono_install_get_cached_class_info (mono_aot_get_cached_class_info); mono_install_get_class_from_name (mono_aot_get_class_from_name); mono_install_jit_info_find_in_aot (mono_aot_find_jit_info); diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index f1fe616b969..a28fd9168d3 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -501,13 +501,13 @@ mini_add_method_wrappers_llvmonly (MonoMethod *m, gpointer compiled_method, gboo } /** - * common_call_trampoline: + * common_call_trampoline_inner: * * The code to handle normal, virtual, and interface method calls and jumps, both * from JITted and LLVM compiled code. */ static gpointer -common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *vt, gpointer *vtable_slot) +common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *vt, gpointer *vtable_slot, MonoError *error) { gpointer addr, compiled_method; gboolean generic_shared = FALSE; @@ -520,6 +520,8 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT gpointer *orig_vtable_slot, *vtable_slot_to_patch = NULL; MonoJitInfo *ji = NULL; + mono_error_init (error); + virtual_ = vt && (gpointer)vtable_slot > (gpointer)vt; imt_call = vt && (gpointer)vtable_slot < (gpointer)vt; @@ -691,8 +693,9 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT if (!code && mono_method_needs_static_rgctx_invoke (m, FALSE)) need_rgctx_tramp = TRUE; - addr = compiled_method = mono_compile_method (m); - g_assert (addr); + addr = compiled_method = mono_jit_compile_method (m, error); + if (!addr) + return NULL; if (generic_virtual || variant_iface) { if (vt->klass->valuetype) /*FIXME is this required variant iface?*/ @@ -801,11 +804,11 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT } static gpointer -common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *vt, gpointer *vtable_slot) +common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *vt, gpointer *vtable_slot, MonoError *error) { gpointer res; MONO_PREPARE_RESET_BLOCKING; - res = common_call_trampoline_inner (regs, code, m, vt, vtable_slot); + res = common_call_trampoline_inner (regs, code, m, vt, vtable_slot, error); MONO_FINISH_RESET_BLOCKING; return res; } @@ -818,9 +821,17 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * gpointer mono_magic_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp) { + MonoError error; + gpointer res; + trampoline_calls ++; - return common_call_trampoline (regs, code, (MonoMethod *)arg, NULL, NULL); + res = common_call_trampoline (regs, code, (MonoMethod *)arg, NULL, NULL, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + return res; } /** @@ -835,7 +846,8 @@ mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp) MonoVTable *vt; gpointer *vtable_slot; MonoMethod *m; - gpointer addr; + MonoError error; + gpointer addr, res; trampoline_calls ++; @@ -889,7 +901,12 @@ mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp) m = NULL; } - return common_call_trampoline (regs, code, m, vt, vtable_slot); + res = common_call_trampoline (regs, code, m, vt, vtable_slot, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + return res; } #ifndef DISABLE_REMOTING @@ -922,7 +939,11 @@ mono_generic_virtual_remoting_trampoline (mgreg_t *regs, guint8 *code, MonoMetho g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */; m = mono_marshal_get_remoting_invoke_with_check (m); - addr = mono_compile_method (m); + addr = mono_jit_compile_method (m, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } g_assert (addr); return addr; @@ -990,8 +1011,14 @@ mono_aot_plt_trampoline (mgreg_t *regs, guint8 *code, guint8 *aot_module, res = mono_aot_plt_resolve (aot_module, plt_info_offset, code); if (!res) { - if (mono_loader_get_last_error ()) - mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ())); + if (mono_loader_get_last_error ()) { + MonoError error; + + mono_error_init (&error); + mono_error_set_from_loader_error (&error); + mono_error_set_pending_exception (&error); + return NULL; + } // FIXME: Error handling (how ?) g_assert (res); } @@ -1010,6 +1037,8 @@ mono_rgctx_lazy_fetch_trampoline (mgreg_t *regs, guint8 *code, gpointer data, gu gpointer arg = (gpointer)(gssize)r [MONO_ARCH_VTABLE_REG]; guint32 index = MONO_RGCTX_SLOT_INDEX (slot); gboolean mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot); + MonoError error; + gpointer res; trampoline_calls ++; @@ -1021,9 +1050,14 @@ mono_rgctx_lazy_fetch_trampoline (mgreg_t *regs, guint8 *code, gpointer data, gu num_lookups++; if (mrgctx) - return mono_method_fill_runtime_generic_context ((MonoMethodRuntimeGenericContext *)arg, index); + res = mono_method_fill_runtime_generic_context ((MonoMethodRuntimeGenericContext *)arg, index, &error); else - return mono_class_fill_runtime_generic_context ((MonoVTable *)arg, index); + res = mono_class_fill_runtime_generic_context ((MonoVTable *)arg, index, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + return res; } /* @@ -1070,6 +1104,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr MonoJitInfo *ji; MonoMethod *m; MonoMethod *method = NULL; + MonoError error; gboolean multicast, callvirt = FALSE, closed_over_null = FALSE; gboolean need_rgctx_tramp = FALSE; gboolean need_unbox_tramp = FALSE; @@ -1114,8 +1149,10 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr if (!(sig && method == tramp_info->method)) { mono_error_init (&err); sig = mono_method_signature_checked (method, &err); - if (!sig) - mono_error_raise_exception (&err); + if (!sig) { + mono_error_set_pending_exception (&err); + return NULL; + } } if (sig->hasthis && method->klass->valuetype) { @@ -1146,8 +1183,10 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr if (!(sig && method == tramp_info->method)) { mono_error_init (&err); sig = mono_method_signature_checked (method, &err); - if (!sig) - mono_error_raise_exception (&err); + if (!sig) { + mono_error_set_pending_exception (&err); + return NULL; + } } callvirt = !delegate->target && sig->hasthis; @@ -1196,7 +1235,11 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr if (enable_caching && delegate->method_code && *delegate->method_code) { delegate->method_ptr = *delegate->method_code; } else { - compiled_method = addr = mono_compile_method (method); + compiled_method = addr = mono_jit_compile_method (method, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } addr = mini_add_method_trampoline (method, compiled_method, need_rgctx_tramp, need_unbox_tramp); delegate->method_ptr = addr; if (enable_caching && delegate->method_code) @@ -1222,7 +1265,11 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr if (!code) { /* The general, unoptimized case */ m = mono_marshal_get_delegate_invoke (invoke, delegate); - code = (guint8 *)mono_compile_method (m); + code = (guint8 *)mono_jit_compile_method (m, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } code = (guint8 *)mini_add_method_trampoline (m, code, mono_method_needs_static_rgctx_invoke (m, FALSE), FALSE); } @@ -1407,6 +1454,7 @@ mono_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, M gpointer mono_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper) { + MonoError error; MonoJitInfo *ji; gpointer code; guint32 code_size = 0; @@ -1421,8 +1469,12 @@ mono_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean ad if (code && !ji->has_generic_jit_info && !(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) return code; - if (mono_llvm_only) - return mono_jit_compile_method (method); + if (mono_llvm_only) { + code = mono_jit_compile_method (method, &error); + if (!mono_error_ok (&error)) + mono_error_raise_exception (&error); + return code; + } mono_domain_lock (domain); code = g_hash_table_lookup (domain_jit_info (domain)->jump_trampoline_hash, method); @@ -1461,6 +1513,7 @@ method_not_found (void) gpointer mono_create_jit_trampoline_in_domain (MonoDomain *domain, MonoMethod *method) { + MonoError error; gpointer tramp; if (mono_aot_only) { @@ -1475,7 +1528,10 @@ mono_create_jit_trampoline_in_domain (MonoDomain *domain, MonoMethod *method) /* These wrappers are not generated */ return method_not_found; /* Methods are lazily initialized on first call, so this can't lead recursion */ - return mono_compile_method (method); + code = mono_jit_compile_method (method, &error); + if (!mono_error_ok (&error)) + mono_error_raise_exception (&error); + return code; } } diff --git a/mono/mini/mini.c b/mono/mini/mini.c index ba5577ef60a..c7306b08998 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -1208,7 +1208,7 @@ mini_assembly_can_skip_verification (MonoDomain *domain, MonoMethod *method) /* * mini_method_verify: * - * Verify the method using the new verfier. + * Verify the method using the verfier. * * Returns true if the method is invalid. */ @@ -1217,7 +1217,6 @@ mini_method_verify (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile) { GSList *tmp, *res; gboolean is_fulltrust; - MonoLoaderError *error; if (method->verification_success) return FALSE; @@ -1230,11 +1229,13 @@ mini_method_verify (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile) res = mono_method_verify_with_current_settings (method, cfg->skip_visibility, is_fulltrust); - if ((error = mono_loader_get_last_error ())) { - if (fail_compile) - cfg->exception_type = error->exception_type; - else + if (mono_loader_get_last_error ()) { + if (fail_compile) { + mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR); + mono_error_set_from_loader_error (&cfg->error); + } else { mono_loader_clear_error (); + } if (res) mono_free_verify_list (res); return TRUE; @@ -1256,16 +1257,20 @@ mini_method_verify (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile) if (info->info.status == MONO_VERIFY_NOT_VERIFIABLE && (!is_fulltrust || info->exception_type == MONO_EXCEPTION_METHOD_ACCESS || info->exception_type == MONO_EXCEPTION_FIELD_ACCESS)) { if (fail_compile) { char *method_name = mono_method_full_name (method, TRUE); - - if (info->exception_type == MONO_EXCEPTION_METHOD_ACCESS || info->exception_type == MONO_EXCEPTION_FIELD_ACCESS) { - if (info->exception_type == MONO_EXCEPTION_METHOD_ACCESS) - mono_error_set_generic_error (&cfg->error, "System", "MethodAccessException", "Error verifying %s: %s", method_name, info->info.message); - else - mono_error_set_generic_error (&cfg->error, "System", "FieldAccessException", "Error verifying %s: %s", method_name, info->info.message); - cfg->exception_type = MONO_EXCEPTION_MONO_ERROR; + char *msg = g_strdup_printf ("Error verifying %s: %s", method_name, info->info.message); + + if (info->exception_type == MONO_EXCEPTION_METHOD_ACCESS) + mono_error_set_generic_error (&cfg->error, "System", "MethodAccessException", "%s", msg); + else if (info->exception_type == info->exception_type == MONO_EXCEPTION_FIELD_ACCESS) + mono_error_set_generic_error (&cfg->error, "System", "FieldAccessException", "%s", msg); + else if (info->exception_type == MONO_EXCEPTION_UNVERIFIABLE_IL) + mono_error_set_generic_error (&cfg->error, "System.Security", "VerificationException", msg); + if (!mono_error_ok (&cfg->error)) { + mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR); + g_free (msg); } else { cfg->exception_type = info->exception_type; - cfg->exception_message = g_strdup_printf ("Error verifying %s: %s", method_name, info->info.message); + cfg->exception_message = msg; } g_free (method_name); } @@ -3481,10 +3486,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl header = cfg->header; if (!header) { - MonoLoaderError *error; - - if ((error = mono_loader_get_last_error ())) { - cfg->exception_type = error->exception_type; + if (mono_loader_get_last_error ()) { + mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR); + mono_error_set_from_loader_error (&cfg->error); } else { mono_cfg_set_exception_invalid_program (cfg, g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name)); } @@ -4186,7 +4190,7 @@ create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info) * Main entry point for the JIT. */ gpointer -mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoException **jit_ex) +mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoError *error) { MonoCompile *cfg; gpointer code = NULL; @@ -4197,6 +4201,8 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in GTimer *jit_timer; MonoMethod *prof_method, *shared; + mono_error_init (error); + if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) { MonoMethod *nm; @@ -4259,7 +4265,8 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in full_name = mono_method_full_name (method, TRUE); msg = g_strdup_printf ("Unrecognizable runtime implemented method '%s'", full_name); - *jit_ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", msg); + ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", msg); + mono_error_set_exception_instance (error, ex); g_free (full_name); g_free (msg); return NULL; @@ -4302,7 +4309,8 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in char *fullname = mono_method_full_name (method, TRUE); char *msg = g_strdup_printf ("Attempting to JIT compile method '%s' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.\n", fullname); - *jit_ex = mono_get_exception_execution_engine (msg); + ex = mono_get_exception_execution_engine (msg); + mono_error_set_exception_instance (error, ex); g_free (fullname); g_free (msg); @@ -4327,34 +4335,26 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in case MONO_EXCEPTION_FILE_NOT_FOUND: case MONO_EXCEPTION_BAD_IMAGE: { /* Throw a type load exception if needed */ - MonoLoaderError *error = mono_loader_get_last_error (); - - if (error) { - ex = mono_loader_error_prepare_exception (error); + if (cfg->exception_ptr) { + ex = mono_class_get_exception_for_failure ((MonoClass *)cfg->exception_ptr); } else { - if (cfg->exception_ptr) { - ex = mono_class_get_exception_for_failure ((MonoClass *)cfg->exception_ptr); - } else { - if (cfg->exception_type == MONO_EXCEPTION_MISSING_FIELD) - ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", cfg->exception_message); - else if (cfg->exception_type == MONO_EXCEPTION_MISSING_METHOD) - ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", cfg->exception_message); - else if (cfg->exception_type == MONO_EXCEPTION_TYPE_LOAD) - ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", cfg->exception_message); - else if (cfg->exception_type == MONO_EXCEPTION_FILE_NOT_FOUND) - ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.IO", "FileNotFoundException", cfg->exception_message); - else if (cfg->exception_type == MONO_EXCEPTION_BAD_IMAGE) - ex = mono_get_exception_bad_image_format (cfg->exception_message); - else - g_assert_not_reached (); - } + if (cfg->exception_type == MONO_EXCEPTION_MISSING_FIELD) + ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", cfg->exception_message); + else if (cfg->exception_type == MONO_EXCEPTION_MISSING_METHOD) + ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", cfg->exception_message); + else if (cfg->exception_type == MONO_EXCEPTION_TYPE_LOAD) + ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", cfg->exception_message); + else if (cfg->exception_type == MONO_EXCEPTION_FILE_NOT_FOUND) + ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.IO", "FileNotFoundException", cfg->exception_message); + else if (cfg->exception_type == MONO_EXCEPTION_BAD_IMAGE) + ex = mono_get_exception_bad_image_format (cfg->exception_message); + else + g_assert_not_reached (); } break; } - case MONO_EXCEPTION_UNVERIFIABLE_IL: - ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", cfg->exception_message); - break; case MONO_EXCEPTION_MONO_ERROR: + // FIXME: MonoError has no copy ctor g_assert (!mono_error_ok (&cfg->error)); ex = mono_error_convert_to_exception (&cfg->error); break; @@ -4367,7 +4367,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_FAILED); mono_destroy_compile (cfg); - *jit_ex = ex; + mono_error_set_exception_instance (error, ex); return NULL; } @@ -4464,7 +4464,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in if (!vtable) { ex = mono_class_get_exception_for_failure (method->klass); g_assert (ex); - *jit_ex = ex; + mono_error_set_exception_instance (error, ex); return NULL; } @@ -4484,7 +4484,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in ex = mono_runtime_class_init_full (vtable, FALSE); if (ex) { - *jit_ex = ex; + mono_error_set_exception_instance (error, ex); return NULL; } return code; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 592d2945d2f..db5c133266f 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2325,8 +2325,8 @@ MonoJumpInfo *mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJum gpointer mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors) MONO_LLVM_INTERNAL; gpointer mono_jit_find_compiled_method_with_jit_info (MonoDomain *domain, MonoMethod *method, MonoJitInfo **ji); gpointer mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method); -gpointer mono_jit_compile_method (MonoMethod *method); -gpointer mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoException **jit_ex); +gpointer mono_jit_compile_method (MonoMethod *method, MonoError *error); +gpointer mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoError *error); MonoLMF * mono_get_lmf (void); MonoLMF** mono_get_lmf_addr (void); void mono_set_lmf (MonoLMF *lmf); @@ -2913,10 +2913,10 @@ gboolean mono_class_generic_sharing_enabled (MonoClass *klass); gpointer -mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot); +mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot, MonoError *error); gpointer -mono_method_fill_runtime_generic_context (MonoMethodRuntimeGenericContext *mrgctx, guint32 slot); +mono_method_fill_runtime_generic_context (MonoMethodRuntimeGenericContext *mrgctx, guint32 slot, MonoError *error); MonoMethodRuntimeGenericContext* mono_method_lookup_rgctx (MonoVTable *class_vtable, MonoGenericInst *method_inst); diff --git a/mono/utils/mono-error-internals.h b/mono/utils/mono-error-internals.h index 926e76c9bbd..d16f9ef6602 100644 --- a/mono/utils/mono-error-internals.h +++ b/mono/utils/mono-error-internals.h @@ -40,7 +40,9 @@ typedef struct { #define is_ok(error) ((error)->error_code == MONO_ERROR_NONE) void -mono_error_assert_ok (MonoError *error); +mono_error_assert_ok_pos (MonoError *error, const char* filename, int lineno); + +#define mono_error_assert_ok(e) mono_error_assert_ok_pos (e, __FILE__, __LINE__); void mono_error_dup_strings (MonoError *error, gboolean dup_strings); diff --git a/mono/utils/mono-error.c b/mono/utils/mono-error.c index ca3350c5fd4..5673719059b 100644 --- a/mono/utils/mono-error.c +++ b/mono/utils/mono-error.c @@ -119,12 +119,12 @@ mono_error_ok (MonoError *error) } void -mono_error_assert_ok (MonoError *error) +mono_error_assert_ok_pos (MonoError *error, const char* filename, int lineno) { if (mono_error_ok (error)) return; - g_error ("%s\n", mono_error_get_message (error)); + g_error ("%s:%d: %s\n", filename, lineno, mono_error_get_message (error)); } unsigned short @@ -347,6 +347,7 @@ mono_error_set_exception_instance (MonoError *oerror, MonoException *exc) { MonoErrorInternal *error = (MonoErrorInternal*)oerror; + mono_error_prepare (error); error->error_code = MONO_ERROR_EXCEPTION_INSTANCE; error->exn.instance_handle = mono_gchandle_new (exc ? &exc->object : NULL, FALSE); } diff --git a/mono/utils/mono-publib.h b/mono/utils/mono-publib.h index c9becb2bf5e..30c80704399 100644 --- a/mono/utils/mono-publib.h +++ b/mono/utils/mono-publib.h @@ -73,6 +73,22 @@ MONO_API void mono_free (void *); #define MONO_CONST_RETURN const + +#if defined (MONO_INSIDE_RUNTIME) + +#if defined (__clang__) +#define MONO_RT_EXTERNAL_ONLY __attribute__ ((unavailable("The mono runtime must not call this function"))) +#elif defined (__GNUC__) +#define MONO_RT_EXTERNAL_ONLY __attribute__ ((error("The mono runtime must not call this function"))) +#else +#define MONO_RT_EXTERNAL_ONLY +#endif /* __clang__ */ + +#else +#define MONO_RT_EXTERNAL_ONLY +#endif /* MONO_INSIDE_RUNTIME */ + + MONO_END_DECLS #endif /* __MONO_PUBLIB_H__ */ |