~ubuntu-branches/ubuntu/quantal/libgc/quantal

« back to all changes in this revision

Viewing changes to allchblk.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger
  • Date: 2011-02-19 12:19:56 UTC
  • mfrom: (1.3.2 upstream) (0.1.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20110219121956-67rb69xlt5nud3v2
Tags: 1:7.1-5
Upload to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
  word GC_free_bytes[N_HBLK_FLS+1] = { 0 };
52
52
        /* Number of free bytes on each list.   */
53
53
 
54
 
  /* Is bytes + the number of free bytes on lists n .. N_HBLK_FLS       */
55
 
  /* > GC_max_large_allocd_bytes?                                       */
 
54
  /* Return the largest n such that                                     */
 
55
  /* Is GC_large_allocd_bytes + the number of free bytes on lists       */
 
56
  /* n .. N_HBLK_FLS > GC_max_large_allocd_bytes.                       */
 
57
  /* If there is no such n, return 0.                                   */
56
58
# ifdef __GNUC__
57
59
  __inline__
58
60
# endif
59
 
  static GC_bool GC_enough_large_bytes_left(bytes,n)
60
 
  word bytes;
61
 
  int n;
 
61
  static int GC_enough_large_bytes_left(void)
62
62
  {
63
 
    int i;
64
 
    for (i = N_HBLK_FLS; i >= n; --i) {
65
 
        bytes += GC_free_bytes[i];
66
 
        if (bytes > GC_max_large_allocd_bytes) return TRUE;
 
63
    int n;
 
64
    word bytes = GC_large_allocd_bytes;
 
65
 
 
66
    GC_ASSERT(GC_max_large_allocd_bytes <= GC_heapsize);
 
67
    for (n = N_HBLK_FLS; n >= 0; --n) {
 
68
        bytes += GC_free_bytes[n];
 
69
        if (bytes >= GC_max_large_allocd_bytes) return n;
67
70
    }
68
 
    return FALSE;
 
71
    return 0;
69
72
  }
70
73
 
71
74
# define INCR_FREE_BYTES(n, b) GC_free_bytes[n] += (b);
80
83
#endif /* USE_MUNMAP */
81
84
 
82
85
/* Map a number of blocks to the appropriate large block free list index. */
83
 
int GC_hblk_fl_from_blocks(blocks_needed)
84
 
word blocks_needed;
 
86
int GC_hblk_fl_from_blocks(word blocks_needed)
85
87
{
86
 
    if (blocks_needed <= UNIQUE_THRESHOLD) return blocks_needed;
 
88
    if (blocks_needed <= UNIQUE_THRESHOLD) return (int)blocks_needed;
87
89
    if (blocks_needed >= HUGE_THRESHOLD) return N_HBLK_FLS;
88
 
    return (blocks_needed - UNIQUE_THRESHOLD)/FL_COMPRESSION
 
90
    return (int)(blocks_needed - UNIQUE_THRESHOLD)/FL_COMPRESSION
89
91
                                        + UNIQUE_THRESHOLD;
90
92
    
91
93
}
106
108
    word total_free = 0;
107
109
    hdr * hhdr;
108
110
    word sz;
109
 
    int i;
 
111
    unsigned i;
110
112
    
111
113
    for (i = 0; i <= N_HBLK_FLS; ++i) {
112
114
      h = GC_hblkfreelist[i];
113
115
#     ifdef USE_MUNMAP
114
 
        if (0 != h) GC_printf1("Free list %ld:\n",
115
 
                               (unsigned long)i);
 
116
        if (0 != h) GC_printf("Free list %ld:\n",
 
117
                              (unsigned long)i);
116
118
#     else
117
 
        if (0 != h) GC_printf2("Free list %ld (Total size %ld):\n",
118
 
                               (unsigned long)i,
119
 
                               (unsigned long)GC_free_bytes[i]);
 
119
        if (0 != h) GC_printf("Free list %lu (Total size %lu):\n",
 
120
                              i, (unsigned long)GC_free_bytes[i]);
120
121
#     endif
121
122
      while (h != 0) {
122
123
        hhdr = HDR(h);
123
124
        sz = hhdr -> hb_sz;
124
 
        GC_printf2("\t0x%lx size %lu ", (unsigned long)h, (unsigned long)sz);
 
125
        GC_printf("\t%p size %lu ", h, (unsigned long)sz);
125
126
        total_free += sz;
126
127
        if (GC_is_black_listed(h, HBLKSIZE) != 0) {
127
 
             GC_printf0("start black listed\n");
 
128
             GC_printf("start black listed\n");
128
129
        } else if (GC_is_black_listed(h, hhdr -> hb_sz) != 0) {
129
 
             GC_printf0("partially black listed\n");
 
130
             GC_printf("partially black listed\n");
130
131
        } else {
131
 
             GC_printf0("not black listed\n");
 
132
             GC_printf("not black listed\n");
132
133
        }
133
134
        h = hhdr -> hb_next;
134
135
      }
135
136
    }
136
137
#   ifndef USE_MUNMAP
137
138
      if (total_free != GC_large_free_bytes) {
138
 
        GC_printf1("GC_large_free_bytes = %lu (INCONSISTENT!!)\n",
139
 
                   (unsigned long) GC_large_free_bytes);
 
139
        GC_printf("GC_large_free_bytes = %lu (INCONSISTENT!!)\n",
 
140
                  (unsigned long) GC_large_free_bytes);
140
141
      }
141
142
#   endif
142
 
    GC_printf1("Total of %lu bytes on free list\n", (unsigned long)total_free);
 
143
    GC_printf("Total of %lu bytes on free list\n", (unsigned long)total_free);
143
144
}
144
145
 
145
146
/* Return the free list index on which the block described by the header */
146
147
/* appears, or -1 if it appears nowhere.                                 */
147
 
int free_list_index_of(wanted)
148
 
hdr * wanted;
 
148
int free_list_index_of(hdr *wanted)
149
149
{
150
150
    struct hblk * h;
151
151
    hdr * hhdr;
178
178
            ++i;
179
179
            end = GC_heap_sects[i].hs_start + GC_heap_sects[i].hs_bytes;
180
180
          }
181
 
        GC_printf2("***Section from 0x%lx to 0x%lx\n", start, end);
 
181
        GC_printf("***Section from %p to %p\n", start, end);
182
182
        for (p = start; p < end;) {
183
183
            hhdr = HDR(p);
184
 
            GC_printf1("\t0x%lx ", (unsigned long)p);
 
184
            GC_printf("\t%p ", p);
185
185
            if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
186
 
                GC_printf1("Missing header!!(%ld)\n", hhdr);
 
186
                GC_printf("Missing header!!(%d)\n", hhdr);
187
187
                p += HBLKSIZE;
188
188
                continue;
189
189
            }
192
192
                                        divHBLKSZ(hhdr -> hb_sz));
