new_hblk.c 6.16 KB
Newer Older
eg's avatar
eg committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
 * Copyright (c) 2000 by Hewlett-Packard Company.  All rights reserved.
 *
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 *
 * Permission is hereby granted to use or copy this program
 * for any purpose,  provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is granted,
 * provided the above notices are retained, and a notice that the code was
 * modified is included with the above copyright notice.
 */

16
#include "private/gc_priv.h"
eg's avatar
eg committed
17 18

/*
19 20 21
 * This file contains the functions:
 *      ptr_t GC_build_flXXX(h, old_fl)
 *      void GC_new_hblk(size)
eg's avatar
eg committed
22
 */
23 24 25 26 27 28 29 30 31

#include <stdio.h>

#ifndef SMALL_CONFIG
  /* Build a free list for size 2 (words) cleared objects inside        */
  /* hblk h.  Set the last link to be ofl.  Return a pointer to the     */
  /* first free list entry.                                             */
  STATIC ptr_t GC_build_fl_clear2(struct hblk *h, ptr_t ofl)
  {
eg's avatar
eg committed
32 33
    word * p = (word *)(h -> hb_body);
    word * lim = (word *)(h + 1);
34

eg's avatar
eg committed
35 36 37 38 39
    p[0] = (word)ofl;
    p[1] = 0;
    p[2] = (word)p;
    p[3] = 0;
    p += 4;
40
    for (; (word)p < (word)lim; p += 4) {
eg's avatar
eg committed
41 42 43 44 45 46
        p[0] = (word)(p-2);
        p[1] = 0;
        p[2] = (word)p;
        p[3] = 0;
    };
    return((ptr_t)(p-2));
47
  }
eg's avatar
eg committed
48

49 50 51
  /* The same for size 4 cleared objects.       */
  STATIC ptr_t GC_build_fl_clear4(struct hblk *h, ptr_t ofl)
  {
eg's avatar
eg committed
52 53
    word * p = (word *)(h -> hb_body);
    word * lim = (word *)(h + 1);
54

eg's avatar
eg committed
55 56 57 58 59
    p[0] = (word)ofl;
    p[1] = 0;
    p[2] = 0;
    p[3] = 0;
    p += 4;
60 61
    for (; (word)p < (word)lim; p += 4) {
        GC_PREFETCH_FOR_WRITE((ptr_t)(p + 64));
eg's avatar
eg committed
62 63
        p[0] = (word)(p-4);
        p[1] = 0;
64
        CLEAR_DOUBLE(p+2);
eg's avatar
eg committed
65 66
    };
    return((ptr_t)(p-4));
67
  }
eg's avatar
eg committed
68

69 70 71
  /* The same for size 2 uncleared objects.     */
  STATIC ptr_t GC_build_fl2(struct hblk *h, ptr_t ofl)
  {
eg's avatar
eg committed
72 73
    word * p = (word *)(h -> hb_body);
    word * lim = (word *)(h + 1);
74

eg's avatar
eg committed
75 76 77
    p[0] = (word)ofl;
    p[2] = (word)p;
    p += 4;
78
    for (; (word)p < (word)lim; p += 4) {
eg's avatar
eg committed
79 80 81 82
        p[0] = (word)(p-2);
        p[2] = (word)p;
    };
    return((ptr_t)(p-2));
83
  }
eg's avatar
eg committed
84

85 86 87
  /* The same for size 4 uncleared objects.     */
  STATIC ptr_t GC_build_fl4(struct hblk *h, ptr_t ofl)
  {
eg's avatar
eg committed
88 89
    word * p = (word *)(h -> hb_body);
    word * lim = (word *)(h + 1);
90

eg's avatar
eg committed
91 92 93
    p[0] = (word)ofl;
    p[4] = (word)p;
    p += 8;
94 95
    for (; (word)p < (word)lim; p += 8) {
        GC_PREFETCH_FOR_WRITE((ptr_t)(p + 64));
eg's avatar
eg committed
96 97 98 99
        p[0] = (word)(p-4);
        p[4] = (word)p;
    };
    return((ptr_t)(p-4));
100
  }
eg's avatar
eg committed
101 102
#endif /* !SMALL_CONFIG */

