| 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 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 // to be in; willObjectBeLazilySwept() has undefined behavior if passed | 171 // to be in; willObjectBeLazilySwept() has undefined behavior if passed |
| 172 // such a reference. | 172 // such a reference. |
| 173 template<typename T> | 173 template<typename T> |
| 174 NO_LAZY_SWEEP_SANITIZE_ADDRESS | 174 NO_LAZY_SWEEP_SANITIZE_ADDRESS |
| 175 static bool willObjectBeLazilySwept(const T* objectPointer) | 175 static bool willObjectBeLazilySwept(const T* objectPointer) |
| 176 { | 176 { |
| 177 static_assert(IsGarbageCollectedType<T>::value, "only objects deriving f
rom GarbageCollected can be used."); | 177 static_assert(IsGarbageCollectedType<T>::value, "only objects deriving f
rom GarbageCollected can be used."); |
| 178 BasePage* page = pageFromObject(objectPointer); | 178 BasePage* page = pageFromObject(objectPointer); |
| 179 if (page->hasBeenSwept()) | 179 if (page->hasBeenSwept()) |
| 180 return false; | 180 return false; |
| 181 ASSERT(page->heap()->threadState()->isSweepingInProgress()); | 181 ASSERT(page->arena()->threadState()->isSweepingInProgress()); |
| 182 | 182 |
| 183 return !Heap::isHeapObjectAlive(const_cast<T*>(objectPointer)); | 183 return !Heap::isHeapObjectAlive(const_cast<T*>(objectPointer)); |
| 184 } | 184 } |
| 185 | 185 |
| 186 // Push a trace callback on the marking stack. | 186 // Push a trace callback on the marking stack. |
| 187 static void pushTraceCallback(void* containerObject, TraceCallback); | 187 static void pushTraceCallback(void* containerObject, TraceCallback); |
| 188 | 188 |
| 189 // Push a trace callback on the post-marking callback stack. These | 189 // Push a trace callback on the post-marking callback stack. These |
| 190 // callbacks are called after normal marking (including ephemeron | 190 // callbacks are called after normal marking (including ephemeron |
| 191 // iteration). | 191 // iteration). |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 // allocation size calculation can overflow for large sizes and the chec
k | 232 // allocation size calculation can overflow for large sizes and the chec
k |
| 233 // therefore has to happen before any calculation on the size. | 233 // therefore has to happen before any calculation on the size. |
| 234 RELEASE_ASSERT(size < maxHeapObjectSize); | 234 RELEASE_ASSERT(size < maxHeapObjectSize); |
| 235 | 235 |
| 236 // Add space for header. | 236 // Add space for header. |
| 237 size_t allocationSize = size + sizeof(HeapObjectHeader); | 237 size_t allocationSize = size + sizeof(HeapObjectHeader); |
| 238 // Align size with allocation granularity. | 238 // Align size with allocation granularity. |
| 239 allocationSize = (allocationSize + allocationMask) & ~allocationMask; | 239 allocationSize = (allocationSize + allocationMask) & ~allocationMask; |
| 240 return allocationSize; | 240 return allocationSize; |
| 241 } | 241 } |
| 242 static Address allocateOnHeapIndex(ThreadState*, size_t, int heapIndex, size
_t gcInfoIndex); | 242 static Address allocateOnArenaIndex(ThreadState*, size_t, int arenaIndex, si
ze_t gcInfoIndex); |
| 243 template<typename T> static Address allocate(size_t, bool eagerlySweep = fal
se); | 243 template<typename T> static Address allocate(size_t, bool eagerlySweep = fal
se); |
| 244 template<typename T> static Address reallocate(void* previous, size_t); | 244 template<typename T> static Address reallocate(void* previous, size_t); |
| 245 | 245 |
| 246 static const char* gcReasonString(BlinkGC::GCReason); | 246 static const char* gcReasonString(BlinkGC::GCReason); |
| 247 static void collectGarbage(BlinkGC::StackState, BlinkGC::GCType, BlinkGC::GC
Reason); | 247 static void collectGarbage(BlinkGC::StackState, BlinkGC::GCType, BlinkGC::GC
Reason); |
| 248 static void collectGarbageForTerminatingThread(ThreadState*); | 248 static void collectGarbageForTerminatingThread(ThreadState*); |
| 249 static void collectAllGarbage(); | 249 static void collectAllGarbage(); |
| 250 | 250 |
| 251 static void processMarkingStack(Visitor*); | 251 static void processMarkingStack(Visitor*); |
| 252 static void postMarkingProcessing(Visitor*); | 252 static void postMarkingProcessing(Visitor*); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 static bool isLowEndDevice() { return s_isLowEndDevice; } | 309 static bool isLowEndDevice() { return s_isLowEndDevice; } |
| 310 | 310 |
| 311 #if ENABLE(ASSERT) | 311 #if ENABLE(ASSERT) |
| 312 static uint16_t gcGeneration() { return s_gcGeneration; } | 312 static uint16_t gcGeneration() { return s_gcGeneration; } |
| 313 #endif | 313 #endif |
| 314 | 314 |
| 315 private: | 315 private: |
| 316 // Reset counters that track live and allocated-since-last-GC sizes. | 316 // Reset counters that track live and allocated-since-last-GC sizes. |
| 317 static void resetHeapCounters(); | 317 static void resetHeapCounters(); |
| 318 | 318 |
| 319 static int heapIndexForObjectSize(size_t); | 319 static int arenaIndexForObjectSize(size_t); |
| 320 static bool isNormalHeapIndex(int); | 320 static bool isNormalArenaIndex(int); |
| 321 | 321 |
| 322 static void decommitCallbackStacks(); | 322 static void decommitCallbackStacks(); |
| 323 | 323 |
| 324 static CallbackStack* s_markingStack; | 324 static CallbackStack* s_markingStack; |
| 325 static CallbackStack* s_postMarkingCallbackStack; | 325 static CallbackStack* s_postMarkingCallbackStack; |
| 326 static CallbackStack* s_globalWeakCallbackStack; | 326 static CallbackStack* s_globalWeakCallbackStack; |
| 327 static CallbackStack* s_ephemeronStack; | 327 static CallbackStack* s_ephemeronStack; |
| 328 static HeapDoesNotContainCache* s_heapDoesNotContainCache; | 328 static HeapDoesNotContainCache* s_heapDoesNotContainCache; |
| 329 static bool s_shutdownCalled; | 329 static bool s_shutdownCalled; |
| 330 static FreePagePool* s_freePagePool; | 330 static FreePagePool* s_freePagePool; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 { | 401 { |
| 402 ASSERT_NOT_REACHED(); | 402 ASSERT_NOT_REACHED(); |
| 403 } | 403 } |
| 404 | 404 |
| 405 protected: | 405 protected: |
| 406 GarbageCollected() | 406 GarbageCollected() |
| 407 { | 407 { |
| 408 } | 408 } |
| 409 }; | 409 }; |
| 410 | 410 |
| 411 // Assigning class types to their heaps. | 411 // Assigning class types to their arenas. |
| 412 // | 412 // |
| 413 // We use sized heaps for most 'normal' objects to improve memory locality. | 413 // We use sized arenas for most 'normal' objects to improve memory locality. |
| 414 // It seems that the same type of objects are likely to be accessed together, | 414 // It seems that the same type of objects are likely to be accessed together, |
| 415 // which means that we want to group objects by type. That's one reason | 415 // which means that we want to group objects by type. That's one reason |
| 416 // why we provide dedicated heaps for popular types (e.g., Node, CSSValue), | 416 // why we provide dedicated arenas for popular types (e.g., Node, CSSValue), |
| 417 // but it's not practical to prepare dedicated heaps for all types. | 417 // but it's not practical to prepare dedicated arenas for all types. |
| 418 // Thus we group objects by their sizes, hoping that this will approximately | 418 // Thus we group objects by their sizes, hoping that this will approximately |
| 419 // group objects by their types. | 419 // group objects by their types. |
| 420 // | 420 // |
| 421 // An exception to the use of sized heaps is made for class types that | 421 // An exception to the use of sized arenas is made for class types that |
| 422 // require prompt finalization after a garbage collection. That is, their | 422 // require prompt finalization after a garbage collection. That is, their |
| 423 // instances have to be finalized early and cannot be delayed until lazy | 423 // instances have to be finalized early and cannot be delayed until lazy |
| 424 // sweeping kicks in for their heap and page. The EAGERLY_FINALIZE() | 424 // sweeping kicks in for their heap and page. The EAGERLY_FINALIZE() |
| 425 // macro is used to declare a class (and its derived classes) as being | 425 // macro is used to declare a class (and its derived classes) as being |
| 426 // in need of eager finalization. Must be defined with 'public' visibility | 426 // in need of eager finalization. Must be defined with 'public' visibility |
| 427 // for a class. | 427 // for a class. |
| 428 // | 428 // |
| 429 | 429 |
| 430 inline int Heap::heapIndexForObjectSize(size_t size) | 430 inline int Heap::arenaIndexForObjectSize(size_t size) |
| 431 { | 431 { |
| 432 if (size < 64) { | 432 if (size < 64) { |
| 433 if (size < 32) | 433 if (size < 32) |
| 434 return BlinkGC::NormalPage1HeapIndex; | 434 return BlinkGC::NormalPage1ArenaIndex; |
| 435 return BlinkGC::NormalPage2HeapIndex; | 435 return BlinkGC::NormalPage2ArenaIndex; |
| 436 } | 436 } |
| 437 if (size < 128) | 437 if (size < 128) |
| 438 return BlinkGC::NormalPage3HeapIndex; | 438 return BlinkGC::NormalPage3ArenaIndex; |
| 439 return BlinkGC::NormalPage4HeapIndex; | 439 return BlinkGC::NormalPage4ArenaIndex; |
| 440 } | 440 } |
| 441 | 441 |
| 442 inline bool Heap::isNormalHeapIndex(int index) | 442 inline bool Heap::isNormalArenaIndex(int index) |
| 443 { | 443 { |
| 444 return index >= BlinkGC::NormalPage1HeapIndex && index <= BlinkGC::NormalPag
e4HeapIndex; | 444 return index >= BlinkGC::NormalPage1ArenaIndex && index <= BlinkGC::NormalPa
ge4ArenaIndex; |
| 445 } | 445 } |
| 446 | 446 |
| 447 #define DECLARE_EAGER_FINALIZATION_OPERATOR_NEW() \ | 447 #define DECLARE_EAGER_FINALIZATION_OPERATOR_NEW() \ |
| 448 public: \ | 448 public: \ |
| 449 GC_PLUGIN_IGNORE("491488") \ | 449 GC_PLUGIN_IGNORE("491488") \ |
| 450 void* operator new(size_t size) \ | 450 void* operator new(size_t size) \ |
| 451 { \ | 451 { \ |
| 452 return allocateObject(size, true); \ | 452 return allocateObject(size, true); \ |
| 453 } | 453 } |
| 454 | 454 |
| 455 #define IS_EAGERLY_FINALIZED() (pageFromObject(this)->heap()->heapIndex() == Bli
nkGC::EagerSweepHeapIndex) | 455 #define IS_EAGERLY_FINALIZED() (pageFromObject(this)->arena()->arenaIndex() == B
linkGC::EagerSweepArenaIndex) |
| 456 #if ENABLE(ASSERT) && ENABLE(OILPAN) | 456 #if ENABLE(ASSERT) && ENABLE(OILPAN) |
| 457 class VerifyEagerFinalization { | 457 class VerifyEagerFinalization { |
| 458 DISALLOW_NEW(); | 458 DISALLOW_NEW(); |
| 459 public: | 459 public: |
| 460 ~VerifyEagerFinalization() | 460 ~VerifyEagerFinalization() |
| 461 { | 461 { |
| 462 // If this assert triggers, the class annotated as eagerly | 462 // If this assert triggers, the class annotated as eagerly |
| 463 // finalized ended up not being allocated on the heap | 463 // finalized ended up not being allocated on the heap |
| 464 // set aside for eager finalization. The reason is most | 464 // set aside for eager finalization. The reason is most |
| 465 // likely that the effective 'operator new' overload for | 465 // likely that the effective 'operator new' overload for |
| (...skipping 12 matching lines...) Expand all Loading... |
| 478 #else | 478 #else |
| 479 #define EAGERLY_FINALIZE() typedef int IsEagerlyFinalizedMarker | 479 #define EAGERLY_FINALIZE() typedef int IsEagerlyFinalizedMarker |
| 480 #endif | 480 #endif |
| 481 | 481 |
| 482 #if !ENABLE(OILPAN) | 482 #if !ENABLE(OILPAN) |
| 483 #define EAGERLY_FINALIZE_WILL_BE_REMOVED() EAGERLY_FINALIZE() | 483 #define EAGERLY_FINALIZE_WILL_BE_REMOVED() EAGERLY_FINALIZE() |
| 484 #else | 484 #else |
| 485 #define EAGERLY_FINALIZE_WILL_BE_REMOVED() | 485 #define EAGERLY_FINALIZE_WILL_BE_REMOVED() |
| 486 #endif | 486 #endif |
| 487 | 487 |
| 488 inline Address Heap::allocateOnHeapIndex(ThreadState* state, size_t size, int he
apIndex, size_t gcInfoIndex) | 488 inline Address Heap::allocateOnArenaIndex(ThreadState* state, size_t size, int a
renaIndex, size_t gcInfoIndex) |
| 489 { | 489 { |
| 490 ASSERT(state->isAllocationAllowed()); | 490 ASSERT(state->isAllocationAllowed()); |
| 491 ASSERT(heapIndex != BlinkGC::LargeObjectHeapIndex); | 491 ASSERT(arenaIndex != BlinkGC::LargeObjectArenaIndex); |
| 492 NormalPageHeap* heap = static_cast<NormalPageHeap*>(state->heap(heapIndex)); | 492 NormalPageHeap* heap = static_cast<NormalPageHeap*>(state->arena(arenaIndex)
); |
| 493 return heap->allocateObject(allocationSizeFromSize(size), gcInfoIndex); | 493 return heap->allocateObject(allocationSizeFromSize(size), gcInfoIndex); |
| 494 } | 494 } |
| 495 | 495 |
| 496 template<typename T> | 496 template<typename T> |
| 497 Address Heap::allocate(size_t size, bool eagerlySweep) | 497 Address Heap::allocate(size_t size, bool eagerlySweep) |
| 498 { | 498 { |
| 499 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); | 499 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); |
| 500 Address address = Heap::allocateOnHeapIndex(state, size, eagerlySweep ? Blin
kGC::EagerSweepHeapIndex : Heap::heapIndexForObjectSize(size), GCInfoTrait<T>::i
ndex()); | 500 Address address = Heap::allocateOnArenaIndex(state, size, eagerlySweep ? Bli
nkGC::EagerSweepArenaIndex : Heap::arenaIndexForObjectSize(size), GCInfoTrait<T>
::index()); |
| 501 const char* typeName = WTF_HEAP_PROFILER_TYPE_NAME(T); | 501 const char* typeName = WTF_HEAP_PROFILER_TYPE_NAME(T); |
| 502 HeapAllocHooks::allocationHookIfEnabled(address, size, typeName); | 502 HeapAllocHooks::allocationHookIfEnabled(address, size, typeName); |
| 503 return address; | 503 return address; |
| 504 } | 504 } |
| 505 | 505 |
| 506 template<typename T> | 506 template<typename T> |
| 507 Address Heap::reallocate(void* previous, size_t size) | 507 Address Heap::reallocate(void* previous, size_t size) |
| 508 { | 508 { |
| 509 // Not intended to be a full C realloc() substitute; | 509 // Not intended to be a full C realloc() substitute; |
| 510 // realloc(nullptr, size) is not a supported alias for malloc(size). | 510 // realloc(nullptr, size) is not a supported alias for malloc(size). |
| 511 | 511 |
| 512 // TODO(sof): promptly free the previous object. | 512 // TODO(sof): promptly free the previous object. |
| 513 if (!size) { | 513 if (!size) { |
| 514 // If the new size is 0 this is considered equivalent to free(previous). | 514 // If the new size is 0 this is considered equivalent to free(previous). |
| 515 return nullptr; | 515 return nullptr; |
| 516 } | 516 } |
| 517 | 517 |
| 518 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); | 518 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); |
| 519 HeapObjectHeader* previousHeader = HeapObjectHeader::fromPayload(previous); | 519 HeapObjectHeader* previousHeader = HeapObjectHeader::fromPayload(previous); |
| 520 BasePage* page = pageFromObject(previousHeader); | 520 BasePage* page = pageFromObject(previousHeader); |
| 521 ASSERT(page); | 521 ASSERT(page); |
| 522 int heapIndex = page->heap()->heapIndex(); | 522 int arenaIndex = page->arena()->arenaIndex(); |
| 523 // Recompute the effective heap index if previous allocation | 523 // Recompute the effective heap index if previous allocation |
| 524 // was on the normal heaps or a large object. | 524 // was on the normal arenas or a large object. |
| 525 if (isNormalHeapIndex(heapIndex) || heapIndex == BlinkGC::LargeObjectHeapInd
ex) | 525 if (isNormalArenaIndex(arenaIndex) || arenaIndex == BlinkGC::LargeObjectAren
aIndex) |
| 526 heapIndex = heapIndexForObjectSize(size); | 526 arenaIndex = arenaIndexForObjectSize(size); |
| 527 | 527 |
| 528 // TODO(haraken): We don't support reallocate() for finalizable objects. | 528 // TODO(haraken): We don't support reallocate() for finalizable objects. |
| 529 ASSERT(!Heap::gcInfo(previousHeader->gcInfoIndex())->hasFinalizer()); | 529 ASSERT(!Heap::gcInfo(previousHeader->gcInfoIndex())->hasFinalizer()); |
| 530 ASSERT(previousHeader->gcInfoIndex() == GCInfoTrait<T>::index()); | 530 ASSERT(previousHeader->gcInfoIndex() == GCInfoTrait<T>::index()); |
| 531 Address address = Heap::allocateOnHeapIndex(state, size, heapIndex, GCInfoTr
ait<T>::index()); | 531 Address address = Heap::allocateOnArenaIndex(state, size, arenaIndex, GCInfo
Trait<T>::index()); |
| 532 size_t copySize = previousHeader->payloadSize(); | 532 size_t copySize = previousHeader->payloadSize(); |
| 533 if (copySize > size) | 533 if (copySize > size) |
| 534 copySize = size; | 534 copySize = size; |
| 535 memcpy(address, previous, copySize); | 535 memcpy(address, previous, copySize); |
| 536 const char* typeName = WTF_HEAP_PROFILER_TYPE_NAME(T); | 536 const char* typeName = WTF_HEAP_PROFILER_TYPE_NAME(T); |
| 537 HeapAllocHooks::reallocHookIfEnabled(static_cast<Address>(previous), address
, size, typeName); | 537 HeapAllocHooks::reallocHookIfEnabled(static_cast<Address>(previous), address
, size, typeName); |
| 538 return address; | 538 return address; |
| 539 } | 539 } |
| 540 | 540 |
| 541 template<typename Derived> | 541 template<typename Derived> |
| 542 template<typename T> | 542 template<typename T> |
| 543 void VisitorHelper<Derived>::handleWeakCell(Visitor* self, void* object) | 543 void VisitorHelper<Derived>::handleWeakCell(Visitor* self, void* object) |
| 544 { | 544 { |
| 545 T** cell = reinterpret_cast<T**>(object); | 545 T** cell = reinterpret_cast<T**>(object); |
| 546 if (*cell && !ObjectAliveTrait<T>::isHeapObjectAlive(*cell)) | 546 if (*cell && !ObjectAliveTrait<T>::isHeapObjectAlive(*cell)) |
| 547 *cell = nullptr; | 547 *cell = nullptr; |
| 548 } | 548 } |
| 549 | 549 |
| 550 } // namespace blink | 550 } // namespace blink |
| 551 | 551 |
| 552 #endif // Heap_h | 552 #endif // Heap_h |
| OLD | NEW |