From d80990a8ad016a6949ff015ab573bf52520d55b0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 14 Feb 2016 12:10:17 +1100 Subject: [PATCH 1/3] Reverting #513 Removal of code related to creation of hash/equals/compare that had been implemented in #513. --- src/fsharp/FSharp.Core/prim-types.fs | 1567 +++----------------------- 1 file changed, 148 insertions(+), 1419 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index bf1168b597d..69b6a46b636 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -905,10 +905,7 @@ namespace Microsoft.FSharp.Core let anyToStringShowingNull x = anyToString "null" x module HashCompare = - open System.Reflection - open System.Linq.Expressions - open System.Runtime.CompilerServices - + //------------------------------------------------------------------------- // LangaugePrimitives.HashCompare: Physical Equality //------------------------------------------------------------------------- @@ -952,20 +949,13 @@ namespace Microsoft.FSharp.Core /// This type has two instances - fsComparerER and fsComparerThrow. /// - fsComparerER = ER semantics = no throw on NaN comparison = new GenericComparer(false) = GenericComparer = GenericComparison /// - fsComparerPER = PER semantics = local throw on NaN comparison = new GenericComparer(true) = LessThan/GreaterThan etc. - type ComparerType = - | ER = 0 - | PER_lt = 1 - | PER_gt = 2 - - type GenericComparer(comparerType:ComparerType) = + type GenericComparer(throwsOnPER:bool) = interface System.Collections.IComparer - member c.ComparerType = comparerType + member c.ThrowsOnPER = throwsOnPER - let getPERNaNCompareToResult (comp:GenericComparer) = - match comp.ComparerType with - | ComparerType.PER_gt -> -2 - | ComparerType.PER_lt -> 2 - | _ -> raise (Exception "Invalid logic") + /// The unique exception object that is thrown locally when NaNs are compared in PER mode (by fsComparerPER) + /// This exception should never be observed by user code. + let NaNException = new System.Exception() /// Implements generic comparison between two objects. This corresponds to the pseudo-code in the F# /// specification. The treatment of NaNs is governed by "comp". @@ -990,21 +980,17 @@ namespace Microsoft.FSharp.Core | (:? IStructuralComparable as x),_ -> x.CompareTo(yobj,comp) // Check for IComparable - | (:? System.IComparable as x),_ -> - if comp.ComparerType.Equals ComparerType.ER then - x.CompareTo yobj - else - match xobj, yobj with - | (:? float as x), (:? float as y) -> - if System.Double.IsNaN x || System.Double.IsNaN y - then getPERNaNCompareToResult comp - else x.CompareTo y - | (:? float32 as x), (:? float32 as y) -> - if System.Single.IsNaN x || System.Single.IsNaN y - then getPERNaNCompareToResult comp - else x.CompareTo y - | _ -> x.CompareTo yobj - + | (:? System.IComparable as x),_ -> + if comp.ThrowsOnPER then + match xobj,yobj with + | (:? float as x),(:? float as y) -> + if (System.Double.IsNaN x || System.Double.IsNaN y) then + raise NaNException + | (:? float32 as x),(:? float32 as y) -> + if (System.Single.IsNaN x || System.Single.IsNaN y) then + raise NaNException + | _ -> () + x.CompareTo(yobj) | (:? nativeint as x),(:? nativeint as y) -> if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #) | (:? unativeint as x),(:? unativeint as y) -> if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #) | _,(:? IStructuralComparable as yc) -> @@ -1195,917 +1181,13 @@ namespace Microsoft.FSharp.Core type GenericComparer with interface System.Collections.IComparer with override c.Compare(x:obj,y:obj) = GenericCompare c (x,y) - + /// The unique object for comparing values in PER mode (where local exceptions are thrown when NaNs are compared) - let fsComparerPER_gt = GenericComparer ComparerType.PER_gt - let fsComparerPER_lt = GenericComparer ComparerType.PER_lt + let fsComparerPER = GenericComparer(true) /// The unique object for comparing values in ER mode (where "0" is returned when NaNs are compared) - let fsComparerER = GenericComparer ComparerType.ER :> System.Collections.IComparer - - // eliminate_tail_call_xxx are to elimate tail calls which are a problem with value types > 64 bits - // and the 64-bit JIT due to the amd64 calling convention which needs to do some magic. - let inline eliminate_tail_call_int x = 0 + x - let inline eliminate_tail_call_bool x = - // previously: not (not (x)) - // but found that the following also removes tail calls, although this could obviously - // change if the fsharp optimizer is changed... - match x with - | true -> true - | false -> false - - // Used to denote the use of a struct that is not initialized, because we are using them to - // denote pure functions that have no state - let phantom<'t> = unsafeDefault<'t> - - type IEssenceOfCompareTo<'a> = - abstract Ensorcel : IComparer * 'a * 'a -> int - - type IEssenceOfEquals<'a> = - abstract Ensorcel : IEqualityComparer * 'a * 'a -> bool - - type IEssenceOfGetHashCode<'a> = - abstract Ensorcel : IEqualityComparer * 'a -> int - - module ComparerTypes = - let getPERNaNResult (comp:IComparer) = - match comp with - | :? GenericComparer as comp -> getPERNaNCompareToResult comp - | _ -> raise (Exception "invalid logic") - - [] - type FloatPER = - interface IEssenceOfCompareTo with - member __.Ensorcel (c,x,y) = - if System.Double.IsNaN x || System.Double.IsNaN y - then getPERNaNResult c - else x.CompareTo y - - [] - type Float32PER = - interface IEssenceOfCompareTo with - member __.Ensorcel (c,x,y) = - if System.Single.IsNaN x || System.Single.IsNaN y - then getPERNaNResult c - else x.CompareTo y - - [] - type NullableFloatPER = - interface IEssenceOfCompareTo> with - member __.Ensorcel (c,x,y) = - match x.HasValue, y.HasValue with - | false, false -> 0 - | false, _ -> -1 - | _, false -> +1 - | _ -> - if System.Double.IsNaN x.Value || System.Double.IsNaN y.Value - then getPERNaNResult c - else x.Value.CompareTo y.Value - - [] - type NullableFloat32PER = - interface IEssenceOfCompareTo> with - member __.Ensorcel (c,x,y) = - match x.HasValue, y.HasValue with - | false, false -> 0 - | false, _ -> -1 - | _, false -> +1 - | _ -> - if System.Single.IsNaN x.Value || System.Single.IsNaN y.Value - then getPERNaNResult c - else x.Value.CompareTo y.Value - - [] - type FloatER = - interface IEssenceOfCompareTo with - member __.Ensorcel (_,x,y) = x.CompareTo y - - [] - type Float32ER = - interface IEssenceOfCompareTo with - member __.Ensorcel (_,x,y) = x.CompareTo y - - [] - type NullableFloatER = - interface IEssenceOfCompareTo> with - member __.Ensorcel (_,x,y) = - match x.HasValue, y.HasValue with - | false, false -> 0 - | false, _ -> -1 - | _, false -> +1 - | _ -> x.Value.CompareTo y.Value - - [] - type NullableFloat32ER = - interface IEssenceOfCompareTo> with - member __.Ensorcel (_,x,y) = - match x.HasValue, y.HasValue with - | false, false -> 0 - | false, _ -> -1 - | _, false -> +1 - | _ -> x.Value.CompareTo y.Value - - - [] type Bool = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #) - [] type Sbyte = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = (# "" x : int #) - (# "" y : int #) - [] type Int16 = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = (# "" x : int #) - (# "" y : int #) - [] type Int32 = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #) - [] type Int64 = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #) - [] type Nativeint = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #) - [] type Byte = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = (# "" x : int #) - (# "" y : int #) - [] type Uint16 = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = (# "" x : int #) - (# "" y : int #) - [] type Uint32 = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #) - [] type Uint64 = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #) - [] type Unativeint = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #) - [] type Char = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = (# "" x : int #) - (# "" y : int #) - [] type String = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = System.String.CompareOrdinal((# "" x : string #) ,(# "" y : string #)) - [] type Decimal = interface IEssenceOfCompareTo with member __.Ensorcel (_,x,y) = System.Decimal.Compare((# "" x:decimal #), (# "" y:decimal #)) - - [] - type Tuple<'a,'b, - 'comp1,'comp2 - when 'comp1 :> IEssenceOfCompareTo<'a> and 'comp1 : (new : unit -> 'comp1) and 'comp1 : struct - and 'comp2 :> IEssenceOfCompareTo<'b> and 'comp2 : (new : unit -> 'comp2) and 'comp2 : struct - > = - interface IEssenceOfCompareTo> with - member __.Ensorcel (comparer:IComparer, x:System.Tuple<'a,'b>, y:System.Tuple<'a,'b>) = - match x, y with - | null, null -> 0 - | null, _ -> -1 - | _, null -> +1 - | _, _ -> - match phantom<'comp1>.Ensorcel (comparer, x.Item1, y.Item1) with - | x when x <> 0 -> x - | _ -> - eliminate_tail_call_int (phantom<'comp2>.Ensorcel (comparer, x.Item2, y.Item2)) - - [] - type Tuple<'a,'b,'c, - 'comp1,'comp2,'comp3 - when 'comp1 :> IEssenceOfCompareTo<'a> and 'comp1 : (new : unit -> 'comp1) and 'comp1 : struct - and 'comp2 :> IEssenceOfCompareTo<'b> and 'comp2 : (new : unit -> 'comp2) and 'comp2 : struct - and 'comp3 :> IEssenceOfCompareTo<'c> and 'comp3 : (new : unit -> 'comp3) and 'comp3 : struct - > = - interface IEssenceOfCompareTo> with - member __.Ensorcel (comparer:IComparer, x:System.Tuple<'a,'b,'c>, y:System.Tuple<'a,'b,'c>) = - match x, y with - | null, null -> 0 - | null, _ -> -1 - | _, null -> +1 - | _, _ -> - match phantom<'comp1>.Ensorcel (comparer, x.Item1, y.Item1) with - | x when x <> 0 -> x - | _ -> - match phantom<'comp2>.Ensorcel (comparer, x.Item2, y.Item2) with - | x when x <> 0 -> x - | _ -> - eliminate_tail_call_int (phantom<'comp3>.Ensorcel (comparer, x.Item3, y.Item3)) - - - [] - type Tuple<'a,'b,'c,'d, - 'comp1,'comp2,'comp3,'comp4 - when 'comp1 :> IEssenceOfCompareTo<'a> and 'comp1 : (new : unit -> 'comp1) and 'comp1 : struct - and 'comp2 :> IEssenceOfCompareTo<'b> and 'comp2 : (new : unit -> 'comp2) and 'comp2 : struct - and 'comp3 :> IEssenceOfCompareTo<'c> and 'comp3 : (new : unit -> 'comp3) and 'comp3 : struct - and 'comp4 :> IEssenceOfCompareTo<'d> and 'comp4 : (new : unit -> 'comp4) and 'comp4 : struct - > = - interface IEssenceOfCompareTo> with - member __.Ensorcel (comparer:IComparer, x:System.Tuple<'a,'b,'c,'d>, y:System.Tuple<'a,'b,'c,'d>) = - match x, y with - | null, null -> 0 - | null, _ -> -1 - | _, null -> +1 - | _, _ -> - match phantom<'comp1>.Ensorcel (comparer, x.Item1, y.Item1) with - | x when x <> 0 -> x - | _ -> - match phantom<'comp2>.Ensorcel (comparer, x.Item2, y.Item2) with - | x when x <> 0 -> x - | _ -> - match phantom<'comp3>.Ensorcel (comparer, x.Item3, y.Item3) with - | x when x <> 0 -> x - | _ -> - eliminate_tail_call_int (phantom<'comp4>.Ensorcel (comparer, x.Item4, y.Item4)) - - [] - type Tuple<'a,'b,'c,'d,'e, - 'comp1,'comp2,'comp3,'comp4,'comp5 - when 'comp1 :> IEssenceOfCompareTo<'a> and 'comp1 : (new : unit -> 'comp1) and 'comp1 : struct - and 'comp2 :> IEssenceOfCompareTo<'b> and 'comp2 : (new : unit -> 'comp2) and 'comp2 : struct - and 'comp3 :> IEssenceOfCompareTo<'c> and 'comp3 : (new : unit -> 'comp3) and 'comp3 : struct - and 'comp4 :> IEssenceOfCompareTo<'d> and 'comp4 : (new : unit -> 'comp4) and 'comp4 : struct - and 'comp5 :> IEssenceOfCompareTo<'e> and 'comp5 : (new : unit -> 'comp5) and 'comp5 : struct - > = - interface IEssenceOfCompareTo> with - member __.Ensorcel (comparer:IComparer, x:System.Tuple<'a,'b,'c,'d,'e>, y:System.Tuple<'a,'b,'c,'d,'e>) = - match x, y with - | null, null -> 0 - | null, _ -> -1 - | _, null -> +1 - | _, _ -> - match phantom<'comp1>.Ensorcel (comparer, x.Item1, y.Item1) with - | x when x <> 0 -> x - | _ -> - match phantom<'comp2>.Ensorcel (comparer, x.Item2, y.Item2) with - | x when x <> 0 -> x - | _ -> - match phantom<'comp3>.Ensorcel (comparer, x.Item3, y.Item3) with - | x when x <> 0 -> x - | _ -> - match phantom<'comp4>.Ensorcel (comparer, x.Item4, y.Item4) with - | x when x <> 0 -> x - | _ -> - eliminate_tail_call_int (phantom<'comp5>.Ensorcel (comparer, x.Item5, y.Item5)) - - module Nullable = - [] - type StructuralComparable<'a when 'a : struct and 'a : (new : unit -> 'a) and 'a :> ValueType and 'a :> IStructuralComparable> = - interface IEssenceOfCompareTo> with - member __.Ensorcel (ec:IComparer, x:Nullable<'a>, y:Nullable<'a>) = - match x.HasValue, y.HasValue with - | false, false -> 0 - | false, _ -> -1 - | _, false -> +1 - | _, _ -> x.Value.CompareTo (box y.Value, ec) - - [] - type ComparableGeneric<'a when 'a : struct and 'a : (new : unit -> 'a) and 'a :> ValueType and 'a :> IComparable<'a>> = - interface IEssenceOfCompareTo> with - member __.Ensorcel (_:IComparer, x:Nullable<'a>, y:Nullable<'a>) = - match x.HasValue, y.HasValue with - | false, false -> 0 - | false, _ -> -1 - | _, false -> +1 - | _, _ -> x.Value.CompareTo y.Value - - [] - type Comparable<'a when 'a : struct and 'a : (new : unit -> 'a) and 'a :> ValueType and 'a :> IComparable> = - interface IEssenceOfCompareTo> with - member __.Ensorcel (_:IComparer, x:Nullable<'a>, y:Nullable<'a>) = - match x.HasValue, y.HasValue with - | false, false -> 0 - | false, _ -> -1 - | _, false -> +1 - | _, _ -> x.Value.CompareTo (box y.Value) - - module ValueType = - [] - type StructuralComparable<'a when 'a : struct and 'a :> IStructuralComparable> = - interface IEssenceOfCompareTo<'a> with - member __.Ensorcel (ec:IComparer, x:'a, y:'a) = - x.CompareTo (box y, ec) - - [] - type ComparableGeneric<'a when 'a : struct and 'a :> IComparable<'a>> = - interface IEssenceOfCompareTo<'a> with - member __.Ensorcel (_:IComparer, x:'a, y:'a) = - x.CompareTo y - - [] - type Comparable<'a when 'a : struct and 'a :> IComparable> = - interface IEssenceOfCompareTo<'a> with - member __.Ensorcel (_:IComparer, x:'a, y:'a) = - x.CompareTo y - - module RefType = - [] - type StructuralComparable<'a when 'a : not struct and 'a : null and 'a :> IStructuralComparable> = - interface IEssenceOfCompareTo<'a> with - member __.Ensorcel (ec:IComparer, x:'a, y:'a) = - match x, y with - | null, null -> 0 - | null, _ -> -1 - | _, null -> +1 - | _, _ -> x.CompareTo (box y, ec) - - [] - type ComparableGeneric<'a when 'a : not struct and 'a : null and 'a :> IComparable<'a>> = - interface IEssenceOfCompareTo<'a> with - member __.Ensorcel (_:IComparer, x:'a, y:'a) = - match x, y with - | null, null -> 0 - | null, _ -> -1 - | _, null -> +1 - | _, _ -> x.CompareTo y - - [] - type Comparable<'a when 'a : not struct and 'a : null and 'a :> IComparable> = - interface IEssenceOfCompareTo<'a> with - member __.Ensorcel (_:IComparer, x:'a, y:'a) = - match x, y with - | null, null -> 0 - | null, _ -> -1 - | _, null -> +1 - | _, _ -> x.CompareTo y - - module EqualsTypes = - [] - type FloatPER = - interface IEssenceOfEquals - with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - - [] - type Float32PER = - interface IEssenceOfEquals with - member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - - [] - type NullableFloatPER = - interface IEssenceOfEquals> with - member __.Ensorcel (_,x,y) = - match x.HasValue, y.HasValue with - | false, false -> true - | false, _ - | _, false -> false - | _ -> (# "ceq" x.Value y.Value : bool #) - - [] - type NullableFloat32PER = - interface IEssenceOfEquals> with - member __.Ensorcel (_,x,y) = - match x.HasValue, y.HasValue with - | false, false -> true - | false, _ - | _, false -> false - | _ -> (# "ceq" x.Value y.Value : bool #) - - [] - type FloatER = - interface IEssenceOfEquals - with member __.Ensorcel (_,x,y) = if not (# "ceq" x x : bool #) && not (# "ceq" y y : bool #) then true else (# "ceq" x y : bool #) - - [] - type Float32ER = - interface IEssenceOfEquals with - member __.Ensorcel (_,x,y) = if not (# "ceq" x x : bool #) && not (# "ceq" y y : bool #) then true else (# "ceq" x y : bool #) - - [] - type NullableFloatER = - interface IEssenceOfEquals> with - member __.Ensorcel (_,x,y) = - match x.HasValue, y.HasValue with - | false, false -> true - | false, _ - | _, false -> false - | _ -> if not (# "ceq" x.Value x.Value : bool #) && not (# "ceq" y.Value y.Value : bool #) then true else (# "ceq" x.Value y.Value : bool #) - - [] - type NullableFloat32ER = - interface IEssenceOfEquals> with - member __.Ensorcel (_,x,y) = - match x.HasValue, y.HasValue with - | false, false -> true - | false, _ - | _, false -> false - | _ -> if not (# "ceq" x.Value x.Value : bool #) && not (# "ceq" y.Value y.Value : bool #) then true else (# "ceq" x.Value y.Value : bool #) - - [] type Bool = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Sbyte = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Int16 = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Int32 = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Int64 = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Byte = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Uint16 = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Uint32 = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Uint64 = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Nativeint = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Unativeint = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type Char = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = (# "ceq" x y : bool #) - [] type String = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = System.String.Equals((# "" x : string #),(# "" y : string #)) - [] type Decimal = interface IEssenceOfEquals with member __.Ensorcel (_,x,y) = System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) - - [] - type Tuple<'a,'b, - 'eq1,'eq2 - when 'eq1 :> IEssenceOfEquals<'a> and 'eq1 : (new : unit -> 'eq1) and 'eq1 : struct - and 'eq2 :> IEssenceOfEquals<'b> and 'eq2 : (new : unit -> 'eq2) and 'eq2 : struct - > = - interface IEssenceOfEquals> with - member __.Ensorcel (ec:IEqualityComparer, x:System.Tuple<'a,'b>, y:System.Tuple<'a,'b>) = - match x, y with - | null, null -> true - | null, _ | _, null -> false - | _, _ -> - match phantom<'eq1>.Ensorcel (ec, x.Item1, y.Item1) with - | false -> false - | _ -> - phantom<'eq2>.Ensorcel (ec, x.Item2, y.Item2) - - [] - type Tuple<'a,'b,'c, - 'eq1,'eq2,'eq3 - when 'eq1 :> IEssenceOfEquals<'a> and 'eq1 : (new : unit -> 'eq1) and 'eq1 : struct - and 'eq2 :> IEssenceOfEquals<'b> and 'eq2 : (new : unit -> 'eq2) and 'eq2 : struct - and 'eq3 :> IEssenceOfEquals<'c> and 'eq3 : (new : unit -> 'eq3) and 'eq3 : struct - > = - interface IEssenceOfEquals> with - member __.Ensorcel (ec:IEqualityComparer, x:System.Tuple<'a,'b,'c>, y:System.Tuple<'a,'b,'c>) = - match x, y with - | null, null -> true - | null, _ | _, null -> false - | _, _ -> - match phantom<'eq1>.Ensorcel (ec, x.Item1, y.Item1) with - | false -> false - | _ -> - match phantom<'eq2>.Ensorcel (ec, x.Item2, y.Item2) with - | false -> false - | _ -> - phantom<'eq3>.Ensorcel (ec, x.Item3, y.Item3) - - [] - type Tuple<'a,'b,'c,'d, - 'eq1,'eq2,'eq3,'eq4 - when 'eq1 :> IEssenceOfEquals<'a> and 'eq1 : (new : unit -> 'eq1) and 'eq1 : struct - and 'eq2 :> IEssenceOfEquals<'b> and 'eq2 : (new : unit -> 'eq2) and 'eq2 : struct - and 'eq3 :> IEssenceOfEquals<'c> and 'eq3 : (new : unit -> 'eq3) and 'eq3 : struct - and 'eq4 :> IEssenceOfEquals<'d> and 'eq4 : (new : unit -> 'eq4) and 'eq4 : struct - > = - interface IEssenceOfEquals> with - member __.Ensorcel (ec:IEqualityComparer, x:System.Tuple<'a,'b,'c,'d>, y:System.Tuple<'a,'b,'c,'d>) = - match x, y with - | null, null -> true - | null, _ | _, null -> false - | _, _ -> - match phantom<'eq1>.Ensorcel (ec, x.Item1, y.Item1) with - | false -> false - | _ -> - match phantom<'eq2>.Ensorcel (ec, x.Item2, y.Item2) with - | false -> false - | _ -> - match phantom<'eq3>.Ensorcel (ec, x.Item3, y.Item3) with - | false -> false - | _ -> - phantom<'eq4>.Ensorcel (ec, x.Item4, y.Item4) - - [] - type Tuple<'a,'b,'c,'d,'e, - 'eq1,'eq2,'eq3,'eq4,'eq5 - when 'eq1 :> IEssenceOfEquals<'a> and 'eq1 : (new : unit -> 'eq1) and 'eq1 : struct - and 'eq2 :> IEssenceOfEquals<'b> and 'eq2 : (new : unit -> 'eq2) and 'eq2 : struct - and 'eq3 :> IEssenceOfEquals<'c> and 'eq3 : (new : unit -> 'eq3) and 'eq3 : struct - and 'eq4 :> IEssenceOfEquals<'d> and 'eq4 : (new : unit -> 'eq4) and 'eq4 : struct - and 'eq5 :> IEssenceOfEquals<'e> and 'eq5 : (new : unit -> 'eq5) and 'eq5 : struct - > = - interface IEssenceOfEquals> with - member __.Ensorcel (ec:IEqualityComparer, x:System.Tuple<'a,'b,'c,'d,'e>, y:System.Tuple<'a,'b,'c,'d,'e>) = - match x, y with - | null, null -> true - | null, _ | _, null -> false - | _, _ -> - match phantom<'eq1>.Ensorcel (ec, x.Item1, y.Item1) with - | false -> false - | _ -> - match phantom<'eq2>.Ensorcel (ec, x.Item2, y.Item2) with - | false -> false - | _ -> - match phantom<'eq3>.Ensorcel (ec, x.Item3, y.Item3) with - | false -> false - | _ -> - match phantom<'eq4>.Ensorcel (ec, x.Item4, y.Item4) with - | false -> false - | _ -> - phantom<'eq5>.Ensorcel (ec, x.Item5, y.Item5) - - module GetHashCodeTypes = - [] type Bool = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Float = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Sbyte = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Int16 = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Int32 = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Int64 = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Byte = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Uint16 = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Uint32 = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Uint64 = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Nativeint = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Unativeint = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Char = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type String = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Decimal = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - [] type Float32 = interface IEssenceOfGetHashCode with member __.Ensorcel (_,a) = a.GetHashCode() - -(* - let inline mask (n:int) (m:int) = (# "and" n m : int #) - let inline opshl (x:int) (n:int) : int = (# "shl" x (mask n 31) : int #) - let inline opshr (x:int) (n:int) : int = (# "shr" x (mask n 31) : int #) - let inline opxor (x:int) (y:int) : int = (# "xor" x y : int32 #) - let inline combineTupleHashes (h1 : int) (h2 : int) = -1640531527 + (h2 + (opshl h1 6) + (opshr h1 2)) -*) - let inline cth a b = TupleUtils.combineTupleHashes a b - - [] - type Tuple<'a,'b, - 'ghc1,'ghc2 - when 'ghc1 :> IEssenceOfGetHashCode<'a> and 'ghc1 : (new : unit -> 'ghc1) and 'ghc1 : struct - and 'ghc2 :> IEssenceOfGetHashCode<'b> and 'ghc2 : (new : unit -> 'ghc2) and 'ghc2 : struct - > = - interface IEssenceOfGetHashCode> with - member __.Ensorcel (iec:IEqualityComparer, x:System.Tuple<'a,'b>) = - let a = phantom<'ghc1>.Ensorcel (iec, x.Item1) - let b = phantom<'ghc2>.Ensorcel (iec, x.Item2) - eliminate_tail_call_int (cth a b) - - [] - type Tuple<'a,'b,'c, - 'ghc1,'ghc2,'ghc3 - when 'ghc1 :> IEssenceOfGetHashCode<'a> and 'ghc1 : (new : unit -> 'ghc1) and 'ghc1 : struct - and 'ghc2 :> IEssenceOfGetHashCode<'b> and 'ghc2 : (new : unit -> 'ghc2) and 'ghc2 : struct - and 'ghc3 :> IEssenceOfGetHashCode<'c> and 'ghc3 : (new : unit -> 'ghc3) and 'ghc3 : struct - > = - interface IEssenceOfGetHashCode> with - member __.Ensorcel (iec:IEqualityComparer, x:System.Tuple<'a,'b,'c>) = - let a = phantom<'ghc1>.Ensorcel (iec, x.Item1) - let b = phantom<'ghc2>.Ensorcel (iec, x.Item2) - let c = phantom<'ghc3>.Ensorcel (iec, x.Item3) - eliminate_tail_call_int (cth (cth a b) c) - - [] - type Tuple<'a,'b,'c,'d, - 'ghc1,'ghc2,'ghc3,'ghc4 - when 'ghc1 :> IEssenceOfGetHashCode<'a> and 'ghc1 : (new : unit -> 'ghc1) and 'ghc1 : struct - and 'ghc2 :> IEssenceOfGetHashCode<'b> and 'ghc2 : (new : unit -> 'ghc2) and 'ghc2 : struct - and 'ghc3 :> IEssenceOfGetHashCode<'c> and 'ghc3 : (new : unit -> 'ghc3) and 'ghc3 : struct - and 'ghc4 :> IEssenceOfGetHashCode<'d> and 'ghc4 : (new : unit -> 'ghc4) and 'ghc4 : struct - > = - interface IEssenceOfGetHashCode> with - member __.Ensorcel (iec:IEqualityComparer, x:System.Tuple<'a,'b,'c,'d>) = - let a = phantom<'ghc1>.Ensorcel (iec, x.Item1) - let b = phantom<'ghc2>.Ensorcel (iec, x.Item2) - let c = phantom<'ghc3>.Ensorcel (iec, x.Item3) - let d = phantom<'ghc4>.Ensorcel (iec, x.Item4) - eliminate_tail_call_int (cth (cth a b) (cth c d)) - - [] - type Tuple<'a,'b,'c,'d,'e, - 'ghc1,'ghc2,'ghc3,'ghc4,'ghc5 - when 'ghc1 :> IEssenceOfGetHashCode<'a> and 'ghc1 : (new : unit -> 'ghc1) and 'ghc1 : struct - and 'ghc2 :> IEssenceOfGetHashCode<'b> and 'ghc2 : (new : unit -> 'ghc2) and 'ghc2 : struct - and 'ghc3 :> IEssenceOfGetHashCode<'c> and 'ghc3 : (new : unit -> 'ghc3) and 'ghc3 : struct - and 'ghc4 :> IEssenceOfGetHashCode<'d> and 'ghc4 : (new : unit -> 'ghc4) and 'ghc4 : struct - and 'ghc5 :> IEssenceOfGetHashCode<'e> and 'ghc5 : (new : unit -> 'ghc5) and 'ghc5 : struct - > = - interface IEssenceOfGetHashCode> with - member __.Ensorcel (iec:IEqualityComparer, x:System.Tuple<'a,'b,'c,'d,'e>) = - let a = phantom<'ghc1>.Ensorcel (iec, x.Item1) - let b = phantom<'ghc2>.Ensorcel (iec, x.Item2) - let c = phantom<'ghc3>.Ensorcel (iec, x.Item3) - let d = phantom<'ghc4>.Ensorcel (iec, x.Item4) - let e = phantom<'ghc5>.Ensorcel (iec, x.Item5) - eliminate_tail_call_int (cth (cth (cth a b) (cth c d)) e) - - module CommonEqualityTypes = - module Nullable = - [] - type StructuralEquatable<'a when 'a : struct and 'a : (new : unit -> 'a) and 'a :> ValueType and 'a :> IStructuralEquatable> = - interface IEssenceOfEquals> with - member __.Ensorcel (ec:IEqualityComparer, x:Nullable<'a>, y:Nullable<'a>) = - match x.HasValue, y.HasValue with - | false, false -> true - | false, _ | _, false -> false - | _, _ -> x.Value.Equals (box y.Value, ec) - - interface IEssenceOfGetHashCode> with - member __.Ensorcel (ec:IEqualityComparer, x:Nullable<'a>) = - if x.HasValue then x.Value.GetHashCode (ec) - else 0 - - [] - type Equatable<'a when 'a : struct and 'a : (new : unit -> 'a) and 'a :> ValueType and 'a :> IEquatable<'a>> = - interface IEssenceOfEquals> with - member __.Ensorcel (_:IEqualityComparer, x:Nullable<'a>, y:Nullable<'a>) = - match x.HasValue, y.HasValue with - | false, false -> true - | false, _ | _, false -> false - | _, _ -> x.Value.Equals y.Value - - [] - type Equality<'a when 'a : struct and 'a : (new : unit -> 'a) and 'a :> ValueType and 'a : equality> = - interface IEssenceOfEquals> with - member __.Ensorcel (_:IEqualityComparer, x:Nullable<'a>, y:Nullable<'a>) = - match x.HasValue, y.HasValue with - | false, false -> true - | false, _ | _, false -> false - | _, _ -> x.Value.Equals y.Value - - interface IEssenceOfGetHashCode> with - member __.Ensorcel (_:IEqualityComparer, x:Nullable<'a>) = - if x.HasValue then x.Value.GetHashCode () - else 0 - - module ValueType = - [] - type StructuralEquatable<'a when 'a : struct and 'a :> IStructuralEquatable> = - interface IEssenceOfEquals<'a> with - member __.Ensorcel (ec:IEqualityComparer, x:'a, y:'a) = - x.Equals (box y, ec) - interface IEssenceOfGetHashCode<'a> with - member __.Ensorcel (ec:IEqualityComparer, x:'a) = - x.GetHashCode (ec) - - [] - type Equatable<'a when 'a : struct and 'a :> IEquatable<'a>> = - interface IEssenceOfEquals<'a> with - member __.Ensorcel (_:IEqualityComparer, x:'a, y:'a) = - x.Equals y - - [] - type Equality<'a when 'a : struct and 'a : equality> = - interface IEssenceOfEquals<'a> with - member __.Ensorcel (_:IEqualityComparer, x:'a, y:'a) = - x.Equals y - interface IEssenceOfGetHashCode<'a> with - member __.Ensorcel (_:IEqualityComparer, x:'a) = - x.GetHashCode () - - module RefType = - [] - type StructuralEquatable<'a when 'a : not struct and 'a : null and 'a :> IStructuralEquatable> = - interface IEssenceOfEquals<'a> with - member __.Ensorcel (ec:IEqualityComparer, x:'a, y:'a) = - match x, y with - | null, null -> true - | null, _ | _, null -> false - | _, _ -> x.Equals (box y, ec) - - interface IEssenceOfGetHashCode<'a> with - member __.Ensorcel (ec:IEqualityComparer, x:'a) = - match x with - | null -> 0 - | _ -> x.GetHashCode (ec) - - [] - type Equatable<'a when 'a : not struct and 'a : null and 'a :> IEquatable<'a>> = - interface IEssenceOfEquals<'a> with - member __.Ensorcel (_:IEqualityComparer, x:'a, y:'a) = - match x, y with - | null, null -> true - | null, _ | _, null -> false - | _, _ -> x.Equals y - - [] - type Equality<'a when 'a : not struct and 'a : null and 'a : equality> = - interface IEssenceOfEquals<'a> with - member __.Ensorcel (_:IEqualityComparer, x:'a, y:'a) = - match x, y with - | null, null -> true - | null, _ | _, null -> false - | _, _ -> x.Equals y - - interface IEssenceOfGetHashCode<'a> with - member __.Ensorcel (_:IEqualityComparer, x:'a) = - match x with - | null -> 0 - | _ -> x.GetHashCode () - - let doNotEat () = raise (Exception "not for consumption! this type only exist for getting typedef.") - [] - type DummyValueType = - interface IStructuralComparable with member __.CompareTo (_,_) = doNotEat () - interface IStructuralEquatable with member __.Equals (_,_) = doNotEat () - member __.GetHashCode _ = doNotEat () - - type private EquivalenceRelation = class end - type private PartialEquivalenceRelation = class end - - module mos = - type IGetType = - abstract Get : unit -> Type - - let makeType (ct:Type) (def:Type) : Type = - def.MakeGenericType [|ct|] - - let makeGenericType<'a> tys = - let typedef = typedefof<'a> - typedef.MakeGenericType tys - - let makeEquatableType ty = - makeGenericType> [|ty|] - - let makeComparableType ty = - makeGenericType> [|ty|] - -// portable47 doesn't support reflection in the way I'm using it; maybe someone with greater understanding -// of the configurations could provide a real solution -#if FX_ATLEAST_40 - let rec private tryFindObjectsInterfaceMethod (objectType:Type) (interfaceType:Type) (methodName:string) (methodArgTypes:array) = - if not (interfaceType.IsAssignableFrom objectType) then null - else - let methodInfo = interfaceType.GetMethod (methodName, methodArgTypes) - let interfaceMap = objectType.GetInterfaceMap interfaceType - let rec findTargetMethod index = - if index = interfaceMap.InterfaceMethods.Length then null - elif methodInfo.Equals (get interfaceMap.InterfaceMethods index) then (get interfaceMap.TargetMethods index) - else findTargetMethod (index+1) - findTargetMethod 0 - - let rec private isCompilerGeneratedInterfaceMethod objectType interfaceType methodName methodArgTypes = - match tryFindObjectsInterfaceMethod objectType interfaceType methodName methodArgTypes with - | null -> false - | m -> - match m.GetCustomAttribute typeof with - | null -> false - | _ -> true - - let rec private isCompilerGeneratedMethod (objectType:Type) (methodName:string) (methodArgTypes:array) = - match objectType.GetMethod (methodName, methodArgTypes) with - | null -> false - | m -> - match m.GetCustomAttribute typeof with - | null -> false - | _ -> true - - let hasFSharpCompilerGeneratedEquality (ty:Type) = - match ty.GetCustomAttribute typeof with - | :? CompilationMappingAttribute as m when (m.SourceConstructFlags.Equals SourceConstructFlags.ObjectType(*struct*)) || (m.SourceConstructFlags.Equals SourceConstructFlags.RecordType) -> - isCompilerGeneratedInterfaceMethod ty (makeEquatableType ty) "Equals" [|ty|] - && isCompilerGeneratedInterfaceMethod ty typeof "Equals" [|typeof; typeof|] - && isCompilerGeneratedMethod ty "Equals" [|typeof|] - | _ -> false - - let hasFSharpCompilerGeneratedComparison (ty:Type) = - match ty.GetCustomAttribute typeof with - | :? CompilationMappingAttribute as m when (m.SourceConstructFlags.Equals SourceConstructFlags.ObjectType(*struct*)) || (m.SourceConstructFlags.Equals SourceConstructFlags.RecordType) -> - isCompilerGeneratedInterfaceMethod ty (makeComparableType ty) "CompareTo" [|ty|] - && isCompilerGeneratedInterfaceMethod ty typeof "CompareTo" [|typeof; typeof|] - && isCompilerGeneratedInterfaceMethod ty typeof "CompareTo" [|typeof|] - | _ -> false -#else - let hasFSharpCompilerGeneratedEquality (_:Type) = false - let hasFSharpCompilerGeneratedComparison (_:Type) = false -#endif - - let takeFirstNonNull items = - let rec takeFirst idx = - if idx = length items then raise (Exception "invalid logic") - else - let f = get items idx - match f () with - | null -> takeFirst (idx+1) - | result -> result - takeFirst 0 - - let compositeType (getEssence:Type->Type) (args:Type[]) (genericCompositeEssenceType:Type) = - let compositeArgs : Type[] = unboxPrim (Array.CreateInstance (typeof, args.Length*2)) - for i = 0 to args.Length-1 do - let argType = get args i - let essenceType = getEssence argType - compositeArgs.SetValue (argType, i) - compositeArgs.SetValue (essenceType, i+args.Length) - genericCompositeEssenceType.MakeGenericType compositeArgs - - module GenericSpecializeCompareTo = - let floatingPointTypes (tyRelation:Type) (ty:Type) = - match tyRelation with - | r when r.Equals typeof -> - match ty with - | t when t.Equals typeof -> typeof - | t when t.Equals typeof -> typeof - | t when t.Equals typeof> -> typeof - | t when t.Equals typeof> -> typeof - | _ -> null - | r when r.Equals typeof -> - match ty with - | t when t.Equals typeof -> typeof - | t when t.Equals typeof -> typeof - | t when t.Equals typeof> -> typeof - | t when t.Equals typeof> -> typeof - | _ -> null - | _ -> raise (Exception "invalid logic") - - let standardTypes (t:Type) : Type = - if t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - else null - - let compilerGenerated tyRelation ty = - match tyRelation with - | r when r.Equals typeof -> - if mos.hasFSharpCompilerGeneratedComparison ty then - if ty.IsValueType - then mos.makeType ty typedefof> - else mos.makeType ty typedefof> - else null - | r when r.Equals typeof -> null - | _ -> raise (Exception "invalid logic") - - [] - type GenericComparerObj<'a> = - interface IEssenceOfCompareTo<'a> with - member __.Ensorcel (comp:IComparer, x:'a, y:'a) = comp.Compare (box x, box y) - - let arrays (t:Type) : Type = - if t.IsArray || typeof.IsAssignableFrom t then - // TODO: Future; for now just default back to previous functionality - mos.makeType t typedefof> - else null - - let nullableType (t:Type) : Type = - if t.IsGenericType && ((t.GetGenericTypeDefinition ()).Equals typedefof>) then - let underlying = get (t.GetGenericArguments()) 0 - let comparableGeneric = mos.makeComparableType underlying - let make = mos.makeType underlying - - if typeof.IsAssignableFrom underlying then make typedefof> - elif comparableGeneric.IsAssignableFrom underlying then make typedefof> - else make typedefof> - else null - - let comparisonInterfaces (t:Type) : Type = - let make = mos.makeType t - let comparableGeneric = mos.makeComparableType t - - if t.IsValueType && typeof.IsAssignableFrom t then make typedefof> - elif t.IsValueType && comparableGeneric.IsAssignableFrom t then make typedefof> - elif t.IsValueType && typeof.IsAssignableFrom t then make typedefof> - - elif typeof.IsAssignableFrom t then make typedefof>> - - // only sealed as a derived class might inherit from IStructuralComparable - elif t.IsSealed && comparableGeneric.IsAssignableFrom t then make typedefof> - elif t.IsSealed && typeof.IsAssignableFrom t then make typedefof> - - else null - - let defaultCompare ty = - mos.makeType ty typedefof> - - let getCompareEssenceType (tyRelation:Type) (ty:Type) tuples : Type = - mos.takeFirstNonNull [| - fun () -> tuples tyRelation ty - fun () -> floatingPointTypes tyRelation ty - fun () -> standardTypes ty - fun () -> compilerGenerated tyRelation ty - fun () -> arrays ty - fun () -> nullableType ty - fun () -> comparisonInterfaces ty - fun () -> defaultCompare ty - |] - - [] - type ComparerInvoker<'a>() = - class - abstract Invoke : IComparer * 'a * 'a -> int - end - - [] - type EssenceOfCompareWrapper<'a, 'comp - when 'comp :> IEssenceOfCompareTo<'a> and 'comp : (new : unit -> 'comp) and 'comp : struct>() = - inherit ComparerInvoker<'a>() - - override __.Invoke (comp, x:'a, y:'a) = - phantom<'comp>.Ensorcel (comp, x, y) - - let makeComparerInvoker (ty:Type) comp = - let wrapperTypeDef = typedefof> - let wrapperType = wrapperTypeDef.MakeGenericType [| ty; comp |] - Activator.CreateInstance wrapperType - - type t = ComparerTypes.Int32 - type Function<'relation, 'a>() = - static let essenceType : Type = - getCompareEssenceType typeof<'relation> typeof<'a> Helpers.tuplesCompareTo - - static let invoker : ComparerInvoker<'a> = - unboxPrim (makeComparerInvoker typeof<'a> essenceType) - - static member Invoker = invoker - - interface mos.IGetType with - member __.Get () = essenceType - and Helpers = - static member getEssenceOfCompareToType (tyRelation:Type) (ty:Type) = - let compareTo = mos.makeGenericType> [|tyRelation; ty|] - match Activator.CreateInstance compareTo with - | :? mos.IGetType as getter -> getter.Get () - | _ -> raise (Exception "invalid logic") - - static member tuplesCompareTo (tyRelation:Type) (ty:Type) : Type = - if ty.IsGenericType then - let tyDef = ty.GetGenericTypeDefinition () - let tyDefArgs = ty.GetGenericArguments () - let create = mos.compositeType (Helpers.getEssenceOfCompareToType tyRelation) tyDefArgs - if tyDef.Equals typedefof> then create typedefof> - elif tyDef.Equals typedefof> then create typedefof> - elif tyDef.Equals typedefof> then create typedefof> - elif tyDef.Equals typedefof> then create typedefof> - else null - else null - - let inline GenericComparisonForInequality comp x y = - GenericSpecializeCompareTo.Function.Invoker.Invoke (comp, x, y) + let fsComparerER = GenericComparer(false) + /// Compare two values of the same generic type, using "comp". // // "comp" is assumed to be either fsComparerPER or fsComparerER (and hence 'Compare' is implemented via 'GenericCompare'). @@ -2113,44 +1195,7 @@ namespace Microsoft.FSharp.Core // NOTE: the compiler optimizer is aware of this function and devirtualizes in the // cases where it is known how a particular type implements generic comparison. let GenericComparisonWithComparerIntrinsic<'T> (comp:System.Collections.IComparer) (x:'T) (y:'T) : int = - match comp with - | :? GenericComparer as info -> - match info.ComparerType with - | ComparerType.ER -> eliminate_tail_call_int (GenericSpecializeCompareTo.Function.Invoker.Invoke (comp, x, y)) - | ComparerType.PER_gt - | ComparerType.PER_lt -> eliminate_tail_call_int (GenericComparisonForInequality comp x y) - | _ -> raise (Exception "invalid logic") - | c when obj.ReferenceEquals (c, Comparer<'T>.Default) -> - eliminate_tail_call_int (Comparer<'T>.Default.Compare (x, y)) - | _ -> - eliminate_tail_call_int (comp.Compare (box x, box y)) - - /// Generic comparison. Implements ER mode (where "0" is returned when NaNs are compared) - // - // The compiler optimizer is aware of this function (see use of generic_comparison_inner_vref in opt.fs) - // and devirtualizes calls to it based on "T". - let GenericComparisonIntrinsic<'T> (x:'T) (y:'T) : int = - eliminate_tail_call_int (GenericSpecializeCompareTo.Function.Invoker.Invoke (fsComparerER, x, y)) - - /// Generic less-than. Uses comparison implementation in PER mode but catches - /// the local exception that is thrown when NaN's are compared. - let GenericLessThanIntrinsic (x:'T) (y:'T) = - (# "clt" (GenericComparisonForInequality fsComparerPER_lt x y) 0 : bool #) - - /// Generic greater-than. Uses comparison implementation in PER mode but catches - /// the local exception that is thrown when NaN's are compared. - let GenericGreaterThanIntrinsic (x:'T) (y:'T) = - (# "cgt" (GenericComparisonForInequality fsComparerPER_gt x y) 0 : bool #) - - /// Generic greater-than-or-equal. Uses comparison implementation in PER mode but catches - /// the local exception that is thrown when NaN's are compared. - let GenericGreaterOrEqualIntrinsic (x:'T) (y:'T) = - (# "cgt" (GenericComparisonForInequality fsComparerPER_gt x y) (-1) : bool #) - - /// Generic less-than-or-equal. Uses comparison implementation in PER mode but catches - /// the local exception that is thrown when NaN's are compared. - let GenericLessOrEqualIntrinsic (x:'T) (y:'T) = - (# "clt" (GenericComparisonForInequality fsComparerPER_lt x y) 1 : bool #) + comp.Compare(box x, box y) /// Compare two values of the same generic type, in either PER or ER mode, but include static optimizations /// for various well-known cases. @@ -2187,6 +1232,49 @@ namespace Microsoft.FSharp.Core when 'T : decimal = System.Decimal.Compare((# "" x:decimal #), (# "" y:decimal #)) + /// Generic comparison. Implements ER mode (where "0" is returned when NaNs are compared) + // + // The compiler optimizer is aware of this function (see use of generic_comparison_inner_vref in opt.fs) + // and devirtualizes calls to it based on "T". + let GenericComparisonIntrinsic<'T> (x:'T) (y:'T) : int = + GenericComparisonWithComparerIntrinsic (fsComparerER :> IComparer) x y + + + /// Generic less-than. Uses comparison implementation in PER mode but catches + /// the local exception that is thrown when NaN's are compared. + let GenericLessThanIntrinsic (x:'T) (y:'T) = + try + (# "clt" (GenericComparisonWithComparerIntrinsic fsComparerPER x y) 0 : bool #) + with + | e when System.Runtime.CompilerServices.RuntimeHelpers.Equals(e, NaNException) -> false + + + /// Generic greater-than. Uses comparison implementation in PER mode but catches + /// the local exception that is thrown when NaN's are compared. + let GenericGreaterThanIntrinsic (x:'T) (y:'T) = + try + (# "cgt" (GenericComparisonWithComparerIntrinsic fsComparerPER x y) 0 : bool #) + with + | e when System.Runtime.CompilerServices.RuntimeHelpers.Equals(e, NaNException) -> false + + + /// Generic greater-than-or-equal. Uses comparison implementation in PER mode but catches + /// the local exception that is thrown when NaN's are compared. + let GenericGreaterOrEqualIntrinsic (x:'T) (y:'T) = + try + (# "cgt" (GenericComparisonWithComparerIntrinsic fsComparerPER x y) (-1) : bool #) + with + | e when System.Runtime.CompilerServices.RuntimeHelpers.Equals(e, NaNException) -> false + + + + /// Generic less-than-or-equal. Uses comparison implementation in PER mode but catches + /// the local exception that is thrown when NaN's are compared. + let GenericLessOrEqualIntrinsic (x:'T) (y:'T) = + try + (# "clt" (GenericComparisonWithComparerIntrinsic fsComparerPER x y) 1 : bool #) + with + | e when System.Runtime.CompilerServices.RuntimeHelpers.Equals(e, NaNException) -> false /// Compare two values of the same generic type, in ER mode, with static optimizations @@ -2567,203 +1655,28 @@ namespace Microsoft.FSharp.Core else i <- i + 1 res - type EqualityComparerInfo = - | PER = 0 - | ER = 1 - - type IEqualityComparerInfo = - abstract Info : EqualityComparerInfo /// One of the two unique instances of System.Collections.IEqualityComparer. Implements PER semantics /// where equality on NaN returns "false". let fsEqualityComparerNoHashingPER = { new System.Collections.IEqualityComparer with override iec.Equals(x:obj,y:obj) = GenericEqualityObj false iec (x,y) // PER Semantics - override iec.GetHashCode(x:obj) = raise (InvalidOperationException (SR.GetString(SR.notUsedForHashing))) - interface IEqualityComparerInfo with - member __.Info = EqualityComparerInfo.PER } - + override iec.GetHashCode(x:obj) = raise (InvalidOperationException (SR.GetString(SR.notUsedForHashing))) } + /// One of the two unique instances of System.Collections.IEqualityComparer. Implements ER semantics /// where equality on NaN returns "true". let fsEqualityComparerNoHashingER = { new System.Collections.IEqualityComparer with override iec.Equals(x:obj,y:obj) = GenericEqualityObj true iec (x,y) // ER Semantics - override iec.GetHashCode(x:obj) = raise (InvalidOperationException (SR.GetString(SR.notUsedForHashing))) - interface IEqualityComparerInfo with - member __.Info = EqualityComparerInfo.ER } - - module GenericSpecializeEquals = - let floatingPointTypes (tyRelation:Type) (ty:Type) = - match tyRelation with - | r when r.Equals typeof -> - match ty with - | t when t.Equals typeof -> typeof - | t when t.Equals typeof -> typeof - | t when t.Equals typeof> -> typeof - | t when t.Equals typeof> -> typeof - | _ -> null - | r when r.Equals typeof -> - match ty with - | t when t.Equals typeof -> typeof - | t when t.Equals typeof -> typeof - | t when t.Equals typeof> -> typeof - | t when t.Equals typeof> -> typeof - | _ -> null - | _ -> raise (Exception "invalid logic") - - let standardTypes (t:Type) : Type = - if t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - else null - - let compilerGenerated tyRelation ty = - // if we are using the ER comparer, and we are a standard f# record or value type with compiler generated - // equality operators, then we can avoid the boxing of IStructuralEquatable and just call the - // IEquatable<'a>.Equals method. - match tyRelation with - | r when r.Equals typeof -> - if mos.hasFSharpCompilerGeneratedEquality ty then - if ty.IsValueType - then mos.makeType ty typedefof> - else mos.makeType ty typedefof> - else null - | r when r.Equals typeof -> null - | _ -> raise (Exception "invalid logic") - - [] - type GenericEqualityObj_ER<'a> = - interface IEssenceOfEquals<'a> with - member __.Ensorcel (ec:IEqualityComparer, x:'a, y:'a) = GenericEqualityObj true ec (box x, box y) - - [] - type GenericEqualityObj_PER<'a> = - interface IEssenceOfEquals<'a> with - member __.Ensorcel (ec:IEqualityComparer, x:'a, y:'a) = GenericEqualityObj false ec (box x, box y) - - let arrays (tyRelation:Type) (t:Type) : Type = - if t.IsArray || typeof.IsAssignableFrom t then - // TODO: Future; for now just default back to previous functionality - match tyRelation with - | r when r.Equals typeof -> mos.makeType t typedefof> - | r when r.Equals typeof -> mos.makeType t typedefof> - | _ -> raise (Exception "invalid logic") - else null - - let nullableType (t:Type) : Type = - if t.IsGenericType && ((t.GetGenericTypeDefinition ()).Equals typedefof>) then - let underlying = get (t.GetGenericArguments()) 0 - let equatable = mos.makeEquatableType underlying - let make = mos.makeType underlying - - if typeof.IsAssignableFrom underlying then make typedefof> - elif equatable.IsAssignableFrom underlying then make typedefof> - else make typedefof> - else null - - let equalityInterfaces (t:Type) : Type = - let make = mos.makeType t - let equatable = mos.makeEquatableType t - - if t.IsValueType && typeof.IsAssignableFrom t then make typedefof> - elif t.IsValueType && equatable.IsAssignableFrom t then make typedefof> - elif t.IsValueType then make typedefof> - - elif typeof.IsAssignableFrom t then make typedefof>> - - // only sealed as a derived class might inherit from IStructuralEquatable - elif t.IsSealed && equatable.IsAssignableFrom t then make typedefof> - elif t.IsSealed then make typedefof> - - else null - - let defaultEquality tyRelation ty = - match tyRelation with - | r when r.Equals typeof -> mos.makeType ty typedefof> - | r when r.Equals typeof -> mos.makeType ty typedefof> - | _ -> raise (Exception "invalid logic") - - let getEqualsEssenceType (tyRelation:Type) (ty:Type) tuples : Type = - mos.takeFirstNonNull [| - fun () -> tuples tyRelation ty - fun () -> floatingPointTypes tyRelation ty - fun () -> standardTypes ty - fun () -> compilerGenerated tyRelation ty - fun () -> arrays tyRelation ty - fun () -> nullableType ty - fun () -> equalityInterfaces ty - fun () -> defaultEquality tyRelation ty - |] - - [] - type EqualsInvoker<'a>() = - class - abstract Invoke : IEqualityComparer * 'a * 'a -> bool - end - - [] - type EssenceOfEqualsWrapper<'a, 'eq - when 'eq :> IEssenceOfEquals<'a> and 'eq : (new : unit -> 'eq) and 'eq : struct>() = - inherit EqualsInvoker<'a>() - - override __.Invoke (comp, x:'a, y:'a) = - phantom<'eq>.Ensorcel (comp, x, y) - - let makeEqualsWrapper (ty:Type) comp = - let wrapperTypeDef = typedefof> - let wrapperType = wrapperTypeDef.MakeGenericType [| ty; comp |] - Activator.CreateInstance wrapperType - - type u = EqualsTypes.Int32 - type Function<'relation, 'a>() = - static let essenceType : Type = - getEqualsEssenceType typeof<'relation> typeof<'a> Helpers.tuplesEquals - - static let invoker : EqualsInvoker<'a> = - unboxPrim (makeEqualsWrapper typeof<'a> essenceType) - - static member Invoker = invoker - - interface mos.IGetType with - member __.Get () = essenceType - and Helpers = - static member getEssenceOfEqualsType tyRelation ty = - let equals = mos.makeGenericType> [| tyRelation; ty|] - match Activator.CreateInstance equals with - | :? mos.IGetType as getter -> getter.Get () - | _ -> raise (Exception "invalid logic") - - static member tuplesEquals (tyRelation:Type) (ty:Type) : Type = - if ty.IsGenericType then - let tyDef = ty.GetGenericTypeDefinition () - let tyDefArgs = ty.GetGenericArguments () - let create = mos.compositeType (Helpers.getEssenceOfEqualsType tyRelation) tyDefArgs - if tyDef.Equals typedefof> then create typedefof> - elif tyDef.Equals typedefof> then create typedefof> - elif tyDef.Equals typedefof> then create typedefof> - elif tyDef.Equals typedefof> then create typedefof> - else null - else null - + override iec.GetHashCode(x:obj) = raise (InvalidOperationException (SR.GetString(SR.notUsedForHashing))) } /// Implements generic equality between two values, with PER semantics for NaN (so equality on two NaN values returns false) // // The compiler optimizer is aware of this function (see use of generic_equality_per_inner_vref in opt.fs) // and devirtualizes calls to it based on "T". let GenericEqualityIntrinsic (x : 'T) (y : 'T) : bool = - eliminate_tail_call_bool (GenericSpecializeEquals.Function.Invoker.Invoke (fsEqualityComparerNoHashingPER, x, y)) - + GenericEqualityObj false fsEqualityComparerNoHashingPER ((box x), (box y)) + /// Implements generic equality between two values, with ER semantics for NaN (so equality on two NaN values returns true) // // ER semantics is used for recursive calls when implementing .Equals(that) for structural data, see the code generated for record and union types in augment.fs @@ -2771,28 +1684,16 @@ namespace Microsoft.FSharp.Core // The compiler optimizer is aware of this function (see use of generic_equality_er_inner_vref in opt.fs) // and devirtualizes calls to it based on "T". let GenericEqualityERIntrinsic (x : 'T) (y : 'T) : bool = - eliminate_tail_call_bool (GenericSpecializeEquals.Function.Invoker.Invoke (fsEqualityComparerNoHashingER, x, y)) + GenericEqualityObj true fsEqualityComparerNoHashingER ((box x), (box y)) /// Implements generic equality between two values using "comp" for recursive calls. // // The compiler optimizer is aware of this function (see use of generic_equality_withc_inner_vref in opt.fs) // and devirtualizes calls to it based on "T", and under the assumption that "comp" // is either fsEqualityComparerNoHashingER or fsEqualityComparerNoHashingPER. - // - // <> I think the above compiler optimization is misplaced, as it means that you can end - // up with differing functionality of generic and non-generic types when the IStructuralEquatable - // this is doucmented here- https://github.com/Microsoft/visualfsharp/pull/513#issuecomment-117995410 let GenericEqualityWithComparerIntrinsic (comp : System.Collections.IEqualityComparer) (x : 'T) (y : 'T) : bool = - match comp with - | :? IEqualityComparerInfo as info -> - match info.Info with - | EqualityComparerInfo.ER -> eliminate_tail_call_bool (GenericEqualityERIntrinsic x y) - | EqualityComparerInfo.PER -> eliminate_tail_call_bool (GenericEqualityIntrinsic x y) - | _ -> raise (Exception "invalid logic") - | c when obj.ReferenceEquals (c, EqualityComparer<'T>.Default) -> - eliminate_tail_call_bool (EqualityComparer<'T>.Default.Equals (x, y)) - | _ -> - eliminate_tail_call_bool (comp.Equals (box x, box y)) + comp.Equals((box x),(box y)) + /// Implements generic equality between two values, with ER semantics for NaN (so equality on two NaN values returns true) // @@ -2899,23 +1800,21 @@ namespace Microsoft.FSharp.Core new CountLimitedHasherPER(sz) interface IEqualityComparer - interface IEqualityComparerInfo /// The implementation of IEqualityComparer, using unlimited depth for hashing and ER semantics for NaN equality. type UnlimitedHasherER() = interface IEqualityComparer - interface IEqualityComparerInfo - + /// The implementation of IEqualityComparer, using unlimited depth for hashing and PER semantics for NaN equality. type UnlimitedHasherPER() = interface IEqualityComparer - interface IEqualityComparerInfo + /// The unique object for unlimited depth for hashing and ER semantics for equality. - let fsEqualityComparerUnlimitedHashingER = UnlimitedHasherER() :> IEqualityComparer + let fsEqualityComparerUnlimitedHashingER = UnlimitedHasherER() /// The unique object for unlimited depth for hashing and PER semantics for equality. - let fsEqualityComparerUnlimitedHashingPER = UnlimitedHasherPER() :> IEqualityComparer + let fsEqualityComparerUnlimitedHashingPER = UnlimitedHasherPER() let inline HashCombine nr x y = (x <<< 1) + y + 631 * nr @@ -3000,8 +1899,10 @@ namespace Microsoft.FSharp.Core | _ -> x.GetHashCode() + /// Fill in the implementation of CountLimitedHasherPER type CountLimitedHasherPER with + interface System.Collections.IEqualityComparer with override iec.Equals(x:obj,y:obj) = GenericEqualityObj false iec (x,y) @@ -3011,157 +1912,28 @@ namespace Microsoft.FSharp.Core GenericHashParamObj iec x else -1 - interface IEqualityComparerInfo with - member __.Info = EqualityComparerInfo.PER /// Fill in the implementation of UnlimitedHasherER type UnlimitedHasherER with + interface System.Collections.IEqualityComparer with override iec.Equals(x:obj,y:obj) = GenericEqualityObj true iec (x,y) override iec.GetHashCode(x:obj) = GenericHashParamObj iec x - interface IEqualityComparerInfo with - member __.Info = EqualityComparerInfo.ER /// Fill in the implementation of UnlimitedHasherPER type UnlimitedHasherPER with interface System.Collections.IEqualityComparer with override iec.Equals(x:obj,y:obj) = GenericEqualityObj false iec (x,y) override iec.GetHashCode(x:obj) = GenericHashParamObj iec x - interface IEqualityComparerInfo with - member __.Info = EqualityComparerInfo.PER - - // functionality of GenericSpecializedHash should match GenericHashParamObj, or return null - // for fallback to that funciton. - module GenericSpecializeHash = - let standardTypes (t:Type) : Type = - if t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - elif t.Equals typeof then typeof - else null - - [] - type GenericHashParamObject<'a> = - interface IEssenceOfGetHashCode<'a> with - member __.Ensorcel (iec:IEqualityComparer, x:'a) = GenericHashParamObj iec (box x) - - let arrays (t:Type) : Type = - if t.IsArray || typeof.IsAssignableFrom t then - // TODO: Future; for now just default back to previous functionality - mos.makeType t typedefof> - else null - - let nullableType (t:Type) : Type = - if t.IsGenericType && ((t.GetGenericTypeDefinition ()).Equals typedefof>) then - let underlying = get (t.GetGenericArguments()) 0 - let make = mos.makeType underlying - - if typeof.IsAssignableFrom underlying then make typedefof> - else make typedefof> - else null - - let structualEquatable (t:Type): Type = - let make = mos.makeType t - - if t.IsValueType && typeof.IsAssignableFrom t then make typedefof> - elif typeof.IsAssignableFrom t then make typedefof>> - else null - - let sealedTypes (t:Type): Type = - let make = mos.makeType t - - if t.IsValueType then make typedefof> - elif t.IsSealed then make typedefof> - else null - - let defaultGetHashCode ty = - mos.makeType ty typedefof> - - let getGetHashCodeEssenceType (t:Type) tuples : Type = - mos.takeFirstNonNull [| - fun () -> tuples t - fun () -> standardTypes t - fun () -> arrays t - fun () -> nullableType t - fun () -> structualEquatable t - fun () -> sealedTypes t - fun () -> defaultGetHashCode t - |] - - [] - type GetHashCodeInvoker<'a>() = - class - abstract Invoke : IEqualityComparer * 'a -> int - end - - [] - type EssenceOfGetHashCodeWrapper<'a, 'ghc - when 'ghc :> IEssenceOfGetHashCode<'a> and 'ghc : (new : unit -> 'ghc) and 'ghc : struct>() = - inherit GetHashCodeInvoker<'a>() - - override __.Invoke (comp, x:'a) = - phantom<'ghc>.Ensorcel (comp, x) - - let makeGetHashCodeWrapper (ty:Type) comp = - let wrapperTypeDef = typedefof> - let wrapperType = wrapperTypeDef.MakeGenericType [| ty; comp |] - Activator.CreateInstance wrapperType - - type t = GetHashCodeTypes.Int32 - type Function<'a>() = - static let essenceType : Type = - getGetHashCodeEssenceType typeof<'a> Helpers.tuplesGetHashCode - - static let invoker : GetHashCodeInvoker<'a> = - unboxPrim (makeGetHashCodeWrapper typeof<'a> essenceType) - - static member Invoker = invoker - - interface mos.IGetType with - member __.Get () = essenceType - and Helpers = - static member getEssenceOfGetHashCodeType ty = - let getHashCode = mos.makeGenericType> [|ty|] - match Activator.CreateInstance getHashCode with - | :? mos.IGetType as getter -> getter.Get () - | _ -> raise (Exception "invalid logic") - - static member tuplesGetHashCode (ty:Type) : Type = - if ty.IsGenericType then - let tyDef = ty.GetGenericTypeDefinition () - let tyDefArgs = ty.GetGenericArguments () - let create = mos.compositeType Helpers.getEssenceOfGetHashCodeType tyDefArgs - if tyDef.Equals typedefof> then create typedefof> - elif tyDef.Equals typedefof> then create typedefof> - elif tyDef.Equals typedefof> then create typedefof> - elif tyDef.Equals typedefof> then create typedefof> - else null - else null /// Intrinsic for calls to depth-unlimited structural hashing that were not optimized by static conditionals. // // NOTE: The compiler optimizer is aware of this function (see uses of generic_hash_inner_vref in opt.fs) // and devirtualizes calls to it based on type "T". - let GenericHashIntrinsic x = - let iec = fsEqualityComparerUnlimitedHashingPER - eliminate_tail_call_int (GenericSpecializeHash.Function<_>.Invoker.Invoke (iec, x)) + let GenericHashIntrinsic x = GenericHashParamObj fsEqualityComparerUnlimitedHashingPER (box(x)) /// Intrinsic for calls to depth-limited structural hashing that were not optimized by static conditionals. - let LimitedGenericHashIntrinsic limit x = - let iec = CountLimitedHasherPER limit - eliminate_tail_call_int (GenericSpecializeHash.Function<_>.Invoker.Invoke (iec, x)) + let LimitedGenericHashIntrinsic limit x = GenericHashParamObj (CountLimitedHasherPER(limit)) (box(x)) /// Intrinsic for a recursive call to structural hashing that was not optimized by static conditionals. // @@ -3171,39 +1943,7 @@ namespace Microsoft.FSharp.Core // NOTE: The compiler optimizer is aware of this function (see uses of generic_hash_withc_inner_vref in opt.fs) // and devirtualizes calls to it based on type "T". let GenericHashWithComparerIntrinsic<'T> (iec : System.Collections.IEqualityComparer) (x : 'T) : int = - eliminate_tail_call_int (GenericSpecializeHash.Function<_>.Invoker.Invoke (iec, x)) - - [] - type EssenceOfEqualityComparer<'a, 'eq, 'ghc - when 'eq :> IEssenceOfEquals<'a> and 'eq : (new : unit -> 'eq) and 'eq : struct - and 'ghc :> IEssenceOfGetHashCode<'a> and 'ghc : (new : unit -> 'ghc) and 'ghc : struct>() = - - interface IEqualityComparer<'a> with - member __.Equals (x:'a, y:'a) = - phantom<'eq>.Ensorcel (fsEqualityComparerNoHashingPER, x, y) - member __.GetHashCode (x:'a) = - phantom<'ghc>.Ensorcel (fsEqualityComparerUnlimitedHashingPER, x) - - [] - type EssenceOfComparer<'a, 'comp - when 'comp :> IEssenceOfCompareTo<'a> and 'comp : (new : unit -> 'comp) and 'comp : struct>() = - - interface IComparer<'a> with - member __.Compare (x:'a, y:'a) = - phantom<'comp>.Ensorcel (fsComparerER, x, y) - - let makeEqualityComparer (ty:Type) = - let eq = GenericSpecializeEquals.Helpers.getEssenceOfEqualsType typeof ty - let ghc = GenericSpecializeHash.Helpers.getEssenceOfGetHashCodeType ty - let equalityComparerDef = typedefof> - let equalityComparer = equalityComparerDef.MakeGenericType [| ty; eq; ghc |] - Activator.CreateInstance equalityComparer - - let makeComparer (ty:Type) = - let comp = GenericSpecializeCompareTo.Helpers.getEssenceOfCompareToType typeof ty - let comparerDef = typedefof> - let comparer = comparerDef.MakeGenericType [| ty; comp |] - Activator.CreateInstance comparer + GenericHashParamObj iec (box(x)) /// Direct call to GetHashCode on the string type let inline HashString (s:string) = @@ -3459,9 +2199,9 @@ namespace Microsoft.FSharp.Core let inline PhysicalEquality x y = HashCompare.PhysicalEqualityFast x y let inline PhysicalHash x = HashCompare.PhysicalHashFast x - let GenericComparer = HashCompare.fsComparerER - let GenericEqualityComparer = HashCompare.fsEqualityComparerUnlimitedHashingPER - let GenericEqualityERComparer = HashCompare.fsEqualityComparerUnlimitedHashingER + let GenericComparer = HashCompare.fsComparerER :> System.Collections.IComparer + let GenericEqualityComparer = HashCompare.fsEqualityComparerUnlimitedHashingPER :> System.Collections.IEqualityComparer + let GenericEqualityERComparer = HashCompare.fsEqualityComparerUnlimitedHashingER :> System.Collections.IEqualityComparer let inline GenericHash x = HashCompare.GenericHashFast x let inline GenericLimitedHash limit x = HashCompare.GenericLimitedHashFast limit x @@ -3471,15 +2211,13 @@ namespace Microsoft.FSharp.Core // LanguagePrimitives: PUBLISH IEqualityComparer AND IComparer OBJECTS //------------------------------------------------------------------------- + let inline MakeGenericEqualityComparer<'T>() = // type-specialize some common cases to generate more efficient functions { new System.Collections.Generic.IEqualityComparer<'T> with member self.GetHashCode(x) = GenericHash x member self.Equals(x,y) = GenericEquality x y } - let inline MakeGenericEqualityComparerWithEssence<'T>() : IEqualityComparer<'T> = - unboxPrim (HashCompare.makeEqualityComparer typeof<'T>) - let inline MakeGenericLimitedEqualityComparer<'T>(limit:int) = // type-specialize some common cases to generate more efficient functions { new System.Collections.Generic.IEqualityComparer<'T> with @@ -3503,32 +2241,27 @@ namespace Microsoft.FSharp.Core let Float32IEquality = MakeGenericEqualityComparer() let DecimalIEquality = MakeGenericEqualityComparer() - let getFastGenericEqualityComparerTable ty = - match ty with - | ty when ty.Equals typeof -> box BoolIEquality - | ty when ty.Equals typeof -> box ByteIEquality - | ty when ty.Equals typeof -> box Int32IEquality - | ty when ty.Equals typeof -> box UInt32IEquality - | ty when ty.Equals typeof -> box CharIEquality - | ty when ty.Equals typeof -> box SByteIEquality - | ty when ty.Equals typeof -> box Int16IEquality - | ty when ty.Equals typeof -> box Int64IEquality - | ty when ty.Equals typeof -> box IntPtrIEquality - | ty when ty.Equals typeof -> box UInt16IEquality - | ty when ty.Equals typeof -> box UInt64IEquality - | ty when ty.Equals typeof -> box UIntPtrIEquality - | ty when ty.Equals typeof -> box FloatIEquality - | ty when ty.Equals typeof -> box Float32IEquality - | ty when ty.Equals typeof -> box DecimalIEquality - | ty when ty.Equals typeof -> box StringIEquality - | _ -> null - [] type FastGenericEqualityComparerTable<'T>() = static let f : System.Collections.Generic.IEqualityComparer<'T> = - match getFastGenericEqualityComparerTable typeof<'T> with - | null -> MakeGenericEqualityComparerWithEssence<'T>() - | iec -> unboxPrim iec + match typeof<'T> with + | ty when ty.Equals(typeof) -> unboxPrim (box BoolIEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box ByteIEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box Int32IEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box UInt32IEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box CharIEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box SByteIEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box Int16IEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box Int64IEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box IntPtrIEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box UInt16IEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box UInt64IEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box UIntPtrIEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box FloatIEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box Float32IEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box DecimalIEquality) + | ty when ty.Equals(typeof) -> unboxPrim (box StringIEquality) + | _ -> MakeGenericEqualityComparer<'T>() static member Function : System.Collections.Generic.IEqualityComparer<'T> = f let FastGenericEqualityComparerFromTable<'T> = FastGenericEqualityComparerTable<'T>.Function @@ -3570,9 +2303,6 @@ namespace Microsoft.FSharp.Core { new System.Collections.Generic.IComparer<'T> with member __.Compare(x,y) = GenericComparison x y } - let inline MakeGenericComparerWithEssence<'T>() : IComparer<'T> = - unboxPrim (HashCompare.makeComparer typeof<'T>) - let CharComparer = MakeGenericComparer() let StringComparer = MakeGenericComparer() let SByteComparer = MakeGenericComparer() @@ -3589,37 +2319,11 @@ namespace Microsoft.FSharp.Core let Float32Comparer = MakeGenericComparer() let DecimalComparer = MakeGenericComparer() - let getFastGenericComparerTable ty = - match ty with - | ty when ty.Equals typeof -> box ByteComparer - | ty when ty.Equals typeof -> box CharComparer - | ty when ty.Equals typeof -> box SByteComparer - | ty when ty.Equals typeof -> box Int16Comparer - | ty when ty.Equals typeof -> box Int32Comparer - | ty when ty.Equals typeof -> box Int64Comparer - | ty when ty.Equals typeof -> box IntPtrComparer - | ty when ty.Equals typeof -> box UInt16Comparer - | ty when ty.Equals typeof -> box UInt32Comparer - | ty when ty.Equals typeof -> box UInt64Comparer - | ty when ty.Equals typeof -> box UIntPtrComparer - | ty when ty.Equals typeof -> box FloatComparer - | ty when ty.Equals typeof -> box Float32Comparer - | ty when ty.Equals typeof -> box DecimalComparer - | ty when ty.Equals typeof -> box StringComparer - | _ -> null - /// Use a type-indexed table to ensure we only create a single FastStructuralComparison function /// for each type [] type FastGenericComparerTable<'T>() = - static let f : System.Collections.Generic.IComparer<'T> = - match getFastGenericComparerTable typeof<'T> with - | null -> MakeGenericComparerWithEssence<'T>() - | ic -> unboxPrim ic - - static member Value : System.Collections.Generic.IComparer<'T> = f - let getFastGenericComparerTable_fCanBeNull ty = // The CLI implementation of mscorlib optimizes array sorting // when the comparer is either null or precisely // reference-equals to System.Collections.Generic.Comparer<'T>.Default. @@ -3634,24 +2338,49 @@ namespace Microsoft.FSharp.Core // same as a stable sort of the array. See Array.stableSortInPlace. // // REVIEW: in a future version we could extend this to include additional types - ty.Equals typeof - || ty.Equals typeof - || ty.Equals typeof - || ty.Equals typeof - || ty.Equals typeof - || ty.Equals typeof - || ty.Equals typeof - || ty.Equals typeof - || ty.Equals typeof - || ty.Equals typeof - || ty.Equals typeof - || ty.Equals typeof - - type FastGenericComparerTable_fCanBeNull<'T>() = static let fCanBeNull : System.Collections.Generic.IComparer<'T> = - match getFastGenericComparerTable_fCanBeNull typeof<'T> with - | true -> null - | false -> FastGenericComparerTable.Value + match typeof<'T> with + | ty when ty.Equals(typeof) -> unboxPrim (box IntPtrComparer) + | ty when ty.Equals(typeof) -> unboxPrim (box UIntPtrComparer) + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> null + | ty when ty.Equals(typeof) -> unboxPrim (box StringComparer) + | _ -> MakeGenericComparer<'T>() + + static let f : System.Collections.Generic.IComparer<'T> = + match typeof<'T> with + | ty when ty.Equals(typeof) -> unboxPrim (box ByteComparer) + | ty when ty.Equals(typeof) -> unboxPrim (box CharComparer) + | ty when ty.Equals(typeof) -> unboxPrim (box SByteComparer) + | ty when ty.Equals(typeof) -> unboxPrim (box Int16Comparer) + | ty when ty.Equals(typeof) -> unboxPrim (box Int32Comparer) + | ty when ty.Equals(typeof) -> unboxPrim (box Int64Comparer) + | ty when ty.Equals(typeof) -> unboxPrim (box IntPtrComparer) + | ty when ty.Equals(typeof) -> unboxPrim (box UInt16Comparer) + | ty when ty.Equals(typeof) -> unboxPrim (box UInt32Comparer) + | ty when ty.Equals(typeof) -> unboxPrim (box UInt64Comparer) + | ty when ty.Equals(typeof) -> unboxPrim (box UIntPtrComparer) + | ty when ty.Equals(typeof) -> unboxPrim (box FloatComparer) + | ty when ty.Equals(typeof) -> unboxPrim (box Float32Comparer) + | ty when ty.Equals(typeof) -> unboxPrim (box DecimalComparer) + | ty when ty.Equals(typeof) -> unboxPrim (box StringComparer) + | _ -> + // Review: There are situations where we should be able + // to return System.Collections.Generic.Comparer<'T>.Default here. + // For example, for any value type. + MakeGenericComparer<'T>() + + static member Value : System.Collections.Generic.IComparer<'T> = f static member ValueCanBeNullIfDefaultSemantics : System.Collections.Generic.IComparer<'T> = fCanBeNull @@ -3687,7 +2416,7 @@ namespace Microsoft.FSharp.Core // which are then optimized for the particular nominal type involved. when 'T : 'T = MakeGenericComparer<'T>() - let FastGenericComparerCanBeNull<'T> = FastGenericComparerTable_fCanBeNull<'T>.ValueCanBeNullIfDefaultSemantics + let FastGenericComparerCanBeNull<'T> = FastGenericComparerTable<'T>.ValueCanBeNullIfDefaultSemantics //------------------------------------------------------------------------- // LanguagePrimitives: ENUMS From 6fdc01ecdb77482fc335e5f67cab88c41e48a6d5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 6 Mar 2016 20:05:56 +1100 Subject: [PATCH 2/3] Fix tests by restore tail calls in IL output --- .../GenericComparison/Compare07.il.netfx4.bsl | 41 +++++++------------ .../GenericComparison/Compare10.il.netfx4.bsl | 36 +++++----------- .../GenericComparison/Equals06.il.netfx4.bsl | 41 +++++++------------ .../GenericComparison/Equals09.il.netfx4.bsl | 36 +++++----------- .../GenericComparison/Hash09.il.netfx4.bsl | 37 +++++++---------- .../GenericComparison/Hash12.il.netfx4.bsl | 34 +++++---------- 6 files changed, 78 insertions(+), 147 deletions(-) diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.netfx4.bsl index 9264f0d50ee..b659eadc973 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.netfx4.bsl @@ -29,22 +29,20 @@ } .mresource public FSharpSignatureData.Compare07 { - // Offset: 0x00000000 Length: 0x0000089A - // WARNING: managed resource file FSharpSignatureData.Compare07 created + // Offset: 0x00000000 Length: 0x000008A2 } .mresource public FSharpOptimizationData.Compare07 { - // Offset: 0x000008A0 Length: 0x00000694 - // WARNING: managed resource file FSharpOptimizationData.Compare07 created + // Offset: 0x000008A8 Length: 0x00000698 } .module Compare07.dll -// MVID: {56B7C20F-05DE-F88E-A745-03830FC2B756} +// MVID: {56DBF219-05DE-F88E-A745-038319F2DB56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01310000 +// Image base: 0x00C20000 // =============== CLASS MEMBERS DECLARATION =================== @@ -256,16 +254,15 @@ instance int32 CompareTo(object obj) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 14 (0xe) + // Code size 16 (0x10) .maxstack 8 - .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 4,4 : 10,20 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 IL_0003: unbox.any class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 - IL_0008: callvirt instance int32 class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1::CompareTo(class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1) - IL_000d: ret + IL_0008: tail. + IL_000a: callvirt instance int32 class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1::CompareTo(class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1) + IL_000f: ret } // end of method GenericKey`1::CompareTo .method public hidebysig virtual final @@ -281,7 +278,6 @@ [3] int32 V_3, [4] !a V_4, [5] !a V_5) - .line 4,4 : 10,20 IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 @@ -433,7 +429,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 - .line 4,4 : 10,20 IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -584,7 +579,7 @@ instance bool Equals(object obj) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 21 (0x15) + // Code size 23 (0x17) .maxstack 4 .locals init (class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 V_0) IL_0000: nop @@ -592,15 +587,16 @@ IL_0002: isinst class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 IL_0007: stloc.0 IL_0008: ldloc.0 - IL_0009: brfalse.s IL_0013 + IL_0009: brfalse.s IL_0015 IL_000b: ldarg.0 IL_000c: ldloc.0 - IL_000d: callvirt instance bool class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1::Equals(class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1) - IL_0012: ret - - IL_0013: ldc.i4.0 + IL_000d: tail. + IL_000f: callvirt instance bool class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1::Equals(class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1) IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret } // end of method GenericKey`1::Equals .property instance int32 Tag() @@ -638,28 +634,23 @@ [1] class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 t1, [2] class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 t2, [3] int32 i) - .line 6,6 : 8,25 IL_0000: nop IL_0001: ldc.i4.1 IL_0002: stloc.0 - .line 7,7 : 8,32 IL_0003: ldc.i4.1 IL_0004: ldc.i4.2 IL_0005: call class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1::NewGenericKey(!0, !0) IL_000a: stloc.1 - .line 8,8 : 8,32 IL_000b: ldc.i4.1 IL_000c: ldc.i4.3 IL_000d: call class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1::NewGenericKey(!0, !0) IL_0012: stloc.2 - .line 9,9 : 8,32 IL_0013: ldc.i4.0 IL_0014: stloc.3 IL_0015: br.s IL_0023 - .line 10,10 : 12,30 IL_0017: ldloc.1 IL_0018: ldloc.2 IL_0019: callvirt instance int32 class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1::CompareTo(class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1) @@ -668,12 +659,10 @@ IL_0020: ldc.i4.1 IL_0021: add IL_0022: stloc.3 - .line 9,9 : 21,29 IL_0023: ldloc.3 IL_0024: ldc.i4 0x989681 IL_0029: blt.s IL_0017 - .line 11,11 : 8,9 IL_002b: ldloc.0 IL_002c: ret } // end of method CompareMicroPerfAndCodeGenerationTests::f6 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.netfx4.bsl index a425e0cd968..793d2fe80a1 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.netfx4.bsl @@ -29,22 +29,20 @@ } .mresource public FSharpSignatureData.Compare10 { - // Offset: 0x00000000 Length: 0x00000AA4 - // WARNING: managed resource file FSharpSignatureData.Compare10 created + // Offset: 0x00000000 Length: 0x00000AAC } .mresource public FSharpOptimizationData.Compare10 { - // Offset: 0x00000AA8 Length: 0x00000592 - // WARNING: managed resource file FSharpOptimizationData.Compare10 created + // Offset: 0x00000AB0 Length: 0x00000592 } .module Compare10.dll -// MVID: {56B7C2B8-04BF-1753-A745-0383B8C2B756} +// MVID: {56DBF21D-04BF-1753-A745-03831DF2DB56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00F70000 +// Image base: 0x01100000 // =============== CLASS MEMBERS DECLARATION =================== @@ -267,8 +265,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 - .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 4,4 : 10,13 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -290,7 +286,6 @@ [3] int32 V_3, [4] int32 V_4, [5] int32 V_5) - .line 4,4 : 10,13 IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Compare10/CompareMicroPerfAndCodeGenerationTests/Key @@ -440,7 +435,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 - .line 4,4 : 10,13 IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -832,7 +826,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 - .line 5,5 : 10,26 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -859,7 +852,6 @@ [8] class Compare10/CompareMicroPerfAndCodeGenerationTests/Key V_8, [9] class Compare10/CompareMicroPerfAndCodeGenerationTests/Key V_9, [10] int32 V_10) - .line 5,5 : 10,26 IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys @@ -1047,7 +1039,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 - .line 5,5 : 10,26 IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -1210,7 +1201,7 @@ instance bool Equals(object obj) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 21 (0x15) + // Code size 23 (0x17) .maxstack 4 .locals init (class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys V_0) IL_0000: nop @@ -1218,15 +1209,16 @@ IL_0002: isinst Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys IL_0007: stloc.0 IL_0008: ldloc.0 - IL_0009: brfalse.s IL_0013 + IL_0009: brfalse.s IL_0015 IL_000b: ldarg.0 IL_000c: ldloc.0 - IL_000d: callvirt instance bool Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::Equals(class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys) - IL_0012: ret - - IL_0013: ldc.i4.0 + IL_000d: tail. + IL_000f: callvirt instance bool Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::Equals(class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys) IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret } // end of method KeyWithInnerKeys::Equals .property instance int32 Tag() @@ -1266,11 +1258,9 @@ [1] class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys key1, [2] class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys key2, [3] int32 i) - .line 7,7 : 8,25 IL_0000: nop IL_0001: ldc.i4.1 IL_0002: stloc.0 - .line 8,8 : 8,65 IL_0003: ldc.i4.1 IL_0004: ldc.i4.2 IL_0005: call class Compare10/CompareMicroPerfAndCodeGenerationTests/Key Compare10/CompareMicroPerfAndCodeGenerationTests/Key::NewKey(int32, @@ -1288,7 +1278,6 @@ IL_001d: call class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::NewKeyWithInnerKeys(class Compare10/CompareMicroPerfAndCodeGenerationTests/Key, class [mscorlib]System.Tuple`2) IL_0022: stloc.1 - .line 9,9 : 8,65 IL_0023: ldc.i4.1 IL_0024: ldc.i4.2 IL_0025: call class Compare10/CompareMicroPerfAndCodeGenerationTests/Key Compare10/CompareMicroPerfAndCodeGenerationTests/Key::NewKey(int32, @@ -1306,12 +1295,10 @@ IL_003d: call class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::NewKeyWithInnerKeys(class Compare10/CompareMicroPerfAndCodeGenerationTests/Key, class [mscorlib]System.Tuple`2) IL_0042: stloc.2 - .line 10,10 : 8,32 IL_0043: ldc.i4.0 IL_0044: stloc.3 IL_0045: br.s IL_0053 - .line 11,11 : 12,34 IL_0047: ldloc.1 IL_0048: ldloc.2 IL_0049: callvirt instance int32 Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::CompareTo(class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys) @@ -1320,7 +1307,6 @@ IL_0050: ldc.i4.1 IL_0051: add IL_0052: stloc.3 - .line 10,10 : 21,29 IL_0053: ldloc.3 IL_0054: ldc.i4 0x989681 IL_0059: blt.s IL_0047 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.netfx4.bsl index 4dc8fc9bf24..fe154591c40 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.netfx4.bsl @@ -29,22 +29,20 @@ } .mresource public FSharpSignatureData.Equals06 { - // Offset: 0x00000000 Length: 0x00000896 - // WARNING: managed resource file FSharpSignatureData.Equals06 created + // Offset: 0x00000000 Length: 0x0000089E } .mresource public FSharpOptimizationData.Equals06 { - // Offset: 0x000008A0 Length: 0x00000690 - // WARNING: managed resource file FSharpOptimizationData.Equals06 created + // Offset: 0x000008A8 Length: 0x00000694 } .module Equals06.dll -// MVID: {56B7C2C7-0759-31EC-A745-0383C7C2B756} +// MVID: {56DBF226-0759-31EC-A745-038326F2DB56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00B20000 +// Image base: 0x00BD0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -256,16 +254,15 @@ instance int32 CompareTo(object obj) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 14 (0xe) + // Code size 16 (0x10) .maxstack 8 - .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 4,4 : 10,20 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 IL_0003: unbox.any class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 - IL_0008: callvirt instance int32 class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1::CompareTo(class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1) - IL_000d: ret + IL_0008: tail. + IL_000a: callvirt instance int32 class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1::CompareTo(class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1) + IL_000f: ret } // end of method GenericKey`1::CompareTo .method public hidebysig virtual final @@ -281,7 +278,6 @@ [3] int32 V_3, [4] !a V_4, [5] !a V_5) - .line 4,4 : 10,20 IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 @@ -433,7 +429,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 - .line 4,4 : 10,20 IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -584,7 +579,7 @@ instance bool Equals(object obj) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 21 (0x15) + // Code size 23 (0x17) .maxstack 4 .locals init (class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 V_0) IL_0000: nop @@ -592,15 +587,16 @@ IL_0002: isinst class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 IL_0007: stloc.0 IL_0008: ldloc.0 - IL_0009: brfalse.s IL_0013 + IL_0009: brfalse.s IL_0015 IL_000b: ldarg.0 IL_000c: ldloc.0 - IL_000d: callvirt instance bool class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1::Equals(class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1) - IL_0012: ret - - IL_0013: ldc.i4.0 + IL_000d: tail. + IL_000f: callvirt instance bool class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1::Equals(class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1) IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret } // end of method GenericKey`1::Equals .property instance int32 Tag() @@ -638,28 +634,23 @@ [1] class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 t1, [2] class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 t2, [3] int32 i) - .line 6,6 : 8,29 IL_0000: nop IL_0001: ldc.i4.0 IL_0002: stloc.0 - .line 7,7 : 8,32 IL_0003: ldc.i4.1 IL_0004: ldc.i4.2 IL_0005: call class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1::NewGenericKey(!0, !0) IL_000a: stloc.1 - .line 8,8 : 8,32 IL_000b: ldc.i4.1 IL_000c: ldc.i4.3 IL_000d: call class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1::NewGenericKey(!0, !0) IL_0012: stloc.2 - .line 9,9 : 8,32 IL_0013: ldc.i4.0 IL_0014: stloc.3 IL_0015: br.s IL_0028 - .line 10,10 : 12,26 IL_0017: ldloc.1 IL_0018: ldloc.2 IL_0019: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -670,12 +661,10 @@ IL_0025: ldc.i4.1 IL_0026: add IL_0027: stloc.3 - .line 9,9 : 21,29 IL_0028: ldloc.3 IL_0029: ldc.i4 0x989681 IL_002e: blt.s IL_0017 - .line 11,11 : 8,9 IL_0030: ldloc.0 IL_0031: ret } // end of method EqualsMicroPerfAndCodeGenerationTests::f6 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.netfx4.bsl index 78b85edbba2..4d58b633bb9 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.netfx4.bsl @@ -29,22 +29,20 @@ } .mresource public FSharpSignatureData.Equals09 { - // Offset: 0x00000000 Length: 0x00000AA0 - // WARNING: managed resource file FSharpSignatureData.Equals09 created + // Offset: 0x00000000 Length: 0x00000AA8 } .mresource public FSharpOptimizationData.Equals09 { - // Offset: 0x00000AA8 Length: 0x0000058F - // WARNING: managed resource file FSharpOptimizationData.Equals09 created + // Offset: 0x00000AB0 Length: 0x0000058F } .module Equals09.dll -// MVID: {56B7C2D8-0759-46D9-A745-0383D8C2B756} +// MVID: {56DBF22A-0759-46D9-A745-03832AF2DB56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00B00000 +// Image base: 0x022D0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -267,8 +265,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 - .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 4,4 : 10,13 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -290,7 +286,6 @@ [3] int32 V_3, [4] int32 V_4, [5] int32 V_5) - .line 4,4 : 10,13 IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Equals09/EqualsMicroPerfAndCodeGenerationTests/Key @@ -440,7 +435,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 - .line 4,4 : 10,13 IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -832,7 +826,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 - .line 5,5 : 10,26 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -859,7 +852,6 @@ [8] class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key V_8, [9] class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key V_9, [10] int32 V_10) - .line 5,5 : 10,26 IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys @@ -1047,7 +1039,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 - .line 5,5 : 10,26 IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -1210,7 +1201,7 @@ instance bool Equals(object obj) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 21 (0x15) + // Code size 23 (0x17) .maxstack 4 .locals init (class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys V_0) IL_0000: nop @@ -1218,15 +1209,16 @@ IL_0002: isinst Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys IL_0007: stloc.0 IL_0008: ldloc.0 - IL_0009: brfalse.s IL_0013 + IL_0009: brfalse.s IL_0015 IL_000b: ldarg.0 IL_000c: ldloc.0 - IL_000d: callvirt instance bool Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::Equals(class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys) - IL_0012: ret - - IL_0013: ldc.i4.0 + IL_000d: tail. + IL_000f: callvirt instance bool Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::Equals(class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys) IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret } // end of method KeyWithInnerKeys::Equals .property instance int32 Tag() @@ -1266,11 +1258,9 @@ [1] class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys key1, [2] class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys key2, [3] int32 i) - .line 7,7 : 8,29 IL_0000: nop IL_0001: ldc.i4.0 IL_0002: stloc.0 - .line 8,8 : 8,65 IL_0003: ldc.i4.1 IL_0004: ldc.i4.2 IL_0005: call class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key Equals09/EqualsMicroPerfAndCodeGenerationTests/Key::NewKey(int32, @@ -1288,7 +1278,6 @@ IL_001d: call class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::NewKeyWithInnerKeys(class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key, class [mscorlib]System.Tuple`2) IL_0022: stloc.1 - .line 9,9 : 8,65 IL_0023: ldc.i4.1 IL_0024: ldc.i4.2 IL_0025: call class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key Equals09/EqualsMicroPerfAndCodeGenerationTests/Key::NewKey(int32, @@ -1306,12 +1295,10 @@ IL_003d: call class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::NewKeyWithInnerKeys(class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key, class [mscorlib]System.Tuple`2) IL_0042: stloc.2 - .line 10,10 : 8,32 IL_0043: ldc.i4.0 IL_0044: stloc.3 IL_0045: br.s IL_0058 - .line 11,11 : 12,30 IL_0047: ldloc.1 IL_0048: ldloc.2 IL_0049: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -1322,7 +1309,6 @@ IL_0055: ldc.i4.1 IL_0056: add IL_0057: stloc.3 - .line 10,10 : 21,29 IL_0058: ldloc.3 IL_0059: ldc.i4 0x989681 IL_005e: blt.s IL_0047 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.netfx4.bsl index d87615b8220..bf1a7a960af 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.netfx4.bsl @@ -29,22 +29,20 @@ } .mresource public FSharpSignatureData.Hash09 { - // Offset: 0x00000000 Length: 0x0000088E - // WARNING: managed resource file FSharpSignatureData.Hash09 created + // Offset: 0x00000000 Length: 0x00000896 } .mresource public FSharpOptimizationData.Hash09 { - // Offset: 0x00000898 Length: 0x00000688 - // WARNING: managed resource file FSharpOptimizationData.Hash09 created + // Offset: 0x000008A0 Length: 0x0000068C } .module Hash09.dll -// MVID: {56B7C2E6-9642-77DB-A745-0383E6C2B756} +// MVID: {56DBF20C-9642-77DB-A745-03830CF2DB56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01150000 +// Image base: 0x00F30000 // =============== CLASS MEMBERS DECLARATION =================== @@ -256,16 +254,15 @@ instance int32 CompareTo(object obj) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 14 (0xe) + // Code size 16 (0x10) .maxstack 8 - .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 4,4 : 10,20 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 IL_0003: unbox.any class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1 - IL_0008: callvirt instance int32 class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1::CompareTo(class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1) - IL_000d: ret + IL_0008: tail. + IL_000a: callvirt instance int32 class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1::CompareTo(class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1) + IL_000f: ret } // end of method GenericKey`1::CompareTo .method public hidebysig virtual final @@ -281,7 +278,6 @@ [3] int32 V_3, [4] !a V_4, [5] !a V_5) - .line 4,4 : 10,20 IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1 @@ -433,7 +429,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 - .line 4,4 : 10,20 IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -584,7 +579,7 @@ instance bool Equals(object obj) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 21 (0x15) + // Code size 23 (0x17) .maxstack 4 .locals init (class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1 V_0) IL_0000: nop @@ -592,15 +587,16 @@ IL_0002: isinst class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1 IL_0007: stloc.0 IL_0008: ldloc.0 - IL_0009: brfalse.s IL_0013 + IL_0009: brfalse.s IL_0015 IL_000b: ldarg.0 IL_000c: ldloc.0 - IL_000d: callvirt instance bool class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1::Equals(class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1) - IL_0012: ret - - IL_0013: ldc.i4.0 + IL_000d: tail. + IL_000f: callvirt instance bool class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1::Equals(class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1) IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret } // end of method GenericKey`1::Equals .property instance int32 Tag() @@ -636,13 +632,11 @@ .maxstack 4 .locals init ([0] int32 i, [1] int32 V_1) - .line 7,7 : 8,32 IL_0000: nop IL_0001: ldc.i4.0 IL_0002: stloc.0 IL_0003: br.s IL_001b - .line 8,8 : 12,44 IL_0005: ldc.i4.1 IL_0006: ldc.i4.2 IL_0007: call class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1 class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1::NewGenericKey(!0, @@ -654,7 +648,6 @@ IL_0018: ldc.i4.1 IL_0019: add IL_001a: stloc.0 - .line 7,7 : 21,29 IL_001b: ldloc.0 IL_001c: ldc.i4 0x989681 IL_0021: blt.s IL_0005 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.netfx4.bsl index a755e31b4b0..3a0db271e58 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.netfx4.bsl @@ -29,22 +29,20 @@ } .mresource public FSharpSignatureData.Hash12 { - // Offset: 0x00000000 Length: 0x00000A98 - // WARNING: managed resource file FSharpSignatureData.Hash12 created + // Offset: 0x00000000 Length: 0x00000AA0 } .mresource public FSharpOptimizationData.Hash12 { - // Offset: 0x00000AA0 Length: 0x00000589 - // WARNING: managed resource file FSharpOptimizationData.Hash12 created + // Offset: 0x00000AA8 Length: 0x00000589 } .module Hash12.dll -// MVID: {56B7C2F3-9661-796E-A745-0383F3C2B756} +// MVID: {56DBF207-9661-796E-A745-038307F2DB56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00C60000 +// Image base: 0x024C0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -267,8 +265,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 - .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 4,4 : 10,13 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -290,7 +286,6 @@ [3] int32 V_3, [4] int32 V_4, [5] int32 V_5) - .line 4,4 : 10,13 IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Hash12/HashMicroPerfAndCodeGenerationTests/Key @@ -440,7 +435,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 - .line 4,4 : 10,13 IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -832,7 +826,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 - .line 5,5 : 10,26 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -859,7 +852,6 @@ [8] class Hash12/HashMicroPerfAndCodeGenerationTests/Key V_8, [9] class Hash12/HashMicroPerfAndCodeGenerationTests/Key V_9, [10] int32 V_10) - .line 5,5 : 10,26 IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys @@ -1047,7 +1039,6 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 - .line 5,5 : 10,26 IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -1210,7 +1201,7 @@ instance bool Equals(object obj) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 21 (0x15) + // Code size 23 (0x17) .maxstack 4 .locals init (class Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys V_0) IL_0000: nop @@ -1218,15 +1209,16 @@ IL_0002: isinst Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys IL_0007: stloc.0 IL_0008: ldloc.0 - IL_0009: brfalse.s IL_0013 + IL_0009: brfalse.s IL_0015 IL_000b: ldarg.0 IL_000c: ldloc.0 - IL_000d: callvirt instance bool Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::Equals(class Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys) - IL_0012: ret - - IL_0013: ldc.i4.0 + IL_000d: tail. + IL_000f: callvirt instance bool Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::Equals(class Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys) IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret } // end of method KeyWithInnerKeys::Equals .property instance int32 Tag() @@ -1265,7 +1257,6 @@ .locals init ([0] class Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys key, [1] int32 i, [2] int32 V_2) - .line 8,8 : 8,64 IL_0000: nop IL_0001: ldc.i4.1 IL_0002: ldc.i4.2 @@ -1284,12 +1275,10 @@ IL_001b: call class Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::NewKeyWithInnerKeys(class Hash12/HashMicroPerfAndCodeGenerationTests/Key, class [mscorlib]System.Tuple`2) IL_0020: stloc.0 - .line 9,9 : 8,32 IL_0021: ldc.i4.0 IL_0022: stloc.1 IL_0023: br.s IL_0035 - .line 10,10 : 12,30 IL_0025: ldloc.0 IL_0026: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityERComparer() IL_002b: callvirt instance int32 Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::GetHashCode(class [mscorlib]System.Collections.IEqualityComparer) @@ -1298,7 +1287,6 @@ IL_0032: ldc.i4.1 IL_0033: add IL_0034: stloc.1 - .line 9,9 : 21,29 IL_0035: ldloc.1 IL_0036: ldc.i4 0x989681 IL_003b: blt.s IL_0025 From 4ecc9d5ad9b44af56de682b33ee7b9d2fb4125a7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 7 Mar 2016 20:33:52 +1100 Subject: [PATCH 3/3] Fix tests take 2, this time leaving path --- .../GenericComparison/Compare07.il.netfx4.bsl | 15 +++++++++++++-- .../GenericComparison/Compare10.il.netfx4.bsl | 17 +++++++++++++++-- .../GenericComparison/Equals06.il.netfx4.bsl | 15 +++++++++++++-- .../GenericComparison/Equals09.il.netfx4.bsl | 17 +++++++++++++++-- .../GenericComparison/Hash09.il.netfx4.bsl | 11 +++++++++-- .../GenericComparison/Hash12.il.netfx4.bsl | 15 +++++++++++++-- 6 files changed, 78 insertions(+), 12 deletions(-) diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.netfx4.bsl index b659eadc973..0e0e05aa367 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.netfx4.bsl @@ -36,13 +36,13 @@ // Offset: 0x000008A8 Length: 0x00000698 } .module Compare07.dll -// MVID: {56DBF219-05DE-F88E-A745-038319F2DB56} +// MVID: {56DD235D-05DE-F88E-A745-03835D23DD56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00C20000 +// Image base: 0x00D80000 // =============== CLASS MEMBERS DECLARATION =================== @@ -256,6 +256,8 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 16 (0x10) .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 4,4 : 10,20 'E:\\Documents\\GitHub\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare07.fsx' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -278,6 +280,7 @@ [3] int32 V_3, [4] !a V_4, [5] !a V_5) + .line 4,4 : 10,20 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 @@ -429,6 +432,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 4,4 : 10,20 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -634,23 +638,28 @@ [1] class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 t1, [2] class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 t2, [3] int32 i) + .line 6,6 : 8,25 '' IL_0000: nop IL_0001: ldc.i4.1 IL_0002: stloc.0 + .line 7,7 : 8,32 '' IL_0003: ldc.i4.1 IL_0004: ldc.i4.2 IL_0005: call class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1::NewGenericKey(!0, !0) IL_000a: stloc.1 + .line 8,8 : 8,32 '' IL_000b: ldc.i4.1 IL_000c: ldc.i4.3 IL_000d: call class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1 class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1::NewGenericKey(!0, !0) IL_0012: stloc.2 + .line 9,9 : 8,32 '' IL_0013: ldc.i4.0 IL_0014: stloc.3 IL_0015: br.s IL_0023 + .line 10,10 : 12,30 '' IL_0017: ldloc.1 IL_0018: ldloc.2 IL_0019: callvirt instance int32 class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1::CompareTo(class Compare07/CompareMicroPerfAndCodeGenerationTests/GenericKey`1) @@ -659,10 +668,12 @@ IL_0020: ldc.i4.1 IL_0021: add IL_0022: stloc.3 + .line 9,9 : 21,29 '' IL_0023: ldloc.3 IL_0024: ldc.i4 0x989681 IL_0029: blt.s IL_0017 + .line 11,11 : 8,9 '' IL_002b: ldloc.0 IL_002c: ret } // end of method CompareMicroPerfAndCodeGenerationTests::f6 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.netfx4.bsl index 793d2fe80a1..9e727240195 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.netfx4.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000AB0 Length: 0x00000592 } .module Compare10.dll -// MVID: {56DBF21D-04BF-1753-A745-03831DF2DB56} +// MVID: {56DD2366-04BF-1753-A745-03836623DD56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01100000 +// Image base: 0x00E00000 // =============== CLASS MEMBERS DECLARATION =================== @@ -265,6 +265,8 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 4,4 : 10,13 'E:\\Documents\\GitHub\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare10.fsx' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -286,6 +288,7 @@ [3] int32 V_3, [4] int32 V_4, [5] int32 V_5) + .line 4,4 : 10,13 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Compare10/CompareMicroPerfAndCodeGenerationTests/Key @@ -435,6 +438,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 4,4 : 10,13 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -826,6 +830,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 + .line 5,5 : 10,26 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -852,6 +857,7 @@ [8] class Compare10/CompareMicroPerfAndCodeGenerationTests/Key V_8, [9] class Compare10/CompareMicroPerfAndCodeGenerationTests/Key V_9, [10] int32 V_10) + .line 5,5 : 10,26 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys @@ -1039,6 +1045,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 5,5 : 10,26 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -1258,9 +1265,11 @@ [1] class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys key1, [2] class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys key2, [3] int32 i) + .line 7,7 : 8,25 '' IL_0000: nop IL_0001: ldc.i4.1 IL_0002: stloc.0 + .line 8,8 : 8,65 '' IL_0003: ldc.i4.1 IL_0004: ldc.i4.2 IL_0005: call class Compare10/CompareMicroPerfAndCodeGenerationTests/Key Compare10/CompareMicroPerfAndCodeGenerationTests/Key::NewKey(int32, @@ -1278,6 +1287,7 @@ IL_001d: call class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::NewKeyWithInnerKeys(class Compare10/CompareMicroPerfAndCodeGenerationTests/Key, class [mscorlib]System.Tuple`2) IL_0022: stloc.1 + .line 9,9 : 8,65 '' IL_0023: ldc.i4.1 IL_0024: ldc.i4.2 IL_0025: call class Compare10/CompareMicroPerfAndCodeGenerationTests/Key Compare10/CompareMicroPerfAndCodeGenerationTests/Key::NewKey(int32, @@ -1295,10 +1305,12 @@ IL_003d: call class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::NewKeyWithInnerKeys(class Compare10/CompareMicroPerfAndCodeGenerationTests/Key, class [mscorlib]System.Tuple`2) IL_0042: stloc.2 + .line 10,10 : 8,32 '' IL_0043: ldc.i4.0 IL_0044: stloc.3 IL_0045: br.s IL_0053 + .line 11,11 : 12,34 '' IL_0047: ldloc.1 IL_0048: ldloc.2 IL_0049: callvirt instance int32 Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::CompareTo(class Compare10/CompareMicroPerfAndCodeGenerationTests/KeyWithInnerKeys) @@ -1307,6 +1319,7 @@ IL_0050: ldc.i4.1 IL_0051: add IL_0052: stloc.3 + .line 10,10 : 21,29 '' IL_0053: ldloc.3 IL_0054: ldc.i4 0x989681 IL_0059: blt.s IL_0047 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.netfx4.bsl index fe154591c40..aa064a3af37 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.netfx4.bsl @@ -36,13 +36,13 @@ // Offset: 0x000008A8 Length: 0x00000694 } .module Equals06.dll -// MVID: {56DBF226-0759-31EC-A745-038326F2DB56} +// MVID: {56DD23B2-0759-31EC-A745-0383B223DD56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00BD0000 +// Image base: 0x00AC0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -256,6 +256,8 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 16 (0x10) .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 4,4 : 10,20 'E:\\Documents\\GitHub\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Equals06.fsx' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -278,6 +280,7 @@ [3] int32 V_3, [4] !a V_4, [5] !a V_5) + .line 4,4 : 10,20 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 @@ -429,6 +432,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 4,4 : 10,20 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -634,23 +638,28 @@ [1] class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 t1, [2] class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 t2, [3] int32 i) + .line 6,6 : 8,29 '' IL_0000: nop IL_0001: ldc.i4.0 IL_0002: stloc.0 + .line 7,7 : 8,32 '' IL_0003: ldc.i4.1 IL_0004: ldc.i4.2 IL_0005: call class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1::NewGenericKey(!0, !0) IL_000a: stloc.1 + .line 8,8 : 8,32 '' IL_000b: ldc.i4.1 IL_000c: ldc.i4.3 IL_000d: call class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1 class Equals06/EqualsMicroPerfAndCodeGenerationTests/GenericKey`1::NewGenericKey(!0, !0) IL_0012: stloc.2 + .line 9,9 : 8,32 '' IL_0013: ldc.i4.0 IL_0014: stloc.3 IL_0015: br.s IL_0028 + .line 10,10 : 12,26 '' IL_0017: ldloc.1 IL_0018: ldloc.2 IL_0019: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -661,10 +670,12 @@ IL_0025: ldc.i4.1 IL_0026: add IL_0027: stloc.3 + .line 9,9 : 21,29 '' IL_0028: ldloc.3 IL_0029: ldc.i4 0x989681 IL_002e: blt.s IL_0017 + .line 11,11 : 8,9 '' IL_0030: ldloc.0 IL_0031: ret } // end of method EqualsMicroPerfAndCodeGenerationTests::f6 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.netfx4.bsl index 4d58b633bb9..3b4883d340e 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.netfx4.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000AB0 Length: 0x0000058F } .module Equals09.dll -// MVID: {56DBF22A-0759-46D9-A745-03832AF2DB56} +// MVID: {56DD23D1-0759-46D9-A745-0383D123DD56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x022D0000 +// Image base: 0x00DE0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -265,6 +265,8 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 4,4 : 10,13 'E:\\Documents\\GitHub\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Equals09.fsx' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -286,6 +288,7 @@ [3] int32 V_3, [4] int32 V_4, [5] int32 V_5) + .line 4,4 : 10,13 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Equals09/EqualsMicroPerfAndCodeGenerationTests/Key @@ -435,6 +438,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 4,4 : 10,13 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -826,6 +830,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 + .line 5,5 : 10,26 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -852,6 +857,7 @@ [8] class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key V_8, [9] class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key V_9, [10] int32 V_10) + .line 5,5 : 10,26 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys @@ -1039,6 +1045,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 5,5 : 10,26 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -1258,9 +1265,11 @@ [1] class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys key1, [2] class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys key2, [3] int32 i) + .line 7,7 : 8,29 '' IL_0000: nop IL_0001: ldc.i4.0 IL_0002: stloc.0 + .line 8,8 : 8,65 '' IL_0003: ldc.i4.1 IL_0004: ldc.i4.2 IL_0005: call class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key Equals09/EqualsMicroPerfAndCodeGenerationTests/Key::NewKey(int32, @@ -1278,6 +1287,7 @@ IL_001d: call class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::NewKeyWithInnerKeys(class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key, class [mscorlib]System.Tuple`2) IL_0022: stloc.1 + .line 9,9 : 8,65 '' IL_0023: ldc.i4.1 IL_0024: ldc.i4.2 IL_0025: call class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key Equals09/EqualsMicroPerfAndCodeGenerationTests/Key::NewKey(int32, @@ -1295,10 +1305,12 @@ IL_003d: call class Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys Equals09/EqualsMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::NewKeyWithInnerKeys(class Equals09/EqualsMicroPerfAndCodeGenerationTests/Key, class [mscorlib]System.Tuple`2) IL_0042: stloc.2 + .line 10,10 : 8,32 '' IL_0043: ldc.i4.0 IL_0044: stloc.3 IL_0045: br.s IL_0058 + .line 11,11 : 12,30 '' IL_0047: ldloc.1 IL_0048: ldloc.2 IL_0049: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -1309,6 +1321,7 @@ IL_0055: ldc.i4.1 IL_0056: add IL_0057: stloc.3 + .line 10,10 : 21,29 '' IL_0058: ldloc.3 IL_0059: ldc.i4 0x989681 IL_005e: blt.s IL_0047 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.netfx4.bsl index bf1a7a960af..3531b818563 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.netfx4.bsl @@ -36,13 +36,13 @@ // Offset: 0x000008A0 Length: 0x0000068C } .module Hash09.dll -// MVID: {56DBF20C-9642-77DB-A745-03830CF2DB56} +// MVID: {56DD2422-9642-77DB-A745-03832224DD56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00F30000 +// Image base: 0x00C80000 // =============== CLASS MEMBERS DECLARATION =================== @@ -256,6 +256,8 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 16 (0x10) .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 4,4 : 10,20 'E:\\Documents\\GitHub\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash09.fsx' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -278,6 +280,7 @@ [3] int32 V_3, [4] !a V_4, [5] !a V_5) + .line 4,4 : 10,20 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1 @@ -429,6 +432,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 4,4 : 10,20 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -632,11 +636,13 @@ .maxstack 4 .locals init ([0] int32 i, [1] int32 V_1) + .line 7,7 : 8,32 '' IL_0000: nop IL_0001: ldc.i4.0 IL_0002: stloc.0 IL_0003: br.s IL_001b + .line 8,8 : 12,44 '' IL_0005: ldc.i4.1 IL_0006: ldc.i4.2 IL_0007: call class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1 class Hash09/HashMicroPerfAndCodeGenerationTests/GenericKey`1::NewGenericKey(!0, @@ -648,6 +654,7 @@ IL_0018: ldc.i4.1 IL_0019: add IL_001a: stloc.0 + .line 7,7 : 21,29 '' IL_001b: ldloc.0 IL_001c: ldc.i4 0x989681 IL_0021: blt.s IL_0005 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.netfx4.bsl index 3a0db271e58..f0345f4d871 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.netfx4.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000AA8 Length: 0x00000589 } .module Hash12.dll -// MVID: {56DBF207-9661-796E-A745-038307F2DB56} +// MVID: {56DD478C-9661-796E-A745-03838C47DD56} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x024C0000 +// Image base: 0x00BC0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -265,6 +265,8 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 4,4 : 10,13 'E:\\Documents\\GitHub\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash12.fsx' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -286,6 +288,7 @@ [3] int32 V_3, [4] int32 V_4, [5] int32 V_5) + .line 4,4 : 10,13 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Hash12/HashMicroPerfAndCodeGenerationTests/Key @@ -435,6 +438,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 4,4 : 10,13 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -826,6 +830,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 + .line 5,5 : 10,26 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -852,6 +857,7 @@ [8] class Hash12/HashMicroPerfAndCodeGenerationTests/Key V_8, [9] class Hash12/HashMicroPerfAndCodeGenerationTests/Key V_9, [10] int32 V_10) + .line 5,5 : 10,26 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys @@ -1039,6 +1045,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 5,5 : 10,26 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -1257,6 +1264,7 @@ .locals init ([0] class Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys key, [1] int32 i, [2] int32 V_2) + .line 8,8 : 8,64 '' IL_0000: nop IL_0001: ldc.i4.1 IL_0002: ldc.i4.2 @@ -1275,10 +1283,12 @@ IL_001b: call class Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::NewKeyWithInnerKeys(class Hash12/HashMicroPerfAndCodeGenerationTests/Key, class [mscorlib]System.Tuple`2) IL_0020: stloc.0 + .line 9,9 : 8,32 '' IL_0021: ldc.i4.0 IL_0022: stloc.1 IL_0023: br.s IL_0035 + .line 10,10 : 12,30 '' IL_0025: ldloc.0 IL_0026: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityERComparer() IL_002b: callvirt instance int32 Hash12/HashMicroPerfAndCodeGenerationTests/KeyWithInnerKeys::GetHashCode(class [mscorlib]System.Collections.IEqualityComparer) @@ -1287,6 +1297,7 @@ IL_0032: ldc.i4.1 IL_0033: add IL_0034: stloc.1 + .line 9,9 : 21,29 '' IL_0035: ldloc.1 IL_0036: ldc.i4 0x989681 IL_003b: blt.s IL_0025