⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prmsgc.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (!base) {    PR_DELETE(segInfo);    return 0;    }    nhbits = (PRInt32)(        (allocSize + PR_BYTES_PER_WORD - 1L) >> PR_BYTES_PER_WORD_LOG2);    nhbytes = ((nhbits + PR_BITS_PER_WORD - 1L) >> PR_BITS_PER_WORD_LOG2)    * sizeof(PRWord);    /* Get bitmap memory from malloc heap */#if defined(WIN16)    PR_ASSERT( nhbytes < MAX_ALLOC_SIZE );#endif    hbits = (PRWord *) PR_CALLOC((PRUint32)nhbytes);    if (!hbits) {    /* Loser! */    PR_DELETE(segInfo);    if (exactly) {        PR_DELETE(base);    } else {      /* XXX do something about this */      /* _MD_FreeGCSegment(base, allocSize); */    }    return 0;    }    /*    ** Setup new segment.    */    sp = &segs[nsegs++];    segInfo->base = sp->base = base;    segInfo->limit = sp->limit = base + allocSize;    segInfo->hbits = sp->hbits = hbits;    sp->info = segInfo;    segInfo->fromMalloc = exactly;    memset(base, 0, allocSize);#ifdef GCMETER    if (_pr_gcMeter & _GC_METER_GROWTH) {        fprintf(stderr, "[GC: new segment base=%p size=%ld]\n",                sp->base, (long) allocSize);    }#endif        _pr_gcData.allocMemory += allocSize;    _pr_gcData.freeMemory  += allocSize;    if (!exactly) {    PRInt32 bin;        /* Put free memory into a freelist bin */        cp = (GCFreeChunk *) base;        cp->segment = sp;        cp->chunkSize = allocSize;        InlineBinNumber(bin, allocSize)        cp->next = bins[bin];        bins[bin] = cp;    if (bin < minBin) minBin = bin;    if (bin > maxBin) maxBin = bin;    } else {        /*        ** When exactly allocating the entire segment is given over to a        ** single object to prevent fragmentation        */    }    if (!_pr_gcData.lowSeg) {    _pr_gcData.lowSeg  = (PRWord*) sp->base;    _pr_gcData.highSeg = (PRWord*) sp->limit;    } else {    if ((PRWord*)sp->base < _pr_gcData.lowSeg) {        _pr_gcData.lowSeg = (PRWord*) sp->base;    }    if ((PRWord*)sp->limit > _pr_gcData.highSeg) {        _pr_gcData.highSeg = (PRWord*) sp->limit;    }    }    /*     ** Get rid of the GC pointer in case it shows up in some uninitialized    ** local stack variable later (while scanning the C stack looking for    ** roots).    */     memset(&base, 0, sizeof(base));  /* optimizers beware */    PR_LOG(_pr_msgc_lm, PR_LOG_WARNING, ("grow heap: total gc memory now %d",                      _pr_gcData.allocMemory));    return sp;}#ifdef USE_EXTEND_HEAPstatic PRBool ExtendHeap(PRInt32 requestedSize) {  GCSeg* sp;  PRUint32 allocSize;  PRInt32 oldSize, newSize;  PRInt32 newHBits, newHBytes;  PRInt32 oldHBits, oldHBytes;  PRWord* hbits;  GCFreeChunk* cp;  PRInt32 bin;  /* Can't extend nothing */  if (nsegs == 0) return PR_FALSE;  /* Round up requested size to the size of a page */  allocSize = (PRUint32) requestedSize;  allocSize = (allocSize + _pr_pageSize - 1L) >> _pr_pageShift;  allocSize <<= _pr_pageShift;  /* Malloc some memory for the new hbits array */  sp = segs;  oldSize = sp->limit - sp->base;  newSize = oldSize + allocSize;  newHBits = (newSize + PR_BYTES_PER_WORD - 1L) >> PR_BYTES_PER_WORD_LOG2;  newHBytes = ((newHBits + PR_BITS_PER_WORD - 1L) >> PR_BITS_PER_WORD_LOG2)    * sizeof(PRWord);  hbits = (PRWord*) PR_MALLOC(newHBytes);  if (0 == hbits) return PR_FALSE;  /* Attempt to extend the last segment by the desired amount */  if (_MD_ExtendGCHeap(sp->base, oldSize, newSize)) {    oldHBits = (oldSize + PR_BYTES_PER_WORD - 1L) >> PR_BYTES_PER_WORD_LOG2;    oldHBytes = ((oldHBits + PR_BITS_PER_WORD - 1L) >> PR_BITS_PER_WORD_LOG2)      * sizeof(PRWord);    /* Copy hbits from old memory into new memory */    memset(hbits, 0, newHBytes);    memcpy(hbits, sp->hbits, oldHBytes);    PR_DELETE(sp->hbits);    memset(sp->base + oldSize, 0, allocSize);    /* Adjust segment state */    sp->limit += allocSize;    sp->hbits = hbits;    sp->info->limit = sp->limit;    sp->info->hbits = hbits;    /* Put free memory into a freelist bin */    cp = (GCFreeChunk *) (sp->base + oldSize);    cp->segment = sp;    cp->chunkSize = allocSize;    InlineBinNumber(bin, allocSize)    cp->next = bins[bin];    bins[bin] = cp;    if (bin < minBin) minBin = bin;    if (bin > maxBin) maxBin = bin;    /* Prevent a pointer that points to the free memory from showing       up on the call stack later on */    memset(&cp, 0, sizeof(cp));    /* Update heap brackets and counters */    if ((PRWord*)sp->limit > _pr_gcData.highSeg) {      _pr_gcData.highSeg = (PRWord*) sp->limit;    }    _pr_gcData.allocMemory += allocSize;    _pr_gcData.freeMemory  += allocSize;    return PR_TRUE;  }  PR_DELETE(hbits);  return PR_FALSE;}#endif /* USE_EXTEND_HEAP */static GCSeg *GrowHeapExactly(PRInt32 requestedSize){    GCSeg *sp = DoGrowHeap(requestedSize, PR_TRUE);    return sp;}static PRBool GrowHeap(PRInt32 requestedSize){  void *p;#ifdef USE_EXTEND_HEAP  if (ExtendHeap(requestedSize)) {    return PR_TRUE;  }#endif  p = DoGrowHeap(requestedSize, PR_FALSE);  return (p != NULL ? PR_TRUE : PR_FALSE);}/*** Release a segment when it is entirely free.*/static void ShrinkGCHeap(GCSeg *sp){#ifdef GCMETER    if (_pr_gcMeter & _GC_METER_GROWTH) {        fprintf(stderr, "[GC: free segment base=%p size=%ld]\n",                sp->base, (long) (sp->limit - sp->base));    }#endif        /*     * Put segment onto free seginfo list (we can't call free right now     * because we have the GC lock and all of the other threads are     * suspended; if one of them has the malloc lock we would deadlock)     */    sp->info->next = freeSegs;    freeSegs = sp->info;    collectorCleanupNeeded = 1;    _pr_gcData.allocMemory -= sp->limit - sp->base;    if (sp == lastInHeap) lastInHeap = 0;    /* Squish out disappearing segment from segment table */    --nsegs;    if ((sp - segs) != nsegs) {        *sp = segs[nsegs];    } else {        sp->base = 0;        sp->limit = 0;        sp->hbits = 0;    sp->info = 0;    }    /* Recalculate the lowSeg and highSeg values */    _pr_gcData.lowSeg  = (PRWord*) segs[0].base;    _pr_gcData.highSeg = (PRWord*) segs[0].limit;    for (sp = segs; sp < &segs[nsegs]; sp++) {    if ((PRWord*)sp->base < _pr_gcData.lowSeg) {        _pr_gcData.lowSeg = (PRWord*) sp->base;    }    if ((PRWord*)sp->limit > _pr_gcData.highSeg) {        _pr_gcData.highSeg = (PRWord*) sp->limit;    }    }}static void FreeSegments(void){    GCSegInfo *si;    while (0 != freeSegs) {    LOCK_GC();    si = freeSegs;    if (si) {        freeSegs = si->next;    }    UNLOCK_GC();    if (!si) {        break;    }    PR_DELETE(si->base);    PR_DELETE(si->hbits);    PR_DELETE(si);    }}/************************************************************************/void ScanScanQ(GCScanQ *iscan){    PRWord *p;    PRWord **pp;    PRWord **epp;    GCScanQ nextQ, *scan, *next, *temp;    CollectorType *ct;    if (!iscan->queued) return;    _GCTRACE(GC_MARK, ("begin scanQ @ 0x%x (%d)", iscan, iscan->queued));    scan = iscan;    next = &nextQ;    while (scan->queued) {	_GCTRACE(GC_MARK, ("continue scanQ @ 0x%x (%d)", scan, scan->queued));    /*     * Set pointer to current scanQ so that _pr_gcData.livePointer     * can find it.     */    pScanQ = next;    next->queued = 0;    /* Now scan the scan Q */    pp = scan->q;    epp = &scan->q[scan->queued];    scan->queued = 0;    while (pp < epp) {        p = *pp++;        ct = &_pr_collectorTypes[GET_TYPEIX(p[0])];        PR_ASSERT(0 != ct->gctype.scan);        /* Scan object ... */        (*ct->gctype.scan)(p + 1);    }    /* Exchange pointers so that we scan next */    temp = scan;    scan = next;    next = temp;    }    pScanQ = iscan;    PR_ASSERT(nextQ.queued == 0);    PR_ASSERT(iscan->queued == 0);}/*** Called during root finding step to identify "root" pointers into the** GC heap. First validate if it is a real heap pointer and then mark the** object being pointed to and add it to the scan Q for eventual** scanning.*/static void PR_CALLBACK ProcessRootBlock(void **base, PRInt32 count){    GCSeg *sp;    PRWord *p0, *p, h, tix, *low, *high, *segBase;    CollectorType *ct;#ifdef DEBUG    void **base0 = base;#endif    low = _pr_gcData.lowSeg;    high = _pr_gcData.highSeg;    while (--count >= 0) {        p0 = (PRWord*) *base++;        /*        ** XXX:          ** Until Win16 maintains lowSeg and highSeg correctly,        ** (ie. lowSeg=MIN(all segs) and highSeg = MAX(all segs))        ** Allways scan through the segment list        */#if !defined(WIN16)        if (p0 < low) continue;                  /* below gc heap */        if (p0 >= high) continue;                /* above gc heap */#endif        /* NOTE: inline expansion of InHeap */        /* Find segment */    sp = lastInHeap;        if (!sp || !IN_SEGMENT(sp,p0)) {            GCSeg *esp;            sp = segs;        esp = segs + nsegs;            for (; sp < esp; sp++) {                if (IN_SEGMENT(sp, p0)) {                    lastInHeap = sp;                    goto find_object;                }            }            continue;        }      find_object:        /* NOTE: Inline expansion of FindObject */        /* Align p to it's proper boundary before we start fiddling with it */        p = (PRWord*) ((PRWord)p0 & ~(PR_BYTES_PER_WORD-1L));        segBase = (PRWord *) sp->base;        do {            if (IS_HBIT(sp, p)) {                goto winner;            }            p--;        } while (p >= segBase);        /*        ** We have a pointer into the heap, but it has no header        ** bit. This means that somehow the very first object in the heap        ** doesn't have a header. This is impossible so when debugging        ** lets abort.        */#ifdef DEBUG        PR_Abort();#endif      winner:        h = p[0];        if ((h & MARK_BIT) == 0) {#ifdef DEBUG            _GCTRACE(GC_ROOTS,            ("root 0x%p (%d) base0=%p off=%d",             p, OBJ_BYTES(h), base0, (base-1) - base0));#endif            /* Mark the root we just found */            p[0] = h | MARK_BIT;            /*         * See if object we just found needs scanning. It must         * have a scan function to be placed on the scanQ.         */            tix = (PRWord)GET_TYPEIX(h);        ct = &_pr_collectorTypes[tix];        if (0 == ct->gctype.scan) {        continue;        }            /*            ** Put a pointer onto the scan Q. We use the scan Q to avoid            ** deep recursion on the C call stack. Objects are added to            ** the scan Q until the scan Q fills up. At that point we            ** make a call to ScanScanQ which proceeds to scan each of            ** the objects in the Q. This limits the recursion level by a            ** large amount though the stack frames get larger to hold            ** the GCScanQ's.            */            pScanQ->q[pScanQ->queued++] = p;            if (pScanQ->queued == MAX_SCAN_Q) {                METER(_pr_scanDepth++);                ScanScanQ(pScanQ);            }        }    }}static void PR_CALLBACK ProcessRootPointer(void *ptr){  PRWord *p0, *p, h, tix, *segBase;  GCSeg* sp;  CollectorType *ct;  p0 = (PRWord*) ptr;  /*  ** XXX:    ** Until Win16 maintains lowSeg and highSeg correctly,  ** (ie. lowSeg=MIN(all segs) and highSeg = MAX(all segs))  ** Allways scan through the segment list  */#if !defined(WIN16)  if (p0 < _pr_gcData.lowSeg) return;                  /* below gc heap */  if (p0 >= _pr_gcData.highSeg) return;                /* above gc heap */#endif  /* NOTE: inline expansion of InHeap */  /* Find segment */  sp = lastInHeap;  if (!sp || !IN_SEGMENT(sp,p0)) {    GCSeg *esp;    sp = segs;    esp = segs + nsegs;    for (; sp < esp; sp++) {      if (IN_SEGMENT(sp, p0)) {    lastInHeap = sp;    goto find_object;      }    }    return;  } find_object:  /* NOTE: Inline expansion of FindObject */  /* Align p to it's proper boundary before we start fiddling with it */    p = (PRWord*) ((PRWord)p0 & ~(BYTES_PER_WORD-1L));    segBase = (PRWord *) sp->base;    do {      if (IS_HBIT(sp, p)) {    goto winner;      }      p--;    } while (p >= segBase);    /*    ** We have a pointer into the heap, but it has no header    ** bit. This means that somehow the very first object in the heap    ** doesn't have a header. This is impossible so when debugging    ** lets abort.    */#ifdef DEBUG    PR_Abort();#endif winner:  h = p[0];  if ((h & MARK_BIT) == 0) {#ifdef DEBUG    _GCTRACE(GC_ROOTS, ("root 0x%p (%d)", p, OBJ_BYTES(h)));#endif    /* Mark the root we just found */    p[0] = h | MARK_BIT;    /*     * See if object we just found needs scanning. It must     * have a scan function to be placed on the scanQ.     */    tix = (PRWord)GET_TYPEIX(h);    ct = &_pr_collectorTypes[tix];    if (0 == ct->gctype.scan) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -