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