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 21 matching lines...) Expand all Loading... |
32 #include "platform/heap/ThreadState.h" | 32 #include "platform/heap/ThreadState.h" |
33 | 33 |
34 #include "platform/ScriptForbiddenScope.h" | 34 #include "platform/ScriptForbiddenScope.h" |
35 #include "platform/TraceEvent.h" | 35 #include "platform/TraceEvent.h" |
36 #include "platform/heap/AddressSanitizer.h" | 36 #include "platform/heap/AddressSanitizer.h" |
37 #include "platform/heap/Handle.h" | 37 #include "platform/heap/Handle.h" |
38 #include "platform/heap/Heap.h" | 38 #include "platform/heap/Heap.h" |
39 #include "public/platform/Platform.h" | 39 #include "public/platform/Platform.h" |
40 #include "wtf/ThreadingPrimitives.h" | 40 #include "wtf/ThreadingPrimitives.h" |
41 | 41 |
| 42 #if GC_PROFILE_HEAP |
| 43 #include "platform/TracedValue.h" |
| 44 #endif |
| 45 |
42 #if OS(WIN) | 46 #if OS(WIN) |
43 #include <stddef.h> | 47 #include <stddef.h> |
44 #include <windows.h> | 48 #include <windows.h> |
45 #include <winnt.h> | 49 #include <winnt.h> |
46 #elif defined(__GLIBC__) | 50 #elif defined(__GLIBC__) |
47 extern "C" void* __libc_stack_end; // NOLINT | 51 extern "C" void* __libc_stack_end; // NOLINT |
48 #endif | 52 #endif |
49 | 53 |
50 #if defined(MEMORY_SANITIZER) | 54 #if defined(MEMORY_SANITIZER) |
51 #include <sanitizer/msan_interface.h> | 55 #include <sanitizer/msan_interface.h> |
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 // Whether or not the pointer was within an object it was certainly | 528 // Whether or not the pointer was within an object it was certainly |
525 // within a page that is part of the heap, so we don't want to ask the | 529 // within a page that is part of the heap, so we don't want to ask the |
526 // other other heaps or put this address in the | 530 // other other heaps or put this address in the |
527 // HeapDoesNotContainCache. | 531 // HeapDoesNotContainCache. |
528 return true; | 532 return true; |
529 } | 533 } |
530 | 534 |
531 return false; | 535 return false; |
532 } | 536 } |
533 | 537 |
534 #if ENABLE(GC_TRACING) | 538 #if GC_PROFILE_MARKING |
535 const GCInfo* ThreadState::findGCInfo(Address address) | 539 const GCInfo* ThreadState::findGCInfo(Address address) |
536 { | 540 { |
537 BaseHeapPage* page = heapPageFromAddress(address); | 541 BaseHeapPage* page = heapPageFromAddress(address); |
538 if (page) { | 542 if (page) { |
539 return page->findGCInfo(address); | 543 return page->findGCInfo(address); |
540 } | 544 } |
541 return 0; | 545 return 0; |
542 } | 546 } |
543 #endif | 547 #endif |
544 | 548 |
| 549 #if GC_PROFILE_HEAP |
| 550 size_t ThreadState::SnapshotInfo::getClassTag(const GCInfo* gcinfo) |
| 551 { |
| 552 HashMap<const GCInfo*, size_t>::AddResult result = classTags.add(gcinfo, cla
ssTags.size()); |
| 553 if (result.isNewEntry) { |
| 554 liveCount.append(0); |
| 555 deadCount.append(0); |
| 556 generations.append(Vector<int, 8>()); |
| 557 generations.last().fill(0, 8); |
| 558 } |
| 559 return result.storedValue->value; |
| 560 } |
| 561 |
| 562 void ThreadState::snapshot() |
| 563 { |
| 564 SnapshotInfo info(this); |
| 565 TracedValue json; |
| 566 |
| 567 #define SNAPSHOT_HEAP(HeapType) \ |
| 568 { \ |
| 569 TracedDictionary<TracedArray<TracedValue> >& jsonHeap = heaps.beginDicti
onary(); \ |
| 570 jsonHeap.setString("name", #HeapType); \ |
| 571 m_heaps[HeapType##Heap]->snapshot(&jsonHeap, &info); \ |
| 572 jsonHeap.endDictionary(); \ |
| 573 } |
| 574 TracedArray<TracedValue>& heaps = json.beginArray("heaps"); |
| 575 SNAPSHOT_HEAP(General); |
| 576 FOR_EACH_TYPED_HEAP(SNAPSHOT_HEAP); |
| 577 heaps.endArray(); |
| 578 #undef SNAPSHOT_HEAP |
| 579 |
| 580 json.setInteger("allocatedSpace", m_stats.totalAllocatedSpace()) |
| 581 .setInteger("objectSpace", m_stats.totalObjectSpace()) |
| 582 .setInteger("liveSize", info.liveSize) |
| 583 .setInteger("deadSize", info.deadSize) |
| 584 .setInteger("freeSize", info.freeSize) |
| 585 .setInteger("pageCount", info.freeSize); |
| 586 |
| 587 Vector<String> classNameVector(info.classTags.size()); |
| 588 for (HashMap<const GCInfo*, size_t>::iterator it = info.classTags.begin(); i
t != info.classTags.end(); ++it) |
| 589 classNameVector[it->value] = it->key->m_className; |
| 590 |
| 591 TracedArray<TracedValue>& jsonClasses = json.beginArray("classes"); |
| 592 for (size_t i = 0; i < classNameVector.size(); ++i) { |
| 593 TracedDictionary<TracedArray<TracedValue> >& jsonClass = jsonClasses.beg
inDictionary(); |
| 594 jsonClass |
| 595 .setString("name", classNameVector[i]) |
| 596 .setInteger("liveCount", info.liveCount[i]) |
| 597 .setInteger("deadCount", info.deadCount[i]); |
| 598 TracedArray<TracedDictionary<TracedArray<TracedValue> > >& jsonGens = js
onClass.beginArray("generations"); |
| 599 for (size_t j = 0; j < heapObjectGenerations; ++j) |
| 600 jsonGens.pushInteger(info.generations[i][j]); |
| 601 jsonGens.endArray(); |
| 602 jsonClass.endDictionary(); |
| 603 } |
| 604 jsonClasses.endArray(); |
| 605 |
| 606 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(GC_PROFILE_GROUP, "ThreadState", this, j
son.finish()); |
| 607 } |
| 608 #endif |
| 609 |
545 void ThreadState::pushWeakObjectPointerCallback(void* object, WeakPointerCallbac
k callback) | 610 void ThreadState::pushWeakObjectPointerCallback(void* object, WeakPointerCallbac
k callback) |
546 { | 611 { |
547 CallbackStack::Item* slot = m_weakCallbackStack->allocateEntry(&m_weakCallba
ckStack); | 612 CallbackStack::Item* slot = m_weakCallbackStack->allocateEntry(&m_weakCallba
ckStack); |
548 *slot = CallbackStack::Item(object, callback); | 613 *slot = CallbackStack::Item(object, callback); |
549 } | 614 } |
550 | 615 |
551 bool ThreadState::popAndInvokeWeakPointerCallback(Visitor* visitor) | 616 bool ThreadState::popAndInvokeWeakPointerCallback(Visitor* visitor) |
552 { | 617 { |
553 return m_weakCallbackStack->popAndInvokeCallback(&m_weakCallbackStack, visit
or); | 618 return m_weakCallbackStack->popAndInvokeCallback(&m_weakCallbackStack, visit
or); |
554 } | 619 } |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
830 for (size_t i = 0; i < slotCount; ++i) { | 895 for (size_t i = 0; i < slotCount; ++i) { |
831 m_safePointStackCopy[i] = from[i]; | 896 m_safePointStackCopy[i] = from[i]; |
832 } | 897 } |
833 } | 898 } |
834 | 899 |
835 void ThreadState::performPendingSweep() | 900 void ThreadState::performPendingSweep() |
836 { | 901 { |
837 if (!sweepRequested()) | 902 if (!sweepRequested()) |
838 return; | 903 return; |
839 | 904 |
840 TRACE_EVENT0("blink", "ThreadState::performPendingSweep"); | 905 #if GC_PROFILE_HEAP |
| 906 // We snapshot the heap prior to sweeping to get numbers for both resources |
| 907 // that have been allocated since the last GC and for resources that are |
| 908 // going to be freed. |
| 909 bool gcTracingEnabled; |
| 910 TRACE_EVENT_CATEGORY_GROUP_ENABLED(GC_PROFILE_GROUP, &gcTracingEnabled); |
| 911 if (gcTracingEnabled && m_stats.totalObjectSpace() > 0) |
| 912 snapshot(); |
| 913 #endif |
| 914 |
| 915 TRACE_EVENT0(GC_PROFILE_GROUP, "ThreadState::performPendingSweep"); |
841 ScriptForbiddenScope forbiddenScope; | 916 ScriptForbiddenScope forbiddenScope; |
842 | 917 |
843 double timeStamp = WTF::currentTimeMS(); | 918 double timeStamp = WTF::currentTimeMS(); |
844 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); | 919 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); |
845 if (isMainThread()) | 920 if (isMainThread()) |
846 TRACE_EVENT_SET_SAMPLING_STATE("blink", "BlinkGCSweeping"); | 921 TRACE_EVENT_SET_SAMPLING_STATE(GC_PROFILE_GROUP, "BlinkGCSweeping"); |
847 | 922 |
848 m_sweepInProgress = true; | 923 m_sweepInProgress = true; |
849 // Disallow allocation during weak processing. | 924 // Disallow allocation during weak processing. |
850 enterNoAllocationScope(); | 925 enterNoAllocationScope(); |
851 // Perform thread-specific weak processing. | 926 // Perform thread-specific weak processing. |
852 while (popAndInvokeWeakPointerCallback(Heap::s_markingVisitor)) { } | 927 while (popAndInvokeWeakPointerCallback(Heap::s_markingVisitor)) { } |
853 leaveNoAllocationScope(); | 928 leaveNoAllocationScope(); |
854 // Perform sweeping and finalization. | 929 // Perform sweeping and finalization. |
855 m_stats.clear(); // Sweeping will recalculate the stats | 930 m_stats.clear(); // Sweeping will recalculate the stats |
856 for (int i = 0; i < NumberOfHeaps; i++) | 931 for (int i = 0; i < NumberOfHeaps; i++) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 ASSERT(!state->isAtSafePoint()); | 972 ASSERT(!state->isAtSafePoint()); |
898 state->safePoint(HeapPointersOnStack); | 973 state->safePoint(HeapPointersOnStack); |
899 } | 974 } |
900 | 975 |
901 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() | 976 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() |
902 { | 977 { |
903 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); | 978 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); |
904 return threads; | 979 return threads; |
905 } | 980 } |
906 | 981 |
907 #if ENABLE(GC_TRACING) | 982 #if GC_PROFILE_MARKING |
908 const GCInfo* ThreadState::findGCInfoFromAllThreads(Address address) | 983 const GCInfo* ThreadState::findGCInfoFromAllThreads(Address address) |
909 { | 984 { |
910 bool needLockForIteration = !isAnyThreadInGC(); | 985 bool needLockForIteration = !isAnyThreadInGC(); |
911 if (needLockForIteration) | 986 if (needLockForIteration) |
912 threadAttachMutex().lock(); | 987 threadAttachMutex().lock(); |
913 | 988 |
914 ThreadState::AttachedThreadStateSet& threads = attachedThreads(); | 989 ThreadState::AttachedThreadStateSet& threads = attachedThreads(); |
915 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { | 990 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { |
916 if (const GCInfo* gcInfo = (*it)->findGCInfo(address)) { | 991 if (const GCInfo* gcInfo = (*it)->findGCInfo(address)) { |
917 if (needLockForIteration) | 992 if (needLockForIteration) |
918 threadAttachMutex().unlock(); | 993 threadAttachMutex().unlock(); |
919 return gcInfo; | 994 return gcInfo; |
920 } | 995 } |
921 } | 996 } |
922 if (needLockForIteration) | 997 if (needLockForIteration) |
923 threadAttachMutex().unlock(); | 998 threadAttachMutex().unlock(); |
924 return 0; | 999 return 0; |
925 } | 1000 } |
926 #endif | 1001 #endif |
| 1002 |
927 } | 1003 } |
OLD | NEW |