Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(4750)

Delta Between Two Patch Sets: src/pkg/runtime/hashmap.c

Issue 6137051: code review 6137051: runtime: fix hashmap code for large key size (Closed)
Left Patch Set: diff -r 9d046474e95a https://go.googlecode.com/hg/ Created 12 years, 11 months ago
Right Patch Set: diff -r 09fe7345e11d https://go.googlecode.com/hg/ Created 12 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | test/cmp.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 #include "runtime.h" 5 #include "runtime.h"
6 #include "hashmap.h" 6 #include "hashmap.h"
7 #include "type.h" 7 #include "type.h"
8 8
9 struct Hmap { /* a hash table; initialize with hash_init() */ 9 struct Hmap { /* a hash table; initialize with hash_init() */
10 uint32 count; /* elements in table - must be first */ 10 uint32 count; /* elements in table - must be first */
11 » uint32 datasize; /* amount of data to store in entry */ 11 » uint8 datasize; /* amount of data to store in entry */
12 uint8 max_power; /* max power of 2 to create sub-tables */ 12 uint8 max_power; /* max power of 2 to create sub-tables */
13 » uint8 indirectval;» /* storing pointers to values */ 13 » uint8 indirect;»/* storing pointers to keys and/or values */
14 » uint32 valoff;» /* offset of value in key+value data block */ 14 » uint8 valoff;» /* offset of value in key+value data block */
15 int32 changes; /* inc'ed whenever a subtable is created/grown */ 15 int32 changes; /* inc'ed whenever a subtable is created/grown */
16 uintptr hash0; /* hash seed */ 16 uintptr hash0; /* hash seed */
17 struct hash_subtable *st; /* first-level table */ 17 struct hash_subtable *st; /* first-level table */
18 }; 18 };
19 19
20 struct hash_entry { 20 struct hash_entry {
21 hash_hash_t hash; /* hash value of data */ 21 hash_hash_t hash; /* hash value of data */
22 byte data[1]; /* user data has "datasize" bytes */ 22 byte data[1]; /* user data has "datasize" bytes */
23 }; 23 };
24 24
25 struct hash_subtable { 25 struct hash_subtable {
26 uint8 power; /* bits used to index this table */ 26 uint8 power; /* bits used to index this table */
27 uint8 used; /* bits in hash used before reaching this table */ 27 uint8 used; /* bits in hash used before reaching this table */
28 uint8 datasize; /* bytes of client data in an entry */
28 uint8 max_probes; /* max number of probes when searching */ 29 uint8 max_probes; /* max number of probes when searching */
29 int16 limit_bytes; /* max_probes * (datasize+sizeof (hash_hash_t )) */ 30 int16 limit_bytes; /* max_probes * (datasize+sizeof (hash_hash_t )) */
30 uint32 datasize; /* bytes of client data in an entry */
31 struct hash_entry *last; /* points to last element of entry[] */ 31 struct hash_entry *last; /* points to last element of entry[] */
32 struct hash_entry entry[1]; /* 2**power+max_probes-1 elements of elemsi ze bytes */ 32 struct hash_entry entry[1]; /* 2**power+max_probes-1 elements of elemsi ze bytes */
33 }; 33 };
34 34
35 #define HASH_DATA_EQ(eq, t, h,x,y) ((eq)=0, (*t->key->alg->equal) (&(eq), t->key ->size, (x), (y)), (eq)) 35 #define HASH_DATA_EQ(eq, t, h,x,y) ((eq)=0, (*t->key->alg->equal) (&(eq), t->key ->size, (x), (y)), (eq))
36 36
37 #define HASH_REHASH 0x2 /* an internal flag */ 37 #define HASH_REHASH 0x2 /* an internal flag */
38 /* the number of bits used is stored in the flags word too */ 38 /* the number of bits used is stored in the flags word too */
39 #define HASH_USED(x) ((x) >> 2) 39 #define HASH_USED(x) ((x) >> 2)
40 #define HASH_MAKE_USED(x) ((x) << 2) 40 #define HASH_MAKE_USED(x) ((x) << 2)
41 41
42 #define HASH_LOW 6 42 #define HASH_LOW 6
43 #define HASH_ONE (((hash_hash_t)1) << HASH_LOW) 43 #define HASH_ONE (((hash_hash_t)1) << HASH_LOW)
44 #define HASH_MASK (HASH_ONE - 1) 44 #define HASH_MASK (HASH_ONE - 1)
45 #define HASH_ADJUST(x) (((x) < HASH_ONE) << HASH_LOW) 45 #define HASH_ADJUST(x) (((x) < HASH_ONE) << HASH_LOW)
46 46
47 #define HASH_BITS (sizeof (hash_hash_t) * 8) 47 #define HASH_BITS (sizeof (hash_hash_t) * 8)
48 48
49 #define HASH_SUBHASH HASH_MASK 49 #define HASH_SUBHASH HASH_MASK
50 #define HASH_NIL 0 50 #define HASH_NIL 0
51 #define HASH_NIL_MEMSET 0 51 #define HASH_NIL_MEMSET 0
52 52
53 #define HASH_OFFSET(base, byte_offset) \ 53 #define HASH_OFFSET(base, byte_offset) \
54 ((struct hash_entry *) (((byte *) (base)) + (byte_offset))) 54 ((struct hash_entry *) (((byte *) (base)) + (byte_offset)))
55 55
56 #define HASH_MAX_PROBES 15 /* max entries to probe before rehashing */ 56 #define HASH_MAX_PROBES 15 /* max entries to probe before rehashing */
57
58 // Bit masks for Hmap indirect field.
59 #define HASH_INDIRECT_KEY 1
60 #define HASH_INDIRECT_VAL 2
57 61
58 /* return a hash layer with 2**power empty entries */ 62 /* return a hash layer with 2**power empty entries */
59 static struct hash_subtable * 63 static struct hash_subtable *
60 hash_subtable_new (Hmap *h, int32 power, int32 used) 64 hash_subtable_new (Hmap *h, int32 power, int32 used)
61 { 65 {
62 int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]); 66 int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
63 int32 bytes = elemsize << power; 67 int32 bytes = elemsize << power;
64 struct hash_subtable *st; 68 struct hash_subtable *st;
65 int32 limit_bytes = HASH_MAX_PROBES * elemsize; 69 int32 limit_bytes = HASH_MAX_PROBES * elemsize;
66 int32 max_probes = HASH_MAX_PROBES; 70 int32 max_probes = HASH_MAX_PROBES;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 } 104 }
101 *max_power = 12; 105 *max_power = 12;
102 } 106 }
103 107
104 static void 108 static void
105 hash_init (Hmap *h, int32 datasize, int64 hint) 109 hash_init (Hmap *h, int32 datasize, int64 hint)
106 { 110 {
107 int32 init_power; 111 int32 init_power;
108 int32 max_power; 112 int32 max_power;
109 113
110 assert(datasize >= 0);
111 assert(datasize + offsetof(struct hash_entry, data[0]) <= 0x7fffffff);
112 if(datasize < sizeof (void *)) 114 if(datasize < sizeof (void *))
113 datasize = sizeof (void *); 115 datasize = sizeof (void *);
114 datasize = runtime·rnd(datasize, sizeof (void *)); 116 datasize = runtime·rnd(datasize, sizeof (void *));
115 init_sizes (hint, &init_power, &max_power); 117 init_sizes (hint, &init_power, &max_power);
116 h->datasize = datasize; 118 h->datasize = datasize;
117 h->max_power = max_power; 119 h->max_power = max_power;
118 assert (h->datasize == datasize); 120 assert (h->datasize == datasize);
119 assert (h->max_power == max_power); 121 assert (h->max_power == max_power);
120 assert (sizeof (void *) <= h->datasize || h->max_power == 255); 122 assert (sizeof (void *) <= h->datasize || h->max_power == 255);
121 h->count = 0; 123 h->count = 0;
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 static int32 263 static int32
262 hash_lookup (MapType *t, Hmap *h, void *data, void **pres) 264 hash_lookup (MapType *t, Hmap *h, void *data, void **pres)
263 { 265 {
264 int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]); 266 int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
265 hash_hash_t hash; 267 hash_hash_t hash;
266 struct hash_subtable *st = h->st; 268 struct hash_subtable *st = h->st;
267 int32 used = 0; 269 int32 used = 0;
268 hash_hash_t e_hash; 270 hash_hash_t e_hash;
269 struct hash_entry *e; 271 struct hash_entry *e;
270 struct hash_entry *end_e; 272 struct hash_entry *end_e;
273 bool indirectkey;
271 bool eq; 274 bool eq;
272 ········ 275 ········
273 hash = h->hash0; 276 hash = h->hash0;
274 (*t->key->alg->hash) (&hash, t->key->size, data); 277 (*t->key->alg->hash) (&hash, t->key->size, data);
275 hash &= ~HASH_MASK; 278 hash &= ~HASH_MASK;
276 hash += HASH_ADJUST (hash); 279 hash += HASH_ADJUST (hash);
277 for (;;) { 280 for (;;) {
278 int32 shift = HASH_BITS - (st->power + used); 281 int32 shift = HASH_BITS - (st->power + used);
279 int32 index_mask = (1 << st->power) - 1; 282 int32 index_mask = (1 << st->power) - 1;
280 int32 i = (hash >> shift) & index_mask; /* i is the natural p osition of hash */ 283 int32 i = (hash >> shift) & index_mask; /* i is the natural p osition of hash */
281 284
282 e = HASH_OFFSET (st->entry, i * elemsize); /* e points to elemen t i */ 285 e = HASH_OFFSET (st->entry, i * elemsize); /* e points to elemen t i */
283 e_hash = e->hash; 286 e_hash = e->hash;
284 if ((e_hash & HASH_MASK) != HASH_SUBHASH) { /* a subtable * / 287 if ((e_hash & HASH_MASK) != HASH_SUBHASH) { /* a subtable * /
285 break; 288 break;
286 } 289 }
287 used += st->power; 290 used += st->power;
288 st = *(struct hash_subtable **)e->data; 291 st = *(struct hash_subtable **)e->data;
289 } 292 }
290 end_e = HASH_OFFSET (e, st->limit_bytes); 293 end_e = HASH_OFFSET (e, st->limit_bytes);
291 while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) { 294 while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) {
292 e = HASH_OFFSET (e, elemsize); 295 e = HASH_OFFSET (e, elemsize);
293 } 296 }
297 indirectkey = h->indirect & HASH_INDIRECT_KEY;
294 while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) { 298 while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) {
295 » » if (HASH_DATA_EQ (eq, t, h, data, e->data)) { /* a match */ 299 » » void *k = e->data;
300 » » if (indirectkey)
301 » » » k = *(void**)k;
302 » » if (HASH_DATA_EQ (eq, t, h, data, k)) { /* a match */
296 *pres = e->data; 303 *pres = e->data;
297 return (1); 304 return (1);
298 } 305 }
299 e = HASH_OFFSET (e, elemsize); 306 e = HASH_OFFSET (e, elemsize);
300 } 307 }
301 USED(e_hash); 308 USED(e_hash);
302 *pres = 0; 309 *pres = 0;
303 return (0); 310 return (0);
304 } 311 }
305 312
306 static int32 313 static int32
307 hash_remove (MapType *t, Hmap *h, void *data) 314 hash_remove (MapType *t, Hmap *h, void *data)
308 { 315 {
309 int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]); 316 int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
310 hash_hash_t hash; 317 hash_hash_t hash;
311 struct hash_subtable *st = h->st; 318 struct hash_subtable *st = h->st;
312 int32 used = 0; 319 int32 used = 0;
313 hash_hash_t e_hash; 320 hash_hash_t e_hash;
314 struct hash_entry *e; 321 struct hash_entry *e;
315 struct hash_entry *end_e; 322 struct hash_entry *end_e;
316 bool eq; 323 bool eq;
324 bool indirectkey;
317 325
318 hash = h->hash0; 326 hash = h->hash0;
319 (*t->key->alg->hash) (&hash, t->key->size, data); 327 (*t->key->alg->hash) (&hash, t->key->size, data);
320 hash &= ~HASH_MASK; 328 hash &= ~HASH_MASK;
321 hash += HASH_ADJUST (hash); 329 hash += HASH_ADJUST (hash);
322 for (;;) { 330 for (;;) {
323 int32 shift = HASH_BITS - (st->power + used); 331 int32 shift = HASH_BITS - (st->power + used);
324 int32 index_mask = (1 << st->power) - 1; 332 int32 index_mask = (1 << st->power) - 1;
325 int32 i = (hash >> shift) & index_mask; /* i is the natural p osition of hash */ 333 int32 i = (hash >> shift) & index_mask; /* i is the natural p osition of hash */
326 334
327 e = HASH_OFFSET (st->entry, i * elemsize); /* e points to elemen t i */ 335 e = HASH_OFFSET (st->entry, i * elemsize); /* e points to elemen t i */
328 e_hash = e->hash; 336 e_hash = e->hash;
329 if ((e_hash & HASH_MASK) != HASH_SUBHASH) { /* a subtable * / 337 if ((e_hash & HASH_MASK) != HASH_SUBHASH) { /* a subtable * /
330 break; 338 break;
331 } 339 }
332 used += st->power; 340 used += st->power;
333 st = *(struct hash_subtable **)e->data; 341 st = *(struct hash_subtable **)e->data;
334 } 342 }
335 end_e = HASH_OFFSET (e, st->limit_bytes); 343 end_e = HASH_OFFSET (e, st->limit_bytes);
336 while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) { 344 while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) {
337 e = HASH_OFFSET (e, elemsize); 345 e = HASH_OFFSET (e, elemsize);
338 } 346 }
347 indirectkey = h->indirect & HASH_INDIRECT_KEY;
339 while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) { 348 while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) {
340 » » if (HASH_DATA_EQ (eq, t, h, data, e->data)) { /* a match */ 349 » » void *k = e->data;
341 » » » if (h->indirectval) 350 » » if (indirectkey)
351 » » » k = *(void**)k;
352 » » if (HASH_DATA_EQ (eq, t, h, data, k)) { /* a match */
353 » » » if (indirectkey)
354 » » » » free (k);
355 » » » if (h->indirect & HASH_INDIRECT_VAL)
342 free (*(void**)((byte*)e->data + h->valoff)); 356 free (*(void**)((byte*)e->data + h->valoff));
343 hash_remove_n (st, e, 1); 357 hash_remove_n (st, e, 1);
344 h->count--; 358 h->count--;
345 return (1); 359 return (1);
346 } 360 }
347 e = HASH_OFFSET (e, elemsize); 361 e = HASH_OFFSET (e, elemsize);
348 } 362 }
349 USED(e_hash); 363 USED(e_hash);
350 return (0); 364 return (0);
351 } 365 }
352 366
353 static int32 367 static int32
354 hash_insert_internal (MapType *t, struct hash_subtable **pst, int32 flags, hash_ hash_t hash, 368 hash_insert_internal (MapType *t, struct hash_subtable **pst, int32 flags, hash_ hash_t hash,
355 Hmap *h, void *data, void **pres) 369 Hmap *h, void *data, void **pres)
356 { 370 {
357 int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]); 371 int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
358 bool eq; 372 bool eq;
373 bool indirectkey;
359 374
360 if ((flags & HASH_REHASH) == 0) { 375 if ((flags & HASH_REHASH) == 0) {
361 hash += HASH_ADJUST (hash); 376 hash += HASH_ADJUST (hash);
362 hash &= ~HASH_MASK; 377 hash &= ~HASH_MASK;
363 } 378 }
379 indirectkey = h->indirect & HASH_INDIRECT_KEY;
364 for (;;) { 380 for (;;) {
365 struct hash_subtable *st = *pst; 381 struct hash_subtable *st = *pst;
366 int32 shift = HASH_BITS - (st->power + HASH_USED (flags)); 382 int32 shift = HASH_BITS - (st->power + HASH_USED (flags));
367 int32 index_mask = (1 << st->power) - 1; 383 int32 index_mask = (1 << st->power) - 1;
368 int32 i = (hash >> shift) & index_mask; /* i is the natural p osition of hash */ 384 int32 i = (hash >> shift) & index_mask; /* i is the natural p osition of hash */
369 struct hash_entry *start_e = 385 struct hash_entry *start_e =
370 HASH_OFFSET (st->entry, i * elemsize); /* start_e is the pointer to element i */ 386 HASH_OFFSET (st->entry, i * elemsize); /* start_e is the pointer to element i */
371 struct hash_entry *e = start_e; /* e is going to rang e over [start_e, end_e) */ 387 struct hash_entry *e = start_e; /* e is going to rang e over [start_e, end_e) */
372 struct hash_entry *end_e; 388 struct hash_entry *end_e;
373 hash_hash_t e_hash = e->hash; 389 hash_hash_t e_hash = e->hash;
374 390
375 if ((e_hash & HASH_MASK) == HASH_SUBHASH) { /* a subtable * / 391 if ((e_hash & HASH_MASK) == HASH_SUBHASH) { /* a subtable * /
376 pst = (struct hash_subtable **) e->data; 392 pst = (struct hash_subtable **) e->data;
377 flags += HASH_MAKE_USED (st->power); 393 flags += HASH_MAKE_USED (st->power);
378 continue; 394 continue;
379 } 395 }
380 end_e = HASH_OFFSET (start_e, st->limit_bytes); 396 end_e = HASH_OFFSET (start_e, st->limit_bytes);
381 while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) { 397 while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) {
382 e = HASH_OFFSET (e, elemsize); 398 e = HASH_OFFSET (e, elemsize);
383 i++; 399 i++;
384 } 400 }
385 if (e != end_e && e_hash != HASH_NIL) { 401 if (e != end_e && e_hash != HASH_NIL) {
386 /* ins_e ranges over the elements that may match */ 402 /* ins_e ranges over the elements that may match */
387 struct hash_entry *ins_e = e; 403 struct hash_entry *ins_e = e;
388 int32 ins_i = i; 404 int32 ins_i = i;
389 hash_hash_t ins_e_hash; 405 hash_hash_t ins_e_hash;
390 while (ins_e != end_e && ((e_hash = ins_e->hash) ^ hash) < HASH_SUBHASH) { 406 while (ins_e != end_e && ((e_hash = ins_e->hash) ^ hash) < HASH_SUBHASH) {
391 » » » » if (HASH_DATA_EQ (eq, t, h, data, ins_e->data)) { /* a match */ 407 » » » » void *k = ins_e->data;
408 » » » » if (indirectkey)
409 » » » » » k = *(void**)k;
410 » » » » if (HASH_DATA_EQ (eq, t, h, data, k)) { /* a match */
392 *pres = ins_e->data; 411 *pres = ins_e->data;
393 return (1); 412 return (1);
394 } 413 }
395 assert (e_hash != hash || (flags & HASH_REHASH) == 0); 414 assert (e_hash != hash || (flags & HASH_REHASH) == 0);
396 hash += (e_hash == hash); /* adjust has h if it collides */ 415 hash += (e_hash == hash); /* adjust has h if it collides */
397 ins_e = HASH_OFFSET (ins_e, elemsize); 416 ins_e = HASH_OFFSET (ins_e, elemsize);
398 ins_i++; 417 ins_i++;
399 if (e_hash <= hash) { /* set e to inser tion point */ 418 if (e_hash <= hash) { /* set e to inser tion point */
400 e = ins_e; 419 e = ins_e;
401 i = ins_i; 420 i = ins_i;
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 hash_visit (Hmap *h, void (*data_visit) (void *arg, int32 level, void *data), vo id *arg) 692 hash_visit (Hmap *h, void (*data_visit) (void *arg, int32 level, void *data), vo id *arg)
674 { 693 {
675 hash_visit_internal (h->st, 0, 0, data_visit, arg); 694 hash_visit_internal (h->st, 0, 0, data_visit, arg);
676 } 695 }
677 696
678 // 697 //
679 /// interfaces to go runtime 698 /// interfaces to go runtime
680 // 699 //
681 700
682 // hash requires < 256 bytes of data (key+value) stored inline. 701 // hash requires < 256 bytes of data (key+value) stored inline.
683 // Only basic types can be key - biggest is complex128 (16 bytes). 702 // Biggest basic type is complex128 (16 bytes).
684 // Leave some room to grow, just in case. 703 // Leave some room to grow, just in case.
685 enum { 704 enum {
686 » MaxValsize = 256 - 64 705 » MaxKeysize = 64,
706 » MaxValsize = 256 - MaxKeysize
687 }; 707 };
688 708
689 static void** 709 static void**
690 hash_indirect(Hmap *h, void *p) 710 hash_indirect(Hmap *h, void *p)
691 { 711 {
692 » if(h->indirectval) 712 » if(h->indirect & HASH_INDIRECT_VAL)
693 p = *(void**)p; 713 p = *(void**)p;
694 return p; 714 return p;
695 }······· 715 }·······
696 716
697 static int32 debug = 0; 717 static int32 debug = 0;
698 718
699 // makemap(typ *Type, hint uint32) (hmap *map[any]any); 719 // makemap(typ *Type, hint uint32) (hmap *map[any]any);
700 Hmap* 720 Hmap*
701 runtime·makemap_c(MapType *typ, int64 hint) 721 runtime·makemap_c(MapType *typ, int64 hint)
702 { 722 {
703 Hmap *h; 723 Hmap *h;
724 int32 keysize_in_hash;
704 int32 valsize_in_hash; 725 int32 valsize_in_hash;
705 Type *key, *val; 726 Type *key, *val;
706 ········ 727 ········
707 key = typ->key; 728 key = typ->key;
708 val = typ->elem; 729 val = typ->elem;
709 730
710 if(hint < 0 || (int32)hint != hint) 731 if(hint < 0 || (int32)hint != hint)
711 runtime·panicstring("makemap: size out of range"); 732 runtime·panicstring("makemap: size out of range");
712 733
713 if(key->alg->hash == runtime·nohash) 734 if(key->alg->hash == runtime·nohash)
714 runtime·throw("runtime.makemap: unsupported map key type"); 735 runtime·throw("runtime.makemap: unsupported map key type");
715 736
716 h = runtime·mal(sizeof(*h)); 737 h = runtime·mal(sizeof(*h));
717 738
718 » valsize_in_hash = val->size; 739 » if (key->size <= MaxKeysize)
719 » if (val->size > MaxValsize) { 740 » » keysize_in_hash = key->size;
720 » » h->indirectval = 1; 741 » else {
742 » » h->indirect |= HASH_INDIRECT_KEY;
743 » » keysize_in_hash = sizeof(void*);
744 » }
745
746 » if (val->size <= MaxValsize)
747 » » valsize_in_hash = val->size;
748 » else {
749 » » h->indirect |= HASH_INDIRECT_VAL;
721 valsize_in_hash = sizeof(void*); 750 valsize_in_hash = sizeof(void*);
722 » } 751 » }
723 752
724 // Align value inside data so that mark-sweep gc can find it. 753 // Align value inside data so that mark-sweep gc can find it.
725 » h->valoff = key->size; 754 » h->valoff = keysize_in_hash;
726 » assert(h->valoff == key->size);
727 if(valsize_in_hash >= sizeof(void*)) 755 if(valsize_in_hash >= sizeof(void*))
728 h->valoff = runtime·rnd(key->size, sizeof(void*)); 756 h->valoff = runtime·rnd(key->size, sizeof(void*));
729 757
730 hash_init(h, h->valoff+valsize_in_hash, hint); 758 hash_init(h, h->valoff+valsize_in_hash, hint);
731 759
732 // these calculations are compiler dependent. 760 // these calculations are compiler dependent.
733 // figure out offsets of map call arguments. 761 // figure out offsets of map call arguments.
734 762
735 if(debug) { 763 if(debug) {
736 runtime·printf("makemap: map=%p; keysize=%p; valsize=%p; keyalg= %p; valalg=%p\n", 764 runtime·printf("makemap: map=%p; keysize=%p; valsize=%p; keyalg= %p; valalg=%p\n",
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 if(runtime·gcwaiting) 901 if(runtime·gcwaiting)
874 runtime·gosched(); 902 runtime·gosched();
875 903
876 if(av == nil) { 904 if(av == nil) {
877 hash_remove(t, h, ak); 905 hash_remove(t, h, ak);
878 return; 906 return;
879 } 907 }
880 908
881 res = nil; 909 res = nil;
882 hit = hash_insert(t, h, ak, (void**)&res); 910 hit = hash_insert(t, h, ak, (void**)&res);
883 » if(!hit && h->indirectval) 911 » if(h->indirect&HASH_INDIRECT_KEY) {
912 » » if(!hit)
913 » » » *(void**)res = runtime·mal(t->key->size);
914 » » t->key->alg->copy(t->key->size, *(void**)res, ak);
915 » } else
916 » » t->key->alg->copy(t->key->size, res, ak);
917 » if(!hit && h->indirect&HASH_INDIRECT_VAL)
884 *(void**)(res+h->valoff) = runtime·mal(t->elem->size); 918 *(void**)(res+h->valoff) = runtime·mal(t->elem->size);
885 t->key->alg->copy(t->key->size, res, ak);
886 t->elem->alg->copy(t->elem->size, hash_indirect(h, res+h->valoff), av); 919 t->elem->alg->copy(t->elem->size, hash_indirect(h, res+h->valoff), av);
887 920
888 if(debug) { 921 if(debug) {
889 runtime·prints("mapassign: map="); 922 runtime·prints("mapassign: map=");
890 runtime·printpointer(h); 923 runtime·printpointer(h);
891 runtime·prints("; key="); 924 runtime·prints("; key=");
892 t->key->alg->print(t->key->size, ak); 925 t->key->alg->print(t->key->size, ak);
893 runtime·prints("; val="); 926 runtime·prints("; val=");
894 t->elem->alg->print(t->elem->size, av); 927 t->elem->alg->print(t->elem->size, av);
895 runtime·prints("; hit="); 928 runtime·prints("; hit=");
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 Hmap *h; 1059 Hmap *h;
1027 byte *ak, *res; 1060 byte *ak, *res;
1028 Type *key; 1061 Type *key;
1029 1062
1030 h = it->h; 1063 h = it->h;
1031 ak = (byte*)(&it + 1); 1064 ak = (byte*)(&it + 1);
1032 1065
1033 res = it->data; 1066 res = it->data;
1034 if(res == nil) 1067 if(res == nil)
1035 runtime·throw("runtime.mapiter1: key:val nil pointer"); 1068 runtime·throw("runtime.mapiter1: key:val nil pointer");
1069 if(h->indirect&HASH_INDIRECT_KEY)
1070 res = *(void**)res;
1036 1071
1037 key = it->t->key; 1072 key = it->t->key;
1038 key->alg->copy(key->size, ak, res); 1073 key->alg->copy(key->size, ak, res);
1039 1074
1040 if(debug) { 1075 if(debug) {
1041 runtime·prints("mapiter2: iter="); 1076 runtime·prints("mapiter2: iter=");
1042 runtime·printpointer(it); 1077 runtime·printpointer(it);
1043 runtime·prints("; map="); 1078 runtime·prints("; map=");
1044 runtime·printpointer(h); 1079 runtime·printpointer(h);
1045 runtime·prints("\n"); 1080 runtime·prints("\n");
1046 } 1081 }
1047 } 1082 }
1048 1083
1049 bool 1084 bool
1050 runtime·mapiterkey(struct hash_iter *it, void *ak) 1085 runtime·mapiterkey(struct hash_iter *it, void *ak)
1051 { 1086 {
1052 byte *res; 1087 byte *res;
1053 Type *key; 1088 Type *key;
1054 1089
1055 res = it->data; 1090 res = it->data;
1056 if(res == nil) 1091 if(res == nil)
1057 return false; 1092 return false;
1093 if(it->h->indirect&HASH_INDIRECT_KEY)
1094 res = *(void**)res;
1058 key = it->t->key; 1095 key = it->t->key;
1059 key->alg->copy(key->size, ak, res); 1096 key->alg->copy(key->size, ak, res);
1060 return true; 1097 return true;
1061 } 1098 }
1062 1099
1063 // For reflect: 1100 // For reflect:
1064 // func mapiterkey(h map) (key iword, ok bool) 1101 // func mapiterkey(h map) (key iword, ok bool)
1065 // where an iword is the same word an interface value would use: 1102 // where an iword is the same word an interface value would use:
1066 // the actual data if it fits, or else a pointer to the data. 1103 // the actual data if it fits, or else a pointer to the data.
1067 void 1104 void
1068 reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok) 1105 reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok)
1069 { 1106 {
1070 byte *res; 1107 byte *res;
1071 Type *tkey; 1108 Type *tkey;
1072 1109
1073 key = 0; 1110 key = 0;
1074 ok = false; 1111 ok = false;
1075 res = it->data; 1112 res = it->data;
1076 if(res == nil) { 1113 if(res == nil) {
1077 key = 0; 1114 key = 0;
1078 ok = false; 1115 ok = false;
1079 } else { 1116 } else {
1117 if(it->h->indirect&HASH_INDIRECT_KEY)
1118 res = *(void**)res;
1080 tkey = it->t->key; 1119 tkey = it->t->key;
1081 key = 0; 1120 key = 0;
1082 if(tkey->size <= sizeof(key)) 1121 if(tkey->size <= sizeof(key))
1083 tkey->alg->copy(tkey->size, (byte*)&key, res); 1122 tkey->alg->copy(tkey->size, (byte*)&key, res);
1084 else 1123 else
1085 key = (uintptr)res; 1124 key = (uintptr)res;
1086 ok = true; 1125 ok = true;
1087 } 1126 }
1088 FLUSH(&key); 1127 FLUSH(&key);
1089 FLUSH(&ok); 1128 FLUSH(&ok);
(...skipping 23 matching lines...) Expand all
1113 1152
1114 t = it->t; 1153 t = it->t;
1115 ak = (byte*)(&it + 1); 1154 ak = (byte*)(&it + 1);
1116 av = ak + runtime·rnd(t->key->size, t->elem->align); 1155 av = ak + runtime·rnd(t->key->size, t->elem->align);
1117 1156
1118 res = it->data; 1157 res = it->data;
1119 if(res == nil) 1158 if(res == nil)
1120 runtime·throw("runtime.mapiter2: key:val nil pointer"); 1159 runtime·throw("runtime.mapiter2: key:val nil pointer");
1121 1160
1122 h = it->h; 1161 h = it->h;
1162 if(h->indirect&HASH_INDIRECT_KEY)
1163 res = *(void**)res;
1123 t->key->alg->copy(t->key->size, ak, res); 1164 t->key->alg->copy(t->key->size, ak, res);
1124 t->elem->alg->copy(t->elem->size, av, hash_indirect(h, res+h->valoff)); 1165 t->elem->alg->copy(t->elem->size, av, hash_indirect(h, res+h->valoff));
1125 1166
1126 if(debug) { 1167 if(debug) {
1127 runtime·prints("mapiter2: iter="); 1168 runtime·prints("mapiter2: iter=");
1128 runtime·printpointer(it); 1169 runtime·printpointer(it);
1129 runtime·prints("; map="); 1170 runtime·prints("; map=");
1130 runtime·printpointer(h); 1171 runtime·printpointer(h);
1131 runtime·prints("\n"); 1172 runtime·prints("\n");
1132 } 1173 }
1133 } 1174 }
LEFTRIGHT
« no previous file | test/cmp.go » ('j') | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b