mark-compact.cc revision 8b112d2025046f85ef7f6be087c6129c872ebad2
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
30756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#include "compilation-cache.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "execution.h"
323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch#include "heap-profiler.h"
33b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#include "gdb-jit.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "global-handles.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h"
361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "liveobjectlist-inl.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "mark-compact.h"
38756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#include "objects-visiting.h"
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h"
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MarkCompactCollector
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMarkCompactCollector::MarkCompactCollector() :  // NOLINT
4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
4944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      state_(IDLE),
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      force_compaction_(false),
5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      compacting_collection_(false),
5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      compact_on_next_gc_(false),
5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      previous_marked_count_(0),
5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      tracer_(NULL),
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      live_young_objects_size_(0),
5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      live_old_pointer_objects_size_(0),
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      live_old_data_objects_size_(0),
6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      live_code_objects_size_(0),
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      live_map_objects_size_(0),
6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      live_cell_objects_size_(0),
6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      live_lo_objects_size_(0),
6444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      live_bytes_(0),
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_(NULL),
6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      code_flusher_(NULL) { }
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::CollectGarbage() {
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that Prepare() has been called. The individual steps below will
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // update the state as they proceed.
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == PREPARE_GC);
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Prepare has selected whether to compact the old generation or not.
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tell the tracer.
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IsCompacting()) tracer_->set_is_compacting();
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MarkLiveObjects();
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_collect_maps) ClearNonLiveTransitions();
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SweepLargeObjectSpace();
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IsCompacting()) {
86f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_COMPACT);
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EncodeForwardingAddresses();
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->MarkMapPointersAsEncoded(true);
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UpdatePointers();
918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->MarkMapPointersAsEncoded(false);
928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->isolate()->pc_to_code_cache()->Flush();
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RelocateObjects();
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SweepSpaces();
978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->isolate()->pc_to_code_cache()->Flush();
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Finish();
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the count of marked objects remaining after the collection and
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // null out the GC tracer.
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  previous_marked_count_ = tracer_->marked_count();
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(previous_marked_count_ == 0);
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tracer_ = NULL;
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::Prepare(GCTracer* tracer) {
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Rather than passing the tracer around we stash it in a static member
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // variable.
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tracer_ = tracer;
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == IDLE);
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state_ = PREPARE_GC;
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!FLAG_always_compact || !FLAG_never_compact);
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  compacting_collection_ =
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      FLAG_always_compact || force_compaction_ || compact_on_next_gc_;
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  compact_on_next_gc_ = false;
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_never_compact) compacting_collection_ = false;
1268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!heap()->map_space()->MapPointersEncodable())
127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      compacting_collection_ = false;
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_collect_maps) CreateBackPointers();
129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#ifdef ENABLE_GDB_JIT_INTERFACE
130b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (FLAG_gdbjit) {
131b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // If GDBJIT interface is active disable compaction.
132b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    compacting_collection_ = false;
133b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PagedSpaces spaces;
137d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (PagedSpace* space = spaces.next();
138d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke       space != NULL; space = spaces.next()) {
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    space->PrepareForMarkCompact(compacting_collection_);
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  live_bytes_ = 0;
1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  live_young_objects_size_ = 0;
1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  live_old_pointer_objects_size_ = 0;
1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  live_old_data_objects_size_ = 0;
1476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  live_code_objects_size_ = 0;
1486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  live_map_objects_size_ = 0;
1496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  live_cell_objects_size_ = 0;
1506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  live_lo_objects_size_ = 0;
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::Finish() {
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS);
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state_ = IDLE;
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The stub cache is not traversed during GC; clear the cache to
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // force lazy re-initialization of it. This must be done after the
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // GC, because it relies on the new address of certain old space
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // objects (empty string, illegal builtin).
1648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->stub_cache()->Clear();
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->external_string_table_.CleanUp();
167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we've just compacted old space there's no reason to check the
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // fragmentation limit. Just return.
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (HasCompacted()) return;
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We compact the old generation on the next GC if it has gotten too
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // fragmented (ie, we could recover an expected amount of space by
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // reclaiming the waste and free list blocks).
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kFragmentationLimit = 15;        // Percent.
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kFragmentationAllowed = 1 * MB;  // Absolute.
177f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  intptr_t old_gen_recoverable = 0;
178f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  intptr_t old_gen_used = 0;
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OldSpaces spaces;
181d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (OldSpace* space = spaces.next(); space != NULL; space = spaces.next()) {
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    old_gen_recoverable += space->Waste() + space->AvailableFree();
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    old_gen_used += space->Size();
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int old_gen_fragmentation =
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      static_cast<int>((old_gen_recoverable * 100.0) / old_gen_used);
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (old_gen_fragmentation > kFragmentationLimit &&
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      old_gen_recoverable > kFragmentationAllowed) {
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    compact_on_next_gc_ = true;
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 1: tracing and marking live objects.
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   before: all objects are in normal state.
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   after: a live object's map pointer is marked as '00'.
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Marking all live objects in the heap as part of mark-sweep or mark-compact
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// collection.  Before marking, all objects are in their normal state.  After
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// marking, live objects' map pointers are marked indicating that the object
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// has been found reachable.
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The marking algorithm is a (mostly) depth-first (because of possible stack
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overflow) traversal of the graph of objects reachable from the roots.  It
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// uses an explicit stack of pointers rather than recursion.  The young
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// generation's inactive ('from') space is used as a marking stack.  The
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// objects in the marking stack are the ones that have been reached and marked
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// but their children have not yet been visited.
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The marking stack can overflow during traversal.  In that case, we set an
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overflow flag.  When the overflow flag is set, we continue marking objects
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// reachable from the objects on the marking stack, but no longer push them on
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the marking stack.  Instead, we mark them as both marked and overflowed.
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// When the stack is in the overflowed state, objects marked as overflowed
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// have been reached and marked but their children have not been visited yet.
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// After emptying the marking stack, we clear the overflow flag and traverse
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the heap looking for objects marked as overflowed, push them on the stack,
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and continue with marking.  This process repeats until all reachable
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// objects have been marked.
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass CodeFlusher {
224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
22544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit CodeFlusher(Isolate* isolate)
22644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : isolate_(isolate),
22744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        jsfunction_candidates_head_(NULL),
22844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        shared_function_info_candidates_head_(NULL) {}
22944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AddCandidate(SharedFunctionInfo* shared_info) {
231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetNextCandidate(shared_info, shared_function_info_candidates_head_);
232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    shared_function_info_candidates_head_ = shared_info;
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AddCandidate(JSFunction* function) {
236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(function->unchecked_code() ==
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           function->unchecked_shared()->unchecked_code());
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetNextCandidate(function, jsfunction_candidates_head_);
240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    jsfunction_candidates_head_ = function;
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
24344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void ProcessCandidates() {
244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ProcessSharedFunctionInfoCandidates();
245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ProcessJSFunctionCandidates();
246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
24944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void ProcessJSFunctionCandidates() {
25044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile);
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JSFunction* candidate = jsfunction_candidates_head_;
253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JSFunction* next_candidate;
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (candidate != NULL) {
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      next_candidate = GetNextCandidate(candidate);
256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SharedFunctionInfo* shared = candidate->unchecked_shared();
258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Code* code = shared->unchecked_code();
260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!code->IsMarked()) {
261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        shared->set_code(lazy_compile);
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        candidate->set_code(lazy_compile);
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        candidate->set_code(shared->unchecked_code());
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      candidate = next_candidate;
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    jsfunction_candidates_head_ = NULL;
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
27444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void ProcessSharedFunctionInfoCandidates() {
27544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile);
276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SharedFunctionInfo* candidate = shared_function_info_candidates_head_;
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SharedFunctionInfo* next_candidate;
279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (candidate != NULL) {
280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      next_candidate = GetNextCandidate(candidate);
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SetNextCandidate(candidate, NULL);
282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Code* code = candidate->unchecked_code();
284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!code->IsMarked()) {
285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        candidate->set_code(lazy_compile);
286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      candidate = next_candidate;
289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    shared_function_info_candidates_head_ = NULL;
292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static JSFunction** GetNextCandidateField(JSFunction* candidate) {
295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return reinterpret_cast<JSFunction**>(
296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        candidate->address() + JSFunction::kCodeEntryOffset);
297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static JSFunction* GetNextCandidate(JSFunction* candidate) {
300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return *GetNextCandidateField(candidate);
301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static void SetNextCandidate(JSFunction* candidate,
304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               JSFunction* next_candidate) {
305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    *GetNextCandidateField(candidate) = next_candidate;
306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  STATIC_ASSERT(kPointerSize <= Code::kHeaderSize - Code::kHeaderPaddingStart);
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static SharedFunctionInfo** GetNextCandidateField(
311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SharedFunctionInfo* candidate) {
312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Code* code = candidate->unchecked_code();
313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return reinterpret_cast<SharedFunctionInfo**>(
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        code->address() + Code::kHeaderPaddingStart);
315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static SharedFunctionInfo* GetNextCandidate(SharedFunctionInfo* candidate) {
318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return *GetNextCandidateField(candidate);
319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static void SetNextCandidate(SharedFunctionInfo* candidate,
322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               SharedFunctionInfo* next_candidate) {
323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    *GetNextCandidateField(candidate) = next_candidate;
324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate_;
32744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  JSFunction* jsfunction_candidates_head_;
32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SharedFunctionInfo* shared_function_info_candidates_head_;
329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
33044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DISALLOW_COPY_AND_ASSIGN(CodeFlusher);
331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
33444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMarkCompactCollector::~MarkCompactCollector() {
33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (code_flusher_ != NULL) {
33644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    delete code_flusher_;
33744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    code_flusher_ = NULL;
33844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
33944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
34044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline HeapObject* ShortCircuitConsString(Object** p) {
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Optimization: If the heap object pointed to by p is a non-symbol
34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // cons string whose right substring is HEAP->empty_string, update
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // it in place to its left substring.  Return the updated value.
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Here we assume that if we change *p, we replace it with a heap object
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // (ie, the left substring of a cons string is always a heap object).
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The check performed is:
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   object->IsConsString() && !object->IsSymbol() &&
35244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   (ConsString::cast(object)->second() == HEAP->empty_string())
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // except the maps for the object and its possible substrings might be
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // marked.
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapObject* object = HeapObject::cast(*p);
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord map_word = object->map_word();
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  map_word.ClearMark();
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstanceType type = map_word.ToMap()->instance_type();
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((type & kShortcutTypeMask) != kShortcutTypeTag) return object;
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* second = reinterpret_cast<ConsString*>(object)->unchecked_second();
36244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap = map_word.ToMap()->heap();
36344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (second != heap->raw_unchecked_empty_string()) {
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return object;
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Since we don't have the object's start, it is impossible to update the
3687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // page dirty marks. Therefore, we only replace the string with its left
3697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // substring when page dirty marks do not change.
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first();
37144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!heap->InNewSpace(object) && heap->InNewSpace(first)) return object;
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *p = first;
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return HeapObject::cast(first);
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
378756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickclass StaticMarkingVisitor : public StaticVisitorBase {
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
380756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline void IterateBody(Map* map, HeapObject* obj) {
381756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.GetVisitor(map)(map, obj);
382756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
383756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
384756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static void Initialize() {
385756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.Register(kVisitShortcutCandidate,
386756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                    &FixedBodyVisitor<StaticMarkingVisitor,
387756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                      ConsString::BodyDescriptor,
388756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                      void>::Visit);
389756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
390756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.Register(kVisitConsString,
391756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                    &FixedBodyVisitor<StaticMarkingVisitor,
392756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                      ConsString::BodyDescriptor,
393756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                      void>::Visit);
394756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
395756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
396756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.Register(kVisitFixedArray,
397756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                    &FlexibleBodyVisitor<StaticMarkingVisitor,
398756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                         FixedArray::BodyDescriptor,
399756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                         void>::Visit);
400756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
401f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    table_.Register(kVisitGlobalContext,
402f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                    &FixedBodyVisitor<StaticMarkingVisitor,
403f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                                      Context::MarkCompactBodyDescriptor,
404f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                                      void>::Visit);
405f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
406756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.Register(kVisitByteArray, &DataObjectVisitor::Visit);
407756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit);
408756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit);
409756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
410756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.Register(kVisitOddball,
411756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                    &FixedBodyVisitor<StaticMarkingVisitor,
412756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                      Oddball::BodyDescriptor,
413756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                      void>::Visit);
414756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.Register(kVisitMap,
415756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                    &FixedBodyVisitor<StaticMarkingVisitor,
416756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                      Map::BodyDescriptor,
417756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                      void>::Visit);
418756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
419756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.Register(kVisitCode, &VisitCode);
420756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    table_.Register(kVisitSharedFunctionInfo,
422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    &VisitSharedFunctionInfoAndFlushCode);
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    table_.Register(kVisitJSFunction,
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    &VisitJSFunctionAndFlushCode);
426756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
427756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.Register(kVisitPropertyCell,
428756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                    &FixedBodyVisitor<StaticMarkingVisitor,
429756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                      JSGlobalPropertyCell::BodyDescriptor,
430756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                      void>::Visit);
431756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
432756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.RegisterSpecializations<DataObjectVisitor,
433756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                   kVisitDataObject,
434756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                   kVisitDataObjectGeneric>();
435756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
436756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.RegisterSpecializations<JSObjectVisitor,
437756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                   kVisitJSObject,
438756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                   kVisitJSObjectGeneric>();
439756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
440756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    table_.RegisterSpecializations<StructObjectVisitor,
441756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                   kVisitStruct,
442756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                   kVisitStructGeneric>();
443756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
444756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
44544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  INLINE(static void VisitPointer(Heap* heap, Object** p)) {
44644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MarkObjectByPointer(heap, p);
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) {
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark all objects pointed to in [start, end).
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const int kMinRangeForMarkingRecursion = 64;
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (end - start >= kMinRangeForMarkingRecursion) {
45344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (VisitUnmarkedObjects(heap, start, end)) return;
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // We are close to a stack overflow, so just mark the objects.
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
45644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (Object** p = start; p < end; p++) MarkObjectByPointer(heap, p);
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static inline void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) {
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Code* code = Code::GetCodeFromTargetAddress(rinfo->target_address());
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (FLAG_cleanup_ics_at_gc && code->is_inline_cache_stub()) {
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      IC::Clear(rinfo->pc());
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Please note targets for cleared inline cached do not have to be
46544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // marked since they are contained in HEAP->non_monomorphic_cache().
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
4678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap->mark_compact_collector()->MarkObject(code);
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo) {
472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Object* cell = rinfo->target_cell();
474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Object* old_cell = cell;
4758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    VisitPointer(heap, &cell);
476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (cell != old_cell) {
477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static inline void VisitDebugTarget(Heap* heap, RelocInfo* rinfo) {
4827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
4837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            rinfo->IsPatchedReturnSequence()) ||
4847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch           (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
4857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            rinfo->IsPatchedDebugBreakSlotSequence()));
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapObject* code = Code::GetCodeFromTargetAddress(rinfo->call_address());
4878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap->mark_compact_collector()->MarkObject(code);
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark object pointed to by p.
49144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  INLINE(static void MarkObjectByPointer(Heap* heap, Object** p)) {
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!(*p)->IsHeapObject()) return;
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapObject* object = ShortCircuitConsString(p);
4948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (!object->IsMarked()) {
4958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap->mark_compact_collector()->MarkUnmarkedObject(object);
4968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Visit an unmarked object.
5018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  INLINE(static void VisitUnmarkedObject(MarkCompactCollector* collector,
5028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                         HeapObject* obj)) {
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
5048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(Isolate::Current()->heap()->Contains(obj));
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!obj->IsMarked());
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Map* map = obj->map();
50844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    collector->SetMark(obj);
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark the map pointer and the body.
5108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (!map->IsMarked()) collector->MarkUnmarkedObject(map);
511756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    IterateBody(map, obj);
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Visit all unmarked objects pointed to by [start, end).
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns false if the operation fails (lack of stack space).
51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static inline bool VisitUnmarkedObjects(Heap* heap,
51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Object** start,
51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Object** end) {
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Return false is we are close to the stack limit.
52044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    StackLimitCheck check(heap->isolate());
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (check.HasOverflowed()) return false;
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    MarkCompactCollector* collector = heap->mark_compact_collector();
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Visit the unmarked objects.
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Object** p = start; p < end; p++) {
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!(*p)->IsHeapObject()) continue;
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      HeapObject* obj = HeapObject::cast(*p);
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (obj->IsMarked()) continue;
5298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      VisitUnmarkedObject(collector, obj);
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return true;
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
533756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
534756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline void VisitExternalReference(Address* p) { }
535756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline void VisitRuntimeEntry(RelocInfo* rinfo) { }
536756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
537756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick private:
538756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  class DataObjectVisitor {
539756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick   public:
540756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    template<int size>
541756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    static void VisitSpecialized(Map* map, HeapObject* object) {
542756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
543756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
544756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    static void Visit(Map* map, HeapObject* object) {
545756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
546756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  };
547756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
548756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  typedef FlexibleBodyVisitor<StaticMarkingVisitor,
549756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                              JSObject::BodyDescriptor,
550756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                              void> JSObjectVisitor;
551756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
552756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  typedef FlexibleBodyVisitor<StaticMarkingVisitor,
553756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                              StructBodyDescriptor,
554756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                              void> StructObjectVisitor;
555756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
556756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static void VisitCode(Map* map, HeapObject* object) {
55744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>(
55844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        map->heap());
559756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
560756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
561756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Code flushing support.
562756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
563756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // How many collections newly compiled code object will survive before being
564756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // flushed.
565756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kCodeAgeThreshold = 5;
566756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
5678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) {
5688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Object* undefined = heap->raw_unchecked_undefined_value();
569756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return (info->script() != undefined) &&
570756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        (reinterpret_cast<Script*>(info->script())->source() != undefined);
571756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
572756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
573756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
574756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  inline static bool IsCompiled(JSFunction* function) {
57544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return function->unchecked_code() !=
5768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
577756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
578756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
579756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  inline static bool IsCompiled(SharedFunctionInfo* function) {
58044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return function->unchecked_code() !=
5818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
582756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
583756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
5848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  inline static bool IsFlushable(Heap* heap, JSFunction* function) {
585756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    SharedFunctionInfo* shared_info = function->unchecked_shared();
586756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Code is either on stack, in compilation cache or referenced
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // by optimized version of function.
589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->unchecked_code()->IsMarked()) {
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      shared_info->set_code_age(0);
591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
592756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
593756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // We do not flush code for optimized functions.
595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->code() != shared_info->unchecked_code()) {
596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return IsFlushable(heap, shared_info);
600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  inline static bool IsFlushable(Heap* heap, SharedFunctionInfo* shared_info) {
603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Code is either on stack, in compilation cache or referenced
604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // by optimized version of function.
605756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (shared_info->unchecked_code()->IsMarked()) {
606756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      shared_info->set_code_age(0);
607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
608756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
609756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
610756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The function must be compiled and have the source code available,
611756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // to be able to recompile it in case we need the function again.
6128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (!(shared_info->is_compiled() && HasSourceCode(heap, shared_info))) {
613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
615756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
616756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // We never flush code for Api functions.
617756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Object* function_data = shared_info->function_data();
618756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (function_data->IsHeapObject() &&
619756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        (SafeMap(function_data)->instance_type() ==
620756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick         FUNCTION_TEMPLATE_INFO_TYPE)) {
621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
622756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
623756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
624756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Only flush code for functions.
625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (shared_info->code()->kind() != Code::FUNCTION) return false;
626756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
627756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Function must be lazy compilable.
628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!shared_info->allows_lazy_compilation()) return false;
629756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
630756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // If this is a full script wrapped in a function we do no flush the code.
631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (shared_info->is_toplevel()) return false;
632756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
633756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Age this shared function info.
634756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (shared_info->code_age() < kCodeAgeThreshold) {
635756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      shared_info->set_code_age(shared_info->code_age() + 1);
636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
637756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
638756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return true;
640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
64344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static bool FlushCodeForFunction(Heap* heap, JSFunction* function) {
6448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (!IsFlushable(heap, function)) return false;
645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // This function's code looks flushable. But we have to postpone the
647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // decision until we see all functions that point to the same
648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // SharedFunctionInfo because some of them might be optimized.
649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // That would make the nonoptimized version of the code nonflushable,
650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // because it is required for bailing out from optimized code.
65144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap->mark_compact_collector()->code_flusher()->AddCandidate(function);
652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return true;
653756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
654756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
655756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
656756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline Map* SafeMap(Object* obj) {
657756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    MapWord map_word = HeapObject::cast(obj)->map_word();
658756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    map_word.ClearMark();
659756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    map_word.ClearOverflow();
660756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return map_word.ToMap();
661756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
662756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
663756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
664756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline bool IsJSBuiltinsObject(Object* obj) {
665756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return obj->IsHeapObject() &&
666756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        (SafeMap(obj)->instance_type() == JS_BUILTINS_OBJECT_TYPE);
667756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
668756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
669756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
670756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline bool IsValidNotBuiltinContext(Object* ctx) {
671756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (!ctx->IsHeapObject()) return false;
672756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
673756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Map* map = SafeMap(ctx);
67444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap = map->heap();
67544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!(map == heap->raw_unchecked_context_map() ||
67644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          map == heap->raw_unchecked_catch_context_map() ||
67744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          map == heap->raw_unchecked_global_context_map())) {
678756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      return false;
679756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
680756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
681756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Context* context = reinterpret_cast<Context*>(ctx);
682756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
683756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (IsJSBuiltinsObject(context->global())) {
684756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      return false;
685756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
686756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
687756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return true;
688756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
689756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
690756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static void VisitSharedFunctionInfoGeneric(Map* map, HeapObject* object) {
6920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object);
693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap();
695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    FixedBodyVisitor<StaticMarkingVisitor,
6970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                     SharedFunctionInfo::BodyDescriptor,
6980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                     void>::Visit(map, object);
6990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
7000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static void VisitSharedFunctionInfoAndFlushCode(Map* map,
703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HeapObject* object) {
70444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MarkCompactCollector* collector = map->heap()->mark_compact_collector();
70544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!collector->is_code_flushing_enabled()) {
70644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      VisitSharedFunctionInfoGeneric(map, object);
70744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
70844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitSharedFunctionInfoAndFlushCodeGeneric(map, object, false);
710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static void VisitSharedFunctionInfoAndFlushCodeGeneric(
714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Map* map, HeapObject* object, bool known_flush_code_candidate) {
71544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap = map->heap();
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object);
717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap();
719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!known_flush_code_candidate) {
7218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      known_flush_code_candidate = IsFlushable(heap, shared);
72244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (known_flush_code_candidate) {
72344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        heap->mark_compact_collector()->code_flusher()->AddCandidate(shared);
72444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
72744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitSharedFunctionInfoFields(heap, object, known_flush_code_candidate);
728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
73144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static void VisitCodeEntry(Heap* heap, Address entry_address) {
732791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    Object* code = Code::GetObjectFromEntryAddress(entry_address);
733791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    Object* old_code = code;
73444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitPointer(heap, &code);
735791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (code != old_code) {
736791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      Memory::Address_at(entry_address) =
737791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block          reinterpret_cast<Code*>(code)->entry();
738791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
739791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
740756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
741791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
742791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) {
74344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap = map->heap();
74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MarkCompactCollector* collector = heap->mark_compact_collector();
74544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!collector->is_code_flushing_enabled()) {
74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      VisitJSFunction(map, object);
74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
750791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object);
751756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The function must have a valid context and not be a builtin.
752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool flush_code_candidate = false;
753756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) {
75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      flush_code_candidate = FlushCodeForFunction(heap, jsfunction);
755756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!flush_code_candidate) {
75844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      collector->MarkObject(jsfunction->unchecked_shared()->unchecked_code());
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) {
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // For optimized functions we should retain both non-optimized version
762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // of it's code and non-optimized version of all inlined functions.
763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // This is required to support bailing out from inlined code.
764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        DeoptimizationInputData* data =
765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            reinterpret_cast<DeoptimizationInputData*>(
766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                jsfunction->unchecked_code()->unchecked_deoptimization_data());
767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FixedArray* literals = data->UncheckedLiteralArray();
769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        for (int i = 0, count = data->InlinedFunctionCount()->value();
771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             i < count;
772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             i++) {
773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i));
77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          collector->MarkObject(inlined->unchecked_shared()->unchecked_code());
775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitJSFunctionFields(map,
780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          reinterpret_cast<JSFunction*>(object),
781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          flush_code_candidate);
782791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
783791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
784791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
785791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  static void VisitJSFunction(Map* map, HeapObject* object) {
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitJSFunctionFields(map,
787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          reinterpret_cast<JSFunction*>(object),
788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          false);
789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define SLOT_ADDR(obj, offset) \
793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  reinterpret_cast<Object**>((obj)->address() + offset)
794756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static inline void VisitJSFunctionFields(Map* map,
797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           JSFunction* object,
798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           bool flush_code_candidate) {
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap = map->heap();
80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MarkCompactCollector* collector = heap->mark_compact_collector();
80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitPointers(heap,
80344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  SLOT_ADDR(object, JSFunction::kPropertiesOffset),
804791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                  SLOT_ADDR(object, JSFunction::kCodeEntryOffset));
805791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!flush_code_candidate) {
80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      VisitCodeEntry(heap, object->address() + JSFunction::kCodeEntryOffset);
808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Don't visit code object.
810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Visit shared function info to avoid double checking of it's
812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // flushability.
813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SharedFunctionInfo* shared_info = object->unchecked_shared();
814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!shared_info->IsMarked()) {
815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Map* shared_info_map = shared_info->map();
81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        collector->SetMark(shared_info);
81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        collector->MarkObject(shared_info_map);
818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VisitSharedFunctionInfoAndFlushCodeGeneric(shared_info_map,
819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   shared_info,
820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   true);
821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
823791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitPointers(heap,
82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  SLOT_ADDR(object,
826791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                            JSFunction::kCodeEntryOffset + kPointerSize),
827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                  SLOT_ADDR(object, JSFunction::kNonWeakFieldsEndOffset));
828f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Don't visit the next function list field as it is a weak reference.
830756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
831756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
832791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static void VisitSharedFunctionInfoFields(Heap* heap,
83444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            HeapObject* object,
835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            bool flush_code_candidate) {
83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kNameOffset));
837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!flush_code_candidate) {
83944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kCodeOffset));
840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
84244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitPointers(heap,
84344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  SLOT_ADDR(object, SharedFunctionInfo::kScopeInfoOffset),
844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                  SLOT_ADDR(object, SharedFunctionInfo::kSize));
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  #undef SLOT_ADDR
848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
849756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  typedef void (*Callback)(Map* map, HeapObject* object);
850756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
851756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static VisitorDispatchTable<Callback> table_;
852756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick};
853756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
854756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
855756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickVisitorDispatchTable<StaticMarkingVisitor::Callback>
856756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  StaticMarkingVisitor::table_;
857756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
858756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
859756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickclass MarkingVisitor : public ObjectVisitor {
860756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick public:
86144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit MarkingVisitor(Heap* heap) : heap_(heap) { }
86244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
863756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitPointer(Object** p) {
86444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    StaticMarkingVisitor::VisitPointer(heap_, p);
865756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
866756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
867756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitPointers(Object** start, Object** end) {
86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    StaticMarkingVisitor::VisitPointers(heap_, start, end);
869756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
870756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
8718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) {
8728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    StaticMarkingVisitor::VisitCodeTarget(heap, rinfo);
873756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
874756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
8758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo) {
8768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    StaticMarkingVisitor::VisitGlobalPropertyCell(heap, rinfo);
877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  void VisitDebugTarget(Heap* heap, RelocInfo* rinfo) {
8808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    StaticMarkingVisitor::VisitDebugTarget(heap, rinfo);
881756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
88244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
88344f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
88444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap_;
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
888756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickclass CodeMarkingVisitor : public ThreadVisitor {
889756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick public:
89044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit CodeMarkingVisitor(MarkCompactCollector* collector)
89144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : collector_(collector) {}
89244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
89544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      collector_->MarkObject(it.frame()->unchecked_code());
896756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
897756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
89944f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
90044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MarkCompactCollector* collector_;
901756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick};
902756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
903756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
904756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickclass SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
905756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick public:
90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector)
90744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : collector_(collector) {}
90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
909756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitPointers(Object** start, Object** end) {
910756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (Object** p = start; p < end; p++) VisitPointer(p);
911756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
912756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
913756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitPointer(Object** slot) {
914756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Object* obj = *slot;
915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (obj->IsSharedFunctionInfo()) {
916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj);
91744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      collector_->MarkObject(shared->unchecked_code());
91844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      collector_->MarkObject(shared);
919756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
920756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
92144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
92244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
92344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MarkCompactCollector* collector_;
924756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick};
925756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
926756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
927756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MarkCompactCollector::PrepareForCodeFlushing() {
9288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(heap() == Isolate::Current()->heap());
92944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
930756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (!FLAG_flush_code) {
93144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    EnableCodeFlushing(false);
932756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return;
933756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
934756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
935756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#ifdef ENABLE_DEBUGGER_SUPPORT
9368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (heap()->isolate()->debug()->IsLoaded() ||
9378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->isolate()->debug()->has_break_points()) {
93844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    EnableCodeFlushing(false);
939756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return;
940756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
941756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#endif
94244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  EnableCodeFlushing(true);
943756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
9449ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // Ensure that empty descriptor array is marked. Method MarkDescriptorArray
9459ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // relies on it being marked before any other descriptor array.
9468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MarkObject(heap()->raw_unchecked_empty_descriptor_array());
9479ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
948756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Make sure we are not referencing the code from the stack.
9498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(this == heap()->mark_compact_collector());
950756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (StackFrameIterator it; !it.done(); it.Advance()) {
9519ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    MarkObject(it.frame()->unchecked_code());
952756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
953756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
954756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Iterate the archived stacks in all threads to check if
955756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // the code is referenced.
95644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CodeMarkingVisitor code_marking_visitor(this);
9578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->thread_manager()->IterateArchivedThreads(
95844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &code_marking_visitor);
959756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
96044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SharedFunctionInfoMarkingVisitor visitor(this);
9618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->compilation_cache()->IterateFunctions(&visitor);
9628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->handle_scope_implementer()->Iterate(&visitor);
963756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
9649ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  ProcessMarkingStack();
965756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
966756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
967756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Visitor class for marking heap roots.
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RootMarkingVisitor : public ObjectVisitor {
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
97144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit RootMarkingVisitor(Heap* heap)
97244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : collector_(heap->mark_compact_collector()) { }
97344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitPointer(Object** p) {
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    MarkObjectByPointer(p);
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitPointers(Object** start, Object** end) {
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void MarkObjectByPointer(Object** p) {
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!(*p)->IsHeapObject()) return;
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Replace flat cons strings in place.
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapObject* object = ShortCircuitConsString(p);
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (object->IsMarked()) return;
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Map* map = object->map();
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark the object.
99244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    collector_->SetMark(object);
993756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark the map pointer and body, and push them on the marking stack.
99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    collector_->MarkObject(map);
996756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    StaticMarkingVisitor::IterateBody(map, object);
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark all the objects reachable from the map and body.  May leave
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // overflowed objects in the heap.
100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    collector_->EmptyMarkingStack();
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
100244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
100344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MarkCompactCollector* collector_;
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class for pruning the symbol table.
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SymbolTableCleaner : public ObjectVisitor {
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
10108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  explicit SymbolTableCleaner(Heap* heap)
10118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : heap_(heap), pointers_removed_(0) { }
1012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  virtual void VisitPointers(Object** start, Object** end) {
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Visit all HeapObject pointers in [start, end).
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Object** p = start; p < end; p++) {
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked()) {
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Check if the symbol being pruned is an external symbol. We need to
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // delete the associated external data as this symbol is going away.
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Since no objects have yet been moved we can safely access the map of
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // the object.
1022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if ((*p)->IsExternalString()) {
10238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          heap_->FinalizeExternalString(String::cast(*p));
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Set the entry to null_value (as deleted).
10268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        *p = heap_->raw_unchecked_null_value();
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        pointers_removed_++;
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PointersRemoved() {
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return pointers_removed_;
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
10368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Heap* heap_;
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pointers_removed_;
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// Implementation of WeakObjectRetainer for mark compact GCs. All marked objects
1042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// are retained.
1043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochclass MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
1044f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch public:
1045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  virtual Object* RetainAs(Object* object) {
1046f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    MapWord first_word = HeapObject::cast(object)->map_word();
1047f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    if (first_word.IsMarked()) {
1048f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      return object;
1049f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    } else {
1050f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      return NULL;
1051f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    }
1052f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
1053f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch};
1054f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1055f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!object->IsMarked());
105844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(HEAP->Contains(object));
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsMap()) {
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Map* map = Map::cast(object);
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (FLAG_cleanup_caches_in_maps_at_gc) {
10628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      map->ClearCodeCache(heap());
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SetMark(map);
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (FLAG_collect_maps &&
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        map->instance_type() <= JS_FUNCTION_TYPE) {
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      MarkMapContents(map);
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
107044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      marking_stack_.Push(map);
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SetMark(object);
107444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    marking_stack_.Push(object);
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkMapContents(Map* map) {
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MarkDescriptorArray(reinterpret_cast<DescriptorArray*>(
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *HeapObject::RawField(map, Map::kInstanceDescriptorsOffset)));
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark the Object* fields of the Map.
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Since the descriptor array has been marked already, it is fine
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // that one of these fields contains a pointer to it.
1086756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Object** start_slot = HeapObject::RawField(map,
1087756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                             Map::kPointerFieldsBeginOffset);
1088756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1089756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Object** end_slot = HeapObject::RawField(map, Map::kPointerFieldsEndOffset);
1090756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
109144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  StaticMarkingVisitor::VisitPointers(map->heap(), start_slot, end_slot);
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkDescriptorArray(
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DescriptorArray* descriptors) {
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (descriptors->IsMarked()) return;
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Empty descriptor array is marked as a root before any maps are marked.
109944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(descriptors != HEAP->raw_unchecked_empty_descriptor_array());
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetMark(descriptors);
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FixedArray* contents = reinterpret_cast<FixedArray*>(
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      descriptors->get(DescriptorArray::kContentArrayIndex));
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(contents->IsHeapObject());
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!contents->IsMarked());
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(contents->IsFixedArray());
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(contents->length() >= 2);
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetMark(contents);
110944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Contents contains (value, details) pairs.  If the details say that the type
111044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION,
111144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // EXTERNAL_ARRAY_TRANSITION or NULL_DESCRIPTOR, we don't mark the value as
111244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // live.  Only for MAP_TRANSITION, EXTERNAL_ARRAY_TRANSITION and
111344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // CONSTANT_TRANSITION is the value an Object* (a Map*).
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < contents->length(); i += 2) {
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If the pair (value, details) at index i, i+1 is not
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // a transition or null descriptor, mark the value.
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PropertyDetails details(Smi::cast(contents->get(i + 1)));
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (details.type() < FIRST_PHANTOM_PROPERTY_TYPE) {
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      HeapObject* object = reinterpret_cast<HeapObject*>(contents->get(i));
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsHeapObject() && !object->IsMarked()) {
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        SetMark(object);
112244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        marking_stack_.Push(object);
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The DescriptorArray descriptors contains a pointer to its contents array,
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // but the contents array is already marked.
112844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  marking_stack_.Push(descriptors);
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::CreateBackPointers() {
11338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HeapObjectIterator iterator(heap()->map_space());
1134d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (HeapObject* next_object = iterator.next();
1135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke       next_object != NULL; next_object = iterator.next()) {
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (next_object->IsMap()) {  // Could also be ByteArray on free list.
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Map* map = Map::cast(next_object);
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          map->instance_type() <= JS_FUNCTION_TYPE) {
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        map->CreateBackPointers();
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
11428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        ASSERT(map->instance_descriptors() == heap()->empty_descriptor_array());
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int OverflowObjectSize(HeapObject* obj) {
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Recover the normal map pointer, it might be marked as live and
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // overflowed.
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord map_word = obj->map_word();
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  map_word.ClearMark();
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  map_word.ClearOverflow();
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj->SizeFromMap(map_word.ToMap());
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass OverflowedObjectsScanner : public AllStatic {
116044f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
116144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Fill the marking stack with overflowed objects returned by the given
116244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // iterator.  Stop when the marking stack is filled or the end of the space
116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // is reached, whichever comes first.
116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  template<class T>
116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static inline void ScanOverflowedObjects(MarkCompactCollector* collector,
116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           T* it) {
116744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The caller should ensure that the marking stack is initially not full,
116844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // so that we don't waste effort pointlessly scanning for objects.
116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(!collector->marking_stack_.is_full());
117044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
117144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (HeapObject* object = it->next(); object != NULL; object = it->next()) {
117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (object->IsOverflowed()) {
117344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        object->ClearOverflow();
117444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ASSERT(object->IsMarked());
117544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ASSERT(HEAP->Contains(object));
117644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        collector->marking_stack_.Push(object);
117744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (collector->marking_stack_.is_full()) return;
117844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
118144f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) {
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return (*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked();
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkSymbolTable() {
11908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SymbolTable* symbol_table = heap()->raw_unchecked_symbol_table();
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark the symbol table itself.
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetMark(symbol_table);
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Explicitly mark the prefix.
11948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MarkingVisitor marker(heap());
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  symbol_table->IteratePrefix(&marker);
1196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ProcessMarkingStack();
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) {
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark the heap roots including global variables, stack variables,
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // etc., and all objects reachable from them.
12038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG);
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle the symbol table specially.
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MarkSymbolTable();
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // There may be overflowed objects in the heap.  Visit them now.
120944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (marking_stack_.overflowed()) {
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RefillMarkingStack();
1211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    EmptyMarkingStack();
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkObjectGroups() {
121744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  List<ObjectGroup*>* object_groups =
12188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->isolate()->global_handles()->object_groups();
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int last = 0;
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < object_groups->length(); i++) {
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ObjectGroup* entry = object_groups->at(i);
12238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(entry != NULL);
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Object*** objects = entry->objects_;
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool group_marked = false;
12278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    for (size_t j = 0; j < entry->length_; j++) {
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Object* object = *objects[j];
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsHeapObject() && HeapObject::cast(object)->IsMarked()) {
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        group_marked = true;
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (!group_marked) {
12368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      (*object_groups)[last++] = entry;
12378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      continue;
12388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // An object in the group is marked, so mark all heap objects in
12418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // the group.
12428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    for (size_t j = 0; j < entry->length_; ++j) {
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((*objects[j])->IsHeapObject()) {
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        MarkObject(HeapObject::cast(*objects[j]));
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
124744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // Once the entire group has been marked, dispose it because it's
12498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // not needed anymore.
12508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    entry->Dispose();
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
12528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  object_groups->Rewind(last);
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
125644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MarkCompactCollector::MarkImplicitRefGroups() {
125744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  List<ImplicitRefGroup*>* ref_groups =
12588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->isolate()->global_handles()->implicit_ref_groups();
125944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int last = 0;
126144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < ref_groups->length(); i++) {
126244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ImplicitRefGroup* entry = ref_groups->at(i);
12638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(entry != NULL);
126444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (!(*entry->parent_)->IsMarked()) {
12668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      (*ref_groups)[last++] = entry;
12678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      continue;
12688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
126944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Object*** children = entry->children_;
12718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // A parent object is marked, so mark all child heap objects.
12728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    for (size_t j = 0; j < entry->length_; ++j) {
127344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if ((*children[j])->IsHeapObject()) {
127444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        MarkObject(HeapObject::cast(*children[j]));
127544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
127644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
127744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // Once the entire group has been marked, dispose it because it's
12798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // not needed anymore.
12808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    entry->Dispose();
128144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
12828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ref_groups->Rewind(last);
128344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
128444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
128544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mark all objects reachable from the objects on the marking stack.
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Before: the marking stack contains zero or more heap object pointers.
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// After: the marking stack is empty, and all objects reachable from the
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// marking stack have been marked, or are overflowed in the heap.
1290756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MarkCompactCollector::EmptyMarkingStack() {
129144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (!marking_stack_.is_empty()) {
129244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HeapObject* object = marking_stack_.Pop();
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(object->IsHeapObject());
12948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(heap()->Contains(object));
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(object->IsMarked());
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!object->IsOverflowed());
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Because the object is marked, we have to recover the original map
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // pointer and use it to mark the object's body.
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    MapWord map_word = object->map_word();
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    map_word.ClearMark();
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Map* map = map_word.ToMap();
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    MarkObject(map);
1304756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1305756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    StaticMarkingVisitor::IterateBody(map, object);
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Sweep the heap for overflowed objects, clear their overflow bits, and
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// push them on the marking stack.  Stop early if the marking stack fills
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// before sweeping completes.  If sweeping completes, there are no remaining
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overflowed objects in the heap so the overflow flag on the markings stack
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is cleared.
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::RefillMarkingStack() {
131644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(marking_stack_.overflowed());
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SemiSpaceIterator new_it(heap()->new_space(), &OverflowObjectSize);
131944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &new_it);
132044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HeapObjectIterator old_pointer_it(heap()->old_pointer_space(),
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    &OverflowObjectSize);
132444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &old_pointer_it);
132544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HeapObjectIterator old_data_it(heap()->old_data_space(), &OverflowObjectSize);
132844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &old_data_it);
132944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HeapObjectIterator code_it(heap()->code_space(), &OverflowObjectSize);
133244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &code_it);
133344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HeapObjectIterator map_it(heap()->map_space(), &OverflowObjectSize);
133644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &map_it);
133744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HeapObjectIterator cell_it(heap()->cell_space(), &OverflowObjectSize);
134044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &cell_it);
134144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  LargeObjectIterator lo_it(heap()->lo_space(), &OverflowObjectSize);
134444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &lo_it);
134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  marking_stack_.clear_overflowed();
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mark all objects reachable (transitively) from objects on the marking
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// stack.  Before: the marking stack contains zero or more heap object
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// pointers.  After: the marking stack is empty and there are no overflowed
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// objects in the heap.
1355756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MarkCompactCollector::ProcessMarkingStack() {
1356756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  EmptyMarkingStack();
135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (marking_stack_.overflowed()) {
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RefillMarkingStack();
1359756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    EmptyMarkingStack();
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
136444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MarkCompactCollector::ProcessExternalMarking() {
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool work_to_do = true;
136644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(marking_stack_.is_empty());
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (work_to_do) {
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    MarkObjectGroups();
136944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MarkImplicitRefGroups();
137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    work_to_do = !marking_stack_.is_empty();
1371756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ProcessMarkingStack();
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkLiveObjects() {
1377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_MARK);
1378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The recursive GC marker detects when it is nearing stack overflow,
1379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // and switches to a different marking system.  JS interrupts interfere
1380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // with the C stack limit check.
13818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  PostponeInterruptsScope postpone(heap()->isolate());
1382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == PREPARE_GC);
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state_ = MARK_LIVE_OBJECTS;
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The to space contains live objects, the from space is used as a marking
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stack.
13898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  marking_stack_.Initialize(heap()->new_space()->FromSpaceLow(),
13908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                            heap()->new_space()->FromSpaceHigh());
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!marking_stack_.overflowed());
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1394756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PrepareForCodeFlushing();
1395756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
13968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  RootMarkingVisitor root_visitor(heap());
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MarkRoots(&root_visitor);
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The objects reachable from the roots are marked, yet unreachable
140044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // objects are unmarked.  Mark objects reachable due to host
140144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // application specific logic.
140244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ProcessExternalMarking();
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The objects reachable from the roots or object groups are marked,
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // yet unreachable objects are unmarked.  Mark objects reachable
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // only from weak global handles.
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // First we identify nonlive weak handles and mark them as pending
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // destruction.
14108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->global_handles()->IdentifyWeakHandles(
141144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &IsUnmarkedHeapObject);
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Then we mark the objects and process the transitive closure.
14138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->global_handles()->IterateWeakRoots(&root_visitor);
141444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (marking_stack_.overflowed()) {
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RefillMarkingStack();
1416756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    EmptyMarkingStack();
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Repeat host application specific marking to mark unmarked objects
142044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // reachable from the weak roots.
142144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ProcessExternalMarking();
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Prune the symbol table removing all symbols only pointed to by the
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // symbol table.  Cannot use symbol_table() here because the symbol
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // table is marked.
14268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SymbolTable* symbol_table = heap()->raw_unchecked_symbol_table();
14278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SymbolTableCleaner v(heap());
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  symbol_table->IterateElements(&v);
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  symbol_table->ElementsRemoved(v.PointersRemoved());
14308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->external_string_table_.Iterate(&v);
14318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->external_string_table_.CleanUp();
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1433f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Process the weak references.
1434f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  MarkCompactWeakObjectRetainer mark_compact_object_retainer;
14358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->ProcessWeakReferences(&mark_compact_object_retainer);
1436f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove object groups after marking phase.
14388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->global_handles()->RemoveObjectGroups();
14398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->global_handles()->RemoveImplicitRefGroups();
1440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Flush code from collected candidates.
144244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_code_flushing_enabled()) {
144344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    code_flusher_->ProcessCandidates();
144444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Clean up dead objects from the runtime profiler.
14478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->runtime_profiler()->RemoveDeadSamples();
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) {
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  live_bytes_ += obj->Size();
14548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (heap()->new_space()->Contains(obj)) {
14556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_young_objects_size_ += obj->Size();
14568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (heap()->map_space()->Contains(obj)) {
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(obj->IsMap());
14586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_map_objects_size_ += obj->Size();
14598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (heap()->cell_space()->Contains(obj)) {
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(obj->IsJSGlobalPropertyCell());
14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_cell_objects_size_ += obj->Size();
14628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (heap()->old_pointer_space()->Contains(obj)) {
14636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_old_pointer_objects_size_ += obj->Size();
14648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (heap()->old_data_space()->Contains(obj)) {
14656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_old_data_objects_size_ += obj->Size();
14668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (heap()->code_space()->Contains(obj)) {
14676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_code_objects_size_ += obj->Size();
14688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (heap()->lo_space()->Contains(obj)) {
14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_lo_objects_size_ += obj->Size();
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UNREACHABLE();
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // DEBUG
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::SweepLargeObjectSpace() {
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == MARK_LIVE_OBJECTS);
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state_ =
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      compacting_collection_ ? ENCODE_FORWARDING_ADDRESSES : SWEEP_SPACES;
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Deallocate unmarked objects and clear marked bits for marked objects.
14848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->lo_space()->FreeUnmarkedObjects();
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Safe to use during marking phase only.
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool MarkCompactCollector::SafeIsMap(HeapObject* object) {
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord metamap = object->map_word();
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  metamap.ClearMark();
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return metamap.ToMap()->instance_type() == MAP_TYPE;
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::ClearNonLiveTransitions() {
14978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HeapObjectIterator map_iterator(heap() ->map_space(), &SizeOfMarkedObject);
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Iterate over the map space, setting map transitions that go from
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a marked map to an unmarked map to null transitions.  At the same time,
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // set all the prototype fields of maps back to their original value,
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // dropping the back pointers temporarily stored in the prototype field.
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setting the prototype field requires following the linked list of
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // back pointers, reversing them all at once.  This allows us to find
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // those maps with map transitions that need to be nulled, and only
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scan the descriptor arrays of those maps, not all maps.
1506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // All of these actions are carried out only on maps of JSObjects
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and related subtypes.
1508d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (HeapObject* obj = map_iterator.next();
1509d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke       obj != NULL; obj = map_iterator.next()) {
1510d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Map* map = reinterpret_cast<Map*>(obj);
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!map->IsMarked() && map->IsByteArray()) continue;
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(SafeIsMap(map));
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Only JSObject and subtypes have map transitions and back pointers.
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue;
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (map->instance_type() > JS_FUNCTION_TYPE) continue;
15170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
15180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (map->IsMarked() && map->attached_to_shared_function_info()) {
15190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // This map is used for inobject slack tracking and has been detached
15200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // from SharedFunctionInfo during the mark phase.
15210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Since it survived the GC, reattach it now.
15220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map);
15230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
15240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Follow the chain of back pointers to find the prototype.
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Map* current = map;
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (SafeIsMap(current)) {
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current = reinterpret_cast<Map*>(current->prototype());
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(current->IsHeapObject());
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object* real_prototype = current;
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Follow back pointers, setting them to prototype,
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // clearing map transitions when necessary.
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current = map;
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool on_dead_path = !current->IsMarked();
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object* next;
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (SafeIsMap(current)) {
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      next = current->prototype();
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // There should never be a dead map above a live map.
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(on_dead_path || current->IsMarked());
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // A live map above a dead map indicates a dead transition.
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // This test will always be false on the first iteration.
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (on_dead_path && current->IsMarked()) {
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        on_dead_path = false;
15478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        current->ClearNonLiveTransitions(heap(), real_prototype);
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *HeapObject::RawField(current, Map::kPrototypeOffset) =
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          real_prototype;
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current = reinterpret_cast<Map*>(next);
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 2: Encode forwarding addresses.
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// When compacting, forwarding addresses for objects in old space and map
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// space are encoded in their map pointer word (along with an encoding of
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// their map pointers).
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
1562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// The excact encoding is described in the comments for class MapWord in
1563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// objects.h.
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// An address range [start, end) can have both live and non-live objects.
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Maximal non-live regions are marked so they can be skipped on subsequent
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sweeps of the heap.  A distinguished map-pointer encoding is used to mark
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// free regions of one-word size (in which case the next word is the start
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of a live object).  A second distinguished map-pointer encoding is used
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to mark free regions larger than one word, and the size of the free
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// region (including the first word) is written to the second word of the
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// region.
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Any valid map page offset must lie in the object area of the page, so map
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// page offsets less than Page::kObjectStartOffset are invalid.  We use a
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// pair of distinguished invalid map encodings (for single word and multiple
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// words) to indicate free regions in the page found during computation of
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forwarding addresses and skipped over in subsequent sweeps.
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Encode a free region, defined by the given start address and size, in the
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// first word or two of the region.
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid EncodeFreeRegion(Address free_start, int free_size) {
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(free_size >= kIntSize);
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (free_size == kIntSize) {
158680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Memory::uint32_at(free_start) = MarkCompactCollector::kSingleFreeEncoding;
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(free_size >= 2 * kIntSize);
158980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Memory::uint32_at(free_start) = MarkCompactCollector::kMultiFreeEncoding;
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Memory::int_at(free_start + kIntSize) = free_size;
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Zap the body of the free region.
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_enable_slow_asserts) {
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int offset = 2 * kIntSize;
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         offset < free_size;
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         offset += kPointerSize) {
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Memory::Address_at(free_start + offset) = kZapValue;
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Try to promote all objects in new space.  Heap numbers and sequential
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// strings are promoted to the code space, large objects to large object space,
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and all others to the old space.
160944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockinline MaybeObject* MCAllocateFromNewSpace(Heap* heap,
161044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           HeapObject* object,
16115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                           int object_size) {
16125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MaybeObject* forwarded;
161344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (object_size > heap->MaxObjectSizeInPagedSpace()) {
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    forwarded = Failure::Exception();
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
161644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    OldSpace* target_space = heap->TargetSpace(object);
161744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target_space == heap->old_pointer_space() ||
161844f0eee88ff00398ff7f715fab053374d808c90dSteve Block           target_space == heap->old_data_space());
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    forwarded = target_space->MCAllocateRaw(object_size);
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
16215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* result;
16225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!forwarded->ToObject(&result)) {
162344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result = heap->new_space()->MCAllocateRaw(object_size)->ToObjectUnchecked();
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
16255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  return result;
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocation functions for the paged spaces call the space's MCAllocateRaw.
16305913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT inline MaybeObject* MCAllocateFromOldPointerSpace(
163144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap *heap,
16325913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    HeapObject* ignore,
16335913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int object_size) {
163444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return heap->old_pointer_space()->MCAllocateRaw(object_size);
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16385913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT inline MaybeObject* MCAllocateFromOldDataSpace(
163944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap,
16405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    HeapObject* ignore,
16415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int object_size) {
164244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return heap->old_data_space()->MCAllocateRaw(object_size);
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16465913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT inline MaybeObject* MCAllocateFromCodeSpace(
164744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap,
16485913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    HeapObject* ignore,
16495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int object_size) {
165044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return heap->code_space()->MCAllocateRaw(object_size);
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16545913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT inline MaybeObject* MCAllocateFromMapSpace(
165544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap,
16565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    HeapObject* ignore,
16575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int object_size) {
165844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return heap->map_space()->MCAllocateRaw(object_size);
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMUST_USE_RESULT inline MaybeObject* MCAllocateFromCellSpace(
166344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap, HeapObject* ignore, int object_size) {
166444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return heap->cell_space()->MCAllocateRaw(object_size);
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The forwarding address is encoded at the same offset as the current
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to-space object, but in from space.
167044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockinline void EncodeForwardingAddressInNewSpace(Heap* heap,
167144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              HeapObject* old_object,
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              int object_size,
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              Object* new_object,
1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              int* ignored) {
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset =
167644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap->new_space()->ToSpaceOffsetForAddress(old_object->address());
167744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Memory::Address_at(heap->new_space()->FromSpaceLow() + offset) =
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      HeapObject::cast(new_object)->address();
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The forwarding address is encoded in the map pointer of the object as an
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// offset (in terms of live bytes) from the address of the first live object
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// in the page.
168544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockinline void EncodeForwardingAddressInPagedSpace(Heap* heap,
168644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                HeapObject* old_object,
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                int object_size,
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                Object* new_object,
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                int* offset) {
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Record the forwarding address of the first live object if necessary.
1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*offset == 0) {
1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Page::FromAddress(old_object->address())->mc_first_forwarded =
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        HeapObject::cast(new_object)->address();
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding =
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      MapWord::EncodeAddress(old_object->map()->address(), *offset);
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  old_object->set_map_word(encoding);
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *offset += object_size;
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(*offset <= Page::kObjectAreaSize);
1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Most non-live objects are ignored.
17058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochinline void IgnoreNonLiveObject(HeapObject* object, Isolate* isolate) {}
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Function template that, given a range of addresses (eg, a semispace or a
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// paged space page), iterates through the objects in the range to clear
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mark bits and compute and encode forwarding addresses.  As a side effect,
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// maximal free chunks are marked so that they can be skipped on subsequent
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sweeps.
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The template parameters are an allocation function, a forwarding address
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// encoding function, and a function to process non-live objects.
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate<MarkCompactCollector::AllocationFunction Alloc,
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MarkCompactCollector::EncodingFunction Encode,
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
171944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockinline void EncodeForwardingAddressesInRange(MarkCompactCollector* collector,
172044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             Address start,
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Address end,
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             int* offset) {
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The start address of the current free region while sweeping the space.
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This address is set when a transition from live to non-live objects is
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // encountered.  A value (an encoding of the 'next free region' pointer)
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is written to memory at this address when a transition from non-live to
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // live objects is encountered.
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address free_start = NULL;
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // A flag giving the state of the previously swept object.  Initially true
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to ensure that free_start is initialized to a proper address before
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // trying to write to it.
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_prev_alive = true;
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int object_size;  // Will be set on each iteration of the loop.
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Address current = start; current < end; current += object_size) {
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapObject* object = HeapObject::FromAddress(current);
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (object->IsMarked()) {
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      object->ClearMark();
174044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      collector->tracer()->decrement_marked_count();
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      object_size = object->Size();
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
174344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Object* forwarded =
174444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          Alloc(collector->heap(), object, object_size)->ToObjectUnchecked();
174544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Encode(collector->heap(), object, object_size, forwarded, offset);
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (FLAG_gc_verbose) {
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("forward %p -> %p.\n", object->address(),
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               HeapObject::cast(forwarded)->address());
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!is_prev_alive) {  // Transition from non-live to live.
1754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        EncodeFreeRegion(free_start, static_cast<int>(current - free_start));
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        is_prev_alive = true;
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {  // Non-live object.
1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      object_size = object->Size();
17598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ProcessNonLive(object, collector->heap()->isolate());
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (is_prev_alive) {  // Transition from live to non-live.
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        free_start = current;
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        is_prev_alive = false;
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
17641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      LiveObjectList::ProcessNonLive(object);
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we ended on a free region, mark it.
1769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (!is_prev_alive) {
1770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EncodeFreeRegion(free_start, static_cast<int>(end - free_start));
1771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Functions to encode the forwarding pointers in each compactable space.
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::EncodeForwardingAddressesInNewSpace() {
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int ignored;
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInRange<MCAllocateFromNewSpace,
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   EncodeForwardingAddressInNewSpace,
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   IgnoreNonLiveObject>(
178144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      this,
17828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->new_space()->bottom(),
17838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->new_space()->top(),
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      &ignored);
1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate<MarkCompactCollector::AllocationFunction Alloc,
1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::EncodeForwardingAddressesInPagedSpace(
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PagedSpace* space) {
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PageIterator it(space, PageIterator::PAGES_IN_USE);
1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (it.has_next()) {
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Page* p = it.next();
17956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The offset of each live object in the page from the first live object
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in the page.
1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = 0;
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EncodeForwardingAddressesInRange<Alloc,
1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     EncodeForwardingAddressInPagedSpace,
1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     ProcessNonLive>(
180244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        this,
1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        p->ObjectAreaStart(),
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        p->AllocationTop(),
1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        &offset);
1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// We scavange new space simultaneously with sweeping. This is done in two
18116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// passes.
18126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// The first pass migrates all alive objects from one semispace to another or
18136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// promotes them to old space. Forwading address is written directly into
18146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// first word of object without any encoding. If object is dead we are writing
18156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// NULL as a forwarding address.
18166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// The second pass updates pointers to new space in all spaces. It is possible
18177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// to encounter pointers to dead objects during traversal of dirty regions we
18187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// should clear them to avoid encountering them during next dirty regions
18197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// iteration.
182044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void MigrateObject(Heap* heap,
182144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Address dst,
18227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          Address src,
18237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          int size,
18247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          bool to_old_space) {
18257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (to_old_space) {
182644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap->CopyBlockToOldSpaceAndUpdateRegionMarks(dst, src, size);
18277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
182844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap->CopyBlock(dst, src, size);
18297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
18306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Memory::Address_at(src) = dst;
18326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
18336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1835756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickclass StaticPointersToNewGenUpdatingVisitor : public
1836756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  StaticNewSpaceVisitor<StaticPointersToNewGenUpdatingVisitor> {
1837756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick public:
183844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static inline void VisitPointer(Heap* heap, Object** p) {
1839756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (!(*p)->IsHeapObject()) return;
1840756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1841756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    HeapObject* obj = HeapObject::cast(*p);
1842756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Address old_addr = obj->address();
1843756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
184444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (heap->new_space()->Contains(obj)) {
184544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(heap->InFromSpace(*p));
1846756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      *p = HeapObject::FromAddress(Memory::Address_at(old_addr));
1847756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
1848756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
1849756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick};
1850756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1851756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
18526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Visitor for updating pointers from live objects in old spaces to new space.
18536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It does not expect to encounter pointers to dead objects.
18546ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass PointersToNewGenUpdatingVisitor: public ObjectVisitor {
18556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
185644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit PointersToNewGenUpdatingVisitor(Heap* heap) : heap_(heap) { }
185744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
18586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitPointer(Object** p) {
185944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    StaticPointersToNewGenUpdatingVisitor::VisitPointer(heap_, p);
18606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
18616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitPointers(Object** start, Object** end) {
1863756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (Object** p = start; p < end; p++) {
186444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      StaticPointersToNewGenUpdatingVisitor::VisitPointer(heap_, p);
1865756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
18666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
18676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitCodeTarget(RelocInfo* rinfo) {
18696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
18706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
18716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    VisitPointer(&target);
18726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    rinfo->set_target_address(Code::cast(target)->instruction_start());
18736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
18746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitDebugTarget(RelocInfo* rinfo) {
18767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
18777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            rinfo->IsPatchedReturnSequence()) ||
18787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch           (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
18797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            rinfo->IsPatchedDebugBreakSlotSequence()));
18806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
18816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    VisitPointer(&target);
18826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    rinfo->set_call_address(Code::cast(target)->instruction_start());
18836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
188444f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
188544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap_;
18866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
18876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Visitor for updating pointers from live objects in old spaces to new space.
18906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It can encounter pointers to dead objects in new space when traversing map
18916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// space (see comment for MigrateObject).
18926ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void UpdatePointerToNewGen(HeapObject** p) {
18936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!(*p)->IsHeapObject()) return;
18946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address old_addr = (*p)->address();
189644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(HEAP->InFromSpace(*p));
18976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address new_addr = Memory::Address_at(old_addr);
18996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (new_addr == NULL) {
19017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // We encountered pointer to a dead object. Clear it so we will
19027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // not visit it again during next iteration of dirty regions.
19037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    *p = NULL;
19047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
19057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    *p = HeapObject::FromAddress(new_addr);
19067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
19076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
19086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
191044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic String* UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
191144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                                 Object** p) {
19126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address old_addr = HeapObject::cast(*p)->address();
19136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address new_addr = Memory::Address_at(old_addr);
19146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return String::cast(HeapObject::FromAddress(new_addr));
19156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
19166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
191844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic bool TryPromoteObject(Heap* heap, HeapObject* object, int object_size) {
19196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* result;
19206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
192144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (object_size > heap->MaxObjectSizeInPagedSpace()) {
19225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    MaybeObject* maybe_result =
192344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        heap->lo_space()->AllocateRawFixedArray(object_size);
19245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (maybe_result->ToObject(&result)) {
19256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      HeapObject* target = HeapObject::cast(result);
192644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      MigrateObject(heap, target->address(), object->address(), object_size,
192744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    true);
192844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap->mark_compact_collector()->tracer()->
1929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          increment_promoted_objects_size(object_size);
19306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
19316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
19326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
193344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    OldSpace* target_space = heap->TargetSpace(object);
19346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
193544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target_space == heap->old_pointer_space() ||
193644f0eee88ff00398ff7f715fab053374d808c90dSteve Block           target_space == heap->old_data_space());
19375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    MaybeObject* maybe_result = target_space->AllocateRaw(object_size);
19385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (maybe_result->ToObject(&result)) {
19396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      HeapObject* target = HeapObject::cast(result);
194044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      MigrateObject(heap,
194144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    target->address(),
19427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    object->address(),
19437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    object_size,
194444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    target_space == heap->old_pointer_space());
194544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap->mark_compact_collector()->tracer()->
1946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          increment_promoted_objects_size(object_size);
19476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
19486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
19496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
19506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return false;
19526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
19536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
195544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void SweepNewSpace(Heap* heap, NewSpace* space) {
195644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->CheckNewSpaceExpansionCriteria();
19576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address from_bottom = space->bottom();
19596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address from_top = space->top();
19606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Flip the semispaces.  After flipping, to space is empty, from space has
19626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // live objects.
19636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  space->Flip();
19646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  space->ResetAllocationInfo();
19656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int size = 0;
19676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int survivors_size = 0;
19686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // First pass: traverse all objects in inactive semispace, remove marks,
19706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // migrate live objects and write forwarding addresses.
19716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (Address current = from_bottom; current < from_top; current += size) {
19726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HeapObject* object = HeapObject::FromAddress(current);
19736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (object->IsMarked()) {
19756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      object->ClearMark();
197644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap->mark_compact_collector()->tracer()->decrement_marked_count();
19776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      size = object->Size();
19796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      survivors_size += size;
19806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Aggressively promote young survivors to the old space.
198244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (TryPromoteObject(heap, object, size)) {
19836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        continue;
19846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
19856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Promotion failed. Just migrate object to another semispace.
19876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Allocation cannot fail at this point: semispaces are of equal size.
19885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      Object* target = space->AllocateRaw(size)->ToObjectUnchecked();
19896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
199044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      MigrateObject(heap,
199144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    HeapObject::cast(target)->address(),
19927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    current,
19937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    size,
19947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    false);
19956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
19961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Process the dead object before we write a NULL into its header.
19971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      LiveObjectList::ProcessNonLive(object);
19981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
19996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      size = object->Size();
20006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Memory::Address_at(current) = NULL;
20016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
20026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
20036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Second pass: find pointers to new space and update them.
200544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PointersToNewGenUpdatingVisitor updating_visitor(heap);
20066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Update pointers in to space.
2008756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Address current = space->bottom();
2009756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  while (current < space->top()) {
2010756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    HeapObject* object = HeapObject::FromAddress(current);
2011756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    current +=
2012756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        StaticPointersToNewGenUpdatingVisitor::IterateBody(object->map(),
2013756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                                           object);
20146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
20156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Update roots.
201744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE);
20181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LiveObjectList::IterateElements(&updating_visitor);
20196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Update pointers in old spaces.
202144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->IterateDirtyRegions(heap->old_pointer_space(),
20227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                            &Heap::IteratePointersInDirtyRegion,
20237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                            &UpdatePointerToNewGen,
202444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            heap->WATERMARK_SHOULD_BE_VALID);
20257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
202644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->lo_space()->IterateDirtyRegions(&UpdatePointerToNewGen);
20276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Update pointers from cells.
202944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapObjectIterator cell_iterator(heap->cell_space());
20306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (HeapObject* cell = cell_iterator.next();
20316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block       cell != NULL;
20326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block       cell = cell_iterator.next()) {
20336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (cell->IsJSGlobalPropertyCell()) {
20346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Address value_address =
20356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          reinterpret_cast<Address>(cell) +
20366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag);
20376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
2038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
20406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Update pointer from the global contexts list.
204244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  updating_visitor.VisitPointer(heap->global_contexts_list_address());
2043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Update pointers from external string table.
204544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->UpdateNewSpaceReferencesInExternalStringTable(
20466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      &UpdateNewSpaceReferenceInExternalStringTableEntry);
20476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // All pointers were updated. Update auxiliary allocation info.
204944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->IncrementYoungSurvivorsCounter(survivors_size);
20506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  space->set_age_mark(space->top());
2051e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2052e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Update JSFunction pointers from the runtime profiler.
205344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->isolate()->runtime_profiler()->UpdateSamplesAfterScavenge();
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
205744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void SweepSpace(Heap* heap, PagedSpace* space) {
2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PageIterator it(space, PageIterator::PAGES_IN_USE);
20596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // During sweeping of paged space we are trying to find longest sequences
20616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // of pages without live objects and free them (instead of putting them on
20626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the free list).
20636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Page preceding current.
20656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Page* prev = Page::FromAddress(NULL);
20666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // First empty page in a sequence.
20686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Page* first_empty_page = Page::FromAddress(NULL);
20696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Page preceding first empty page.
20716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Page* prec_first_empty_page = Page::FromAddress(NULL);
20726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If last used page of space ends with a sequence of dead objects
20746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // we can adjust allocation top instead of puting this free area into
20756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the free list. Thus during sweeping we keep track of such areas
20766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // and defer their deallocation until the sweeping of the next page
20776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // is done: if one of the next pages contains live objects we have
20786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // to put such area into the free list.
20796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address last_free_start = NULL;
20806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int last_free_size = 0;
20816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (it.has_next()) {
2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Page* p = it.next();
2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool is_previous_alive = true;
2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address free_start = NULL;
2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapObject* object;
2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Address current = p->ObjectAreaStart();
2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         current < p->AllocationTop();
2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         current += object->Size()) {
2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      object = HeapObject::FromAddress(current);
2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsMarked()) {
2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        object->ClearMark();
209544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        heap->mark_compact_collector()->tracer()->decrement_marked_count();
20966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!is_previous_alive) {  // Transition from free to live.
209880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          space->DeallocateBlock(free_start,
209980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                 static_cast<int>(current - free_start),
210080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                 true);
2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          is_previous_alive = true;
2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
21048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        heap->mark_compact_collector()->ReportDeleteIfNeeded(
21058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            object, heap->isolate());
2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (is_previous_alive) {  // Transition from live to free.
2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          free_start = current;
2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          is_previous_alive = false;
2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
21101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        LiveObjectList::ProcessNonLive(object);
2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The object is now unmarked for the call to Size() at the top of the
2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // loop.
2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool page_is_empty = (p->ObjectAreaStart() == p->AllocationTop())
21176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        || (!is_previous_alive && free_start == p->ObjectAreaStart());
21186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (page_is_empty) {
21206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // This page is empty. Check whether we are in the middle of
21216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // sequence of empty pages and start one if not.
21226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (!first_empty_page->is_valid()) {
21236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        first_empty_page = p;
21246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        prec_first_empty_page = prev;
21256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
21266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (!is_previous_alive) {
21286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // There are dead objects on this page. Update space accounting stats
21296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // without putting anything into free list.
21306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int size_in_bytes = static_cast<int>(p->AllocationTop() - free_start);
21316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (size_in_bytes > 0) {
213280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          space->DeallocateBlock(free_start, size_in_bytes, false);
21336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
21346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
21356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
21366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // This page is not empty. Sequence of empty pages ended on the previous
21376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // one.
21386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (first_empty_page->is_valid()) {
21396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        space->FreePages(prec_first_empty_page, prev);
21406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        prec_first_empty_page = first_empty_page = Page::FromAddress(NULL);
21416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
21426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // If there is a free ending area on one of the previous pages we have
21446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // deallocate that area and put it on the free list.
21456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (last_free_size > 0) {
21467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        Page::FromAddress(last_free_start)->
21477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            SetAllocationWatermark(last_free_start);
214880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        space->DeallocateBlock(last_free_start, last_free_size, true);
21496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        last_free_start = NULL;
21506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        last_free_size  = 0;
21516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
21526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // If the last region of this page was not live we remember it.
21546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (!is_previous_alive) {
21556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        ASSERT(last_free_size == 0);
21566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        last_free_size = static_cast<int>(p->AllocationTop() - free_start);
21576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        last_free_start = free_start;
2158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
21606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    prev = p;
21626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // We reached end of space. See if we need to adjust allocation top.
21656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address new_allocation_top = NULL;
21666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (first_empty_page->is_valid()) {
21686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Last used pages in space are empty. We can move allocation top backwards
21696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // to the beginning of first empty page.
21706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(prev == space->AllocationTopPage());
21716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    new_allocation_top = first_empty_page->ObjectAreaStart();
21736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (last_free_size > 0) {
21766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // There was a free ending area on the previous page.
21776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Deallocate it without putting it into freelist and move allocation
21786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // top to the beginning of this free area.
217980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    space->DeallocateBlock(last_free_start, last_free_size, false);
21806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    new_allocation_top = last_free_start;
21816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (new_allocation_top != NULL) {
21846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
21856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Page* new_allocation_top_page = Page::FromAllocationTop(new_allocation_top);
21866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!first_empty_page->is_valid()) {
21876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ASSERT(new_allocation_top_page == space->AllocationTopPage());
21886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else if (last_free_size > 0) {
21896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ASSERT(new_allocation_top_page == prec_first_empty_page);
21906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
21916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ASSERT(new_allocation_top_page == first_empty_page);
21926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
21936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
21946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    space->SetTop(new_allocation_top);
2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::EncodeForwardingAddresses() {
2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Objects in the active semispace of the young generation may be
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocated to the inactive semispace (if not promoted).  Set the
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocation info to the beginning of the inactive semispace.
22058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->new_space()->MCResetRelocationInfo();
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the forwarding pointers in each space.
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace,
2209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                        ReportDeleteIfNeeded>(
22108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->old_pointer_space());
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace,
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        IgnoreNonLiveObject>(
22148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->old_data_space());
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace,
2217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                        ReportDeleteIfNeeded>(
22188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->code_space());
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInPagedSpace<MCAllocateFromCellSpace,
2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        IgnoreNonLiveObject>(
22228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->cell_space());
2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute new space next to last after the old and code spaces have been
2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compacted.  Objects in new space can be promoted to old or code space.
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInNewSpace();
2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute map space last because computing forwarding addresses
2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // overwrites non-live objects.  Objects in the other spaces rely on
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // non-live map pointers to get the sizes of non-live objects.
2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace,
2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        IgnoreNonLiveObject>(
22348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->map_space());
2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Write relocation info to the top page, so we can use it later.  This is
2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // done after promoting objects from the new space so we get the correct
2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocation top.
22398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->old_pointer_space()->MCWriteRelocationInfoToPage();
22408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->old_data_space()->MCWriteRelocationInfoToPage();
22418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->code_space()->MCWriteRelocationInfoToPage();
22428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->map_space()->MCWriteRelocationInfoToPage();
22438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->cell_space()->MCWriteRelocationInfoToPage();
2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeclass MapIterator : public HeapObjectIterator {
2248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke public:
22498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  explicit MapIterator(Heap* heap)
22508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : HeapObjectIterator(heap->map_space(), &SizeCallback) { }
2251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
22528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MapIterator(Heap* heap, Address start)
22538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      : HeapObjectIterator(heap->map_space(), start, &SizeCallback) { }
2254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke private:
2256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static int SizeCallback(HeapObject* unused) {
2257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    USE(unused);
2258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return Map::kSize;
2259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
2261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeclass MapCompact {
2264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke public:
226544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit MapCompact(Heap* heap, int live_maps)
226644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : heap_(heap),
226744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      live_maps_(live_maps),
226844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      to_evacuate_start_(heap->map_space()->TopAfterCompaction(live_maps)),
22698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      vacant_map_it_(heap),
22708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      map_to_evacuate_it_(heap, to_evacuate_start_),
2271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      first_map_to_evacuate_(
2272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          reinterpret_cast<Map*>(HeapObject::FromAddress(to_evacuate_start_))) {
2273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void CompactMaps() {
2276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // As we know the number of maps to evacuate beforehand,
2277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // we stop then there is no more vacant maps.
2278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    for (Map* next_vacant_map = NextVacantMap();
2279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke         next_vacant_map;
2280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke         next_vacant_map = NextVacantMap()) {
2281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EvacuateMap(next_vacant_map, NextMapToEvacuate());
2282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG
2285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    CheckNoMapsToEvacuate();
2286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif
2287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void UpdateMapPointersInRoots() {
229044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MapUpdatingVisitor map_updating_visitor;
22918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->IterateRoots(&map_updating_visitor, VISIT_ONLY_STRONG);
22928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->isolate()->global_handles()->IterateWeakRoots(
22938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        &map_updating_visitor);
229444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LiveObjectList::IterateElements(&map_updating_visitor);
2295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void UpdateMapPointersInPagedSpace(PagedSpace* space) {
22988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(space != heap()->map_space());
2299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    PageIterator it(space, PageIterator::PAGES_IN_USE);
2301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    while (it.has_next()) {
2302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Page* p = it.next();
23038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      UpdateMapPointersInRange(heap(),
23048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                               p->ObjectAreaStart(),
23058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                               p->AllocationTop());
2306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void UpdateMapPointersInNewSpace() {
23108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    NewSpace* space = heap()->new_space();
23118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    UpdateMapPointersInRange(heap(), space->bottom(), space->top());
2312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void UpdateMapPointersInLargeObjectSpace() {
23158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    LargeObjectIterator it(heap()->lo_space());
2316d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    for (HeapObject* obj = it.next(); obj != NULL; obj = it.next())
23178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      UpdateMapPointersInObject(heap(), obj);
2318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Finish() {
23218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->map_space()->FinishCompaction(to_evacuate_start_, live_maps_);
2322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
23248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  inline Heap* heap() const { return heap_; }
23258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke private:
232744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap_;
2328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int live_maps_;
2329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Address to_evacuate_start_;
2330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MapIterator vacant_map_it_;
2331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MapIterator map_to_evacuate_it_;
2332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Map* first_map_to_evacuate_;
2333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Helper class for updating map pointers in HeapObjects.
2335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  class MapUpdatingVisitor: public ObjectVisitor {
2336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  public:
233744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MapUpdatingVisitor() {}
233844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    void VisitPointer(Object** p) {
2340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UpdateMapPointer(p);
2341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    void VisitPointers(Object** start, Object** end) {
2344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      for (Object** p = start; p < end; p++) UpdateMapPointer(p);
2345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  private:
2348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    void UpdateMapPointer(Object** p) {
2349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!(*p)->IsHeapObject()) return;
2350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      HeapObject* old_map = reinterpret_cast<HeapObject*>(*p);
2351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Moved maps are tagged with overflowed map word.  They are the only
2353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // objects those map word is overflowed as marking is already complete.
2354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      MapWord map_word = old_map->map_word();
2355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!map_word.IsOverflowed()) return;
2356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      *p = GetForwardedMap(map_word);
2358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  };
2360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static Map* NextMap(MapIterator* it, HeapObject* last, bool live) {
2362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    while (true) {
2363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      HeapObject* next = it->next();
2364d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      ASSERT(next != NULL);
2365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (next == last)
2366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        return NULL;
2367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(!next->IsOverflowed());
2368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(!next->IsMarked());
2369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(next->IsMap() || FreeListNode::IsFreeListNode(next));
2370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (next->IsMap() == live)
2371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        return reinterpret_cast<Map*>(next);
2372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Map* NextVacantMap() {
2376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Map* map = NextMap(&vacant_map_it_, first_map_to_evacuate_, false);
2377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map == NULL || FreeListNode::IsFreeListNode(map));
2378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return map;
2379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Map* NextMapToEvacuate() {
2382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Map* map = NextMap(&map_to_evacuate_it_, NULL, true);
2383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map != NULL);
2384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map->IsMap());
2385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return map;
2386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static void EvacuateMap(Map* vacant_map, Map* map_to_evacuate) {
2389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(FreeListNode::IsFreeListNode(vacant_map));
2390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map_to_evacuate->IsMap());
2391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
23926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(Map::kSize % 4 == 0);
23936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
239444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    map_to_evacuate->heap()->CopyBlockToOldSpaceAndUpdateRegionMarks(
239544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        vacant_map->address(), map_to_evacuate->address(), Map::kSize);
23966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(vacant_map->IsMap());  // Due to memcpy above.
2398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MapWord forwarding_map_word = MapWord::FromMap(vacant_map);
2400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    forwarding_map_word.SetOverflow();
2401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_to_evacuate->set_map_word(forwarding_map_word);
2402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map_to_evacuate->map_word().IsOverflowed());
2404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(GetForwardedMap(map_to_evacuate->map_word()) == vacant_map);
2405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static Map* GetForwardedMap(MapWord map_word) {
2408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map_word.IsOverflowed());
2409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_word.ClearOverflow();
2410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Map* new_map = map_word.ToMap();
2411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT_MAP_ALIGNED(new_map->address());
2412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return new_map;
2413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
241544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static int UpdateMapPointersInObject(Heap* heap, HeapObject* obj) {
2416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(!obj->IsMarked());
2417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Map* map = obj->map();
241844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(heap->map_space()->Contains(map));
2419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MapWord map_word = map->map_word();
2420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(!map_word.IsMarked());
2421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (map_word.IsOverflowed()) {
2422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Map* new_map = GetForwardedMap(map_word);
242344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(heap->map_space()->Contains(new_map));
2424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      obj->set_map(new_map);
2425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG
2427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (FLAG_gc_verbose) {
2428f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch        PrintF("update %p : %p -> %p\n",
2429f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               obj->address(),
2430f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               reinterpret_cast<void*>(map),
2431f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               reinterpret_cast<void*>(new_map));
2432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif
2434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int size = obj->SizeFromMap(map);
243744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MapUpdatingVisitor map_updating_visitor;
243844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    obj->IterateBody(map->instance_type(), size, &map_updating_visitor);
2439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return size;
2440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
244244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static void UpdateMapPointersInRange(Heap* heap, Address start, Address end) {
2443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    HeapObject* object;
2444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int size;
2445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    for (Address current = start; current < end; current += size) {
2446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      object = HeapObject::FromAddress(current);
244744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      size = UpdateMapPointersInObject(heap, object);
2448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(size > 0);
2449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG
2453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void CheckNoMapsToEvacuate() {
2454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (!FLAG_enable_slow_asserts)
2455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return;
2456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2457d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    for (HeapObject* obj = map_to_evacuate_it_.next();
2458d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke         obj != NULL; obj = map_to_evacuate_it_.next())
2459d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      ASSERT(FreeListNode::IsFreeListNode(obj));
2460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif
2462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
2463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::SweepSpaces() {
2466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP);
2467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == SWEEP_SPACES);
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!IsCompacting());
2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Noncompacting collections simply sweep the spaces to clear the mark
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bits and free the nonlive blocks (for old and map spaces).  We sweep
2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the map space last because freeing non-live maps overwrites them and
2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the other spaces rely on possibly non-live maps to get the sizes for
2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // non-live objects.
24758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SweepSpace(heap(), heap()->old_pointer_space());
24768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SweepSpace(heap(), heap()->old_data_space());
24778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SweepSpace(heap(), heap()->code_space());
24788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SweepSpace(heap(), heap()->cell_space());
2479756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE);
24808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    SweepNewSpace(heap(), heap()->new_space());
2481756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
24828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SweepSpace(heap(), heap()->map_space());
24837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->IterateDirtyRegions(heap()->map_space(),
24858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                             &heap()->IteratePointersInDirtyMapsRegion,
248644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             &UpdatePointerToNewGen,
24878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                             heap()->WATERMARK_SHOULD_BE_VALID);
24887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  intptr_t live_maps_size = heap()->map_space()->Size();
2490f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  int live_maps = static_cast<int>(live_maps_size / Map::kSize);
24916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_map_objects_size_ == live_maps_size);
2492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
24938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (heap()->map_space()->NeedsCompaction(live_maps)) {
24948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    MapCompact map_compact(heap(), live_maps);
2495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_compact.CompactMaps();
2497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_compact.UpdateMapPointersInRoots();
2498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    PagedSpaces spaces;
2500d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    for (PagedSpace* space = spaces.next();
2501d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke         space != NULL; space = spaces.next()) {
25028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (space == heap()->map_space()) continue;
2503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      map_compact.UpdateMapPointersInPagedSpace(space);
2504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_compact.UpdateMapPointersInNewSpace();
2506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_compact.UpdateMapPointersInLargeObjectSpace();
2507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_compact.Finish();
2509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Iterate the live objects in a range of addresses (eg, a page or a
2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// semispace).  The live regions of the range have been linked into a list.
2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The first live region is [first_live_start, first_live_end), and the last
2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// address in the range is top.  The callback function is used to get the
2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// size of each live object.
2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::IterateLiveObjectsInRange(
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address start,
2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address end,
252144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LiveObjectCallback size_func) {
25226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int live_objects_size = 0;
2523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address current = start;
2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (current < end) {
2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t encoded_map = Memory::uint32_at(current);
2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (encoded_map == kSingleFreeEncoding) {
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current += kPointerSize;
2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (encoded_map == kMultiFreeEncoding) {
2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current += Memory::int_at(current + kIntSize);
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
253144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      int size = (this->*size_func)(HeapObject::FromAddress(current));
25326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      current += size;
25336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      live_objects_size += size;
2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
25366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return live_objects_size;
2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
254044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MarkCompactCollector::IterateLiveObjects(
254144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    NewSpace* space, LiveObjectCallback size_f) {
2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return IterateLiveObjectsInRange(space->bottom(), space->top(), size_f);
2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
254744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MarkCompactCollector::IterateLiveObjects(
254844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PagedSpace* space, LiveObjectCallback size_f) {
2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int total = 0;
2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PageIterator it(space, PageIterator::PAGES_IN_USE);
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (it.has_next()) {
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Page* p = it.next();
2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    total += IterateLiveObjectsInRange(p->ObjectAreaStart(),
2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       p->AllocationTop(),
2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       size_f);
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return total;
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 3: Update pointers
2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class for updating pointers in HeapObjects.
2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass UpdatingVisitor: public ObjectVisitor {
2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
256844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit UpdatingVisitor(Heap* heap) : heap_(heap) {}
256944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitPointer(Object** p) {
2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UpdatePointer(p);
2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitPointers(Object** start, Object** end) {
2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark all HeapObject pointers in [start, end)
2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Object** p = start; p < end; p++) UpdatePointer(p);
2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitCodeTarget(RelocInfo* rinfo) {
2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    VisitPointer(&target);
2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rinfo->set_target_address(
2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        reinterpret_cast<Code*>(target)->instruction_start());
2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void VisitDebugTarget(RelocInfo* rinfo) {
25887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
25897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            rinfo->IsPatchedReturnSequence()) ||
25907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch           (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
25917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            rinfo->IsPatchedDebugBreakSlotSequence()));
25923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
25933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    VisitPointer(&target);
25943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    rinfo->set_call_address(
25953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        reinterpret_cast<Code*>(target)->instruction_start());
25963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
25973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
25988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  inline Heap* heap() const { return heap_; }
25998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdatePointer(Object** p) {
2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!(*p)->IsHeapObject()) return;
2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapObject* obj = HeapObject::cast(*p);
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address old_addr = obj->address();
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address new_addr;
26078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(!heap()->InFromSpace(obj));
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (heap()->new_space()->Contains(obj)) {
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Address forwarding_pointer_addr =
26118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          heap()->new_space()->FromSpaceLow() +
26128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          heap()->new_space()->ToSpaceOffsetForAddress(old_addr);
2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      new_addr = Memory::Address_at(forwarding_pointer_addr);
2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
26168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ASSERT(heap()->old_pointer_space()->Contains(new_addr) ||
26178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             heap()->old_data_space()->Contains(new_addr) ||
26188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             heap()->new_space()->FromSpaceContains(new_addr) ||
26198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             heap()->lo_space()->Contains(HeapObject::FromAddress(new_addr)));
26208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (heap()->new_space()->FromSpaceContains(new_addr)) {
26228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        ASSERT(heap()->new_space()->FromSpaceOffsetForAddress(new_addr) <=
26238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch               heap()->new_space()->ToSpaceOffsetForAddress(old_addr));
2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else if (heap()->lo_space()->Contains(obj)) {
2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Don't move objects in the large object space.
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PagedSpaces spaces;
2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PagedSpace* original_space = spaces.next();
2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      while (original_space != NULL) {
2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (original_space->Contains(obj)) break;
2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        original_space = spaces.next();
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(original_space != NULL);
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      new_addr = MarkCompactCollector::GetForwardingAddressInOldSpace(obj);
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(original_space->Contains(new_addr));
2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(original_space->MCSpaceOffsetForAddress(new_addr) <=
2644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             original_space->MCSpaceOffsetForAddress(old_addr));
2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *p = HeapObject::FromAddress(new_addr);
2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (FLAG_gc_verbose) {
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("update %p : %p -> %p\n",
2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             reinterpret_cast<Address>(p), old_addr, new_addr);
2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
265644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
265744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap_;
2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::UpdatePointers() {
2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
2664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state_ = UPDATE_POINTERS;
2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
26668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  UpdatingVisitor updating_visitor(heap());
26678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->runtime_profiler()->UpdateSamplesAfterCompact(
266844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &updating_visitor);
26698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->IterateRoots(&updating_visitor, VISIT_ONLY_STRONG);
26708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->isolate()->global_handles()->IterateWeakRoots(&updating_visitor);
2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2672f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Update the pointer to the head of the weak list of global contexts.
26738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  updating_visitor.VisitPointer(&heap()->global_contexts_list_);
2674f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
26751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LiveObjectList::IterateElements(&updating_visitor);
26761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
267744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_maps_size = IterateLiveObjects(
26788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->map_space(), &MarkCompactCollector::UpdatePointersInOldObject);
267944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_pointer_olds_size = IterateLiveObjects(
26808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->old_pointer_space(),
268144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &MarkCompactCollector::UpdatePointersInOldObject);
268244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_data_olds_size = IterateLiveObjects(
26838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->old_data_space(),
268444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &MarkCompactCollector::UpdatePointersInOldObject);
268544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_codes_size = IterateLiveObjects(
26868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->code_space(), &MarkCompactCollector::UpdatePointersInOldObject);
268744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_cells_size = IterateLiveObjects(
26888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->cell_space(), &MarkCompactCollector::UpdatePointersInOldObject);
268944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_news_size = IterateLiveObjects(
26908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->new_space(), &MarkCompactCollector::UpdatePointersInNewObject);
2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Large objects do not move, the map word can be updated directly.
26938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  LargeObjectIterator it(heap()->lo_space());
2694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
2695d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    UpdatePointersInNewObject(obj);
2696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_maps_size);
26996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_pointer_olds_size);
27006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_data_olds_size);
27016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_codes_size);
27026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_cells_size);
27036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_news_size);
27046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_maps_size == live_map_objects_size_);
27056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_data_olds_size == live_old_data_objects_size_);
27066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_);
27076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_codes_size == live_code_objects_size_);
27086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_cells_size == live_cell_objects_size_);
27096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_news_size == live_young_objects_size_);
2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) {
2714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Keep old map pointers
2715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Map* old_map = obj->map();
2716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(old_map->IsHeapObject());
2717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address forwarded = GetForwardingAddressInOldSpace(old_map);
2719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(heap()->map_space()->Contains(old_map));
27218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(heap()->map_space()->Contains(forwarded));
2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_gc_verbose) {
2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("update %p : %p -> %p\n", obj->address(), old_map->address(),
2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           forwarded);
2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the map pointer.
2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(forwarded)));
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We have to compute the object size relying on the old map because
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // map objects are not relocated yet.
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int obj_size = obj->SizeFromMap(old_map);
2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update pointers in the object body.
27368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  UpdatingVisitor updating_visitor(heap());
2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->IterateBody(old_map->instance_type(), obj_size, &updating_visitor);
2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::UpdatePointersInOldObject(HeapObject* obj) {
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Decode the map pointer.
2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding = obj->map_word();
27458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Address map_addr = encoding.DecodeMapAddress(heap()->map_space());
27468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(heap()->map_space()->Contains(HeapObject::FromAddress(map_addr)));
2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // At this point, the first word of map_addr is also encoded, cannot
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // cast it to Map* using Map::cast.
2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr));
2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int obj_size = obj->SizeFromMap(map);
2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstanceType type = map->instance_type();
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update map pointer.
2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address new_map_addr = GetForwardingAddressInOldSpace(map);
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = encoding.DecodeOffset();
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->set_map_word(MapWord::EncodeAddress(new_map_addr, offset));
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_gc_verbose) {
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("update %p : %p -> %p\n", obj->address(),
2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           map_addr, new_map_addr);
2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update pointers in the object body.
27678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  UpdatingVisitor updating_visitor(heap());
2768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->IterateBody(type, obj_size, &updating_visitor);
2769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) {
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Object should either in old or map space.
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding = obj->map_word();
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Offset to the first live object's forwarding address.
2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = encoding.DecodeOffset();
2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address obj_addr = obj->address();
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find the first live object's forwarding address.
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Page* p = Page::FromAddress(obj_addr);
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address first_forwarded = p->mc_first_forwarded;
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Page start address of forwarded address.
2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Page* forwarded_page = Page::FromAddress(first_forwarded);
2787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int forwarded_offset = forwarded_page->Offset(first_forwarded);
2788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Find end of allocation in the page of first_forwarded.
27907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int mc_top_offset = forwarded_page->AllocationWatermarkOffset();
2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if current object's forward pointer is in the same page
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // as the first live object's forwarding pointer
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (forwarded_offset + offset < mc_top_offset) {
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // In the same page.
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return first_forwarded + offset;
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Must be in the next page, NOTE: this may cross chunks.
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Page* next_page = forwarded_page->next_page();
2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(next_page->is_valid());
2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset -= (mc_top_offset - forwarded_offset);
2804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset += Page::kObjectStartOffset;
2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_PAGE_OFFSET(offset);
28077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(next_page->OffsetToAddress(offset) < next_page->AllocationTop());
2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return next_page->OffsetToAddress(offset);
2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 4: Relocate objects
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::RelocateObjects() {
2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == UPDATE_POINTERS);
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state_ = RELOCATE_OBJECTS;
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Relocates objects, always relocate map objects first. Relocating
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // objects in other space relies on map objects to get object size.
282344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_maps_size = IterateLiveObjects(
28248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->map_space(), &MarkCompactCollector::RelocateMapObject);
282544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_pointer_olds_size = IterateLiveObjects(
28268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->old_pointer_space(),
282744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &MarkCompactCollector::RelocateOldPointerObject);
282844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_data_olds_size = IterateLiveObjects(
28298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->old_data_space(), &MarkCompactCollector::RelocateOldDataObject);
283044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_codes_size = IterateLiveObjects(
28318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->code_space(), &MarkCompactCollector::RelocateCodeObject);
283244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_cells_size = IterateLiveObjects(
28338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->cell_space(), &MarkCompactCollector::RelocateCellObject);
283444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_news_size = IterateLiveObjects(
28358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->new_space(), &MarkCompactCollector::RelocateNewObject);
28366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_maps_size);
28386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_pointer_olds_size);
28396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_data_olds_size);
28406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_codes_size);
28416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_cells_size);
28426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_news_size);
28436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_maps_size == live_map_objects_size_);
28446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_data_olds_size == live_old_data_objects_size_);
28456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_);
28466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_codes_size == live_code_objects_size_);
28476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_cells_size == live_cell_objects_size_);
28486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_news_size == live_young_objects_size_);
2849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Flip from and to spaces
28518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->new_space()->Flip();
2852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->new_space()->MCCommitRelocationInfo();
28547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set age_mark to bottom in to space
28568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Address mark = heap()->new_space()->bottom();
28578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->new_space()->set_age_mark(mark);
2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PagedSpaces spaces;
2860d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next())
2861d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    space->MCCommitRelocationInfo();
28626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->CheckNewSpaceExpansionCriteria();
28648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  heap()->IncrementYoungSurvivorsCounter(live_news_size);
2865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateMapObject(HeapObject* obj) {
2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Recover map pointer.
2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding = obj->map_word();
28718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Address map_addr = encoding.DecodeMapAddress(heap()->map_space());
28728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(heap()->map_space()->Contains(HeapObject::FromAddress(map_addr)));
2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get forwarding address before resetting map pointer
2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address new_addr = GetForwardingAddressInOldSpace(obj);
2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset map pointer.  The meta map object may not be copied yet so
2878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Map::cast does not yet work.
2879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)));
2880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address old_addr = obj->address();
2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (new_addr != old_addr) {
28846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Move contents.
28858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
288644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   old_addr,
288744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   Map::kSize);
2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_gc_verbose) {
2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("relocate %p -> %p\n", old_addr, new_addr);
2893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Map::kSize;
2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline int RestoreMap(HeapObject* obj,
2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             PagedSpace* space,
2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             Address new_addr,
2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             Address map_addr) {
2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This must be a non-map object, and the function relies on the
2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // assumption that the Map space is compacted before the other paged
2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // spaces (see RelocateObjects).
2907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset map pointer.
2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->set_map(Map::cast(HeapObject::FromAddress(map_addr)));
2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int obj_size = obj->Size();
2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_OBJECT_SIZE(obj_size);
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(space->MCSpaceOffsetForAddress(new_addr) <=
2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         space->MCSpaceOffsetForAddress(obj->address()));
2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_gc_verbose) {
2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("relocate %p -> %p\n", obj->address(), new_addr);
2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
2924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj,
2928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   PagedSpace* space) {
2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Recover map pointer.
2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding = obj->map_word();
29318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Address map_addr = encoding.DecodeMapAddress(heap()->map_space());
29328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(heap()->map_space()->Contains(map_addr));
2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get forwarding address before resetting map pointer.
2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address new_addr = GetForwardingAddressInOldSpace(obj);
2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset the map pointer.
2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int obj_size = RestoreMap(obj, space, new_addr, map_addr);
2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address old_addr = obj->address();
2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (new_addr != old_addr) {
29436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Move contents.
29448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (space == heap()->old_data_space()) {
29458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->MoveBlock(new_addr, old_addr, obj_size);
29467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
29478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      heap()->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
294844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                     old_addr,
294944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                     obj_size);
29507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!HeapObject::FromAddress(new_addr)->IsCode());
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2955d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  HeapObject* copied_to = HeapObject::FromAddress(new_addr);
2956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (copied_to->IsSharedFunctionInfo()) {
29578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PROFILE(heap()->isolate(),
295844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            SharedFunctionInfoMoveEvent(old_addr, new_addr));
2959d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
29608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HEAP_PROFILE(heap(), ObjectMoveEvent(old_addr, new_addr));
2961d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) {
29678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return RelocateOldNonCodeObject(obj, heap()->old_pointer_space());
2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) {
29728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return RelocateOldNonCodeObject(obj, heap()->old_data_space());
2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateCellObject(HeapObject* obj) {
29778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return RelocateOldNonCodeObject(obj, heap()->cell_space());
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateCodeObject(HeapObject* obj) {
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Recover map pointer.
2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding = obj->map_word();
29848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Address map_addr = encoding.DecodeMapAddress(heap()->map_space());
29858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(heap()->map_space()->Contains(HeapObject::FromAddress(map_addr)));
2986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get forwarding address before resetting map pointer
2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address new_addr = GetForwardingAddressInOldSpace(obj);
2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset the map pointer.
29918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int obj_size = RestoreMap(obj, heap()->code_space(), new_addr, map_addr);
2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address old_addr = obj->address();
2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (new_addr != old_addr) {
29966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Move contents.
29978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->MoveBlock(new_addr, old_addr, obj_size);
2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapObject* copied_to = HeapObject::FromAddress(new_addr);
3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (copied_to->IsCode()) {
3002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // May also update inline cache target.
3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Code::cast(copied_to)->Relocate(new_addr - old_addr);
3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Notify the logger that compiled code has moved.
30058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PROFILE(heap()->isolate(), CodeMoveEvent(old_addr, new_addr));
3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
30078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HEAP_PROFILE(heap(), ObjectMoveEvent(old_addr, new_addr));
3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int obj_size = obj->Size();
3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get forwarding address
3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address old_addr = obj->address();
30188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int offset = heap()->new_space()->ToSpaceOffsetForAddress(old_addr);
3019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address new_addr =
30218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Memory::Address_at(heap()->new_space()->FromSpaceLow() + offset);
3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
30248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (heap()->new_space()->FromSpaceContains(new_addr)) {
30258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(heap()->new_space()->FromSpaceOffsetForAddress(new_addr) <=
30268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch           heap()->new_space()->ToSpaceOffsetForAddress(old_addr));
3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
30288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(heap()->TargetSpace(obj) == heap()->old_pointer_space() ||
30298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch           heap()->TargetSpace(obj) == heap()->old_data_space());
3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // New and old addresses cannot overlap.
30348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (heap()->InNewSpace(HeapObject::FromAddress(new_addr))) {
30358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->CopyBlock(new_addr, old_addr, obj_size);
30367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
30378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    heap()->CopyBlockToOldSpaceAndUpdateRegionMarks(new_addr,
303844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   old_addr,
303944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   obj_size);
30407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
3041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_gc_verbose) {
3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("relocate %p -> %p\n", old_addr, new_addr);
3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3048d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  HeapObject* copied_to = HeapObject::FromAddress(new_addr);
3049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (copied_to->IsSharedFunctionInfo()) {
30508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PROFILE(heap()->isolate(),
305144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            SharedFunctionInfoMoveEvent(old_addr, new_addr));
3052d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
30538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HEAP_PROFILE(heap(), ObjectMoveEvent(old_addr, new_addr));
3054d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
305944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MarkCompactCollector::EnableCodeFlushing(bool enable) {
306044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (enable) {
306144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (code_flusher_ != NULL) return;
30628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    code_flusher_ = new CodeFlusher(heap()->isolate());
306344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
306444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (code_flusher_ == NULL) return;
306544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    delete code_flusher_;
306644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    code_flusher_ = NULL;
306744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
306844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
306944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
307044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj,
30728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                Isolate* isolate) {
3073b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#ifdef ENABLE_GDB_JIT_INTERFACE
3074b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (obj->IsCode()) {
3075b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    GDBJITInterface::RemoveCode(reinterpret_cast<Code*>(obj));
3076b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
3077b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif
3078d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING
3079d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (obj->IsCode()) {
30808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PROFILE(isolate, CodeDeleteEvent(obj->address()));
3081d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
3082d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif
3083d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
3084d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3085756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
30868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangint MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) {
30878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  MapWord map_word = obj->map_word();
30888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  map_word.ClearMark();
30898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return obj->SizeFromMap(map_word.ToMap());
30908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
30918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
30928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3093756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MarkCompactCollector::Initialize() {
3094756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  StaticPointersToNewGenUpdatingVisitor::Initialize();
3095756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  StaticMarkingVisitor::Initialize();
3096756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
3097756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3098756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
3100