| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "compilation-cache.h" | 31 #include "compilation-cache.h" |
| 32 #include "cpu-profiler.h" | 32 #include "cpu-profiler.h" |
| 33 #include "deoptimizer.h" | 33 #include "deoptimizer.h" |
| 34 #include "execution.h" | 34 #include "execution.h" |
| 35 #include "gdb-jit.h" | 35 #include "gdb-jit.h" |
| 36 #include "global-handles.h" | 36 #include "global-handles.h" |
| 37 #include "heap-profiler.h" | 37 #include "heap-profiler.h" |
| 38 #include "ic-inl.h" | 38 #include "ic-inl.h" |
| 39 #include "incremental-marking.h" | 39 #include "incremental-marking.h" |
| 40 #include "mark-compact.h" | 40 #include "mark-compact.h" |
| 41 #include "marking-thread.h" | |
| 42 #include "objects-visiting.h" | 41 #include "objects-visiting.h" |
| 43 #include "objects-visiting-inl.h" | 42 #include "objects-visiting-inl.h" |
| 44 #include "stub-cache.h" | 43 #include "stub-cache.h" |
| 45 #include "sweeper-thread.h" | 44 #include "sweeper-thread.h" |
| 46 | 45 |
| 47 namespace v8 { | 46 namespace v8 { |
| 48 namespace internal { | 47 namespace internal { |
| 49 | 48 |
| 50 | 49 |
| 51 const char* Marking::kWhiteBitPattern = "00"; | 50 const char* Marking::kWhiteBitPattern = "00"; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 for (Object** current = start; current < end; current++) { | 84 for (Object** current = start; current < end; current++) { |
| 86 if ((*current)->IsHeapObject()) { | 85 if ((*current)->IsHeapObject()) { |
| 87 HeapObject* object = HeapObject::cast(*current); | 86 HeapObject* object = HeapObject::cast(*current); |
| 88 CHECK(heap_->mark_compact_collector()->IsMarked(object)); | 87 CHECK(heap_->mark_compact_collector()->IsMarked(object)); |
| 89 } | 88 } |
| 90 } | 89 } |
| 91 } | 90 } |
| 92 | 91 |
| 93 void VisitEmbeddedPointer(RelocInfo* rinfo) { | 92 void VisitEmbeddedPointer(RelocInfo* rinfo) { |
| 94 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 93 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
| 95 if (!FLAG_weak_embedded_maps_in_optimized_code || !FLAG_collect_maps || | 94 if (!Code::IsWeakEmbeddedObject(rinfo->host()->kind(), |
| 96 rinfo->host()->kind() != Code::OPTIMIZED_FUNCTION || | 95 rinfo->target_object())) { |
| 97 !rinfo->target_object()->IsMap() || | |
| 98 !Map::cast(rinfo->target_object())->CanTransition()) { | |
| 99 VisitPointer(rinfo->target_object_address()); | 96 VisitPointer(rinfo->target_object_address()); |
| 100 } | 97 } |
| 101 } | 98 } |
| 102 | 99 |
| 103 private: | 100 private: |
| 104 Heap* heap_; | 101 Heap* heap_; |
| 105 }; | 102 }; |
| 106 | 103 |
| 107 | 104 |
| 108 static void VerifyMarking(Heap* heap, Address bottom, Address top) { | 105 static void VerifyMarking(Heap* heap, Address bottom, Address top) { |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 return compacting_; | 398 return compacting_; |
| 402 } | 399 } |
| 403 | 400 |
| 404 | 401 |
| 405 void MarkCompactCollector::CollectGarbage() { | 402 void MarkCompactCollector::CollectGarbage() { |
| 406 // Make sure that Prepare() has been called. The individual steps below will | 403 // Make sure that Prepare() has been called. The individual steps below will |
| 407 // update the state as they proceed. | 404 // update the state as they proceed. |
| 408 ASSERT(state_ == PREPARE_GC); | 405 ASSERT(state_ == PREPARE_GC); |
| 409 ASSERT(encountered_weak_collections_ == Smi::FromInt(0)); | 406 ASSERT(encountered_weak_collections_ == Smi::FromInt(0)); |
| 410 | 407 |
| 408 heap()->allocation_mementos_found_ = 0; |
| 409 |
| 411 MarkLiveObjects(); | 410 MarkLiveObjects(); |
| 412 ASSERT(heap_->incremental_marking()->IsStopped()); | 411 ASSERT(heap_->incremental_marking()->IsStopped()); |
| 413 | 412 |
| 414 if (FLAG_collect_maps) ClearNonLiveReferences(); | 413 if (FLAG_collect_maps) ClearNonLiveReferences(); |
| 415 | 414 |
| 416 ClearWeakCollections(); | 415 ClearWeakCollections(); |
| 417 | 416 |
| 418 #ifdef VERIFY_HEAP | 417 #ifdef VERIFY_HEAP |
| 419 if (FLAG_verify_heap) { | 418 if (FLAG_verify_heap) { |
| 420 VerifyMarking(heap_); | 419 VerifyMarking(heap_); |
| 421 } | 420 } |
| 422 #endif | 421 #endif |
| 423 | 422 |
| 424 SweepSpaces(); | 423 SweepSpaces(); |
| 425 | 424 |
| 426 if (!FLAG_collect_maps) ReattachInitialMaps(); | 425 if (!FLAG_collect_maps) ReattachInitialMaps(); |
| 427 | 426 |
| 428 #ifdef DEBUG | 427 #ifdef DEBUG |
| 429 if (FLAG_verify_native_context_separation) { | 428 if (FLAG_verify_native_context_separation) { |
| 430 VerifyNativeContextSeparation(heap_); | 429 VerifyNativeContextSeparation(heap_); |
| 431 } | 430 } |
| 432 #endif | 431 #endif |
| 433 | 432 |
| 434 #ifdef VERIFY_HEAP | 433 #ifdef VERIFY_HEAP |
| 435 if (FLAG_collect_maps && FLAG_weak_embedded_maps_in_optimized_code && | 434 if (heap()->weak_embedded_objects_verification_enabled()) { |
| 436 heap()->weak_embedded_maps_verification_enabled()) { | 435 VerifyWeakEmbeddedObjectsInOptimizedCode(); |
| 437 VerifyWeakEmbeddedMapsInOptimizedCode(); | |
| 438 } | 436 } |
| 439 if (FLAG_collect_maps && FLAG_omit_map_checks_for_leaf_maps) { | 437 if (FLAG_collect_maps && FLAG_omit_map_checks_for_leaf_maps) { |
| 440 VerifyOmittedMapChecks(); | 438 VerifyOmittedMapChecks(); |
| 441 } | 439 } |
| 442 #endif | 440 #endif |
| 443 | 441 |
| 444 Finish(); | 442 Finish(); |
| 445 | 443 |
| 446 if (marking_parity_ == EVEN_MARKING_PARITY) { | 444 if (marking_parity_ == EVEN_MARKING_PARITY) { |
| 447 marking_parity_ = ODD_MARKING_PARITY; | 445 marking_parity_ = ODD_MARKING_PARITY; |
| 448 } else { | 446 } else { |
| 449 ASSERT(marking_parity_ == ODD_MARKING_PARITY); | 447 ASSERT(marking_parity_ == ODD_MARKING_PARITY); |
| 450 marking_parity_ = EVEN_MARKING_PARITY; | 448 marking_parity_ = EVEN_MARKING_PARITY; |
| 451 } | 449 } |
| 452 | 450 |
| 451 if (FLAG_trace_track_allocation_sites && |
| 452 heap()->allocation_mementos_found_ > 0) { |
| 453 PrintF("AllocationMementos found during mark-sweep = %d\n", |
| 454 heap()->allocation_mementos_found_); |
| 455 } |
| 453 tracer_ = NULL; | 456 tracer_ = NULL; |
| 454 } | 457 } |
| 455 | 458 |
| 456 | 459 |
| 457 #ifdef VERIFY_HEAP | 460 #ifdef VERIFY_HEAP |
| 458 void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) { | 461 void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) { |
| 459 PageIterator it(space); | 462 PageIterator it(space); |
| 460 | 463 |
| 461 while (it.has_next()) { | 464 while (it.has_next()) { |
| 462 Page* p = it.next(); | 465 Page* p = it.next(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 488 | 491 |
| 489 LargeObjectIterator it(heap_->lo_space()); | 492 LargeObjectIterator it(heap_->lo_space()); |
| 490 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 493 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
| 491 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 494 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 492 CHECK(Marking::IsWhite(mark_bit)); | 495 CHECK(Marking::IsWhite(mark_bit)); |
| 493 CHECK_EQ(0, Page::FromAddress(obj->address())->LiveBytes()); | 496 CHECK_EQ(0, Page::FromAddress(obj->address())->LiveBytes()); |
| 494 } | 497 } |
| 495 } | 498 } |
| 496 | 499 |
| 497 | 500 |
| 498 void MarkCompactCollector::VerifyWeakEmbeddedMapsInOptimizedCode() { | 501 void MarkCompactCollector::VerifyWeakEmbeddedObjectsInOptimizedCode() { |
| 499 HeapObjectIterator code_iterator(heap()->code_space()); | 502 HeapObjectIterator code_iterator(heap()->code_space()); |
| 500 for (HeapObject* obj = code_iterator.Next(); | 503 for (HeapObject* obj = code_iterator.Next(); |
| 501 obj != NULL; | 504 obj != NULL; |
| 502 obj = code_iterator.Next()) { | 505 obj = code_iterator.Next()) { |
| 503 Code* code = Code::cast(obj); | 506 Code* code = Code::cast(obj); |
| 504 if (code->kind() != Code::OPTIMIZED_FUNCTION) continue; | 507 if (code->kind() != Code::OPTIMIZED_FUNCTION) continue; |
| 505 if (WillBeDeoptimized(code)) continue; | 508 if (WillBeDeoptimized(code)) continue; |
| 506 code->VerifyEmbeddedMapsDependency(); | 509 code->VerifyEmbeddedObjectsDependency(); |
| 507 } | 510 } |
| 508 } | 511 } |
| 509 | 512 |
| 510 | 513 |
| 511 void MarkCompactCollector::VerifyOmittedMapChecks() { | 514 void MarkCompactCollector::VerifyOmittedMapChecks() { |
| 512 HeapObjectIterator iterator(heap()->map_space()); | 515 HeapObjectIterator iterator(heap()->map_space()); |
| 513 for (HeapObject* obj = iterator.Next(); | 516 for (HeapObject* obj = iterator.Next(); |
| 514 obj != NULL; | 517 obj != NULL; |
| 515 obj = iterator.Next()) { | 518 obj = iterator.Next()) { |
| 516 Map* map = Map::cast(obj); | 519 Map* map = Map::cast(obj); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 bool MarkCompactCollector::AreSweeperThreadsActivated() { | 597 bool MarkCompactCollector::AreSweeperThreadsActivated() { |
| 595 return isolate()->sweeper_threads() != NULL; | 598 return isolate()->sweeper_threads() != NULL; |
| 596 } | 599 } |
| 597 | 600 |
| 598 | 601 |
| 599 bool MarkCompactCollector::IsConcurrentSweepingInProgress() { | 602 bool MarkCompactCollector::IsConcurrentSweepingInProgress() { |
| 600 return sweeping_pending_; | 603 return sweeping_pending_; |
| 601 } | 604 } |
| 602 | 605 |
| 603 | 606 |
| 604 void MarkCompactCollector::MarkInParallel() { | |
| 605 for (int i = 0; i < FLAG_marking_threads; i++) { | |
| 606 isolate()->marking_threads()[i]->StartMarking(); | |
| 607 } | |
| 608 } | |
| 609 | |
| 610 | |
| 611 void MarkCompactCollector::WaitUntilMarkingCompleted() { | |
| 612 for (int i = 0; i < FLAG_marking_threads; i++) { | |
| 613 isolate()->marking_threads()[i]->WaitForMarkingThread(); | |
| 614 } | |
| 615 } | |
| 616 | |
| 617 | |
| 618 bool Marking::TransferMark(Address old_start, Address new_start) { | 607 bool Marking::TransferMark(Address old_start, Address new_start) { |
| 619 // This is only used when resizing an object. | 608 // This is only used when resizing an object. |
| 620 ASSERT(MemoryChunk::FromAddress(old_start) == | 609 ASSERT(MemoryChunk::FromAddress(old_start) == |
| 621 MemoryChunk::FromAddress(new_start)); | 610 MemoryChunk::FromAddress(new_start)); |
| 622 | 611 |
| 623 // If the mark doesn't move, we don't check the color of the object. | 612 // If the mark doesn't move, we don't check the color of the object. |
| 624 // It doesn't matter whether the object is black, since it hasn't changed | 613 // It doesn't matter whether the object is black, since it hasn't changed |
| 625 // size, so the adjustment to the live data count will be zero anyway. | 614 // size, so the adjustment to the live data count will be zero anyway. |
| 626 if (old_start == new_start) return false; | 615 if (old_start == new_start) return false; |
| 627 | 616 |
| (...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1474 JSWeakCollection::kTableOffset); | 1463 JSWeakCollection::kTableOffset); |
| 1475 BodyVisitorBase<MarkCompactMarkingVisitor>::IteratePointers( | 1464 BodyVisitorBase<MarkCompactMarkingVisitor>::IteratePointers( |
| 1476 map->GetHeap(), | 1465 map->GetHeap(), |
| 1477 object, | 1466 object, |
| 1478 JSWeakCollection::kTableOffset + kPointerSize, | 1467 JSWeakCollection::kTableOffset + kPointerSize, |
| 1479 object_size); | 1468 object_size); |
| 1480 | 1469 |
| 1481 // Mark the backing hash table without pushing it on the marking stack. | 1470 // Mark the backing hash table without pushing it on the marking stack. |
| 1482 Object* table_object = weak_collection->table(); | 1471 Object* table_object = weak_collection->table(); |
| 1483 if (!table_object->IsHashTable()) return; | 1472 if (!table_object->IsHashTable()) return; |
| 1484 ObjectHashTable* table = ObjectHashTable::cast(table_object); | 1473 WeakHashTable* table = WeakHashTable::cast(table_object); |
| 1485 Object** table_slot = | 1474 Object** table_slot = |
| 1486 HeapObject::RawField(weak_collection, JSWeakCollection::kTableOffset); | 1475 HeapObject::RawField(weak_collection, JSWeakCollection::kTableOffset); |
| 1487 MarkBit table_mark = Marking::MarkBitFrom(table); | 1476 MarkBit table_mark = Marking::MarkBitFrom(table); |
| 1488 collector->RecordSlot(table_slot, table_slot, table); | 1477 collector->RecordSlot(table_slot, table_slot, table); |
| 1489 if (!table_mark.Get()) collector->SetMark(table, table_mark); | 1478 if (!table_mark.Get()) collector->SetMark(table, table_mark); |
| 1490 // Recording the map slot can be skipped, because maps are not compacted. | 1479 // Recording the map slot can be skipped, because maps are not compacted. |
| 1491 collector->MarkObject(table->map(), Marking::MarkBitFrom(table->map())); | 1480 collector->MarkObject(table->map(), Marking::MarkBitFrom(table->map())); |
| 1492 ASSERT(MarkCompactCollector::IsMarked(table->map())); | 1481 ASSERT(MarkCompactCollector::IsMarked(table->map())); |
| 1493 } | 1482 } |
| 1494 | 1483 |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2010 while (current_cell != 0) { | 1999 while (current_cell != 0) { |
| 2011 int trailing_zeros = CompilerIntrinsics::CountTrailingZeros(current_cell); | 2000 int trailing_zeros = CompilerIntrinsics::CountTrailingZeros(current_cell); |
| 2012 current_cell >>= trailing_zeros; | 2001 current_cell >>= trailing_zeros; |
| 2013 offset += trailing_zeros; | 2002 offset += trailing_zeros; |
| 2014 Address address = cell_base + offset * kPointerSize; | 2003 Address address = cell_base + offset * kPointerSize; |
| 2015 HeapObject* object = HeapObject::FromAddress(address); | 2004 HeapObject* object = HeapObject::FromAddress(address); |
| 2016 | 2005 |
| 2017 int size = object->Size(); | 2006 int size = object->Size(); |
| 2018 survivors_size += size; | 2007 survivors_size += size; |
| 2019 | 2008 |
| 2009 if (FLAG_trace_track_allocation_sites && object->IsJSObject()) { |
| 2010 if (AllocationMemento::FindForJSObject(JSObject::cast(object), true) |
| 2011 != NULL) { |
| 2012 heap()->allocation_mementos_found_++; |
| 2013 } |
| 2014 } |
| 2015 |
| 2020 offset++; | 2016 offset++; |
| 2021 current_cell >>= 1; | 2017 current_cell >>= 1; |
| 2022 // Aggressively promote young survivors to the old space. | 2018 // Aggressively promote young survivors to the old space. |
| 2023 if (TryPromoteObject(object, size)) { | 2019 if (TryPromoteObject(object, size)) { |
| 2024 continue; | 2020 continue; |
| 2025 } | 2021 } |
| 2026 | 2022 |
| 2027 // Promotion failed. Just migrate object to another semispace. | 2023 // Promotion failed. Just migrate object to another semispace. |
| 2028 MaybeObject* allocation = new_space->AllocateRaw(size); | 2024 MaybeObject* allocation = new_space->AllocateRaw(size); |
| 2029 if (allocation->IsFailure()) { | 2025 if (allocation->IsFailure()) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2109 | 2105 |
| 2110 | 2106 |
| 2111 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { | 2107 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { |
| 2112 // Mark the heap roots including global variables, stack variables, | 2108 // Mark the heap roots including global variables, stack variables, |
| 2113 // etc., and all objects reachable from them. | 2109 // etc., and all objects reachable from them. |
| 2114 heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG); | 2110 heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG); |
| 2115 | 2111 |
| 2116 // Handle the string table specially. | 2112 // Handle the string table specially. |
| 2117 MarkStringTable(visitor); | 2113 MarkStringTable(visitor); |
| 2118 | 2114 |
| 2115 MarkWeakObjectToCodeTable(); |
| 2116 |
| 2119 // There may be overflowed objects in the heap. Visit them now. | 2117 // There may be overflowed objects in the heap. Visit them now. |
| 2120 while (marking_deque_.overflowed()) { | 2118 while (marking_deque_.overflowed()) { |
| 2121 RefillMarkingDeque(); | 2119 RefillMarkingDeque(); |
| 2122 EmptyMarkingDeque(); | 2120 EmptyMarkingDeque(); |
| 2123 } | 2121 } |
| 2124 } | 2122 } |
| 2125 | 2123 |
| 2126 | 2124 |
| 2127 void MarkCompactCollector::MarkImplicitRefGroups() { | 2125 void MarkCompactCollector::MarkImplicitRefGroups() { |
| 2128 List<ImplicitRefGroup*>* ref_groups = | 2126 List<ImplicitRefGroup*>* ref_groups = |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2149 } | 2147 } |
| 2150 | 2148 |
| 2151 // Once the entire group has been marked, dispose it because it's | 2149 // Once the entire group has been marked, dispose it because it's |
| 2152 // not needed anymore. | 2150 // not needed anymore. |
| 2153 delete entry; | 2151 delete entry; |
| 2154 } | 2152 } |
| 2155 ref_groups->Rewind(last); | 2153 ref_groups->Rewind(last); |
| 2156 } | 2154 } |
| 2157 | 2155 |
| 2158 | 2156 |
| 2157 void MarkCompactCollector::MarkWeakObjectToCodeTable() { |
| 2158 HeapObject* weak_object_to_code_table = |
| 2159 HeapObject::cast(heap()->weak_object_to_code_table()); |
| 2160 if (!IsMarked(weak_object_to_code_table)) { |
| 2161 MarkBit mark = Marking::MarkBitFrom(weak_object_to_code_table); |
| 2162 SetMark(weak_object_to_code_table, mark); |
| 2163 } |
| 2164 } |
| 2165 |
| 2166 |
| 2159 // Mark all objects reachable from the objects on the marking stack. | 2167 // Mark all objects reachable from the objects on the marking stack. |
| 2160 // Before: the marking stack contains zero or more heap object pointers. | 2168 // Before: the marking stack contains zero or more heap object pointers. |
| 2161 // After: the marking stack is empty, and all objects reachable from the | 2169 // After: the marking stack is empty, and all objects reachable from the |
| 2162 // marking stack have been marked, or are overflowed in the heap. | 2170 // marking stack have been marked, or are overflowed in the heap. |
| 2163 void MarkCompactCollector::EmptyMarkingDeque() { | 2171 void MarkCompactCollector::EmptyMarkingDeque() { |
| 2164 while (!marking_deque_.IsEmpty()) { | 2172 while (!marking_deque_.IsEmpty()) { |
| 2165 HeapObject* object = marking_deque_.Pop(); | 2173 HeapObject* object = marking_deque_.Pop(); |
| 2166 ASSERT(object->IsHeapObject()); | 2174 ASSERT(object->IsHeapObject()); |
| 2167 ASSERT(heap()->Contains(object)); | 2175 ASSERT(heap()->Contains(object)); |
| 2168 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(object))); | 2176 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2516 // Since it survived the GC, reattach it now. | 2524 // Since it survived the GC, reattach it now. |
| 2517 JSFunction::cast(map->constructor())->shared()->AttachInitialMap(map); | 2525 JSFunction::cast(map->constructor())->shared()->AttachInitialMap(map); |
| 2518 } | 2526 } |
| 2519 | 2527 |
| 2520 ClearNonLivePrototypeTransitions(map); | 2528 ClearNonLivePrototypeTransitions(map); |
| 2521 ClearNonLiveMapTransitions(map, map_mark); | 2529 ClearNonLiveMapTransitions(map, map_mark); |
| 2522 | 2530 |
| 2523 if (map_mark.Get()) { | 2531 if (map_mark.Get()) { |
| 2524 ClearNonLiveDependentCode(map->dependent_code()); | 2532 ClearNonLiveDependentCode(map->dependent_code()); |
| 2525 } else { | 2533 } else { |
| 2526 ClearAndDeoptimizeDependentCode(map); | 2534 ClearAndDeoptimizeDependentCode(map->dependent_code()); |
| 2535 map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array())); |
| 2527 } | 2536 } |
| 2528 } | 2537 } |
| 2529 | 2538 |
| 2530 // Iterate over property cell space, removing dependent code that is not | 2539 // Iterate over property cell space, removing dependent code that is not |
| 2531 // otherwise kept alive by strong references. | 2540 // otherwise kept alive by strong references. |
| 2532 HeapObjectIterator cell_iterator(heap_->property_cell_space()); | 2541 HeapObjectIterator cell_iterator(heap_->property_cell_space()); |
| 2533 for (HeapObject* cell = cell_iterator.Next(); | 2542 for (HeapObject* cell = cell_iterator.Next(); |
| 2534 cell != NULL; | 2543 cell != NULL; |
| 2535 cell = cell_iterator.Next()) { | 2544 cell = cell_iterator.Next()) { |
| 2536 if (IsMarked(cell)) { | 2545 if (IsMarked(cell)) { |
| 2537 ClearNonLiveDependentCode(PropertyCell::cast(cell)->dependent_code()); | 2546 ClearNonLiveDependentCode(PropertyCell::cast(cell)->dependent_code()); |
| 2538 } | 2547 } |
| 2539 } | 2548 } |
| 2549 |
| 2550 if (heap_->weak_object_to_code_table()->IsHashTable()) { |
| 2551 WeakHashTable* table = |
| 2552 WeakHashTable::cast(heap_->weak_object_to_code_table()); |
| 2553 uint32_t capacity = table->Capacity(); |
| 2554 for (uint32_t i = 0; i < capacity; i++) { |
| 2555 uint32_t key_index = table->EntryToIndex(i); |
| 2556 Object* key = table->get(key_index); |
| 2557 if (!table->IsKey(key)) continue; |
| 2558 uint32_t value_index = table->EntryToValueIndex(i); |
| 2559 Object* value = table->get(value_index); |
| 2560 if (IsMarked(key)) { |
| 2561 if (!IsMarked(value)) { |
| 2562 HeapObject* obj = HeapObject::cast(value); |
| 2563 MarkBit mark = Marking::MarkBitFrom(obj); |
| 2564 SetMark(obj, mark); |
| 2565 } |
| 2566 ClearNonLiveDependentCode(DependentCode::cast(value)); |
| 2567 } else { |
| 2568 ClearAndDeoptimizeDependentCode(DependentCode::cast(value)); |
| 2569 table->set(key_index, heap_->the_hole_value()); |
| 2570 table->set(value_index, heap_->the_hole_value()); |
| 2571 } |
| 2572 } |
| 2573 } |
| 2540 } | 2574 } |
| 2541 | 2575 |
| 2542 | 2576 |
| 2543 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { | 2577 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { |
| 2544 int number_of_transitions = map->NumberOfProtoTransitions(); | 2578 int number_of_transitions = map->NumberOfProtoTransitions(); |
| 2545 FixedArray* prototype_transitions = map->GetPrototypeTransitions(); | 2579 FixedArray* prototype_transitions = map->GetPrototypeTransitions(); |
| 2546 | 2580 |
| 2547 int new_number_of_transitions = 0; | 2581 int new_number_of_transitions = 0; |
| 2548 const int header = Map::kProtoTransitionHeaderSize; | 2582 const int header = Map::kProtoTransitionHeaderSize; |
| 2549 const int proto_offset = header + Map::kProtoTransitionPrototypeOffset; | 2583 const int proto_offset = header + Map::kProtoTransitionPrototypeOffset; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2595 // Follow back pointer, check whether we are dealing with a map transition | 2629 // Follow back pointer, check whether we are dealing with a map transition |
| 2596 // from a live map to a dead path and in case clear transitions of parent. | 2630 // from a live map to a dead path and in case clear transitions of parent. |
| 2597 bool current_is_alive = map_mark.Get(); | 2631 bool current_is_alive = map_mark.Get(); |
| 2598 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); | 2632 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); |
| 2599 if (!current_is_alive && parent_is_alive) { | 2633 if (!current_is_alive && parent_is_alive) { |
| 2600 parent->ClearNonLiveTransitions(heap()); | 2634 parent->ClearNonLiveTransitions(heap()); |
| 2601 } | 2635 } |
| 2602 } | 2636 } |
| 2603 | 2637 |
| 2604 | 2638 |
| 2605 void MarkCompactCollector::ClearAndDeoptimizeDependentCode(Map* map) { | 2639 void MarkCompactCollector::ClearAndDeoptimizeDependentCode( |
| 2640 DependentCode* entries) { |
| 2606 DisallowHeapAllocation no_allocation; | 2641 DisallowHeapAllocation no_allocation; |
| 2607 DependentCode* entries = map->dependent_code(); | |
| 2608 DependentCode::GroupStartIndexes starts(entries); | 2642 DependentCode::GroupStartIndexes starts(entries); |
| 2609 int number_of_entries = starts.number_of_entries(); | 2643 int number_of_entries = starts.number_of_entries(); |
| 2610 if (number_of_entries == 0) return; | 2644 if (number_of_entries == 0) return; |
| 2611 for (int i = 0; i < number_of_entries; i++) { | 2645 for (int i = 0; i < number_of_entries; i++) { |
| 2612 // If the entry is compilation info then the map must be alive, | 2646 // If the entry is compilation info then the map must be alive, |
| 2613 // and ClearAndDeoptimizeDependentCode shouldn't be called. | 2647 // and ClearAndDeoptimizeDependentCode shouldn't be called. |
| 2614 ASSERT(entries->is_code_at(i)); | 2648 ASSERT(entries->is_code_at(i)); |
| 2615 Code* code = entries->code_at(i); | 2649 Code* code = entries->code_at(i); |
| 2616 | 2650 |
| 2617 if (IsMarked(code) && !code->marked_for_deoptimization()) { | 2651 if (IsMarked(code) && !code->marked_for_deoptimization()) { |
| 2618 code->set_marked_for_deoptimization(true); | 2652 code->set_marked_for_deoptimization(true); |
| 2619 have_code_to_deoptimize_ = true; | 2653 have_code_to_deoptimize_ = true; |
| 2620 } | 2654 } |
| 2621 entries->clear_at(i); | 2655 entries->clear_at(i); |
| 2622 } | 2656 } |
| 2623 map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array())); | |
| 2624 } | 2657 } |
| 2625 | 2658 |
| 2626 | 2659 |
| 2627 void MarkCompactCollector::ClearNonLiveDependentCode(DependentCode* entries) { | 2660 void MarkCompactCollector::ClearNonLiveDependentCode(DependentCode* entries) { |
| 2628 DisallowHeapAllocation no_allocation; | 2661 DisallowHeapAllocation no_allocation; |
| 2629 DependentCode::GroupStartIndexes starts(entries); | 2662 DependentCode::GroupStartIndexes starts(entries); |
| 2630 int number_of_entries = starts.number_of_entries(); | 2663 int number_of_entries = starts.number_of_entries(); |
| 2631 if (number_of_entries == 0) return; | 2664 if (number_of_entries == 0) return; |
| 2632 int new_number_of_entries = 0; | 2665 int new_number_of_entries = 0; |
| 2633 // Go through all groups, remove dead codes and compact. | 2666 // Go through all groups, remove dead codes and compact. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2720 // to encounter pointers to dead new space objects during traversal of pointers | 2753 // to encounter pointers to dead new space objects during traversal of pointers |
| 2721 // to new space. We should clear them to avoid encountering them during next | 2754 // to new space. We should clear them to avoid encountering them during next |
| 2722 // pointer iteration. This is an issue if the store buffer overflows and we | 2755 // pointer iteration. This is an issue if the store buffer overflows and we |
| 2723 // have to scan the entire old space, including dead objects, looking for | 2756 // have to scan the entire old space, including dead objects, looking for |
| 2724 // pointers to new space. | 2757 // pointers to new space. |
| 2725 void MarkCompactCollector::MigrateObject(Address dst, | 2758 void MarkCompactCollector::MigrateObject(Address dst, |
| 2726 Address src, | 2759 Address src, |
| 2727 int size, | 2760 int size, |
| 2728 AllocationSpace dest) { | 2761 AllocationSpace dest) { |
| 2729 HEAP_PROFILE(heap(), ObjectMoveEvent(src, dst)); | 2762 HEAP_PROFILE(heap(), ObjectMoveEvent(src, dst)); |
| 2730 // TODO(hpayer): Replace these checks with asserts. | 2763 ASSERT(heap()->AllowedToBeMigrated(HeapObject::FromAddress(src), dest)); |
| 2731 CHECK(heap()->AllowedToBeMigrated(HeapObject::FromAddress(src), dest)); | 2764 ASSERT(dest != LO_SPACE && size <= Page::kMaxNonCodeHeapObjectSize); |
| 2732 CHECK(dest != LO_SPACE && size <= Page::kMaxNonCodeHeapObjectSize); | |
| 2733 if (dest == OLD_POINTER_SPACE) { | 2765 if (dest == OLD_POINTER_SPACE) { |
| 2734 Address src_slot = src; | 2766 Address src_slot = src; |
| 2735 Address dst_slot = dst; | 2767 Address dst_slot = dst; |
| 2736 ASSERT(IsAligned(size, kPointerSize)); | 2768 ASSERT(IsAligned(size, kPointerSize)); |
| 2737 | 2769 |
| 2738 for (int remaining = size / kPointerSize; remaining > 0; remaining--) { | 2770 for (int remaining = size / kPointerSize; remaining > 0; remaining--) { |
| 2739 Object* value = Memory::Object_at(src_slot); | 2771 Object* value = Memory::Object_at(src_slot); |
| 2740 | 2772 |
| 2741 Memory::Object_at(dst_slot) = value; | 2773 Memory::Object_at(dst_slot) = value; |
| 2742 | 2774 |
| (...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3452 cell = js_global_property_cell_iterator.Next()) { | 3484 cell = js_global_property_cell_iterator.Next()) { |
| 3453 if (cell->IsPropertyCell()) { | 3485 if (cell->IsPropertyCell()) { |
| 3454 PropertyCell::BodyDescriptor::IterateBody(cell, &updating_visitor); | 3486 PropertyCell::BodyDescriptor::IterateBody(cell, &updating_visitor); |
| 3455 } | 3487 } |
| 3456 } | 3488 } |
| 3457 | 3489 |
| 3458 // Update the head of the native contexts list in the heap. | 3490 // Update the head of the native contexts list in the heap. |
| 3459 updating_visitor.VisitPointer(heap_->native_contexts_list_address()); | 3491 updating_visitor.VisitPointer(heap_->native_contexts_list_address()); |
| 3460 | 3492 |
| 3461 heap_->string_table()->Iterate(&updating_visitor); | 3493 heap_->string_table()->Iterate(&updating_visitor); |
| 3494 updating_visitor.VisitPointer(heap_->weak_object_to_code_table_address()); |
| 3495 if (heap_->weak_object_to_code_table()->IsHashTable()) { |
| 3496 WeakHashTable* table = |
| 3497 WeakHashTable::cast(heap_->weak_object_to_code_table()); |
| 3498 table->Iterate(&updating_visitor); |
| 3499 table->Rehash(heap_->undefined_value()); |
| 3500 } |
| 3462 | 3501 |
| 3463 // Update pointers from external string table. | 3502 // Update pointers from external string table. |
| 3464 heap_->UpdateReferencesInExternalStringTable( | 3503 heap_->UpdateReferencesInExternalStringTable( |
| 3465 &UpdateReferenceInExternalStringTableEntry); | 3504 &UpdateReferenceInExternalStringTableEntry); |
| 3466 | 3505 |
| 3467 if (!FLAG_watch_ic_patching) { | 3506 if (!FLAG_watch_ic_patching) { |
| 3468 // Update JSFunction pointers from the runtime profiler. | 3507 // Update JSFunction pointers from the runtime profiler. |
| 3469 heap()->isolate()->runtime_profiler()->UpdateSamplesAfterCompact( | 3508 heap()->isolate()->runtime_profiler()->UpdateSamplesAfterCompact( |
| 3470 &updating_visitor); | 3509 &updating_visitor); |
| 3471 } | 3510 } |
| (...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4315 while (buffer != NULL) { | 4354 while (buffer != NULL) { |
| 4316 SlotsBuffer* next_buffer = buffer->next(); | 4355 SlotsBuffer* next_buffer = buffer->next(); |
| 4317 DeallocateBuffer(buffer); | 4356 DeallocateBuffer(buffer); |
| 4318 buffer = next_buffer; | 4357 buffer = next_buffer; |
| 4319 } | 4358 } |
| 4320 *buffer_address = NULL; | 4359 *buffer_address = NULL; |
| 4321 } | 4360 } |
| 4322 | 4361 |
| 4323 | 4362 |
| 4324 } } // namespace v8::internal | 4363 } } // namespace v8::internal |
| OLD | NEW |