193
193
                int actual_index;
194
194
                
195
 
                GC_printf1("\tfree block of size 0x%lx bytes",
196
 
                           (unsigned long)(hhdr -> hb_sz));
 
195
                GC_printf("\tfree block of size 0x%lx bytes",
 
196
                          (unsigned long)(hhdr -> hb_sz));
197
197
                if (IS_MAPPED(hhdr)) {
198
 
                    GC_printf0("\n");
 
198
                    GC_printf("\n");
199
199
                } else {
200
 
                    GC_printf0("(unmapped)\n");
 
200
                    GC_printf("(unmapped)\n");
201
201
                }
202
202
                actual_index = free_list_index_of(hhdr);
203
203
                if (-1 == actual_index) {
204
 
                    GC_printf1("\t\tBlock not on free list %ld!!\n",
205
 
                                correct_index);
 
204
                    GC_printf("\t\tBlock not on free list %d!!\n",
 
205
                              correct_index);
206
206
                } else if (correct_index != actual_index) {
207
 
                    GC_printf2("\t\tBlock on list %ld, should be on %ld!!\n",
208
 
                               actual_index, correct_index);
 
207
                    GC_printf("\t\tBlock on list %d, should be on %d!!\n",
 
208
                              actual_index, correct_index);
209
209
                }
210
210
                p += hhdr -> hb_sz;
