| 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 for KEY. | 104 // Sets the value 'v' for key 'k'. |
| 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 } |
| 108 }; | 118 }; |
| 109 | 119 |
| 110 #ifdef WIN32 | 120 #ifdef WIN32 |
| 111 // Lazy commit, single-level array. | 121 // Lazy commit, single-level array. |
| 112 // Very similar to PageMap1, except the page map is only committed as needed. | 122 // Very similar to PageMap1, except the page map is only committed as needed. |
| 113 // Since we don't return memory to the OS, the committed portion of the map will | 123 // Since we don't return memory to the OS, the committed portion of the map will |
| 114 // only grow, and we'll only be called to Ensure when we really grow the heap. | 124 // only grow, and we'll only be called to Ensure when we really grow the heap. |
| 115 // We maintain a bit map to help us deduce if we've already committed a range | 125 // We maintain a bit map to help us deduce if we've already committed a range |
| 116 // in our map. | 126 // in our map. |
| 117 template <int BITS> | 127 template <int BITS> |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 return array_[k]; | 292 return array_[k]; |
| 283 } | 293 } |
| 284 | 294 |
| 285 // REQUIRES "k" is in range "[0,2^BITS-1]". | 295 // REQUIRES "k" is in range "[0,2^BITS-1]". |
| 286 // REQUIRES "k" has been ensured before. | 296 // REQUIRES "k" has been ensured before. |
| 287 // | 297 // |
| 288 // Sets the value for KEY. | 298 // Sets the value for KEY. |
| 289 void set(Number k, void* v) { | 299 void set(Number k, void* v) { |
| 290 array_[k] = v; | 300 array_[k] = v; |
| 291 } | 301 } |
| 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 } |
| 292 }; | 311 }; |
| 293 #endif // WIN32 | 312 #endif // WIN32 |
| 294 | 313 |
| 295 | 314 |
| 296 // Two-level radix tree | 315 // Two-level radix tree |
| 297 template <int BITS> | 316 template <int BITS> |
| 298 class TCMalloc_PageMap2 { | 317 class TCMalloc_PageMap2 { |
| 299 private: | 318 private: |
| 300 // Put 32 entries in the root and (2^BITS)/32 entries in each leaf. | 319 // Put 32 entries in the root and (2^BITS)/32 entries in each leaf. |
| 301 static const int ROOT_BITS = 5; | 320 static const int ROOT_BITS = 5; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 // Advance key past whatever is covered by this leaf node | 374 // Advance key past whatever is covered by this leaf node |
| 356 key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; | 375 key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; |
| 357 } | 376 } |
| 358 return true; | 377 return true; |
| 359 } | 378 } |
| 360 | 379 |
| 361 void PreallocateMoreMemory() { | 380 void PreallocateMoreMemory() { |
| 362 // Allocate enough to keep track of all possible pages | 381 // Allocate enough to keep track of all possible pages |
| 363 Ensure(0, 1 << BITS); | 382 Ensure(0, 1 << BITS); |
| 364 } | 383 } |
| 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 } |
| 365 }; | 402 }; |
| 366 | 403 |
| 367 // Three-level radix tree | 404 // Three-level radix tree |
| 368 template <int BITS> | 405 template <int BITS> |
| 369 class TCMalloc_PageMap3 { | 406 class TCMalloc_PageMap3 { |
| 370 private: | 407 private: |
| 371 // How many bits should we consume at each interior level | 408 // How many bits should we consume at each interior level |
| 372 static const int INTERIOR_BITS = (BITS + 2) / 3; // Round-up | 409 static const int INTERIOR_BITS = (BITS + 2) / 3; // Round-up |
| 373 static const int INTERIOR_LENGTH = 1 << INTERIOR_BITS; | 410 static const int INTERIOR_LENGTH = 1 << INTERIOR_BITS; |
| 374 | 411 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 } | 486 } |
| 450 | 487 |
| 451 // Advance key past whatever is covered by this leaf node | 488 // Advance key past whatever is covered by this leaf node |
| 452 key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; | 489 key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; |
| 453 } | 490 } |
| 454 return true; | 491 return true; |
| 455 } | 492 } |
| 456 | 493 |
| 457 void PreallocateMoreMemory() { | 494 void PreallocateMoreMemory() { |
| 458 } | 495 } |
| 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 } |
| 459 }; | 519 }; |
| 460 | 520 |
| 461 #endif // TCMALLOC_PAGEMAP_H_ | 521 #endif // TCMALLOC_PAGEMAP_H_ |
| OLD | NEW |