internal static bool ShouldPin(UIntPtr objAddr) { UIntPtr page = PageTable.Page(objAddr); if (PageTable.Type(page) != SegregatedFreeList.SMALL_OBJ_PAGE) { // in practice this won't be reached return(true); } SegregatedFreeList.PageHeader *ph = (SegregatedFreeList.PageHeader *)PageTable.PageAddr(page); return(new CoCoPageUserValue(ph->userValue).Pinned); }
// this is _just_ a notification - it doesn't pin the object, it's just // what we do if an object ends up being pinned. internal static void NotifyPin(UIntPtr objAddr) { UIntPtr page = PageTable.Page(objAddr); if (PageTable.Type(page) != SegregatedFreeList.SMALL_OBJ_PAGE) { return; } SegregatedFreeList.PageHeader *ph = (SegregatedFreeList.PageHeader *)PageTable.PageAddr(page); CoCoPageUserValue v = new CoCoPageUserValue(ph->userValue); if (v.Marked) { v.Pinned = true; } ph->userValue = v.Bits; }
VisitPage(UIntPtr page, SegregatedFreeList.PageHeader *ph, int cells) { if (fDebugPage) { VTable.DebugPrint(" $$ visiting page.\n"); } CoCoPageUserValue v = new CoCoPageUserValue(ph->userValue); if (inFixUp && v.Marked) { unmarkedCnt++; v.Marked = false; if (v.Pinned) { v.Pinned = false; v.Version = pinPenalty; /* use the Version to delay * any future evacuation * attempts for this page */ } } else if (!doingCoCo && !delay) { if (v.Version >= 1) { // this page has a non-zero Version - this means // that any attempts to evacuate it should be delayed. v.Version--; delayedCnt++; if (fDebugPage) { VTable.DebugPrint(" $$ page had non-zero version.\n"); } } else { if (fDebugPage) { VTable.DebugPrint(" $$ cnt = "); VTable.DebugPrint((ulong)cnt); VTable.DebugPrint(", lastSmallPagesRecycle = "); VTable.DebugPrint((ulong)lastSmallPagesRecycle); VTable.DebugPrint(", sizeFracLim = "); VTable.DebugPrint((ulong)sizeFracLim); VTable.DebugPrint(", sizeLim = "); VTable.DebugPrint((ulong)sizeLim); VTable.DebugPrint(", PageSize = "); VTable.DebugPrint((ulong)PageTable.PageSize); VTable.DebugPrint(", freeCount = "); VTable.DebugPrint((ulong)ph->freeCount); VTable.DebugPrint(", pageFragThres = "); VTable.DebugPrint((ulong)pageFragThres); VTable.DebugPrint(", cells = "); VTable.DebugPrint((ulong)cells); VTable.DebugPrint("\n"); } if ((long)cnt < ((long)lastSmallPagesRecycle / (long)sizeFracLim) && (sizeLim < 0 || cnt * PageTable.PageSize < (UIntPtr)sizeLim) && ph->freeCount * pageFragThres >= cells) { cnt++; v.Marked = true; } } } else { if (fDebugPage) { VTable.DebugPrint(" $$ not doing anything about page.\n"); } } ph->userValue = v.Bits; if (v.Marked) { return(SegregatedFreeList.PartialPageAction.CommitFull); } else { return(SegregatedFreeList.PartialPageAction.CommitFree); } }
internal unsafe void ScanHook(Object obj) { UIntPtr page = PageTable.Page(Magic.addressOf(obj)); if (PageTable.Type(page) != SegregatedFreeList.SMALL_OBJ_PAGE) { //VTable.DebugPrint(" not tagging because this isn't a small object page"); return; } SegregatedFreeList.PageHeader *ph = (SegregatedFreeList.PageHeader *)PageTable.PageAddr(page); if (!new CoCoPageUserValue(ph->userValue).Marked) { //VTable.DebugPrint(" not tagging because the page isn't marked\n"); return; } if (obj is EMU || obj is Monitor || obj is Thread || obj is ThreadHeaderQueue) { CoCoBarrier.NotifyPin(Magic.addressOf(obj)); if (fVerbose) { VTable.DebugPrint(" $$ not tagging object because it's a monitor or EMU\n"); } return; } if (doingCoCo) { //VTable.DebugPrint(" not tagging object because doingCoCo\n"); return; } if (!CoCoBarrier.instance.ObjectIsNotCopied(obj)) { if (fVerbose) { VTable.DebugPrint(" not tagging object because object is already in the process of being copied.\n"); } return; } if (fVerbose && obj.GetType() != typeof(Object)) { VTable.DebugPrint(" $$ tagging a non-System.Object; type is "); VTable.DebugPrint(obj.GetType().Name); VTable.DebugPrint("\n"); } // REVIEW: I wish that there was an easier way of // doing this. Object copy; if (obj is Array) { Array a = (Array)obj; if (a.IsVector) { copy = GC.AllocateVector(a.vtable, a.Length); } else { copy = GC.AllocateArray(a.vtable, a.Rank, a.Length); } } else if (obj is String) { String s = (String)obj; // REVIEW: this is not nice. copy = GC.AllocateString(s.ArrayLength - 1); } else { copy = GC.AllocateObject(obj.vtable); } VTable.Assert(ObjectLayout.Sizeof(copy) == ObjectLayout.Sizeof(obj), "Copy is not same size as original"); spaceOverhead += ObjectLayout.Sizeof(copy); bool first = !CoCoBarrier.instance.AnyTaggedForCopying; UIntPtr thisSpaceOverhead; if (CoCoBarrier.instance.TagObjectForCopy(obj, copy, out thisSpaceOverhead)) { cnt++; if (first) { lock (interlock) { if (!wantCoCo && !doingCoCo) { wantCoCo = true; } } } } spaceOverhead += thisSpaceOverhead; }