internal static Object Allocate(VTable vtable, uint count) { UIntPtr numBytes = ObjectLayout.ArraySize(vtable, count); UIntPtr objectAddr = AllocateBlock(numBytes, vtable.baseAlignment); Array result = Magic.toArray(Magic.fromAddress(objectAddr)); #if REFERENCE_COUNTING_GC uint refState = vtable.isAcyclicRefType ? (ReferenceCountingCollector. acyclicFlagMask | 2) : 2; result.REF_STATE = refState & ~ReferenceCountingCollector.countingONFlagMask; #elif DEFERRED_REFERENCE_COUNTING_GC uint refState = vtable.isAcyclicRefType ? (DeferredReferenceCountingCollector. acyclicFlagMask | DeferredReferenceCountingCollector. markFlagMask) : DeferredReferenceCountingCollector. markFlagMask; result.REF_STATE = refState & ~DeferredReferenceCountingCollector.countingONFlagMask; #endif Barrier.BootstrapInitObject(result, vtable); result.InitializeVectorLength((int)count); return(result); }
public static void Initialize() { Object plcLinkObj = BootstrapMemory.Allocate(typeof(PLCLink)); firstPLCLink = (PLCLink *)(Magic.addressOf(plcLinkObj) + PostHeader.Size); plcListVtable = ((RuntimeType)typeof(PLCLink[])).classVtable; plcListChunkBytes = ObjectLayout.ArraySize(plcListVtable, plcListChunkLength); }
internal override Array AllocateVector(VTable vtable, int numElements, Thread currentThread) { UIntPtr numBytes = ObjectLayout.ArraySize(vtable, unchecked ((uint)numElements)); UIntPtr vectorAddr = AllocateObjectMemory(numBytes, vtable.baseAlignment, currentThread); Array result = Magic.toArray(Magic.fromAddress(vectorAddr)); CreateObject(result, vtable, currentThread); result.InitializeVectorLength(numElements); return(result); }
internal override Array AllocateVector(VTable vtable, int numElements, Thread currentThread) { Array result = base.AllocateVector(vtable, numElements, currentThread); if (VTable.enableGCProfiling) { ulong size = (ulong) ObjectLayout.ArraySize(vtable, unchecked ((uint)numElements)); RegisterNewObject(size); } return(result); }
public static unsafe void Initialize() { maxEntries = 1 << 16; VTable UIntPtrArrayVtable = ((RuntimeType)typeof(UIntPtr[])).classVtable; tableSize = ObjectLayout.ArraySize(UIntPtrArrayVtable, maxEntries); // Allocate a pool for ZCT BumpAllocator entryPool = new BumpAllocator(PageType.NonGC); UIntPtr memStart = MemoryManager.AllocateMemory(tableSize); entryPool.SetZeroedRange(memStart, tableSize); PageManager.SetStaticDataPages(memStart, tableSize); // Initialize ZCT zeroCountTable = (UIntPtr[]) DeferredReferenceCountingCollector. AllocateArray(ref entryPool, UIntPtrArrayVtable, tableSize); VTable.Assert(zeroCountTable != null, @"zeroCountTable != null"); *(uint *)(Magic.addressOf(zeroCountTable) + PostHeader.Size) = maxEntries; VTable.Assert(zeroCountTable.Length == maxEntries, @"zeroCountTable.Length == maxEntries"); // Build ZCT freeEntries list freeHead = 1; for (uint i = 1; i < maxEntries - 1; i++) { zeroCountTable[i] = (UIntPtr)(((i + 1) << 2) | 0x01); } zeroCountTable[maxEntries - 1] = (UIntPtr)0x01; zctGarbagePicker = (ZCTGarbagePicker)BootstrapMemory. Allocate(typeof(ZCTGarbagePicker)); }
UIntPtr VisitReferenceFieldsTemplate(ref ObjectDescriptor objDesc) { UIntPtr pointerTracking = objDesc.vtable.pointerTrackingMask; uint objectTag = (pointerTracking & 0xf); UIntPtr size; switch (objectTag) { case ObjectLayout.SPARSE_TAG: { UIntPtr *sparseObject = (UIntPtr *)objDesc.objectBase; size = ObjectLayout.ObjectSize(objDesc.vtable); pointerTracking >>= 4; while (pointerTracking != 0) { uint index = pointerTracking & 0xf; pointerTracking >>= 4; // The cast to int prevents C# from taking the // index * sizeof(UIntPtr) to long: UIntPtr *loc = sparseObject + (int)index; this.Filter(loc, ref objDesc); } break; } case ObjectLayout.DENSE_TAG: { // skip vtable int postHeaderSize = PostHeader.Size; UIntPtr *denseObject = (UIntPtr *) (objDesc.objectBase + postHeaderSize); size = ObjectLayout.ObjectSize(objDesc.vtable); pointerTracking >>= 4; while (pointerTracking != 0) { if ((pointerTracking & ((UIntPtr)0x1)) != 0) { this.Filter(denseObject, ref objDesc); } pointerTracking >>= 1; denseObject++; } break; } case ObjectLayout.PTR_VECTOR_TAG: { int postHeaderSize = PostHeader.Size; uint length = *(uint *)(objDesc.objectBase + postHeaderSize); size = ObjectLayout.ArraySize(objDesc.vtable, length); int preHeaderSize = PreHeader.Size; UIntPtr *elementAddress = (UIntPtr *) (objDesc.objectBase + objDesc.vtable.baseLength - preHeaderSize); for (uint i = 0; i < length; i++, elementAddress++) { this.Filter(elementAddress, ref objDesc); } break; } case ObjectLayout.OTHER_VECTOR_TAG: { int postHeaderSize = PostHeader.Size; uint length = *(uint *)(objDesc.objectBase + postHeaderSize); size = ObjectLayout.ArraySize(objDesc.vtable, length); if (objDesc.vtable.arrayOf == StructuralType.Struct) { // pretend the struct is boxed and account for the // presence of the vtable field VTable elementVTable = objDesc.vtable.arrayElementClass; UIntPtr elementMask = elementVTable.pointerTrackingMask; // A structure with no references will have a SPARSE // descriptor with no offset values. if (elementMask != (UIntPtr)ObjectLayout.SPARSE_TAG) { int preHeaderSize = PreHeader.Size; UIntPtr elementAddress = (objDesc.objectBase + objDesc.vtable.baseLength - preHeaderSize - postHeaderSize); int elementSize = objDesc.vtable.arrayElementSize; objDesc.vtable = elementVTable; for (uint i = 0; i < length; i++) { objDesc.objectBase = elementAddress; this.VisitReferenceFieldsTemplateNoInline(ref objDesc); elementAddress += elementSize; } } } break; } case ObjectLayout.PTR_ARRAY_TAG: { int postHeaderSize = PostHeader.Size; uint length = *(uint *)(objDesc.objectBase + postHeaderSize + sizeof(uint)); size = ObjectLayout.ArraySize(objDesc.vtable, length); int preHeaderSize = PreHeader.Size; UIntPtr *elementAddress = (UIntPtr *) (objDesc.objectBase + objDesc.vtable.baseLength - preHeaderSize); for (uint i = 0; i < length; i++, elementAddress++) { this.Filter(elementAddress, ref objDesc); } break; } case ObjectLayout.OTHER_ARRAY_TAG: { int postHeaderSize = PostHeader.Size; uint length = *(uint *)(objDesc.objectBase + postHeaderSize + sizeof(uint)); size = ObjectLayout.ArraySize(objDesc.vtable, length); if (objDesc.vtable.arrayOf == StructuralType.Struct) { // pretend the struct is boxed and account for the // presence of the PostHeader VTable elementVTable = objDesc.vtable.arrayElementClass; UIntPtr elementMask = elementVTable.pointerTrackingMask; // A structure with no references will have a SPARSE // descriptor with no offset values. if (elementMask != (UIntPtr)ObjectLayout.SPARSE_TAG) { int preHeaderSize = PreHeader.Size; int elementSize = objDesc.vtable.arrayElementSize; UIntPtr elementAddress = objDesc.objectBase + objDesc.vtable.baseLength - preHeaderSize - postHeaderSize; objDesc.vtable = elementVTable; for (uint i = 0; i < length; i++) { objDesc.objectBase = elementAddress; this.VisitReferenceFieldsTemplateNoInline(ref objDesc); elementAddress += elementSize; } } } break; } case ObjectLayout.STRING_TAG: { int postHeaderSize = PostHeader.Size; uint arrayLength = *(uint *)(objDesc.objectBase + postHeaderSize); size = ObjectLayout.StringSize(objDesc.vtable, arrayLength); break; } default: { // escape case VTable.Assert((objectTag & 0x1) == 0, "ReferenceVisitor: (objectTag & 0x1) == 0"); UIntPtr *largeObject = (UIntPtr *)objDesc.objectBase; size = ObjectLayout.ObjectSize(objDesc.vtable); int *pointerDescription = (int *)pointerTracking; int count = *pointerDescription; for (int i = 1; i <= count; i++) { UIntPtr *loc = largeObject + *(pointerDescription + i); this.Filter(loc, ref objDesc); } break; } } return(size); }
internal static unsafe bool AccumulateRCUpdates(String methodName, int methodIndex, uint maxIndex, AcctRecord rec) { VTable.Assert(RCCollector.ProfilingMode, @"RCCollector.ProfilingMode"); // Return if the page table hasn't been set up yet. if (PageTable.pageTableCount == UIntPtr.Zero) { return(false); } if (methods == null) { // Allocate up front storage for the accounting records. // // This is requisitioned directly from the memory // manager. Care should be taken to ensure that // AccumulateRCUpdates does not indirectly call // methods that may have compiler-inserted RC updates. VTable vtable = ((RuntimeType)typeof(AcctRecord[])).classVtable; UIntPtr size = ObjectLayout.ArraySize(vtable, maxIndex + 1); BumpAllocator profileData = new BumpAllocator(PageType.NonGC); UIntPtr profileDataStart = MemoryManager.AllocateMemory(size); profileData.SetRange(profileDataStart, size); PageManager.SetStaticDataPages(profileDataStart, size); methods = (AcctRecord[])Allocate(ref profileData, vtable, size); VTable.Assert(methods != null, @"methods != null"); *(uint *)(Magic.addressOf(methods) + PostHeader.Size) = maxIndex + 1; } VTable.Assert(methods.Length == maxIndex + 1, @"methods.Length == maxIndex+1"); if (methods[methodIndex].methodName == null) { methodNames[methodIndex].methodName = methodName; } // Not "methodNames[methodIndex].methodName == methodName" // because the Equality operator carries compiler-inserted // RC updates! VTable.Assert(Magic.addressOf(methodNames[methodIndex]. methodName) == Magic.addressOf(methodName), @"Magic.addressOf(methodNames[methodIndex]. methodName) == Magic.addressOf(methodName)"); methods[methodIndex] += rec; return(true); }