211
211
            } else {
212
 
                GC_printf1("\tused for blocks of size 0x%lx bytes\n",
213
 
                           (unsigned long)WORDS_TO_BYTES(hhdr -> hb_sz));
 
212
                GC_printf("\tused for blocks of size 0x%lx bytes\n",
 
213
                          (unsigned long)(hhdr -> hb_sz));
214
214
                p += HBLKSIZE * OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
215
215
            }
216
216
        }
222
222
/* Initialize hdr for a block containing the indicated size and         */
223
223
/* kind of objects.                                                     */
224
224
/* Return FALSE on failure.                                             */
225
 
static GC_bool setup_header(hhdr, sz, kind, flags)
226
 
register hdr * hhdr;
227
 
word sz;        /* object size in words */
228
 
int kind;
229
 
unsigned char flags;
 
225
static GC_bool setup_header(hdr * hhdr, struct hblk *block, size_t byte_sz,
 
226
                            int kind, unsigned flags)
230
227
{
231
 
    register word descr;
 
228
    word descr;
 
229
    size_t granules;
232
230
    
233
 
    /* Add description of valid object pointers */
234
 
      if (!GC_add_map_entry(sz)) return(FALSE);
235
 
      hhdr -> hb_map = GC_obj_map[sz > MAXOBJSZ? 0 : sz];
236
 
      
237
231
    /* Set size, kind and mark proc fields */
238
 
      hhdr -> hb_sz = sz;
239
 
      hhdr -> hb_obj_kind = kind;
240
 
      hhdr -> hb_flags = flags;
 
232
      hhdr -> hb_sz = byte_sz;
 
233
      hhdr -> hb_obj_kind = (unsigned char)kind;
 
234
      hhdr -> hb_flags = (unsigned char)flags;
 
235
      hhdr -> hb_block = block;
241
236
      descr = GC_obj_kinds[kind].ok_descriptor;
242
 
      if (GC_obj_kinds[kind].ok_relocate_descr) descr += WORDS_TO_BYTES(sz);
 
237
      if (GC_obj_kinds[kind].ok_relocate_descr) descr += byte_sz;
243
238
      hhdr -> hb_descr = descr;
 
239
    
 
240
#   ifdef MARK_BIT_PER_OBJ
 
241
     /* Set hb_inv_sz as portably as possible.                          */
 
242
     /* We set it to the smallest value such that sz * inv_sz > 2**32    */
 
243
     /* This may be more precision than necessary.                      */
 
244
      if (byte_sz > MAXOBJBYTES) {
 
245
         hhdr -> hb_inv_sz = LARGE_INV_SZ;
 
246
      } else {
 
247
        word inv_sz;
 
248
 
 
249
#       if CPP_WORDSZ == 64
 
250
          inv_sz = ((word)1 << 32)/byte_sz;
 
251
          if (((inv_sz*byte_sz) >> 32) == 0) ++inv_sz;
 
252
#       else  /* 32 bit words */
 
253
          GC_ASSERT(byte_sz >= 4);
 
254
          inv_sz = ((unsigned)1 << 31)/byte_sz;
 
255
          inv_sz *= 2;
 
256
          while (inv_sz*byte_sz > byte_sz) ++inv_sz;
 
257
#       endif
 
258
        hhdr -> hb_inv_sz = inv_sz;
 
259
      }
 
260
#   else /* MARK_BIT_PER_GRANULE */
 
261
      hhdr -> hb_large_block = (unsigned char)(byte_sz > MAXOBJBYTES);
 
262
      granules = BYTES_TO_GRANULES(byte_sz);
 
263
      if (EXPECT(!GC_add_map_entry(granules), FALSE)) {
 
264
        /* Make it look like a valid block. */
 
265
        hhdr -> hb_sz = HBLKSIZE;
 
266
        hhdr -> hb_descr = 0;
 
267
        hhdr -> hb_large_block = TRUE;
 
268
        hhdr -> hb_map = 0;
 
269
        return FALSE;
 
270
      } else {
 
271
        size_t index = (hhdr -> hb_large_block? 0 : granules);
 
272
        hhdr -> hb_map = GC_obj_map[index];
 
273
      }
 
274
#   endif /* MARK_BIT_PER_GRANULE */
244
275
      
245
276
    /* Clear mark bits */
246
277
      GC_clear_hdr_marks(hhdr);
255
286
 * We assume it is on the nth free list, or on the size
256
287
 * appropriate free list if n is FL_UNKNOWN.
257
288
 */
258
 
void GC_remove_from_fl(hhdr, n)
259
 
hdr * hhdr;
260
 
int n;
 
289
void GC_remove_from_fl(hdr *hhdr, int n)
261
290
{
262
291
    int index;
263
292
 
298
327
/*
299
328
 * Return a pointer to the free block ending just before h, if any.
300
329
 */
301
 
struct hblk * GC_free_block_ending_at(h)
302
 
struct hblk *h;
 
330
struct hblk * GC_free_block_ending_at(struct hblk *h)
303
331
{
304
332
    struct hblk * p = h - 1;
305
333
    hdr * phdr;
330
358
 * Add hhdr to the appropriate free list.
331
359
 * We maintain individual free lists sorted by address.
332
360
 */
333
 
void GC_add_to_fl(h, hhdr)
334
 
struct hblk *h;
335
 
hdr * hhdr;
 
361
void GC_add_to_fl(struct hblk *h, hdr *hhdr)
336
362
{
337
363
    int index = GC_hblk_fl_from_blocks(divHBLKSZ(hhdr -> hb_sz));
338
364
    struct hblk *second = GC_hblkfreelist[index];
339
365
    hdr * second_hdr;
340
 
#   ifdef GC_ASSERTIONS
 
366
#   if defined(GC_ASSERTIONS) && !defined(USE_MUNMAP)
341
367
      struct hblk *next = (struct hblk *)((word)h + hhdr -> hb_sz);
342
368
      hdr * nexthdr = HDR(next);
343
369
      struct hblk *prev = GC_free_block_ending_at(h);
344
370
      hdr * prevhdr = HDR(prev);
345
 
      GC_ASSERT(nexthdr == 0 || !HBLK_IS_FREE(nexthdr) || !IS_MAPPED(nexthdr));
346
 
      GC_ASSERT(prev == 0 || !HBLK_IS_FREE(prevhdr) || !IS_MAPPED(prevhdr));
 
371
      GC_ASSERT(nexthdr == 0 || !HBLK_IS_FREE(nexthdr)
 
372
                || (signed_word)GC_heapsize < 0);
 
373
                /* In the last case, blocks may be too large to merge. */
 
374
      GC_ASSERT(prev == 0 || !HBLK_IS_FREE(prevhdr)
 
375
                || (signed_word)GC_heapsize < 0);
347
376
#   endif
348
377
    GC_ASSERT(((hhdr -> hb_sz) & (HBLKSIZE-1)) == 0);
349
378
    GC_hblkfreelist[index] = h;
355
384
      GET_HDR(second, second_hdr);
356
385
      second_hdr -> hb_prev = h;
357
386
    }
358
 
    GC_invalidate_map(hhdr);
 
387
    hhdr -> hb_flags |= FREE_BLK;
359
388
}
360
389
 
361
390
#ifdef USE_MUNMAP
369
398
    word sz;
370
399
    unsigned short last_rec, threshold;
371
400
    int i;
372
 
#   define UNMAP_THRESHOLD 6
 
401
#   ifndef MUNMAP_THRESHOLD
 
402
#     define MUNMAP_THRESHOLD 6
 
403
#   endif
373
404
    
374
405
    for (i = 0; i <= N_HBLK_FLS; ++i) {
375
406
      for (h = GC_hblkfreelist[i]; 0 != h; h = hhdr -> hb_next) {
376
407
        hhdr = HDR(h);
377
408
        if (!IS_MAPPED(hhdr)) continue;
378
 
        threshold = (unsigned short)(GC_gc_no - UNMAP_THRESHOLD);
 
409
        threshold = (unsigned short)(GC_gc_no - MUNMAP_THRESHOLD);
379
410
        last_rec = hhdr -> hb_last_reclaimed;
380
411
        if ((last_rec > GC_gc_no || last_rec < threshold)
381
412
            && threshold < GC_gc_no /* not recently wrapped */) {
405
436
        next = (struct hblk *)((word)h + size);
406
437
        GET_HDR(next, nexthdr);
407
438
        /* Coalesce with successor, if possible */
408
 
          if (0 != nexthdr && HBLK_IS_FREE(nexthdr)) {
409
 
            nextsize = nexthdr -> hb_sz;
 
439
          if (0 != nexthdr && HBLK_IS_FREE(nexthdr)
 
440
              && (signed_word) (size + (nextsize = nexthdr->hb_sz)) > 0
 
441
                 /* no pot. overflow */) {
410
442
            if (IS_MAPPED(hhdr)) {
411
443
              GC_ASSERT(!IS_MAPPED(nexthdr));
412
444
              /* make both consistent, so that we can merge */
455
487
 * The header for the returned block must be set up by the caller.
456
488
 * If the return value is not 0, then hhdr is the header for it.
457
489
 */
458
 
struct hblk * GC_get_first_part(h, hhdr, bytes, index)
459
 
struct hblk *h;
460
 
hdr * hhdr;
461
 
word bytes;
462
 
int index;
 
490
struct hblk * GC_get_first_part(struct hblk *h, hdr *hhdr,
 
491
                                size_t bytes, int index)
463
492
{
464
493
    word total_size = hhdr -> hb_sz;
465
494
    struct hblk * rest;
471
500
    rest = (struct hblk *)((word)h + bytes);
472
501
    rest_hdr = GC_install_header(rest);
473
502
    if (0 == rest_hdr) {
474
 
        /* This may be very bad news ... */
 
503
        /* FIXME: This is likely to be very bad news ... */
475
504
        WARN("Header allocation failed: Dropping block.\n", 0);
476
505
        return(0);
477
506
    }
479
508
    rest_hdr -> hb_flags = 0;
480
509
#   ifdef GC_ASSERTIONS
481
510
      /* Mark h not free, to avoid assertion about adjacent free blocks. */
482
 
        hhdr -> hb_map = 0;
 
511
        hhdr -> hb_flags &= ~FREE_BLK;
483
512
#   endif
484
513
    GC_add_to_fl(rest, rest_hdr);
485
514
    return h;
497
526
 * (Hence adding it to a free list is silly.  But this path is hopefully
498
527
 * rare enough that it doesn't matter.  The code is cleaner this way.)
499
528
 */
500
 
void GC_split_block(h, hhdr, n, nhdr, index)
501
 
struct hblk *h;
502
 
hdr * hhdr;
503
 
struct hblk *n;
504
 
hdr * nhdr;
505
 
int index;      /* Index of free list */
 
529
void GC_split_block(struct hblk *h, hdr *hhdr, struct hblk *n,
 
530
                    hdr *nhdr, int index /* Index of free list */)
506
531
{
507
532
    word total_size = hhdr -> hb_sz;
508
533
    word h_size = (word)n - (word)h;
525
550
      INCR_FREE_BYTES(index, -(signed_word)h_size);
526
551
      FREE_ASSERT(GC_free_bytes[index] > 0);
527
552
#     ifdef GC_ASSERTIONS
528
 
        nhdr -> hb_map = 0;     /* Don't fail test for consecutive      */
 
553
        nhdr -> hb_flags &= ~FREE_BLK;
 
554
                                /* Don't fail test for consecutive      */
529
555
                                /* free blocks in GC_add_to_fl.         */
530
556
#     endif
531
557
#   ifdef USE_MUNMAP
533
559
#   endif
534
560
    hhdr -> hb_sz = h_size;
535
561
    GC_add_to_fl(h, hhdr);
536
 
    GC_invalidate_map(nhdr);
 
562
    nhdr -> hb_flags |= FREE_BLK;
537
563
}
538
564
        
539
 
struct hblk * GC_allochblk_nth();
 
565
struct hblk *
 
566
GC_allochblk_nth(size_t sz/* bytes */, int kind, unsigned flags, int n,
 
567
                 GC_bool may_split);
540
568
 
541
569
/*
542
570
 * Allocate (and return pointer to) a heap block
543
 
 *   for objects of size sz words, searching the nth free list.
 
571
 *   for objects of size sz bytes, searching the nth free list.
544
572
 *
545
573
 * NOTE: We set obj_map field in header correctly.
546
574
 *       Caller is responsible for building an object freelist in block.
547
575
 *
548
 
 * Unlike older versions of the collectors, the client is responsible
549
 
 * for clearing the block, if necessary.
 
576
 * The client is responsible for clearing the block, if necessary.
550
577
 */
551
578
struct hblk *
552
 
GC_allochblk(sz, kind, flags)
553
 
word sz;
554
 
int kind;
555
 
unsigned flags;  /* IGNORE_OFF_PAGE or 0 */
 
579
GC_allochblk(size_t sz, int kind, unsigned flags/* IGNORE_OFF_PAGE or 0 */)
556
580
{
557
 
    word blocks = OBJ_SZ_TO_BLOCKS(sz);
558
 
    int start_list = GC_hblk_fl_from_blocks(blocks);
 
581
    word blocks;
 
582
    int start_list;
559
583
    int i;
560
 
    for (i = start_list; i <= N_HBLK_FLS; ++i) {
561
 
        struct hblk * result = GC_allochblk_nth(sz, kind, flags, i);
562
 
        if (0 != result) {
563
 
            return result;
 
584
    struct hblk *result;
 
585
    int split_limit; /* Highest index of free list whose blocks we      */
 
586
                     /* split.                                          */
 
587
 
 
588
    GC_ASSERT((sz & (GRANULE_BYTES - 1)) == 0);
 
589
    blocks = OBJ_SZ_TO_BLOCKS(sz);
 
590
    if ((signed_word)(blocks * HBLKSIZE) < 0) {
 
591
      return 0;
 
592
    }
 
593
    start_list = GC_hblk_fl_from_blocks(blocks);
 
594
    /* Try for an exact match first. */
 
595
    result = GC_allochblk_nth(sz, kind, flags, start_list, FALSE);
 
596
    if (0 != result) return result;
 
597
    if (GC_use_entire_heap || GC_dont_gc
 
598
        || USED_HEAP_SIZE < GC_requested_heapsize
 
599
        || TRUE_INCREMENTAL || !GC_should_collect()) {
 
600
        /* Should use more of the heap, even if it requires splitting. */
 
601
        split_limit = N_HBLK_FLS;
 
602
    } else {
 
603
#     ifdef USE_MUNMAP
 
604
        /* avoid splitting, since that might require remapping */
 
605
        split_limit = 0;
 
606
#     else
 
607
        if (GC_finalizer_bytes_freed > (GC_heapsize >> 4))  {
 
608
          /* If we are deallocating lots of memory from         */
 
609
          /* finalizers, fail and collect sooner rather         */
 
610
          /* than later.                                        */
 
611
          split_limit = 0;
 
612
        } else {
 
613
          /* If we have enough large blocks left to cover any   */
 
614
          /* previous request for large blocks, we go ahead     */
 
615
          /* and split.  Assuming a steady state, that should   */
 
616
          /* be safe.  It means that we can use the full        */
 
617
          /* heap if we allocate only small objects.            */
 
618
          split_limit = GC_enough_large_bytes_left();
564
619
        }
 
620
#     endif
 
621
    }
 
622
    if (start_list < UNIQUE_THRESHOLD) {
 
623
      /* No reason to try start_list again, since all blocks are exact  */
 
624
      /* matches.                                                       */
 
625
      ++start_list;
 
626
    }
 
627
    for (i = start_list; i <= split_limit; ++i) {
 
628
        struct hblk * result = GC_allochblk_nth(sz, kind, flags, i, TRUE);
 
629
        if (0 != result) return result;
565
630
    }
566
631
    return 0;
567
632
}
568
633
/*
569
634
 * The same, but with search restricted to nth free list.
 
635
 * Flags is IGNORE_OFF_PAGE or zero.
 
636
 * Unlike the above, sz is in bytes.
 
637
 * The may_split flag indicates whether it's OK to split larger blocks.
570
638
 */
571
639
struct hblk *
572
 
GC_allochblk_nth(sz, kind, flags, n)
573
 
word sz;
574
 
int kind;
575
 
unsigned char flags;  /* IGNORE_OFF_PAGE or 0 */
576
 
int n;
 
640
GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n, GC_bool may_split)
577
641
{
578
 
    register struct hblk *hbp;
579
 
    register hdr * hhdr;                /* Header corr. to hbp */
580
 
    register struct hblk *thishbp;
581
 
    register hdr * thishdr;             /* Header corr. to hbp */
 
642
    struct hblk *hbp;
 
643
    hdr * hhdr;         /* Header corr. to hbp */
 
644
                        /* Initialized after loop if hbp !=0    */
 
645
                        /* Gcc uninitialized use warning is bogus.      */
 
646
    struct hblk *thishbp;
 
647
    hdr * thishdr;              /* Header corr. to hbp */
582
648
    signed_word size_needed;    /* number of bytes in requested objects */
583
649
    signed_word size_avail;     /* bytes available in this block        */
584
650
 
590
656
            GET_HDR(hbp, hhdr);
591
657
            size_avail = hhdr->hb_sz;
592
658
            if (size_avail < size_needed) continue;
593
 
            if (size_avail != size_needed
594
 
                && !GC_use_entire_heap
595
 
                && !GC_dont_gc
596
 
                && USED_HEAP_SIZE >= GC_requested_heapsize
597
 
                && !TRUE_INCREMENTAL && GC_should_collect()) {
598
 
#               ifdef USE_MUNMAP
599
 
                    continue;
600
 
#               else
601
 
                    /* If we have enough large blocks left to cover any */
602
 
                    /* previous request for large blocks, we go ahead   */
603
 
                    /* and split.  Assuming a steady state, that should */
604
 
                    /* be safe.  It means that we can use the full      */
605
 
                    /* heap if we allocate only small objects.          */
606
 
                    if (!GC_enough_large_bytes_left(GC_large_allocd_bytes, n)) {
607
 
                      continue;
608
 
                    } 
609
 
                    /* If we are deallocating lots of memory from       */
610
 
                    /* finalizers, fail and collect sooner rather       */
611
 
                    /* than later.                                      */
612
 
                    if (WORDS_TO_BYTES(GC_finalizer_mem_freed)
613
 
                        > (GC_heapsize >> 4))  {
614
 
                      continue;
615
 
                    }
616
 
#               endif /* !USE_MUNMAP */
617
 
            }
618
 
            /* If the next heap block is obviously better, go on.       */
619
 
            /* This prevents us from disassembling a single large block */
620
 
            /* to get tiny blocks.                                      */
621
 
            {
 
659
            if (size_avail != size_needed) {
622
660
              signed_word next_size;
623
 
              
 
661
 
 
662
              if (!may_split) continue;
 
663
              /* If the next heap block is obviously better, go on.     */
 
664
              /* This prevents us from disassembling a single large block */
 
665
              /* to get tiny blocks.                                    */
624
666
              thishbp = hhdr -> hb_next;
625
667
              if (thishbp != 0) {
626
 
                GET_HDR(thishbp, thishdr);
 
668
                GET_HDR(thishbp, thishdr);
627
669
                next_size = (signed_word)(thishdr -> hb_sz);
628
670
                if (next_size < size_avail
629
 
                  && next_size >= size_needed
630
 
                  && !GC_is_black_listed(thishbp, (word)size_needed)) {
631
 
                  continue;
 
671
                    && next_size >= size_needed
 
672
                    && !GC_is_black_listed(thishbp, (word)size_needed)) {
 
673
                    continue;
632
674
                }
633
675
              }
634
676
            }
700
742
                      struct hblk * h;
701
743
                      struct hblk * prev = hhdr -> hb_prev;
702
744
                      
703
 
                      GC_words_wasted += BYTES_TO_WORDS(total_size);
704
745
                      GC_large_free_bytes -= total_size;
 
746
                      GC_bytes_dropped += total_size;
705
747
                      GC_remove_from_fl(hhdr, n);
706
748
                      for (h = hbp; h < limit; h++) {
707
749
                        if (h == hbp || 0 != (hhdr = GC_install_header(h))) {
708
750
                          (void) setup_header(
709
 
                                  hhdr,
710
 
                                  BYTES_TO_WORDS(HBLKSIZE),
 
751
                                  hhdr, h,
 
752
                                  HBLKSIZE,
711
753
                                  PTRFREE, 0); /* Cant fail */
712
754
                          if (GC_debugging_started) {
713
755
                            BZERO(h, HBLKSIZE);
717
759
                    /* Restore hbp to point at free block */
718
760
                      hbp = prev;
719
761
                      if (0 == hbp) {
720
 
                        return GC_allochblk_nth(sz, kind, flags, n);
 
762
                        return GC_allochblk_nth(sz, kind, flags, n, may_split);
721
763
                      }
722
764
                      hhdr = HDR(hbp);
723
765
                  }
729
771
                  if (!IS_MAPPED(hhdr)) {
730
772
                    GC_remap((ptr_t)hbp, hhdr -> hb_sz);
731
773
                    hhdr -> hb_flags &= ~WAS_UNMAPPED;
 
774
                    /* Note: This may leave adjacent, mapped free blocks. */
732
775
                  }
733
776
#               endif
734
777
                /* hbp may be on the wrong freelist; the parameter n    */
745
788
        /* This leaks memory under very rare conditions. */
746
789
                
747
790
    /* Set up header */
748
 
        if (!setup_header(hhdr, sz, kind, flags)) {
 
791
        if (!setup_header(hhdr, hbp, sz, kind, flags)) {
749
792
            GC_remove_counts(hbp, (word)size_needed);
750
793
            return(0); /* ditto */
751
794
        }
779
822
 * All mark words are assumed to be cleared.
780
823
 */
781
824
void
782
 
GC_freehblk(hbp)
783
 
struct hblk *hbp;
 
825
GC_freehblk(struct hblk *hbp)
784
826
{
785
827
struct hblk *next, *prev;
786
828
hdr *hhdr, *prevhdr, *nexthdr;
790
832
    GET_HDR(hbp, hhdr);
791
833
    size = hhdr->hb_sz;
792
834
    size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(size);
 
835
    if (size <= 0)
 
836
      ABORT("Deallocating excessively large block.  Too large an allocation?");
 
837
      /* Probably possible if we try to allocate more than half the address */
 
838
      /* space at once.  If we dont catch it here, strange things happen    */
 
839
      /* later.                                                             */
793
840
    GC_remove_counts(hbp, (word)size);
794
841
    hhdr->hb_sz = size;
795
842
#   ifdef USE_MUNMAP
798
845
    
799
846
    /* Check for duplicate deallocation in the easy case */
800
847
      if (HBLK_IS_FREE(hhdr)) {
801
 
        GC_printf1("Duplicate large block deallocation of 0x%lx\n",
802
 
                   (unsigned long) hbp);
 
848
        GC_printf("Duplicate large block deallocation of %p\n", hbp);
803
849
        ABORT("Duplicate large block deallocation");
804
850
      }
805
851
 
806
852
    GC_ASSERT(IS_MAPPED(hhdr));
807
 
    GC_invalidate_map(hhdr);
 
853
    hhdr -> hb_flags |= FREE_BLK;
808
854
    next = (struct hblk *)((word)hbp + size);
809
855
    GET_HDR(next, nexthdr);
810
856
    prev = GC_free_block_ending_at(hbp);
811
857
    /* Coalesce with successor, if possible */
812
 
      if(0 != nexthdr && HBLK_IS_FREE(nexthdr) && IS_MAPPED(nexthdr)) {
 
858
      if(0 != nexthdr && HBLK_IS_FREE(nexthdr) && IS_MAPPED(nexthdr)
 
859
         && (signed_word)(hhdr -> hb_sz + nexthdr -> hb_sz) > 0
 
860
         /* no overflow */) {
813
861
        GC_remove_from_fl(nexthdr, FL_UNKNOWN);
814
862
        hhdr -> hb_sz += nexthdr -> hb_sz; 
815
863
        GC_remove_header(next);
817
865
    /* Coalesce with predecessor, if possible. */
818
866
      if (0 != prev) {
819
867
        prevhdr = HDR(prev);
820
 
        if (IS_MAPPED(prevhdr)) {
 
868
        if (IS_MAPPED(prevhdr)
 
869
            && (signed_word)(hhdr -> hb_sz + prevhdr -> hb_sz) > 0) {
821
870
          GC_remove_from_fl(prevhdr, FL_UNKNOWN);
822
871
          prevhdr -> hb_sz += hhdr -> hb_sz;
823
872
#         ifdef USE_MUNMAP