Skip to content

Commit 89ef316

Browse files
authored
map: use voidptr-based key equality and meta index methods (vlang#7320)
1 parent 999fe84 commit 89ef316

1 file changed

Lines changed: 32 additions & 20 deletions

File tree

vlib/builtin/map.v

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,8 @@ fn (mut d DenseArray) zeros_to_end() {
194194
}
195195

196196
pub struct map {
197+
// Number of bytes of a key
198+
key_bytes int
197199
// Number of bytes of a value
198200
value_bytes int
199201
mut:
@@ -219,12 +221,14 @@ pub mut:
219221

220222
fn new_map_1(value_bytes int) map {
221223
metasize := int(sizeof(u32) * (init_capicity + extra_metas_inc))
224+
key_bytes := int(sizeof(string))
222225
return map{
226+
key_bytes: key_bytes
223227
value_bytes: value_bytes
224228
cap: init_cap
225229
cached_hashbits: max_cached_hashbits
226230
shift: init_log_capicity
227-
key_values: new_dense_array(int(sizeof(string)), value_bytes)
231+
key_values: new_dense_array(key_bytes, value_bytes)
228232
metas: &u32(vcalloc(metasize))
229233
extra_metas: extra_metas_inc
230234
len: 0
@@ -240,7 +244,14 @@ fn new_map_init(n int, value_bytes int, keys &string, values voidptr) map {
240244
}
241245

242246
[inline]
243-
fn (m &map) key_to_index(key string) (u32, u32) {
247+
fn (m &map) keys_eq(a voidptr, b voidptr) bool {
248+
// assume string for now
249+
return fast_string_eq(*&string(a), *&string(b))
250+
}
251+
252+
[inline]
253+
fn (m &map) key_to_index(pkey voidptr) (u32, u32) {
254+
key := *&string(pkey)
244255
hash := hash.wyhash_c(key.str, u64(key.len), 0)
245256
index := hash & m.cap
246257
meta := ((hash >> m.shift) & hash_mask) | probe_inc
@@ -311,23 +322,23 @@ fn (mut m map) set(k string, value voidptr) {
311322
if load_factor > max_load_factor {
312323
m.expand()
313324
}
314-
mut index, mut meta := m.key_to_index(key)
325+
mut index, mut meta := m.key_to_index(&key)
315326
index, meta = m.meta_less(index, meta)
316327
// While we might have a match
317328
for meta == unsafe {m.metas[index]} {
318329
kv_index := int(unsafe {m.metas[index + 1]})
319-
pkey := unsafe {&string(m.key_values.key(kv_index))}
320-
if fast_string_eq(key, *pkey) {
330+
pkey := unsafe {m.key_values.key(kv_index)}
331+
if m.keys_eq(&key, pkey) {
321332
unsafe {
322-
pval := pkey + 1 // skip string
333+
pval := byteptr(pkey) + m.key_bytes
323334
C.memcpy(pval, value, m.value_bytes)
324335
}
325336
return
326337
}
327338
index += 2
328339
meta += probe_inc
329340
}
330-
kv_index := m.key_values.push(key, value)
341+
kv_index := m.key_values.push(&key, value)
331342
m.meta_greater(index, meta, u32(kv_index))
332343
m.len++
333344
}
@@ -363,8 +374,8 @@ fn (mut m map) rehash() {
363374
if !m.key_values.has_index(i) {
364375
continue
365376
}
366-
pkey := unsafe {&string(m.key_values.key(i))}
367-
mut index, mut meta := m.key_to_index(*pkey)
377+
pkey := unsafe {m.key_values.key(i)}
378+
mut index, mut meta := m.key_to_index(pkey)
368379
index, meta = m.meta_less(index, meta)
369380
m.meta_greater(index, meta, u32(i))
370381
}
@@ -398,12 +409,12 @@ fn (mut m map) cached_rehash(old_cap u32) {
398409
// If the key exists, its respective value is returned.
399410
fn (mut m map) get_and_set(key string, zero voidptr) voidptr {
400411
for {
401-
mut index, mut meta := m.key_to_index(key)
412+
mut index, mut meta := m.key_to_index(&key)
402413
for {
403414
if meta == unsafe {m.metas[index]} {
404415
kv_index := int(unsafe {m.metas[index + 1]})
405-
pkey := unsafe {&string(m.key_values.key(kv_index))}
406-
if fast_string_eq(key, *pkey) {
416+
pkey := unsafe {m.key_values.key(kv_index)}
417+
if m.keys_eq(&key, pkey) {
407418
return unsafe {byteptr(pkey) + m.key_values.key_bytes}
408419
}
409420
}
@@ -424,12 +435,12 @@ fn (mut m map) get_and_set(key string, zero voidptr) voidptr {
424435
// the method returns a reference to its mapped value.
425436
// If not, a zero/default value is returned.
426437
fn (m map) get(key string, zero voidptr) voidptr {
427-
mut index, mut meta := m.key_to_index(key)
438+
mut index, mut meta := m.key_to_index(&key)
428439
for {
429440
if meta == unsafe {m.metas[index]} {
430441
kv_index := int(unsafe {m.metas[index + 1]})
431-
pkey := unsafe {&string(m.key_values.key(kv_index))}
432-
if fast_string_eq(key, *pkey) {
442+
pkey := unsafe {m.key_values.key(kv_index)}
443+
if m.keys_eq(&key, pkey) {
433444
return unsafe {byteptr(pkey) + m.key_values.key_bytes}
434445
}
435446
}
@@ -444,12 +455,12 @@ fn (m map) get(key string, zero voidptr) voidptr {
444455

445456
// Checks whether a particular key exists in the map.
446457
fn (m map) exists(key string) bool {
447-
mut index, mut meta := m.key_to_index(key)
458+
mut index, mut meta := m.key_to_index(&key)
448459
for {
449460
if meta == unsafe {m.metas[index]} {
450461
kv_index := int(unsafe {m.metas[index + 1]})
451-
pkey := unsafe {&string(m.key_values.key(kv_index))}
452-
if fast_string_eq(key, *pkey) {
462+
pkey := unsafe {m.key_values.key(kv_index)}
463+
if m.keys_eq(&key, pkey) {
453464
return true
454465
}
455466
}
@@ -464,13 +475,13 @@ fn (m map) exists(key string) bool {
464475

465476
// Removes the mapping of a particular key from the map.
466477
pub fn (mut m map) delete(key string) {
467-
mut index, mut meta := m.key_to_index(key)
478+
mut index, mut meta := m.key_to_index(&key)
468479
index, meta = m.meta_less(index, meta)
469480
// Perform backwards shifting
470481
for meta == unsafe {m.metas[index]} {
471482
kv_index := int(unsafe {m.metas[index + 1]})
472483
pkey := unsafe {&string(m.key_values.key(kv_index))}
473-
if fast_string_eq(key, *pkey) {
484+
if m.keys_eq(&key, pkey) {
474485
for (unsafe {m.metas[index + 2]} >> hashbits) > 1 {
475486
unsafe {
476487
m.metas[index] = m.metas[index + 2] - probe_inc
@@ -554,6 +565,7 @@ pub fn (d DenseArray) clone() DenseArray {
554565
pub fn (m map) clone() map {
555566
metasize := int(sizeof(u32) * (m.cap + 2 + m.extra_metas))
556567
res := map{
568+
key_bytes: m.key_bytes
557569
value_bytes: m.value_bytes
558570
cap: m.cap
559571
cached_hashbits: m.cached_hashbits

0 commit comments

Comments
 (0)