| 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 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 return heapObjectHeader()->unmark(); | 464 return heapObjectHeader()->unmark(); |
| 465 } | 465 } |
| 466 | 466 |
| 467 template<typename Header> | 467 template<typename Header> |
| 468 bool LargeHeapObject<Header>::isMarked() | 468 bool LargeHeapObject<Header>::isMarked() |
| 469 { | 469 { |
| 470 return heapObjectHeader()->isMarked(); | 470 return heapObjectHeader()->isMarked(); |
| 471 } | 471 } |
| 472 | 472 |
| 473 template<typename Header> | 473 template<typename Header> |
| 474 bool LargeHeapObject<Header>::checkAndVisitPointer(Visitor* visitor, Address add
ress) | 474 bool LargeHeapObject<Header>::checkAndMarkPointer(Visitor* visitor, Address addr
ess) |
| 475 { | 475 { |
| 476 if (contains(address)) { | 476 if (contains(address)) { |
| 477 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING | 477 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING |
| 478 visitor->setHostInfo(&address, "stack"); | 478 visitor->setHostInfo(&address, "stack"); |
| 479 #endif | 479 #endif |
| 480 visit(visitor); | 480 trace(visitor); |
| 481 return true; | 481 return true; |
| 482 } | 482 } |
| 483 return false; | 483 return false; |
| 484 } | 484 } |
| 485 | 485 |
| 486 template<> | 486 template<> |
| 487 void LargeHeapObject<FinalizedHeapObjectHeader>::visit(Visitor* visitor) | 487 void LargeHeapObject<FinalizedHeapObjectHeader>::trace(Visitor* visitor) |
| 488 { | 488 { |
| 489 visitor->visit(heapObjectHeader(), heapObjectHeader()->traceCallback()); | 489 visitor->mark(heapObjectHeader(), heapObjectHeader()->traceCallback()); |
| 490 } | 490 } |
| 491 | 491 |
| 492 template<> | 492 template<> |
| 493 void LargeHeapObject<HeapObjectHeader>::visit(Visitor* visitor) | 493 void LargeHeapObject<HeapObjectHeader>::trace(Visitor* visitor) |
| 494 { | 494 { |
| 495 ASSERT(gcInfo()); | 495 ASSERT(gcInfo()); |
| 496 visitor->visit(heapObjectHeader(), gcInfo()->m_trace); | 496 visitor->mark(heapObjectHeader(), gcInfo()->m_trace); |
| 497 } | 497 } |
| 498 | 498 |
| 499 template<> | 499 template<> |
| 500 void LargeHeapObject<FinalizedHeapObjectHeader>::finalize() | 500 void LargeHeapObject<FinalizedHeapObjectHeader>::finalize() |
| 501 { | 501 { |
| 502 heapObjectHeader()->finalize(); | 502 heapObjectHeader()->finalize(); |
| 503 } | 503 } |
| 504 | 504 |
| 505 template<> | 505 template<> |
| 506 void LargeHeapObject<HeapObjectHeader>::finalize() | 506 void LargeHeapObject<HeapObjectHeader>::finalize() |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 { | 598 { |
| 599 ASSERT(ThreadState::isAnyThreadInGC()); | 599 ASSERT(ThreadState::isAnyThreadInGC()); |
| 600 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); | 600 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); |
| 601 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { | 601 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { |
| 602 if ((*it)->contains(address)) | 602 if ((*it)->contains(address)) |
| 603 return true; | 603 return true; |
| 604 } | 604 } |
| 605 return false; | 605 return false; |
| 606 } | 606 } |
| 607 | 607 |
| 608 Address Heap::checkAndVisitPointer(Visitor* visitor, Address address) | 608 Address Heap::checkAndMarkPointer(Visitor* visitor, Address address) |
| 609 { | 609 { |
| 610 ASSERT(ThreadState::isAnyThreadInGC()); | 610 ASSERT(ThreadState::isAnyThreadInGC()); |
| 611 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); | 611 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); |
| 612 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { | 612 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { |
| 613 if ((*it)->checkAndVisitPointer(visitor, address)) { | 613 if ((*it)->checkAndMarkPointer(visitor, address)) { |
| 614 // Pointer found and visited | 614 // Pointer found and marked. |
| 615 return address; | 615 return address; |
| 616 } | 616 } |
| 617 } | 617 } |
| 618 return 0; | 618 return 0; |
| 619 } | 619 } |
| 620 | 620 |
| 621 template<typename Header> | 621 template<typename Header> |
| 622 BaseHeapPage* ThreadHeap<Header>::heapPageFromAddress(Address address) | 622 BaseHeapPage* ThreadHeap<Header>::heapPageFromAddress(Address address) |
| 623 { | 623 { |
| 624 for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) { | 624 for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) { |
| 625 if (page->contains(address)) | 625 if (page->contains(address)) |
| 626 return page; | 626 return page; |
| 627 } | 627 } |
| 628 return 0; | 628 return 0; |
| 629 } | 629 } |
| 630 | 630 |
| 631 template<typename Header> | 631 template<typename Header> |
| 632 BaseHeapPage* ThreadHeap<Header>::largeHeapObjectFromAddress(Address address) | 632 BaseHeapPage* ThreadHeap<Header>::largeHeapObjectFromAddress(Address address) |
| 633 { | 633 { |
| 634 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur
rent = current->next()) { | 634 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur
rent = current->next()) { |
| 635 if (current->contains(address)) | 635 if (current->contains(address)) |
| 636 return current; | 636 return current; |
| 637 } | 637 } |
| 638 return 0; | 638 return 0; |
| 639 } | 639 } |
| 640 | 640 |
| 641 template<typename Header> | 641 template<typename Header> |
| 642 bool ThreadHeap<Header>::checkAndVisitLargeHeapObjects(Visitor* visitor, Address
address) | 642 bool ThreadHeap<Header>::checkAndMarkLargeHeapObjects(Visitor* visitor, Address
address) |
| 643 { | 643 { |
| 644 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur
rent = current->next()) { | 644 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur
rent = current->next()) { |
| 645 if (current->checkAndVisitPointer(visitor, address)) | 645 if (current->checkAndMarkPointer(visitor, address)) |
| 646 return true; | 646 return true; |
| 647 } | 647 } |
| 648 return false; | 648 return false; |
| 649 } | 649 } |
| 650 | 650 |
| 651 template<typename Header> | 651 template<typename Header> |
| 652 void ThreadHeap<Header>::addToFreeList(Address address, size_t size) | 652 void ThreadHeap<Header>::addToFreeList(Address address, size_t size) |
| 653 { | 653 { |
| 654 ASSERT(heapPageFromAddress(address)); | 654 ASSERT(heapPageFromAddress(address)); |
| 655 ASSERT(heapPageFromAddress(address + size - 1)); | 655 ASSERT(heapPageFromAddress(address + size - 1)); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 873 // FIXME(oilpan): It's unsafe to iterate threads outside of GC. Enable the A
SSERT. | 873 // FIXME(oilpan): It's unsafe to iterate threads outside of GC. Enable the A
SSERT. |
| 874 // ASSERT(ThreadState::isAnyThreadInGC()); | 874 // ASSERT(ThreadState::isAnyThreadInGC()); |
| 875 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); | 875 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); |
| 876 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { | 876 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { |
| 877 HeapStats temp; | 877 HeapStats temp; |
| 878 (*it)->getStats(temp); | 878 (*it)->getStats(temp); |
| 879 stats->add(&temp); | 879 stats->add(&temp); |
| 880 } | 880 } |
| 881 } | 881 } |
| 882 | 882 |
| 883 #ifndef NDEBUG | |
| 884 // #define ENABLE_TRACE_CHECKER | |
| 885 #endif | |
| 886 | |
| 887 #ifdef ENABLE_TRACE_CHECKER | |
| 888 class TraceChecker { | |
| 889 public: | |
| 890 TraceChecker(void* object, TraceCallback callback, TraceRequirement requirem
ent) | |
| 891 : m_object(object) | |
| 892 , m_callback(callback) | |
| 893 , m_traceRequirement(requirement) | |
| 894 , m_previous(s_current) | |
| 895 { | |
| 896 s_current = this; | |
| 897 // Unmark the object pointed to by each intra-heap pointer we find by | |
| 898 // conservative scanning. | |
| 899 iteratePointers(clearMarksAction); | |
| 900 } | |
| 901 | |
| 902 ~TraceChecker() | |
| 903 { | |
| 904 // Check the marks on the objects pointed to by each intra-heap pointer | |
| 905 // we find by conservative scanning. | |
| 906 if (m_traceRequirement == AllPointersMustBeVisited) | |
| 907 iteratePointers(checkDebugMarksAction); | |
| 908 else if (m_traceRequirement == AllPointersMustBeMarked) | |
| 909 iteratePointers(checkMarkedAction); | |
| 910 s_current = m_previous; | |
| 911 } | |
| 912 | |
| 913 static void rememberedToVisit(HeapObjectHeader* header) | |
| 914 { | |
| 915 header->setDebugMark(); | |
| 916 } | |
| 917 | |
| 918 static void registerWeakPointers() | |
| 919 { | |
| 920 s_current->m_traceRequirement = NoRequirement; | |
| 921 } | |
| 922 | |
| 923 static void init() | |
| 924 { | |
| 925 s_current = 0; | |
| 926 } | |
| 927 | |
| 928 private: | |
| 929 typedef void (*IntraHeapPointerAction)(TraceChecker* self, Address); | |
| 930 | |
| 931 // Find the intra-heap pointers by scanning the allocated object | |
| 932 // conservatively. | |
| 933 void iteratePointers(IntraHeapPointerAction action) | |
| 934 { | |
| 935 HeapObjectHeader* header = HeapObjectHeader::fromPayload(m_object); | |
| 936 Address* start = reinterpret_cast<Address*>(m_object); | |
| 937 Address* limit = reinterpret_cast<Address*>(header->payloadEnd()); | |
| 938 | |
| 939 for (Address* p = start; p < limit; p++) { | |
| 940 Address address = *p; | |
| 941 Address* castAddress = reinterpret_cast<Address*>(address); | |
| 942 // Find out whether the pointer looks like a pointer to another | |
| 943 // object on the heap. We ignore pointers within the object itself. | |
| 944 // We assume that things that are not object aligned are not | |
| 945 // actually pointers. | |
| 946 if ((castAddress < start || castAddress >= limit) | |
| 947 && Heap::contains(address) && isObjectAligned(address)) | |
| 948 action(this, address); | |
| 949 } | |
| 950 } | |
| 951 | |
| 952 static void clearMarksAction(TraceChecker* self, Address address) | |
| 953 { | |
| 954 HeapObjectHeader* header = HeapObjectHeader::fromPayload(address); | |
| 955 // Unmark the object (if it was already marked) so that we can check | |
| 956 // the mark after the trace method to see if it has been marked again. | |
| 957 header->clearDebugMark(); | |
| 958 } | |
| 959 | |
| 960 static void checkDebugMarksAction(TraceChecker* self, Address address) | |
| 961 { | |
| 962 HeapObjectHeader* header = HeapObjectHeader::fromPayload(address); | |
| 963 if (!header->hasDebugMark()) { | |
| 964 self->reportMishandledPointer( | |
| 965 address, | |
| 966 "Failure to visit all intra-heap pointers in trace method"); | |
| 967 } | |
| 968 } | |
| 969 | |
| 970 static void checkMarkedAction(TraceChecker* self, Address address) | |
| 971 { | |
| 972 HeapObjectHeader* header = HeapObjectHeader::fromPayload(address); | |
| 973 if (!header->isMarked()) { | |
| 974 self->reportMishandledPointer( | |
| 975 address, | |
| 976 "Failure to visit all strong pointers or clear all weak pointers
to dead objects"); | |
| 977 } | |
| 978 } | |
| 979 | |
| 980 | |
| 981 void reportMishandledPointer(Address unvisitedAddress, const char* reason) | |
| 982 { | |
| 983 // Getting an assert in this method means either the trace method | |
| 984 // failed to visit a strong pointer, or the weak pointer callback failed | |
| 985 // to clear a weak pointer to an object that is dead. | |
| 986 class YouForgotToVisitAllPointersVisitor : public Visitor { | |
| 987 public: | |
| 988 virtual void visit(const void* objectPointer, TraceCallback callback
) | |
| 989 { | |
| 990 ASSERT_NOT_REACHED(); // See comment below. | |
| 991 } | |
| 992 }; | |
| 993 | |
| 994 YouForgotToVisitAllPointersVisitor youForgotToVisitAllPointersVisitor; | |
| 995 // If the callback calls the visitor at least once it will assert, and | |
| 996 // we can catch the assert in the debugger with the offending callback | |
| 997 // on the stack, and the object that was insufficiently visited/cleared | |
| 998 // as its argument. In this frame, 'address' will tell you the pointer | |
| 999 // that was in the object, but which was not visited. | |
| 1000 m_callback(&youForgotToVisitAllPointersVisitor, m_object); | |
| 1001 // If we get here the callback did not even visit one pointer. Cause an | |
| 1002 // assert here, and in the debugger you can get the address of the | |
| 1003 // offending callback from the this->m_callback variable, and the | |
| 1004 // unvisited/uncleared pointer from the 'address' argument. The object t
hat | |
| 1005 // contained the unvisited pointer is in this->m_object. | |
| 1006 ASSERT_NOT_REACHED(); | |
| 1007 } | |
| 1008 | |
| 1009 static bool isObjectAligned(Address address) | |
| 1010 { | |
| 1011 return !(reinterpret_cast<uintptr_t>(address) & allocationMask); | |
| 1012 } | |
| 1013 | |
| 1014 void* m_object; | |
| 1015 TraceCallback m_callback; | |
| 1016 TraceRequirement m_traceRequirement; | |
| 1017 TraceChecker* m_previous; | |
| 1018 static TraceChecker* s_current; | |
| 1019 }; | |
| 1020 | |
| 1021 TraceChecker* TraceChecker::s_current; | |
| 1022 | |
| 1023 #else // !ENABLE_TRACE_CHECKER | |
| 1024 | |
| 1025 class TraceChecker { | |
| 1026 public: | |
| 1027 TraceChecker(void*, TraceCallback, TraceRequirement) { } | |
| 1028 static void rememberedToVisit(const HeapObjectHeader*) { } | |
| 1029 static void init() { } | |
| 1030 static void registerWeakPointers() { } | |
| 1031 }; | |
| 1032 #endif // ENABLE_TRACE_CHECKER | |
| 1033 | |
| 1034 #if TRACE_GC_USING_CLASSOF | 883 #if TRACE_GC_USING_CLASSOF |
| 1035 static const char* classOf(const void* object) | 884 static const char* classOf(const void* object) |
| 1036 { | 885 { |
| 1037 void* obj = const_cast<void*>(object); | 886 void* obj = const_cast<void*>(object); |
| 1038 BaseHeapPage* page = | 887 BaseHeapPage* page = |
| 1039 reinterpret_cast<BaseHeapPage*>(pageHeaderAddress(reinterpret_cast<Addre
ss>(obj))); | 888 reinterpret_cast<BaseHeapPage*>(pageHeaderAddress(reinterpret_cast<Addre
ss>(obj))); |
| 1040 const GCMap* info = page->gcInfo(); | 889 const GCMap* info = page->gcInfo(); |
| 1041 if (info) { | 890 if (info) { |
| 1042 // The GCInfo is set only on typed heap pages. | 891 // The GCInfo is set only on typed heap pages. |
| 1043 ASSERT(info->m_classOf); | 892 ASSERT(info->m_classOf); |
| 1044 return info->m_classOf(obj); | 893 return info->m_classOf(obj); |
| 1045 } | 894 } |
| 1046 return FinalizedHeapObjectHeader::fromPayload(object)->classOf(); | 895 return FinalizedHeapObjectHeader::fromPayload(object)->classOf(); |
| 1047 } | 896 } |
| 1048 #endif | 897 #endif |
| 1049 | 898 |
| 1050 class MarkingVisitor : public Visitor { | 899 class MarkingVisitor : public Visitor { |
| 1051 public: | 900 public: |
| 1052 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING | 901 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING |
| 1053 typedef std::set<intptr_t> LiveObjectSet; | 902 typedef std::set<intptr_t> LiveObjectSet; |
| 1054 typedef std::map<std::string, std::set<intptr_t> > LiveObjectMap; | 903 typedef std::map<std::string, std::set<intptr_t> > LiveObjectMap; |
| 1055 #endif | 904 #endif |
| 1056 | 905 |
| 1057 inline void visitHeader(HeapObjectHeader* header, const void* objectPointer,
TraceCallback callback) | 906 inline void visitHeader(HeapObjectHeader* header, const void* objectPointer,
TraceCallback callback) |
| 1058 { | 907 { |
| 1059 ASSERT(header); | 908 ASSERT(header); |
| 1060 ASSERT(objectPointer); | 909 ASSERT(objectPointer); |
| 1061 TraceChecker::rememberedToVisit(header); | |
| 1062 if (header->isMarked()) | 910 if (header->isMarked()) |
| 1063 return; | 911 return; |
| 1064 header->mark(); | 912 header->mark(); |
| 1065 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING | 913 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING |
| 1066 const std::string className(classOf(objectPointer)); | 914 const std::string className(classOf(objectPointer)); |
| 1067 currentlyLive()[className].insert(reinterpret_cast<intptr_t>(objectPoint
er)); | 915 currentlyLive()[className].insert(reinterpret_cast<intptr_t>(objectPoint
er)); |
| 1068 printf("%s[%p] -> %s[%p]\n", m_hostName, m_hostObject, className.c_str()
, objectPointer); | 916 printf("%s[%p] -> %s[%p]\n", m_hostName, m_hostObject, className.c_str()
, objectPointer); |
| 1069 #endif | 917 #endif |
| 1070 if (callback) | 918 if (callback) |
| 1071 Heap::pushTraceCallback(const_cast<void*>(objectPointer), callback); | 919 Heap::pushTraceCallback(const_cast<void*>(objectPointer), callback); |
| 1072 } | 920 } |
| 1073 | 921 |
| 1074 virtual void visit(HeapObjectHeader* header, TraceCallback callback) | 922 virtual void mark(HeapObjectHeader* header, TraceCallback callback) |
| 1075 { | 923 { |
| 1076 // We need both the HeapObjectHeader and FinalizedHeapObjectHeader versi
on to | 924 // We need both the HeapObjectHeader and FinalizedHeapObjectHeader versi
on to |
| 1077 // correctly find the payload. | 925 // correctly find the payload. |
| 1078 visitHeader(header, header->payload(), callback); | 926 visitHeader(header, header->payload(), callback); |
| 1079 } | 927 } |
| 1080 | 928 |
| 1081 virtual void visit(FinalizedHeapObjectHeader* header, TraceCallback callback
) | 929 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) |
| 1082 { | 930 { |
| 1083 // We need both the HeapObjectHeader and FinalizedHeapObjectHeader versi
on to | 931 // We need both the HeapObjectHeader and FinalizedHeapObjectHeader versi
on to |
| 1084 // correctly find the payload. | 932 // correctly find the payload. |
| 1085 visitHeader(header, header->payload(), callback); | 933 visitHeader(header, header->payload(), callback); |
| 1086 } | 934 } |
| 1087 | 935 |
| 1088 virtual void visit(const void* objectPointer, TraceCallback callback) | 936 virtual void mark(const void* objectPointer, TraceCallback callback) |
| 1089 { | 937 { |
| 1090 if (!objectPointer) | 938 if (!objectPointer) |
| 1091 return; | 939 return; |
| 1092 FinalizedHeapObjectHeader* header = FinalizedHeapObjectHeader::fromPaylo
ad(objectPointer); | 940 FinalizedHeapObjectHeader* header = FinalizedHeapObjectHeader::fromPaylo
ad(objectPointer); |
| 1093 visitHeader(header, header->payload(), callback); | 941 visitHeader(header, header->payload(), callback); |
| 1094 } | 942 } |
| 1095 | 943 |
| 1096 virtual void registerWeakPointers(const void* containingObject, WeakPointerC
allback callback) | 944 virtual void registerWeakPointers(const void* containingObject, WeakPointerC
allback callback) |
| 1097 { | 945 { |
| 1098 TraceChecker::registerWeakPointers(); | |
| 1099 Heap::pushWeakCallback(const_cast<void*>(containingObject), callback); | 946 Heap::pushWeakCallback(const_cast<void*>(containingObject), callback); |
| 1100 } | 947 } |
| 1101 | 948 |
| 1102 virtual bool isMarked(const void* objectPointer) | 949 virtual bool isMarked(const void* objectPointer) |
| 1103 { | 950 { |
| 1104 return FinalizedHeapObjectHeader::fromPayload(objectPointer)->isMarked()
; | 951 return FinalizedHeapObjectHeader::fromPayload(objectPointer)->isMarked()
; |
| 1105 } | 952 } |
| 1106 | 953 |
| 1107 // Macro to help defining the necessary visitor methods for typed heaps | 954 // Macro to help defining the necessary visitor methods for typed heaps |
| 1108 #define DEFINE_VISITOR_METHODS(Type)
\ | 955 #define DEFINE_VISITOR_METHODS(Type)
\ |
| 1109 virtual void visit(const Type* objectPointer, TraceCallback callback)
\ | 956 virtual void mark(const Type* objectPointer, TraceCallback callback)
\ |
| 1110 {
\ | 957 {
\ |
| 1111 if (!objectPointer)
\ | 958 if (!objectPointer)
\ |
| 1112 return;
\ | 959 return;
\ |
| 1113 HeapObjectHeader* header = HeapObjectHeader::fromPayload(objectPointer);
\ | 960 HeapObjectHeader* header = HeapObjectHeader::fromPayload(objectPointer);
\ |
| 1114 visitHeader(header, header->payload(), callback);
\ | 961 visitHeader(header, header->payload(), callback);
\ |
| 1115 }
\ | 962 }
\ |
| 1116 virtual bool isMarked(const Type* objectPointer)
\ | 963 virtual bool isMarked(const Type* objectPointer)
\ |
| 1117 {
\ | 964 {
\ |
| 1118 return HeapObjectHeader::fromPayload(objectPointer)->isMarked();
\ | 965 return HeapObjectHeader::fromPayload(objectPointer)->isMarked();
\ |
| 1119 } | 966 } |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1273 if (byte <= 0x3F) { | 1120 if (byte <= 0x3F) { |
| 1274 result += 2; | 1121 result += 2; |
| 1275 byte = byte << 2; | 1122 byte = byte << 2; |
| 1276 } | 1123 } |
| 1277 if (byte <= 0x7F) | 1124 if (byte <= 0x7F) |
| 1278 result++; | 1125 result++; |
| 1279 return result; | 1126 return result; |
| 1280 } | 1127 } |
| 1281 | 1128 |
| 1282 template<typename Header> | 1129 template<typename Header> |
| 1283 bool HeapPage<Header>::checkAndVisitPointer(Visitor* visitor, Address addr) | 1130 bool HeapPage<Header>::checkAndMarkPointer(Visitor* visitor, Address addr) |
| 1284 { | 1131 { |
| 1285 if (addr < payload()) | 1132 if (addr < payload()) |
| 1286 return false; | 1133 return false; |
| 1287 if (!isObjectStartBitMapComputed()) | 1134 if (!isObjectStartBitMapComputed()) |
| 1288 populateObjectStartBitMap(); | 1135 populateObjectStartBitMap(); |
| 1289 size_t objectOffset = addr - payload(); | 1136 size_t objectOffset = addr - payload(); |
| 1290 size_t objectStartNumber = objectOffset / allocationGranularity; | 1137 size_t objectStartNumber = objectOffset / allocationGranularity; |
| 1291 size_t mapIndex = objectStartNumber / 8; | 1138 size_t mapIndex = objectStartNumber / 8; |
| 1292 ASSERT(mapIndex < objectStartBitMapSize); | 1139 ASSERT(mapIndex < objectStartBitMapSize); |
| 1293 size_t bit = objectStartNumber & 7; | 1140 size_t bit = objectStartNumber & 7; |
| 1294 uint8_t byte = m_objectStartBitMap[mapIndex] & ((1 << (bit + 1)) - 1); | 1141 uint8_t byte = m_objectStartBitMap[mapIndex] & ((1 << (bit + 1)) - 1); |
| 1295 while (!byte) { | 1142 while (!byte) { |
| 1296 ASSERT(mapIndex > 0); | 1143 ASSERT(mapIndex > 0); |
| 1297 byte = m_objectStartBitMap[--mapIndex]; | 1144 byte = m_objectStartBitMap[--mapIndex]; |
| 1298 } | 1145 } |
| 1299 int leadingZeroes = numberOfLeadingZeroes(byte); | 1146 int leadingZeroes = numberOfLeadingZeroes(byte); |
| 1300 objectStartNumber = (mapIndex * 8) + 7 - leadingZeroes; | 1147 objectStartNumber = (mapIndex * 8) + 7 - leadingZeroes; |
| 1301 objectOffset = objectStartNumber * allocationGranularity; | 1148 objectOffset = objectStartNumber * allocationGranularity; |
| 1302 Address objectAddress = objectOffset + payload(); | 1149 Address objectAddress = objectOffset + payload(); |
| 1303 Header* header = reinterpret_cast<Header*>(objectAddress); | 1150 Header* header = reinterpret_cast<Header*>(objectAddress); |
| 1304 if (header->isFree()) | 1151 if (header->isFree()) |
| 1305 return false; | 1152 return false; |
| 1306 | 1153 |
| 1307 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING | 1154 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING |
| 1308 visitor->setHostInfo(&addr, "stack"); | 1155 visitor->setHostInfo(&addr, "stack"); |
| 1309 #endif | 1156 #endif |
| 1310 visitor->visit(header, traceCallback(header)); | 1157 visitor->mark(header, traceCallback(header)); |
| 1311 return true; | 1158 return true; |
| 1312 } | 1159 } |
| 1313 | 1160 |
| 1314 #if USE_ASAN | 1161 #if USE_ASAN |
| 1315 template<typename Header> | 1162 template<typename Header> |
| 1316 void HeapPage<Header>::poisonUnmarkedObjects() | 1163 void HeapPage<Header>::poisonUnmarkedObjects() |
| 1317 { | 1164 { |
| 1318 for (Address headerAddress = payload(); headerAddress < end(); ) { | 1165 for (Address headerAddress = payload(); headerAddress < end(); ) { |
| 1319 Header* header = reinterpret_cast<Header*>(headerAddress); | 1166 Header* header = reinterpret_cast<Header*>(headerAddress); |
| 1320 ASSERT(header->size() < writablePageSize()); | 1167 ASSERT(header->size() < writablePageSize()); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 static void markingTrampoline(VisitorCallback callback, Visitor* visitor, void*
p) | 1247 static void markingTrampoline(VisitorCallback callback, Visitor* visitor, void*
p) |
| 1401 { | 1248 { |
| 1402 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING | 1249 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING |
| 1403 visitor->setHostInfo(p, classOf(p)); | 1250 visitor->setHostInfo(p, classOf(p)); |
| 1404 #endif | 1251 #endif |
| 1405 callback(visitor, p); | 1252 callback(visitor, p); |
| 1406 } | 1253 } |
| 1407 | 1254 |
| 1408 bool Heap::popAndTraceMarkingStack(Visitor* visitor) | 1255 bool Heap::popAndTraceMarkingStack(Visitor* visitor) |
| 1409 { | 1256 { |
| 1410 return s_markingStack->popAndTrace(&s_markingStack, visitor, AllPointersMust
BeVisited, markingTrampoline); | 1257 return s_markingStack->popAndTrace(&s_markingStack, visitor, markingTrampoli
ne); |
| 1411 } | 1258 } |
| 1412 | 1259 |
| 1413 static void weakTrampoline(VisitorCallback callback, Visitor* visitor, void* p) | 1260 static void weakTrampoline(VisitorCallback callback, Visitor* visitor, void* p) |
| 1414 { | 1261 { |
| 1415 callback(visitor, p); | 1262 callback(visitor, p); |
| 1416 } | 1263 } |
| 1417 | 1264 |
| 1418 bool Heap::popAndCallbackWeakPointer(Visitor* visitor) | 1265 bool Heap::popAndCallbackWeakPointer(Visitor* visitor) |
| 1419 { | 1266 { |
| 1420 return s_weakCallbackStack->popAndTrace(&s_weakCallbackStack, visitor, AllPo
intersMustBeMarked, weakTrampoline); | 1267 return s_weakCallbackStack->popAndTrace(&s_weakCallbackStack, visitor, weakT
rampoline); |
| 1421 } | 1268 } |
| 1422 | 1269 |
| 1423 class GCScope { | 1270 class GCScope { |
| 1424 public: | 1271 public: |
| 1425 GCScope(ThreadState::StackState stackState) | 1272 GCScope(ThreadState::StackState stackState) |
| 1426 : m_state(ThreadState::Current()) | 1273 : m_state(ThreadState::Current()) |
| 1427 { | 1274 { |
| 1428 m_state->setGCRequested(false); | 1275 m_state->setGCRequested(false); |
| 1429 m_state->checkThread(); | 1276 m_state->checkThread(); |
| 1430 | 1277 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1532 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING | 1379 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING |
| 1533 marker.reportStats(); | 1380 marker.reportStats(); |
| 1534 #endif | 1381 #endif |
| 1535 | 1382 |
| 1536 { | 1383 { |
| 1537 PERF_STATS(ScopedTimer weakCallbackTimer(collectStats ? PerfStats::get(P
erfStats::WeakCallback) : 0)); | 1384 PERF_STATS(ScopedTimer weakCallbackTimer(collectStats ? PerfStats::get(P
erfStats::WeakCallback) : 0)); |
| 1538 // Call weak callbacks on objects that may now be pointing to dead | 1385 // Call weak callbacks on objects that may now be pointing to dead |
| 1539 // objects. | 1386 // objects. |
| 1540 while (popAndCallbackWeakPointer(&marker)) { } | 1387 while (popAndCallbackWeakPointer(&marker)) { } |
| 1541 } | 1388 } |
| 1542 // It is not permitted to visit pointers of live objects in the weak | 1389 // It is not permitted to trace pointers of live objects in the weak |
| 1543 // callback phase, so the marking stack should still be empty here. | 1390 // callback phase, so the marking stack should still be empty here. |
| 1544 s_markingStack->assertIsEmpty(); | 1391 s_markingStack->assertIsEmpty(); |
| 1545 } | 1392 } |
| 1546 | 1393 |
| 1547 void Heap::pushTraceCallback(void* object, TraceCallback callback) | 1394 void Heap::pushTraceCallback(void* object, TraceCallback callback) |
| 1548 { | 1395 { |
| 1549 ASSERT(Heap::contains(object)); | 1396 ASSERT(Heap::contains(object)); |
| 1550 CallbackStack::Item* slot = s_markingStack->allocateEntry(&s_markingStack); | 1397 CallbackStack::Item* slot = s_markingStack->allocateEntry(&s_markingStack); |
| 1551 *slot = CallbackStack::Item(object, callback); | 1398 *slot = CallbackStack::Item(object, callback); |
| 1552 } | 1399 } |
| 1553 | 1400 |
| 1554 void Heap::pushWeakCallback(void* object, WeakPointerCallback callback) | 1401 void Heap::pushWeakCallback(void* object, WeakPointerCallback callback) |
| 1555 { | 1402 { |
| 1556 CallbackStack::Item* slot = s_weakCallbackStack->allocateEntry(&s_weakCallba
ckStack); | 1403 CallbackStack::Item* slot = s_weakCallbackStack->allocateEntry(&s_weakCallba
ckStack); |
| 1557 *slot = CallbackStack::Item(object, callback); | 1404 *slot = CallbackStack::Item(object, callback); |
| 1558 } | 1405 } |
| 1559 | 1406 |
| 1560 bool CallbackStack::popAndTrace( | 1407 bool CallbackStack::popAndTrace( |
| 1561 CallbackStack** first, | 1408 CallbackStack** first, |
| 1562 Visitor* visitor, | 1409 Visitor* visitor, |
| 1563 TraceRequirement requirement, | |
| 1564 TraceTrampoline trampoline) | 1410 TraceTrampoline trampoline) |
| 1565 { | 1411 { |
| 1566 if (m_current == &(m_buffer[0])) { | 1412 if (m_current == &(m_buffer[0])) { |
| 1567 if (!m_next) { | 1413 if (!m_next) { |
| 1568 #ifndef NDEBUG | 1414 #ifndef NDEBUG |
| 1569 clearUnused(); | 1415 clearUnused(); |
| 1570 #endif | 1416 #endif |
| 1571 return false; | 1417 return false; |
| 1572 } | 1418 } |
| 1573 CallbackStack* nextStack = m_next; | 1419 CallbackStack* nextStack = m_next; |
| 1574 *first = nextStack; | 1420 *first = nextStack; |
| 1575 delete this; | 1421 delete this; |
| 1576 return nextStack->popAndTrace(first, visitor, requirement, trampoline); | 1422 return nextStack->popAndTrace(first, visitor, trampoline); |
| 1577 } | 1423 } |
| 1578 Item* item = --m_current; | 1424 Item* item = --m_current; |
| 1579 TraceChecker checker(item->object(), item->callback(), requirement); | |
| 1580 trampoline(item->callback(), visitor, item->object()); | 1425 trampoline(item->callback(), visitor, item->object()); |
| 1581 | 1426 |
| 1582 return true; | 1427 return true; |
| 1583 } | 1428 } |
| 1584 | 1429 |
| 1585 template<typename Header> | 1430 template<typename Header> |
| 1586 ThreadHeap<Header>::ThreadHeap(ThreadState* state) | 1431 ThreadHeap<Header>::ThreadHeap(ThreadState* state) |
| 1587 : m_inFinalizeAll(false) | 1432 : m_inFinalizeAll(false) |
| 1588 , m_firstPage(0) | 1433 , m_firstPage(0) |
| 1589 , m_firstLargeHeapObject(0) | 1434 , m_firstLargeHeapObject(0) |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1698 doNothingTrace, | 1543 doNothingTrace, |
| 1699 0, | 1544 0, |
| 1700 false | 1545 false |
| 1701 }; | 1546 }; |
| 1702 | 1547 |
| 1703 #ifdef ENABLE_PERF_STATS | 1548 #ifdef ENABLE_PERF_STATS |
| 1704 bool Heap::s_isCollectingStats = false; | 1549 bool Heap::s_isCollectingStats = false; |
| 1705 #endif | 1550 #endif |
| 1706 | 1551 |
| 1707 } // namespace WebCore | 1552 } // namespace WebCore |
| OLD | NEW |