Chromium Code Reviews| 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/Heap.h" | 32 #include "platform/heap/Heap.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/ThreadState.h" | 36 #include "platform/heap/ThreadState.h" |
| 37 #include "public/platform/Platform.h" | 37 #include "public/platform/Platform.h" |
| 38 #include "wtf/AddressSpaceRandomization.h" | 38 #include "wtf/AddressSpaceRandomization.h" |
| 39 #include "wtf/Assertions.h" | 39 #include "wtf/Assertions.h" |
| 40 #include "wtf/LeakAnnotations.h" | 40 #include "wtf/LeakAnnotations.h" |
| 41 #include "wtf/PassOwnPtr.h" | 41 #include "wtf/PassOwnPtr.h" |
| 42 #if ENABLE(GC_TRACING) | 42 #if ENABLE(GC_PROFILE_MARKING) |
| 43 #include "wtf/HashMap.h" | 43 #include "wtf/HashMap.h" |
| 44 #include "wtf/HashSet.h" | 44 #include "wtf/HashSet.h" |
| 45 #include "wtf/text/StringBuilder.h" | 45 #include "wtf/text/StringBuilder.h" |
| 46 #include "wtf/text/StringHash.h" | 46 #include "wtf/text/StringHash.h" |
| 47 #include <stdio.h> | 47 #include <stdio.h> |
| 48 #include <utility> | 48 #include <utility> |
| 49 #endif | 49 #endif |
| 50 #if ENABLE(GC_PROFILE_HEAP) | |
| 51 #include "platform/TracedValue.h" | |
| 52 #endif | |
| 50 | 53 |
| 51 #if OS(POSIX) | 54 #if OS(POSIX) |
| 52 #include <sys/mman.h> | 55 #include <sys/mman.h> |
| 53 #include <unistd.h> | 56 #include <unistd.h> |
| 54 #elif OS(WIN) | 57 #elif OS(WIN) |
| 55 #include <windows.h> | 58 #include <windows.h> |
| 56 #endif | 59 #endif |
| 57 | 60 |
| 58 namespace blink { | 61 namespace blink { |
| 59 | 62 |
| 60 #if ENABLE(GC_TRACING) | 63 #if ENABLE(GC_PROFILE_MARKING) |
| 61 static String classOf(const void* object) | 64 static String classOf(const void* object) |
| 62 { | 65 { |
| 63 const GCInfo* gcInfo = Heap::findGCInfo(reinterpret_cast<Address>(const_cast <void*>(object))); | 66 const GCInfo* gcInfo = Heap::findGCInfo(reinterpret_cast<Address>(const_cast <void*>(object))); |
| 64 if (gcInfo) | 67 if (gcInfo) |
| 65 return gcInfo->m_className; | 68 return gcInfo->m_className; |
| 66 | 69 |
| 67 return "unknown"; | 70 return "unknown"; |
| 68 } | 71 } |
| 69 #endif | 72 #endif |
| 70 | 73 |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 362 MemoryRegion m_writable; | 365 MemoryRegion m_writable; |
| 363 }; | 366 }; |
| 364 | 367 |
| 365 class GCScope { | 368 class GCScope { |
| 366 public: | 369 public: |
| 367 explicit GCScope(ThreadState::StackState stackState) | 370 explicit GCScope(ThreadState::StackState stackState) |
| 368 : m_state(ThreadState::current()) | 371 : m_state(ThreadState::current()) |
| 369 , m_safePointScope(stackState) | 372 , m_safePointScope(stackState) |
| 370 , m_parkedAllThreads(false) | 373 , m_parkedAllThreads(false) |
| 371 { | 374 { |
| 372 TRACE_EVENT0("blink", "Heap::GCScope"); | 375 TRACE_EVENT0("blinkGC", "Heap::GCScope"); |
|
tkent
2014/08/05 00:38:10
should be "blink_gc" for consistency with "blink_r
| |
| 373 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); | 376 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); |
| 374 if (m_state->isMainThread()) | 377 if (m_state->isMainThread()) |
| 375 TRACE_EVENT_SET_SAMPLING_STATE("blink", "BlinkGCWaiting"); | 378 TRACE_EVENT_SET_SAMPLING_STATE("blinkGC", "BlinkGCWaiting"); |
| 376 | 379 |
| 377 m_state->checkThread(); | 380 m_state->checkThread(); |
| 378 | 381 |
| 379 // FIXME: in an unlikely coincidence that two threads decide | 382 // FIXME: in an unlikely coincidence that two threads decide |
| 380 // to collect garbage at the same time, avoid doing two GCs in | 383 // to collect garbage at the same time, avoid doing two GCs in |
| 381 // a row. | 384 // a row. |
| 382 RELEASE_ASSERT(!m_state->isInGC()); | 385 RELEASE_ASSERT(!m_state->isInGC()); |
| 383 RELEASE_ASSERT(!m_state->isSweepInProgress()); | 386 RELEASE_ASSERT(!m_state->isSweepInProgress()); |
| 384 if (LIKELY(ThreadState::stopThreads())) { | 387 if (LIKELY(ThreadState::stopThreads())) { |
| 385 m_parkedAllThreads = true; | 388 m_parkedAllThreads = true; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 { | 508 { |
| 506 heapObjectHeader()->setDeadMark(); | 509 heapObjectHeader()->setDeadMark(); |
| 507 } | 510 } |
| 508 | 511 |
| 509 template<typename Header> | 512 template<typename Header> |
| 510 void LargeHeapObject<Header>::checkAndMarkPointer(Visitor* visitor, Address addr ess) | 513 void LargeHeapObject<Header>::checkAndMarkPointer(Visitor* visitor, Address addr ess) |
| 511 { | 514 { |
| 512 ASSERT(contains(address)); | 515 ASSERT(contains(address)); |
| 513 if (!objectContains(address) || heapObjectHeader()->hasDeadMark()) | 516 if (!objectContains(address) || heapObjectHeader()->hasDeadMark()) |
| 514 return; | 517 return; |
| 515 #if ENABLE(GC_TRACING) | 518 #if ENABLE(GC_PROFILE_MARKING) |
| 516 visitor->setHostInfo(&address, "stack"); | 519 visitor->setHostInfo(&address, "stack"); |
| 517 #endif | 520 #endif |
| 518 mark(visitor); | 521 mark(visitor); |
| 519 } | 522 } |
| 520 | 523 |
| 521 template<> | 524 template<> |
| 522 void LargeHeapObject<FinalizedHeapObjectHeader>::mark(Visitor* visitor) | 525 void LargeHeapObject<FinalizedHeapObjectHeader>::mark(Visitor* visitor) |
| 523 { | 526 { |
| 524 if (heapObjectHeader()->hasVTable() && !vTableInitialized(payload())) | 527 if (heapObjectHeader()->hasVTable() && !vTableInitialized(payload())) |
| 525 visitor->markConservatively(heapObjectHeader()); | 528 visitor->markConservatively(heapObjectHeader()); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 655 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur rent = current->next()) { | 658 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur rent = current->next()) { |
| 656 // Check that large pages are blinkPageSize aligned (modulo the | 659 // Check that large pages are blinkPageSize aligned (modulo the |
| 657 // osPageSize for the guard page). | 660 // osPageSize for the guard page). |
| 658 ASSERT(reinterpret_cast<Address>(current) - osPageSize() == roundToBlink PageStart(reinterpret_cast<Address>(current))); | 661 ASSERT(reinterpret_cast<Address>(current) - osPageSize() == roundToBlink PageStart(reinterpret_cast<Address>(current))); |
| 659 if (current->contains(address)) | 662 if (current->contains(address)) |
| 660 return current; | 663 return current; |
| 661 } | 664 } |
| 662 return 0; | 665 return 0; |
| 663 } | 666 } |
| 664 | 667 |
| 665 #if ENABLE(GC_TRACING) | 668 #if ENABLE(GC_PROFILE_MARKING) |
| 666 template<typename Header> | 669 template<typename Header> |
| 667 const GCInfo* ThreadHeap<Header>::findGCInfoOfLargeHeapObject(Address address) | 670 const GCInfo* ThreadHeap<Header>::findGCInfoOfLargeHeapObject(Address address) |
| 668 { | 671 { |
| 669 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur rent = current->next()) { | 672 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur rent = current->next()) { |
| 670 if (current->contains(address)) | 673 if (current->contains(address)) |
| 671 return current->gcInfo(); | 674 return current->gcInfo(); |
| 672 } | 675 } |
| 673 return 0; | 676 return 0; |
| 674 } | 677 } |
| 675 #endif | 678 #endif |
| 676 | 679 |
| 680 #if ENABLE(GC_PROFILE_HEAP) | |
| 681 #define GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD 0 | |
| 682 template<typename Header> | |
| 683 void ThreadHeap<Header>::snapshot(TracedDictionaryBase* json, ThreadState::Snaps hotInfo* info) | |
| 684 { | |
| 685 size_t previousPageCount = info->pageCount; | |
| 686 | |
| 687 TracedArray<TracedDictionaryBase>& pages = json->beginArray("pages"); | |
| 688 for (HeapPage<Header>* page = m_firstPage; page; page = page->next(), ++info ->pageCount) { | |
| 689 // FIXME: To limit the size of the snapshot we only output "threshold" m any page snapshots. | |
| 690 TracedArray<TracedArray<TracedDictionaryBase> >* jsonPage = 0; | |
| 691 if (info->pageCount < GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD) { | |
| 692 jsonPage = &pages.beginArray(); | |
| 693 jsonPage->pushInteger(reinterpret_cast<intptr_t>(page)); | |
| 694 } | |
| 695 page->snapshot(jsonPage, info); | |
| 696 if (jsonPage) | |
| 697 jsonPage->endArray(); | |
| 698 } | |
| 699 pages.endArray(); | |
| 700 | |
| 701 TracedArray<TracedDictionaryBase>& largeObjects = json->beginArray("largeObj ects"); | |
| 702 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur rent = current->next()) { | |
| 703 TracedDictionary<TracedArray<TracedDictionaryBase> >& jsonCurrent = larg eObjects.beginDictionary(); | |
| 704 current->snapshot(&jsonCurrent, info); | |
| 705 jsonCurrent.endDictionary(); | |
| 706 } | |
| 707 largeObjects.endArray(); | |
| 708 | |
| 709 json->setInteger("pageCount", info->pageCount - previousPageCount); | |
| 710 } | |
| 711 #endif | |
| 712 | |
| 677 template<typename Header> | 713 template<typename Header> |
| 678 void ThreadHeap<Header>::addToFreeList(Address address, size_t size) | 714 void ThreadHeap<Header>::addToFreeList(Address address, size_t size) |
| 679 { | 715 { |
| 680 ASSERT(heapPageFromAddress(address)); | 716 ASSERT(heapPageFromAddress(address)); |
| 681 ASSERT(heapPageFromAddress(address + size - 1)); | 717 ASSERT(heapPageFromAddress(address + size - 1)); |
| 682 ASSERT(size < blinkPagePayloadSize()); | 718 ASSERT(size < blinkPagePayloadSize()); |
| 683 // The free list entries are only pointer aligned (but when we allocate | 719 // The free list entries are only pointer aligned (but when we allocate |
| 684 // from them we are 8 byte aligned due to the header size). | 720 // from them we are 8 byte aligned due to the header size). |
| 685 ASSERT(!((reinterpret_cast<uintptr_t>(address) + sizeof(Header)) & allocatio nMask)); | 721 ASSERT(!((reinterpret_cast<uintptr_t>(address) + sizeof(Header)) & allocatio nMask)); |
| 686 ASSERT(!(size & allocationMask)); | 722 ASSERT(!(size & allocationMask)); |
| (...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1315 } | 1351 } |
| 1316 | 1352 |
| 1317 template<typename Header> | 1353 template<typename Header> |
| 1318 void HeapPage<Header>::checkAndMarkPointer(Visitor* visitor, Address address) | 1354 void HeapPage<Header>::checkAndMarkPointer(Visitor* visitor, Address address) |
| 1319 { | 1355 { |
| 1320 ASSERT(contains(address)); | 1356 ASSERT(contains(address)); |
| 1321 Header* header = findHeaderFromAddress(address); | 1357 Header* header = findHeaderFromAddress(address); |
| 1322 if (!header || header->hasDeadMark()) | 1358 if (!header || header->hasDeadMark()) |
| 1323 return; | 1359 return; |
| 1324 | 1360 |
| 1325 #if ENABLE(GC_TRACING) | 1361 #if ENABLE(GC_PROFILE_MARKING) |
| 1326 visitor->setHostInfo(&address, "stack"); | 1362 visitor->setHostInfo(&address, "stack"); |
| 1327 #endif | 1363 #endif |
| 1328 if (hasVTable(header) && !vTableInitialized(header->payload())) | 1364 if (hasVTable(header) && !vTableInitialized(header->payload())) |
| 1329 visitor->markConservatively(header); | 1365 visitor->markConservatively(header); |
| 1330 else | 1366 else |
| 1331 visitor->mark(header, traceCallback(header)); | 1367 visitor->mark(header, traceCallback(header)); |
| 1332 } | 1368 } |
| 1333 | 1369 |
| 1334 #if ENABLE(GC_TRACING) | 1370 #if ENABLE(GC_PROFILE_MARKING) |
| 1335 template<typename Header> | 1371 template<typename Header> |
| 1336 const GCInfo* HeapPage<Header>::findGCInfo(Address address) | 1372 const GCInfo* HeapPage<Header>::findGCInfo(Address address) |
| 1337 { | 1373 { |
| 1338 if (address < payload()) | 1374 if (address < payload()) |
| 1339 return 0; | 1375 return 0; |
| 1340 | 1376 |
| 1341 if (gcInfo()) // for non FinalizedObjectHeader | 1377 if (gcInfo()) // for non FinalizedObjectHeader |
| 1342 return gcInfo(); | 1378 return gcInfo(); |
| 1343 | 1379 |
| 1344 Header* header = findHeaderFromAddress(address); | 1380 Header* header = findHeaderFromAddress(address); |
| 1345 if (!header) | 1381 if (!header) |
| 1346 return 0; | 1382 return 0; |
| 1347 | 1383 |
| 1348 return header->gcInfo(); | 1384 return header->gcInfo(); |
| 1349 } | 1385 } |
| 1350 #endif | 1386 #endif |
| 1351 | 1387 |
| 1388 #if ENABLE(GC_PROFILE_HEAP) | |
| 1389 template<typename Header> | |
| 1390 void HeapPage<Header>::snapshot(TracedArrayBase* json, ThreadState::SnapshotInfo * info) | |
| 1391 { | |
| 1392 Header* header = 0; | |
| 1393 for (Address addr = payload(); addr < end(); addr += header->size()) { | |
| 1394 header = reinterpret_cast<Header*>(addr); | |
| 1395 if (json) | |
| 1396 json->pushInteger(header->encodedSize()); | |
| 1397 if (header->isFree()) { | |
| 1398 info->freeSize += header->size(); | |
| 1399 continue; | |
| 1400 } | |
| 1401 | |
| 1402 size_t tag = info->getClassTag(header->gcInfo()); | |
| 1403 size_t age = header->age(); | |
| 1404 if (json) | |
| 1405 json->pushInteger(tag); | |
| 1406 if (header->isMarked()) { | |
| 1407 info->liveCount[tag] += 1; | |
| 1408 info->liveSize += header->size(); | |
| 1409 // Count objects that are live when promoted to the final generation . | |
| 1410 if (age == maxHeapObjectAge - 1) | |
| 1411 info->generations[tag][maxHeapObjectAge] += 1; | |
| 1412 header->incAge(); | |
| 1413 } else { | |
| 1414 info->deadCount[tag] += 1; | |
| 1415 info->deadSize += header->size(); | |
| 1416 // Count objects that are dead before the final generation. | |
| 1417 if (age < maxHeapObjectAge) | |
| 1418 info->generations[tag][age] += 1; | |
| 1419 } | |
| 1420 } | |
| 1421 } | |
| 1422 #endif | |
| 1423 | |
| 1352 #if defined(ADDRESS_SANITIZER) | 1424 #if defined(ADDRESS_SANITIZER) |
| 1353 template<typename Header> | 1425 template<typename Header> |
| 1354 void HeapPage<Header>::poisonUnmarkedObjects() | 1426 void HeapPage<Header>::poisonUnmarkedObjects() |
| 1355 { | 1427 { |
| 1356 for (Address headerAddress = payload(); headerAddress < end(); ) { | 1428 for (Address headerAddress = payload(); headerAddress < end(); ) { |
| 1357 Header* header = reinterpret_cast<Header*>(headerAddress); | 1429 Header* header = reinterpret_cast<Header*>(headerAddress); |
| 1358 ASSERT(header->size() < blinkPagePayloadSize()); | 1430 ASSERT(header->size() < blinkPagePayloadSize()); |
| 1359 | 1431 |
| 1360 if (!header->isFree() && !header->isMarked()) | 1432 if (!header->isFree() && !header->isMarked()) |
| 1361 ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); | 1433 ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1403 return header->hasVTable(); | 1475 return header->hasVTable(); |
| 1404 } | 1476 } |
| 1405 | 1477 |
| 1406 template<typename Header> | 1478 template<typename Header> |
| 1407 void LargeHeapObject<Header>::getStats(HeapStats& stats) | 1479 void LargeHeapObject<Header>::getStats(HeapStats& stats) |
| 1408 { | 1480 { |
| 1409 stats.increaseAllocatedSpace(size()); | 1481 stats.increaseAllocatedSpace(size()); |
| 1410 stats.increaseObjectSpace(payloadSize()); | 1482 stats.increaseObjectSpace(payloadSize()); |
| 1411 } | 1483 } |
| 1412 | 1484 |
| 1485 #if ENABLE(GC_PROFILE_HEAP) | |
| 1486 template<typename Header> | |
| 1487 void LargeHeapObject<Header>::snapshot(TracedDictionaryBase* json, ThreadState:: SnapshotInfo* info) | |
| 1488 { | |
| 1489 Header* header = heapObjectHeader(); | |
| 1490 size_t tag = info->getClassTag(header->gcInfo()); | |
| 1491 size_t age = header->age(); | |
| 1492 if (isMarked()) { | |
| 1493 info->liveCount[tag] += 1; | |
| 1494 info->liveSize += header->size(); | |
| 1495 // Count objects that are live when promoted to the final generation. | |
| 1496 if (age == maxHeapObjectAge - 1) | |
| 1497 info->generations[tag][maxHeapObjectAge] += 1; | |
| 1498 header->incAge(); | |
| 1499 } else { | |
| 1500 info->deadCount[tag] += 1; | |
| 1501 info->deadSize += header->size(); | |
| 1502 // Count objects that are dead before the final generation. | |
| 1503 if (age < maxHeapObjectAge) | |
| 1504 info->generations[tag][age] += 1; | |
| 1505 } | |
| 1506 | |
| 1507 if (json) { | |
| 1508 json->setInteger("class", tag) | |
| 1509 .setInteger("size", header->size()) | |
| 1510 .setInteger("isMarked", isMarked()); | |
| 1511 } | |
| 1512 } | |
| 1513 #endif | |
| 1514 | |
| 1413 template<typename Entry> | 1515 template<typename Entry> |
| 1414 void HeapExtentCache<Entry>::flush() | 1516 void HeapExtentCache<Entry>::flush() |
| 1415 { | 1517 { |
| 1416 if (m_hasEntries) { | 1518 if (m_hasEntries) { |
| 1417 for (int i = 0; i < numberOfEntries; i++) | 1519 for (int i = 0; i < numberOfEntries; i++) |
| 1418 m_entries[i] = Entry(); | 1520 m_entries[i] = Entry(); |
| 1419 m_hasEntries = false; | 1521 m_hasEntries = false; |
| 1420 } | 1522 } |
| 1421 } | 1523 } |
| 1422 | 1524 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1541 return true; | 1643 return true; |
| 1542 } | 1644 } |
| 1543 if (Mode == ThreadLocalMarking && (heapPage->orphaned() || !heapPage->termin ating())) | 1645 if (Mode == ThreadLocalMarking && (heapPage->orphaned() || !heapPage->termin ating())) |
| 1544 return true; | 1646 return true; |
| 1545 // For WeaknessProcessing we should never reach orphaned pages since | 1647 // For WeaknessProcessing we should never reach orphaned pages since |
| 1546 // they should never be registered as objects on orphaned pages are not | 1648 // they should never be registered as objects on orphaned pages are not |
| 1547 // traced. We cannot assert this here since we might have an off-heap | 1649 // traced. We cannot assert this here since we might have an off-heap |
| 1548 // collection. However we assert it in Heap::pushWeakObjectPointerCallback. | 1650 // collection. However we assert it in Heap::pushWeakObjectPointerCallback. |
| 1549 | 1651 |
| 1550 VisitorCallback callback = item->callback(); | 1652 VisitorCallback callback = item->callback(); |
| 1551 #if ENABLE(GC_TRACING) | 1653 #if ENABLE(GC_PROFILE_MARKING) |
| 1552 if (ThreadState::isAnyThreadInGC()) // weak-processing will also use popAndI nvokeCallback | 1654 if (ThreadState::isAnyThreadInGC()) // weak-processing will also use popAndI nvokeCallback |
| 1553 visitor->setHostInfo(item->object(), classOf(item->object())); | 1655 visitor->setHostInfo(item->object(), classOf(item->object())); |
| 1554 #endif | 1656 #endif |
| 1555 callback(visitor, item->object()); | 1657 callback(visitor, item->object()); |
| 1556 | 1658 |
| 1557 return true; | 1659 return true; |
| 1558 } | 1660 } |
| 1559 | 1661 |
| 1560 void CallbackStack::invokeCallbacks(CallbackStack** first, Visitor* visitor) | 1662 void CallbackStack::invokeCallbacks(CallbackStack** first, Visitor* visitor) |
| 1561 { | 1663 { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1616 } | 1718 } |
| 1617 if (m_next) | 1719 if (m_next) |
| 1618 return m_next->hasCallbackForObject(object); | 1720 return m_next->hasCallbackForObject(object); |
| 1619 | 1721 |
| 1620 return false; | 1722 return false; |
| 1621 } | 1723 } |
| 1622 #endif | 1724 #endif |
| 1623 | 1725 |
| 1624 class MarkingVisitor : public Visitor { | 1726 class MarkingVisitor : public Visitor { |
| 1625 public: | 1727 public: |
| 1626 #if ENABLE(GC_TRACING) | 1728 #if ENABLE(GC_PROFILE_MARKING) |
| 1627 typedef HashSet<uintptr_t> LiveObjectSet; | 1729 typedef HashSet<uintptr_t> LiveObjectSet; |
| 1628 typedef HashMap<String, LiveObjectSet> LiveObjectMap; | 1730 typedef HashMap<String, LiveObjectSet> LiveObjectMap; |
| 1629 typedef HashMap<uintptr_t, std::pair<uintptr_t, String> > ObjectGraph; | 1731 typedef HashMap<uintptr_t, std::pair<uintptr_t, String> > ObjectGraph; |
| 1630 #endif | 1732 #endif |
| 1631 | 1733 |
| 1632 inline void visitHeader(HeapObjectHeader* header, const void* objectPointer, TraceCallback callback) | 1734 inline void visitHeader(HeapObjectHeader* header, const void* objectPointer, TraceCallback callback) |
| 1633 { | 1735 { |
| 1634 ASSERT(header); | 1736 ASSERT(header); |
| 1635 // Check that we are not marking objects that are outside the heap by ca lling Heap::contains. | 1737 // Check that we are not marking objects that are outside the heap by ca lling Heap::contains. |
| 1636 // However we cannot call Heap::contains when outside a GC and we call m ark when doing weakness | 1738 // However we cannot call Heap::contains when outside a GC and we call m ark when doing weakness |
| 1637 // for ephemerons. Hence we only check when called within. | 1739 // for ephemerons. Hence we only check when called within. |
| 1638 ASSERT(!ThreadState::isAnyThreadInGC() || Heap::containedInHeapOrOrphane dPage(header)); | 1740 ASSERT(!ThreadState::isAnyThreadInGC() || Heap::containedInHeapOrOrphane dPage(header)); |
| 1639 ASSERT(objectPointer); | 1741 ASSERT(objectPointer); |
| 1640 if (header->isMarked()) | 1742 if (header->isMarked()) |
| 1641 return; | 1743 return; |
| 1642 header->mark(); | 1744 header->mark(); |
| 1643 #if ENABLE(GC_TRACING) | 1745 #if ENABLE(GC_PROFILE_MARKING) |
| 1644 MutexLocker locker(objectGraphMutex()); | 1746 MutexLocker locker(objectGraphMutex()); |
| 1645 String className(classOf(objectPointer)); | 1747 String className(classOf(objectPointer)); |
| 1646 { | 1748 { |
| 1647 LiveObjectMap::AddResult result = currentlyLive().add(className, Liv eObjectSet()); | 1749 LiveObjectMap::AddResult result = currentlyLive().add(className, Liv eObjectSet()); |
| 1648 result.storedValue->value.add(reinterpret_cast<uintptr_t>(objectPoin ter)); | 1750 result.storedValue->value.add(reinterpret_cast<uintptr_t>(objectPoin ter)); |
| 1649 } | 1751 } |
| 1650 ObjectGraph::AddResult result = objectGraph().add(reinterpret_cast<uintp tr_t>(objectPointer), std::make_pair(reinterpret_cast<uintptr_t>(m_hostObject), m_hostName)); | 1752 ObjectGraph::AddResult result = objectGraph().add(reinterpret_cast<uintp tr_t>(objectPointer), std::make_pair(reinterpret_cast<uintptr_t>(m_hostObject), m_hostName)); |
| 1651 ASSERT(result.isNewEntry); | 1753 ASSERT(result.isNewEntry); |
| 1652 // fprintf(stderr, "%s[%p] -> %s[%p]\n", m_hostName.ascii().data(), m_ho stObject, className.ascii().data(), objectPointer); | 1754 // fprintf(stderr, "%s[%p] -> %s[%p]\n", m_hostName.ascii().data(), m_ho stObject, className.ascii().data(), objectPointer); |
| 1653 #endif | 1755 #endif |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1739 visitHeader(header, header->payload(), callback); \ | 1841 visitHeader(header, header->payload(), callback); \ |
| 1740 } \ | 1842 } \ |
| 1741 virtual bool isMarked(const Type* objectPointer) OVERRIDE \ | 1843 virtual bool isMarked(const Type* objectPointer) OVERRIDE \ |
| 1742 { \ | 1844 { \ |
| 1743 return HeapObjectHeader::fromPayload(objectPointer)->isMarked(); \ | 1845 return HeapObjectHeader::fromPayload(objectPointer)->isMarked(); \ |
| 1744 } | 1846 } |
| 1745 | 1847 |
| 1746 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS) | 1848 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS) |
| 1747 #undef DEFINE_VISITOR_METHODS | 1849 #undef DEFINE_VISITOR_METHODS |
| 1748 | 1850 |
| 1749 #if ENABLE(GC_TRACING) | 1851 #if ENABLE(GC_PROFILE_MARKING) |
| 1750 void reportStats() | 1852 void reportStats() |
| 1751 { | 1853 { |
| 1752 fprintf(stderr, "\n---------- AFTER MARKING -------------------\n"); | 1854 fprintf(stderr, "\n---------- AFTER MARKING -------------------\n"); |
| 1753 for (LiveObjectMap::iterator it = currentlyLive().begin(), end = current lyLive().end(); it != end; ++it) { | 1855 for (LiveObjectMap::iterator it = currentlyLive().begin(), end = current lyLive().end(); it != end; ++it) { |
| 1754 fprintf(stderr, "%s %u", it->key.ascii().data(), it->value.size()); | 1856 fprintf(stderr, "%s %u", it->key.ascii().data(), it->value.size()); |
| 1755 | 1857 |
| 1756 if (it->key == "blink::Document") | 1858 if (it->key == "blink::Document") |
| 1757 reportStillAlive(it->value, previouslyLive().get(it->key)); | 1859 reportStillAlive(it->value, previouslyLive().get(it->key)); |
| 1758 | 1860 |
| 1759 fprintf(stderr, "\n"); | 1861 fprintf(stderr, "\n"); |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1930 | 2032 |
| 1931 #if !ENABLE(ASSERT) | 2033 #if !ENABLE(ASSERT) |
| 1932 s_heapDoesNotContainCache->addEntry(address, true); | 2034 s_heapDoesNotContainCache->addEntry(address, true); |
| 1933 #else | 2035 #else |
| 1934 if (!s_heapDoesNotContainCache->lookup(address)) | 2036 if (!s_heapDoesNotContainCache->lookup(address)) |
| 1935 s_heapDoesNotContainCache->addEntry(address, true); | 2037 s_heapDoesNotContainCache->addEntry(address, true); |
| 1936 #endif | 2038 #endif |
| 1937 return 0; | 2039 return 0; |
| 1938 } | 2040 } |
| 1939 | 2041 |
| 1940 #if ENABLE(GC_TRACING) | 2042 #if ENABLE(GC_PROFILE_MARKING) |
| 1941 const GCInfo* Heap::findGCInfo(Address address) | 2043 const GCInfo* Heap::findGCInfo(Address address) |
| 1942 { | 2044 { |
| 1943 return ThreadState::findGCInfoFromAllThreads(address); | 2045 return ThreadState::findGCInfoFromAllThreads(address); |
| 1944 } | 2046 } |
| 2047 #endif | |
| 1945 | 2048 |
| 2049 #if ENABLE(GC_PROFILE_MARKING) | |
| 1946 void Heap::dumpPathToObjectOnNextGC(void* p) | 2050 void Heap::dumpPathToObjectOnNextGC(void* p) |
| 1947 { | 2051 { |
| 1948 static_cast<MarkingVisitor*>(s_markingVisitor)->dumpPathToObjectOnNextGC(p); | 2052 static_cast<MarkingVisitor*>(s_markingVisitor)->dumpPathToObjectOnNextGC(p); |
| 1949 } | 2053 } |
| 1950 | 2054 |
| 1951 String Heap::createBacktraceString() | 2055 String Heap::createBacktraceString() |
| 1952 { | 2056 { |
| 1953 int framesToShow = 3; | 2057 int framesToShow = 3; |
| 1954 int stackFrameSize = 16; | 2058 int stackFrameSize = 16; |
| 1955 ASSERT(stackFrameSize >= framesToShow); | 2059 ASSERT(stackFrameSize >= framesToShow); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2058 GCScope gcScope(stackState); | 2162 GCScope gcScope(stackState); |
| 2059 // Check if we successfully parked the other threads. If not we bail out of the GC. | 2163 // Check if we successfully parked the other threads. If not we bail out of the GC. |
| 2060 if (!gcScope.allThreadsParked()) { | 2164 if (!gcScope.allThreadsParked()) { |
| 2061 ThreadState::current()->setGCRequested(); | 2165 ThreadState::current()->setGCRequested(); |
| 2062 return; | 2166 return; |
| 2063 } | 2167 } |
| 2064 | 2168 |
| 2065 ScriptForbiddenScope forbiddenScope; | 2169 ScriptForbiddenScope forbiddenScope; |
| 2066 s_lastGCWasConservative = false; | 2170 s_lastGCWasConservative = false; |
| 2067 | 2171 |
| 2068 TRACE_EVENT0("blink", "Heap::collectGarbage"); | 2172 TRACE_EVENT0("blinkGC", "Heap::collectGarbage"); |
| 2069 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "BlinkGC"); | 2173 TRACE_EVENT_SCOPED_SAMPLING_STATE("blinkGC", "BlinkGC"); |
| 2070 double timeStamp = WTF::currentTimeMS(); | 2174 double timeStamp = WTF::currentTimeMS(); |
| 2071 #if ENABLE(GC_TRACING) | 2175 #if ENABLE(GC_PROFILE_MARKING) |
| 2072 static_cast<MarkingVisitor*>(s_markingVisitor)->objectGraph().clear(); | 2176 static_cast<MarkingVisitor*>(s_markingVisitor)->objectGraph().clear(); |
| 2073 #endif | 2177 #endif |
| 2074 | 2178 |
| 2075 // Disallow allocation during garbage collection (but not | 2179 // Disallow allocation during garbage collection (but not |
| 2076 // during the finalization that happens when the gcScope is | 2180 // during the finalization that happens when the gcScope is |
| 2077 // torn down). | 2181 // torn down). |
| 2078 NoAllocationScope<AnyThread> noAllocationScope; | 2182 NoAllocationScope<AnyThread> noAllocationScope; |
| 2079 | 2183 |
| 2080 prepareForGC(); | 2184 prepareForGC(); |
| 2081 | 2185 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 2099 | 2203 |
| 2100 // After a global marking we know that any orphaned page that was not reache d | 2204 // After a global marking we know that any orphaned page that was not reache d |
| 2101 // cannot be reached in a subsequent GC. This is due to a thread either havi ng | 2205 // cannot be reached in a subsequent GC. This is due to a thread either havi ng |
| 2102 // swept its heap or having done a "poor mans sweep" in prepareForGC which m arks | 2206 // swept its heap or having done a "poor mans sweep" in prepareForGC which m arks |
| 2103 // objects that are dead, but not swept in the previous GC as dead. In this GC's | 2207 // objects that are dead, but not swept in the previous GC as dead. In this GC's |
| 2104 // marking we check that any object marked as dead is not traced. E.g. via a | 2208 // marking we check that any object marked as dead is not traced. E.g. via a |
| 2105 // conservatively found pointer or a programming error with an object contai ning | 2209 // conservatively found pointer or a programming error with an object contai ning |
| 2106 // a dangling pointer. | 2210 // a dangling pointer. |
| 2107 orphanedPagePool()->decommitOrphanedPages(); | 2211 orphanedPagePool()->decommitOrphanedPages(); |
| 2108 | 2212 |
| 2109 #if ENABLE(GC_TRACING) | 2213 #if ENABLE(GC_PROFILE_MARKING) |
| 2110 static_cast<MarkingVisitor*>(s_markingVisitor)->reportStats(); | 2214 static_cast<MarkingVisitor*>(s_markingVisitor)->reportStats(); |
| 2111 #endif | 2215 #endif |
| 2112 | 2216 |
| 2113 if (blink::Platform::current()) { | 2217 if (blink::Platform::current()) { |
| 2114 uint64_t objectSpaceSize; | 2218 uint64_t objectSpaceSize; |
| 2115 uint64_t allocatedSpaceSize; | 2219 uint64_t allocatedSpaceSize; |
| 2116 getHeapSpaceSize(&objectSpaceSize, &allocatedSpaceSize); | 2220 getHeapSpaceSize(&objectSpaceSize, &allocatedSpaceSize); |
| 2117 blink::Platform::current()->histogramCustomCounts("BlinkGC.CollectGarbag e", WTF::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); | 2221 blink::Platform::current()->histogramCustomCounts("BlinkGC.CollectGarbag e", WTF::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); |
| 2118 blink::Platform::current()->histogramCustomCounts("BlinkGC.TotalObjectSp ace", objectSpaceSize / 1024, 0, 4 * 1024 * 1024, 50); | 2222 blink::Platform::current()->histogramCustomCounts("BlinkGC.TotalObjectSp ace", objectSpaceSize / 1024, 0, 4 * 1024 * 1024, 50); |
| 2119 blink::Platform::current()->histogramCustomCounts("BlinkGC.TotalAllocate dSpace", allocatedSpaceSize / 1024, 0, 4 * 1024 * 1024, 50); | 2223 blink::Platform::current()->histogramCustomCounts("BlinkGC.TotalAllocate dSpace", allocatedSpaceSize / 1024, 0, 4 * 1024 * 1024, 50); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2273 Visitor* Heap::s_markingVisitor; | 2377 Visitor* Heap::s_markingVisitor; |
| 2274 CallbackStack* Heap::s_markingStack; | 2378 CallbackStack* Heap::s_markingStack; |
| 2275 CallbackStack* Heap::s_weakCallbackStack; | 2379 CallbackStack* Heap::s_weakCallbackStack; |
| 2276 CallbackStack* Heap::s_ephemeronStack; | 2380 CallbackStack* Heap::s_ephemeronStack; |
| 2277 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; | 2381 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; |
| 2278 bool Heap::s_shutdownCalled = false; | 2382 bool Heap::s_shutdownCalled = false; |
| 2279 bool Heap::s_lastGCWasConservative = false; | 2383 bool Heap::s_lastGCWasConservative = false; |
| 2280 FreePagePool* Heap::s_freePagePool; | 2384 FreePagePool* Heap::s_freePagePool; |
| 2281 OrphanedPagePool* Heap::s_orphanedPagePool; | 2385 OrphanedPagePool* Heap::s_orphanedPagePool; |
| 2282 } | 2386 } |
| OLD | NEW |