1 /**************************************************************************/
2 /*                                                                        */
3 /*                                 OCaml                                  */
4 /*                                                                        */
5 /*             Damien Doligez, projet Para, INRIA Rocquencourt            */
6 /*                                                                        */
7 /*   Copyright 1997 Institut National de Recherche en Informatique et     */
8 /*     en Automatique.                                                    */
9 /*                                                                        */
10 /*   All rights reserved.  This file is distributed under the terms of    */
11 /*   the GNU Lesser General Public License version 2.1, with the          */
12 /*   special exception on linking described in the file LICENSE.          */
13 /*                                                                        */
14 /**************************************************************************/
15 
16 /* Operations on weak arrays */
17 
18 #ifndef CAML_WEAK_H
19 #define CAML_WEAK_H
20 
21 #ifdef CAML_INTERNALS
22 
23 #include "mlvalues.h"
24 
25 extern value caml_ephe_list_head;
26 extern value caml_ephe_none;
27 
28 
29 /** The first field 0:  weak list;
30        second field 1:  data;
31        others       2..:  keys;
32 
33     A weak pointer is an ephemeron with the data at caml_ephe_none
34     If fields are added, don't forget to update weak.ml [additional_values].
35  */
36 
37 #define CAML_EPHE_LINK_OFFSET 0
38 #define CAML_EPHE_DATA_OFFSET 1
39 #define CAML_EPHE_FIRST_KEY 2
40 
41 
42 /* In the header, in order to let major_gc.c
43    and weak.c see the body of the function */
caml_ephe_clean(value v)44 static inline void caml_ephe_clean (value v){
45   value child;
46   int release_data = 0;
47   mlsize_t size, i;
48   header_t hd;
49                                     Assert(caml_gc_phase == Phase_clean);
50 
51   hd = Hd_val (v);
52   size = Wosize_hd (hd);
53   for (i = 2; i < size; i++){
54     child = Field (v, i);
55   ephemeron_again:
56     if (child != caml_ephe_none
57         && Is_block (child) && Is_in_heap_or_young (child)){
58       if (Tag_val (child) == Forward_tag){
59         value f = Forward_val (child);
60         if (Is_block (f)) {
61           if (!Is_in_value_area(f) || Tag_val (f) == Forward_tag
62               || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag){
63             /* Do not short-circuit the pointer. */
64           }else{
65             Field (v, i) = child = f;
66             if (Is_block (f) && Is_young (f))
67               add_to_ephe_ref_table(&caml_ephe_ref_table, v, i);
68             goto ephemeron_again;
69           }
70         }
71       }
72       if (Is_white_val (child) && !Is_young (child)){
73         release_data = 1;
74         Field (v, i) = caml_ephe_none;
75       }
76     }
77   }
78 
79   child = Field (v, 1);
80   if(child != caml_ephe_none){
81       if (release_data){
82         Field (v, 1) = caml_ephe_none;
83       } else {
84         /* The mark phase must have marked it */
85         Assert( !(Is_block (child) && Is_in_heap (child)
86                   && Is_white_val (child)) );
87       }
88   }
89 }
90 
91 #endif /* CAML_INTERNALS */
92 
93 #endif /* CAML_WEAK_H */
94