Skip to content

Commit 4ec5f18

Browse files
committed
@wip adding types to SmallMap
1 parent 42d990d commit 4ec5f18

File tree

3 files changed

+80
-264
lines changed

3 files changed

+80
-264
lines changed

src/FastExpressionCompiler/ImTools.cs

Lines changed: 32 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -945,96 +945,6 @@ public ref TEntry AddKeyAndGetEntryRef(K key, int index)
945945
}
946946
}
947947

948-
// todo: @perf optimize with SIMD, ILP, loop-unrolling, etc.
949-
/// <summary>Lookup for the K in the TStackEntries, first by calculating it hash with TEq and searching the hash in the TStackHashes</summary>
950-
public static ref TEntry TryGetEntryRef_loop<K, TEntry, TEq, TStackHashes, TStackEntries>(
951-
this ref TStackEntries entries, ref TStackHashes hashes, K key, out bool found,
952-
TEq eq = default, Use<TEntry> _ = default)
953-
where TEntry : struct, IEntry<K>
954-
where TEq : struct, IEq<K>
955-
where TStackHashes : struct, IStack<int, TStackHashes>
956-
where TStackEntries : struct, IStack<TEntry, TStackEntries>
957-
{
958-
Debug.Assert(hashes.Capacity == entries.Capacity,
959-
"Expecting that the hashes and entries stacks have the same capacity");
960-
961-
var hash = eq.GetHashCode(key);
962-
963-
for (var i = 0; i < hashes.Capacity; ++i)
964-
{
965-
var h = hashes.GetSurePresentItemRef(i);
966-
if (h == hash)
967-
{
968-
ref var entry = ref entries.GetSurePresentItemRef(i);
969-
if (found = eq.Equals(entry.Key, key))
970-
return ref entry;
971-
}
972-
}
973-
974-
found = false;
975-
return ref RefTools<TEntry>.GetNullRef();
976-
}
977-
978-
/// <summary>Lookup for the K in the TStackEntries, first by calculating it hash with TEq and searching the hash in the TStackHashes</summary>
979-
public static ref TEntry TryGetEntryRef_ILP<K, TEntry, TEq, TStackHashes, TStackEntries, TCap>(
980-
this ref TStackEntries entries, ref TStackHashes hashes, K key, out bool found,
981-
TEq eq = default, TCap cap = default, Use<TEntry> _ = default)
982-
where TEntry : struct, IEntry<K>
983-
where TEq : struct, IEq<K>
984-
where TStackHashes : struct, IStack<int, TCap, TStackHashes>
985-
where TStackEntries : struct, IStack<TEntry, TCap, TStackEntries>
986-
where TCap : struct, ISize4Plus
987-
{
988-
var hash = eq.GetHashCode(key);
989-
990-
for (var i = 0; i < cap.Size; i += 4)
991-
{
992-
ref var h0 = ref hashes.GetSurePresentItemRef(i);
993-
ref var h1 = ref hashes.GetSurePresentItemRef(i + 1);
994-
ref var h2 = ref hashes.GetSurePresentItemRef(i + 2);
995-
ref var h3 = ref hashes.GetSurePresentItemRef(i + 3);
996-
997-
var match0 = h0 == hash;
998-
var match1 = h1 == hash;
999-
var match2 = h2 == hash;
1000-
var match3 = h3 == hash;
1001-
1002-
if (!(match0 | match1 | match2 | match3))
1003-
continue;
1004-
1005-
if (match0)
1006-
{
1007-
ref var entry0 = ref entries.GetSurePresentItemRef(i);
1008-
if (found = eq.Equals(entry0.Key, key))
1009-
return ref entry0;
1010-
}
1011-
1012-
if (match1)
1013-
{
1014-
ref var entry1 = ref entries.GetSurePresentItemRef(i + 1);
1015-
if (found = eq.Equals(entry1.Key, key))
1016-
return ref entry1;
1017-
}
1018-
1019-
if (match2)
1020-
{
1021-
ref var entry2 = ref entries.GetSurePresentItemRef(i + 2);
1022-
if (found = eq.Equals(entry2.Key, key))
1023-
return ref entry2;
1024-
}
1025-
1026-
if (match3)
1027-
{
1028-
ref var entry3 = ref entries.GetSurePresentItemRef(i + 3);
1029-
if (found = eq.Equals(entry3.Key, key))
1030-
return ref entry3;
1031-
}
1032-
}
1033-
1034-
found = false;
1035-
return ref RefTools<TEntry>.GetNullRef();
1036-
}
1037-
1038948
/// <summary>Lookup for the K in the TStackEntries, first by calculating it hash with TEq and searching the hash in the TStackHashes</summary>
1039949
public static ref TEntry TryGetEntryRef<K, TEntry, TEq, TCap, TStackHashes, TStackEntries>(
1040950
this ref TStackEntries entries, ref TStackHashes hashes, K key, out bool found,
@@ -1078,67 +988,14 @@ public static ref TEntry TryGetEntryRef<K, TEntry, TEq, TCap, TStackHashes, TSta
1078988
}
1079989
#endif
1080990

