mark-compact.cc revision e46be819fca9468a0cd4e74859ce0f778eb8ca60
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "execution.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "global-handles.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "mark-compact.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------- 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MarkCompactCollector 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool MarkCompactCollector::force_compaction_ = false; 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool MarkCompactCollector::compacting_collection_ = false; 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool MarkCompactCollector::compact_on_next_gc_ = false; 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::previous_marked_count_ = 0; 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockGCTracer* MarkCompactCollector::tracer_ = NULL; 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMarkCompactCollector::CollectorState MarkCompactCollector::state_ = IDLE; 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Counters used for debugging the marking phase of mark-compact or mark-sweep 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// collection. 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::live_bytes_ = 0; 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::live_young_objects_ = 0; 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::live_old_data_objects_ = 0; 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::live_old_pointer_objects_ = 0; 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::live_code_objects_ = 0; 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::live_map_objects_ = 0; 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::live_cell_objects_ = 0; 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::live_lo_objects_ = 0; 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::CollectGarbage() { 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that Prepare() has been called. The individual steps below will 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // update the state as they proceed. 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == PREPARE_GC); 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Prepare has selected whether to compact the old generation or not. 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tell the tracer. 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (IsCompacting()) tracer_->set_is_compacting(); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkLiveObjects(); 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_collect_maps) ClearNonLiveTransitions(); 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SweepLargeObjectSpace(); 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (IsCompacting()) { 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddresses(); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdatePointers(); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocateObjects(); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RebuildRSets(); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SweepSpaces(); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Finish(); 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the count of marked objects remaining after the collection and 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // null out the GC tracer. 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block previous_marked_count_ = tracer_->marked_count(); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(previous_marked_count_ == 0); 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tracer_ = NULL; 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::Prepare(GCTracer* tracer) { 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Rather than passing the tracer around we stash it in a static member 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // variable. 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tracer_ = tracer; 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == IDLE); 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = PREPARE_GC; 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!FLAG_always_compact || !FLAG_never_compact); 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block compacting_collection_ = 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FLAG_always_compact || force_compaction_ || compact_on_next_gc_; 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block compact_on_next_gc_ = false; 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_never_compact) compacting_collection_ = false; 119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!Heap::map_space()->MapPointersEncodable()) 120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke compacting_collection_ = false; 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_collect_maps) CreateBackPointers(); 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (compacting_collection_) { 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We will write bookkeeping information to the remembered set area 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // starting now. 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page::set_rset_state(Page::NOT_IN_USE); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PagedSpaces spaces; 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (PagedSpace* space = spaces.next()) { 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block space->PrepareForMarkCompact(compacting_collection_); 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_bytes_ = 0; 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_young_objects_ = 0; 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_old_pointer_objects_ = 0; 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_old_data_objects_ = 0; 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_code_objects_ = 0; 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_map_objects_ = 0; 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_cell_objects_ = 0; 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_lo_objects_ = 0; 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::Finish() { 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == SWEEP_SPACES || state_ == REBUILD_RSETS); 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = IDLE; 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The stub cache is not traversed during GC; clear the cache to 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // force lazy re-initialization of it. This must be done after the 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GC, because it relies on the new address of certain old space 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // objects (empty string, illegal builtin). 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::Clear(); 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalStringTable::CleanUp(); 161e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we've just compacted old space there's no reason to check the 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // fragmentation limit. Just return. 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (HasCompacted()) return; 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We compact the old generation on the next GC if it has gotten too 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // fragmented (ie, we could recover an expected amount of space by 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // reclaiming the waste and free list blocks). 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kFragmentationLimit = 15; // Percent. 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kFragmentationAllowed = 1 * MB; // Absolute. 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int old_gen_recoverable = 0; 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int old_gen_used = 0; 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OldSpaces spaces; 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (OldSpace* space = spaces.next()) { 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block old_gen_recoverable += space->Waste() + space->AvailableFree(); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block old_gen_used += space->Size(); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int old_gen_fragmentation = 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<int>((old_gen_recoverable * 100.0) / old_gen_used); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (old_gen_fragmentation > kFragmentationLimit && 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block old_gen_recoverable > kFragmentationAllowed) { 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block compact_on_next_gc_ = true; 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------- 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 1: tracing and marking live objects. 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// before: all objects are in normal state. 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// after: a live object's map pointer is marked as '00'. 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Marking all live objects in the heap as part of mark-sweep or mark-compact 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// collection. Before marking, all objects are in their normal state. After 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// marking, live objects' map pointers are marked indicating that the object 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// has been found reachable. 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The marking algorithm is a (mostly) depth-first (because of possible stack 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overflow) traversal of the graph of objects reachable from the roots. It 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// uses an explicit stack of pointers rather than recursion. The young 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// generation's inactive ('from') space is used as a marking stack. The 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// objects in the marking stack are the ones that have been reached and marked 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// but their children have not yet been visited. 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The marking stack can overflow during traversal. In that case, we set an 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overflow flag. When the overflow flag is set, we continue marking objects 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// reachable from the objects on the marking stack, but no longer push them on 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the marking stack. Instead, we mark them as both marked and overflowed. 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// When the stack is in the overflowed state, objects marked as overflowed 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// have been reached and marked but their children have not been visited yet. 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// After emptying the marking stack, we clear the overflow flag and traverse 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the heap looking for objects marked as overflowed, push them on the stack, 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and continue with marking. This process repeats until all reachable 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// objects have been marked. 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic MarkingStack marking_stack; 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline HeapObject* ShortCircuitConsString(Object** p) { 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Optimization: If the heap object pointed to by p is a non-symbol 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // cons string whose right substring is Heap::empty_string, update 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // it in place to its left substring. Return the updated value. 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Here we assume that if we change *p, we replace it with a heap object 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (ie, the left substring of a cons string is always a heap object). 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The check performed is: 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object->IsConsString() && !object->IsSymbol() && 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (ConsString::cast(object)->second() == Heap::empty_string()) 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // except the maps for the object and its possible substrings might be 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // marked. 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* object = HeapObject::cast(*p); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord map_word = object->map_word(); 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map_word.ClearMark(); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type = map_word.ToMap()->instance_type(); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((type & kShortcutTypeMask) != kShortcutTypeTag) return object; 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* second = reinterpret_cast<ConsString*>(object)->unchecked_second(); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (second != Heap::raw_unchecked_empty_string()) { 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return object; 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Since we don't have the object's start, it is impossible to update the 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // remembered set. Therefore, we only replace the string with its left 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // substring when the remembered set does not change. 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first(); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!Heap::InNewSpace(object) && Heap::InNewSpace(first)) return object; 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *p = first; 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return HeapObject::cast(first); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class for marking pointers in HeapObjects. 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MarkingVisitor : public ObjectVisitor { 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void VisitPointer(Object** p) { 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkObjectByPointer(p); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void VisitPointers(Object** start, Object** end) { 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark all objects pointed to in [start, end). 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kMinRangeForMarkingRecursion = 64; 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (end - start >= kMinRangeForMarkingRecursion) { 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (VisitUnmarkedObjects(start, end)) return; 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We are close to a stack overflow, so just mark the objects. 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Object** p = start; p < end; p++) MarkObjectByPointer(p); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void VisitCodeTarget(RelocInfo* rinfo) { 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Code::GetCodeFromTargetAddress(rinfo->target_address()); 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_cleanup_ics_at_gc && code->is_inline_cache_stub()) { 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IC::Clear(rinfo->pc()); 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Please note targets for cleared inline cached do not have to be 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // marked since they are contained in Heap::non_monomorphic_cache(). 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::MarkObject(code); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void VisitDebugTarget(RelocInfo* rinfo) { 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) && 2863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block rinfo->IsPatchedReturnSequence()); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* code = Code::GetCodeFromTargetAddress(rinfo->call_address()); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::MarkObject(code); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark object pointed to by p. 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void MarkObjectByPointer(Object** p) { 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!(*p)->IsHeapObject()) return; 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* object = ShortCircuitConsString(p); 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::MarkObject(object); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tells whether the mark sweep collection will perform compaction. 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsCompacting() { return MarkCompactCollector::IsCompacting(); } 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Visit an unmarked object. 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void VisitUnmarkedObject(HeapObject* obj) { 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::Contains(obj)); 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!obj->IsMarked()); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* map = obj->map(); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::SetMark(obj); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark the map pointer and the body. 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::MarkObject(map); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj->IterateBody(map->instance_type(), obj->SizeFromMap(map), this); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Visit all unmarked objects pointed to by [start, end). 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns false if the operation fails (lack of stack space). 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline bool VisitUnmarkedObjects(Object** start, Object** end) { 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return false is we are close to the stack limit. 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackLimitCheck check; 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check.HasOverflowed()) return false; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Visit the unmarked objects. 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Object** p = start; p < end; p++) { 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!(*p)->IsHeapObject()) continue; 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* obj = HeapObject::cast(*p); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (obj->IsMarked()) continue; 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block VisitUnmarkedObject(obj); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Visitor class for marking heap roots. 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RootMarkingVisitor : public ObjectVisitor { 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void VisitPointer(Object** p) { 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkObjectByPointer(p); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void VisitPointers(Object** start, Object** end) { 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Object** p = start; p < end; p++) MarkObjectByPointer(p); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkingVisitor* stack_visitor() { return &stack_visitor_; } 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkingVisitor stack_visitor_; 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void MarkObjectByPointer(Object** p) { 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!(*p)->IsHeapObject()) return; 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Replace flat cons strings in place. 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* object = ShortCircuitConsString(p); 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsMarked()) return; 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* map = object->map(); 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark the object. 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::SetMark(object); 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark the map pointer and body, and push them on the marking stack. 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::MarkObject(map); 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object->IterateBody(map->instance_type(), object->SizeFromMap(map), 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &stack_visitor_); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark all the objects reachable from the map and body. May leave 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // overflowed objects in the heap. 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::EmptyMarkingStack(&stack_visitor_); 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class for pruning the symbol table. 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SymbolTableCleaner : public ObjectVisitor { 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SymbolTableCleaner() : pointers_removed_(0) { } 376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke virtual void VisitPointers(Object** start, Object** end) { 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Visit all HeapObject pointers in [start, end). 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Object** p = start; p < end; p++) { 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked()) { 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the symbol being pruned is an external symbol. We need to 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // delete the associated external data as this symbol is going away. 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Since no objects have yet been moved we can safely access the map of 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the object. 386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if ((*p)->IsExternalString()) { 387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Heap::FinalizeExternalString(String::cast(*p)); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the entry to null_value (as deleted). 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *p = Heap::raw_unchecked_null_value(); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pointers_removed_++; 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PointersRemoved() { 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return pointers_removed_; 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int pointers_removed_; 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) { 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!object->IsMarked()); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::Contains(object)); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsMap()) { 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* map = Map::cast(object); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_cleanup_caches_in_maps_at_gc) { 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map->ClearCodeCache(); 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetMark(map); 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_collect_maps && 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map->instance_type() >= FIRST_JS_OBJECT_TYPE && 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map->instance_type() <= JS_FUNCTION_TYPE) { 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkMapContents(map); 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block marking_stack.Push(map); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetMark(object); 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block marking_stack.Push(object); 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkMapContents(Map* map) { 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkDescriptorArray(reinterpret_cast<DescriptorArray*>( 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *HeapObject::RawField(map, Map::kInstanceDescriptorsOffset))); 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark the Object* fields of the Map. 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Since the descriptor array has been marked already, it is fine 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // that one of these fields contains a pointer to it. 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkingVisitor visitor; // Has no state or contents. 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block visitor.VisitPointers(HeapObject::RawField(map, Map::kPrototypeOffset), 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject::RawField(map, Map::kSize)); 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkDescriptorArray( 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DescriptorArray* descriptors) { 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (descriptors->IsMarked()) return; 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Empty descriptor array is marked as a root before any maps are marked. 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(descriptors != Heap::raw_unchecked_empty_descriptor_array()); 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetMark(descriptors); 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FixedArray* contents = reinterpret_cast<FixedArray*>( 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block descriptors->get(DescriptorArray::kContentArrayIndex)); 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(contents->IsHeapObject()); 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!contents->IsMarked()); 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(contents->IsFixedArray()); 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(contents->length() >= 2); 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetMark(contents); 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Contents contains (value, details) pairs. If the details say 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // that the type of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION, 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // or NULL_DESCRIPTOR, we don't mark the value as live. Only for 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // type MAP_TRANSITION is the value a Object* (a Map*). 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < contents->length(); i += 2) { 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the pair (value, details) at index i, i+1 is not 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a transition or null descriptor, mark the value. 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PropertyDetails details(Smi::cast(contents->get(i + 1))); 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (details.type() < FIRST_PHANTOM_PROPERTY_TYPE) { 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* object = reinterpret_cast<HeapObject*>(contents->get(i)); 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsHeapObject() && !object->IsMarked()) { 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetMark(object); 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block marking_stack.Push(object); 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The DescriptorArray descriptors contains a pointer to its contents array, 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // but the contents array is already marked. 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block marking_stack.Push(descriptors); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::CreateBackPointers() { 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObjectIterator iterator(Heap::map_space()); 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (iterator.has_next()) { 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* next_object = iterator.next(); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (next_object->IsMap()) { // Could also be ByteArray on free list. 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* map = Map::cast(next_object); 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (map->instance_type() >= FIRST_JS_OBJECT_TYPE && 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map->instance_type() <= JS_FUNCTION_TYPE) { 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map->CreateBackPointers(); 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(map->instance_descriptors() == Heap::empty_descriptor_array()); 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int OverflowObjectSize(HeapObject* obj) { 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Recover the normal map pointer, it might be marked as live and 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // overflowed. 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord map_word = obj->map_word(); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map_word.ClearMark(); 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map_word.ClearOverflow(); 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return obj->SizeFromMap(map_word.ToMap()); 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Fill the marking stack with overflowed objects returned by the given 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// iterator. Stop when the marking stack is filled or the end of the space 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is reached, whichever comes first. 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate<class T> 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ScanOverflowedObjects(T* it) { 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The caller should ensure that the marking stack is initially not full, 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // so that we don't waste effort pointlessly scanning for objects. 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!marking_stack.is_full()); 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (it->has_next()) { 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* object = it->next(); 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsOverflowed()) { 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object->ClearOverflow(); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsMarked()); 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::Contains(object)); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block marking_stack.Push(object); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (marking_stack.is_full()) return; 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked(); 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkSymbolTable() { 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table(); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark the symbol table itself. 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetMark(symbol_table); 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Explicitly mark the prefix. 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkingVisitor marker; 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block symbol_table->IteratePrefix(&marker); 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ProcessMarkingStack(&marker); 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark the heap roots including global variables, stack variables, 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // etc., and all objects reachable from them. 544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Heap::IterateStrongRoots(visitor, VISIT_ONLY_STRONG); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle the symbol table specially. 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkSymbolTable(); 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // There may be overflowed objects in the heap. Visit them now. 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (marking_stack.overflowed()) { 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RefillMarkingStack(); 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EmptyMarkingStack(visitor->stack_visitor()); 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkObjectGroups() { 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<ObjectGroup*>* object_groups = GlobalHandles::ObjectGroups(); 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < object_groups->length(); i++) { 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ObjectGroup* entry = object_groups->at(i); 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (entry == NULL) continue; 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<Object**>& objects = entry->objects_; 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool group_marked = false; 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int j = 0; j < objects.length(); j++) { 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* object = *objects[j]; 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsHeapObject() && HeapObject::cast(object)->IsMarked()) { 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block group_marked = true; 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!group_marked) continue; 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // An object in the group is marked, so mark as gray all white heap 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // objects in the group. 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int j = 0; j < objects.length(); ++j) { 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((*objects[j])->IsHeapObject()) { 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkObject(HeapObject::cast(*objects[j])); 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Once the entire group has been colored gray, set the object group 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to NULL so it won't be processed again. 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete object_groups->at(i); 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object_groups->at(i) = NULL; 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mark all objects reachable from the objects on the marking stack. 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Before: the marking stack contains zero or more heap object pointers. 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// After: the marking stack is empty, and all objects reachable from the 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// marking stack have been marked, or are overflowed in the heap. 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::EmptyMarkingStack(MarkingVisitor* visitor) { 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (!marking_stack.is_empty()) { 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* object = marking_stack.Pop(); 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsHeapObject()); 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::Contains(object)); 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsMarked()); 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!object->IsOverflowed()); 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Because the object is marked, we have to recover the original map 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // pointer and use it to mark the object's body. 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord map_word = object->map_word(); 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map_word.ClearMark(); 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* map = map_word.ToMap(); 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkObject(map); 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object->IterateBody(map->instance_type(), object->SizeFromMap(map), 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block visitor); 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Sweep the heap for overflowed objects, clear their overflow bits, and 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// push them on the marking stack. Stop early if the marking stack fills 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// before sweeping completes. If sweeping completes, there are no remaining 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overflowed objects in the heap so the overflow flag on the markings stack 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is cleared. 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::RefillMarkingStack() { 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(marking_stack.overflowed()); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SemiSpaceIterator new_it(Heap::new_space(), &OverflowObjectSize); 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScanOverflowedObjects(&new_it); 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (marking_stack.is_full()) return; 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObjectIterator old_pointer_it(Heap::old_pointer_space(), 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &OverflowObjectSize); 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScanOverflowedObjects(&old_pointer_it); 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (marking_stack.is_full()) return; 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObjectIterator old_data_it(Heap::old_data_space(), &OverflowObjectSize); 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScanOverflowedObjects(&old_data_it); 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (marking_stack.is_full()) return; 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObjectIterator code_it(Heap::code_space(), &OverflowObjectSize); 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScanOverflowedObjects(&code_it); 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (marking_stack.is_full()) return; 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObjectIterator map_it(Heap::map_space(), &OverflowObjectSize); 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScanOverflowedObjects(&map_it); 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (marking_stack.is_full()) return; 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObjectIterator cell_it(Heap::cell_space(), &OverflowObjectSize); 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScanOverflowedObjects(&cell_it); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (marking_stack.is_full()) return; 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LargeObjectIterator lo_it(Heap::lo_space(), &OverflowObjectSize); 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScanOverflowedObjects(&lo_it); 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (marking_stack.is_full()) return; 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block marking_stack.clear_overflowed(); 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mark all objects reachable (transitively) from objects on the marking 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// stack. Before: the marking stack contains zero or more heap object 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// pointers. After: the marking stack is empty and there are no overflowed 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// objects in the heap. 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::ProcessMarkingStack(MarkingVisitor* visitor) { 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EmptyMarkingStack(visitor); 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (marking_stack.overflowed()) { 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RefillMarkingStack(); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EmptyMarkingStack(visitor); 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::ProcessObjectGroups(MarkingVisitor* visitor) { 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool work_to_do = true; 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(marking_stack.is_empty()); 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (work_to_do) { 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkObjectGroups(); 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block work_to_do = !marking_stack.is_empty(); 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ProcessMarkingStack(visitor); 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkLiveObjects() { 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == PREPARE_GC); 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = MARK_LIVE_OBJECTS; 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The to space contains live objects, the from space is used as a marking 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stack. 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block marking_stack.Initialize(Heap::new_space()->FromSpaceLow(), 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->FromSpaceHigh()); 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!marking_stack.overflowed()); 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RootMarkingVisitor root_visitor; 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkRoots(&root_visitor); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The objects reachable from the roots are marked, yet unreachable 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // objects are unmarked. Mark objects reachable from object groups 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // containing at least one marked object, and continue until no new 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // objects are reachable from the object groups. 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ProcessObjectGroups(root_visitor.stack_visitor()); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The objects reachable from the roots or object groups are marked, 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // yet unreachable objects are unmarked. Mark objects reachable 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // only from weak global handles. 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First we identify nonlive weak handles and mark them as pending 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // destruction. 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::IdentifyWeakHandles(&IsUnmarkedHeapObject); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Then we mark the objects and process the transitive closure. 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::IterateWeakRoots(&root_visitor); 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (marking_stack.overflowed()) { 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RefillMarkingStack(); 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EmptyMarkingStack(root_visitor.stack_visitor()); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Repeat the object groups to mark unmarked groups reachable from the 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // weak roots. 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ProcessObjectGroups(root_visitor.stack_visitor()); 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Prune the symbol table removing all symbols only pointed to by the 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // symbol table. Cannot use symbol_table() here because the symbol 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // table is marked. 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table(); 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SymbolTableCleaner v; 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block symbol_table->IterateElements(&v); 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block symbol_table->ElementsRemoved(v.PointersRemoved()); 726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalStringTable::Iterate(&v); 727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalStringTable::CleanUp(); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove object groups after marking phase. 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::RemoveObjectGroups(); 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int CountMarkedCallback(HeapObject* obj) { 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord map_word = obj->map_word(); 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map_word.ClearMark(); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return obj->SizeFromMap(map_word.ToMap()); 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_bytes_ += obj->Size(); 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (Heap::new_space()->Contains(obj)) { 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_young_objects_++; 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (Heap::map_space()->Contains(obj)) { 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(obj->IsMap()); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_map_objects_++; 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (Heap::cell_space()->Contains(obj)) { 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(obj->IsJSGlobalPropertyCell()); 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_cell_objects_++; 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (Heap::old_pointer_space()->Contains(obj)) { 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_old_pointer_objects_++; 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (Heap::old_data_space()->Contains(obj)) { 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_old_data_objects_++; 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (Heap::code_space()->Contains(obj)) { 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_code_objects_++; 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (Heap::lo_space()->Contains(obj)) { 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_lo_objects_++; 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // DEBUG 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::SweepLargeObjectSpace() { 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == MARK_LIVE_OBJECTS); 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block compacting_collection_ ? ENCODE_FORWARDING_ADDRESSES : SWEEP_SPACES; 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Deallocate unmarked objects and clear marked bits for marked objects. 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::lo_space()->FreeUnmarkedObjects(); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Safe to use during marking phase only. 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool MarkCompactCollector::SafeIsMap(HeapObject* object) { 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord metamap = object->map_word(); 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block metamap.ClearMark(); 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return metamap.ToMap()->instance_type() == MAP_TYPE; 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::ClearNonLiveTransitions() { 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObjectIterator map_iterator(Heap::map_space(), &CountMarkedCallback); 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Iterate over the map space, setting map transitions that go from 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a marked map to an unmarked map to null transitions. At the same time, 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // set all the prototype fields of maps back to their original value, 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // dropping the back pointers temporarily stored in the prototype field. 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setting the prototype field requires following the linked list of 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // back pointers, reversing them all at once. This allows us to find 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // those maps with map transitions that need to be nulled, and only 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scan the descriptor arrays of those maps, not all maps. 794e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // All of these actions are carried out only on maps of JSObjects 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and related subtypes. 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (map_iterator.has_next()) { 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* map = reinterpret_cast<Map*>(map_iterator.next()); 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!map->IsMarked() && map->IsByteArray()) continue; 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(SafeIsMap(map)); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Only JSObject and subtypes have map transitions and back pointers. 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue; 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (map->instance_type() > JS_FUNCTION_TYPE) continue; 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Follow the chain of back pointers to find the prototype. 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* current = map; 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (SafeIsMap(current)) { 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current = reinterpret_cast<Map*>(current->prototype()); 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(current->IsHeapObject()); 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* real_prototype = current; 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Follow back pointers, setting them to prototype, 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // clearing map transitions when necessary. 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current = map; 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool on_dead_path = !current->IsMarked(); 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* next; 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (SafeIsMap(current)) { 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next = current->prototype(); 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // There should never be a dead map above a live map. 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(on_dead_path || current->IsMarked()); 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // A live map above a dead map indicates a dead transition. 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This test will always be false on the first iteration. 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (on_dead_path && current->IsMarked()) { 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block on_dead_path = false; 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current->ClearNonLiveTransitions(real_prototype); 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *HeapObject::RawField(current, Map::kPrototypeOffset) = 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block real_prototype; 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current = reinterpret_cast<Map*>(next); 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------- 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 2: Encode forwarding addresses. 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// When compacting, forwarding addresses for objects in old space and map 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// space are encoded in their map pointer word (along with an encoding of 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// their map pointers). 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 841e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// The excact encoding is described in the comments for class MapWord in 842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// objects.h. 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// An address range [start, end) can have both live and non-live objects. 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Maximal non-live regions are marked so they can be skipped on subsequent 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sweeps of the heap. A distinguished map-pointer encoding is used to mark 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// free regions of one-word size (in which case the next word is the start 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of a live object). A second distinguished map-pointer encoding is used 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to mark free regions larger than one word, and the size of the free 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// region (including the first word) is written to the second word of the 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// region. 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Any valid map page offset must lie in the object area of the page, so map 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// page offsets less than Page::kObjectStartOffset are invalid. We use a 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// pair of distinguished invalid map encodings (for single word and multiple 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// words) to indicate free regions in the page found during computation of 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forwarding addresses and skipped over in subsequent sweeps. 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const uint32_t kSingleFreeEncoding = 0; 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const uint32_t kMultiFreeEncoding = 1; 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Encode a free region, defined by the given start address and size, in the 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// first word or two of the region. 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid EncodeFreeRegion(Address free_start, int free_size) { 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(free_size >= kIntSize); 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (free_size == kIntSize) { 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Memory::uint32_at(free_start) = kSingleFreeEncoding; 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(free_size >= 2 * kIntSize); 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Memory::uint32_at(free_start) = kMultiFreeEncoding; 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Memory::int_at(free_start + kIntSize) = free_size; 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Zap the body of the free region. 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_enable_slow_asserts) { 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int offset = 2 * kIntSize; 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset < free_size; 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset += kPointerSize) { 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Memory::Address_at(free_start + offset) = kZapValue; 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Try to promote all objects in new space. Heap numbers and sequential 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// strings are promoted to the code space, large objects to large object space, 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and all others to the old space. 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Object* MCAllocateFromNewSpace(HeapObject* object, int object_size) { 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* forwarded; 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object_size > Heap::MaxObjectSizeInPagedSpace()) { 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block forwarded = Failure::Exception(); 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OldSpace* target_space = Heap::TargetSpace(object); 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(target_space == Heap::old_pointer_space() || 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block target_space == Heap::old_data_space()); 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block forwarded = target_space->MCAllocateRaw(object_size); 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (forwarded->IsFailure()) { 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block forwarded = Heap::new_space()->MCAllocateRaw(object_size); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return forwarded; 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocation functions for the paged spaces call the space's MCAllocateRaw. 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Object* MCAllocateFromOldPointerSpace(HeapObject* ignore, 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int object_size) { 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Heap::old_pointer_space()->MCAllocateRaw(object_size); 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Object* MCAllocateFromOldDataSpace(HeapObject* ignore, int object_size) { 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Heap::old_data_space()->MCAllocateRaw(object_size); 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Object* MCAllocateFromCodeSpace(HeapObject* ignore, int object_size) { 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Heap::code_space()->MCAllocateRaw(object_size); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Object* MCAllocateFromMapSpace(HeapObject* ignore, int object_size) { 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Heap::map_space()->MCAllocateRaw(object_size); 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Object* MCAllocateFromCellSpace(HeapObject* ignore, int object_size) { 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Heap::cell_space()->MCAllocateRaw(object_size); 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The forwarding address is encoded at the same offset as the current 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to-space object, but in from space. 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline void EncodeForwardingAddressInNewSpace(HeapObject* old_object, 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int object_size, 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* new_object, 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* ignored) { 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->ToSpaceOffsetForAddress(old_object->address()); 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset) = 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject::cast(new_object)->address(); 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The forwarding address is encoded in the map pointer of the object as an 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// offset (in terms of live bytes) from the address of the first live object 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// in the page. 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline void EncodeForwardingAddressInPagedSpace(HeapObject* old_object, 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int object_size, 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* new_object, 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* offset) { 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Record the forwarding address of the first live object if necessary. 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*offset == 0) { 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page::FromAddress(old_object->address())->mc_first_forwarded = 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject::cast(new_object)->address(); 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord encoding = 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord::EncodeAddress(old_object->map()->address(), *offset); 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block old_object->set_map_word(encoding); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *offset += object_size; 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(*offset <= Page::kObjectAreaSize); 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Most non-live objects are ignored. 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline void IgnoreNonLiveObject(HeapObject* object) {} 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A code deletion event is logged for non-live code objects. 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline void LogNonLiveCodeObject(HeapObject* object) { 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsCode()) LOG(CodeDeleteEvent(object->address())); 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Function template that, given a range of addresses (eg, a semispace or a 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// paged space page), iterates through the objects in the range to clear 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mark bits and compute and encode forwarding addresses. As a side effect, 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// maximal free chunks are marked so that they can be skipped on subsequent 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sweeps. 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The template parameters are an allocation function, a forwarding address 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// encoding function, and a function to process non-live objects. 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate<MarkCompactCollector::AllocationFunction Alloc, 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::EncodingFunction Encode, 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive> 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline void EncodeForwardingAddressesInRange(Address start, 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address end, 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* offset) { 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The start address of the current free region while sweeping the space. 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This address is set when a transition from live to non-live objects is 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // encountered. A value (an encoding of the 'next free region' pointer) 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is written to memory at this address when a transition from non-live to 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // live objects is encountered. 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address free_start = NULL; 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // A flag giving the state of the previously swept object. Initially true 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to ensure that free_start is initialized to a proper address before 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // trying to write to it. 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_prev_alive = true; 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int object_size; // Will be set on each iteration of the loop. 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Address current = start; current < end; current += object_size) { 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* object = HeapObject::FromAddress(current); 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsMarked()) { 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object->ClearMark(); 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::tracer()->decrement_marked_count(); 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object_size = object->Size(); 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* forwarded = Alloc(object, object_size); 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocation cannot fail, because we are compacting the space. 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!forwarded->IsFailure()); 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Encode(object, object_size, forwarded, offset); 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_gc_verbose) { 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("forward %p -> %p.\n", object->address(), 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject::cast(forwarded)->address()); 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_prev_alive) { // Transition from non-live to live. 1024d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EncodeFreeRegion(free_start, static_cast<int>(current - free_start)); 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block is_prev_alive = true; 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { // Non-live object. 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object_size = object->Size(); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ProcessNonLive(object); 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_prev_alive) { // Transition from live to non-live. 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block free_start = current; 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block is_prev_alive = false; 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we ended on a free region, mark it. 1038d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!is_prev_alive) { 1039d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EncodeFreeRegion(free_start, static_cast<int>(end - free_start)); 1040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Functions to encode the forwarding pointers in each compactable space. 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::EncodeForwardingAddressesInNewSpace() { 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int ignored; 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddressesInRange<MCAllocateFromNewSpace, 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddressInNewSpace, 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IgnoreNonLiveObject>( 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->bottom(), 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->top(), 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &ignored); 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate<MarkCompactCollector::AllocationFunction Alloc, 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive> 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::EncodeForwardingAddressesInPagedSpace( 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PagedSpace* space) { 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PageIterator it(space, PageIterator::PAGES_IN_USE); 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (it.has_next()) { 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page* p = it.next(); 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The offset of each live object in the page from the first live object 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in the page. 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = 0; 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddressesInRange<Alloc, 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddressInPagedSpace, 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ProcessNonLive>( 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p->ObjectAreaStart(), 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p->AllocationTop(), 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &offset); 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void SweepSpace(NewSpace* space) { 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* object; 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Address current = space->bottom(); 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current < space->top(); 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += object->Size()) { 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object = HeapObject::FromAddress(current); 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsMarked()) { 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object->ClearMark(); 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::tracer()->decrement_marked_count(); 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We give non-live objects a map that will correctly give their size, 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // since their existing map might not be live after the collection. 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size = object->Size(); 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (size >= ByteArray::kHeaderSize) { 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object->set_map(Heap::raw_unchecked_byte_array_map()); 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ByteArray::cast(object)->set_length(ByteArray::LengthFor(size)); 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(size == kPointerSize); 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object->set_map(Heap::raw_unchecked_one_pointer_filler_map()); 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->Size() == size); 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The object is now unmarked for the call to Size() at the top of the 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // loop. 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) { 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PageIterator it(space, PageIterator::PAGES_IN_USE); 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (it.has_next()) { 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page* p = it.next(); 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_previous_alive = true; 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address free_start = NULL; 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* object; 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Address current = p->ObjectAreaStart(); 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current < p->AllocationTop(); 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += object->Size()) { 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object = HeapObject::FromAddress(current); 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsMarked()) { 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object->ClearMark(); 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkCompactCollector::tracer()->decrement_marked_count(); 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_previous_alive) { // Transition from free to live. 1121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block dealloc(free_start, static_cast<int>(current - free_start)); 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block is_previous_alive = true; 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsCode()) { 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notify the logger that compiled code has been collected. 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LOG(CodeDeleteEvent(Code::cast(object)->address())); 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_previous_alive) { // Transition from live to free. 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block free_start = current; 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block is_previous_alive = false; 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The object is now unmarked for the call to Size() at the top of the 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // loop. 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the last region was not live we need to deallocate from 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // free_start to the allocation top in the page. 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_previous_alive) { 1141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int free_size = static_cast<int>(p->AllocationTop() - free_start); 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (free_size > 0) { 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block dealloc(free_start, free_size); 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::DeallocateOldPointerBlock(Address start, 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_in_bytes) { 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::ClearRSetRange(start, size_in_bytes); 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::old_pointer_space()->Free(start, size_in_bytes); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::DeallocateOldDataBlock(Address start, 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_in_bytes) { 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::old_data_space()->Free(start, size_in_bytes); 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::DeallocateCodeBlock(Address start, 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_in_bytes) { 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::code_space()->Free(start, size_in_bytes); 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::DeallocateMapBlock(Address start, 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_in_bytes) { 1171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Objects in map space are assumed to have size Map::kSize and a 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // valid map in their first word. Thus, we break the free block up into 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // chunks and free them separately. 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(size_in_bytes % Map::kSize == 0); 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::ClearRSetRange(start, size_in_bytes); 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address end = start + size_in_bytes; 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Address a = start; a < end; a += Map::kSize) { 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::map_space()->Free(a); 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::DeallocateCellBlock(Address start, 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_in_bytes) { 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Free-list elements in cell space are assumed to have a fixed size. 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We break the free block into chunks and add them to the free list 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // individually. 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size = Heap::cell_space()->object_size_in_bytes(); 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(size_in_bytes % size == 0); 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::ClearRSetRange(start, size_in_bytes); 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address end = start + size_in_bytes; 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Address a = start; a < end; a += size) { 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::cell_space()->Free(a); 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::EncodeForwardingAddresses() { 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Objects in the active semispace of the young generation may be 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocated to the inactive semispace (if not promoted). Set the 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocation info to the beginning of the inactive semispace. 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->MCResetRelocationInfo(); 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the forwarding pointers in each space. 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace, 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IgnoreNonLiveObject>( 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::old_pointer_space()); 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace, 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IgnoreNonLiveObject>( 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::old_data_space()); 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace, 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LogNonLiveCodeObject>( 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::code_space()); 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddressesInPagedSpace<MCAllocateFromCellSpace, 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IgnoreNonLiveObject>( 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::cell_space()); 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute new space next to last after the old and code spaces have been 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // compacted. Objects in new space can be promoted to old or code space. 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddressesInNewSpace(); 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute map space last because computing forwarding addresses 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // overwrites non-live objects. Objects in the other spaces rely on 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // non-live map pointers to get the sizes of non-live objects. 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace, 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IgnoreNonLiveObject>( 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::map_space()); 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write relocation info to the top page, so we can use it later. This is 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // done after promoting objects from the new space so we get the correct 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allocation top. 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::old_pointer_space()->MCWriteRelocationInfoToPage(); 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::old_data_space()->MCWriteRelocationInfoToPage(); 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::code_space()->MCWriteRelocationInfoToPage(); 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::map_space()->MCWriteRelocationInfoToPage(); 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::cell_space()->MCWriteRelocationInfoToPage(); 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeclass MapIterator : public HeapObjectIterator { 1246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke public: 1247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MapIterator() : HeapObjectIterator(Heap::map_space(), &SizeCallback) { } 1248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke explicit MapIterator(Address start) 1250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke : HeapObjectIterator(Heap::map_space(), start, &SizeCallback) { } 1251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke private: 1253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke static int SizeCallback(HeapObject* unused) { 1254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke USE(unused); 1255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Map::kSize; 1256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}; 1258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeclass MapCompact { 1261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke public: 1262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke explicit MapCompact(int live_maps) 1263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke : live_maps_(live_maps), 1264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke to_evacuate_start_(Heap::map_space()->TopAfterCompaction(live_maps)), 1265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map_to_evacuate_it_(to_evacuate_start_), 1266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke first_map_to_evacuate_( 1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke reinterpret_cast<Map*>(HeapObject::FromAddress(to_evacuate_start_))) { 1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void CompactMaps() { 1271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // As we know the number of maps to evacuate beforehand, 1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // we stop then there is no more vacant maps. 1273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke for (Map* next_vacant_map = NextVacantMap(); 1274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke next_vacant_map; 1275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke next_vacant_map = NextVacantMap()) { 1276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EvacuateMap(next_vacant_map, NextMapToEvacuate()); 1277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG 1280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CheckNoMapsToEvacuate(); 1281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif 1282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void UpdateMapPointersInRoots() { 1285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Heap::IterateRoots(&map_updating_visitor_, VISIT_ONLY_STRONG); 1286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GlobalHandles::IterateWeakRoots(&map_updating_visitor_); 1287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void FinishMapSpace() { 1290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Iterate through to space and finish move. 1291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MapIterator it; 1292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke HeapObject* o = it.next(); 1293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke for (; o != first_map_to_evacuate_; o = it.next()) { 1294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Map* map = reinterpret_cast<Map*>(o); 1295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!map->IsMarked()); 1296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!map->IsOverflowed()); 1297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(map->IsMap()); 1298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Heap::UpdateRSet(map); 1299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void UpdateMapPointersInPagedSpace(PagedSpace* space) { 1303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(space != Heap::map_space()); 1304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke PageIterator it(space, PageIterator::PAGES_IN_USE); 1306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke while (it.has_next()) { 1307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Page* p = it.next(); 1308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UpdateMapPointersInRange(p->ObjectAreaStart(), p->AllocationTop()); 1309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void UpdateMapPointersInNewSpace() { 1313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NewSpace* space = Heap::new_space(); 1314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UpdateMapPointersInRange(space->bottom(), space->top()); 1315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void UpdateMapPointersInLargeObjectSpace() { 1318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LargeObjectIterator it(Heap::lo_space()); 1319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke while (true) { 1320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!it.has_next()) break; 1321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UpdateMapPointersInObject(it.next()); 1322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Finish() { 1326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Heap::map_space()->FinishCompaction(to_evacuate_start_, live_maps_); 1327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke private: 1330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int live_maps_; 1331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Address to_evacuate_start_; 1332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MapIterator vacant_map_it_; 1333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MapIterator map_to_evacuate_it_; 1334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Map* first_map_to_evacuate_; 1335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Helper class for updating map pointers in HeapObjects. 1337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke class MapUpdatingVisitor: public ObjectVisitor { 1338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke public: 1339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void VisitPointer(Object** p) { 1340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UpdateMapPointer(p); 1341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void VisitPointers(Object** start, Object** end) { 1344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke for (Object** p = start; p < end; p++) UpdateMapPointer(p); 1345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke private: 1348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void UpdateMapPointer(Object** p) { 1349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!(*p)->IsHeapObject()) return; 1350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke HeapObject* old_map = reinterpret_cast<HeapObject*>(*p); 1351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Moved maps are tagged with overflowed map word. They are the only 1353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // objects those map word is overflowed as marking is already complete. 1354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MapWord map_word = old_map->map_word(); 1355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!map_word.IsOverflowed()) return; 1356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke *p = GetForwardedMap(map_word); 1358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke }; 1360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke static MapUpdatingVisitor map_updating_visitor_; 1362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke static Map* NextMap(MapIterator* it, HeapObject* last, bool live) { 1364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke while (true) { 1365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(it->has_next()); 1366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke HeapObject* next = it->next(); 1367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (next == last) 1368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return NULL; 1369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!next->IsOverflowed()); 1370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!next->IsMarked()); 1371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(next->IsMap() || FreeListNode::IsFreeListNode(next)); 1372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (next->IsMap() == live) 1373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return reinterpret_cast<Map*>(next); 1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Map* NextVacantMap() { 1378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Map* map = NextMap(&vacant_map_it_, first_map_to_evacuate_, false); 1379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(map == NULL || FreeListNode::IsFreeListNode(map)); 1380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return map; 1381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Map* NextMapToEvacuate() { 1384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Map* map = NextMap(&map_to_evacuate_it_, NULL, true); 1385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(map != NULL); 1386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(map->IsMap()); 1387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return map; 1388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke static void EvacuateMap(Map* vacant_map, Map* map_to_evacuate) { 1391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(FreeListNode::IsFreeListNode(vacant_map)); 1392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(map_to_evacuate->IsMap()); 1393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke memcpy( 1395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke reinterpret_cast<void*>(vacant_map->address()), 1396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke reinterpret_cast<void*>(map_to_evacuate->address()), 1397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Map::kSize); 1398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(vacant_map->IsMap()); // Due to memcpy above. 1399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MapWord forwarding_map_word = MapWord::FromMap(vacant_map); 1401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke forwarding_map_word.SetOverflow(); 1402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map_to_evacuate->set_map_word(forwarding_map_word); 1403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(map_to_evacuate->map_word().IsOverflowed()); 1405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(GetForwardedMap(map_to_evacuate->map_word()) == vacant_map); 1406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke static Map* GetForwardedMap(MapWord map_word) { 1409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(map_word.IsOverflowed()); 1410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map_word.ClearOverflow(); 1411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Map* new_map = map_word.ToMap(); 1412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_MAP_ALIGNED(new_map->address()); 1413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return new_map; 1414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke static int UpdateMapPointersInObject(HeapObject* obj) { 1417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!obj->IsMarked()); 1418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Map* map = obj->map(); 1419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(Heap::map_space()->Contains(map)); 1420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MapWord map_word = map->map_word(); 1421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!map_word.IsMarked()); 1422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (map_word.IsOverflowed()) { 1423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Map* new_map = GetForwardedMap(map_word); 1424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(Heap::map_space()->Contains(new_map)); 1425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke obj->set_map(new_map); 1426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG 1428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (FLAG_gc_verbose) { 1429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke PrintF("update %p : %p -> %p\n", obj->address(), 1430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map, new_map); 1431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif 1433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int size = obj->SizeFromMap(map); 1436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke obj->IterateBody(map->instance_type(), size, &map_updating_visitor_); 1437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return size; 1438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke static void UpdateMapPointersInRange(Address start, Address end) { 1441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke HeapObject* object; 1442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int size; 1443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke for (Address current = start; current < end; current += size) { 1444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke object = HeapObject::FromAddress(current); 1445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke size = UpdateMapPointersInObject(object); 1446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(size > 0); 1447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG 1451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void CheckNoMapsToEvacuate() { 1452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!FLAG_enable_slow_asserts) 1453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return; 1454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke while (map_to_evacuate_it_.has_next()) 1456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(FreeListNode::IsFreeListNode(map_to_evacuate_it_.next())); 1457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif 1459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}; 1460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeMapCompact::MapUpdatingVisitor MapCompact::map_updating_visitor_; 1462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::SweepSpaces() { 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == SWEEP_SPACES); 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!IsCompacting()); 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Noncompacting collections simply sweep the spaces to clear the mark 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bits and free the nonlive blocks (for old and map spaces). We sweep 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the map space last because freeing non-live maps overwrites them and 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the other spaces rely on possibly non-live maps to get the sizes for 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // non-live objects. 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SweepSpace(Heap::old_pointer_space(), &DeallocateOldPointerBlock); 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock); 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SweepSpace(Heap::code_space(), &DeallocateCodeBlock); 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SweepSpace(Heap::cell_space(), &DeallocateCellBlock); 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SweepSpace(Heap::new_space()); 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SweepSpace(Heap::map_space(), &DeallocateMapBlock); 1478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int live_maps = Heap::map_space()->Size() / Map::kSize; 1479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(live_map_objects_ == live_maps); 1480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (Heap::map_space()->NeedsCompaction(live_maps)) { 1482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MapCompact map_compact(live_maps); 1483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map_compact.CompactMaps(); 1485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map_compact.UpdateMapPointersInRoots(); 1486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map_compact.FinishMapSpace(); 1488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke PagedSpaces spaces; 1489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke while (PagedSpace* space = spaces.next()) { 1490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (space == Heap::map_space()) continue; 1491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map_compact.UpdateMapPointersInPagedSpace(space); 1492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map_compact.UpdateMapPointersInNewSpace(); 1494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map_compact.UpdateMapPointersInLargeObjectSpace(); 1495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke map_compact.Finish(); 1497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Iterate the live objects in a range of addresses (eg, a page or a 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// semispace). The live regions of the range have been linked into a list. 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The first live region is [first_live_start, first_live_end), and the last 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// address in the range is top. The callback function is used to get the 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// size of each live object. 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::IterateLiveObjectsInRange( 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address start, 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address end, 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObjectCallback size_func) { 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_objects = 0; 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address current = start; 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (current < end) { 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t encoded_map = Memory::uint32_at(current); 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (encoded_map == kSingleFreeEncoding) { 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += kPointerSize; 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (encoded_map == kMultiFreeEncoding) { 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += Memory::int_at(current + kIntSize); 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block live_objects++; 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += size_func(HeapObject::FromAddress(current)); 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return live_objects; 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::IterateLiveObjects(NewSpace* space, 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObjectCallback size_f) { 1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS); 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return IterateLiveObjectsInRange(space->bottom(), space->top(), size_f); 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::IterateLiveObjects(PagedSpace* space, 1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObjectCallback size_f) { 1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS); 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int total = 0; 1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PageIterator it(space, PageIterator::PAGES_IN_USE); 1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (it.has_next()) { 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page* p = it.next(); 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block total += IterateLiveObjectsInRange(p->ObjectAreaStart(), 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p->AllocationTop(), 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block size_f); 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return total; 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------- 1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 3: Update pointers 1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class for updating pointers in HeapObjects. 1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass UpdatingVisitor: public ObjectVisitor { 1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void VisitPointer(Object** p) { 1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdatePointer(p); 1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void VisitPointers(Object** start, Object** end) { 1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark all HeapObject pointers in [start, end) 1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Object** p = start; p < end; p++) UpdatePointer(p); 1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void VisitCodeTarget(RelocInfo* rinfo) { 1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block VisitPointer(&target); 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rinfo->set_target_address( 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<Code*>(target)->instruction_start()); 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void VisitDebugTarget(RelocInfo* rinfo) { 15733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) && 15743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block rinfo->IsPatchedReturnSequence()); 15753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); 15763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block VisitPointer(&target); 15773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block rinfo->set_call_address( 15783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block reinterpret_cast<Code*>(target)->instruction_start()); 15793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UpdatePointer(Object** p) { 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!(*p)->IsHeapObject()) return; 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* obj = HeapObject::cast(*p); 1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address old_addr = obj->address(); 1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address new_addr; 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!Heap::InFromSpace(obj)); 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (Heap::new_space()->Contains(obj)) { 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address forwarding_pointer_addr = 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->FromSpaceLow() + 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->ToSpaceOffsetForAddress(old_addr); 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new_addr = Memory::Address_at(forwarding_pointer_addr); 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::old_pointer_space()->Contains(new_addr) || 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::old_data_space()->Contains(new_addr) || 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->FromSpaceContains(new_addr) || 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::lo_space()->Contains(HeapObject::FromAddress(new_addr))); 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (Heap::new_space()->FromSpaceContains(new_addr)) { 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->ToSpaceOffsetForAddress(old_addr)); 1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (Heap::lo_space()->Contains(obj)) { 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Don't move objects in the large object space. 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PagedSpaces spaces; 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PagedSpace* original_space = spaces.next(); 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (original_space != NULL) { 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (original_space->Contains(obj)) break; 1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block original_space = spaces.next(); 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(original_space != NULL); 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new_addr = MarkCompactCollector::GetForwardingAddressInOldSpace(obj); 1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(original_space->Contains(new_addr)); 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(original_space->MCSpaceOffsetForAddress(new_addr) <= 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block original_space->MCSpaceOffsetForAddress(old_addr)); 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *p = HeapObject::FromAddress(new_addr); 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_gc_verbose) { 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("update %p : %p -> %p\n", 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<Address>(p), old_addr, new_addr); 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::UpdatePointers() { 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = UPDATE_POINTERS; 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdatingVisitor updating_visitor; 1646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG); 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::IterateWeakRoots(&updating_visitor); 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_maps = IterateLiveObjects(Heap::map_space(), 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &UpdatePointersInOldObject); 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &UpdatePointersInOldObject); 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_data_olds = IterateLiveObjects(Heap::old_data_space(), 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &UpdatePointersInOldObject); 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_codes = IterateLiveObjects(Heap::code_space(), 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &UpdatePointersInOldObject); 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_cells = IterateLiveObjects(Heap::cell_space(), 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &UpdatePointersInOldObject); 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_news = IterateLiveObjects(Heap::new_space(), 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &UpdatePointersInNewObject); 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Large objects do not move, the map word can be updated directly. 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LargeObjectIterator it(Heap::lo_space()); 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (it.has_next()) UpdatePointersInNewObject(it.next()); 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_maps); 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_pointer_olds); 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_data_olds); 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_codes); 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_cells); 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_news); 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_maps == live_map_objects_); 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_data_olds == live_old_data_objects_); 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_pointer_olds == live_old_pointer_objects_); 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_codes == live_code_objects_); 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_cells == live_cell_objects_); 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_news == live_young_objects_); 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) { 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Keep old map pointers 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* old_map = obj->map(); 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(old_map->IsHeapObject()); 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address forwarded = GetForwardingAddressInOldSpace(old_map); 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::map_space()->Contains(old_map)); 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::map_space()->Contains(forwarded)); 1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_gc_verbose) { 1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("update %p : %p -> %p\n", obj->address(), old_map->address(), 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block forwarded); 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the map pointer. 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(forwarded))); 1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We have to compute the object size relying on the old map because 1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // map objects are not relocated yet. 1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int obj_size = obj->SizeFromMap(old_map); 1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update pointers in the object body. 1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdatingVisitor updating_visitor; 1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj->IterateBody(old_map->instance_type(), obj_size, &updating_visitor); 1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return obj_size; 1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::UpdatePointersInOldObject(HeapObject* obj) { 1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Decode the map pointer. 1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord encoding = obj->map_word(); 1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); 1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); 1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // At this point, the first word of map_addr is also encoded, cannot 1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // cast it to Map* using Map::cast. 1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)); 1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int obj_size = obj->SizeFromMap(map); 1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type = map->instance_type(); 1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update map pointer. 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address new_map_addr = GetForwardingAddressInOldSpace(map); 1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = encoding.DecodeOffset(); 1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj->set_map_word(MapWord::EncodeAddress(new_map_addr, offset)); 1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_gc_verbose) { 1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("update %p : %p -> %p\n", obj->address(), 1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block map_addr, new_map_addr); 1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update pointers in the object body. 1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdatingVisitor updating_visitor; 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj->IterateBody(type, obj_size, &updating_visitor); 1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return obj_size; 1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) { 1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Object should either in old or map space. 1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord encoding = obj->map_word(); 1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Offset to the first live object's forwarding address. 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = encoding.DecodeOffset(); 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address obj_addr = obj->address(); 1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find the first live object's forwarding address. 1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page* p = Page::FromAddress(obj_addr); 1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address first_forwarded = p->mc_first_forwarded; 1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Page start address of forwarded address. 1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page* forwarded_page = Page::FromAddress(first_forwarded); 1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int forwarded_offset = forwarded_page->Offset(first_forwarded); 1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find end of allocation of in the page of first_forwarded. 1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address mc_top = forwarded_page->mc_relocation_top; 1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mc_top_offset = forwarded_page->Offset(mc_top); 1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if current object's forward pointer is in the same page 1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // as the first live object's forwarding pointer 1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (forwarded_offset + offset < mc_top_offset) { 1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In the same page. 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return first_forwarded + offset; 1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Must be in the next page, NOTE: this may cross chunks. 1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page* next_page = forwarded_page->next_page(); 1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(next_page->is_valid()); 1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset -= (mc_top_offset - forwarded_offset); 1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset += Page::kObjectStartOffset; 1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_PAGE_OFFSET(offset); 1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(next_page->OffsetToAddress(offset) < next_page->mc_relocation_top); 1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return next_page->OffsetToAddress(offset); 1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------- 1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 4: Relocate objects 1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::RelocateObjects() { 1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == UPDATE_POINTERS); 1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = RELOCATE_OBJECTS; 1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Relocates objects, always relocate map objects first. Relocating 1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // objects in other space relies on map objects to get object size. 1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_maps = IterateLiveObjects(Heap::map_space(), &RelocateMapObject); 1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), 1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &RelocateOldPointerObject); 1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_data_olds = IterateLiveObjects(Heap::old_data_space(), 1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &RelocateOldDataObject); 1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_codes = IterateLiveObjects(Heap::code_space(), &RelocateCodeObject); 1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_cells = IterateLiveObjects(Heap::cell_space(), &RelocateCellObject); 1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int live_news = IterateLiveObjects(Heap::new_space(), &RelocateNewObject); 1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_maps); 1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_data_olds); 1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_pointer_olds); 1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_codes); 1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_cells); 1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(live_news); 1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_maps == live_map_objects_); 1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_data_olds == live_old_data_objects_); 1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_pointer_olds == live_old_pointer_objects_); 1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_codes == live_code_objects_); 1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_cells == live_cell_objects_); 1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(live_news == live_young_objects_); 1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Flip from and to spaces 1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->Flip(); 1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set age_mark to bottom in to space 1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address mark = Heap::new_space()->bottom(); 1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->set_age_mark(mark); 1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->MCCommitRelocationInfo(); 1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // It is safe to write to the remembered sets as remembered sets on a 1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // page-by-page basis after committing the m-c forwarding pointer. 1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Page::set_rset_state(Page::IN_USE); 1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PagedSpaces spaces; 1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (PagedSpace* space = spaces.next()) space->MCCommitRelocationInfo(); 1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateMapObject(HeapObject* obj) { 1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Recover map pointer. 1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord encoding = obj->map_word(); 1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); 1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); 1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get forwarding address before resetting map pointer 1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address new_addr = GetForwardingAddressInOldSpace(obj); 1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reset map pointer. The meta map object may not be copied yet so 1842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Map::cast does not yet work. 1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); 1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address old_addr = obj->address(); 1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (new_addr != old_addr) { 1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memmove(new_addr, old_addr, Map::kSize); // copy contents 1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_gc_verbose) { 1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("relocate %p -> %p\n", old_addr, new_addr); 1854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Map::kSize; 1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline int RestoreMap(HeapObject* obj, 1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PagedSpace* space, 1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address new_addr, 1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_addr) { 1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This must be a non-map object, and the function relies on the 1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // assumption that the Map space is compacted before the other paged 1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // spaces (see RelocateObjects). 1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reset map pointer. 1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj->set_map(Map::cast(HeapObject::FromAddress(map_addr))); 1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int obj_size = obj->Size(); 1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_OBJECT_SIZE(obj_size); 1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(space->MCSpaceOffsetForAddress(new_addr) <= 1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block space->MCSpaceOffsetForAddress(obj->address())); 1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_gc_verbose) { 1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("relocate %p -> %p\n", obj->address(), new_addr); 1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return obj_size; 1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj, 1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PagedSpace* space) { 1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Recover map pointer. 1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord encoding = obj->map_word(); 1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); 1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::map_space()->Contains(map_addr)); 1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get forwarding address before resetting map pointer. 1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address new_addr = GetForwardingAddressInOldSpace(obj); 1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reset the map pointer. 1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int obj_size = RestoreMap(obj, space, new_addr, map_addr); 1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address old_addr = obj->address(); 1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (new_addr != old_addr) { 1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memmove(new_addr, old_addr, obj_size); // Copy contents 1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); 1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return obj_size; 1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) { 1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RelocateOldNonCodeObject(obj, Heap::old_pointer_space()); 1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) { 1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RelocateOldNonCodeObject(obj, Heap::old_data_space()); 1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateCellObject(HeapObject* obj) { 1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RelocateOldNonCodeObject(obj, Heap::cell_space()); 1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateCodeObject(HeapObject* obj) { 1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Recover map pointer. 1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MapWord encoding = obj->map_word(); 1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); 1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); 1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get forwarding address before resetting map pointer 1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address new_addr = GetForwardingAddressInOldSpace(obj); 1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reset the map pointer. 1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int obj_size = RestoreMap(obj, Heap::code_space(), new_addr, map_addr); 1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address old_addr = obj->address(); 1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (new_addr != old_addr) { 1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memmove(new_addr, old_addr, obj_size); // Copy contents. 1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapObject* copied_to = HeapObject::FromAddress(new_addr); 1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (copied_to->IsCode()) { 1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // May also update inline cache target. 1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::cast(copied_to)->Relocate(new_addr - old_addr); 1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notify the logger that compiled code has moved. 1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LOG(CodeMoveEvent(old_addr, new_addr)); 1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return obj_size; 1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateNewObject(HeapObject* obj) { 1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int obj_size = obj->Size(); 1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get forwarding address 1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address old_addr = obj->address(); 1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = Heap::new_space()->ToSpaceOffsetForAddress(old_addr); 1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address new_addr = 1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset); 1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (Heap::new_space()->FromSpaceContains(new_addr)) { 1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= 1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::new_space()->ToSpaceOffsetForAddress(old_addr)); 1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::TargetSpace(obj) == Heap::old_pointer_space() || 1974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::TargetSpace(obj) == Heap::old_data_space()); 1975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // New and old addresses cannot overlap. 1979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memcpy(reinterpret_cast<void*>(new_addr), 1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(old_addr), 1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj_size); 1982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_gc_verbose) { 1985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("relocate %p -> %p\n", old_addr, new_addr); 1986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return obj_size; 1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------- 1994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 5: rebuild remembered sets 1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::RebuildRSets() { 1997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == RELOCATE_OBJECTS); 1999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = REBUILD_RSETS; 2000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::RebuildRSets(); 2002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 2005