OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/heap/heap.h" | 5 #include "src/heap/heap.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 1726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1737 } | 1737 } |
1738 | 1738 |
1739 | 1739 |
1740 void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) { | 1740 void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) { |
1741 Object* head = VisitWeakList<Context>(this, native_contexts_list(), retainer); | 1741 Object* head = VisitWeakList<Context>(this, native_contexts_list(), retainer); |
1742 // Update the head of the list of contexts. | 1742 // Update the head of the list of contexts. |
1743 set_native_contexts_list(head); | 1743 set_native_contexts_list(head); |
1744 } | 1744 } |
1745 | 1745 |
1746 | 1746 |
1747 void Heap::RegisterNewArrayBufferHelper(std::map<void*, size_t>& live_buffers, | |
1748 void* data, size_t length) { | |
1749 live_buffers[data] = length; | |
1750 } | |
1751 | |
1752 | |
1753 void Heap::UnregisterArrayBufferHelper( | |
1754 std::map<void*, size_t>& live_buffers, | |
1755 std::map<void*, size_t>& not_yet_discovered_buffers, void* data) { | |
1756 DCHECK(live_buffers.count(data) > 0); | |
1757 live_buffers.erase(data); | |
1758 not_yet_discovered_buffers.erase(data); | |
1759 } | |
1760 | |
1761 | |
1762 void Heap::RegisterLiveArrayBufferHelper( | |
1763 std::map<void*, size_t>& not_yet_discovered_buffers, void* data) { | |
1764 not_yet_discovered_buffers.erase(data); | |
1765 } | |
1766 | |
1767 | |
1768 size_t Heap::FreeDeadArrayBuffersHelper( | |
1769 Isolate* isolate, std::map<void*, size_t>& live_buffers, | |
1770 std::map<void*, size_t>& not_yet_discovered_buffers) { | |
1771 size_t freed_memory = 0; | |
1772 for (auto buffer = not_yet_discovered_buffers.begin(); | |
1773 buffer != not_yet_discovered_buffers.end(); ++buffer) { | |
1774 isolate->array_buffer_allocator()->Free(buffer->first, buffer->second); | |
1775 freed_memory += buffer->second; | |
1776 live_buffers.erase(buffer->first); | |
1777 } | |
1778 not_yet_discovered_buffers = live_buffers; | |
1779 return freed_memory; | |
1780 } | |
1781 | |
1782 | |
1783 void Heap::TearDownArrayBuffersHelper( | |
1784 Isolate* isolate, std::map<void*, size_t>& live_buffers, | |
1785 std::map<void*, size_t>& not_yet_discovered_buffers) { | |
1786 for (auto buffer = live_buffers.begin(); buffer != live_buffers.end(); | |
1787 ++buffer) { | |
1788 isolate->array_buffer_allocator()->Free(buffer->first, buffer->second); | |
1789 } | |
1790 live_buffers.clear(); | |
1791 not_yet_discovered_buffers.clear(); | |
1792 } | |
1793 | |
1794 | |
1795 void Heap::RegisterNewArrayBuffer(bool in_new_space, void* data, | 1747 void Heap::RegisterNewArrayBuffer(bool in_new_space, void* data, |
1796 size_t length) { | 1748 size_t length) { |
1797 if (!data) return; | 1749 if (!data) return; |
1798 RegisterNewArrayBufferHelper(live_array_buffers_, data, length); | |
1799 if (in_new_space) { | 1750 if (in_new_space) { |
1800 RegisterNewArrayBufferHelper(live_array_buffers_for_scavenge_, data, | 1751 live_array_buffers_for_scavenge_[data] = length; |
1801 length); | 1752 } else { |
| 1753 live_array_buffers_[data] = length; |
1802 } | 1754 } |
1803 | 1755 |
1804 // We may go over the limit of externally allocated memory here. We call the | 1756 // We may go over the limit of externally allocated memory here. We call the |
1805 // api function to trigger a GC in this case. | 1757 // api function to trigger a GC in this case. |
1806 reinterpret_cast<v8::Isolate*>(isolate_) | 1758 reinterpret_cast<v8::Isolate*>(isolate_) |
1807 ->AdjustAmountOfExternalAllocatedMemory(length); | 1759 ->AdjustAmountOfExternalAllocatedMemory(length); |
1808 } | 1760 } |
1809 | 1761 |
1810 | 1762 |
1811 void Heap::UnregisterArrayBuffer(bool in_new_space, void* data) { | 1763 void Heap::UnregisterArrayBuffer(bool in_new_space, void* data) { |
1812 if (!data) return; | 1764 if (!data) return; |
1813 UnregisterArrayBufferHelper(live_array_buffers_, | 1765 |
1814 not_yet_discovered_array_buffers_, data); | 1766 std::map<void*, size_t>* live_buffers = |
| 1767 in_new_space ? &live_array_buffers_for_scavenge_ : &live_array_buffers_; |
| 1768 std::map<void*, size_t>* not_yet_discovered_buffers = |
| 1769 in_new_space ? ¬_yet_discovered_array_buffers_for_scavenge_ |
| 1770 : ¬_yet_discovered_array_buffers_; |
| 1771 |
| 1772 DCHECK(live_buffers->count(data) > 0); |
| 1773 |
| 1774 size_t length = (*live_buffers)[data]; |
| 1775 live_buffers->erase(data); |
| 1776 not_yet_discovered_buffers->erase(data); |
| 1777 |
| 1778 amount_of_external_allocated_memory_ -= length; |
| 1779 } |
| 1780 |
| 1781 |
| 1782 void Heap::RegisterLiveArrayBuffer(bool in_new_space, void* data) { |
| 1783 // ArrayBuffer might be in the middle of being constructed. |
| 1784 if (data == undefined_value()) return; |
1815 if (in_new_space) { | 1785 if (in_new_space) { |
1816 UnregisterArrayBufferHelper(live_array_buffers_for_scavenge_, | 1786 not_yet_discovered_array_buffers_for_scavenge_.erase(data); |
1817 not_yet_discovered_array_buffers_for_scavenge_, | 1787 } else { |
1818 data); | 1788 not_yet_discovered_array_buffers_.erase(data); |
1819 } | 1789 } |
1820 } | 1790 } |
1821 | 1791 |
1822 | 1792 |
1823 void Heap::RegisterLiveArrayBuffer(bool from_scavenge, void* data) { | 1793 void Heap::FreeDeadArrayBuffers(bool from_scavenge) { |
1824 // ArrayBuffer might be in the middle of being constructed. | 1794 size_t freed_memory = 0; |
1825 if (data == undefined_value()) return; | 1795 for (auto& buffer : not_yet_discovered_array_buffers_for_scavenge_) { |
1826 RegisterLiveArrayBufferHelper( | 1796 isolate()->array_buffer_allocator()->Free(buffer.first, buffer.second); |
1827 from_scavenge ? not_yet_discovered_array_buffers_for_scavenge_ | 1797 freed_memory += buffer.second; |
1828 : not_yet_discovered_array_buffers_, | 1798 live_array_buffers_for_scavenge_.erase(buffer.first); |
1829 data); | 1799 } |
1830 } | |
1831 | 1800 |
1832 | 1801 if (!from_scavenge) { |
1833 void Heap::FreeDeadArrayBuffers(bool from_scavenge) { | 1802 for (auto& buffer : not_yet_discovered_array_buffers_) { |
1834 if (from_scavenge) { | 1803 isolate()->array_buffer_allocator()->Free(buffer.first, buffer.second); |
1835 for (auto& buffer : not_yet_discovered_array_buffers_for_scavenge_) { | 1804 freed_memory += buffer.second; |
1836 not_yet_discovered_array_buffers_.erase(buffer.first); | |
1837 live_array_buffers_.erase(buffer.first); | 1805 live_array_buffers_.erase(buffer.first); |
1838 } | 1806 } |
1839 } else { | |
1840 for (auto& buffer : not_yet_discovered_array_buffers_) { | |
1841 // Scavenge can't happend during evacuation, so we only need to update | |
1842 // live_array_buffers_for_scavenge_. | |
1843 // not_yet_discovered_array_buffers_for_scanvenge_ will be reset before | |
1844 // the next scavenge run in PrepareArrayBufferDiscoveryInNewSpace. | |
1845 live_array_buffers_for_scavenge_.erase(buffer.first); | |
1846 } | |
1847 } | 1807 } |
1848 | 1808 |
| 1809 not_yet_discovered_array_buffers_for_scavenge_ = |
| 1810 live_array_buffers_for_scavenge_; |
| 1811 if (!from_scavenge) not_yet_discovered_array_buffers_ = live_array_buffers_; |
| 1812 |
1849 // Do not call through the api as this code is triggered while doing a GC. | 1813 // Do not call through the api as this code is triggered while doing a GC. |
1850 amount_of_external_allocated_memory_ -= FreeDeadArrayBuffersHelper( | 1814 amount_of_external_allocated_memory_ -= freed_memory; |
1851 isolate_, | |
1852 from_scavenge ? live_array_buffers_for_scavenge_ : live_array_buffers_, | |
1853 from_scavenge ? not_yet_discovered_array_buffers_for_scavenge_ | |
1854 : not_yet_discovered_array_buffers_); | |
1855 } | 1815 } |
1856 | 1816 |
1857 | 1817 |
1858 void Heap::TearDownArrayBuffers() { | 1818 void Heap::TearDownArrayBuffers() { |
1859 TearDownArrayBuffersHelper(isolate_, live_array_buffers_, | 1819 size_t freed_memory = 0; |
1860 not_yet_discovered_array_buffers_); | 1820 for (auto& buffer : live_array_buffers_) { |
| 1821 isolate()->array_buffer_allocator()->Free(buffer.first, buffer.second); |
| 1822 freed_memory += buffer.second; |
| 1823 } |
| 1824 for (auto& buffer : live_array_buffers_for_scavenge_) { |
| 1825 isolate()->array_buffer_allocator()->Free(buffer.first, buffer.second); |
| 1826 freed_memory += buffer.second; |
| 1827 } |
| 1828 live_array_buffers_.clear(); |
| 1829 live_array_buffers_for_scavenge_.clear(); |
| 1830 not_yet_discovered_array_buffers_.clear(); |
| 1831 not_yet_discovered_array_buffers_for_scavenge_.clear(); |
| 1832 |
| 1833 if (freed_memory > 0) { |
| 1834 reinterpret_cast<v8::Isolate*>(isolate_) |
| 1835 ->AdjustAmountOfExternalAllocatedMemory( |
| 1836 -static_cast<int64_t>(freed_memory)); |
| 1837 } |
1861 } | 1838 } |
1862 | 1839 |
1863 | 1840 |
1864 void Heap::PrepareArrayBufferDiscoveryInNewSpace() { | 1841 void Heap::PrepareArrayBufferDiscoveryInNewSpace() { |
1865 not_yet_discovered_array_buffers_for_scavenge_ = | 1842 not_yet_discovered_array_buffers_for_scavenge_ = |
1866 live_array_buffers_for_scavenge_; | 1843 live_array_buffers_for_scavenge_; |
1867 } | 1844 } |
1868 | 1845 |
1869 | 1846 |
1870 void Heap::PromoteArrayBuffer(Object* obj) { | 1847 void Heap::PromoteArrayBuffer(Object* obj) { |
1871 JSArrayBuffer* buffer = JSArrayBuffer::cast(obj); | 1848 JSArrayBuffer* buffer = JSArrayBuffer::cast(obj); |
1872 if (buffer->is_external()) return; | 1849 if (buffer->is_external()) return; |
1873 void* data = buffer->backing_store(); | 1850 void* data = buffer->backing_store(); |
1874 if (!data) return; | 1851 if (!data) return; |
1875 // ArrayBuffer might be in the middle of being constructed. | 1852 // ArrayBuffer might be in the middle of being constructed. |
1876 if (data == undefined_value()) return; | 1853 if (data == undefined_value()) return; |
1877 DCHECK(live_array_buffers_for_scavenge_.count(data) > 0); | 1854 DCHECK(live_array_buffers_for_scavenge_.count(data) > 0); |
1878 DCHECK(live_array_buffers_.count(data) > 0); | 1855 live_array_buffers_[data] = live_array_buffers_for_scavenge_[data]; |
1879 live_array_buffers_for_scavenge_.erase(data); | 1856 live_array_buffers_for_scavenge_.erase(data); |
1880 not_yet_discovered_array_buffers_for_scavenge_.erase(data); | 1857 not_yet_discovered_array_buffers_for_scavenge_.erase(data); |
1881 } | 1858 } |
1882 | 1859 |
1883 | 1860 |
1884 void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) { | 1861 void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) { |
1885 Object* allocation_site_obj = | 1862 Object* allocation_site_obj = |
1886 VisitWeakList<AllocationSite>(this, allocation_sites_list(), retainer); | 1863 VisitWeakList<AllocationSite>(this, allocation_sites_list(), retainer); |
1887 set_allocation_sites_list(allocation_site_obj); | 1864 set_allocation_sites_list(allocation_site_obj); |
1888 } | 1865 } |
(...skipping 4885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6774 *object_type = "CODE_TYPE"; \ | 6751 *object_type = "CODE_TYPE"; \ |
6775 *object_sub_type = "CODE_AGE/" #name; \ | 6752 *object_sub_type = "CODE_AGE/" #name; \ |
6776 return true; | 6753 return true; |
6777 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) | 6754 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) |
6778 #undef COMPARE_AND_RETURN_NAME | 6755 #undef COMPARE_AND_RETURN_NAME |
6779 } | 6756 } |
6780 return false; | 6757 return false; |
6781 } | 6758 } |
6782 } // namespace internal | 6759 } // namespace internal |
6783 } // namespace v8 | 6760 } // namespace v8 |
OLD | NEW |