Skip to content

Instantly share code, notes, and snippets.

@Mrnikbobjeff
Last active September 21, 2020 10:57
Show Gist options
  • Save Mrnikbobjeff/44962407589d9651fc9051c57f09c020 to your computer and use it in GitHub Desktop.
Save Mrnikbobjeff/44962407589d9651fc9051c57f09c020 to your computer and use it in GitHub Desktop.
quick hacky way to find null references
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