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

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, 1 month 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 // This should be done before processing weak cells because it checks
Hannes Payer (out of office) 2015/11/24 09:35:36 Let's add here a special category: ProcessWeakRefe
ulan 2015/11/24 12:00:08 Done.
353 // Process weak cells before so that weak cells in dependent code 353 // mark bits of maps in weak cells.
354 // arrays are cleared or contain only live code objects. 354 DependentCode* dependent_code_list = DependentCodeListFromNonLiveMaps();
355
356 // Process weak cells before MarkCodeForDeoptimization and
357 // ClearNonLiveReferences so that weak cells in dependent code arrays are
358 // cleared or contain only live code objects.
355 ProcessAndClearWeakCells(); 359 ProcessAndClearWeakCells();
356 360
361 MarkDependentCodeListForDeoptimization(dependent_code_list);
362
357 ClearNonLiveReferences(); 363 ClearNonLiveReferences();
358 364
359 ClearWeakCollections(); 365 ClearWeakCollections();
360 366
361 heap_->set_encountered_weak_cells(Smi::FromInt(0)); 367 heap_->set_encountered_weak_cells(Smi::FromInt(0));
362 368
363 #ifdef VERIFY_HEAP 369 #ifdef VERIFY_HEAP
364 if (FLAG_verify_heap) { 370 if (FLAG_verify_heap) {
365 VerifyMarking(heap_); 371 VerifyMarking(heap_);
366 } 372 }
(...skipping 1447 matching lines...) Expand 10 before | Expand all | Expand 10 after
1814 if (!code->CanDeoptAt(it.frame()->pc())) { 1820 if (!code->CanDeoptAt(it.frame()->pc())) {
1815 Code::BodyDescriptor::IterateBody(code, visitor); 1821 Code::BodyDescriptor::IterateBody(code, visitor);
1816 } 1822 }
1817 ProcessMarkingDeque(); 1823 ProcessMarkingDeque();
1818 return; 1824 return;
1819 } 1825 }
1820 } 1826 }
1821 } 1827 }
1822 1828
1823 1829
1830 bool ShouldRetainMap(Map* map, int age) {
1831 if (age == 0) {
1832 // The map has aged. Do not retain this map.
1833 return false;
1834 }
1835 Object* constructor = map->GetConstructor();
1836 if (!constructor->IsHeapObject() ||
1837 Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(constructor)))) {
1838 // The constructor is dead, no new objects with this map can
1839 // be created. Do not retain this map.
1840 return false;
1841 }
1842 return true;
1843 }
1844
1845
1824 void MarkCompactCollector::RetainMaps() { 1846 void MarkCompactCollector::RetainMaps() {
1825 if (heap()->ShouldReduceMemory() || heap()->ShouldAbortIncrementalMarking() || 1847 // Do not retain dead maps if flag disables it or there is
1826 FLAG_retain_maps_for_n_gc == 0) { 1848 // - memory pressure (reduce_memory_footprint_),
1827 // Do not retain dead maps if flag disables it or there is 1849 // - GC is requested by tests or dev-tools (abort_incremental_marking_).
1828 // - memory pressure (reduce_memory_footprint_), 1850 bool map_retaining_is_disabled = heap()->ShouldReduceMemory() ||
1829 // - GC is requested by tests or dev-tools (abort_incremental_marking_). 1851 heap()->ShouldAbortIncrementalMarking() ||
1830 return; 1852 FLAG_retain_maps_for_n_gc == 0;
1831 }
1832 1853
1833 ArrayList* retained_maps = heap()->retained_maps(); 1854 ArrayList* retained_maps = heap()->retained_maps();
1834 int length = retained_maps->Length(); 1855 int length = retained_maps->Length();
1835 int new_length = 0; 1856 int new_length = 0;
1857 // This loop compacts the array by removing cleared weak cells,
1858 // ages and retains dead maps.
1836 for (int i = 0; i < length; i += 2) { 1859 for (int i = 0; i < length; i += 2) {
1837 DCHECK(retained_maps->Get(i)->IsWeakCell()); 1860 DCHECK(retained_maps->Get(i)->IsWeakCell());
1838 WeakCell* cell = WeakCell::cast(retained_maps->Get(i)); 1861 WeakCell* cell = WeakCell::cast(retained_maps->Get(i));
1839 if (cell->cleared()) continue; 1862 if (cell->cleared()) continue;
1840 int age = Smi::cast(retained_maps->Get(i + 1))->value(); 1863 int age = Smi::cast(retained_maps->Get(i + 1))->value();
1841 int new_age; 1864 int new_age;
1842 Map* map = Map::cast(cell->value()); 1865 Map* map = Map::cast(cell->value());
1843 MarkBit map_mark = Marking::MarkBitFrom(map); 1866 MarkBit map_mark = Marking::MarkBitFrom(map);
1844 if (Marking::IsWhite(map_mark)) { 1867 // Age the map and retain it if necessary.
1845 if (age == 0) { 1868 if (!map_retaining_is_disabled && Marking::IsWhite(map_mark)) {
1846 // The map has aged. Do not retain this map. 1869 if (ShouldRetainMap(map, age)) {
1847 continue; 1870 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 } 1871 }
1856 Object* prototype = map->prototype(); 1872 Object* prototype = map->prototype();
1857 if (prototype->IsHeapObject() && 1873 if (age > 0 && prototype->IsHeapObject() &&
1858 Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(prototype)))) { 1874 Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(prototype)))) {
1859 // The prototype is not marked, age the map. 1875 // The prototype is not marked, age the map.
1860 new_age = age - 1; 1876 new_age = age - 1;
1861 } else { 1877 } else {
1862 // The prototype and the constructor are marked, this map keeps only 1878 // The prototype and the constructor are marked, this map keeps only
1863 // transition tree alive, not JSObjects. Do not age the map. 1879 // transition tree alive, not JSObjects. Do not age the map.
1864 new_age = age; 1880 new_age = age;
1865 } 1881 }
1866 MarkObject(map, map_mark);
1867 } else { 1882 } else {
1868 new_age = FLAG_retain_maps_for_n_gc; 1883 new_age = FLAG_retain_maps_for_n_gc;
1869 } 1884 }
1885 // Compact the array and update the age.
1870 if (i != new_length) { 1886 if (i != new_length) {
1871 retained_maps->Set(new_length, cell); 1887 retained_maps->Set(new_length, cell);
1872 Object** slot = retained_maps->Slot(new_length); 1888 Object** slot = retained_maps->Slot(new_length);
1873 RecordSlot(retained_maps, slot, cell); 1889 RecordSlot(retained_maps, slot, cell);
1874 retained_maps->Set(new_length + 1, Smi::FromInt(new_age)); 1890 retained_maps->Set(new_length + 1, Smi::FromInt(new_age));
1875 } else if (new_age != age) { 1891 } else if (new_age != age) {
1876 retained_maps->Set(new_length + 1, Smi::FromInt(new_age)); 1892 retained_maps->Set(new_length + 1, Smi::FromInt(new_age));
1877 } 1893 }
1878 new_length += 2; 1894 new_length += 2;
1879 } 1895 }
1880 Object* undefined = heap()->undefined_value(); 1896 Object* undefined = heap()->undefined_value();
1881 for (int i = new_length; i < length; i++) { 1897 for (int i = new_length; i < length; i++) {
1882 retained_maps->Clear(i, undefined); 1898 retained_maps->Clear(i, undefined);
1883 } 1899 }
1884 if (new_length != length) retained_maps->SetLength(new_length); 1900 if (new_length != length) retained_maps->SetLength(new_length);
1885 ProcessMarkingDeque(); 1901 ProcessMarkingDeque();
1886 } 1902 }
1887 1903
1888 1904
1905 DependentCode* MarkCompactCollector::DependentCodeListFromNonLiveMaps() {
Hannes Payer (out of office) 2015/11/24 09:35:37 Timer scope.
ulan 2015/11/24 12:00:08 Done.
1906 ArrayList* retained_maps = heap()->retained_maps();
1907 int length = retained_maps->Length();
1908 DependentCode* head = DependentCode::cast(heap()->empty_fixed_array());
1909 for (int i = 0; i < length; i += 2) {
1910 DCHECK(retained_maps->Get(i)->IsWeakCell());
1911 WeakCell* cell = WeakCell::cast(retained_maps->Get(i));
1912 DCHECK(!cell->cleared());
1913 Map* map = Map::cast(cell->value());
1914 MarkBit map_mark = Marking::MarkBitFrom(map);
1915 if (Marking::IsWhite(map_mark)) {
1916 DependentCode* candidate = map->dependent_code();
1917 // We rely on the fact that the weak code group comes first.
1918 STATIC_ASSERT(DependentCode::kWeakCodeGroup == 0);
1919 if (candidate->length() > 0 &&
1920 candidate->group() == DependentCode::kWeakCodeGroup) {
1921 candidate->set_next_link(head);
1922 head = candidate;
1923 }
1924 }
1925 }
1926 return head;
1927 }
1928
1929
1889 void MarkCompactCollector::EnsureMarkingDequeIsReserved() { 1930 void MarkCompactCollector::EnsureMarkingDequeIsReserved() {
1890 DCHECK(!marking_deque_.in_use()); 1931 DCHECK(!marking_deque_.in_use());
1891 if (marking_deque_memory_ == NULL) { 1932 if (marking_deque_memory_ == NULL) {
1892 marking_deque_memory_ = new base::VirtualMemory(kMaxMarkingDequeSize); 1933 marking_deque_memory_ = new base::VirtualMemory(kMaxMarkingDequeSize);
1893 marking_deque_memory_committed_ = 0; 1934 marking_deque_memory_committed_ = 0;
1894 } 1935 }
1895 if (marking_deque_memory_ == NULL) { 1936 if (marking_deque_memory_ == NULL) {
1896 V8::FatalProcessOutOfMemory("EnsureMarkingDequeIsReserved"); 1937 V8::FatalProcessOutOfMemory("EnsureMarkingDequeIsReserved");
1897 } 1938 }
1898 } 1939 }
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
2202 for (HeapObject* obj = map_iterator.Next(); obj != NULL; 2243 for (HeapObject* obj = map_iterator.Next(); obj != NULL;
2203 obj = map_iterator.Next()) { 2244 obj = map_iterator.Next()) {
2204 Map* map = Map::cast(obj); 2245 Map* map = Map::cast(obj);
2205 if (!map->CanTransition()) continue; 2246 if (!map->CanTransition()) continue;
2206 MarkBit map_mark = Marking::MarkBitFrom(map); 2247 MarkBit map_mark = Marking::MarkBitFrom(map);
2207 bool alive = Marking::IsBlackOrGrey(map_mark); 2248 bool alive = Marking::IsBlackOrGrey(map_mark);
2208 if (alive) { 2249 if (alive) {
2209 ClearNonLivePrototypeTransitions(map); 2250 ClearNonLivePrototypeTransitions(map);
2210 } else { 2251 } else {
2211 ClearNonLiveMapTransitions(map); 2252 ClearNonLiveMapTransitions(map);
2212 have_code_to_deoptimize_ |=
2213 map->dependent_code()->MarkCodeForDeoptimization(
2214 isolate(), DependentCode::kWeakCodeGroup);
2215 map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array()));
2216 } 2253 }
2217 } 2254 }
2218 2255
2219 WeakHashTable* table = heap_->weak_object_to_code_table(); 2256 WeakHashTable* table = heap_->weak_object_to_code_table();
2220 uint32_t capacity = table->Capacity(); 2257 uint32_t capacity = table->Capacity();
2221 for (uint32_t i = 0; i < capacity; i++) { 2258 for (uint32_t i = 0; i < capacity; i++) {
2222 uint32_t key_index = table->EntryToIndex(i); 2259 uint32_t key_index = table->EntryToIndex(i);
2223 Object* key = table->get(key_index); 2260 Object* key = table->get(key_index);
2224 if (!table->IsKey(key)) continue; 2261 if (!table->IsKey(key)) continue;
2225 uint32_t value_index = table->EntryToValueIndex(i); 2262 uint32_t value_index = table->EntryToValueIndex(i);
2226 Object* value = table->get(value_index); 2263 Object* value = table->get(value_index);
2227 DCHECK(key->IsWeakCell()); 2264 DCHECK(key->IsWeakCell());
2228 if (WeakCell::cast(key)->cleared()) { 2265 if (WeakCell::cast(key)->cleared()) {
2229 have_code_to_deoptimize_ |= 2266 have_code_to_deoptimize_ |=
2230 DependentCode::cast(value)->MarkCodeForDeoptimization( 2267 DependentCode::cast(value)->MarkCodeForDeoptimization(
2231 isolate(), DependentCode::kWeakCodeGroup); 2268 isolate(), DependentCode::kWeakCodeGroup);
2232 table->set(key_index, heap_->the_hole_value()); 2269 table->set(key_index, heap_->the_hole_value());
2233 table->set(value_index, heap_->the_hole_value()); 2270 table->set(value_index, heap_->the_hole_value());
2234 table->ElementRemoved(); 2271 table->ElementRemoved();
2235 } 2272 }
2236 } 2273 }
2237 } 2274 }
2238 2275
2239 2276
2277 void MarkCompactCollector::MarkDependentCodeListForDeoptimization(
Hannes Payer (out of office) 2015/11/24 09:35:36 Timer scope.
ulan 2015/11/24 12:00:08 Done.
2278 DependentCode* list_head) {
2279 Isolate* isolate = this->isolate();
2280 DependentCode* current = list_head;
2281 while (current->length() > 0) {
2282 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization(
2283 isolate, DependentCode::kWeakCodeGroup);
2284 current = current->next_link();
2285 }
2286 }
2287
2288
2240 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { 2289 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) {
2241 FixedArray* prototype_transitions = 2290 FixedArray* prototype_transitions =
2242 TransitionArray::GetPrototypeTransitions(map); 2291 TransitionArray::GetPrototypeTransitions(map);
2243 int number_of_transitions = 2292 int number_of_transitions =
2244 TransitionArray::NumberOfPrototypeTransitions(prototype_transitions); 2293 TransitionArray::NumberOfPrototypeTransitions(prototype_transitions);
2245 2294
2246 const int header = TransitionArray::kProtoTransitionHeaderSize; 2295 const int header = TransitionArray::kProtoTransitionHeaderSize;
2247 int new_number_of_transitions = 0; 2296 int new_number_of_transitions = 0;
2248 for (int i = 0; i < number_of_transitions; i++) { 2297 for (int i = 0; i < number_of_transitions; i++) {
2249 Object* cell = prototype_transitions->get(header + i); 2298 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); 4536 MarkBit mark_bit = Marking::MarkBitFrom(host);
4488 if (Marking::IsBlack(mark_bit)) { 4537 if (Marking::IsBlack(mark_bit)) {
4489 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); 4538 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host);
4490 RecordRelocSlot(&rinfo, target); 4539 RecordRelocSlot(&rinfo, target);
4491 } 4540 }
4492 } 4541 }
4493 } 4542 }
4494 4543
4495 } // namespace internal 4544 } // namespace internal
4496 } // namespace v8 4545 } // 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