Exemple #1
0
        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);
        }
Exemple #2
0
        // 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;
            }