Merge pull request #1857 from slluis/fix-assembly-resolver
[mono.git] / mcs / class / corlib / System / ValueType.cs
index 8bc186e73f92769ffd4e2b07b939711184ad7028..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]
-#if NET_2_0
        [ComVisible (true)]
-#endif
        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 ()
                {
                }
@@ -54,11 +70,18 @@ namespace System
                // 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;
+
+                       RuntimeType o1_type = (RuntimeType) o1.GetType ();
+                       RuntimeType o2_type = (RuntimeType) o2.GetType ();
 
-                       if (o2 == null)
+                       if (o1_type != o2_type)
                                return false;
 
+                       object[] fields;
                        bool res = InternalEquals (o1, o2, out fields);
                        if (fields == null)
                                return res;
@@ -109,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