Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions src/Compiler/AbstractIL/ilwrite.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3058,23 +3058,27 @@ and GetModuleAsRow (cenv: cenv) (modul: ILModuleDef) =
Guid 0 |]


let rowElemCompare (e1: RowElement) (e2: RowElement) =
let c = compare e1.Val e2.Val
if c <> 0 then c else
compare e1.Tag e2.Tag

let TableRequiresSorting tab =
List.memAssoc tab sortedTableInfo

let SortTableRows tab (rows: GenericRow[]) =
assert (TableRequiresSorting tab)
let col = List.assoc tab sortedTableInfo
rows
// This needs to be a stable sort, so we use List.sortWith
|> Array.toList
|> List.sortWith (fun r1 r2 -> rowElemCompare r1[col] r2[col])
|> Array.ofList
//|> Array.map SharedRow
let n = rows.Length
if n <= 1 then
rows
else
System.Diagnostics.Debug.Assert(n <= 0xFFFFFF, "metadata table exceeds the 2^24-1 RID limit")
// Pack the key column per row into one int64: [Val:31 @ bit32][Tag:8 @ bit24][originalPos:24 @ bit0].
// Sorting the int64[] then orders by (Val, Tag, pos) = a stable (Val, Tag) sort.
let keys =
[| for i in 0 .. n - 1 ->
let e = rows[i][col]
((int64 e.Val) <<< 32) ||| ((int64 e.Tag) <<< 24) ||| int64 i |]

System.Array.Sort keys
let result = [| for key in keys -> rows[int (key &&& 0xFFFFFFL)] |]
result

let GenModule (cenv : cenv) (modul: ILModuleDef) =
let midx = AddUnsharedRow cenv TableNames.Module (GetModuleAsRow cenv modul)
Expand Down
8 changes: 5 additions & 3 deletions src/Compiler/Checking/TypeHierarchy.fs
Original file line number Diff line number Diff line change
Expand Up @@ -233,19 +233,21 @@ type AllowMultiIntfInstantiations = Yes | No
let FoldHierarchyOfTypeAux followInterfaces allowMultiIntfInst skipUnref visitor g amap m ty acc =
let rec loop ndeep ty (visitedTycon, visited: TyconRefMultiMap<_>, acc as state) =

let tcrefOpt = tryTcrefOfAppTy g ty

let seenThisTycon =
match tryTcrefOfAppTy g ty with
match tcrefOpt with
| ValueSome tcref -> Set.contains tcref.Stamp visitedTycon
| _ -> false

// Do not visit the same type twice. Could only be doing this if we've seen this tycon
if seenThisTycon && List.exists (typeEquiv g ty) (visited.Find (tcrefOfAppTy g ty)) then state else
if seenThisTycon && (match tcrefOpt with ValueSome tcref -> List.exists (typeEquiv g ty) (visited.Find tcref) | ValueNone -> false) then state else

// Do not visit the same tycon twice, e.g. I<int> and I<string>, collect I<int> only, unless directed to allow this
if seenThisTycon && allowMultiIntfInst = AllowMultiIntfInstantiations.No then state else

let state =
match tryTcrefOfAppTy g ty with
match tcrefOpt with
| ValueSome tcref ->
let visitedTycon = Set.add tcref.Stamp visitedTycon
visitedTycon, visited.Add (tcref, ty), acc
Expand Down
13 changes: 6 additions & 7 deletions src/Compiler/CodeGen/IlxGen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8037,14 +8037,13 @@ and GenDecisionTreeAndTargets cenv cgbuf stackAtTargets eenv tree targets sequel
(IntMap.empty ())
sequel
(fun targetInfos ->
let sortedTargetInfos =
targetInfos
|> Seq.sortBy (fun (KeyValue(targetIdx, _)) -> targetIdx)
|> Seq.filter (fun (KeyValue(_, (_, isTargetPostponed))) -> isTargetPostponed)
|> Seq.map (fun (KeyValue(_, (targetInfo, _))) -> targetInfo)
|> List.ofSeq
// targetInfos is an IntMap; IntMap.fold visits keys in descending order, so prepending
// yields ascending directly - no sort (old Seq.sortBy was redundant) and no List.rev.
let postponedTargetInfos =
(targetInfos, [])
||> IntMap.fold (fun _ (targetInfo, isTargetPostponed) acc -> if isTargetPostponed then targetInfo :: acc else acc)

GenPostponedDecisionTreeTargets cenv cgbuf sortedTargetInfos stackAtTargets sequel contf)
GenPostponedDecisionTreeTargets cenv cgbuf postponedTargetInfos stackAtTargets sequel contf)

