| 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 |