1 | // "noscan" versions of `map` initialization routines |
2 | // |
3 | // They are used when the compiler can proof that either the keys or the values or both |
4 | // do not contain any pointers. Such objects can be placed in a memory area that is not |
5 | // scanned by the garbage collector |
6 | |
7 | module builtin |
8 | |
9 | [inline] |
10 | fn __malloc_at_least_one(how_many_bytes u64, noscan bool) &u8 { |
11 | if noscan { |
12 | return unsafe { malloc_noscan(__at_least_one(how_many_bytes)) } |
13 | } |
14 | return unsafe { malloc(__at_least_one(how_many_bytes)) } |
15 | } |
16 | |
17 | [inline] |
18 | fn new_dense_array_noscan(key_bytes int, key_noscan bool, value_bytes int, value_noscan bool) DenseArray { |
19 | cap := 8 |
20 | return DenseArray{ |
21 | key_bytes: key_bytes |
22 | value_bytes: value_bytes |
23 | cap: cap |
24 | len: 0 |
25 | deletes: 0 |
26 | all_deleted: 0 |
27 | keys: __malloc_at_least_one(u64(cap) * u64(key_bytes), key_noscan) |
28 | values: __malloc_at_least_one(u64(cap) * u64(value_bytes), value_noscan) |
29 | } |
30 | } |
31 | |
32 | fn new_map_noscan_key(key_bytes int, value_bytes int, hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn) map { |
33 | metasize := int(sizeof(u32) * (init_capicity + extra_metas_inc)) |
34 | // for now assume anything bigger than a pointer is a string |
35 | has_string_keys := key_bytes > sizeof(voidptr) |
36 | return map{ |
37 | key_bytes: key_bytes |
38 | value_bytes: value_bytes |
39 | even_index: init_even_index |
40 | cached_hashbits: max_cached_hashbits |
41 | shift: init_log_capicity |
42 | key_values: new_dense_array_noscan(key_bytes, true, value_bytes, false) |
43 | metas: unsafe { &u32(vcalloc_noscan(metasize)) } |
44 | extra_metas: extra_metas_inc |
45 | len: 0 |
46 | has_string_keys: has_string_keys |
47 | hash_fn: hash_fn |
48 | key_eq_fn: key_eq_fn |
49 | clone_fn: clone_fn |
50 | free_fn: free_fn |
51 | } |
52 | } |
53 | |
54 | fn new_map_noscan_value(key_bytes int, value_bytes int, hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn) map { |
55 | metasize := int(sizeof(u32) * (init_capicity + extra_metas_inc)) |
56 | // for now assume anything bigger than a pointer is a string |
57 | has_string_keys := key_bytes > sizeof(voidptr) |
58 | return map{ |
59 | key_bytes: key_bytes |
60 | value_bytes: value_bytes |
61 | even_index: init_even_index |
62 | cached_hashbits: max_cached_hashbits |
63 | shift: init_log_capicity |
64 | key_values: new_dense_array_noscan(key_bytes, false, value_bytes, true) |
65 | metas: unsafe { &u32(vcalloc_noscan(metasize)) } |
66 | extra_metas: extra_metas_inc |
67 | len: 0 |
68 | has_string_keys: has_string_keys |
69 | hash_fn: hash_fn |
70 | key_eq_fn: key_eq_fn |
71 | clone_fn: clone_fn |
72 | free_fn: free_fn |
73 | } |
74 | } |
75 | |
76 | fn new_map_noscan_key_value(key_bytes int, value_bytes int, hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn) map { |
77 | metasize := int(sizeof(u32) * (init_capicity + extra_metas_inc)) |
78 | // for now assume anything bigger than a pointer is a string |
79 | has_string_keys := key_bytes > sizeof(voidptr) |
80 | return map{ |
81 | key_bytes: key_bytes |
82 | value_bytes: value_bytes |
83 | even_index: init_even_index |
84 | cached_hashbits: max_cached_hashbits |
85 | shift: init_log_capicity |
86 | key_values: new_dense_array_noscan(key_bytes, true, value_bytes, true) |
87 | metas: unsafe { &u32(vcalloc_noscan(metasize)) } |
88 | extra_metas: extra_metas_inc |
89 | len: 0 |
90 | has_string_keys: has_string_keys |
91 | hash_fn: hash_fn |
92 | key_eq_fn: key_eq_fn |
93 | clone_fn: clone_fn |
94 | free_fn: free_fn |
95 | } |
96 | } |
97 | |
98 | fn new_map_init_noscan_key(hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn, n int, key_bytes int, value_bytes int, keys voidptr, values voidptr) map { |
99 | mut out := new_map_noscan_key(key_bytes, value_bytes, hash_fn, key_eq_fn, clone_fn, |
100 | free_fn) |
101 | // TODO pre-allocate n slots |
102 | mut pkey := &u8(keys) |
103 | mut pval := &u8(values) |
104 | for _ in 0 .. n { |
105 | unsafe { |
106 | out.set(pkey, pval) |
107 | pkey = pkey + key_bytes |
108 | pval = pval + value_bytes |
109 | } |
110 | } |
111 | return out |
112 | } |
113 | |
114 | fn new_map_init_noscan_value(hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn, n int, key_bytes int, value_bytes int, keys voidptr, values voidptr) map { |
115 | mut out := new_map_noscan_value(key_bytes, value_bytes, hash_fn, key_eq_fn, clone_fn, |
116 | free_fn) |
117 | // TODO pre-allocate n slots |
118 | mut pkey := &u8(keys) |
119 | mut pval := &u8(values) |
120 | for _ in 0 .. n { |
121 | unsafe { |
122 | out.set(pkey, pval) |
123 | pkey = pkey + key_bytes |
124 | pval = pval + value_bytes |
125 | } |
126 | } |
127 | return out |
128 | } |
129 | |
130 | fn new_map_init_noscan_key_value(hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn, n int, key_bytes int, value_bytes int, keys voidptr, values voidptr) map { |
131 | mut out := new_map_noscan_key_value(key_bytes, value_bytes, hash_fn, key_eq_fn, clone_fn, |
132 | free_fn) |
133 | // TODO pre-allocate n slots |
134 | mut pkey := &u8(keys) |
135 | mut pval := &u8(values) |
136 | for _ in 0 .. n { |
137 | unsafe { |
138 | out.set(pkey, pval) |
139 | pkey = pkey + key_bytes |
140 | pval = pval + value_bytes |
141 | } |
142 | } |
143 | return out |
144 | } |