v / vlib / builtin
Raw file | 144 loc (135 sloc) | 4.55 KB | Latest commit hash fc5826b7c
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
7module builtin
8
9[inline]
10fn __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]
18fn 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
32fn 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
54fn 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
76fn 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
98fn 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
114fn 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
130fn 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}