1081-
if (cap.Size >= 4)
1082-
{
1083-
for (var i = 0; i < hashes.Capacity; i += 4)
1084-
{
1085-
ref var h0 = ref hashes.GetSurePresentItemRef(i);
1086-
ref var h1 = ref hashes.GetSurePresentItemRef(i + 1);
1087-
ref var h2 = ref hashes.GetSurePresentItemRef(i + 2);
1088-
ref var h3 = ref hashes.GetSurePresentItemRef(i + 3);
1089-
1090-
var match0 = h0 == hash;
1091-
var match1 = h1 == hash;
1092-
var match2 = h2 == hash;
1093-
var match3 = h3 == hash;
1094-
1095-
if (!(match0 | match1 | match2 | match3))
1096-
continue;
1097-
1098-
if (match0)
1099-
{
1100-
ref var entry0 = ref entries.GetSurePresentItemRef(i);
1101-
if (found = eq.Equals(entry0.Key, key))
1102-
return ref entry0;
1103-
}
1104-
1105-
if (match1)
1106-
{
1107-
ref var entry1 = ref entries.GetSurePresentItemRef(i + 1);
1108-
if (found = eq.Equals(entry1.Key, key))
1109-
return ref entry1;
1110-
}
1111-
1112-
if (match2)
1113-
{
1114-
ref var entry2 = ref entries.GetSurePresentItemRef(i + 2);
1115-
if (found = eq.Equals(entry2.Key, key))
1116-
return ref entry2;
1117-
}
1118-
1119-
if (match3)
1120-
{
1121-
ref var entry3 = ref entries.GetSurePresentItemRef(i + 3);
1122-
if (found = eq.Equals(entry3.Key, key))
1123-
return ref entry3;
1124-
}
1125-
}
1126-
}
1127-
else
991+
for (var i = 0; i < hashes.Capacity; ++i)
1128992
{
1129-
ref var h0 = ref hashes.GetSurePresentItemRef(0);
1130-
ref var h1 = ref hashes.GetSurePresentItemRef(1);
1131-
if (h0 == hash)
1132-
{
1133-
ref var entry0 = ref entries.GetSurePresentItemRef(0);
1134-
if (found = eq.Equals(entry0.Key, key))
1135-
return ref entry0;
1136-
}
1137-
if (h1 == hash)
993+
var h = hashes.GetSurePresentItemRef(i);
994+
if (h == hash)
1138995
{
1139-
ref var entry1 = ref entries.GetSurePresentItemRef(1);
1140-
if (found = eq.Equals(entry1.Key, key))
1141-
return ref entry1;
996+
ref var entry = ref entries.GetSurePresentItemRef(i);
997+
if (found = eq.Equals(entry.Key, key))
998+
return ref entry;
1142999
}
11431000
}
11441001

@@ -1150,30 +1007,36 @@ public static ref TEntry TryGetEntryRef<K, TEntry, TEq, TCap, TStackHashes, TSta
11501007
/// or adds a new entry (found == false) and returns it.Value by ref.
11511008
/// So the method always return a non-null ref to the value, either existing or added</summary>
11521009
[MethodImpl((MethodImplOptions)256)]
1153-
public static ref V AddOrGetValueRef<K, V, TEq, TStackEntries, TEntries>(
1154-
this ref SmallMap<K, Entry<K, V>, TEq, TStackEntries, TEntries> map, K key, out bool found)
1010+
public static ref V AddOrGetValueRef<K, V, TEq, TStackCap, TStackHashes, TStackEntries, TEntries>(
1011+
this ref SmallMap<K, Entry<K, V>, TEq, TStackCap, TStackHashes, TStackEntries, TEntries> map, K key, out bool found)
11551012
where TEq : struct, IEq<K>
1156-
where TStackEntries : struct, IStack<Entry<K, V>, TStackEntries>
1013+
where TStackCap : struct, ISize2Plus
1014+
where TStackHashes : struct, IStack<int, TStackCap, TStackHashes>
1015+
where TStackEntries : struct, IStack<Entry<K, V>, TStackCap, TStackEntries>
11571016
where TEntries : struct, IEntries<K, Entry<K, V>, TEq> =>
11581017
ref map.AddOrGetEntryRef(key, out found).Value;
11591018

