Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. 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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 // - 1 bit used to mark DOM trees for V8. | 150 // - 1 bit used to mark DOM trees for V8. |
| 151 // - 14 bit is enough for gcInfoIndex because there are less than 2^14 types | 151 // - 14 bit is enough for gcInfoIndex because there are less than 2^14 types |
| 152 // in Blink. | 152 // in Blink. |
| 153 const size_t headerWrapperMarkBitMask = 1u << 17; | 153 const size_t headerWrapperMarkBitMask = 1u << 17; |
| 154 const size_t headerGCInfoIndexShift = 18; | 154 const size_t headerGCInfoIndexShift = 18; |
| 155 const size_t headerGCInfoIndexMask = (static_cast<size_t>((1 << 14) - 1)) | 155 const size_t headerGCInfoIndexMask = (static_cast<size_t>((1 << 14) - 1)) |
| 156 << headerGCInfoIndexShift; | 156 << headerGCInfoIndexShift; |
| 157 const size_t headerSizeMask = (static_cast<size_t>((1 << 14) - 1)) << 3; | 157 const size_t headerSizeMask = (static_cast<size_t>((1 << 14) - 1)) << 3; |
| 158 const size_t headerMarkBitMask = 1; | 158 const size_t headerMarkBitMask = 1; |
| 159 const size_t headerFreedBitMask = 2; | 159 const size_t headerFreedBitMask = 2; |
| 160 // The dead bit is used for objects that have gone through a GC marking, but did | 160 // TODO(haraken): Remove the dead bit. It is used only by a header of |
| 161 // not get swept before a new GC started. In that case we set the dead bit on | 161 // a promptly freed header. |
|
haraken
2017/02/08 09:18:06
I'll look into this. I'm not sure how easy it is t
sof
2017/02/08 09:24:00
s/a promptly freed header/promptly freed object/
| |
| 162 // objects that were not marked in the previous GC to ensure we are not tracing | |
| 163 // them via a conservatively found pointer. Tracing dead objects could lead to | |
| 164 // tracing of already finalized objects in another thread's heap which is a | |
| 165 // use-after-free situation. | |
| 166 const size_t headerDeadBitMask = 4; | 162 const size_t headerDeadBitMask = 4; |
| 167 // On free-list entries we reuse the dead bit to distinguish a normal free-list | 163 // On free-list entries we reuse the dead bit to distinguish a normal free-list |
| 168 // entry from one that has been promptly freed. | 164 // entry from one that has been promptly freed. |
| 169 const size_t headerPromptlyFreedBitMask = | 165 const size_t headerPromptlyFreedBitMask = |
| 170 headerFreedBitMask | headerDeadBitMask; | 166 headerFreedBitMask | headerDeadBitMask; |
| 171 const size_t largeObjectSizeInHeader = 0; | 167 const size_t largeObjectSizeInHeader = 0; |
| 172 const size_t gcInfoIndexForFreeListHeader = 0; | 168 const size_t gcInfoIndexForFreeListHeader = 0; |
| 173 const size_t nonLargeObjectPageSizeMax = 1 << 17; | 169 const size_t nonLargeObjectPageSizeMax = 1 << 17; |
| 174 | 170 |
| 175 static_assert( | 171 static_assert( |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 void setSize(size_t size) { | 221 void setSize(size_t size) { |
| 226 ASSERT(size < nonLargeObjectPageSizeMax); | 222 ASSERT(size < nonLargeObjectPageSizeMax); |
| 227 m_encoded = static_cast<uint32_t>(size) | (m_encoded & ~headerSizeMask); | 223 m_encoded = static_cast<uint32_t>(size) | (m_encoded & ~headerSizeMask); |
| 228 } | 224 } |
| 229 bool isWrapperHeaderMarked() const; | 225 bool isWrapperHeaderMarked() const; |
| 230 void markWrapperHeader(); | 226 void markWrapperHeader(); |
| 231 void unmarkWrapperHeader(); | 227 void unmarkWrapperHeader(); |
| 232 bool isMarked() const; | 228 bool isMarked() const; |
| 233 void mark(); | 229 void mark(); |
| 234 void unmark(); | 230 void unmark(); |
| 235 void markDead(); | |
| 236 bool isDead() const; | |
| 237 | 231 |
| 238 Address payload(); | 232 Address payload(); |
| 239 size_t payloadSize(); | 233 size_t payloadSize(); |
| 240 Address payloadEnd(); | 234 Address payloadEnd(); |
| 241 | 235 |
| 242 #if DCHECK_IS_ON() | 236 #if DCHECK_IS_ON() |
| 243 bool checkHeader() const; | 237 bool checkHeader() const; |
| 244 // Zap magic number with a new magic number that means there was once an | 238 // Zap magic number with a new magic number that means there was once an |
| 245 // object allocated here, but it was freed because nobody marked it during | 239 // object allocated here, but it was freed because nobody marked it during |
| 246 // GC. | 240 // GC. |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 } | 386 } |
| 393 BasePage* next() const { return m_next; } | 387 BasePage* next() const { return m_next; } |
| 394 | 388 |
| 395 // virtual methods are slow. So performance-sensitive methods | 389 // virtual methods are slow. So performance-sensitive methods |
| 396 // should be defined as non-virtual methods on NormalPage and LargeObjectPage. | 390 // should be defined as non-virtual methods on NormalPage and LargeObjectPage. |
| 397 // The following methods are not performance-sensitive. | 391 // The following methods are not performance-sensitive. |
| 398 virtual size_t objectPayloadSizeForTesting() = 0; | 392 virtual size_t objectPayloadSizeForTesting() = 0; |
| 399 virtual bool isEmpty() = 0; | 393 virtual bool isEmpty() = 0; |
| 400 virtual void removeFromHeap() = 0; | 394 virtual void removeFromHeap() = 0; |
| 401 virtual void sweep() = 0; | 395 virtual void sweep() = 0; |
| 402 virtual void makeConsistentForGC() = 0; | |
| 403 virtual void makeConsistentForMutator() = 0; | 396 virtual void makeConsistentForMutator() = 0; |
| 404 virtual void invalidateObjectStartBitmap() = 0; | 397 virtual void invalidateObjectStartBitmap() = 0; |
| 405 | 398 |
| 406 #if defined(ADDRESS_SANITIZER) | 399 #if defined(ADDRESS_SANITIZER) |
| 407 virtual void poisonUnmarkedObjects() = 0; | 400 virtual void poisonUnmarkedObjects() = 0; |
| 408 #endif | 401 #endif |
| 409 // Check if the given address points to an object in this | 402 // Check if the given address points to an object in this |
| 410 // heap page. If so, find the start of that object and mark it | 403 // heap page. If so, find the start of that object and mark it |
| 411 // using the given Visitor. Otherwise do nothing. The pointer must | 404 // using the given Visitor. Otherwise do nothing. The pointer must |
| 412 // be within the same aligned blinkPageSize as the this-pointer. | 405 // be within the same aligned blinkPageSize as the this-pointer. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 485 } | 478 } |
| 486 Address payloadEnd() { return payload() + payloadSize(); } | 479 Address payloadEnd() { return payload() + payloadSize(); } |
| 487 bool containedInObjectPayload(Address address) { | 480 bool containedInObjectPayload(Address address) { |
| 488 return payload() <= address && address < payloadEnd(); | 481 return payload() <= address && address < payloadEnd(); |
| 489 } | 482 } |
| 490 | 483 |
| 491 size_t objectPayloadSizeForTesting() override; | 484 size_t objectPayloadSizeForTesting() override; |
| 492 bool isEmpty() override; | 485 bool isEmpty() override; |
| 493 void removeFromHeap() override; | 486 void removeFromHeap() override; |
| 494 void sweep() override; | 487 void sweep() override; |
| 495 void makeConsistentForGC() override; | |
| 496 void makeConsistentForMutator() override; | 488 void makeConsistentForMutator() override; |
| 497 void invalidateObjectStartBitmap() override { | 489 void invalidateObjectStartBitmap() override { |
| 498 m_objectStartBitMapComputed = false; | 490 m_objectStartBitMapComputed = false; |
| 499 } | 491 } |
| 500 #if defined(ADDRESS_SANITIZER) | 492 #if defined(ADDRESS_SANITIZER) |
| 501 void poisonUnmarkedObjects() override; | 493 void poisonUnmarkedObjects() override; |
| 502 #endif | 494 #endif |
| 503 void checkAndMarkPointer(Visitor*, Address) override; | 495 void checkAndMarkPointer(Visitor*, Address) override; |
| 504 #if DCHECK_IS_ON() | 496 #if DCHECK_IS_ON() |
| 505 void checkAndMarkPointer(Visitor*, | 497 void checkAndMarkPointer(Visitor*, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 size_t payloadSize() { return m_payloadSize; } | 562 size_t payloadSize() { return m_payloadSize; } |
| 571 Address payloadEnd() { return payload() + payloadSize(); } | 563 Address payloadEnd() { return payload() + payloadSize(); } |
| 572 bool containedInObjectPayload(Address address) { | 564 bool containedInObjectPayload(Address address) { |
| 573 return payload() <= address && address < payloadEnd(); | 565 return payload() <= address && address < payloadEnd(); |
| 574 } | 566 } |
| 575 | 567 |
| 576 size_t objectPayloadSizeForTesting() override; | 568 size_t objectPayloadSizeForTesting() override; |
| 577 bool isEmpty() override; | 569 bool isEmpty() override; |
| 578 void removeFromHeap() override; | 570 void removeFromHeap() override; |
| 579 void sweep() override; | 571 void sweep() override; |
| 580 void makeConsistentForGC() override; | |
| 581 void makeConsistentForMutator() override; | 572 void makeConsistentForMutator() override; |
| 582 void invalidateObjectStartBitmap() override {} | 573 void invalidateObjectStartBitmap() override {} |
| 583 #if defined(ADDRESS_SANITIZER) | 574 #if defined(ADDRESS_SANITIZER) |
| 584 void poisonUnmarkedObjects() override; | 575 void poisonUnmarkedObjects() override; |
| 585 #endif | 576 #endif |
| 586 void checkAndMarkPointer(Visitor*, Address) override; | 577 void checkAndMarkPointer(Visitor*, Address) override; |
| 587 #if DCHECK_IS_ON() | 578 #if DCHECK_IS_ON() |
| 588 void checkAndMarkPointer(Visitor*, | 579 void checkAndMarkPointer(Visitor*, |
| 589 Address, | 580 Address, |
| 590 MarkedPointerCallbackForTesting) override; | 581 MarkedPointerCallbackForTesting) override; |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 934 ASSERT(!isMarked()); | 925 ASSERT(!isMarked()); |
| 935 m_encoded = m_encoded | headerMarkBitMask; | 926 m_encoded = m_encoded | headerMarkBitMask; |
| 936 } | 927 } |
| 937 | 928 |
| 938 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::unmark() { | 929 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::unmark() { |
| 939 ASSERT(checkHeader()); | 930 ASSERT(checkHeader()); |
| 940 ASSERT(isMarked()); | 931 ASSERT(isMarked()); |
| 941 m_encoded &= ~headerMarkBitMask; | 932 m_encoded &= ~headerMarkBitMask; |
| 942 } | 933 } |
| 943 | 934 |
| 944 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::isDead() const { | |
| 945 ASSERT(checkHeader()); | |
| 946 return m_encoded & headerDeadBitMask; | |
| 947 } | |
| 948 | |
| 949 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::markDead() { | |
| 950 // A Dead state should not happen in a per-thread heap world. | |
| 951 // TODO(haraken): Remove code to handle the Dead state. | |
| 952 CHECK(false); | |
| 953 ASSERT(checkHeader()); | |
| 954 ASSERT(!isMarked()); | |
| 955 m_encoded |= headerDeadBitMask; | |
| 956 } | |
| 957 | |
| 958 inline Address NormalPageArena::allocateObject(size_t allocationSize, | 935 inline Address NormalPageArena::allocateObject(size_t allocationSize, |
| 959 size_t gcInfoIndex) { | 936 size_t gcInfoIndex) { |
| 960 if (LIKELY(allocationSize <= m_remainingAllocationSize)) { | 937 if (LIKELY(allocationSize <= m_remainingAllocationSize)) { |
| 961 Address headerAddress = m_currentAllocationPoint; | 938 Address headerAddress = m_currentAllocationPoint; |
| 962 m_currentAllocationPoint += allocationSize; | 939 m_currentAllocationPoint += allocationSize; |
| 963 m_remainingAllocationSize -= allocationSize; | 940 m_remainingAllocationSize -= allocationSize; |
| 964 ASSERT(gcInfoIndex > 0); | 941 ASSERT(gcInfoIndex > 0); |
| 965 new (NotNull, headerAddress) HeapObjectHeader(allocationSize, gcInfoIndex); | 942 new (NotNull, headerAddress) HeapObjectHeader(allocationSize, gcInfoIndex); |
| 966 Address result = headerAddress + sizeof(HeapObjectHeader); | 943 Address result = headerAddress + sizeof(HeapObjectHeader); |
| 967 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); | 944 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); |
| 968 | 945 |
| 969 SET_MEMORY_ACCESSIBLE(result, allocationSize - sizeof(HeapObjectHeader)); | 946 SET_MEMORY_ACCESSIBLE(result, allocationSize - sizeof(HeapObjectHeader)); |
| 970 ASSERT(findPageFromAddress(headerAddress + allocationSize - 1)); | 947 ASSERT(findPageFromAddress(headerAddress + allocationSize - 1)); |
| 971 return result; | 948 return result; |
| 972 } | 949 } |
| 973 return outOfLineAllocate(allocationSize, gcInfoIndex); | 950 return outOfLineAllocate(allocationSize, gcInfoIndex); |
| 974 } | 951 } |
| 975 | 952 |
| 976 inline NormalPageArena* NormalPage::arenaForNormalPage() const { | 953 inline NormalPageArena* NormalPage::arenaForNormalPage() const { |
| 977 return static_cast<NormalPageArena*>(arena()); | 954 return static_cast<NormalPageArena*>(arena()); |
| 978 } | 955 } |
| 979 | 956 |
| 980 } // namespace blink | 957 } // namespace blink |
| 981 | 958 |
| 982 #endif // HeapPage_h | 959 #endif // HeapPage_h |
| OLD | NEW |