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 20 matching lines...) Expand all Loading... |
31 #include "config.h" | 31 #include "config.h" |
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 #if ENABLE(GC_PROFILE_HEAP) |
| 42 #include "platform/TracedValue.h" |
| 43 #endif |
41 | 44 |
42 #if OS(WIN) | 45 #if OS(WIN) |
43 #include <stddef.h> | 46 #include <stddef.h> |
44 #include <windows.h> | 47 #include <windows.h> |
45 #include <winnt.h> | 48 #include <winnt.h> |
46 #elif defined(__GLIBC__) | 49 #elif defined(__GLIBC__) |
47 extern "C" void* __libc_stack_end; // NOLINT | 50 extern "C" void* __libc_stack_end; // NOLINT |
48 #endif | 51 #endif |
49 | 52 |
50 #if defined(MEMORY_SANITIZER) | 53 #if defined(MEMORY_SANITIZER) |
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 // Whether or not the pointer was within an object it was certainly | 564 // Whether or not the pointer was within an object it was certainly |
562 // within a page that is part of the heap, so we don't want to ask the | 565 // within a page that is part of the heap, so we don't want to ask the |
563 // other other heaps or put this address in the | 566 // other other heaps or put this address in the |
564 // HeapDoesNotContainCache. | 567 // HeapDoesNotContainCache. |
565 return true; | 568 return true; |
566 } | 569 } |
567 | 570 |
568 return false; | 571 return false; |
569 } | 572 } |
570 | 573 |
571 #if ENABLE(GC_TRACING) | 574 #if ENABLE(GC_PROFILE_MARKING) |
572 const GCInfo* ThreadState::findGCInfo(Address address) | 575 const GCInfo* ThreadState::findGCInfo(Address address) |
573 { | 576 { |
574 BaseHeapPage* page = heapPageFromAddress(address); | 577 BaseHeapPage* page = heapPageFromAddress(address); |
575 if (page) { | 578 if (page) { |
576 return page->findGCInfo(address); | 579 return page->findGCInfo(address); |
577 } | 580 } |
578 return 0; | 581 return 0; |
579 } | 582 } |
580 #endif | 583 #endif |
581 | 584 |
| 585 #if ENABLE(GC_PROFILE_HEAP) |
| 586 size_t ThreadState::SnapshotInfo::getClassTag(const GCInfo* gcinfo) |
| 587 { |
| 588 HashMap<const GCInfo*, size_t>::AddResult result = classTags.add(gcinfo, cla
ssTags.size()); |
| 589 if (result.isNewEntry) { |
| 590 liveCount.append(0); |
| 591 deadCount.append(0); |
| 592 generations.append(Vector<int, 8>()); |
| 593 generations.last().fill(0, 8); |
| 594 } |
| 595 return result.storedValue->value; |
| 596 } |
| 597 |
| 598 void ThreadState::snapshot() |
| 599 { |
| 600 SnapshotInfo info(this); |
| 601 RefPtr<TracedValue> json = TracedValue::create(); |
| 602 |
| 603 #define SNAPSHOT_HEAP(HeapType) \ |
| 604 { \ |
| 605 json->beginDictionary(); \ |
| 606 json->setString("name", #HeapType); \ |
| 607 m_heaps[HeapType##Heap]->snapshot(json.get(), &info); \ |
| 608 json->endDictionary(); \ |
| 609 } |
| 610 json->beginArray("heaps"); |
| 611 SNAPSHOT_HEAP(General); |
| 612 FOR_EACH_TYPED_HEAP(SNAPSHOT_HEAP); |
| 613 json->endArray(); |
| 614 #undef SNAPSHOT_HEAP |
| 615 |
| 616 json->setInteger("allocatedSpace", m_stats.totalAllocatedSpace()); |
| 617 json->setInteger("objectSpace", m_stats.totalObjectSpace()); |
| 618 json->setInteger("liveSize", info.liveSize); |
| 619 json->setInteger("deadSize", info.deadSize); |
| 620 json->setInteger("freeSize", info.freeSize); |
| 621 json->setInteger("pageCount", info.freeSize); |
| 622 |
| 623 Vector<String> classNameVector(info.classTags.size()); |
| 624 for (HashMap<const GCInfo*, size_t>::iterator it = info.classTags.begin(); i
t != info.classTags.end(); ++it) |
| 625 classNameVector[it->value] = it->key->m_className; |
| 626 |
| 627 json->beginArray("classes"); |
| 628 for (size_t i = 0; i < classNameVector.size(); ++i) { |
| 629 json->beginDictionary(); |
| 630 json->setString("name", classNameVector[i]); |
| 631 json->setInteger("liveCount", info.liveCount[i]); |
| 632 json->setInteger("deadCount", info.deadCount[i]); |
| 633 json->beginArray("generations"); |
| 634 for (size_t j = 0; j < heapObjectGenerations; ++j) |
| 635 json->pushInteger(info.generations[i][j]); |
| 636 json->endArray(); |
| 637 json->endDictionary(); |
| 638 } |
| 639 json->endArray(); |
| 640 |
| 641 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("blink_gc", "ThreadState", this, json); |
| 642 } |
| 643 #endif |
| 644 |
582 void ThreadState::pushWeakObjectPointerCallback(void* object, WeakPointerCallbac
k callback) | 645 void ThreadState::pushWeakObjectPointerCallback(void* object, WeakPointerCallbac
k callback) |
583 { | 646 { |
584 CallbackStack::Item* slot = m_weakCallbackStack->allocateEntry(&m_weakCallba
ckStack); | 647 CallbackStack::Item* slot = m_weakCallbackStack->allocateEntry(&m_weakCallba
ckStack); |
585 *slot = CallbackStack::Item(object, callback); | 648 *slot = CallbackStack::Item(object, callback); |
586 } | 649 } |
587 | 650 |
588 bool ThreadState::popAndInvokeWeakPointerCallback(Visitor* visitor) | 651 bool ThreadState::popAndInvokeWeakPointerCallback(Visitor* visitor) |
589 { | 652 { |
590 return m_weakCallbackStack->popAndInvokeCallback<WeaknessProcessing>(&m_weak
CallbackStack, visitor); | 653 return m_weakCallbackStack->popAndInvokeCallback<WeaknessProcessing>(&m_weak
CallbackStack, visitor); |
591 } | 654 } |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
879 for (size_t i = 0; i < slotCount; ++i) { | 942 for (size_t i = 0; i < slotCount; ++i) { |
880 m_safePointStackCopy[i] = from[i]; | 943 m_safePointStackCopy[i] = from[i]; |
881 } | 944 } |
882 } | 945 } |
883 | 946 |
884 void ThreadState::performPendingSweep() | 947 void ThreadState::performPendingSweep() |
885 { | 948 { |
886 if (!sweepRequested()) | 949 if (!sweepRequested()) |
887 return; | 950 return; |
888 | 951 |
889 TRACE_EVENT0("blink", "ThreadState::performPendingSweep"); | 952 #if ENABLE(GC_PROFILE_HEAP) |
| 953 // We snapshot the heap prior to sweeping to get numbers for both resources |
| 954 // that have been allocated since the last GC and for resources that are |
| 955 // going to be freed. |
| 956 bool gcTracingEnabled; |
| 957 TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink_gc", &gcTracingEnabled); |
| 958 if (gcTracingEnabled && m_stats.totalObjectSpace() > 0) |
| 959 snapshot(); |
| 960 #endif |
| 961 |
| 962 TRACE_EVENT0("blink_gc", "ThreadState::performPendingSweep"); |
890 | 963 |
891 double timeStamp = WTF::currentTimeMS(); | 964 double timeStamp = WTF::currentTimeMS(); |
892 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); | 965 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); |
893 if (isMainThread()) { | 966 if (isMainThread()) { |
894 ScriptForbiddenScope::enter(); | 967 ScriptForbiddenScope::enter(); |
895 TRACE_EVENT_SET_SAMPLING_STATE("blink", "BlinkGCSweeping"); | 968 TRACE_EVENT_SET_SAMPLING_STATE("blink", "BlinkGCSweeping"); |
896 } | 969 } |
897 | 970 |
898 m_sweepInProgress = true; | 971 m_sweepInProgress = true; |
899 // Disallow allocation during weak processing. | 972 // Disallow allocation during weak processing. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 ASSERT(!state->isAtSafePoint()); | 1027 ASSERT(!state->isAtSafePoint()); |
955 state->safePoint(HeapPointersOnStack); | 1028 state->safePoint(HeapPointersOnStack); |
956 } | 1029 } |
957 | 1030 |
958 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() | 1031 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() |
959 { | 1032 { |
960 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); | 1033 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); |
961 return threads; | 1034 return threads; |
962 } | 1035 } |
963 | 1036 |
964 #if ENABLE(GC_TRACING) | 1037 #if ENABLE(GC_PROFILE_MARKING) |
965 const GCInfo* ThreadState::findGCInfoFromAllThreads(Address address) | 1038 const GCInfo* ThreadState::findGCInfoFromAllThreads(Address address) |
966 { | 1039 { |
967 bool needLockForIteration = !isAnyThreadInGC(); | 1040 bool needLockForIteration = !isAnyThreadInGC(); |
968 if (needLockForIteration) | 1041 if (needLockForIteration) |
969 threadAttachMutex().lock(); | 1042 threadAttachMutex().lock(); |
970 | 1043 |
971 ThreadState::AttachedThreadStateSet& threads = attachedThreads(); | 1044 ThreadState::AttachedThreadStateSet& threads = attachedThreads(); |
972 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { | 1045 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { |
973 if (const GCInfo* gcInfo = (*it)->findGCInfo(address)) { | 1046 if (const GCInfo* gcInfo = (*it)->findGCInfo(address)) { |
974 if (needLockForIteration) | 1047 if (needLockForIteration) |
975 threadAttachMutex().unlock(); | 1048 threadAttachMutex().unlock(); |
976 return gcInfo; | 1049 return gcInfo; |
977 } | 1050 } |
978 } | 1051 } |
979 if (needLockForIteration) | 1052 if (needLockForIteration) |
980 threadAttachMutex().unlock(); | 1053 threadAttachMutex().unlock(); |
981 return 0; | 1054 return 0; |
982 } | 1055 } |
983 #endif | 1056 #endif |
| 1057 |
984 } | 1058 } |
OLD | NEW |