11601019
/// <summary>Adds an entry for sure absent key.
11611020
/// Provides the performance in scenarios where you look for the present key, and using it, and if ABSENT then add the new one.
11621021
/// So this method optimized NOT to look for the present item for the second time</summary>
11631022
[MethodImpl((MethodImplOptions)256)]
1164-
public static ref V AddSureAbsentDefaultAndGetRef<K, V, TEq, TStackEntries, TEntries>(
1165-
this ref SmallMap<K, Entry<K, V>, TEq, TStackEntries, TEntries> map, K key)
1023+
public static ref V AddSureAbsentDefaultAndGetRef<K, V, TEq, TStackCap, TStackHashes, TStackEntries, TEntries>(
1024+
this ref SmallMap<K, Entry<K, V>, TEq, TStackCap, TStackHashes, TStackEntries, TEntries> map, K key)
11661025
where TEq : struct, IEq<K>
1167-
where TStackEntries : struct, IStack<Entry<K, V>, TStackEntries>
1026+
where TStackCap : struct, ISize2Plus
1027+
where TStackHashes : struct, IStack<int, TStackCap, TStackHashes>
1028+
where TStackEntries : struct, IStack<Entry<K, V>, TStackCap, TStackEntries>
11681029
where TEntries : struct, IEntries<K, Entry<K, V>, TEq>
11691030
=> ref map.AddSureAbsentDefaultEntryAndGetRef(key).Value;
11701031

