public static unsafe Object CompilerAllocateGenerational (VTable vtable, Thread currentThread, UIntPtr bytes, uint alignment) { VTable.Assert((alignment == 4) || ((alignment == 8) && (UIntPtr.Size == 8)) || ((alignment == 8) && (PreHeader.Size == 4)), "Unsupported object layout"); VTable.Assert(UIntPtr.Size == PreHeader.Size, "Unsupported preheader size"); VTable.Assert (Util.IsAligned((uint)PreHeader.Size + (uint)PostHeader.Size, alignment), "Unsupported header sizes"); UIntPtr preHeaderAddr = MixinThread(currentThread).bumpAllocator.allocPtr; // allocPtr is only needed when alignment needs to be checked. It // stores the beginning of the region to be allocation including // a possible alignment token. UIntPtr allocPtr = UIntPtr.Zero; if ((alignment == 8) && (UIntPtr.Size == 4)) { allocPtr = preHeaderAddr; preHeaderAddr = Util.Pad(preHeaderAddr, (UIntPtr)alignment); } UIntPtr bound = preHeaderAddr + bytes; UIntPtr limitPtr = MixinThread(currentThread).bumpAllocator.zeroedLimit; if (bound <= limitPtr) { if ((alignment == 8) && (UIntPtr.Size == 4)) { // Store alignment token at allocPtr. This will be where an // alignment token should go if 'preHeaderAddr' was // bumped... Allocator.WriteAlignment(allocPtr); // ... or the alignment token is where the object header // should be. This code zeroes the object header regardless // and avoids a branch in this fast path. *(UIntPtr *)preHeaderAddr = UIntPtr.Zero; } MixinThread(currentThread).bumpAllocator.allocPtr = bound; UIntPtr objAddr = preHeaderAddr + PreHeader.Size; Object obj = Magic.fromAddress(objAddr); obj.vtable = vtable; return(obj); } return(GC.AllocateObjectNoInline(vtable, currentThread)); }