| OLD | NEW |
| 1 // Copyright (c) 2005, Google Inc. | 1 // Copyright (c) 2005, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 void* get(Number k) const { | 94 void* get(Number k) const { |
| 95 if ((k >> BITS) > 0) { | 95 if ((k >> BITS) > 0) { |
| 96 return NULL; | 96 return NULL; |
| 97 } | 97 } |
| 98 return array_[k]; | 98 return array_[k]; |
| 99 } | 99 } |
| 100 | 100 |
| 101 // REQUIRES "k" is in range "[0,2^BITS-1]". | 101 // REQUIRES "k" is in range "[0,2^BITS-1]". |
| 102 // REQUIRES "k" has been ensured before. | 102 // REQUIRES "k" has been ensured before. |
| 103 // | 103 // |
| 104 // Sets the value 'v' for key 'k'. | 104 // Sets the value for KEY. |
| 105 void set(Number k, void* v) { | 105 void set(Number k, void* v) { |
| 106 array_[k] = v; | 106 array_[k] = v; |
| 107 } | 107 } |
| 108 | |
| 109 // Return the first non-NULL pointer found in this map for | |
| 110 // a page number >= k. Returns NULL if no such number is found. | |
| 111 void* Next(Number k) const { | |
| 112 while (k < (1 << BITS)) { | |
| 113 if (array_[k] != NULL) return array_[k]; | |
| 114 k++; | |
| 115 } | |
| 116 return NULL; | |
| 117 } | |
| 118 }; | 108 }; |
| 119 | 109 |
| 120 #ifdef WIN32 | 110 #ifdef WIN32 |
| 121 // Lazy commit, single-level array. | 111 // Lazy commit, single-level array. |
| 122 // Very similar to PageMap1, except the page map is only committed as needed. | 112 // Very similar to PageMap1, except the page map is only committed as needed. |
| 123 // Since we don't return memory to the OS, the committed portion of the map will | 113 // Since we don't return memory to the OS, the committed portion of the map will |
| 124 // only grow, and we'll only be called to Ensure when we really grow the heap. | 114 // only grow, and we'll only be called to Ensure when we really grow the heap. |
| 125 // We maintain a bit map to help us deduce if we've already committed a range | 115 // We maintain a bit map to help us deduce if we've already committed a range |
| 126 // in our map. | 116 // in our map. |
| 127 template <int BITS> | 117 template <int BITS> |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 return array_[k]; | 282 return array_[k]; |
| 293 } | 283 } |
| 294 | 284 |
| 295 // REQUIRES "k" is in range "[0,2^BITS-1]". | 285 // REQUIRES "k" is in range "[0,2^BITS-1]". |
| 296 // REQUIRES "k" has been ensured before. | 286 // REQUIRES "k" has been ensured before. |
| 297 // | 287 // |
| 298 // Sets the value for KEY. | 288 // Sets the value for KEY. |
| 299 void set(Number k, void* v) { | 289 void set(Number k, void* v) { |
| 300 array_[k] = v; | 290 array_[k] = v; |
| 301 } | 291 } |
| 302 // Return the first non-NULL pointer found in this map for | |
| 303 // a page number >= k. Returns NULL if no such number is found. | |
| 304 void* Next(Number k) const { | |
| 305 while (k < (1 << BITS)) { | |
| 306 if (array_[k] != NULL) return array_[k]; | |
| 307 k++; | |
| 308 } | |
| 309 return NULL; | |
| 310 } | |
| 311 }; | 292 }; |
| 312 #endif // WIN32 | 293 #endif // WIN32 |
| 313 | 294 |
| 314 | 295 |
| 315 // Two-level radix tree | 296 // Two-level radix tree |
| 316 template <int BITS> | 297 template <int BITS> |
| 317 class TCMalloc_PageMap2 { | 298 class TCMalloc_PageMap2 { |
| 318 private: | 299 private: |
| 319 // Put 32 entries in the root and (2^BITS)/32 entries in each leaf. | 300 // Put 32 entries in the root and (2^BITS)/32 entries in each leaf. |
| 320 static const int ROOT_BITS = 5; | 301 static const int ROOT_BITS = 5; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 // Advance key past whatever is covered by this leaf node | 355 // Advance key past whatever is covered by this leaf node |
| 375 key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; | 356 key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; |
| 376 } | 357 } |
| 377 return true; | 358 return true; |
| 378 } | 359 } |
| 379 | 360 |
| 380 void PreallocateMoreMemory() { | 361 void PreallocateMoreMemory() { |
| 381 // Allocate enough to keep track of all possible pages | 362 // Allocate enough to keep track of all possible pages |
| 382 Ensure(0, 1 << BITS); | 363 Ensure(0, 1 << BITS); |
| 383 } | 364 } |
| 384 | |
| 385 void* Next(Number k) const { | |
| 386 while (k < (1 << BITS)) { | |
| 387 const Number i1 = k >> LEAF_BITS; | |
| 388 Leaf* leaf = root_[i1]; | |
| 389 if (leaf != NULL) { | |
| 390 // Scan forward in leaf | |
| 391 for (Number i2 = k & (LEAF_LENGTH - 1); i2 < LEAF_LENGTH; i2++) { | |
| 392 if (leaf->values[i2] != NULL) { | |
| 393 return leaf->values[i2]; | |
| 394 } | |
| 395 } | |
| 396 } | |
| 397 // Skip to next top-level entry | |
| 398 k = (i1 + 1) << LEAF_BITS; | |
| 399 } | |
| 400 return NULL; | |
| 401 } | |
| 402 }; | 365 }; |
| 403 | 366 |
| 404 // Three-level radix tree | 367 // Three-level radix tree |
| 405 template <int BITS> | 368 template <int BITS> |
| 406 class TCMalloc_PageMap3 { | 369 class TCMalloc_PageMap3 { |
| 407 private: | 370 private: |
| 408 // How many bits should we consume at each interior level | 371 // How many bits should we consume at each interior level |
| 409 static const int INTERIOR_BITS = (BITS + 2) / 3; // Round-up | 372 static const int INTERIOR_BITS = (BITS + 2) / 3; // Round-up |
| 410 static const int INTERIOR_LENGTH = 1 << INTERIOR_BITS; | 373 static const int INTERIOR_LENGTH = 1 << INTERIOR_BITS; |
| 411 | 374 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 } | 449 } |
| 487 | 450 |
| 488 // Advance key past whatever is covered by this leaf node | 451 // Advance key past whatever is covered by this leaf node |
| 489 key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; | 452 key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; |
| 490 } | 453 } |
| 491 return true; | 454 return true; |
| 492 } | 455 } |
| 493 | 456 |
| 494 void PreallocateMoreMemory() { | 457 void PreallocateMoreMemory() { |
| 495 } | 458 } |
| 496 | |
| 497 void* Next(Number k) const { | |
| 498 while (k < (Number(1) << BITS)) { | |
| 499 const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS); | |
| 500 const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1); | |
| 501 if (root_->ptrs[i1] == NULL) { | |
| 502 // Advance to next top-level entry | |
| 503 k = (i1 + 1) << (LEAF_BITS + INTERIOR_BITS); | |
| 504 } else { | |
| 505 Leaf* leaf = reinterpret_cast<Leaf*>(root_->ptrs[i1]->ptrs[i2]); | |
| 506 if (leaf != NULL) { | |
| 507 for (Number i3 = (k & (LEAF_LENGTH-1)); i3 < LEAF_LENGTH; i3++) { | |
| 508 if (leaf->values[i3] != NULL) { | |
| 509 return leaf->values[i3]; | |
| 510 } | |
| 511 } | |
| 512 } | |
| 513 // Advance to next interior entry | |
| 514 k = ((k >> LEAF_BITS) + 1) << LEAF_BITS; | |
| 515 } | |
| 516 } | |
| 517 return NULL; | |
| 518 } | |
| 519 }; | 459 }; |
| 520 | 460 |
| 521 #endif // TCMALLOC_PAGEMAP_H_ | 461 #endif // TCMALLOC_PAGEMAP_H_ |
| OLD | NEW |