Back to index

plt-scheme  4.2.1
weak.c
Go to the documentation of this file.
00001 
00002 /* 
00003    Provides:
00004       GC_malloc_weak_array
00005       size_weak_array, mark_weak_array, fixup_weak_array
00006       init_weak_arrays zero_weak_arrays
00007       GC_malloc_weak_box
00008       size_weak_box, mark_weak_box, fixup_weak_box
00009       init_weak_boxes zero_weak_boxes
00010       GC_malloc_ephemeron
00011       size_ephemeron, mark_ephemeron, fixup_ephemeron
00012       BTC_ephemeron_mark [ifdef NEW_BTC_ACCOUNT]
00013       init_ephemerons mark_ready_ephemerons zero_remaining_ephemerons
00014       num_last_seen_ephemerons
00015    Requires:
00016       weak_array_tag
00017       weak_box_tag
00018       ephemeron_tag
00019       is_marked(p)
00020       Type_Tag
00021 */
00022 
00023 
00024 /******************************************************************************/
00025 /*                               weak arrays                                  */
00026 /******************************************************************************/
00027 
00028 static int size_weak_array(void *p)
00029 {
00030   GC_Weak_Array *a = (GC_Weak_Array *)p;
00031 
00032   return gcBYTES_TO_WORDS(sizeof(GC_Weak_Array) 
00033                        + ((a->count - 1) * sizeof(void *)));
00034 }
00035 
00036 static int mark_weak_array(void *p)
00037 {
00038   GCTYPE *gc = GC_get_GC();
00039   GC_Weak_Array *a = (GC_Weak_Array *)p;
00040 
00041   gcMARK(a->replace_val);
00042 
00043   a->next = gc->weak_arrays;
00044   gc->weak_arrays = a;
00045 
00046 #if CHECKS
00047   /* For now, weak arrays only used for symbols, keywords, and falses: */
00048   {
00049     void **data;
00050     int i;
00051     data = a->data;
00052     for (i = a->count; i--; ) {
00053       if (data[i] 
00054          && (*(short *)(data[i]) != 48)
00055          && (*(short *)(data[i]) != 49)
00056          && (*(short *)(data[i]) != 58)) {
00057        CRASH(1);
00058       }
00059     }
00060   }
00061 #endif
00062 
00063   return gcBYTES_TO_WORDS(sizeof(GC_Weak_Array) 
00064                        + ((a->count - 1) * sizeof(void *)));
00065 }
00066 
00067 static int fixup_weak_array(void *p)
00068 {
00069   GC_Weak_Array *a = (GC_Weak_Array *)p;
00070   int i;
00071   void **data;
00072 
00073   gcFIXUP(a->replace_val);
00074 
00075   data = a->data;
00076   for (i = a->count; i--; ) {
00077     if (data[i])
00078       gcFIXUP(data[i]);
00079   }
00080 
00081   return gcBYTES_TO_WORDS(sizeof(GC_Weak_Array) 
00082                        + ((a->count - 1) * sizeof(void *)));
00083 }
00084 
00085 void *GC_malloc_weak_array(size_t size_in_bytes, void *replace_val)
00086 {
00087   GCTYPE *gc = GC_get_GC();
00088   GC_Weak_Array *w;
00089 
00090   /* Allcation might trigger GC, so we use park: */
00091   gc->park[0] = replace_val;
00092 
00093   w = (GC_Weak_Array *)GC_malloc_one_tagged(size_in_bytes 
00094                                        + sizeof(GC_Weak_Array) 
00095                                        - sizeof(void *));
00096 
00097   replace_val = gc->park[0];
00098   gc->park[0] = NULL;
00099 
00100   w->type = gc->weak_array_tag;
00101   w->replace_val = replace_val;
00102   w->count = (size_in_bytes >> LOG_WORD_SIZE);
00103   
00104   return w;
00105 }
00106 
00107 static void init_weak_arrays(GCTYPE *gc) {
00108   gc->weak_arrays = NULL;
00109 }
00110 
00111 static void zero_weak_arrays(GCTYPE *gc)
00112 {
00113   GC_Weak_Array *wa;
00114   int i;
00115 
00116   wa = gc->weak_arrays;
00117   while (wa) {
00118     void **data;
00119 
00120     data = wa->data;
00121     for (i = wa->count; i--; ) {
00122       void *p = data[i];
00123       if (p && !is_marked(gc, p))
00124         data[i] = wa->replace_val;
00125     }
00126 
00127     wa = wa->next;
00128   }
00129 }
00130 
00131 /******************************************************************************/
00132 /*                                weak boxes                                  */
00133 /******************************************************************************/
00134 
00135 static int size_weak_box(void *p)
00136 {
00137   return gcBYTES_TO_WORDS(sizeof(GC_Weak_Box));
00138 }
00139 
00140 static int mark_weak_box(void *p)
00141 {
00142   GCTYPE *gc = GC_get_GC();
00143   GC_Weak_Box *wb = (GC_Weak_Box *)p;
00144     
00145   gcMARK(wb->secondary_erase);
00146 
00147   if (wb->val) {
00148     wb->next = gc->weak_boxes;
00149     gc->weak_boxes = wb;
00150   }
00151 
00152   return gcBYTES_TO_WORDS(sizeof(GC_Weak_Box));
00153 }
00154 
00155 static int fixup_weak_box(void *p)
00156 {
00157   GC_Weak_Box *wb = (GC_Weak_Box *)p;
00158     
00159   gcFIXUP(wb->secondary_erase);
00160   gcFIXUP(wb->val);
00161 
00162   return gcBYTES_TO_WORDS(sizeof(GC_Weak_Box));
00163 }
00164 
00165 void *GC_malloc_weak_box(void *p, void **secondary, int soffset)
00166 {
00167   GCTYPE *gc = GC_get_GC();
00168   GC_Weak_Box *w;
00169 
00170   /* Allcation might trigger GC, so we use park: */
00171   gc->park[0] = p;
00172   gc->park[1] = secondary;
00173 
00174   w = (GC_Weak_Box *)GC_malloc_one_tagged(sizeof(GC_Weak_Box));
00175 
00176   p = gc->park[0];
00177   secondary = (void **)gc->park[1];
00178   gc->park[0] = NULL;
00179   gc->park[1] = NULL;
00180   
00181   w->type = gc->weak_box_tag;
00182   w->val = p;
00183   w->secondary_erase = secondary;
00184   w->soffset = soffset;
00185 
00186   return w;
00187 }
00188 
00189 static void init_weak_boxes(GCTYPE *gc) {
00190   gc->weak_boxes = NULL;
00191 }
00192 
00193 static void zero_weak_boxes(GCTYPE *gc)
00194 {
00195   GC_Weak_Box *wb;
00196 
00197   wb = gc->weak_boxes;
00198   while (wb) {
00199     if (!is_marked(gc, wb->val)) {
00200       wb->val = NULL;
00201       if (wb->secondary_erase) {
00202         void **p;
00203         p = (void **)GC_resolve(wb->secondary_erase);
00204         *(p + wb->soffset) = NULL;
00205         wb->secondary_erase = NULL;
00206       }
00207     }
00208     wb = wb->next;
00209   }
00210 }
00211 
00212 /******************************************************************************/
00213 /*                                 ephemeron                                  */
00214 /******************************************************************************/
00215 
00216 static int size_ephemeron(void *p)
00217 {
00218   return gcBYTES_TO_WORDS(sizeof(GC_Ephemeron));
00219 }
00220 
00221 static int mark_ephemeron(void *p)
00222 {
00223   GCTYPE *gc = GC_get_GC();
00224   GC_Ephemeron *eph = (GC_Ephemeron *)p;
00225 
00226   if (eph->val) {
00227     eph->next = gc->ephemerons;
00228     gc->ephemerons = eph;
00229   }
00230 
00231   return gcBYTES_TO_WORDS(sizeof(GC_Ephemeron));
00232 }
00233 
00234 #ifdef NEWGC_BTC_ACCOUNT
00235 static int BTC_ephemeron_mark(void *p)
00236 {
00237   GCTYPE *gc = GC_get_GC();
00238   if (gc->doing_memory_accounting) {
00239 
00240     GC_Ephemeron *eph = (GC_Ephemeron *)p;
00241 
00242     gcMARK(eph->key);
00243     gcMARK(eph->val);
00244 
00245     return gcBYTES_TO_WORDS(sizeof(GC_Ephemeron));
00246   }
00247   return mark_ephemeron(p);
00248 }
00249 #endif
00250 
00251 
00252 static int fixup_ephemeron(void *p)
00253 {
00254   GC_Ephemeron *eph = (GC_Ephemeron *)p;
00255     
00256   gcFIXUP(eph->key);
00257   gcFIXUP(eph->val);
00258 
00259   return gcBYTES_TO_WORDS(sizeof(GC_Ephemeron));
00260 }
00261 
00262 void *GC_malloc_ephemeron(void *k, void *v)
00263 {
00264   GCTYPE *gc = GC_get_GC();
00265   GC_Ephemeron *eph;
00266 
00267   /* Allcation might trigger GC, so we use park: */
00268   gc->park[0] = k;
00269   gc->park[1] = v;
00270 
00271   eph = (GC_Ephemeron *)GC_malloc_one_tagged(sizeof(GC_Ephemeron));
00272 
00273   k = gc->park[0];
00274   v = gc->park[1];
00275   gc->park[0] = NULL;
00276   gc->park[1] = NULL;
00277   
00278   eph->type = gc->ephemeron_tag;
00279   eph->key = k;
00280   eph->val = v;
00281 
00282   return eph;
00283 }
00284 
00285 void init_ephemerons(GCTYPE *gc) {
00286   gc->ephemerons = NULL;
00287   gc->num_last_seen_ephemerons = 0;
00288 }
00289 
00290 static void mark_ready_ephemerons(GCTYPE *gc)
00291 {
00292   GC_Ephemeron *waiting = NULL, *next, *eph;
00293 
00294   for (eph = gc->ephemerons; eph; eph = next) {
00295     next = eph->next;
00296     if (is_marked(gc, eph->key)) {
00297       gcMARK(eph->val);
00298       gc->num_last_seen_ephemerons++;
00299     } else {
00300       eph->next = waiting;
00301       waiting = eph;
00302     }
00303   }
00304   gc->ephemerons = waiting;
00305 }
00306 
00307 static void zero_remaining_ephemerons(GCTYPE *gc)
00308 {
00309   GC_Ephemeron *eph;
00310 
00311   /* After unordered finalization, any remaining ephemerons
00312      should be zeroed. */
00313   for (eph = gc->ephemerons; eph; eph = eph->next) {
00314     eph->key = NULL;
00315     eph->val = NULL;
00316   }
00317 }