@@ -374,24 +374,25 @@ again:
374
374
}
375
375
b := (* bmap )(unsafe .Pointer (uintptr (h .buckets ) + bucket * uintptr (t .bucketsize )))
376
376
377
- var inserti * uint8
377
+ var insertb * bmap
378
+ var inserti uintptr
378
379
var insertk unsafe.Pointer
379
- var val unsafe. Pointer
380
+
380
381
for {
381
382
for i := uintptr (0 ); i < bucketCnt ; i ++ {
382
383
if b .tophash [i ] == empty {
383
- if inserti == nil {
384
- inserti = & b .tophash [i ]
385
- insertk = add (unsafe .Pointer (b ), dataOffset + i * 4 )
386
- val = add (unsafe .Pointer (b ), dataOffset + bucketCnt * 4 + i * uintptr (t .valuesize ))
384
+ if insertb == nil {
385
+ inserti = i
386
+ insertb = b
387
387
}
388
388
continue
389
389
}
390
390
k := * ((* uint32 )(add (unsafe .Pointer (b ), dataOffset + i * 4 )))
391
391
if k != key {
392
392
continue
393
393
}
394
- val = add (unsafe .Pointer (b ), dataOffset + bucketCnt * 4 + i * uintptr (t .valuesize ))
394
+ inserti = i
395
+ insertb = b
395
396
goto done
396
397
}
397
398
ovf := b .overflow (t )
@@ -410,25 +411,25 @@ again:
410
411
goto again // Growing the table invalidates everything, so try again
411
412
}
412
413
413
- if inserti == nil {
414
+ if insertb == nil {
414
415
// all current buckets are full, allocate a new one.
415
- newb := h .newoverflow (t , b )
416
- inserti = & newb .tophash [0 ]
417
- insertk = add (unsafe .Pointer (newb ), dataOffset )
418
- val = add (insertk , bucketCnt * 4 )
416
+ insertb = h .newoverflow (t , b )
417
+ inserti = 0 // not necessary, but avoids needlessly spilling inserti
419
418
}
419
+ insertb .tophash [inserti & (bucketCnt - 1 )] = tophash (hash ) // mask inserti to avoid bounds checks
420
420
421
+ insertk = add (unsafe .Pointer (insertb ), dataOffset + inserti * 4 )
421
422
// store new key at insert position
422
423
if sys .PtrSize == 4 && t .key .kind & kindNoPointers == 0 && writeBarrier .enabled {
423
424
writebarrierptr ((* uintptr )(insertk ), uintptr (key ))
424
425
} else {
425
426
* (* uint32 )(insertk ) = key
426
427
}
427
428
428
- * inserti = tophash (hash )
429
429
h .count ++
430
430
431
431
done:
432
+ val := add (unsafe .Pointer (insertb ), dataOffset + bucketCnt * 4 + inserti * uintptr (t .valuesize ))
432
433
if h .flags & hashWriting == 0 {
433
434
throw ("concurrent map writes" )
434
435
}
@@ -463,24 +464,25 @@ again:
463
464
}
464
465
b := (* bmap )(unsafe .Pointer (uintptr (h .buckets ) + bucket * uintptr (t .bucketsize )))
465
466
466
- var inserti * uint8
467
+ var insertb * bmap
468
+ var inserti uintptr
467
469
var insertk unsafe.Pointer
468
- var val unsafe. Pointer
470
+
469
471
for {
470
472
for i := uintptr (0 ); i < bucketCnt ; i ++ {
471
473
if b .tophash [i ] == empty {
472
- if inserti == nil {
473
- inserti = & b .tophash [i ]
474
- insertk = add (unsafe .Pointer (b ), dataOffset + i * 8 )
475
- val = add (unsafe .Pointer (b ), dataOffset + bucketCnt * 8 + i * uintptr (t .valuesize ))
474
+ if insertb == nil {
475
+ insertb = b
476
+ inserti = i
476
477
}
477
478
continue
478
479
}
479
480
k := * ((* uint64 )(add (unsafe .Pointer (b ), dataOffset + i * 8 )))
480
481
if k != key {
481
482
continue
482
483
}
483
- val = add (unsafe .Pointer (b ), dataOffset + bucketCnt * 8 + i * uintptr (t .valuesize ))
484
+ insertb = b
485
+ inserti = i
484
486
goto done
485
487
}
486
488
ovf := b .overflow (t )
@@ -499,14 +501,14 @@ again:
499
501
goto again // Growing the table invalidates everything, so try again
500
502
}
501
503
502
- if inserti == nil {
504
+ if insertb == nil {
503
505
// all current buckets are full, allocate a new one.
504
- newb := h .newoverflow (t , b )
505
- inserti = & newb .tophash [0 ]
506
- insertk = add (unsafe .Pointer (newb ), dataOffset )
507
- val = add (insertk , bucketCnt * 8 )
506
+ insertb = h .newoverflow (t , b )
507
+ inserti = 0 // not necessary, but avoids needlessly spilling inserti
508
508
}
509
+ insertb .tophash [inserti & (bucketCnt - 1 )] = tophash (hash ) // mask inserti to avoid bounds checks
509
510
511
+ insertk = add (unsafe .Pointer (insertb ), dataOffset + inserti * 8 )
510
512
// store new key at insert position
511
513
if t .key .kind & kindNoPointers == 0 && writeBarrier .enabled {
512
514
if sys .PtrSize == 8 {
@@ -520,18 +522,18 @@ again:
520
522
* (* uint64 )(insertk ) = key
521
523
}
522
524
523
- * inserti = tophash (hash )
524
525
h .count ++
525
526
526
527
done:
528
+ val := add (unsafe .Pointer (insertb ), dataOffset + bucketCnt * 8 + inserti * uintptr (t .valuesize ))
527
529
if h .flags & hashWriting == 0 {
528
530
throw ("concurrent map writes" )
529
531
}
530
532
h .flags &^= hashWriting
531
533
return val
532
534
}
533
535
534
- func mapassign_faststr (t * maptype , h * hmap , ky string ) unsafe.Pointer {
536
+ func mapassign_faststr (t * maptype , h * hmap , s string ) unsafe.Pointer {
535
537
if h == nil {
536
538
panic (plainError ("assignment to entry in nil map" ))
537
539
}
@@ -542,8 +544,8 @@ func mapassign_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer {
542
544
if h .flags & hashWriting != 0 {
543
545
throw ("concurrent map writes" )
544
546
}
545
- key := stringStructOf (& ky )
546
- hash := t .key .alg .hash (noescape (unsafe .Pointer (& ky )), uintptr (h .hash0 ))
547
+ key := stringStructOf (& s )
548
+ hash := t .key .alg .hash (noescape (unsafe .Pointer (& s )), uintptr (h .hash0 ))
547
549
548
550
// Set hashWriting after calling alg.hash for consistency with mapassign.
549
551
h .flags |= hashWriting
@@ -560,16 +562,16 @@ again:
560
562
b := (* bmap )(unsafe .Pointer (uintptr (h .buckets ) + bucket * uintptr (t .bucketsize )))
561
563
top := tophash (hash )
562
564
563
- var inserti * uint8
565
+ var insertb * bmap
566
+ var inserti uintptr
564
567
var insertk unsafe.Pointer
565
- var val unsafe. Pointer
568
+
566
569
for {
567
570
for i := uintptr (0 ); i < bucketCnt ; i ++ {
568
571
if b .tophash [i ] != top {
569
- if b .tophash [i ] == empty && inserti == nil {
570
- inserti = & b .tophash [i ]
571
- insertk = add (unsafe .Pointer (b ), dataOffset + i * 2 * sys .PtrSize )
572
- val = add (unsafe .Pointer (b ), dataOffset + bucketCnt * 2 * sys .PtrSize + i * uintptr (t .valuesize ))
572
+ if b .tophash [i ] == empty && insertb == nil {
573
+ insertb = b
574
+ inserti = i
573
575
}
574
576
continue
575
577
}
@@ -581,7 +583,8 @@ again:
581
583
continue
582
584
}
583
585
// already have a mapping for key. Update it.
584
- val = add (unsafe .Pointer (b ), dataOffset + bucketCnt * 2 * sys .PtrSize + i * uintptr (t .valuesize ))
586
+ inserti = i
587
+ insertb = b
585
588
goto done
586
589
}
587
590
ovf := b .overflow (t )
@@ -600,20 +603,20 @@ again:
600
603
goto again // Growing the table invalidates everything, so try again
601
604
}
602
605
603
- if inserti == nil {
606
+ if insertb == nil {
604
607
// all current buckets are full, allocate a new one.
605
- newb := h .newoverflow (t , b )
606
- inserti = & newb .tophash [0 ]
607
- insertk = add (unsafe .Pointer (newb ), dataOffset )
608
- val = add (insertk , bucketCnt * 2 * sys .PtrSize )
608
+ insertb = h .newoverflow (t , b )
609
+ inserti = 0 // not necessary, but avoids needlessly spilling inserti
609
610
}
611
+ insertb .tophash [inserti & (bucketCnt - 1 )] = top // mask inserti to avoid bounds checks
610
612
613
+ insertk = add (unsafe .Pointer (insertb ), dataOffset + inserti * 2 * sys .PtrSize )
611
614
// store new key at insert position
612
615
* ((* stringStruct )(insertk )) = * key
613
- * inserti = top
614
616
h .count ++
615
617
616
618
done:
619
+ val := add (unsafe .Pointer (insertb ), dataOffset + bucketCnt * 2 * sys .PtrSize + inserti * uintptr (t .valuesize ))
617
620
if h .flags & hashWriting == 0 {
618
621
throw ("concurrent map writes" )
619
622
}
0 commit comments