| 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 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 } | 445 } |
| 446 } | 446 } |
| 447 | 447 |
| 448 private: | 448 private: |
| 449 ThreadState* m_state; | 449 ThreadState* m_state; |
| 450 ThreadState::SafePointScope m_safePointScope; | 450 ThreadState::SafePointScope m_safePointScope; |
| 451 bool m_parkedAllThreads; // False if we fail to park all threads | 451 bool m_parkedAllThreads; // False if we fail to park all threads |
| 452 }; | 452 }; |
| 453 | 453 |
| 454 NO_SANITIZE_ADDRESS inline | 454 NO_SANITIZE_ADDRESS inline |
| 455 bool HeapObjectHeader::isMarked() const | |
| 456 { | |
| 457 checkHeader(); | |
| 458 return m_size & markBitMask; | |
| 459 } | |
| 460 | |
| 461 NO_SANITIZE_ADDRESS inline | |
| 462 void HeapObjectHeader::mark() | |
| 463 { | |
| 464 checkHeader(); | |
| 465 ASSERT(!isMarked()); | |
| 466 m_size = m_size | markBitMask; | |
| 467 } | |
| 468 | |
| 469 NO_SANITIZE_ADDRESS inline | |
| 470 void HeapObjectHeader::unmark() | 455 void HeapObjectHeader::unmark() |
| 471 { | 456 { |
| 472 checkHeader(); | 457 checkHeader(); |
| 473 ASSERT(isMarked()); | 458 ASSERT(isMarked()); |
| 474 m_size &= ~markBitMask; | 459 m_size &= ~markBitMask; |
| 475 } | 460 } |
| 476 | 461 |
| 477 NO_SANITIZE_ADDRESS inline | 462 NO_SANITIZE_ADDRESS inline |
| 478 bool HeapObjectHeader::isDead() const | 463 bool HeapObjectHeader::isDead() const |
| 479 { | 464 { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 491 | 476 |
| 492 #if ENABLE(ASSERT) | 477 #if ENABLE(ASSERT) |
| 493 NO_SANITIZE_ADDRESS | 478 NO_SANITIZE_ADDRESS |
| 494 void HeapObjectHeader::zapMagic() | 479 void HeapObjectHeader::zapMagic() |
| 495 { | 480 { |
| 496 checkHeader(); | 481 checkHeader(); |
| 497 m_magic = zappedMagic; | 482 m_magic = zappedMagic; |
| 498 } | 483 } |
| 499 #endif | 484 #endif |
| 500 | 485 |
| 501 HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) | |
| 502 { | |
| 503 Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); | |
| 504 HeapObjectHeader* header = | |
| 505 reinterpret_cast<HeapObjectHeader*>(addr - sizeof(HeapObjectHeader)); | |
| 506 return header; | |
| 507 } | |
| 508 | |
| 509 void HeapObjectHeader::finalize(const GCInfo* gcInfo, Address object, size_t obj
ectSize) | 486 void HeapObjectHeader::finalize(const GCInfo* gcInfo, Address object, size_t obj
ectSize) |
| 510 { | 487 { |
| 511 ASSERT(gcInfo); | 488 ASSERT(gcInfo); |
| 512 if (gcInfo->hasFinalizer()) { | 489 if (gcInfo->hasFinalizer()) { |
| 513 gcInfo->m_finalize(object); | 490 gcInfo->m_finalize(object); |
| 514 } | 491 } |
| 515 | 492 |
| 516 #if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) | 493 #if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) |
| 517 // In Debug builds, memory is zapped when it's freed, and the zapped memory
is | 494 // In Debug builds, memory is zapped when it's freed, and the zapped memory
is |
| 518 // zeroed out when the memory is reused. Memory is also zapped when using Le
ak | 495 // zeroed out when the memory is reused. Memory is also zapped when using Le
ak |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 heapObjectHeader()->finalize(); | 596 heapObjectHeader()->finalize(); |
| 620 } | 597 } |
| 621 | 598 |
| 622 template<> | 599 template<> |
| 623 void LargeObject<HeapObjectHeader>::finalize() | 600 void LargeObject<HeapObjectHeader>::finalize() |
| 624 { | 601 { |
| 625 ASSERT(gcInfo()); | 602 ASSERT(gcInfo()); |
| 626 HeapObjectHeader::finalize(gcInfo(), payload(), payloadSize()); | 603 HeapObjectHeader::finalize(gcInfo(), payload(), payloadSize()); |
| 627 } | 604 } |
| 628 | 605 |
| 629 GeneralHeapObjectHeader* GeneralHeapObjectHeader::fromPayload(const void* payloa
d) | |
| 630 { | |
| 631 Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); | |
| 632 GeneralHeapObjectHeader* header = | |
| 633 reinterpret_cast<GeneralHeapObjectHeader*>(addr - sizeof(GeneralHeapObje
ctHeader)); | |
| 634 return header; | |
| 635 } | |
| 636 | |
| 637 template<typename Header> | 606 template<typename Header> |
| 638 ThreadHeap<Header>::ThreadHeap(ThreadState* state, int index) | 607 ThreadHeap<Header>::ThreadHeap(ThreadState* state, int index) |
| 639 : m_currentAllocationPoint(0) | 608 : m_currentAllocationPoint(0) |
| 640 , m_remainingAllocationSize(0) | 609 , m_remainingAllocationSize(0) |
| 641 , m_lastRemainingAllocationSize(0) | 610 , m_lastRemainingAllocationSize(0) |
| 642 , m_firstPage(0) | 611 , m_firstPage(0) |
| 643 , m_firstLargeObject(0) | 612 , m_firstLargeObject(0) |
| 644 , m_firstPageAllocatedDuringSweeping(0) | 613 , m_firstPageAllocatedDuringSweeping(0) |
| 645 , m_lastPageAllocatedDuringSweeping(0) | 614 , m_lastPageAllocatedDuringSweeping(0) |
| 646 , m_firstLargeObjectAllocatedDuringSweeping(0) | 615 , m_firstLargeObjectAllocatedDuringSweeping(0) |
| (...skipping 1318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1965 void Heap::flushHeapDoesNotContainCache() | 1934 void Heap::flushHeapDoesNotContainCache() |
| 1966 { | 1935 { |
| 1967 s_heapDoesNotContainCache->flush(); | 1936 s_heapDoesNotContainCache->flush(); |
| 1968 } | 1937 } |
| 1969 | 1938 |
| 1970 static void markNoTracingCallback(Visitor* visitor, void* object) | 1939 static void markNoTracingCallback(Visitor* visitor, void* object) |
| 1971 { | 1940 { |
| 1972 visitor->markNoTracing(object); | 1941 visitor->markNoTracing(object); |
| 1973 } | 1942 } |
| 1974 | 1943 |
| 1975 enum MarkingMode { | |
| 1976 GlobalMarking, | |
| 1977 ThreadLocalMarking, | |
| 1978 }; | |
| 1979 | |
| 1980 template<MarkingMode Mode> | 1944 template<MarkingMode Mode> |
| 1981 class MarkingVisitor final : public Visitor { | 1945 class MarkingVisitor final : public Visitor { |
| 1982 public: | 1946 public: |
| 1983 #if ENABLE(GC_PROFILE_MARKING) | 1947 #if ENABLE(GC_PROFILE_MARKING) |
| 1984 typedef HashSet<uintptr_t> LiveObjectSet; | 1948 typedef HashSet<uintptr_t> LiveObjectSet; |
| 1985 typedef HashMap<String, LiveObjectSet> LiveObjectMap; | 1949 typedef HashMap<String, LiveObjectSet> LiveObjectMap; |
| 1986 typedef HashMap<uintptr_t, std::pair<uintptr_t, String> > ObjectGraph; | 1950 typedef HashMap<uintptr_t, std::pair<uintptr_t, String> > ObjectGraph; |
| 1987 #endif | 1951 #endif |
| 1988 | 1952 |
| 1989 explicit MarkingVisitor(CallbackStack* markingStack) | 1953 explicit MarkingVisitor(CallbackStack* markingStack) |
| 1990 : m_markingStack(markingStack) | 1954 : Visitor(Mode) |
| 1955 , m_markingStack(markingStack) |
| 1991 { | 1956 { |
| 1992 } | 1957 } |
| 1993 | 1958 |
| 1994 inline void visitHeader(HeapObjectHeader* header, const void* objectPointer,
TraceCallback callback) | 1959 inline void visitHeader(HeapObjectHeader* header, const void* objectPointer,
TraceCallback callback) |
| 1995 { | 1960 { |
| 1996 ASSERT(header); | 1961 ASSERT(header); |
| 1997 ASSERT(objectPointer); | 1962 ASSERT(objectPointer); |
| 1998 // Check that we are not marking objects that are outside | 1963 // Check that we are not marking objects that are outside |
| 1999 // the heap by calling Heap::contains. However we cannot | 1964 // the heap by calling Heap::contains. However we cannot |
| 2000 // call Heap::contains when outside a GC and we call mark | 1965 // call Heap::contains when outside a GC and we call mark |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2071 { | 2036 { |
| 2072 return Heap::weakTableRegistered(closure); | 2037 return Heap::weakTableRegistered(closure); |
| 2073 } | 2038 } |
| 2074 #endif | 2039 #endif |
| 2075 | 2040 |
| 2076 virtual bool isMarked(const void* objectPointer) override | 2041 virtual bool isMarked(const void* objectPointer) override |
| 2077 { | 2042 { |
| 2078 return GeneralHeapObjectHeader::fromPayload(objectPointer)->isMarked(); | 2043 return GeneralHeapObjectHeader::fromPayload(objectPointer)->isMarked(); |
| 2079 } | 2044 } |
| 2080 | 2045 |
| 2081 virtual bool ensureMarked(const void* objectPointer) override | 2046 /* |
| 2082 { | |
| 2083 if (!objectPointer) | |
| 2084 return false; | |
| 2085 if (Mode == ThreadLocalMarking && !objectInTerminatingThreadHeap(objectP
ointer)) | |
| 2086 return false; | |
| 2087 #if ENABLE(ASSERT) | |
| 2088 if (isMarked(objectPointer)) | |
| 2089 return false; | |
| 2090 | |
| 2091 markNoTracing(objectPointer); | |
| 2092 #else | |
| 2093 // Inline what the above markNoTracing() call expands to, | |
| 2094 // so as to make sure that we do get all the benefits. | |
| 2095 GeneralHeapObjectHeader* header = | |
| 2096 GeneralHeapObjectHeader::fromPayload(objectPointer); | |
| 2097 if (header->isMarked()) | |
| 2098 return false; | |
| 2099 header->mark(); | |
| 2100 #endif | |
| 2101 return true; | |
| 2102 } | |
| 2103 | |
| 2104 #if ENABLE(ASSERT) | 2047 #if ENABLE(ASSERT) |
| 2105 #define DEFINE_ENSURE_MARKED_METHOD(Type)
\ | 2048 #define DEFINE_ENSURE_MARKED_METHOD(Type)
\ |
| 2106 virtual bool ensureMarked(const Type* objectPointer) override
\ | 2049 virtual bool ensureMarked(const Type* objectPointer) override
\ |
| 2107 {
\ | 2050 {
\ |
| 2108 if (!objectPointer)
\ | 2051 if (!objectPointer)
\ |
| 2109 return false;
\ | 2052 return false;
\ |
| 2110 COMPILE_ASSERT(!NeedsAdjustAndMark<Type>::value, CanOnlyUseIsMarkedOnNon
AdjustedTypes); \ | 2053 COMPILE_ASSERT(!NeedsAdjustAndMark<Type>::value, CanOnlyUseIsMarkedOnNon
AdjustedTypes); \ |
| 2111 if (Mode == ThreadLocalMarking && !objectInTerminatingThreadHeap(objectP
ointer)) \ | 2054 if (Mode == ThreadLocalMarking && !objectInTerminatingThreadHeap(objectP
ointer)) \ |
| 2112 return false;
\ | 2055 return false;
\ |
| 2113 if (isMarked(objectPointer))
\ | 2056 if (isMarked(objectPointer))
\ |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2124 if (Mode == ThreadLocalMarking && !objectInTerminatingThreadHeap(objectP
ointer)) \ | 2067 if (Mode == ThreadLocalMarking && !objectInTerminatingThreadHeap(objectP
ointer)) \ |
| 2125 return false;
\ | 2068 return false;
\ |
| 2126 HeapObjectHeader* header =
\ | 2069 HeapObjectHeader* header =
\ |
| 2127 HeapObjectHeader::fromPayload(objectPointer);
\ | 2070 HeapObjectHeader::fromPayload(objectPointer);
\ |
| 2128 if (header->isMarked())
\ | 2071 if (header->isMarked())
\ |
| 2129 return false;
\ | 2072 return false;
\ |
| 2130 header->mark();
\ | 2073 header->mark();
\ |
| 2131 return true;
\ | 2074 return true;
\ |
| 2132 } | 2075 } |
| 2133 #endif | 2076 #endif |
| 2077 */ |
| 2134 | 2078 |
| 2135 // This macro defines the necessary visitor methods for typed heaps | 2079 // This macro defines the necessary visitor methods for typed heaps |
| 2136 #define DEFINE_VISITOR_METHODS(Type)
\ | 2080 #define DEFINE_VISITOR_METHODS(Type)
\ |
| 2137 virtual void mark(const Type* objectPointer, TraceCallback callback) overrid
e \ | 2081 virtual void mark(const Type* objectPointer, TraceCallback callback) overrid
e \ |
| 2138 {
\ | 2082 {
\ |
| 2139 if (!objectPointer)
\ | 2083 if (!objectPointer)
\ |
| 2140 return;
\ | 2084 return;
\ |
| 2141 HeapObjectHeader* header =
\ | 2085 HeapObjectHeader* header =
\ |
| 2142 HeapObjectHeader::fromPayload(objectPointer);
\ | 2086 HeapObjectHeader::fromPayload(objectPointer);
\ |
| 2143 visitHeader(header, header->payload(), callback);
\ | 2087 visitHeader(header, header->payload(), callback);
\ |
| 2144 }
\ | 2088 }
\ |
| 2145 virtual bool isMarked(const Type* objectPointer) override
\ | 2089 virtual bool isMarked(const Type* objectPointer) override
\ |
| 2146 {
\ | 2090 {
\ |
| 2147 return HeapObjectHeader::fromPayload(objectPointer)->isMarked();
\ | 2091 return HeapObjectHeader::fromPayload(objectPointer)->isMarked();
\ |
| 2148 }
\ | 2092 } |
| 2149 DEFINE_ENSURE_MARKED_METHOD(Type) | |
| 2150 | 2093 |
| 2151 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS) | 2094 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS) |
| 2152 #undef DEFINE_VISITOR_METHODS | 2095 #undef DEFINE_VISITOR_METHODS |
| 2153 | 2096 |
| 2154 #if ENABLE(GC_PROFILE_MARKING) | 2097 #if ENABLE(GC_PROFILE_MARKING) |
| 2155 void reportStats() | 2098 void reportStats() |
| 2156 { | 2099 { |
| 2157 fprintf(stderr, "\n---------- AFTER MARKING -------------------\n"); | 2100 fprintf(stderr, "\n---------- AFTER MARKING -------------------\n"); |
| 2158 for (LiveObjectMap::iterator it = currentlyLive().begin(), end = current
lyLive().end(); it != end; ++it) { | 2101 for (LiveObjectMap::iterator it = currentlyLive().begin(), end = current
lyLive().end(); it != end; ++it) { |
| 2159 fprintf(stderr, "%s %u", it->key.ascii().data(), it->value.size()); | 2102 fprintf(stderr, "%s %u", it->key.ascii().data(), it->value.size()); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2240 return graph; | 2183 return graph; |
| 2241 } | 2184 } |
| 2242 | 2185 |
| 2243 static HashSet<uintptr_t>& objectsToFindPath() | 2186 static HashSet<uintptr_t>& objectsToFindPath() |
| 2244 { | 2187 { |
| 2245 DEFINE_STATIC_LOCAL(HashSet<uintptr_t>, set, ()); | 2188 DEFINE_STATIC_LOCAL(HashSet<uintptr_t>, set, ()); |
| 2246 return set; | 2189 return set; |
| 2247 } | 2190 } |
| 2248 #endif | 2191 #endif |
| 2249 | 2192 |
| 2250 static inline bool objectInTerminatingThreadHeap(const void* objectPointer) | |
| 2251 { | |
| 2252 BaseHeapPage* page = pageFromObject(objectPointer); | |
| 2253 ASSERT(!page->orphaned()); | |
| 2254 // When doing a thread local GC, the marker checks if | |
| 2255 // the object resides in another thread's heap. The | |
| 2256 // object should not be traced, if it does. | |
| 2257 return page->terminating(); | |
| 2258 } | |
| 2259 | |
| 2260 protected: | 2193 protected: |
| 2261 virtual void registerWeakCell(void** cell, WeakPointerCallback callback) ove
rride | 2194 virtual void registerWeakCell(void** cell, WeakPointerCallback callback) ove
rride |
| 2262 { | 2195 { |
| 2263 Heap::pushWeakCellPointerCallback(cell, callback); | 2196 Heap::pushWeakCellPointerCallback(cell, callback); |
| 2264 } | 2197 } |
| 2265 | 2198 |
| 2266 private: | 2199 private: |
| 2267 CallbackStack* m_markingStack; | 2200 CallbackStack* m_markingStack; |
| 2268 }; | 2201 }; |
| 2269 | 2202 |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2938 bool Heap::s_shutdownCalled = false; | 2871 bool Heap::s_shutdownCalled = false; |
| 2939 bool Heap::s_lastGCWasConservative = false; | 2872 bool Heap::s_lastGCWasConservative = false; |
| 2940 FreePagePool* Heap::s_freePagePool; | 2873 FreePagePool* Heap::s_freePagePool; |
| 2941 OrphanedPagePool* Heap::s_orphanedPagePool; | 2874 OrphanedPagePool* Heap::s_orphanedPagePool; |
| 2942 Heap::RegionTree* Heap::s_regionTree = 0; | 2875 Heap::RegionTree* Heap::s_regionTree = 0; |
| 2943 size_t Heap::s_allocatedObjectSize = 0; | 2876 size_t Heap::s_allocatedObjectSize = 0; |
| 2944 size_t Heap::s_allocatedSpace = 0; | 2877 size_t Heap::s_allocatedSpace = 0; |
| 2945 size_t Heap::s_markedObjectSize = 0; | 2878 size_t Heap::s_markedObjectSize = 0; |
| 2946 | 2879 |
| 2947 } // namespace blink | 2880 } // namespace blink |
| OLD | NEW |