Merge pull request #1857 from slluis/fix-assembly-resolver
[mono.git] / mcs / class / corlib / System / ValueType.cs
index 641d18013de2c7cca33efc5720bb73e1516cd8a2..2956ffb317c034e67c8d92aec692adaedf53afd2 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+// Files:
+//  - mscorlib/system/valuetype.cs
+//
+
 using System.Reflection;
 using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Threading;
 
 namespace System
 {
        [Serializable]
+       [ComVisible (true)]
        public abstract class ValueType
        {
+               /*
+                * Caution: Fields added to ValueType can mess with sub class layouts.
+                * Causing bugs that appear completely unrelated as #30060
+                */
+               private static class Internal
+               {
+                       public static int hash_code_of_ptr_seed = 0;
+               }
+
                protected ValueType ()
                {
                }
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               internal extern static bool InternalEquals (object o1, object o2, out object[] fields);
+               private extern static bool InternalEquals (object o1, object o2, out object[] fields);
 
                // This is also used by RuntimeHelpers
                internal static bool DefaultEquals (object o1, object o2)
                {
-                       object[] fields;
+                       if (o1 == null && o2 == null)
+                               return true;
+                       if (o1 == null || o2 == null)
+                               return false;
 
-                       if (o2 == null)
+                       RuntimeType o1_type = (RuntimeType) o1.GetType ();
+                       RuntimeType o2_type = (RuntimeType) o2.GetType ();
+
+                       if (o1_type != o2_type)
                                return false;
 
+                       object[] fields;
                        bool res = InternalEquals (o1, o2, out fields);
                        if (fields == null)
                                return res;
@@ -80,8 +107,9 @@ namespace System
                //   True if this instance and o represent the same type
                //   and have the same value.
                // </summary>
-               public override bool Equals (object o) {
-                       return DefaultEquals (this, o);
+               public override bool Equals (object obj)
+               {
+                       return DefaultEquals (this, obj);
                }
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
@@ -104,6 +132,23 @@ namespace System
                        return result;
                }
 
+               internal static int GetHashCodeOfPtr (IntPtr ptr)
+               {
+                       int hash_code = (int) ptr;
+                       int seed = Internal.hash_code_of_ptr_seed;
+
+                       if (seed == 0) {
+                               /* We use the first non-0 pointer as the seed, all hashcodes will be
+                                * based off that. This is to make sure that we only reveal relative
+                                * memory addresses and never absolute ones. */
+                               seed = hash_code;
+                               Interlocked.CompareExchange (ref Internal.hash_code_of_ptr_seed, seed, 0);
+                               seed = Internal.hash_code_of_ptr_seed;
+                       }
+
+                       return hash_code - seed;
+               }
+
                // <summary>
                //   Stringified representation of this ValueType.
                //   Must be overriden for better results, by default