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