Last active
September 21, 2020 10:57
-
-
Save Mrnikbobjeff/44962407589d9651fc9051c57f09c020 to your computer and use it in GitHub Desktop.
quick hacky way to find null references
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.CompilerServices; | |
using System.Runtime.Intrinsics; | |
using System.Runtime.Intrinsics.X86; | |
using System.Threading; | |
namespace ObjectPools | |
{ | |
public class FastRefPool<T> where T : class | |
{ | |
public struct Element | |
{ | |
public T Value; | |
} | |
public readonly Element[] _items; | |
private readonly long[] itemsRef; | |
private readonly Func<T> _factory; | |
public ObjectPoolFast(Func<T> factory, int size) | |
{ | |
_factory = factory; | |
_items = new Element[size]; | |
itemsRef = ReinterpretCast<Element[], long[]>(_items); | |
} | |
private T CreateInstance() | |
{ | |
var inst = _factory(); | |
return inst; | |
} | |
internal T Allocate() | |
{ | |
var items = _items; | |
T inst; | |
for (int i = 0; i < items.Length; i++) | |
{ | |
inst = items[i].Value; | |
if (inst != null) | |
{ | |
if (inst == Interlocked.CompareExchange(ref items[i].Value, null, inst)) | |
{ | |
goto gotInstance; | |
} | |
} | |
} | |
inst = CreateInstance(); | |
gotInstance: | |
return inst; | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
static unsafe TDest ReinterpretCast<TSource, TDest>(TSource source) | |
{ | |
var sourceRef = __makeref(source); | |
var dest = default(TDest); | |
var destRef = __makeref(dest); | |
*(IntPtr*)&destRef = *(IntPtr*)&sourceRef; | |
return __refvalue(destRef, TDest); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveOptimization)] | |
public unsafe int FindNullSimplifiedAsmAlignedNonTemporalUnrolledUnsafePinConstant() | |
{ | |
var items = _items; | |
var length = items.Length; | |
fixed (long* addrPtr = &itemsRef[0]) | |
{ | |
var aligned = (long*)(((ulong)addrPtr + 31UL) & ~31UL); | |
var pos = (((long)aligned) - ((long)addrPtr)); | |
if (pos != 0) | |
for (int w = 0; w < pos; w++) | |
if (addrPtr[w] == 0) | |
{ | |
return w; | |
} | |
int i = 0; //Have to check whether reusing pos creates different asm | |
const int vSizeLong = 4; | |
const int bSizeLong = 8; | |
var lengthWithoutBlockSize = length - bSizeLong; | |
for (; i < lengthWithoutBlockSize; i += bSizeLong) | |
{ | |
var v21 = Avx2.LoadAlignedVector256NonTemporal(aligned + i); | |
var v22 = Avx2.LoadAlignedVector256NonTemporal(aligned + i + vSizeLong); | |
var temp1 = Avx2.CompareEqual(v21, Vector256<long>.Zero).AsByte(); | |
var m1 = Avx2.MoveMask(temp1); | |
var temp2 = Avx2.CompareEqual(v22, Vector256<long>.Zero).AsByte(); | |
var m2 = Avx2.MoveMask(temp2); | |
if (m1 + m2 == 0) | |
continue; | |
if (m1 == 0) | |
{ | |
i += vSizeLong; | |
} | |
goto nullOrFound; | |
} | |
nullOrFound: | |
for (var x = i + (int)pos; x < length; x++) | |
{ | |
if (addrPtr[x] == 0) | |
{ | |
return x; | |
} | |
} | |
} | |
return -1; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment