LEFT | RIGHT |
(no file at all) | |
| 1 // Copyright 2013 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. |
| 4 |
| 5 // Fast hashmap lookup specialized to a specific key type. |
| 6 // Included by hashmap.c once for each specialized type. |
| 7 |
| 8 // Note that this code differs from hash_lookup in that |
| 9 // it returns a pointer to the result, not the result itself. |
| 10 // The returned pointer is only valid until the next GC |
| 11 // point, so the caller must dereference it before then. |
| 12 |
| 13 // +build ignore |
| 14 |
| 15 #pragma textflag 7 |
| 16 void |
| 17 HASH_LOOKUP1(MapType *t, Hmap *h, KEYTYPE key, byte *value) |
| 18 { |
| 19 uintptr hash; |
| 20 uintptr bucket; |
| 21 Bucket *b; |
| 22 uint8 top; |
| 23 uintptr i; |
| 24 KEYTYPE *k; |
| 25 byte *v; |
| 26 |
| 27 if(debug) { |
| 28 runtime·prints("runtime.mapaccess1_fastXXX: map="); |
| 29 runtime·printpointer(h); |
| 30 runtime·prints("; key="); |
| 31 t->key->alg->print(t->key->size, &key); |
| 32 runtime·prints("\n"); |
| 33 } |
| 34 if(h == nil || h->count == 0) { |
| 35 value = empty_value; |
| 36 FLUSH(&value); |
| 37 return; |
| 38 } |
| 39 if(raceenabled) |
| 40 runtime·racereadpc(h, runtime·getcallerpc(&t), HASH_LOOKUP1); |
| 41 if(docheck) |
| 42 check(t, h); |
| 43 |
| 44 if(h->B == 0 && (h->count == 1 || QUICKEQ(key))) { |
| 45 // One-bucket table. Don't hash, just check each bucket entry. |
| 46 b = (Bucket*)h->buckets; |
| 47 for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i
< BUCKETSIZE; i++, k++, v += h->valuesize) { |
| 48 if(b->tophash[i] != 0 && EQFUNC(key, *k)) { |
| 49 value = v; |
| 50 FLUSH(&value); |
| 51 return; |
| 52 } |
| 53 } |
| 54 } else { |
| 55 hash = h->hash0; |
| 56 HASHFUNC(&hash, sizeof(KEYTYPE), &key); |
| 57 bucket = hash & (((uintptr)1 << h->B) - 1); |
| 58 if(h->oldbuckets != nil) |
| 59 grow_work(t, h, bucket); |
| 60 b = (Bucket*)(h->buckets + bucket * (offsetof(Bucket, data[0]) +
BUCKETSIZE * sizeof(KEYTYPE) + BUCKETSIZE * h->valuesize)); |
| 61 top = hash >> (sizeof(uintptr)*8 - 8); |
| 62 if(top == 0) |
| 63 top = 1; |
| 64 do { |
| 65 for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKET
SIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) { |
| 66 if(b->tophash[i] == top && EQFUNC(key, *k)) { |
| 67 value = v; |
| 68 FLUSH(&value); |
| 69 return; |
| 70 } |
| 71 } |
| 72 b = b->overflow; |
| 73 } while(b != nil); |
| 74 } |
| 75 value = empty_value; |
| 76 FLUSH(&value); |
| 77 } |
| 78 |
| 79 #pragma textflag 7 |
| 80 void |
| 81 HASH_LOOKUP2(MapType *t, Hmap *h, KEYTYPE key, byte *value, bool res) |
| 82 { |
| 83 uintptr hash; |
| 84 uintptr bucket; |
| 85 Bucket *b; |
| 86 uint8 top; |
| 87 uintptr i; |
| 88 KEYTYPE *k; |
| 89 byte *v; |
| 90 |
| 91 if(debug) { |
| 92 runtime·prints("runtime.mapaccess2_fastXXX: map="); |
| 93 runtime·printpointer(h); |
| 94 runtime·prints("; key="); |
| 95 t->key->alg->print(t->key->size, &key); |
| 96 runtime·prints("\n"); |
| 97 } |
| 98 if(h == nil || h->count == 0) { |
| 99 value = empty_value; |
| 100 res = false; |
| 101 FLUSH(&value); |
| 102 FLUSH(&res); |
| 103 return; |
| 104 } |
| 105 if(raceenabled) |
| 106 runtime·racereadpc(h, runtime·getcallerpc(&t), HASH_LOOKUP2); |
| 107 if(docheck) |
| 108 check(t, h); |
| 109 |
| 110 if(h->B == 0 && (h->count == 1 || QUICKEQ(key))) { |
| 111 // One-bucket table. Don't hash, just check each bucket entry. |
| 112 b = (Bucket*)h->buckets; |
| 113 for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i
< BUCKETSIZE; i++, k++, v += h->valuesize) { |
| 114 if(b->tophash[i] != 0 && EQFUNC(key, *k)) { |
| 115 value = v; |
| 116 res = true; |
| 117 FLUSH(&value); |
| 118 FLUSH(&res); |
| 119 return; |
| 120 } |
| 121 } |
| 122 } else { |
| 123 hash = h->hash0; |
| 124 HASHFUNC(&hash, sizeof(KEYTYPE), &key); |
| 125 bucket = hash & (((uintptr)1 << h->B) - 1); |
| 126 if(h->oldbuckets != nil) |
| 127 grow_work(t, h, bucket); |
| 128 b = (Bucket*)(h->buckets + bucket * (offsetof(Bucket, data[0]) +
BUCKETSIZE * sizeof(KEYTYPE) + BUCKETSIZE * h->valuesize)); |
| 129 top = hash >> (sizeof(uintptr)*8 - 8); |
| 130 if(top == 0) |
| 131 top = 1; |
| 132 do { |
| 133 for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKET
SIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) { |
| 134 if(b->tophash[i] == top && EQFUNC(key, *k)) { |
| 135 value = v; |
| 136 res = true; |
| 137 FLUSH(&value); |
| 138 FLUSH(&res); |
| 139 return; |
| 140 } |
| 141 } |
| 142 b = b->overflow; |
| 143 } while(b != nil); |
| 144 } |
| 145 value = empty_value; |
| 146 res = false; |
| 147 FLUSH(&value); |
| 148 FLUSH(&res); |
| 149 } |
LEFT | RIGHT |