103 104 105 106 107 108 109 110
/* Build a free list for objects of size sz inside heap block h.        */
/* Clear objects inside h if clear is set.  Add list to the end of      */
/* the free list we build.  Return the new free list.                   */
/* This could be called without the main GC lock, if we ensure that     */
/* there is no concurrent collection which might reclaim objects that   */
/* we have not yet allocated.                                           */
GC_INNER ptr_t GC_build_fl(struct hblk *h, size_t sz, GC_bool clear,
                           ptr_t list)
eg's avatar
eg committed
111 112
{
  word *p, *prev;
113 114 115 116 117 118 119 120 121 122 123 124 125
  word *last_object;            /* points to last object in new hblk    */

  /* Do a few prefetches here, just because its cheap.          */
  /* If we were more serious about it, these should go inside   */
  /* the loops.  But write prefetches usually don't seem to     */
  /* matter much.                                               */
    GC_PREFETCH_FOR_WRITE((ptr_t)h);
    GC_PREFETCH_FOR_WRITE((ptr_t)h + 128);
    GC_PREFETCH_FOR_WRITE((ptr_t)h + 256);
    GC_PREFETCH_FOR_WRITE((ptr_t)h + 378);
# ifndef SMALL_CONFIG
    /* Handle small objects sizes more efficiently.  For larger objects */
    /* the difference is less significant.                              */
eg's avatar
eg committed
126 127
    switch (sz) {
        case 2: if (clear) {
128 129 130 131
                    return GC_build_fl_clear2(h, list);
                } else {
                    return GC_build_fl2(h, list);
                }
eg's avatar
eg committed
132
        case 4: if (clear) {
133 134 135 136
                    return GC_build_fl_clear4(h, list);
                } else {
                    return GC_build_fl4(h, list);
                }
eg's avatar
eg committed
137
        default:
138
                break;
eg's avatar
eg committed
139
    }
140 141
# endif /* !SMALL_CONFIG */

eg's avatar
eg committed
142 143
  /* Clear the page if necessary. */
    if (clear) BZERO(h, HBLKSIZE);
144

eg's avatar
eg committed
145
  /* Add objects to free list */
146 147
    p = (word *)(h -> hb_body) + sz;    /* second object in *h  */
    prev = (word *)(h -> hb_body);              /* One object behind p  */
eg's avatar
eg committed
148 149
    last_object = (word *)((char *)h + HBLKSIZE);
    last_object -= sz;
150
                            /* Last place for last object to start */
eg's avatar
eg committed
151 152

  /* make a list of all objects in *h with head as last object */
153
    while ((word)p <= (word)last_object) {
eg's avatar
eg committed
154 155
      /* current object's link points to last object */
        obj_link(p) = (ptr_t)prev;
156 157
        prev = p;
        p += sz;
eg's avatar
eg committed
158
    }
159
    p -= sz;                    /* p now points to last object */
eg's avatar
eg committed
160

161 162 163 164 165
  /* Put p (which is now head of list of objects in *h) as first    */
  /* pointer in the appropriate free list for this size.            */
    *(ptr_t *)h = list;
    return ((ptr_t)p);
}
eg's avatar
eg committed
166

167 168 169 170 171
/* Allocate a new heapblock for small objects of size gran granules.    */
/* Add all of the heapblock's objects to the free list for objects      */
/* of that size.  Set all mark bits if objects are uncollectible.       */
/* Will fail to do anything if we are out of memory.                    */
GC_INNER void GC_new_hblk(size_t gran, int kind)
eg's avatar
eg committed
172
{
173
  struct hblk *h;       /* the new heap block */
eg's avatar
eg committed
174
  GC_bool clear = GC_obj_kinds[kind].ok_init;
eg's avatar
eg committed
175

eg's avatar
eg committed
176
  GC_STATIC_ASSERT((sizeof (struct hblk)) == HBLKSIZE);
177

eg's avatar
eg committed
178 179 180
  if (GC_debugging_started) clear = TRUE;

  /* Allocate a new heap block */
eg's avatar
eg committed
181
    h = GC_allochblk(GRANULES_TO_BYTES(gran), kind, 0);
eg's avatar
eg committed
182 183 184 185 186 187
    if (h == 0) return;

  /* Mark all objects if appropriate. */
      if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h));

  /* Build the free list */
eg's avatar
eg committed
188
      GC_obj_kinds[kind].ok_freelist[gran] =
189 190
        GC_build_fl(h, GRANULES_TO_WORDS(gran), clear,
                    GC_obj_kinds[kind].ok_freelist[gran]);
eg's avatar
eg committed
191
}