| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 // Tell the tracer. | 75 // Tell the tracer. |
| 76 if (IsCompacting()) tracer_->set_is_compacting(); | 76 if (IsCompacting()) tracer_->set_is_compacting(); |
| 77 | 77 |
| 78 MarkLiveObjects(); | 78 MarkLiveObjects(); |
| 79 | 79 |
| 80 if (FLAG_collect_maps) ClearNonLiveTransitions(); | 80 if (FLAG_collect_maps) ClearNonLiveTransitions(); |
| 81 | 81 |
| 82 SweepLargeObjectSpace(); | 82 SweepLargeObjectSpace(); |
| 83 | 83 |
| 84 if (IsCompacting()) { | 84 if (IsCompacting()) { |
| 85 #ifndef BASELINE_GC |
| 85 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_COMPACT); | 86 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_COMPACT); |
| 86 EncodeForwardingAddresses(); | 87 EncodeForwardingAddresses(); |
| 87 | 88 |
| 88 Heap::MarkMapPointersAsEncoded(true); | 89 Heap::MarkMapPointersAsEncoded(true); |
| 89 UpdatePointers(); | 90 UpdatePointers(); |
| 90 Heap::MarkMapPointersAsEncoded(false); | 91 Heap::MarkMapPointersAsEncoded(false); |
| 91 PcToCodeCache::FlushPcToCodeCache(); | 92 PcToCodeCache::FlushPcToCodeCache(); |
| 92 | 93 |
| 93 RelocateObjects(); | 94 RelocateObjects(); |
| 95 #else |
| 96 UNREACHABLE(); |
| 97 #endif |
| 94 } else { | 98 } else { |
| 95 SweepSpaces(); | 99 SweepSpaces(); |
| 96 PcToCodeCache::FlushPcToCodeCache(); | 100 PcToCodeCache::FlushPcToCodeCache(); |
| 97 } | 101 } |
| 98 | 102 |
| 99 Finish(); | 103 Finish(); |
| 100 | 104 |
| 101 // Save the count of marked objects remaining after the collection and | 105 // Save the count of marked objects remaining after the collection and |
| 102 // null out the GC tracer. | 106 // null out the GC tracer. |
| 103 previous_marked_count_ = tracer_->marked_count(); | 107 previous_marked_count_ = tracer_->marked_count(); |
| 104 ASSERT(previous_marked_count_ == 0); | 108 ASSERT(previous_marked_count_ == 0); |
| 105 tracer_ = NULL; | 109 tracer_ = NULL; |
| 106 } | 110 } |
| 107 | 111 |
| 108 | 112 |
| 109 void MarkCompactCollector::Prepare(GCTracer* tracer) { | 113 void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| 114 #ifdef BASELINE_GC |
| 115 FLAG_flush_code = false; |
| 116 FLAG_always_compact = false; |
| 117 FLAG_never_compact = true; |
| 118 #endif |
| 119 |
| 110 // Rather than passing the tracer around we stash it in a static member | 120 // Rather than passing the tracer around we stash it in a static member |
| 111 // variable. | 121 // variable. |
| 112 tracer_ = tracer; | 122 tracer_ = tracer; |
| 113 | 123 |
| 114 #ifdef DEBUG | 124 #ifdef DEBUG |
| 115 ASSERT(state_ == IDLE); | 125 ASSERT(state_ == IDLE); |
| 116 state_ = PREPARE_GC; | 126 state_ = PREPARE_GC; |
| 117 #endif | 127 #endif |
| 118 ASSERT(!FLAG_always_compact || !FLAG_never_compact); | 128 ASSERT(!FLAG_always_compact || !FLAG_never_compact); |
| 119 | 129 |
| (...skipping 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 // to mark free regions larger than one word, and the size of the free | 1475 // to mark free regions larger than one word, and the size of the free |
| 1466 // region (including the first word) is written to the second word of the | 1476 // region (including the first word) is written to the second word of the |
| 1467 // region. | 1477 // region. |
| 1468 // | 1478 // |
| 1469 // Any valid map page offset must lie in the object area of the page, so map | 1479 // Any valid map page offset must lie in the object area of the page, so map |
| 1470 // page offsets less than Page::kObjectStartOffset are invalid. We use a | 1480 // page offsets less than Page::kObjectStartOffset are invalid. We use a |
| 1471 // pair of distinguished invalid map encodings (for single word and multiple | 1481 // pair of distinguished invalid map encodings (for single word and multiple |
| 1472 // words) to indicate free regions in the page found during computation of | 1482 // words) to indicate free regions in the page found during computation of |
| 1473 // forwarding addresses and skipped over in subsequent sweeps. | 1483 // forwarding addresses and skipped over in subsequent sweeps. |
| 1474 | 1484 |
| 1475 | 1485 #ifndef BASELINE_GC |
| 1476 // Encode a free region, defined by the given start address and size, in the | 1486 // Encode a free region, defined by the given start address and size, in the |
| 1477 // first word or two of the region. | 1487 // first word or two of the region. |
| 1478 void EncodeFreeRegion(Address free_start, int free_size) { | 1488 void EncodeFreeRegion(Address free_start, int free_size) { |
| 1479 ASSERT(free_size >= kIntSize); | 1489 ASSERT(free_size >= kIntSize); |
| 1480 if (free_size == kIntSize) { | 1490 if (free_size == kIntSize) { |
| 1481 Memory::uint32_at(free_start) = MarkCompactCollector::kSingleFreeEncoding; | 1491 Memory::uint32_at(free_start) = MarkCompactCollector::kSingleFreeEncoding; |
| 1482 } else { | 1492 } else { |
| 1483 ASSERT(free_size >= 2 * kIntSize); | 1493 ASSERT(free_size >= 2 * kIntSize); |
| 1484 Memory::uint32_at(free_start) = MarkCompactCollector::kMultiFreeEncoding; | 1494 Memory::uint32_at(free_start) = MarkCompactCollector::kMultiFreeEncoding; |
| 1485 Memory::int_at(free_start + kIntSize) = free_size; | 1495 Memory::int_at(free_start + kIntSize) = free_size; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1682 // in the page. | 1692 // in the page. |
| 1683 int offset = 0; | 1693 int offset = 0; |
| 1684 EncodeForwardingAddressesInRange<Alloc, | 1694 EncodeForwardingAddressesInRange<Alloc, |
| 1685 EncodeForwardingAddressInPagedSpace, | 1695 EncodeForwardingAddressInPagedSpace, |
| 1686 ProcessNonLive>( | 1696 ProcessNonLive>( |
| 1687 p->ObjectAreaStart(), | 1697 p->ObjectAreaStart(), |
| 1688 p->AllocationTop(), | 1698 p->AllocationTop(), |
| 1689 &offset); | 1699 &offset); |
| 1690 } | 1700 } |
| 1691 } | 1701 } |
| 1692 | 1702 #endif |
| 1693 | 1703 |
| 1694 // We scavange new space simultaneously with sweeping. This is done in two | 1704 // We scavange new space simultaneously with sweeping. This is done in two |
| 1695 // passes. | 1705 // passes. |
| 1696 // The first pass migrates all alive objects from one semispace to another or | 1706 // The first pass migrates all alive objects from one semispace to another or |
| 1697 // promotes them to old space. Forwading address is written directly into | 1707 // promotes them to old space. Forwading address is written directly into |
| 1698 // first word of object without any encoding. If object is dead we are writing | 1708 // first word of object without any encoding. If object is dead we are writing |
| 1699 // NULL as a forwarding address. | 1709 // NULL as a forwarding address. |
| 1700 // The second pass updates pointers to new space in all spaces. It is possible | 1710 // The second pass updates pointers to new space in all spaces. It is possible |
| 1701 // to encounter pointers to dead objects during traversal of dirty regions we | 1711 // to encounter pointers to dead objects during traversal of dirty regions we |
| 1702 // should clear them to avoid encountering them during next dirty regions | 1712 // should clear them to avoid encountering them during next dirty regions |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2055 ASSERT(new_allocation_top_page == prec_first_empty_page); | 2065 ASSERT(new_allocation_top_page == prec_first_empty_page); |
| 2056 } else { | 2066 } else { |
| 2057 ASSERT(new_allocation_top_page == first_empty_page); | 2067 ASSERT(new_allocation_top_page == first_empty_page); |
| 2058 } | 2068 } |
| 2059 #endif | 2069 #endif |
| 2060 | 2070 |
| 2061 space->SetTop(new_allocation_top); | 2071 space->SetTop(new_allocation_top); |
| 2062 } | 2072 } |
| 2063 } | 2073 } |
| 2064 | 2074 |
| 2065 | 2075 #ifndef BASELINE_GC |
| 2066 void MarkCompactCollector::EncodeForwardingAddresses() { | 2076 void MarkCompactCollector::EncodeForwardingAddresses() { |
| 2067 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); | 2077 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); |
| 2068 // Objects in the active semispace of the young generation may be | 2078 // Objects in the active semispace of the young generation may be |
| 2069 // relocated to the inactive semispace (if not promoted). Set the | 2079 // relocated to the inactive semispace (if not promoted). Set the |
| 2070 // relocation info to the beginning of the inactive semispace. | 2080 // relocation info to the beginning of the inactive semispace. |
| 2071 Heap::new_space()->MCResetRelocationInfo(); | 2081 Heap::new_space()->MCResetRelocationInfo(); |
| 2072 | 2082 |
| 2073 // Compute the forwarding pointers in each space. | 2083 // Compute the forwarding pointers in each space. |
| 2074 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace, | 2084 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace, |
| 2075 ReportDeleteIfNeeded>( | 2085 ReportDeleteIfNeeded>( |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2310 return; | 2320 return; |
| 2311 | 2321 |
| 2312 for (HeapObject* obj = map_to_evacuate_it_.next(); | 2322 for (HeapObject* obj = map_to_evacuate_it_.next(); |
| 2313 obj != NULL; obj = map_to_evacuate_it_.next()) | 2323 obj != NULL; obj = map_to_evacuate_it_.next()) |
| 2314 ASSERT(FreeListNode::IsFreeListNode(obj)); | 2324 ASSERT(FreeListNode::IsFreeListNode(obj)); |
| 2315 } | 2325 } |
| 2316 #endif | 2326 #endif |
| 2317 }; | 2327 }; |
| 2318 | 2328 |
| 2319 MapCompact::MapUpdatingVisitor MapCompact::map_updating_visitor_; | 2329 MapCompact::MapUpdatingVisitor MapCompact::map_updating_visitor_; |
| 2320 | 2330 #endif |
| 2321 | 2331 |
| 2322 void MarkCompactCollector::SweepSpaces() { | 2332 void MarkCompactCollector::SweepSpaces() { |
| 2323 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); | 2333 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); |
| 2324 | 2334 |
| 2325 ASSERT(state_ == SWEEP_SPACES); | 2335 ASSERT(state_ == SWEEP_SPACES); |
| 2326 ASSERT(!IsCompacting()); | 2336 ASSERT(!IsCompacting()); |
| 2327 // Noncompacting collections simply sweep the spaces to clear the mark | 2337 // Noncompacting collections simply sweep the spaces to clear the mark |
| 2328 // bits and free the nonlive blocks (for old and map spaces). We sweep | 2338 // bits and free the nonlive blocks (for old and map spaces). We sweep |
| 2329 // the map space last because freeing non-live maps overwrites them and | 2339 // the map space last because freeing non-live maps overwrites them and |
| 2330 // the other spaces rely on possibly non-live maps to get the sizes for | 2340 // the other spaces rely on possibly non-live maps to get the sizes for |
| 2331 // non-live objects. | 2341 // non-live objects. |
| 2332 SweepSpace(Heap::old_pointer_space()); | 2342 SweepSpace(Heap::old_pointer_space()); |
| 2333 SweepSpace(Heap::old_data_space()); | 2343 SweepSpace(Heap::old_data_space()); |
| 2334 SweepSpace(Heap::code_space()); | 2344 SweepSpace(Heap::code_space()); |
| 2335 SweepSpace(Heap::cell_space()); | 2345 SweepSpace(Heap::cell_space()); |
| 2336 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); | 2346 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); |
| 2337 SweepNewSpace(Heap::new_space()); | 2347 SweepNewSpace(Heap::new_space()); |
| 2338 } | 2348 } |
| 2339 SweepSpace(Heap::map_space()); | 2349 SweepSpace(Heap::map_space()); |
| 2340 | 2350 |
| 2341 Heap::IterateDirtyRegions(Heap::map_space(), | 2351 Heap::IterateDirtyRegions(Heap::map_space(), |
| 2342 &Heap::IteratePointersInDirtyMapsRegion, | 2352 &Heap::IteratePointersInDirtyMapsRegion, |
| 2343 &UpdatePointerToNewGen, | 2353 &UpdatePointerToNewGen, |
| 2344 Heap::WATERMARK_SHOULD_BE_VALID); | 2354 Heap::WATERMARK_SHOULD_BE_VALID); |
| 2345 | 2355 |
| 2346 intptr_t live_maps_size = Heap::map_space()->Size(); | 2356 intptr_t live_maps_size = Heap::map_space()->Size(); |
| 2347 int live_maps = static_cast<int>(live_maps_size / Map::kSize); | 2357 int live_maps = static_cast<int>(live_maps_size / Map::kSize); |
| 2348 ASSERT(live_map_objects_size_ == live_maps_size); | 2358 ASSERT(live_map_objects_size_ == live_maps_size); |
| 2349 | 2359 |
| 2360 #ifndef BASELINE_GC |
| 2350 if (Heap::map_space()->NeedsCompaction(live_maps)) { | 2361 if (Heap::map_space()->NeedsCompaction(live_maps)) { |
| 2351 MapCompact map_compact(live_maps); | 2362 MapCompact map_compact(live_maps); |
| 2352 | 2363 |
| 2353 map_compact.CompactMaps(); | 2364 map_compact.CompactMaps(); |
| 2354 map_compact.UpdateMapPointersInRoots(); | 2365 map_compact.UpdateMapPointersInRoots(); |
| 2355 | 2366 |
| 2356 PagedSpaces spaces; | 2367 PagedSpaces spaces; |
| 2357 for (PagedSpace* space = spaces.next(); | 2368 for (PagedSpace* space = spaces.next(); |
| 2358 space != NULL; space = spaces.next()) { | 2369 space != NULL; space = spaces.next()) { |
| 2359 if (space == Heap::map_space()) continue; | 2370 if (space == Heap::map_space()) continue; |
| 2360 map_compact.UpdateMapPointersInPagedSpace(space); | 2371 map_compact.UpdateMapPointersInPagedSpace(space); |
| 2361 } | 2372 } |
| 2362 map_compact.UpdateMapPointersInNewSpace(); | 2373 map_compact.UpdateMapPointersInNewSpace(); |
| 2363 map_compact.UpdateMapPointersInLargeObjectSpace(); | 2374 map_compact.UpdateMapPointersInLargeObjectSpace(); |
| 2364 | 2375 |
| 2365 map_compact.Finish(); | 2376 map_compact.Finish(); |
| 2366 } | 2377 } |
| 2378 #else |
| 2379 USE(live_maps); |
| 2380 #endif |
| 2367 } | 2381 } |
| 2368 | 2382 |
| 2369 | 2383 |
| 2370 // Iterate the live objects in a range of addresses (eg, a page or a | 2384 // Iterate the live objects in a range of addresses (eg, a page or a |
| 2371 // semispace). The live regions of the range have been linked into a list. | 2385 // semispace). The live regions of the range have been linked into a list. |
| 2372 // The first live region is [first_live_start, first_live_end), and the last | 2386 // The first live region is [first_live_start, first_live_end), and the last |
| 2373 // address in the range is top. The callback function is used to get the | 2387 // address in the range is top. The callback function is used to get the |
| 2374 // size of each live object. | 2388 // size of each live object. |
| 2375 int MarkCompactCollector::IterateLiveObjectsInRange( | 2389 int MarkCompactCollector::IterateLiveObjectsInRange( |
| 2376 Address start, | 2390 Address start, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2409 while (it.has_next()) { | 2423 while (it.has_next()) { |
| 2410 Page* p = it.next(); | 2424 Page* p = it.next(); |
| 2411 total += IterateLiveObjectsInRange(p->ObjectAreaStart(), | 2425 total += IterateLiveObjectsInRange(p->ObjectAreaStart(), |
| 2412 p->AllocationTop(), | 2426 p->AllocationTop(), |
| 2413 size_f); | 2427 size_f); |
| 2414 } | 2428 } |
| 2415 return total; | 2429 return total; |
| 2416 } | 2430 } |
| 2417 | 2431 |
| 2418 | 2432 |
| 2433 #ifndef BASELINE_GC |
| 2419 // ------------------------------------------------------------------------- | 2434 // ------------------------------------------------------------------------- |
| 2420 // Phase 3: Update pointers | 2435 // Phase 3: Update pointers |
| 2421 | 2436 |
| 2422 // Helper class for updating pointers in HeapObjects. | 2437 // Helper class for updating pointers in HeapObjects. |
| 2423 class UpdatingVisitor: public ObjectVisitor { | 2438 class UpdatingVisitor: public ObjectVisitor { |
| 2424 public: | 2439 public: |
| 2425 void VisitPointer(Object** p) { | 2440 void VisitPointer(Object** p) { |
| 2426 UpdatePointer(p); | 2441 UpdatePointer(p); |
| 2427 } | 2442 } |
| 2428 | 2443 |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2891 | 2906 |
| 2892 HeapObject* copied_to = HeapObject::FromAddress(new_addr); | 2907 HeapObject* copied_to = HeapObject::FromAddress(new_addr); |
| 2893 if (copied_to->IsJSFunction()) { | 2908 if (copied_to->IsJSFunction()) { |
| 2894 PROFILE(FunctionMoveEvent(old_addr, new_addr)); | 2909 PROFILE(FunctionMoveEvent(old_addr, new_addr)); |
| 2895 PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to))); | 2910 PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to))); |
| 2896 } | 2911 } |
| 2897 HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr)); | 2912 HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr)); |
| 2898 | 2913 |
| 2899 return obj_size; | 2914 return obj_size; |
| 2900 } | 2915 } |
| 2916 #endif |
| 2901 | 2917 |
| 2902 | 2918 |
| 2903 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) { | 2919 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) { |
| 2904 #ifdef ENABLE_LOGGING_AND_PROFILING | 2920 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 2905 if (obj->IsCode()) { | 2921 if (obj->IsCode()) { |
| 2906 PROFILE(CodeDeleteEvent(obj->address())); | 2922 PROFILE(CodeDeleteEvent(obj->address())); |
| 2907 } else if (obj->IsJSFunction()) { | 2923 } else if (obj->IsJSFunction()) { |
| 2908 PROFILE(FunctionDeleteEvent(obj->address())); | 2924 PROFILE(FunctionDeleteEvent(obj->address())); |
| 2909 } | 2925 } |
| 2910 #endif | 2926 #endif |
| 2911 } | 2927 } |
| 2912 | 2928 |
| 2913 | 2929 |
| 2914 int MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) { | 2930 int MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) { |
| 2915 MapWord map_word = obj->map_word(); | 2931 MapWord map_word = obj->map_word(); |
| 2916 map_word.ClearMark(); | 2932 map_word.ClearMark(); |
| 2917 return obj->SizeFromMap(map_word.ToMap()); | 2933 return obj->SizeFromMap(map_word.ToMap()); |
| 2918 } | 2934 } |
| 2919 | 2935 |
| 2920 | 2936 |
| 2921 void MarkCompactCollector::Initialize() { | 2937 void MarkCompactCollector::Initialize() { |
| 2922 StaticPointersToNewGenUpdatingVisitor::Initialize(); | 2938 StaticPointersToNewGenUpdatingVisitor::Initialize(); |
| 2923 StaticMarkingVisitor::Initialize(); | 2939 StaticMarkingVisitor::Initialize(); |
| 2924 } | 2940 } |
| 2925 | 2941 |
| 2926 | 2942 |
| 2927 } } // namespace v8::internal | 2943 } } // namespace v8::internal |
| OLD | NEW |