and GenPostponedDecisionTreeTargets cenv cgbuf targetInfos stackAtTargets sequel contf =
match targetInfos with
Expand Down
56 changes: 26 additions & 30 deletions src/Compiler/TypedTree/TypedTreeBasics.fs
Original file line number Diff line number Diff line change
Expand Up @@ -254,47 +254,43 @@ let combineNullness (nullnessOrig: Nullness) (nullnessNew: Nullness) =

let nullnessEquiv (nullnessOrig: Nullness) (nullnessNew: Nullness) = LanguagePrimitives.PhysicalEquality nullnessOrig nullnessNew

/// Matches only when combining `nullnessNew` into the original nullness actually changes it (physically).
/// A failed match means "unchanged" — callers fall through and reuse the original TType.
[<return: Struct>]
let inline (|CombinedNullness|_|) (nullnessNew: Nullness) (nullnessOrig: Nullness) =
let nullnessAfter = combineNullness nullnessOrig nullnessNew
if nullnessEquiv nullnessAfter nullnessOrig then ValueNone else ValueSome nullnessAfter

let tryAddNullnessToTy nullnessNew (ty:TType) =
let inline (|NullnessWouldChangeTo|_|) orig = (|CombinedNullness|_|) nullnessNew orig
match ty with
| TType_var (tp, nullnessOrig) ->
let nullnessAfter = combineNullness nullnessOrig nullnessNew
if nullnessEquiv nullnessAfter nullnessOrig then
Some ty
else
Some (TType_var (tp, nullnessAfter))
| TType_app (tcr, tinst, nullnessOrig) ->
let nullnessAfter = combineNullness nullnessOrig nullnessNew
if nullnessEquiv nullnessAfter nullnessOrig then
Some ty
else
Some (TType_app (tcr, tinst, nullnessAfter))
| TType_ucase _ -> None
| TType_tuple _ -> None
| TType_anon _ -> None
| TType_fun (d, r, nullnessOrig) ->
let nullnessAfter = combineNullness nullnessOrig nullnessNew
if nullnessEquiv nullnessAfter nullnessOrig then
Some ty
else
Some (TType_fun (d, r, nullnessAfter))
| TType_forall _ -> None
| TType_var (tp, NullnessWouldChangeTo after) -> Some (TType_var (tp, after))
| TType_app (tcr, tinst, NullnessWouldChangeTo after) -> Some (TType_app (tcr, tinst, after))
| TType_fun (d, r, NullnessWouldChangeTo after) -> Some (TType_fun (d, r, after))
| TType_var _
| TType_app _
| TType_fun _ -> Some ty
| TType_ucase _
| TType_tuple _
| TType_anon _
| TType_forall _
| TType_measure _ -> None

/// Matches a `TyconRef` whose definition is a struct/enum value type (which never carries outer nullness).
let inline (|StructTyconRef|_|) (tcref: TyconRef) = tcref.IsStructOrEnumTycon

let addNullnessToTy (nullness: Nullness) (ty:TType) =
match nullness with
| Nullness.Known NullnessInfo.WithoutNull -> ty
| Nullness.KnownFromConstructor -> ty
| Nullness.Variable nv when nv.IsFullySolved && nv.TryEvaluate() = ValueSome NullnessInfo.WithoutNull -> ty
| _ ->
let inline (|NullnessWouldChangeTo|_|) orig = (|CombinedNullness|_|) nullness orig
match ty with
| TType_var (tp, nullnessOrig) -> TType_var (tp, combineNullness nullnessOrig nullness)
| TType_app (tcr, tinst, nullnessOrig) ->
let tycon = tcr.Deref
if tycon.IsStructRecordOrUnionTycon || tycon.IsStructOrEnumTycon then
ty
else
TType_app (tcr, tinst, combineNullness nullnessOrig nullness)
| TType_fun (d, r, nullnessOrig) -> TType_fun (d, r, combineNullness nullnessOrig nullness)
| TType_var (tp, NullnessWouldChangeTo after) -> TType_var (tp, after)
| TType_app (StructTyconRef, _, _) -> ty
| TType_app (tcr, tinst, NullnessWouldChangeTo after) -> TType_app (tcr, tinst, after)
| TType_fun (d, r, NullnessWouldChangeTo after) -> TType_fun (d, r, after)
| _ -> ty

let rec stripTyparEqnsAux nullness0 canShortcut ty =
Expand Down
4 changes: 1 addition & 3 deletions src/Compiler/TypedTree/TypedTreeOps.ExprConstruction.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1055,9 +1055,7 @@ module internal TypeTesters =
| ValueSome tcref -> tcref.Deref.IsStructRecordOrUnionTycon
| _ -> false

let isStructTyconRef (tcref: TyconRef) =
let tycon = tcref.Deref
tycon.IsStructRecordOrUnionTycon || tycon.IsStructOrEnumTycon
let isStructTyconRef (tcref: TyconRef) = tcref.IsStructOrEnumTycon

let isStructTy g ty =
match tryTcrefOfAppTy g ty with
Expand Down
Loading