v4 / vlib / v / tests / fns / closure_context_boehm_root_test.c.v
162 lines · 147 sloc · 3.08 KB · 1a2d0e5b70d6dd1baaa60290f2446e9ece4324bf
Raw
1struct CapturedValueReceiver {
2 value int
3}
4
5fn (r CapturedValueReceiver) get() int {
6 return r.value
7}
8
9@[heap]
10struct CapturedPointerReceiver {
11 value int
12}
13
14fn (r &CapturedPointerReceiver) get() int {
15 return r.value
16}
17
18fn stored_anon_closure() fn () int {
19 value := 27445
20 return fn [value] () int {
21 return value
22 }
23}
24
25fn stored_value_method_closure() fn () int {
26 receiver := CapturedValueReceiver{
27 value: 27445
28 }
29 return receiver.get
30}
31
32fn stored_pointer_method_closure() fn () int {
33 receiver := &CapturedPointerReceiver{
34 value: 27445
35 }
36 return receiver.get
37}
38
39fn collect_and_churn() {
40 $if gcboehm ? {
41 C.GC_gcollect()
42 }
43 for _ in 0 .. 1000 {
44 unsafe {
45 p := malloc(16)
46 vmemset(p, 0x33, 16)
47 }
48 }
49 $if gcboehm ? {
50 C.GC_gcollect()
51 }
52}
53
54fn test_stored_closure_contexts_survive_boehm_collection() {
55 anon_cb := stored_anon_closure()
56 value_method_cb := stored_value_method_closure()
57 pointer_method_cb := stored_pointer_method_closure()
58 collect_and_churn()
59 assert anon_cb() == 27445
60 assert value_method_cb() == 27445
61 assert pointer_method_cb() == 27445
62}
63
64fn consume_with_return(n int) int {
65 big := []int{len: 200, init: index + n}
66 h := fn [big] (x int) int {
67 return big[x % big.len]
68 }
69 if n >= 0 {
70 return h(n % 200)
71 }
72 return 0
73}
74
75fn consume_with_call_then_return(n int) int {
76 big := []int{len: 200, init: index + n}
77 h := fn [big] (x int) int {
78 return big[x % big.len]
79 }
80 _ = h(n % 200)
81 return 0
82}
83
84fn consume_with_labeled_break(n int) int {
85 mut value := 0
86 inner: for {
87 big := []int{len: 200, init: index + n}
88 h := fn [big] (x int) int {
89 return big[x % big.len]
90 }
91 value = h(n % 200)
92 break inner
93 }
94 return value
95}
96
97fn consume_with_labeled_continue(n int) int {
98 mut value := 0
99 outer: for _ in 0 .. 1 {
100 big := []int{len: 200, init: index + n}
101 h := fn [big] (x int) int {
102 return big[x % big.len]
103 }
104 value = h(n % 200)
105 continue outer
106 }
107 return value
108}
109
110fn test_issue_27445_local_closure_contexts_do_not_accumulate() {
111 $if gcboehm ? {
112 gc_collect()
113 start_mb := gc_memory_use() / 1024 / 1024
114 for n in 0 .. 80_000 {
115 big := []int{len: 200, init: index + n}
116 h := fn [big] (x int) int {
117 return big[x % big.len]
118 }
119 _ = h(n % 200)
120 if n % 20_000 == 0 {
121 gc_collect()
122 }
123 }
124 gc_collect()
125 end_mb := gc_memory_use() / 1024 / 1024
126 assert end_mb <= start_mb + 24
127 }
128}
129
130fn test_issue_27445_return_paths_with_local_closure_do_not_accumulate() {
131 $if gcboehm ? {
132 gc_collect()
133 start_mb := gc_memory_use() / 1024 / 1024
134 for n in 0 .. 80_000 {
135 _ = consume_with_return(n)
136 _ = consume_with_call_then_return(n)
137 if n % 20_000 == 0 {
138 gc_collect()
139 }
140 }
141 gc_collect()
142 end_mb := gc_memory_use() / 1024 / 1024
143 assert end_mb <= start_mb + 24
144 }
145}
146
147fn test_issue_27445_labeled_branches_with_local_closure_do_not_accumulate() {
148 $if gcboehm ? {
149 gc_collect()
150 start_mb := gc_memory_use() / 1024 / 1024
151 for n in 0 .. 80_000 {
152 _ = consume_with_labeled_break(n)
153 _ = consume_with_labeled_continue(n)
154 if n % 20_000 == 0 {
155 gc_collect()
156 }
157 }
158 gc_collect()
159 end_mb := gc_memory_use() / 1024 / 1024
160 assert end_mb <= start_mb + 24
161 }
162}
163