Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/heap/mark-compact.cc

Issue 1471703002: Optimize ClearNonLiveReferences: collect dependent code only from maps that are embedded in optimize (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap/mark-compact.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/mark-compact.h" 5 #include "src/heap/mark-compact.h"
6 6
7 #include "src/base/atomicops.h" 7 #include "src/base/atomicops.h"
8 #include "src/base/bits.h" 8 #include "src/base/bits.h"
9 #include "src/base/sys-info.h" 9 #include "src/base/sys-info.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 342
343 void MarkCompactCollector::CollectGarbage() { 343 void MarkCompactCollector::CollectGarbage() {
344 // Make sure that Prepare() has been called. The individual steps below will 344 // Make sure that Prepare() has been called. The individual steps below will
345 // update the state as they proceed. 345 // update the state as they proceed.
346 DCHECK(state_ == PREPARE_GC); 346 DCHECK(state_ == PREPARE_GC);
347 347
348 MarkLiveObjects(); 348 MarkLiveObjects();
349 349
350 DCHECK(heap_->incremental_marking()->IsStopped()); 350 DCHECK(heap_->incremental_marking()->IsStopped());
351 351
352 // ClearNonLiveReferences can deoptimize code in dependent code arrays. 352 DependentCode* dependent_code_list = DependentCodeListFromNonLiveMaps();
353 // Process weak cells before so that weak cells in dependent code 353
354 // arrays are cleared or contain only live code objects. 354 // Process weak cells before MarkCodeForDeoptimization and
355 // ClearNonLiveReferences so that weak cells in dependent code arrays are
356 // cleared or contain only live code objects.
355 ProcessAndClearWeakCells(); 357 ProcessAndClearWeakCells();
356 358
359 MarkDependentCodeListForDeoptimization(dependent_code_list);
360
357 ClearNonLiveReferences(); 361 ClearNonLiveReferences();
358 362
359 ClearWeakCollections(); 363 ClearWeakCollections();
360 364
361 heap_->set_encountered_weak_cells(Smi::FromInt(0)); 365 heap_->set_encountered_weak_cells(Smi::FromInt(0));
362 366
363 #ifdef VERIFY_HEAP 367 #ifdef VERIFY_HEAP
364 if (FLAG_verify_heap) { 368 if (FLAG_verify_heap) {
365 VerifyMarking(heap_); 369 VerifyMarking(heap_);
366 } 370 }
(...skipping 1447 matching lines...) Expand 10 before | Expand all | Expand 10 after
1814 if (!code->CanDeoptAt(it.frame()->pc())) { 1818 if (!code->CanDeoptAt(it.frame()->pc())) {
1815 Code::BodyDescriptor::IterateBody(code, visitor); 1819 Code::BodyDescriptor::IterateBody(code, visitor);
1816 } 1820 }
1817 ProcessMarkingDeque(); 1821 ProcessMarkingDeque();
1818 return; 1822 return;
1819 } 1823 }
1820 } 1824 }
1821 } 1825 }
1822 1826
1823 1827
1828 bool ShouldRetainMap(Map* map, int age) {
1829 if (age == 0) {
1830 // The map has aged. Do not retain this map.
1831 return false;
1832 }
1833 Object* constructor = map->GetConstructor();
1834 if (!constructor->IsHeapObject() ||
1835 Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(constructor)))) {
1836 // The constructor is dead, no new objects with this map can
1837 // be created. Do not retain this map.
1838 return false;
1839 }
1840 return true;
1841 }
1842
1843
1824 void MarkCompactCollector::RetainMaps() { 1844 void MarkCompactCollector::RetainMaps() {
1825 if (heap()->ShouldReduceMemory() || heap()->ShouldAbortIncrementalMarking() || 1845 // Do not retain dead maps if flag disables it or there is
ulan 2015/11/23 12:16:13 Early return was a bug. We still need to compact t
1826 FLAG_retain_maps_for_n_gc == 0) { 1846 // - memory pressure (reduce_memory_footprint_),
1827 // Do not retain dead maps if flag disables it or there is 1847 // - GC is requested by tests or dev-tools (abort_incremental_marking_).
1828 // - memory pressure (reduce_memory_footprint_), 1848 bool map_retaining_is_disabled = heap()->ShouldReduceMemory() ||
1829 // - GC is requested by tests or dev-tools (abort_incremental_marking_). 1849 heap()->ShouldAbortIncrementalMarking() ||
1830 return; 1850 FLAG_retain_maps_for_n_gc == 0;
1831 }
1832 1851
1833 ArrayList* retained_maps = heap()->retained_maps(); 1852 ArrayList* retained_maps = heap()->retained_maps();
1834 int length = retained_maps->Length(); 1853 int length = retained_maps->Length();
1835 int new_length = 0; 1854 int new_length = 0;
1855 // This loop compacts the array by removing cleared weak cells,
1856 // ages and retains dead maps.
1836 for (int i = 0; i < length; i += 2) { 1857 for (int i = 0; i < length; i += 2) {
1837 DCHECK(retained_maps->Get(i)->IsWeakCell()); 1858 DCHECK(retained_maps->Get(i)->IsWeakCell());
1838 WeakCell* cell = WeakCell::cast(retained_maps->Get(i)); 1859 WeakCell* cell = WeakCell::cast(retained_maps->Get(i));
1839 if (cell->cleared()) continue; 1860 if (cell->cleared()) continue;
1840 int age = Smi::cast(retained_maps->Get(i + 1))->value(); 1861 int age = Smi::cast(retained_maps->Get(i + 1))->value();
1841 int new_age; 1862 int new_age;
1842 Map* map = Map::cast(cell->value()); 1863 Map* map = Map::cast(cell->value());
1843 MarkBit map_mark = Marking::MarkBitFrom(map); 1864 MarkBit map_mark = Marking::MarkBitFrom(map);
1844 if (Marking::IsWhite(map_mark)) { 1865 // Age the map and retain it if necessary.
1845 if (age == 0) { 1866 if (!map_retaining_is_disabled && Marking::IsWhite(map_mark)) {
1846 // The map has aged. Do not retain this map. 1867 if (ShouldRetainMap(map, age)) {
1847 continue; 1868 MarkObject(map, map_mark);
1848 }
1849 Object* constructor = map->GetConstructor();
1850 if (!constructor->IsHeapObject() || Marking::IsWhite(Marking::MarkBitFrom(
1851 HeapObject::cast(constructor)))) {
1852 // The constructor is dead, no new objects with this map can
1853 // be created. Do not retain this map.
1854 continue;
1855 } 1869 }
1856 Object* prototype = map->prototype(); 1870 Object* prototype = map->prototype();
1857 if (prototype->IsHeapObject() && 1871 if (age > 0 && prototype->IsHeapObject() &&
1858 Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(prototype)))) { 1872 Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(prototype)))) {
1859 // The prototype is not marked, age the map. 1873 // The prototype is not marked, age the map.
1860 new_age = age - 1; 1874 new_age = age - 1;
1861 } else { 1875 } else {
1862 // The prototype and the constructor are marked, this map keeps only 1876 // The prototype and the constructor are marked, this map keeps only
1863 // transition tree alive, not JSObjects. Do not age the map. 1877 // transition tree alive, not JSObjects. Do not age the map.
1864 new_age = age; 1878 new_age = age;
1865 } 1879 }
1866 MarkObject(map, map_mark);
1867 } else { 1880 } else {
1868 new_age = FLAG_retain_maps_for_n_gc; 1881 new_age = FLAG_retain_maps_for_n_gc;
1869 } 1882 }
1883 // Compact the array and update the age.
1870 if (i != new_length) { 1884 if (i != new_length) {
1871 retained_maps->Set(new_length, cell); 1885 retained_maps->Set(new_length, cell);
1872 Object** slot = retained_maps->Slot(new_length); 1886 Object** slot = retained_maps->Slot(new_length);
1873 RecordSlot(retained_maps, slot, cell); 1887 RecordSlot(retained_maps, slot, cell);
1874 retained_maps->Set(new_length + 1, Smi::FromInt(new_age)); 1888 retained_maps->Set(new_length + 1, Smi::FromInt(new_age));
1875 } else if (new_age != age) { 1889 } else if (new_age != age) {
1876 retained_maps->Set(new_length + 1, Smi::FromInt(new_age)); 1890 retained_maps->Set(new_length + 1, Smi::FromInt(new_age));
1877 } 1891 }
1878 new_length += 2; 1892 new_length += 2;
1879 } 1893 }
1880 Object* undefined = heap()->undefined_value(); 1894 Object* undefined = heap()->undefined_value();
1881 for (int i = new_length; i < length; i++) { 1895 for (int i = new_length; i < length; i++) {
1882 retained_maps->Clear(i, undefined); 1896 retained_maps->Clear(i, undefined);
1883 } 1897 }
1884 if (new_length != length) retained_maps->SetLength(new_length); 1898 if (new_length != length) retained_maps->SetLength(new_length);
1885 ProcessMarkingDeque(); 1899 ProcessMarkingDeque();
1886 } 1900 }
1887 1901
1888 1902
1903 DependentCode* MarkCompactCollector::DependentCodeListFromNonLiveMaps() {
1904 ArrayList* retained_maps = heap()->retained_maps();
1905 int length = retained_maps->Length();
1906 DependentCode* head = DependentCode::cast(heap()->empty_fixed_array());
1907 for (int i = 0; i < length; i += 2) {
1908 DCHECK(retained_maps->Get(i)->IsWeakCell());
1909 WeakCell* cell = WeakCell::cast(retained_maps->Get(i));
1910 DCHECK(!cell->cleared());
1911 Map* map = Map::cast(cell->value());
1912 MarkBit map_mark = Marking::MarkBitFrom(map);
1913 if (Marking::IsWhite(map_mark)) {
1914 DependentCode* new_head = map->dependent_code();
1915 DCHECK_EQ(DependentCode::kWeakCodeGroup, new_head->group());
1916 new_head->set_next_link(head);
1917 head = new_head;
1918 }
1919 }
1920 return head;
1921 }
1922
1923
1889 void MarkCompactCollector::EnsureMarkingDequeIsReserved() { 1924 void MarkCompactCollector::EnsureMarkingDequeIsReserved() {
1890 DCHECK(!marking_deque_.in_use()); 1925 DCHECK(!marking_deque_.in_use());
1891 if (marking_deque_memory_ == NULL) { 1926 if (marking_deque_memory_ == NULL) {
1892 marking_deque_memory_ = new base::VirtualMemory(kMaxMarkingDequeSize); 1927 marking_deque_memory_ = new base::VirtualMemory(kMaxMarkingDequeSize);
1893 marking_deque_memory_committed_ = 0; 1928 marking_deque_memory_committed_ = 0;
1894 } 1929 }
1895 if (marking_deque_memory_ == NULL) { 1930 if (marking_deque_memory_ == NULL) {
1896 V8::FatalProcessOutOfMemory("EnsureMarkingDequeIsReserved"); 1931 V8::FatalProcessOutOfMemory("EnsureMarkingDequeIsReserved");
1897 } 1932 }
1898 } 1933 }
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
2202 for (HeapObject* obj = map_iterator.Next(); obj != NULL; 2237 for (HeapObject* obj = map_iterator.Next(); obj != NULL;
2203 obj = map_iterator.Next()) { 2238 obj = map_iterator.Next()) {
2204 Map* map = Map::cast(obj); 2239 Map* map = Map::cast(obj);
2205 if (!map->CanTransition()) continue; 2240 if (!map->CanTransition()) continue;
2206 MarkBit map_mark = Marking::MarkBitFrom(map); 2241 MarkBit map_mark = Marking::MarkBitFrom(map);
2207 bool alive = Marking::IsBlackOrGrey(map_mark); 2242 bool alive = Marking::IsBlackOrGrey(map_mark);
2208 if (alive) { 2243 if (alive) {
2209 ClearNonLivePrototypeTransitions(map); 2244 ClearNonLivePrototypeTransitions(map);
2210 } else { 2245 } else {
2211 ClearNonLiveMapTransitions(map); 2246 ClearNonLiveMapTransitions(map);
2212 have_code_to_deoptimize_ |=
ulan 2015/11/23 12:16:13 Moving this code out is the main change.
2213 map->dependent_code()->MarkCodeForDeoptimization(
2214 isolate(), DependentCode::kWeakCodeGroup);
2215 map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array()));
2216 } 2247 }
2217 } 2248 }
2218 2249
2219 WeakHashTable* table = heap_->weak_object_to_code_table(); 2250 WeakHashTable* table = heap_->weak_object_to_code_table();
2220 uint32_t capacity = table->Capacity(); 2251 uint32_t capacity = table->Capacity();
2221 for (uint32_t i = 0; i < capacity; i++) { 2252 for (uint32_t i = 0; i < capacity; i++) {
2222 uint32_t key_index = table->EntryToIndex(i); 2253 uint32_t key_index = table->EntryToIndex(i);
2223 Object* key = table->get(key_index); 2254 Object* key = table->get(key_index);
2224 if (!table->IsKey(key)) continue; 2255 if (!table->IsKey(key)) continue;
2225 uint32_t value_index = table->EntryToValueIndex(i); 2256 uint32_t value_index = table->EntryToValueIndex(i);
2226 Object* value = table->get(value_index); 2257 Object* value = table->get(value_index);
2227 DCHECK(key->IsWeakCell()); 2258 DCHECK(key->IsWeakCell());
2228 if (WeakCell::cast(key)->cleared()) { 2259 if (WeakCell::cast(key)->cleared()) {
2229 have_code_to_deoptimize_ |= 2260 have_code_to_deoptimize_ |=
2230 DependentCode::cast(value)->MarkCodeForDeoptimization( 2261 DependentCode::cast(value)->MarkCodeForDeoptimization(
2231 isolate(), DependentCode::kWeakCodeGroup); 2262 isolate(), DependentCode::kWeakCodeGroup);
2232 table->set(key_index, heap_->the_hole_value()); 2263 table->set(key_index, heap_->the_hole_value());
2233 table->set(value_index, heap_->the_hole_value()); 2264 table->set(value_index, heap_->the_hole_value());
2234 table->ElementRemoved(); 2265 table->ElementRemoved();
2235 } 2266 }
2236 } 2267 }
2237 } 2268 }
2238 2269
2239 2270
2271 void MarkCompactCollector::MarkDependentCodeListForDeoptimization(
2272 DependentCode* list_head) {
2273 Isolate* isolate = this->isolate();
2274 DependentCode* current = list_head;
2275 while (current->length() > 0) {
2276 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization(
2277 isolate, DependentCode::kWeakCodeGroup);
2278 current = current->next_link();
2279 }
2280 }
2281
2282
2240 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { 2283 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) {
2241 FixedArray* prototype_transitions = 2284 FixedArray* prototype_transitions =
2242 TransitionArray::GetPrototypeTransitions(map); 2285 TransitionArray::GetPrototypeTransitions(map);
2243 int number_of_transitions = 2286 int number_of_transitions =
2244 TransitionArray::NumberOfPrototypeTransitions(prototype_transitions); 2287 TransitionArray::NumberOfPrototypeTransitions(prototype_transitions);
2245 2288
2246 const int header = TransitionArray::kProtoTransitionHeaderSize; 2289 const int header = TransitionArray::kProtoTransitionHeaderSize;
2247 int new_number_of_transitions = 0; 2290 int new_number_of_transitions = 0;
2248 for (int i = 0; i < number_of_transitions; i++) { 2291 for (int i = 0; i < number_of_transitions; i++) {
2249 Object* cell = prototype_transitions->get(header + i); 2292 Object* cell = prototype_transitions->get(header + i);
(...skipping 2237 matching lines...) Expand 10 before | Expand all | Expand 10 after
4487 MarkBit mark_bit = Marking::MarkBitFrom(host); 4530 MarkBit mark_bit = Marking::MarkBitFrom(host);
4488 if (Marking::IsBlack(mark_bit)) { 4531 if (Marking::IsBlack(mark_bit)) {
4489 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); 4532 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host);
4490 RecordRelocSlot(&rinfo, target); 4533 RecordRelocSlot(&rinfo, target);
4491 } 4534 }
4492 } 4535 }
4493 } 4536 }
4494 4537
4495 } // namespace internal 4538 } // namespace internal
4496 } // namespace v8 4539 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/mark-compact.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698