1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
(* TEST
*)
let () = Random.init 12345
let size, num_gcs =
1000, 20
type block = int array
type objdata =
| Present of block
| Absent of int (* GC count at time of erase *)
type bunch = {
objs : objdata array;
wp : block Weak.t;
}
let data =
Array.init size (fun i ->
let n = 1 + Random.int size in
{
objs = Array.make n (Absent 0);
wp = Weak.create n;
}
)
let gccount () = (Gc.quick_stat ()).Gc.major_collections
type change = No_change | Fill | Erase
(* Check the correctness condition on the data at (i,j):
1. if the block is present, the weak pointer must be full
2. if the block was removed at GC n, and the weak pointer is still
full, then the current GC must be at most n+2.
(could have promotion from minor during n+1 which keeps alive in n+1,
so will die at n+2)
Then modify the data in one of the following ways:
1. if the block and weak pointer are absent, fill them
2. if the block and weak pointer are present, randomly erase the block
*)
let check_and_change i j =
let gc1 = gccount () in
let change =
(* we only read data.(i).objs.(j) in this local binding to ensure
that it does not remain reachable on the bytecode stack
in the rest of the function below, when we overwrite the value
and try to observe its collection. *)
match data.(i).objs.(j), Weak.check data.(i).wp j with
| Present x, false -> assert false
| Absent n, true -> assert (gc1 <= n+2); No_change
| Absent _, false -> Fill
| Present _, true ->
if Random.int 10 = 0 then Erase else No_change
in
begin match change with
| No_change -> ()
| Fill ->
let x = Array.make (1 + Random.int 10) 42 in
data.(i).objs.(j) <- Present x;
Weak.set data.(i).wp j (Some x);
| Erase ->
data.(i).objs.(j) <- Absent gc1;
let gc2 = gccount () in
if gc1 <> gc2 then data.(i).objs.(j) <- Absent gc2;
end
let dummy = ref [||]
let () =
while gccount () < num_gcs do
dummy := Array.make (Random.int 300) 0;
let i = Random.int size in
let j = Random.int (Array.length data.(i).objs) in
check_and_change i j;
done
|