11711032
/// <summary>Lookups for the stored entry by key. Returns the ref to the found entry.Value or the null ref</summary>
11721033
[MethodImpl((MethodImplOptions)256)]
1173-
public static ref V TryGetValueRef<K, V, TEq, TStackEntries, TEntries>(
1174-
this ref SmallMap<K, Entry<K, V>, TEq, TStackEntries, TEntries> map, K key, out bool found)
1034+
public static ref V TryGetValueRef<K, V, TEq, TStackCap, TStackHashes, TStackEntries, TEntries>(
1035+
this ref SmallMap<K, Entry<K, V>, TEq, TStackCap, TStackHashes, TStackEntries, TEntries> map, K key, out bool found)
11751036
where TEq : struct, IEq<K>
1176-
where TStackEntries : struct, IStack<Entry<K, V>, TStackEntries>
1037+
where TStackCap : struct, ISize2Plus
1038+
where TStackHashes : struct, IStack<int, TStackCap, TStackHashes>
1039+
where TStackEntries : struct, IStack<Entry<K, V>, TStackCap, TStackEntries>
11771040
where TEntries : struct, IEntries<K, Entry<K, V>, TEq>
11781041
{
11791042
ref var e = ref map.TryGetEntryRef(key, out found);
@@ -1198,10 +1061,12 @@ public static ref V TryGetValueRef<K, V, TEq, TStackEntries, TEntries>(
11981061
///
11991062
/// </summary>
12001063
[DebuggerDisplay("{Count} of {_e0}, {_e1}, {_e2}, {_e3}, ...")]
1201-
public struct SmallMap<K, TEntry, TEq, TStackEntries, TEntries>
1064+
public struct SmallMap<K, TEntry, TEq, TStackCap, TStackHashes, TStackEntries, TEntries>
12021065
where TEntry : struct, IEntry<K>
12031066
where TEq : struct, IEq<K>
1204-
where TStackEntries : struct, IStack<TEntry, TStackEntries>
1067+
where TStackCap : struct, ISize2Plus
1068+
where TStackHashes : struct, IStack<int, TStackCap, TStackHashes>
1069+
where TStackEntries : struct, IStack<TEntry, TStackCap, TStackEntries>
12051070
where TEntries : struct, IEntries<K, TEntry, TEq>
12061071
{
12071072
internal byte _capacityBitShift;
@@ -1219,6 +1084,7 @@ public struct SmallMap<K, TEntry, TEq, TStackEntries, TEntries>
12191084
internal TEntries _entries;
12201085
#pragma warning restore IDE0044
12211086
#pragma warning disable CS0649 // Field 'SmallMap<K, V, TEq, TStack, TEntries>.Stack' is never assigned to, and will always have its default value
1087+
internal TStackHashes StackHashes;
12221088
internal TStackEntries StackEntries;
12231089
#pragma warning restore CS0649
12241090

@@ -1614,42 +1480,42 @@ internal int ResizeHashes(int indexMask)
16141480
public struct SmallMap4<K, V, TEq>() where TEq : struct, IEq<K>
16151481
{
16161482
/// <summary>Map with 4 elements on stack and entries baked by the single array</summary>
1617-
public SmallMap<K, SmallMap.Entry<K, V>, TEq, Stack4<SmallMap.Entry<K, V>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K, V>, TEq>> Map;
1483+
public SmallMap<K, SmallMap.Entry<K, V>, TEq, Size4, Stack4<int>, Stack4<SmallMap.Entry<K, V>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K, V>, TEq>> Map;
16181484
}
16191485

16201486
/// <summary>Holds the Map with 8 items on stack. Minimizes the number of type arguments required to be specified</summary>
16211487
public struct SmallMap8<K, V, TEq>() where TEq : struct, IEq<K>
16221488
{
16231489
/// <summary>Map with 8 elements on stack and entries baked by the single array</summary>
1624-
public SmallMap<K, SmallMap.Entry<K, V>, TEq, Stack8<SmallMap.Entry<K, V>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K, V>, TEq>> Map;
1490+
public SmallMap<K, SmallMap.Entry<K, V>, TEq, Size8, Stack8<int>, Stack8<SmallMap.Entry<K, V>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K, V>, TEq>> Map;
16251491
}
16261492

16271493
/// <summary>Holds the Map with 16 items on stack. Minimizes the number of type arguments required to be specified</summary>
16281494
public struct SmallMap16<K, V, TEq>() where TEq : struct, IEq<K>
16291495
{
16301496
/// <summary>Map with 16 elements on stack and entries baked by the single array</summary>
1631-
public SmallMap<K, SmallMap.Entry<K, V>, TEq, Stack16<SmallMap.Entry<K, V>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K, V>, TEq>> Map;
1497+
public SmallMap<K, SmallMap.Entry<K, V>, TEq, Size16, Stack16<int>, Stack16<SmallMap.Entry<K, V>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K, V>, TEq>> Map;
16321498
}
16331499

16341500
/// <summary>Holds the Set with 4 items on stack. Minimizes the number of type arguments required to be specified</summary>
16351501
public struct SmallSet4<K, TEq>() where TEq : struct, IEq<K>
16361502
{
16371503
/// <summary>Set with 4 keys on stack and entries baked by the single array</summary>
1638-
public SmallMap<K, SmallMap.Entry<K>, TEq, Stack4<SmallMap.Entry<K>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K>, TEq>> Set;
1504+
public SmallMap<K, SmallMap.Entry<K>, TEq, Size4, Stack4<int>, Stack4<SmallMap.Entry<K>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K>, TEq>> Set;
16391505
}
16401506

16411507
/// <summary>Holds the Set with 8 items on stack. Minimizes the number of type arguments required to be specified</summary>
16421508
public struct SmallSet8<K, TEq>() where TEq : struct, IEq<K>
16431509
{
16441510
/// <summary>Set with 8 keys on stack and entries baked by the single array</summary>
1645-
public SmallMap<K, SmallMap.Entry<K>, TEq, Stack8<SmallMap.Entry<K>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K>, TEq>> Set;
1511+
public SmallMap<K, SmallMap.Entry<K>, TEq, Size8, Stack8<int>, Stack8<SmallMap.Entry<K>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K>, TEq>> Set;
16461512
}
16471513

16481514
/// <summary>Holds the Set with 16 items on stack. Minimizes the number of type arguments required to be specified</summary>
16491515
public struct SmallSet16<K, TEq>() where TEq : struct, IEq<K>
16501516
{
16511517
/// <summary>Set with 16 keys on stack and entries baked by the single array</summary>
1652-
public SmallMap<K, SmallMap.Entry<K>, TEq, Stack16<SmallMap.Entry<K>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K>, TEq>> Set;
1518+
public SmallMap<K, SmallMap.Entry<K>, TEq, Size16, Stack16<int>, Stack16<SmallMap.Entry<K>>, SmallMap.SingleArrayEntries<K, SmallMap.Entry<K>, TEq>> Set;
16531519
}
16541520

16551521
#nullable restore

0 commit comments

Comments
 (0)