internal override void Shutdown()
 {
     base.Shutdown();
     lock (interlock) {
         die = true;
         Monitor.PulseAll(interlock);
     }
     cocoThread.Join();
     if (VTable.enableFinalGCTiming)
     {
         VTable.DebugPrint("CoCo completed ");
         VTable.DebugPrint(cycles);
         VTable.DebugPrint(" cycles, started ");
         VTable.DebugPrint(cyclesStarted);
         VTable.DebugPrint(" cycles, and copied ");
         VTable.DebugPrint(numCopied);
         VTable.DebugPrint(" objects.\n");
         VTable.DebugPrint("CoCo took ");
         VTable.DebugPrint((ulong)pinTime);
         VTable.DebugPrint("+");
         VTable.DebugPrint((ulong)prepTime);
         VTable.DebugPrint("+");
         VTable.DebugPrint((ulong)copyTime);
         VTable.DebugPrint("+");
         VTable.DebugPrint((ulong)forwardTime);
         VTable.DebugPrint("=");
         VTable.DebugPrint((ulong)(pinTime + prepTime + copyTime + forwardTime));
         VTable.DebugPrint(" ms.\n");
         VTable.DebugPrint("max space overhead = ");
         VTable.DebugPrint((ulong)maxSpaceOverhead);
         VTable.DebugPrint("\n");
         CoCoBarrier.PrintStats();
     }
 }
        internal override void EnableHeap()
        {
            interlock = new Object();
            MultiUseWord.GetMonitor(interlock);
            CoCoBarrier.InitLate();

            // REVIEW: add some bartok args instead

            sizeFracLim   = EnvInt(10, "COCO_SIZE_FRAC_LIM");
            sizeLim       = EnvInt(-1, "COCO_SIZE_LIM");
            pageFragThres = EnvInt(2, "COCO_PAGE_FRAG_THRES");
            pinPenalty    = EnvInt(10, "COCO_PIN_PENALTY");
            cocoDelay     = EnvInt(8, "COCO_COPY_DELAY");

            if (EnvInt(0, "COCO_FORCE_SLOW") != 0)
            {
                CoCoBarrier.ForceSlow();
            }
            if (EnvInt(0, "COCO_FORCE_NOT_IDLE") != 0)
            {
                CoCoBarrier.ForceNotIdle();
            }
            if (EnvInt(0, "COCO_FORCE_FORWARDING") != 0)
            {
                CoCoBarrier.ForceForwarding();
            }
            if (EnvInt(0, "COCO_FORCE_PINNING") != 0)
            {
                CoCoBarrier.ForcePinning();
            }

            base.EnableHeap();
            cocoThread = new Thread(new ThreadStart(CoCoLoop));
            cocoThread.Start();
        }
 internal override void PostRootScanHook()
 {
     if (inFixUp)
     {
         timingAfterCopy = Environment.TickCount;
         CoCoBarrier.ChangePhase(CoCoBarrier.Phase.Idle, true, true);
     }
 }
 internal override UIntPtr AllocateObjectMemorySlow(UIntPtr numBytes,
                                                    uint alignment,
                                                    Thread currentThread)
 {
     CoCoBarrier.ClientHandshake();
     return(base.AllocateObjectMemorySlow(numBytes,
                                          alignment,
                                          currentThread));
 }
            internal override unsafe void ProcessObjectPtr(UIntPtr realPtr,
                                                           UIntPtr *loc,
                                                           UIntPtr addr)
            {
                UIntPtr forward = CoCoBarrier.ToSpaceAsPtr(realPtr);

                if (forward != realPtr)
                {
                    *loc = addr - realPtr + forward;
                }
                markReferenceVisitor.VisitValueAnyThreadMaybeNull(forward);
            }
            internal unsafe void ForwardAndVisit(UIntPtr *loc)
            {
                UIntPtr addr = *loc;

                if (addr == UIntPtr.Zero)
                {
                    return;
                }
                UIntPtr forward =
                    CoCoBarrier.instance.ToSpaceImplNonNull(Magic.fromAddress(addr));

                if (forward != addr)
                {
                    CoCoBarrier.CAS(loc, forward, addr);
                    // if this CAS fails it means that someone stored
                    // a different pointer into the field, but in that
                    // case the pointer stored would have already been
                    // forwarded thanks to the CoCo write barrier.
                }
                VisitValueNonNull(forward);
            }
 internal override UIntPtr ForwardIfNecessary(UIntPtr addr)
 {
     return(CoCoBarrier.ToSpaceAsPtr(addr));
 }
            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;
            }
        internal static void CoCoLoop()
        {
            if (fDebug)
            {
                VTable.DebugPrint("coco thread = ");
                VTable.DebugPrint((ulong)Win32Native.GetCurrentThreadId());
                VTable.DebugPrint("\n");
                VTable.DebugPrint("CoCo at ");
                VTable.DebugPrint((ulong)Magic.addressOf(Thread.CurrentThread));
                VTable.DebugPrint("\n");
            }
            for (;;)
            {
                lock (interlock) {
                    doingCoCo = false;
                    for (;;)
                    {
                        if (die)
                        {
                            return;
                        }
                        else if (didStartTrace)
                        {
                            didStartTrace = false;
                            Monitor.PulseAll(interlock);
                        }
                        else if (didEndTrace)
                        {
                            didEndTrace = false;
                            Monitor.PulseAll(interlock);
                            if (wantCoCo)
                            {
                                break;
                            }
                        }
                        Monitor.Wait(interlock);
                    }
                    wantCoCo = false;
                }

                // now further tracing is BLOCKED

                cyclesStarted++;
                timingBefore = Environment.TickCount;

                if (fDebug)
                {
                    VTable.DebugPrint("+++++ Start Concurrent Copying\n");
                }

                CoCoBarrier.EnablePinning();
                doingCoCo = true;
                ConcurrentMSCollector.stackMarkReferenceVisitor =
                    CoCoMSCollector.nopStackMarker;
                ConcurrentMSCollector.stackMarkPinnedReferenceVisitor =
                    CoCoMSCollector.pinStackMarker;
                // Perform a scan of all call stacks, including the call
                // stack of the CoCo thread.
                ConcurrentMSCollector.TrivialHandshake      = false;
                ConcurrentMSCollector.IncludeMUWInHandshake = false;
                ConcurrentMSCollector.CollectorHandshake(cocoThread);
                // In order to scan the call stack of the current thread,
                // we need a TransitionRecord for the thread.  At this
                // point we don't have one, so we have to go through
                // CollectBodyTransition to get one.
                Transitions.MakeGCRequest(cocoThread.threadIndex);
                GC.InvokeCollection(cocoThread);
                ConcurrentMSCollector.TrivialHandshake          = true;
                ConcurrentMSCollector.IncludeMUWInHandshake     = true;
                ConcurrentMSCollector.stackMarkReferenceVisitor =
                    CoCoMSCollector.normalStackMarker;
                ConcurrentMSCollector.stackMarkPinnedReferenceVisitor =
                    CoCoMSCollector.normalStackMarker;

                timingAfterPin = Environment.TickCount;

                if (fDebug)
                {
                    VTable.DebugPrint("+++++ Copying\n");
                }

                if (CoCoBarrier.instance.NeedsPrepPhase)
                {
                    CoCoBarrier.ChangePhase(CoCoBarrier.Phase.Prep, false, true);
                }

                timingAfterPrep = Environment.TickCount;

                CoCoBarrier.ChangePhase(CoCoBarrier.Phase.Copy, true, true);

                numCopied += CoCoBarrier.instance.Copy();

                CoCoBarrier.ChangePhase(CoCoBarrier.Phase.Fixup, true, true);

                AddCollectionRequest();

                // wait for a complete collector cycle.  This is for fixup.
                if (fDebug)
                {
                    VTable.DebugPrint("+++++ Fixup: Waiting to start tracing\n");
                }
                lock (interlock) {
                    while (!didStartTrace && !die)
                    {
                        Monitor.Wait(interlock);
                    }
                    if (die)
                    {
                        return;
                    }
                    didStartTrace = false;
                    inFixUp       = true;
                    Monitor.PulseAll(interlock);
                }

                if (fDebug)
                {
                    VTable.DebugPrint("+++++ Fixup: Waiting to end tracing\n");
                }
                lock (interlock) {
                    while (!didEndTrace && !die)
                    {
                        Monitor.Wait(interlock);
                    }
                    if (die)
                    {
                        return;
                    }
                    didEndTrace = false;
                    doingCoCo   = false;
                    inFixUp     = false;
                    Monitor.PulseAll(interlock);
                }

                timingAfter = Environment.TickCount;

                CoCoBarrier.ChangePhase(CoCoBarrier.Phase.Idle, false, false);

                if (fDebug)
                {
                    VTable.DebugPrint("+++++ Finish Concurrent Copying\n");
                }

                pinTime     += (timingAfterPin - timingBefore);
                prepTime    += (timingAfterPrep - timingAfterPin);
                copyTime    += (timingAfterCopy - timingAfterPrep);
                forwardTime += (timingAfter - timingAfterCopy);

                cycles++;
            }
        }
Esempio n. 10
0
 internal override void PostSweepHook()
 {
     CoCoBarrier.ExchangeReadyForCoCo(true);
 }
Esempio n. 11
0
 internal override void PreSweepHook()
 {
     CoCoBarrier.ExchangeReadyForCoCo(false);
 }
Esempio n. 12
0
 internal override void ThreadStartNotification(int currentThreadIndex)
 {
     base.ThreadStartNotification(currentThreadIndex);
     CoCoBarrier.ThreadStart(Thread.threadTable[currentThreadIndex]);
 }