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; }