| 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/v8.h" | 5 #include "src/v8.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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 gc_count_at_last_idle_gc_(0), | 134 gc_count_at_last_idle_gc_(0), |
| 135 full_codegen_bytes_generated_(0), | 135 full_codegen_bytes_generated_(0), |
| 136 crankshaft_codegen_bytes_generated_(0), | 136 crankshaft_codegen_bytes_generated_(0), |
| 137 gcs_since_last_deopt_(0), | 137 gcs_since_last_deopt_(0), |
| 138 allocation_sites_scratchpad_length_(0), | 138 allocation_sites_scratchpad_length_(0), |
| 139 promotion_queue_(this), | 139 promotion_queue_(this), |
| 140 configured_(false), | 140 configured_(false), |
| 141 external_string_table_(this), | 141 external_string_table_(this), |
| 142 chunks_queued_for_free_(NULL), | 142 chunks_queued_for_free_(NULL), |
| 143 gc_callbacks_depth_(0), | 143 gc_callbacks_depth_(0), |
| 144 deserialization_complete_(false), | 144 deserialization_complete_(false) { |
| 145 promotion_failure_(false) { | |
| 146 // Allow build-time customization of the max semispace size. Building | 145 // Allow build-time customization of the max semispace size. Building |
| 147 // V8 with snapshots and a non-default max semispace size is much | 146 // V8 with snapshots and a non-default max semispace size is much |
| 148 // easier if you can define it as part of the build environment. | 147 // easier if you can define it as part of the build environment. |
| 149 #if defined(V8_MAX_SEMISPACE_SIZE) | 148 #if defined(V8_MAX_SEMISPACE_SIZE) |
| 150 max_semi_space_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; | 149 max_semi_space_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; |
| 151 #endif | 150 #endif |
| 152 | 151 |
| 153 // Ensure old_generation_size_ is a multiple of kPageSize. | 152 // Ensure old_generation_size_ is a multiple of kPageSize. |
| 154 DCHECK(MB >= Page::kPageSize); | 153 DCHECK(MB >= Page::kPageSize); |
| 155 | 154 |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 #undef UPDATE_FRAGMENTATION_FOR_SPACE | 721 #undef UPDATE_FRAGMENTATION_FOR_SPACE |
| 723 #undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE | 722 #undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE |
| 724 | 723 |
| 725 #ifdef DEBUG | 724 #ifdef DEBUG |
| 726 ReportStatisticsAfterGC(); | 725 ReportStatisticsAfterGC(); |
| 727 #endif // DEBUG | 726 #endif // DEBUG |
| 728 | 727 |
| 729 // Remember the last top pointer so that we can later find out | 728 // Remember the last top pointer so that we can later find out |
| 730 // whether we allocated in new space since the last GC. | 729 // whether we allocated in new space since the last GC. |
| 731 new_space_top_after_last_gc_ = new_space()->top(); | 730 new_space_top_after_last_gc_ = new_space()->top(); |
| 732 set_promotion_failure(false); | |
| 733 } | 731 } |
| 734 | 732 |
| 735 | 733 |
| 736 void Heap::HandleGCRequest() { | 734 void Heap::HandleGCRequest() { |
| 737 if (incremental_marking()->request_type() == | 735 if (incremental_marking()->request_type() == |
| 738 IncrementalMarking::COMPLETE_MARKING) { | 736 IncrementalMarking::COMPLETE_MARKING) { |
| 739 CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt"); | 737 CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt"); |
| 740 return; | 738 return; |
| 741 } | 739 } |
| 742 DCHECK(FLAG_overapproximate_weak_closure); | 740 DCHECK(FLAG_overapproximate_weak_closure); |
| (...skipping 981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1724 Object** start = &external_string_table_.old_space_strings_[0]; | 1722 Object** start = &external_string_table_.old_space_strings_[0]; |
| 1725 Object** end = start + external_string_table_.old_space_strings_.length(); | 1723 Object** end = start + external_string_table_.old_space_strings_.length(); |
| 1726 for (Object** p = start; p < end; ++p) *p = updater_func(this, p); | 1724 for (Object** p = start; p < end; ++p) *p = updater_func(this, p); |
| 1727 } | 1725 } |
| 1728 | 1726 |
| 1729 UpdateNewSpaceReferencesInExternalStringTable(updater_func); | 1727 UpdateNewSpaceReferencesInExternalStringTable(updater_func); |
| 1730 } | 1728 } |
| 1731 | 1729 |
| 1732 | 1730 |
| 1733 void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) { | 1731 void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) { |
| 1734 ProcessArrayBuffers(retainer, false); | 1732 ProcessArrayBuffers(retainer); |
| 1735 ProcessNewArrayBufferViews(retainer); | |
| 1736 ProcessNativeContexts(retainer); | 1733 ProcessNativeContexts(retainer); |
| 1737 ProcessAllocationSites(retainer); | 1734 ProcessAllocationSites(retainer); |
| 1738 } | 1735 } |
| 1739 | 1736 |
| 1740 | 1737 |
| 1741 void Heap::ProcessYoungWeakReferences(WeakObjectRetainer* retainer) { | 1738 void Heap::ProcessYoungWeakReferences(WeakObjectRetainer* retainer) { |
| 1742 ProcessArrayBuffers(retainer, true); | 1739 ProcessArrayBuffers(retainer); |
| 1743 ProcessNewArrayBufferViews(retainer); | |
| 1744 ProcessNativeContexts(retainer); | 1740 ProcessNativeContexts(retainer); |
| 1745 } | 1741 } |
| 1746 | 1742 |
| 1747 | 1743 |
| 1748 void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) { | 1744 void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) { |
| 1749 Object* head = | 1745 Object* head = VisitWeakList<Context>(this, native_contexts_list(), retainer); |
| 1750 VisitWeakList<Context>(this, native_contexts_list(), retainer, false); | |
| 1751 // Update the head of the list of contexts. | 1746 // Update the head of the list of contexts. |
| 1752 set_native_contexts_list(head); | 1747 set_native_contexts_list(head); |
| 1753 } | 1748 } |
| 1754 | 1749 |
| 1755 | 1750 |
| 1756 void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer, | 1751 void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer) { |
| 1757 bool stop_after_young) { | 1752 Object* array_buffer_obj = |
| 1758 Object* array_buffer_obj = VisitWeakList<JSArrayBuffer>( | 1753 VisitWeakList<JSArrayBuffer>(this, array_buffers_list(), retainer); |
| 1759 this, array_buffers_list(), retainer, stop_after_young); | |
| 1760 set_array_buffers_list(array_buffer_obj); | 1754 set_array_buffers_list(array_buffer_obj); |
| 1761 | |
| 1762 #ifdef DEBUG | |
| 1763 // Verify invariant that young array buffers come before old array buffers | |
| 1764 // in array buffers list if there was no promotion failure. | |
| 1765 Object* undefined = undefined_value(); | |
| 1766 Object* next = array_buffers_list(); | |
| 1767 bool old_objects_recorded = false; | |
| 1768 if (promotion_failure()) return; | |
| 1769 while (next != undefined) { | |
| 1770 if (!old_objects_recorded) { | |
| 1771 old_objects_recorded = !InNewSpace(next); | |
| 1772 } | |
| 1773 DCHECK((InNewSpace(next) && !old_objects_recorded) || !InNewSpace(next)); | |
| 1774 next = JSArrayBuffer::cast(next)->weak_next(); | |
| 1775 } | |
| 1776 #endif | |
| 1777 } | 1755 } |
| 1778 | 1756 |
| 1779 | 1757 |
| 1780 void Heap::ProcessNewArrayBufferViews(WeakObjectRetainer* retainer) { | |
| 1781 // Retain the list of new space views. | |
| 1782 Object* typed_array_obj = VisitWeakList<JSArrayBufferView>( | |
| 1783 this, new_array_buffer_views_list_, retainer, false); | |
| 1784 set_new_array_buffer_views_list(typed_array_obj); | |
| 1785 | |
| 1786 // Some objects in the list may be in old space now. Find them | |
| 1787 // and move them to the corresponding array buffer. | |
| 1788 Object* undefined = undefined_value(); | |
| 1789 Object* previous = undefined; | |
| 1790 Object* head = undefined; | |
| 1791 Object* next; | |
| 1792 for (Object* o = new_array_buffer_views_list(); o != undefined;) { | |
| 1793 JSArrayBufferView* view = JSArrayBufferView::cast(o); | |
| 1794 next = view->weak_next(); | |
| 1795 if (!InNewSpace(view)) { | |
| 1796 if (previous != undefined) { | |
| 1797 // We are in the middle of the list, skip the old space element. | |
| 1798 JSArrayBufferView::cast(previous)->set_weak_next(next); | |
| 1799 } | |
| 1800 JSArrayBuffer* buffer = JSArrayBuffer::cast(view->buffer()); | |
| 1801 view->set_weak_next(buffer->weak_first_view()); | |
| 1802 buffer->set_weak_first_view(view); | |
| 1803 } else { | |
| 1804 // We found a valid new space view, remember it. | |
| 1805 previous = view; | |
| 1806 if (head == undefined) { | |
| 1807 // We are at the list head. | |
| 1808 head = view; | |
| 1809 } | |
| 1810 } | |
| 1811 o = next; | |
| 1812 } | |
| 1813 set_new_array_buffer_views_list(head); | |
| 1814 } | |
| 1815 | |
| 1816 | |
| 1817 void Heap::TearDownArrayBuffers() { | 1758 void Heap::TearDownArrayBuffers() { |
| 1818 Object* undefined = undefined_value(); | 1759 Object* undefined = undefined_value(); |
| 1819 for (Object* o = array_buffers_list(); o != undefined;) { | 1760 for (Object* o = array_buffers_list(); o != undefined;) { |
| 1820 JSArrayBuffer* buffer = JSArrayBuffer::cast(o); | 1761 JSArrayBuffer* buffer = JSArrayBuffer::cast(o); |
| 1821 Runtime::FreeArrayBuffer(isolate(), buffer); | 1762 Runtime::FreeArrayBuffer(isolate(), buffer); |
| 1822 o = buffer->weak_next(); | 1763 o = buffer->weak_next(); |
| 1823 } | 1764 } |
| 1824 set_array_buffers_list(undefined); | 1765 set_array_buffers_list(undefined); |
| 1825 } | 1766 } |
| 1826 | 1767 |
| 1827 | 1768 |
| 1828 void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) { | 1769 void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) { |
| 1829 Object* allocation_site_obj = VisitWeakList<AllocationSite>( | 1770 Object* allocation_site_obj = |
| 1830 this, allocation_sites_list(), retainer, false); | 1771 VisitWeakList<AllocationSite>(this, allocation_sites_list(), retainer); |
| 1831 set_allocation_sites_list(allocation_site_obj); | 1772 set_allocation_sites_list(allocation_site_obj); |
| 1832 } | 1773 } |
| 1833 | 1774 |
| 1834 | 1775 |
| 1835 void Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) { | 1776 void Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) { |
| 1836 DisallowHeapAllocation no_allocation_scope; | 1777 DisallowHeapAllocation no_allocation_scope; |
| 1837 Object* cur = allocation_sites_list(); | 1778 Object* cur = allocation_sites_list(); |
| 1838 bool marked = false; | 1779 bool marked = false; |
| 1839 while (cur->IsAllocationSite()) { | 1780 while (cur->IsAllocationSite()) { |
| 1840 AllocationSite* casted = AllocationSite::cast(cur); | 1781 AllocationSite* casted = AllocationSite::cast(cur); |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2253 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) { | 2194 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) { |
| 2254 return; | 2195 return; |
| 2255 } | 2196 } |
| 2256 } | 2197 } |
| 2257 | 2198 |
| 2258 if (PromoteObject<object_contents, alignment>(map, slot, object, | 2199 if (PromoteObject<object_contents, alignment>(map, slot, object, |
| 2259 object_size)) { | 2200 object_size)) { |
| 2260 return; | 2201 return; |
| 2261 } | 2202 } |
| 2262 | 2203 |
| 2263 heap->set_promotion_failure(true); | |
| 2264 // If promotion failed, we try to copy the object to the other semi-space | 2204 // If promotion failed, we try to copy the object to the other semi-space |
| 2265 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return; | 2205 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return; |
| 2266 | 2206 |
| 2267 UNREACHABLE(); | 2207 UNREACHABLE(); |
| 2268 } | 2208 } |
| 2269 | 2209 |
| 2270 | 2210 |
| 2271 static inline void EvacuateJSFunction(Map* map, HeapObject** slot, | 2211 static inline void EvacuateJSFunction(Map* map, HeapObject** slot, |
| 2272 HeapObject* object) { | 2212 HeapObject* object) { |
| 2273 ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized< | 2213 ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized< |
| (...skipping 3318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5592 // Create initial maps. | 5532 // Create initial maps. |
| 5593 if (!CreateInitialMaps()) return false; | 5533 if (!CreateInitialMaps()) return false; |
| 5594 CreateApiObjects(); | 5534 CreateApiObjects(); |
| 5595 | 5535 |
| 5596 // Create initial objects | 5536 // Create initial objects |
| 5597 CreateInitialObjects(); | 5537 CreateInitialObjects(); |
| 5598 CHECK_EQ(0u, gc_count_); | 5538 CHECK_EQ(0u, gc_count_); |
| 5599 | 5539 |
| 5600 set_native_contexts_list(undefined_value()); | 5540 set_native_contexts_list(undefined_value()); |
| 5601 set_array_buffers_list(undefined_value()); | 5541 set_array_buffers_list(undefined_value()); |
| 5602 set_new_array_buffer_views_list(undefined_value()); | |
| 5603 set_allocation_sites_list(undefined_value()); | 5542 set_allocation_sites_list(undefined_value()); |
| 5604 return true; | 5543 return true; |
| 5605 } | 5544 } |
| 5606 | 5545 |
| 5607 | 5546 |
| 5608 void Heap::SetStackLimits() { | 5547 void Heap::SetStackLimits() { |
| 5609 DCHECK(isolate_ != NULL); | 5548 DCHECK(isolate_ != NULL); |
| 5610 DCHECK(isolate_ == isolate()); | 5549 DCHECK(isolate_ == isolate()); |
| 5611 // On 64 bit machines, pointers are generally out of range of Smis. We write | 5550 // On 64 bit machines, pointers are generally out of range of Smis. We write |
| 5612 // something that looks like an out of range Smi to the GC. | 5551 // something that looks like an out of range Smi to the GC. |
| (...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6581 static_cast<int>(object_sizes_last_time_[index])); | 6520 static_cast<int>(object_sizes_last_time_[index])); |
| 6582 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6521 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 6583 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6522 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 6584 | 6523 |
| 6585 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6524 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 6586 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6525 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 6587 ClearObjectStats(); | 6526 ClearObjectStats(); |
| 6588 } | 6527 } |
| 6589 } | 6528 } |
| 6590 } // namespace v8::internal | 6529 } // namespace v8::internal |
| OLD | NEW |