mark-compact.cc revision 44f0eee88ff00398ff7f715fab053374d808c90d
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
8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap_->MarkMapPointersAsEncoded(true);
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UpdatePointers();
9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap_->MarkMapPointersAsEncoded(false);
9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap_->isolate()->pc_to_code_cache()->Flush();
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RelocateObjects();
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SweepSpaces();
9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    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;
12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  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).
16444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->stub_cache()->Clear();
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  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
459756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline void VisitCodeTarget(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 {
46744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->mark_compact_collector()->MarkObject(code);
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static void VisitGlobalPropertyCell(RelocInfo* rinfo) {
472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Object* cell = rinfo->target_cell();
474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Object* old_cell = cell;
47544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    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
481756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline void VisitDebugTarget(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());
48744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    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);
49444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap->mark_compact_collector()->MarkObject(object);
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Visit an unmarked object.
499756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline void VisitUnmarkedObject(HeapObject* obj) {
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(HEAP->Contains(obj));
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!obj->IsMarked());
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Map* map = obj->map();
50544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MarkCompactCollector* collector = map->heap()->mark_compact_collector();
50644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    collector->SetMark(obj);
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark the map pointer and the body.
50844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    collector->MarkObject(map);
509756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    IterateBody(map, obj);
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Visit all unmarked objects pointed to by [start, end).
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns false if the operation fails (lack of stack space).
51444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static inline bool VisitUnmarkedObjects(Heap* heap,
51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Object** start,
51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Object** end) {
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Return false is we are close to the stack limit.
51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    StackLimitCheck check(heap->isolate());
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (check.HasOverflowed()) return false;
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Visit the unmarked objects.
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Object** p = start; p < end; p++) {
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!(*p)->IsHeapObject()) continue;
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      HeapObject* obj = HeapObject::cast(*p);
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (obj->IsMarked()) continue;
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      VisitUnmarkedObject(obj);
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return true;
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
530756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
531756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline void VisitExternalReference(Address* p) { }
532756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline void VisitRuntimeEntry(RelocInfo* rinfo) { }
533756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
534756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick private:
535756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  class DataObjectVisitor {
536756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick   public:
537756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    template<int size>
538756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    static void VisitSpecialized(Map* map, HeapObject* object) {
539756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
540756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
541756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    static void Visit(Map* map, HeapObject* object) {
542756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
543756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  };
544756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
545756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  typedef FlexibleBodyVisitor<StaticMarkingVisitor,
546756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                              JSObject::BodyDescriptor,
547756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                              void> JSObjectVisitor;
548756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
549756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  typedef FlexibleBodyVisitor<StaticMarkingVisitor,
550756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                              StructBodyDescriptor,
551756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                              void> StructObjectVisitor;
552756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
553756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static void VisitCode(Map* map, HeapObject* object) {
55444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>(
55544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        map->heap());
556756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
557756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
558756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Code flushing support.
559756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
560756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // How many collections newly compiled code object will survive before being
561756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // flushed.
562756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kCodeAgeThreshold = 5;
563756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
564756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  inline static bool HasSourceCode(SharedFunctionInfo* info) {
56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* undefined = HEAP->raw_unchecked_undefined_value();
566756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return (info->script() != undefined) &&
567756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        (reinterpret_cast<Script*>(info->script())->source() != undefined);
568756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
569756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
570756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
571756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  inline static bool IsCompiled(JSFunction* function) {
57244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return function->unchecked_code() !=
57344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
574756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
575756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
576756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  inline static bool IsCompiled(SharedFunctionInfo* function) {
57744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return function->unchecked_code() !=
57844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
579756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
580756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  inline static bool IsFlushable(JSFunction* function) {
582756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    SharedFunctionInfo* shared_info = function->unchecked_shared();
583756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Code is either on stack, in compilation cache or referenced
585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // by optimized version of function.
586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->unchecked_code()->IsMarked()) {
587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      shared_info->set_code_age(0);
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
589756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
590756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // We do not flush code for optimized functions.
592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->code() != shared_info->unchecked_code()) {
593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return IsFlushable(shared_info);
597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  inline static bool IsFlushable(SharedFunctionInfo* shared_info) {
600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Code is either on stack, in compilation cache or referenced
601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // by optimized version of function.
602756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (shared_info->unchecked_code()->IsMarked()) {
603756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      shared_info->set_code_age(0);
604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
605756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
606756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
607756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The function must be compiled and have the source code available,
608756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // to be able to recompile it in case we need the function again.
609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!(shared_info->is_compiled() && HasSourceCode(shared_info))) {
610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
612756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
613756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // We never flush code for Api functions.
614756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Object* function_data = shared_info->function_data();
615756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (function_data->IsHeapObject() &&
616756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        (SafeMap(function_data)->instance_type() ==
617756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick         FUNCTION_TEMPLATE_INFO_TYPE)) {
618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
619756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
620756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
621756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Only flush code for functions.
622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (shared_info->code()->kind() != Code::FUNCTION) return false;
623756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
624756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Function must be lazy compilable.
625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!shared_info->allows_lazy_compilation()) return false;
626756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
627756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // If this is a full script wrapped in a function we do no flush the code.
628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (shared_info->is_toplevel()) return false;
629756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
630756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Age this shared function info.
631756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (shared_info->code_age() < kCodeAgeThreshold) {
632756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      shared_info->set_code_age(shared_info->code_age() + 1);
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
634756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
635756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return true;
637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
64044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static bool FlushCodeForFunction(Heap* heap, JSFunction* function) {
641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!IsFlushable(function)) return false;
642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // This function's code looks flushable. But we have to postpone the
644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // decision until we see all functions that point to the same
645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // SharedFunctionInfo because some of them might be optimized.
646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // That would make the nonoptimized version of the code nonflushable,
647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // because it is required for bailing out from optimized code.
64844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap->mark_compact_collector()->code_flusher()->AddCandidate(function);
649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return true;
650756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
651756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
652756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
653756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline Map* SafeMap(Object* obj) {
654756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    MapWord map_word = HeapObject::cast(obj)->map_word();
655756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    map_word.ClearMark();
656756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    map_word.ClearOverflow();
657756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return map_word.ToMap();
658756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
659756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
660756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
661756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline bool IsJSBuiltinsObject(Object* obj) {
662756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return obj->IsHeapObject() &&
663756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        (SafeMap(obj)->instance_type() == JS_BUILTINS_OBJECT_TYPE);
664756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
665756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
666756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
667756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static inline bool IsValidNotBuiltinContext(Object* ctx) {
668756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (!ctx->IsHeapObject()) return false;
669756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
670756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Map* map = SafeMap(ctx);
67144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap = map->heap();
67244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!(map == heap->raw_unchecked_context_map() ||
67344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          map == heap->raw_unchecked_catch_context_map() ||
67444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          map == heap->raw_unchecked_global_context_map())) {
675756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      return false;
676756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
677756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
678756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Context* context = reinterpret_cast<Context*>(ctx);
679756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
680756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (IsJSBuiltinsObject(context->global())) {
681756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      return false;
682756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
683756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
684756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return true;
685756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
686756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
687756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static void VisitSharedFunctionInfoGeneric(Map* map, HeapObject* object) {
6890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object);
690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap();
692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    FixedBodyVisitor<StaticMarkingVisitor,
6940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                     SharedFunctionInfo::BodyDescriptor,
6950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                     void>::Visit(map, object);
6960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
6970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static void VisitSharedFunctionInfoAndFlushCode(Map* map,
700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HeapObject* object) {
70144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MarkCompactCollector* collector = map->heap()->mark_compact_collector();
70244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!collector->is_code_flushing_enabled()) {
70344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      VisitSharedFunctionInfoGeneric(map, object);
70444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
70544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitSharedFunctionInfoAndFlushCodeGeneric(map, object, false);
707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static void VisitSharedFunctionInfoAndFlushCodeGeneric(
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Map* map, HeapObject* object, bool known_flush_code_candidate) {
71244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap = map->heap();
713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object);
714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap();
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!known_flush_code_candidate) {
718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      known_flush_code_candidate = IsFlushable(shared);
71944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (known_flush_code_candidate) {
72044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        heap->mark_compact_collector()->code_flusher()->AddCandidate(shared);
72144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
72444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitSharedFunctionInfoFields(heap, object, known_flush_code_candidate);
725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
72844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static void VisitCodeEntry(Heap* heap, Address entry_address) {
729791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    Object* code = Code::GetObjectFromEntryAddress(entry_address);
730791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    Object* old_code = code;
73144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitPointer(heap, &code);
732791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (code != old_code) {
733791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      Memory::Address_at(entry_address) =
734791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block          reinterpret_cast<Code*>(code)->entry();
735791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
736791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
737756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
738791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
739791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) {
74044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap = map->heap();
74144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MarkCompactCollector* collector = heap->mark_compact_collector();
74244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!collector->is_code_flushing_enabled()) {
74344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      VisitJSFunction(map, object);
74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
74544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
747791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object);
748756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The function must have a valid context and not be a builtin.
749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool flush_code_candidate = false;
750756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) {
75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      flush_code_candidate = FlushCodeForFunction(heap, jsfunction);
752756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!flush_code_candidate) {
75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      collector->MarkObject(jsfunction->unchecked_shared()->unchecked_code());
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) {
758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // For optimized functions we should retain both non-optimized version
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // of it's code and non-optimized version of all inlined functions.
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // This is required to support bailing out from inlined code.
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        DeoptimizationInputData* data =
762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            reinterpret_cast<DeoptimizationInputData*>(
763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                jsfunction->unchecked_code()->unchecked_deoptimization_data());
764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FixedArray* literals = data->UncheckedLiteralArray();
766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        for (int i = 0, count = data->InlinedFunctionCount()->value();
768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             i < count;
769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             i++) {
770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i));
77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          collector->MarkObject(inlined->unchecked_shared()->unchecked_code());
772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitJSFunctionFields(map,
777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          reinterpret_cast<JSFunction*>(object),
778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          flush_code_candidate);
779791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
780791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
781791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
782791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  static void VisitJSFunction(Map* map, HeapObject* object) {
783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitJSFunctionFields(map,
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          reinterpret_cast<JSFunction*>(object),
785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          false);
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define SLOT_ADDR(obj, offset) \
790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  reinterpret_cast<Object**>((obj)->address() + offset)
791756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static inline void VisitJSFunctionFields(Map* map,
794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           JSFunction* object,
795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           bool flush_code_candidate) {
79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap = map->heap();
79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MarkCompactCollector* collector = heap->mark_compact_collector();
79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitPointers(heap,
80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  SLOT_ADDR(object, JSFunction::kPropertiesOffset),
801791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                  SLOT_ADDR(object, JSFunction::kCodeEntryOffset));
802791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!flush_code_candidate) {
80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      VisitCodeEntry(heap, object->address() + JSFunction::kCodeEntryOffset);
805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Don't visit code object.
807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Visit shared function info to avoid double checking of it's
809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // flushability.
810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SharedFunctionInfo* shared_info = object->unchecked_shared();
811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!shared_info->IsMarked()) {
812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Map* shared_info_map = shared_info->map();
81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        collector->SetMark(shared_info);
81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        collector->MarkObject(shared_info_map);
815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VisitSharedFunctionInfoAndFlushCodeGeneric(shared_info_map,
816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   shared_info,
817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   true);
818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
820791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitPointers(heap,
82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  SLOT_ADDR(object,
823791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                            JSFunction::kCodeEntryOffset + kPointerSize),
824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                  SLOT_ADDR(object, JSFunction::kNonWeakFieldsEndOffset));
825f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Don't visit the next function list field as it is a weak reference.
827756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
828756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
829791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static void VisitSharedFunctionInfoFields(Heap* heap,
83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            HeapObject* object,
832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            bool flush_code_candidate) {
83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kNameOffset));
834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!flush_code_candidate) {
83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kCodeOffset));
837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
83944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    VisitPointers(heap,
84044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  SLOT_ADDR(object, SharedFunctionInfo::kScopeInfoOffset),
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                  SLOT_ADDR(object, SharedFunctionInfo::kSize));
842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  #undef SLOT_ADDR
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
846756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  typedef void (*Callback)(Map* map, HeapObject* object);
847756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
848756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static VisitorDispatchTable<Callback> table_;
849756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick};
850756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
851756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
852756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickVisitorDispatchTable<StaticMarkingVisitor::Callback>
853756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  StaticMarkingVisitor::table_;
854756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
855756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
856756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickclass MarkingVisitor : public ObjectVisitor {
857756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick public:
85844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit MarkingVisitor(Heap* heap) : heap_(heap) { }
85944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
860756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitPointer(Object** p) {
86144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    StaticMarkingVisitor::VisitPointer(heap_, p);
862756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
863756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
864756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitPointers(Object** start, Object** end) {
86544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    StaticMarkingVisitor::VisitPointers(heap_, start, end);
866756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
867756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
868756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitCodeTarget(RelocInfo* rinfo) {
869756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    StaticMarkingVisitor::VisitCodeTarget(rinfo);
870756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
871756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void VisitGlobalPropertyCell(RelocInfo* rinfo) {
873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    StaticMarkingVisitor::VisitGlobalPropertyCell(rinfo);
874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
876756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitDebugTarget(RelocInfo* rinfo) {
877756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    StaticMarkingVisitor::VisitDebugTarget(rinfo);
878756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
88044f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap_;
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
885756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickclass CodeMarkingVisitor : public ThreadVisitor {
886756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick public:
88744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit CodeMarkingVisitor(MarkCompactCollector* collector)
88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : collector_(collector) {}
88944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
890756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitThread(ThreadLocalTop* top) {
891756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (StackFrameIterator it(top); !it.done(); it.Advance()) {
89244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      collector_->MarkObject(it.frame()->unchecked_code());
893756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
894756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
89544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
89644f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MarkCompactCollector* collector_;
898756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick};
899756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
900756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
901756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickclass SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
902756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick public:
90344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector)
90444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : collector_(collector) {}
90544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
906756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitPointers(Object** start, Object** end) {
907756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (Object** p = start; p < end; p++) VisitPointer(p);
908756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
909756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
910756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void VisitPointer(Object** slot) {
911756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Object* obj = *slot;
912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (obj->IsSharedFunctionInfo()) {
913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj);
91444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      collector_->MarkObject(shared->unchecked_code());
91544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      collector_->MarkObject(shared);
916756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
917756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
91844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
91944f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
92044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MarkCompactCollector* collector_;
921756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick};
922756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
923756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
924756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MarkCompactCollector::PrepareForCodeFlushing() {
92544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(heap_ == Isolate::Current()->heap());
92644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
927756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (!FLAG_flush_code) {
92844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    EnableCodeFlushing(false);
929756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return;
930756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
931756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
932756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#ifdef ENABLE_DEBUGGER_SUPPORT
93344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (heap_->isolate()->debug()->IsLoaded() ||
93444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->isolate()->debug()->has_break_points()) {
93544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    EnableCodeFlushing(false);
936756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return;
937756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
938756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#endif
93944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  EnableCodeFlushing(true);
940756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
9419ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // Ensure that empty descriptor array is marked. Method MarkDescriptorArray
9429ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // relies on it being marked before any other descriptor array.
94344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MarkObject(heap_->raw_unchecked_empty_descriptor_array());
9449ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
945756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Make sure we are not referencing the code from the stack.
94644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(this == heap_->mark_compact_collector());
947756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (StackFrameIterator it; !it.done(); it.Advance()) {
9489ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    MarkObject(it.frame()->unchecked_code());
949756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
950756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
951756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Iterate the archived stacks in all threads to check if
952756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // the code is referenced.
95344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CodeMarkingVisitor code_marking_visitor(this);
95444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->isolate()->thread_manager()->IterateArchivedThreads(
95544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &code_marking_visitor);
956756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
95744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SharedFunctionInfoMarkingVisitor visitor(this);
95844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->isolate()->compilation_cache()->IterateFunctions(&visitor);
95944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->isolate()->handle_scope_implementer()->Iterate(&visitor);
960756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
9619ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  ProcessMarkingStack();
962756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
963756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
964756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Visitor class for marking heap roots.
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RootMarkingVisitor : public ObjectVisitor {
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
96844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit RootMarkingVisitor(Heap* heap)
96944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : collector_(heap->mark_compact_collector()) { }
97044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitPointer(Object** p) {
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    MarkObjectByPointer(p);
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitPointers(Object** start, Object** end) {
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void MarkObjectByPointer(Object** p) {
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!(*p)->IsHeapObject()) return;
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Replace flat cons strings in place.
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapObject* object = ShortCircuitConsString(p);
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (object->IsMarked()) return;
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Map* map = object->map();
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark the object.
98944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    collector_->SetMark(object);
990756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark the map pointer and body, and push them on the marking stack.
99244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    collector_->MarkObject(map);
993756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    StaticMarkingVisitor::IterateBody(map, object);
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark all the objects reachable from the map and body.  May leave
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // overflowed objects in the heap.
99744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    collector_->EmptyMarkingStack();
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
99944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MarkCompactCollector* collector_;
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class for pruning the symbol table.
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SymbolTableCleaner : public ObjectVisitor {
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SymbolTableCleaner() : pointers_removed_(0) { }
1008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1009e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  virtual void VisitPointers(Object** start, Object** end) {
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Visit all HeapObject pointers in [start, end).
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Object** p = start; p < end; p++) {
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked()) {
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Check if the symbol being pruned is an external symbol. We need to
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // delete the associated external data as this symbol is going away.
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Since no objects have yet been moved we can safely access the map of
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // the object.
1018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if ((*p)->IsExternalString()) {
101944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          HEAP->FinalizeExternalString(String::cast(*p));
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Set the entry to null_value (as deleted).
102244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        *p = HEAP->raw_unchecked_null_value();
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        pointers_removed_++;
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PointersRemoved() {
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return pointers_removed_;
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pointers_removed_;
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1036f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// Implementation of WeakObjectRetainer for mark compact GCs. All marked objects
1037f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// are retained.
1038f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochclass MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
1039f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch public:
1040f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  virtual Object* RetainAs(Object* object) {
1041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    MapWord first_word = HeapObject::cast(object)->map_word();
1042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    if (first_word.IsMarked()) {
1043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      return object;
1044f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    } else {
1045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      return NULL;
1046f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    }
1047f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
1048f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch};
1049f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1050f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!object->IsMarked());
105344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(HEAP->Contains(object));
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsMap()) {
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Map* map = Map::cast(object);
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (FLAG_cleanup_caches_in_maps_at_gc) {
105744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      map->ClearCodeCache(heap_);
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SetMark(map);
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (FLAG_collect_maps &&
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        map->instance_type() <= JS_FUNCTION_TYPE) {
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      MarkMapContents(map);
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
106544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      marking_stack_.Push(map);
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SetMark(object);
106944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    marking_stack_.Push(object);
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkMapContents(Map* map) {
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MarkDescriptorArray(reinterpret_cast<DescriptorArray*>(
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *HeapObject::RawField(map, Map::kInstanceDescriptorsOffset)));
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark the Object* fields of the Map.
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Since the descriptor array has been marked already, it is fine
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // that one of these fields contains a pointer to it.
1081756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Object** start_slot = HeapObject::RawField(map,
1082756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                             Map::kPointerFieldsBeginOffset);
1083756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1084756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Object** end_slot = HeapObject::RawField(map, Map::kPointerFieldsEndOffset);
1085756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
108644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  StaticMarkingVisitor::VisitPointers(map->heap(), start_slot, end_slot);
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkDescriptorArray(
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DescriptorArray* descriptors) {
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (descriptors->IsMarked()) return;
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Empty descriptor array is marked as a root before any maps are marked.
109444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(descriptors != HEAP->raw_unchecked_empty_descriptor_array());
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetMark(descriptors);
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FixedArray* contents = reinterpret_cast<FixedArray*>(
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      descriptors->get(DescriptorArray::kContentArrayIndex));
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(contents->IsHeapObject());
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!contents->IsMarked());
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(contents->IsFixedArray());
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(contents->length() >= 2);
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetMark(contents);
110444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Contents contains (value, details) pairs.  If the details say that the type
110544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION,
110644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // EXTERNAL_ARRAY_TRANSITION or NULL_DESCRIPTOR, we don't mark the value as
110744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // live.  Only for MAP_TRANSITION, EXTERNAL_ARRAY_TRANSITION and
110844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // CONSTANT_TRANSITION is the value an Object* (a Map*).
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < contents->length(); i += 2) {
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If the pair (value, details) at index i, i+1 is not
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // a transition or null descriptor, mark the value.
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PropertyDetails details(Smi::cast(contents->get(i + 1)));
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (details.type() < FIRST_PHANTOM_PROPERTY_TYPE) {
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      HeapObject* object = reinterpret_cast<HeapObject*>(contents->get(i));
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsHeapObject() && !object->IsMarked()) {
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        SetMark(object);
111744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        marking_stack_.Push(object);
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The DescriptorArray descriptors contains a pointer to its contents array,
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // but the contents array is already marked.
112344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  marking_stack_.Push(descriptors);
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::CreateBackPointers() {
112844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapObjectIterator iterator(HEAP->map_space());
1129d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (HeapObject* next_object = iterator.next();
1130d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke       next_object != NULL; next_object = iterator.next()) {
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (next_object->IsMap()) {  // Could also be ByteArray on free list.
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Map* map = Map::cast(next_object);
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          map->instance_type() <= JS_FUNCTION_TYPE) {
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        map->CreateBackPointers();
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
113744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ASSERT(map->instance_descriptors() == HEAP->empty_descriptor_array());
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int OverflowObjectSize(HeapObject* obj) {
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Recover the normal map pointer, it might be marked as live and
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // overflowed.
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord map_word = obj->map_word();
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  map_word.ClearMark();
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  map_word.ClearOverflow();
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj->SizeFromMap(map_word.ToMap());
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass OverflowedObjectsScanner : public AllStatic {
115544f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
115644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Fill the marking stack with overflowed objects returned by the given
115744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // iterator.  Stop when the marking stack is filled or the end of the space
115844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // is reached, whichever comes first.
115944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  template<class T>
116044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static inline void ScanOverflowedObjects(MarkCompactCollector* collector,
116144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           T* it) {
116244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The caller should ensure that the marking stack is initially not full,
116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // so that we don't waste effort pointlessly scanning for objects.
116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(!collector->marking_stack_.is_full());
116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (HeapObject* object = it->next(); object != NULL; object = it->next()) {
116744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (object->IsOverflowed()) {
116844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        object->ClearOverflow();
116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ASSERT(object->IsMarked());
117044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ASSERT(HEAP->Contains(object));
117144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        collector->marking_stack_.Push(object);
117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (collector->marking_stack_.is_full()) return;
117344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
117644f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) {
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return (*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked();
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkSymbolTable() {
118544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SymbolTable* symbol_table = heap_->raw_unchecked_symbol_table();
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark the symbol table itself.
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetMark(symbol_table);
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Explicitly mark the prefix.
118944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MarkingVisitor marker(heap_);
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  symbol_table->IteratePrefix(&marker);
1191756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ProcessMarkingStack();
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) {
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark the heap roots including global variables, stack variables,
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // etc., and all objects reachable from them.
119844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->IterateStrongRoots(visitor, VISIT_ONLY_STRONG);
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle the symbol table specially.
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MarkSymbolTable();
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // There may be overflowed objects in the heap.  Visit them now.
120444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (marking_stack_.overflowed()) {
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RefillMarkingStack();
1206756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    EmptyMarkingStack();
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkObjectGroups() {
121244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  List<ObjectGroup*>* object_groups =
121344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->isolate()->global_handles()->object_groups();
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < object_groups->length(); i++) {
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ObjectGroup* entry = object_groups->at(i);
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (entry == NULL) continue;
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    List<Object**>& objects = entry->objects_;
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool group_marked = false;
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int j = 0; j < objects.length(); j++) {
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Object* object = *objects[j];
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsHeapObject() && HeapObject::cast(object)->IsMarked()) {
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        group_marked = true;
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!group_marked) continue;
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // An object in the group is marked, so mark as gray all white heap
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // objects in the group.
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int j = 0; j < objects.length(); ++j) {
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((*objects[j])->IsHeapObject()) {
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        MarkObject(HeapObject::cast(*objects[j]));
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
123844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Once the entire group has been colored gray, set the object group
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // to NULL so it won't be processed again.
124144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    delete entry;
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    object_groups->at(i) = NULL;
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
124744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MarkCompactCollector::MarkImplicitRefGroups() {
124844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  List<ImplicitRefGroup*>* ref_groups =
124944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->isolate()->global_handles()->implicit_ref_groups();
125044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
125144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < ref_groups->length(); i++) {
125244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ImplicitRefGroup* entry = ref_groups->at(i);
125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (entry == NULL) continue;
125444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
125544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!entry->parent_->IsMarked()) continue;
125644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
125744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    List<Object**>& children = entry->children_;
125844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // A parent object is marked, so mark as gray all child white heap
125944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // objects.
126044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int j = 0; j < children.length(); ++j) {
126144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if ((*children[j])->IsHeapObject()) {
126244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        MarkObject(HeapObject::cast(*children[j]));
126344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
126444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
126544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
126644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Once the entire group has been colored gray, set the  group
126744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // to NULL so it won't be processed again.
126844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    delete entry;
126944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ref_groups->at(i) = NULL;
127044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
127144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
127244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
127344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mark all objects reachable from the objects on the marking stack.
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Before: the marking stack contains zero or more heap object pointers.
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// After: the marking stack is empty, and all objects reachable from the
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// marking stack have been marked, or are overflowed in the heap.
1278756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MarkCompactCollector::EmptyMarkingStack() {
127944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (!marking_stack_.is_empty()) {
128044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HeapObject* object = marking_stack_.Pop();
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(object->IsHeapObject());
128244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(heap_->Contains(object));
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(object->IsMarked());
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!object->IsOverflowed());
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Because the object is marked, we have to recover the original map
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // pointer and use it to mark the object's body.
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    MapWord map_word = object->map_word();
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    map_word.ClearMark();
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Map* map = map_word.ToMap();
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    MarkObject(map);
1292756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1293756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    StaticMarkingVisitor::IterateBody(map, object);
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Sweep the heap for overflowed objects, clear their overflow bits, and
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// push them on the marking stack.  Stop early if the marking stack fills
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// before sweeping completes.  If sweeping completes, there are no remaining
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overflowed objects in the heap so the overflow flag on the markings stack
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is cleared.
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::RefillMarkingStack() {
130444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(marking_stack_.overflowed());
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
130644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SemiSpaceIterator new_it(HEAP->new_space(), &OverflowObjectSize);
130744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &new_it);
130844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapObjectIterator old_pointer_it(HEAP->old_pointer_space(),
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    &OverflowObjectSize);
131244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &old_pointer_it);
131344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapObjectIterator old_data_it(HEAP->old_data_space(), &OverflowObjectSize);
131644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &old_data_it);
131744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapObjectIterator code_it(HEAP->code_space(), &OverflowObjectSize);
132044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &code_it);
132144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapObjectIterator map_it(HEAP->map_space(), &OverflowObjectSize);
132444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &map_it);
132544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapObjectIterator cell_it(HEAP->cell_space(), &OverflowObjectSize);
132844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &cell_it);
132944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LargeObjectIterator lo_it(HEAP->lo_space(), &OverflowObjectSize);
133244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OverflowedObjectsScanner::ScanOverflowedObjects(this, &lo_it);
133344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (marking_stack_.is_full()) return;
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  marking_stack_.clear_overflowed();
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mark all objects reachable (transitively) from objects on the marking
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// stack.  Before: the marking stack contains zero or more heap object
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// pointers.  After: the marking stack is empty and there are no overflowed
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// objects in the heap.
1343756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MarkCompactCollector::ProcessMarkingStack() {
1344756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  EmptyMarkingStack();
134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (marking_stack_.overflowed()) {
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RefillMarkingStack();
1347756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    EmptyMarkingStack();
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MarkCompactCollector::ProcessExternalMarking() {
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool work_to_do = true;
135444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(marking_stack_.is_empty());
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (work_to_do) {
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    MarkObjectGroups();
135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MarkImplicitRefGroups();
135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    work_to_do = !marking_stack_.is_empty();
1359756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ProcessMarkingStack();
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::MarkLiveObjects() {
1365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_MARK);
1366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The recursive GC marker detects when it is nearing stack overflow,
1367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // and switches to a different marking system.  JS interrupts interfere
1368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // with the C stack limit check.
136944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PostponeInterruptsScope postpone(heap_->isolate());
1370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == PREPARE_GC);
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state_ = MARK_LIVE_OBJECTS;
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The to space contains live objects, the from space is used as a marking
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stack.
137744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  marking_stack_.Initialize(heap_->new_space()->FromSpaceLow(),
137844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            heap_->new_space()->FromSpaceHigh());
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
138044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!marking_stack_.overflowed());
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1382756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PrepareForCodeFlushing();
1383756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
138444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  RootMarkingVisitor root_visitor(heap_);
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MarkRoots(&root_visitor);
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The objects reachable from the roots are marked, yet unreachable
138844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // objects are unmarked.  Mark objects reachable due to host
138944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // application specific logic.
139044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ProcessExternalMarking();
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The objects reachable from the roots or object groups are marked,
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // yet unreachable objects are unmarked.  Mark objects reachable
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // only from weak global handles.
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // First we identify nonlive weak handles and mark them as pending
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // destruction.
139844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->isolate()->global_handles()->IdentifyWeakHandles(
139944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &IsUnmarkedHeapObject);
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Then we mark the objects and process the transitive closure.
140144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->isolate()->global_handles()->IterateWeakRoots(&root_visitor);
140244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (marking_stack_.overflowed()) {
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RefillMarkingStack();
1404756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    EmptyMarkingStack();
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
140744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Repeat host application specific marking to mark unmarked objects
140844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // reachable from the weak roots.
140944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ProcessExternalMarking();
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Prune the symbol table removing all symbols only pointed to by the
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // symbol table.  Cannot use symbol_table() here because the symbol
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // table is marked.
141444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SymbolTable* symbol_table = heap_->raw_unchecked_symbol_table();
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SymbolTableCleaner v;
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  symbol_table->IterateElements(&v);
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  symbol_table->ElementsRemoved(v.PointersRemoved());
141844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->external_string_table_.Iterate(&v);
141944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->external_string_table_.CleanUp();
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1421f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Process the weak references.
1422f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  MarkCompactWeakObjectRetainer mark_compact_object_retainer;
142344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->ProcessWeakReferences(&mark_compact_object_retainer);
1424f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove object groups after marking phase.
142644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->isolate()->global_handles()->RemoveObjectGroups();
142744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->isolate()->global_handles()->RemoveImplicitRefGroups();
1428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Flush code from collected candidates.
143044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_code_flushing_enabled()) {
143144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    code_flusher_->ProcessCandidates();
143244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Clean up dead objects from the runtime profiler.
143544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->isolate()->runtime_profiler()->RemoveDeadSamples();
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) {
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  live_bytes_ += obj->Size();
144244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HEAP->new_space()->Contains(obj)) {
14436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_young_objects_size_ += obj->Size();
144444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (HEAP->map_space()->Contains(obj)) {
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(obj->IsMap());
14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_map_objects_size_ += obj->Size();
144744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (HEAP->cell_space()->Contains(obj)) {
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(obj->IsJSGlobalPropertyCell());
14496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_cell_objects_size_ += obj->Size();
145044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (HEAP->old_pointer_space()->Contains(obj)) {
14516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_old_pointer_objects_size_ += obj->Size();
145244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (HEAP->old_data_space()->Contains(obj)) {
14536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_old_data_objects_size_ += obj->Size();
145444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (HEAP->code_space()->Contains(obj)) {
14556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_code_objects_size_ += obj->Size();
145644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (HEAP->lo_space()->Contains(obj)) {
14576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    live_lo_objects_size_ += obj->Size();
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UNREACHABLE();
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // DEBUG
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::SweepLargeObjectSpace() {
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == MARK_LIVE_OBJECTS);
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state_ =
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      compacting_collection_ ? ENCODE_FORWARDING_ADDRESSES : SWEEP_SPACES;
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Deallocate unmarked objects and clear marked bits for marked objects.
147244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->lo_space()->FreeUnmarkedObjects();
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Safe to use during marking phase only.
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool MarkCompactCollector::SafeIsMap(HeapObject* object) {
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord metamap = object->map_word();
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  metamap.ClearMark();
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return metamap.ToMap()->instance_type() == MAP_TYPE;
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::ClearNonLiveTransitions() {
148544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapObjectIterator map_iterator(HEAP->map_space(), &SizeOfMarkedObject);
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Iterate over the map space, setting map transitions that go from
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a marked map to an unmarked map to null transitions.  At the same time,
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // set all the prototype fields of maps back to their original value,
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // dropping the back pointers temporarily stored in the prototype field.
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setting the prototype field requires following the linked list of
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // back pointers, reversing them all at once.  This allows us to find
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // those maps with map transitions that need to be nulled, and only
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scan the descriptor arrays of those maps, not all maps.
1494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // All of these actions are carried out only on maps of JSObjects
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and related subtypes.
1496d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (HeapObject* obj = map_iterator.next();
1497d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke       obj != NULL; obj = map_iterator.next()) {
1498d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Map* map = reinterpret_cast<Map*>(obj);
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!map->IsMarked() && map->IsByteArray()) continue;
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(SafeIsMap(map));
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Only JSObject and subtypes have map transitions and back pointers.
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue;
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (map->instance_type() > JS_FUNCTION_TYPE) continue;
15050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
15060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (map->IsMarked() && map->attached_to_shared_function_info()) {
15070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // This map is used for inobject slack tracking and has been detached
15080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // from SharedFunctionInfo during the mark phase.
15090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Since it survived the GC, reattach it now.
15100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map);
15110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
15120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Follow the chain of back pointers to find the prototype.
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Map* current = map;
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (SafeIsMap(current)) {
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current = reinterpret_cast<Map*>(current->prototype());
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(current->IsHeapObject());
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object* real_prototype = current;
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Follow back pointers, setting them to prototype,
1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // clearing map transitions when necessary.
1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current = map;
1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool on_dead_path = !current->IsMarked();
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object* next;
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (SafeIsMap(current)) {
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      next = current->prototype();
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // There should never be a dead map above a live map.
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(on_dead_path || current->IsMarked());
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // A live map above a dead map indicates a dead transition.
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // This test will always be false on the first iteration.
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (on_dead_path && current->IsMarked()) {
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        on_dead_path = false;
153544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        current->ClearNonLiveTransitions(heap_, real_prototype);
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *HeapObject::RawField(current, Map::kPrototypeOffset) =
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          real_prototype;
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current = reinterpret_cast<Map*>(next);
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 2: Encode forwarding addresses.
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// When compacting, forwarding addresses for objects in old space and map
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// space are encoded in their map pointer word (along with an encoding of
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// their map pointers).
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
1550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// The excact encoding is described in the comments for class MapWord in
1551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// objects.h.
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// An address range [start, end) can have both live and non-live objects.
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Maximal non-live regions are marked so they can be skipped on subsequent
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sweeps of the heap.  A distinguished map-pointer encoding is used to mark
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// free regions of one-word size (in which case the next word is the start
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of a live object).  A second distinguished map-pointer encoding is used
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to mark free regions larger than one word, and the size of the free
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// region (including the first word) is written to the second word of the
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// region.
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Any valid map page offset must lie in the object area of the page, so map
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// page offsets less than Page::kObjectStartOffset are invalid.  We use a
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// pair of distinguished invalid map encodings (for single word and multiple
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// words) to indicate free regions in the page found during computation of
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forwarding addresses and skipped over in subsequent sweeps.
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Encode a free region, defined by the given start address and size, in the
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// first word or two of the region.
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid EncodeFreeRegion(Address free_start, int free_size) {
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(free_size >= kIntSize);
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (free_size == kIntSize) {
157480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Memory::uint32_at(free_start) = MarkCompactCollector::kSingleFreeEncoding;
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(free_size >= 2 * kIntSize);
157780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Memory::uint32_at(free_start) = MarkCompactCollector::kMultiFreeEncoding;
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Memory::int_at(free_start + kIntSize) = free_size;
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Zap the body of the free region.
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_enable_slow_asserts) {
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int offset = 2 * kIntSize;
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         offset < free_size;
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         offset += kPointerSize) {
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Memory::Address_at(free_start + offset) = kZapValue;
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Try to promote all objects in new space.  Heap numbers and sequential
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// strings are promoted to the code space, large objects to large object space,
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and all others to the old space.
159744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockinline MaybeObject* MCAllocateFromNewSpace(Heap* heap,
159844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           HeapObject* object,
15995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                           int object_size) {
16005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MaybeObject* forwarded;
160144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (object_size > heap->MaxObjectSizeInPagedSpace()) {
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    forwarded = Failure::Exception();
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
160444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    OldSpace* target_space = heap->TargetSpace(object);
160544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target_space == heap->old_pointer_space() ||
160644f0eee88ff00398ff7f715fab053374d808c90dSteve Block           target_space == heap->old_data_space());
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    forwarded = target_space->MCAllocateRaw(object_size);
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
16095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* result;
16105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!forwarded->ToObject(&result)) {
161144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result = heap->new_space()->MCAllocateRaw(object_size)->ToObjectUnchecked();
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
16135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  return result;
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocation functions for the paged spaces call the space's MCAllocateRaw.
16185913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT inline MaybeObject* MCAllocateFromOldPointerSpace(
161944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap *heap,
16205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    HeapObject* ignore,
16215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int object_size) {
162244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return heap->old_pointer_space()->MCAllocateRaw(object_size);
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16265913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT inline MaybeObject* MCAllocateFromOldDataSpace(
162744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap,
16285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    HeapObject* ignore,
16295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int object_size) {
163044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return heap->old_data_space()->MCAllocateRaw(object_size);
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16345913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT inline MaybeObject* MCAllocateFromCodeSpace(
163544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap,
16365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    HeapObject* ignore,
16375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int object_size) {
163844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return heap->code_space()->MCAllocateRaw(object_size);
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16425913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT inline MaybeObject* MCAllocateFromMapSpace(
164344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap,
16445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    HeapObject* ignore,
16455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int object_size) {
164644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return heap->map_space()->MCAllocateRaw(object_size);
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMUST_USE_RESULT inline MaybeObject* MCAllocateFromCellSpace(
165144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Heap* heap, HeapObject* ignore, int object_size) {
165244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return heap->cell_space()->MCAllocateRaw(object_size);
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The forwarding address is encoded at the same offset as the current
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to-space object, but in from space.
165844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockinline void EncodeForwardingAddressInNewSpace(Heap* heap,
165944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              HeapObject* old_object,
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              int object_size,
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              Object* new_object,
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              int* ignored) {
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset =
166444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap->new_space()->ToSpaceOffsetForAddress(old_object->address());
166544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Memory::Address_at(heap->new_space()->FromSpaceLow() + offset) =
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      HeapObject::cast(new_object)->address();
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The forwarding address is encoded in the map pointer of the object as an
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// offset (in terms of live bytes) from the address of the first live object
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// in the page.
167344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockinline void EncodeForwardingAddressInPagedSpace(Heap* heap,
167444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                HeapObject* old_object,
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                int object_size,
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                Object* new_object,
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                int* offset) {
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Record the forwarding address of the first live object if necessary.
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*offset == 0) {
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Page::FromAddress(old_object->address())->mc_first_forwarded =
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        HeapObject::cast(new_object)->address();
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding =
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      MapWord::EncodeAddress(old_object->map()->address(), *offset);
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  old_object->set_map_word(encoding);
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *offset += object_size;
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(*offset <= Page::kObjectAreaSize);
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Most non-live objects are ignored.
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline void IgnoreNonLiveObject(HeapObject* object) {}
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Function template that, given a range of addresses (eg, a semispace or a
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// paged space page), iterates through the objects in the range to clear
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mark bits and compute and encode forwarding addresses.  As a side effect,
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// maximal free chunks are marked so that they can be skipped on subsequent
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sweeps.
1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The template parameters are an allocation function, a forwarding address
1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// encoding function, and a function to process non-live objects.
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate<MarkCompactCollector::AllocationFunction Alloc,
1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MarkCompactCollector::EncodingFunction Encode,
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
170744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockinline void EncodeForwardingAddressesInRange(MarkCompactCollector* collector,
170844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             Address start,
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Address end,
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             int* offset) {
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The start address of the current free region while sweeping the space.
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This address is set when a transition from live to non-live objects is
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // encountered.  A value (an encoding of the 'next free region' pointer)
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is written to memory at this address when a transition from non-live to
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // live objects is encountered.
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address free_start = NULL;
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // A flag giving the state of the previously swept object.  Initially true
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to ensure that free_start is initialized to a proper address before
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // trying to write to it.
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_prev_alive = true;
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int object_size;  // Will be set on each iteration of the loop.
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Address current = start; current < end; current += object_size) {
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapObject* object = HeapObject::FromAddress(current);
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (object->IsMarked()) {
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      object->ClearMark();
172844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      collector->tracer()->decrement_marked_count();
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      object_size = object->Size();
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Object* forwarded =
173244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          Alloc(collector->heap(), object, object_size)->ToObjectUnchecked();
173344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Encode(collector->heap(), object, object_size, forwarded, offset);
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (FLAG_gc_verbose) {
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("forward %p -> %p.\n", object->address(),
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               HeapObject::cast(forwarded)->address());
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!is_prev_alive) {  // Transition from non-live to live.
1742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        EncodeFreeRegion(free_start, static_cast<int>(current - free_start));
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        is_prev_alive = true;
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {  // Non-live object.
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      object_size = object->Size();
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ProcessNonLive(object);
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (is_prev_alive) {  // Transition from live to non-live.
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        free_start = current;
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        is_prev_alive = false;
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
17521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      LiveObjectList::ProcessNonLive(object);
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we ended on a free region, mark it.
1757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (!is_prev_alive) {
1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EncodeFreeRegion(free_start, static_cast<int>(end - free_start));
1759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Functions to encode the forwarding pointers in each compactable space.
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::EncodeForwardingAddressesInNewSpace() {
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int ignored;
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInRange<MCAllocateFromNewSpace,
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   EncodeForwardingAddressInNewSpace,
1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   IgnoreNonLiveObject>(
176944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      this,
177044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->new_space()->bottom(),
177144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->new_space()->top(),
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      &ignored);
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate<MarkCompactCollector::AllocationFunction Alloc,
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::EncodeForwardingAddressesInPagedSpace(
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PagedSpace* space) {
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PageIterator it(space, PageIterator::PAGES_IN_USE);
1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (it.has_next()) {
1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Page* p = it.next();
17836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The offset of each live object in the page from the first live object
1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in the page.
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = 0;
1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EncodeForwardingAddressesInRange<Alloc,
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     EncodeForwardingAddressInPagedSpace,
1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     ProcessNonLive>(
179044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        this,
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        p->ObjectAreaStart(),
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        p->AllocationTop(),
1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        &offset);
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// We scavange new space simultaneously with sweeping. This is done in two
17996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// passes.
18006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// The first pass migrates all alive objects from one semispace to another or
18016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// promotes them to old space. Forwading address is written directly into
18026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// first word of object without any encoding. If object is dead we are writing
18036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// NULL as a forwarding address.
18046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// The second pass updates pointers to new space in all spaces. It is possible
18057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// to encounter pointers to dead objects during traversal of dirty regions we
18067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// should clear them to avoid encountering them during next dirty regions
18077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// iteration.
180844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void MigrateObject(Heap* heap,
180944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Address dst,
18107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          Address src,
18117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          int size,
18127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          bool to_old_space) {
18137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (to_old_space) {
181444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap->CopyBlockToOldSpaceAndUpdateRegionMarks(dst, src, size);
18157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
181644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap->CopyBlock(dst, src, size);
18177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
18186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Memory::Address_at(src) = dst;
18206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
18216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1823756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickclass StaticPointersToNewGenUpdatingVisitor : public
1824756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  StaticNewSpaceVisitor<StaticPointersToNewGenUpdatingVisitor> {
1825756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick public:
182644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static inline void VisitPointer(Heap* heap, Object** p) {
1827756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (!(*p)->IsHeapObject()) return;
1828756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1829756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    HeapObject* obj = HeapObject::cast(*p);
1830756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Address old_addr = obj->address();
1831756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
183244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (heap->new_space()->Contains(obj)) {
183344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(heap->InFromSpace(*p));
1834756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      *p = HeapObject::FromAddress(Memory::Address_at(old_addr));
1835756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
1836756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
1837756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick};
1838756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1839756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
18406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Visitor for updating pointers from live objects in old spaces to new space.
18416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It does not expect to encounter pointers to dead objects.
18426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass PointersToNewGenUpdatingVisitor: public ObjectVisitor {
18436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
184444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit PointersToNewGenUpdatingVisitor(Heap* heap) : heap_(heap) { }
184544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
18466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitPointer(Object** p) {
184744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    StaticPointersToNewGenUpdatingVisitor::VisitPointer(heap_, p);
18486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
18496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitPointers(Object** start, Object** end) {
1851756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (Object** p = start; p < end; p++) {
185244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      StaticPointersToNewGenUpdatingVisitor::VisitPointer(heap_, p);
1853756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
18546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
18556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitCodeTarget(RelocInfo* rinfo) {
18576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
18586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
18596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    VisitPointer(&target);
18606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    rinfo->set_target_address(Code::cast(target)->instruction_start());
18616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
18626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitDebugTarget(RelocInfo* rinfo) {
18647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
18657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            rinfo->IsPatchedReturnSequence()) ||
18667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch           (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
18677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            rinfo->IsPatchedDebugBreakSlotSequence()));
18686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
18696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    VisitPointer(&target);
18706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    rinfo->set_call_address(Code::cast(target)->instruction_start());
18716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
187244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
187344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap_;
18746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
18756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Visitor for updating pointers from live objects in old spaces to new space.
18786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It can encounter pointers to dead objects in new space when traversing map
18796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// space (see comment for MigrateObject).
18806ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void UpdatePointerToNewGen(HeapObject** p) {
18816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!(*p)->IsHeapObject()) return;
18826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address old_addr = (*p)->address();
188444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(HEAP->InFromSpace(*p));
18856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address new_addr = Memory::Address_at(old_addr);
18876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (new_addr == NULL) {
18897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // We encountered pointer to a dead object. Clear it so we will
18907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // not visit it again during next iteration of dirty regions.
18917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    *p = NULL;
18927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
18937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    *p = HeapObject::FromAddress(new_addr);
18947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
18956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
18966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
189844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic String* UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
189944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                                 Object** p) {
19006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address old_addr = HeapObject::cast(*p)->address();
19016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address new_addr = Memory::Address_at(old_addr);
19026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return String::cast(HeapObject::FromAddress(new_addr));
19036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
19046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
190644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic bool TryPromoteObject(Heap* heap, HeapObject* object, int object_size) {
19076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* result;
19086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
190944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (object_size > heap->MaxObjectSizeInPagedSpace()) {
19105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    MaybeObject* maybe_result =
191144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        heap->lo_space()->AllocateRawFixedArray(object_size);
19125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (maybe_result->ToObject(&result)) {
19136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      HeapObject* target = HeapObject::cast(result);
191444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      MigrateObject(heap, target->address(), object->address(), object_size,
191544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    true);
191644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap->mark_compact_collector()->tracer()->
1917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          increment_promoted_objects_size(object_size);
19186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
19196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
19206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
192144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    OldSpace* target_space = heap->TargetSpace(object);
19226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
192344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(target_space == heap->old_pointer_space() ||
192444f0eee88ff00398ff7f715fab053374d808c90dSteve Block           target_space == heap->old_data_space());
19255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    MaybeObject* maybe_result = target_space->AllocateRaw(object_size);
19265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (maybe_result->ToObject(&result)) {
19276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      HeapObject* target = HeapObject::cast(result);
192844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      MigrateObject(heap,
192944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    target->address(),
19307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    object->address(),
19317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    object_size,
193244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    target_space == heap->old_pointer_space());
193344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap->mark_compact_collector()->tracer()->
1934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          increment_promoted_objects_size(object_size);
19356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
19366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
19376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
19386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return false;
19406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
19416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
194344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void SweepNewSpace(Heap* heap, NewSpace* space) {
194444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->CheckNewSpaceExpansionCriteria();
19456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address from_bottom = space->bottom();
19476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address from_top = space->top();
19486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Flip the semispaces.  After flipping, to space is empty, from space has
19506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // live objects.
19516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  space->Flip();
19526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  space->ResetAllocationInfo();
19536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int size = 0;
19556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int survivors_size = 0;
19566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // First pass: traverse all objects in inactive semispace, remove marks,
19586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // migrate live objects and write forwarding addresses.
19596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (Address current = from_bottom; current < from_top; current += size) {
19606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HeapObject* object = HeapObject::FromAddress(current);
19616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (object->IsMarked()) {
19636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      object->ClearMark();
196444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap->mark_compact_collector()->tracer()->decrement_marked_count();
19656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      size = object->Size();
19676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      survivors_size += size;
19686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Aggressively promote young survivors to the old space.
197044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (TryPromoteObject(heap, object, size)) {
19716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        continue;
19726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
19736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Promotion failed. Just migrate object to another semispace.
19756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Allocation cannot fail at this point: semispaces are of equal size.
19765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      Object* target = space->AllocateRaw(size)->ToObjectUnchecked();
19776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
197844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      MigrateObject(heap,
197944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    HeapObject::cast(target)->address(),
19807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    current,
19817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    size,
19827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    false);
19836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
19841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Process the dead object before we write a NULL into its header.
19851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      LiveObjectList::ProcessNonLive(object);
19861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
19876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      size = object->Size();
19886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Memory::Address_at(current) = NULL;
19896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
19906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
19916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Second pass: find pointers to new space and update them.
199344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PointersToNewGenUpdatingVisitor updating_visitor(heap);
19946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Update pointers in to space.
1996756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Address current = space->bottom();
1997756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  while (current < space->top()) {
1998756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    HeapObject* object = HeapObject::FromAddress(current);
1999756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    current +=
2000756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        StaticPointersToNewGenUpdatingVisitor::IterateBody(object->map(),
2001756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                                                           object);
20026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
20036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Update roots.
200544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE);
20061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LiveObjectList::IterateElements(&updating_visitor);
20076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Update pointers in old spaces.
200944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->IterateDirtyRegions(heap->old_pointer_space(),
20107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                            &Heap::IteratePointersInDirtyRegion,
20117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                            &UpdatePointerToNewGen,
201244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            heap->WATERMARK_SHOULD_BE_VALID);
20137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->lo_space()->IterateDirtyRegions(&UpdatePointerToNewGen);
20156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Update pointers from cells.
201744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapObjectIterator cell_iterator(heap->cell_space());
20186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (HeapObject* cell = cell_iterator.next();
20196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block       cell != NULL;
20206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block       cell = cell_iterator.next()) {
20216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (cell->IsJSGlobalPropertyCell()) {
20226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Address value_address =
20236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          reinterpret_cast<Address>(cell) +
20246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag);
20256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
2026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
20286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2029f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Update pointer from the global contexts list.
203044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  updating_visitor.VisitPointer(heap->global_contexts_list_address());
2031f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Update pointers from external string table.
203344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->UpdateNewSpaceReferencesInExternalStringTable(
20346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      &UpdateNewSpaceReferenceInExternalStringTableEntry);
20356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // All pointers were updated. Update auxiliary allocation info.
203744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->IncrementYoungSurvivorsCounter(survivors_size);
20386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  space->set_age_mark(space->top());
2039e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2040e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Update JSFunction pointers from the runtime profiler.
204144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap->isolate()->runtime_profiler()->UpdateSamplesAfterScavenge();
2042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void SweepSpace(Heap* heap, PagedSpace* space) {
2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PageIterator it(space, PageIterator::PAGES_IN_USE);
20476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // During sweeping of paged space we are trying to find longest sequences
20496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // of pages without live objects and free them (instead of putting them on
20506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the free list).
20516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Page preceding current.
20536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Page* prev = Page::FromAddress(NULL);
20546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // First empty page in a sequence.
20566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Page* first_empty_page = Page::FromAddress(NULL);
20576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Page preceding first empty page.
20596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Page* prec_first_empty_page = Page::FromAddress(NULL);
20606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If last used page of space ends with a sequence of dead objects
20626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // we can adjust allocation top instead of puting this free area into
20636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the free list. Thus during sweeping we keep track of such areas
20646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // and defer their deallocation until the sweeping of the next page
20656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // is done: if one of the next pages contains live objects we have
20666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // to put such area into the free list.
20676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address last_free_start = NULL;
20686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int last_free_size = 0;
20696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (it.has_next()) {
2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Page* p = it.next();
2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool is_previous_alive = true;
2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address free_start = NULL;
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapObject* object;
2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Address current = p->ObjectAreaStart();
2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         current < p->AllocationTop();
2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         current += object->Size()) {
2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      object = HeapObject::FromAddress(current);
2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsMarked()) {
2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        object->ClearMark();
208344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        heap->mark_compact_collector()->tracer()->decrement_marked_count();
20846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!is_previous_alive) {  // Transition from free to live.
208680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          space->DeallocateBlock(free_start,
208780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                 static_cast<int>(current - free_start),
208880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                 true);
2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          is_previous_alive = true;
2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
209244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        heap->mark_compact_collector()->ReportDeleteIfNeeded(object);
2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (is_previous_alive) {  // Transition from live to free.
2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          free_start = current;
2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          is_previous_alive = false;
2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
20971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        LiveObjectList::ProcessNonLive(object);
2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The object is now unmarked for the call to Size() at the top of the
2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // loop.
2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool page_is_empty = (p->ObjectAreaStart() == p->AllocationTop())
21046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        || (!is_previous_alive && free_start == p->ObjectAreaStart());
21056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (page_is_empty) {
21076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // This page is empty. Check whether we are in the middle of
21086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // sequence of empty pages and start one if not.
21096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (!first_empty_page->is_valid()) {
21106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        first_empty_page = p;
21116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        prec_first_empty_page = prev;
21126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
21136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (!is_previous_alive) {
21156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // There are dead objects on this page. Update space accounting stats
21166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // without putting anything into free list.
21176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int size_in_bytes = static_cast<int>(p->AllocationTop() - free_start);
21186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (size_in_bytes > 0) {
211980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          space->DeallocateBlock(free_start, size_in_bytes, false);
21206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
21216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
21226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
21236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // This page is not empty. Sequence of empty pages ended on the previous
21246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // one.
21256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (first_empty_page->is_valid()) {
21266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        space->FreePages(prec_first_empty_page, prev);
21276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        prec_first_empty_page = first_empty_page = Page::FromAddress(NULL);
21286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
21296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // If there is a free ending area on one of the previous pages we have
21316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // deallocate that area and put it on the free list.
21326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (last_free_size > 0) {
21337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        Page::FromAddress(last_free_start)->
21347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            SetAllocationWatermark(last_free_start);
213580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        space->DeallocateBlock(last_free_start, last_free_size, true);
21366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        last_free_start = NULL;
21376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        last_free_size  = 0;
21386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
21396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // If the last region of this page was not live we remember it.
21416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (!is_previous_alive) {
21426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        ASSERT(last_free_size == 0);
21436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        last_free_size = static_cast<int>(p->AllocationTop() - free_start);
21446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        last_free_start = free_start;
2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
21476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    prev = p;
21496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // We reached end of space. See if we need to adjust allocation top.
21526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address new_allocation_top = NULL;
21536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (first_empty_page->is_valid()) {
21556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Last used pages in space are empty. We can move allocation top backwards
21566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // to the beginning of first empty page.
21576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(prev == space->AllocationTopPage());
21586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    new_allocation_top = first_empty_page->ObjectAreaStart();
21606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (last_free_size > 0) {
21636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // There was a free ending area on the previous page.
21646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Deallocate it without putting it into freelist and move allocation
21656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // top to the beginning of this free area.
216680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    space->DeallocateBlock(last_free_start, last_free_size, false);
21676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    new_allocation_top = last_free_start;
21686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (new_allocation_top != NULL) {
21716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
21726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Page* new_allocation_top_page = Page::FromAllocationTop(new_allocation_top);
21736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!first_empty_page->is_valid()) {
21746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ASSERT(new_allocation_top_page == space->AllocationTopPage());
21756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else if (last_free_size > 0) {
21766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ASSERT(new_allocation_top_page == prec_first_empty_page);
21776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
21786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ASSERT(new_allocation_top_page == first_empty_page);
21796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
21806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
21816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    space->SetTop(new_allocation_top);
2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::EncodeForwardingAddresses() {
2188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Objects in the active semispace of the young generation may be
2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocated to the inactive semispace (if not promoted).  Set the
2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocation info to the beginning of the inactive semispace.
219244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->new_space()->MCResetRelocationInfo();
2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the forwarding pointers in each space.
2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace,
2196d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                        ReportDeleteIfNeeded>(
219744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->old_pointer_space());
2198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace,
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        IgnoreNonLiveObject>(
220144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->old_data_space());
2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace,
2204d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                        ReportDeleteIfNeeded>(
220544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->code_space());
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInPagedSpace<MCAllocateFromCellSpace,
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        IgnoreNonLiveObject>(
220944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->cell_space());
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute new space next to last after the old and code spaces have been
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compacted.  Objects in new space can be promoted to old or code space.
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInNewSpace();
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute map space last because computing forwarding addresses
2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // overwrites non-live objects.  Objects in the other spaces rely on
2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // non-live map pointers to get the sizes of non-live objects.
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace,
2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        IgnoreNonLiveObject>(
222144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->map_space());
2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Write relocation info to the top page, so we can use it later.  This is
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // done after promoting objects from the new space so we get the correct
2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocation top.
222644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->old_pointer_space()->MCWriteRelocationInfoToPage();
222744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->old_data_space()->MCWriteRelocationInfoToPage();
222844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->code_space()->MCWriteRelocationInfoToPage();
222944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->map_space()->MCWriteRelocationInfoToPage();
223044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->cell_space()->MCWriteRelocationInfoToPage();
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2234e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeclass MapIterator : public HeapObjectIterator {
2235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke public:
223644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MapIterator() : HeapObjectIterator(HEAP->map_space(), &SizeCallback) { }
2237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  explicit MapIterator(Address start)
223944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : HeapObjectIterator(HEAP->map_space(), start, &SizeCallback) { }
2240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke private:
2242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static int SizeCallback(HeapObject* unused) {
2243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    USE(unused);
2244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return Map::kSize;
2245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
2247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeclass MapCompact {
2250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke public:
225144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit MapCompact(Heap* heap, int live_maps)
225244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : heap_(heap),
225344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      live_maps_(live_maps),
225444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      to_evacuate_start_(heap->map_space()->TopAfterCompaction(live_maps)),
2255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      map_to_evacuate_it_(to_evacuate_start_),
2256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      first_map_to_evacuate_(
2257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          reinterpret_cast<Map*>(HeapObject::FromAddress(to_evacuate_start_))) {
2258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void CompactMaps() {
2261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // As we know the number of maps to evacuate beforehand,
2262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // we stop then there is no more vacant maps.
2263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    for (Map* next_vacant_map = NextVacantMap();
2264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke         next_vacant_map;
2265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke         next_vacant_map = NextVacantMap()) {
2266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EvacuateMap(next_vacant_map, NextMapToEvacuate());
2267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG
2270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    CheckNoMapsToEvacuate();
2271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif
2272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void UpdateMapPointersInRoots() {
227544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MapUpdatingVisitor map_updating_visitor;
227644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap_->IterateRoots(&map_updating_visitor, VISIT_ONLY_STRONG);
227744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap_->isolate()->global_handles()->IterateWeakRoots(&map_updating_visitor);
227844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LiveObjectList::IterateElements(&map_updating_visitor);
2279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void UpdateMapPointersInPagedSpace(PagedSpace* space) {
228244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(space != heap_->map_space());
2283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    PageIterator it(space, PageIterator::PAGES_IN_USE);
2285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    while (it.has_next()) {
2286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Page* p = it.next();
228744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      UpdateMapPointersInRange(heap_, p->ObjectAreaStart(), p->AllocationTop());
2288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void UpdateMapPointersInNewSpace() {
229244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    NewSpace* space = heap_->new_space();
229344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    UpdateMapPointersInRange(heap_, space->bottom(), space->top());
2294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void UpdateMapPointersInLargeObjectSpace() {
229744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LargeObjectIterator it(heap_->lo_space());
2298d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    for (HeapObject* obj = it.next(); obj != NULL; obj = it.next())
229944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      UpdateMapPointersInObject(heap_, obj);
2300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Finish() {
230344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap_->map_space()->FinishCompaction(to_evacuate_start_, live_maps_);
2304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke private:
230744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap_;
2308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int live_maps_;
2309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Address to_evacuate_start_;
2310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MapIterator vacant_map_it_;
2311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MapIterator map_to_evacuate_it_;
2312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Map* first_map_to_evacuate_;
2313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Helper class for updating map pointers in HeapObjects.
2315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  class MapUpdatingVisitor: public ObjectVisitor {
2316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  public:
231744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MapUpdatingVisitor() {}
231844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    void VisitPointer(Object** p) {
2320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UpdateMapPointer(p);
2321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    void VisitPointers(Object** start, Object** end) {
2324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      for (Object** p = start; p < end; p++) UpdateMapPointer(p);
2325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  private:
2328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    void UpdateMapPointer(Object** p) {
2329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!(*p)->IsHeapObject()) return;
2330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      HeapObject* old_map = reinterpret_cast<HeapObject*>(*p);
2331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Moved maps are tagged with overflowed map word.  They are the only
2333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // objects those map word is overflowed as marking is already complete.
2334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      MapWord map_word = old_map->map_word();
2335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!map_word.IsOverflowed()) return;
2336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      *p = GetForwardedMap(map_word);
2338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  };
2340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static Map* NextMap(MapIterator* it, HeapObject* last, bool live) {
2342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    while (true) {
2343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      HeapObject* next = it->next();
2344d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      ASSERT(next != NULL);
2345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (next == last)
2346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        return NULL;
2347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(!next->IsOverflowed());
2348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(!next->IsMarked());
2349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(next->IsMap() || FreeListNode::IsFreeListNode(next));
2350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (next->IsMap() == live)
2351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        return reinterpret_cast<Map*>(next);
2352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Map* NextVacantMap() {
2356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Map* map = NextMap(&vacant_map_it_, first_map_to_evacuate_, false);
2357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map == NULL || FreeListNode::IsFreeListNode(map));
2358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return map;
2359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Map* NextMapToEvacuate() {
2362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Map* map = NextMap(&map_to_evacuate_it_, NULL, true);
2363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map != NULL);
2364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map->IsMap());
2365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return map;
2366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static void EvacuateMap(Map* vacant_map, Map* map_to_evacuate) {
2369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(FreeListNode::IsFreeListNode(vacant_map));
2370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map_to_evacuate->IsMap());
2371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
23726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(Map::kSize % 4 == 0);
23736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
237444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    map_to_evacuate->heap()->CopyBlockToOldSpaceAndUpdateRegionMarks(
237544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        vacant_map->address(), map_to_evacuate->address(), Map::kSize);
23766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(vacant_map->IsMap());  // Due to memcpy above.
2378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MapWord forwarding_map_word = MapWord::FromMap(vacant_map);
2380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    forwarding_map_word.SetOverflow();
2381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_to_evacuate->set_map_word(forwarding_map_word);
2382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map_to_evacuate->map_word().IsOverflowed());
2384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(GetForwardedMap(map_to_evacuate->map_word()) == vacant_map);
2385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static Map* GetForwardedMap(MapWord map_word) {
2388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(map_word.IsOverflowed());
2389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_word.ClearOverflow();
2390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Map* new_map = map_word.ToMap();
2391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT_MAP_ALIGNED(new_map->address());
2392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return new_map;
2393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
239544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static int UpdateMapPointersInObject(Heap* heap, HeapObject* obj) {
2396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(!obj->IsMarked());
2397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Map* map = obj->map();
239844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(heap->map_space()->Contains(map));
2399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MapWord map_word = map->map_word();
2400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(!map_word.IsMarked());
2401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (map_word.IsOverflowed()) {
2402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Map* new_map = GetForwardedMap(map_word);
240344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(heap->map_space()->Contains(new_map));
2404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      obj->set_map(new_map);
2405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG
2407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (FLAG_gc_verbose) {
2408f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch        PrintF("update %p : %p -> %p\n",
2409f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               obj->address(),
2410f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               reinterpret_cast<void*>(map),
2411f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch               reinterpret_cast<void*>(new_map));
2412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif
2414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int size = obj->SizeFromMap(map);
241744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MapUpdatingVisitor map_updating_visitor;
241844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    obj->IterateBody(map->instance_type(), size, &map_updating_visitor);
2419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return size;
2420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
242244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static void UpdateMapPointersInRange(Heap* heap, Address start, Address end) {
2423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    HeapObject* object;
2424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int size;
2425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    for (Address current = start; current < end; current += size) {
2426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      object = HeapObject::FromAddress(current);
242744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      size = UpdateMapPointersInObject(heap, object);
2428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      ASSERT(size > 0);
2429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG
2433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void CheckNoMapsToEvacuate() {
2434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (!FLAG_enable_slow_asserts)
2435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return;
2436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2437d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    for (HeapObject* obj = map_to_evacuate_it_.next();
2438d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke         obj != NULL; obj = map_to_evacuate_it_.next())
2439d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      ASSERT(FreeListNode::IsFreeListNode(obj));
2440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif
2442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
2443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::SweepSpaces() {
2446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP);
2447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == SWEEP_SPACES);
2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!IsCompacting());
2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Noncompacting collections simply sweep the spaces to clear the mark
2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bits and free the nonlive blocks (for old and map spaces).  We sweep
2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the map space last because freeing non-live maps overwrites them and
2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the other spaces rely on possibly non-live maps to get the sizes for
2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // non-live objects.
245544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SweepSpace(heap_, heap_->old_pointer_space());
245644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SweepSpace(heap_, heap_->old_data_space());
245744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SweepSpace(heap_, heap_->code_space());
245844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SweepSpace(heap_, heap_->cell_space());
2459756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE);
246044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SweepNewSpace(heap_, heap_->new_space());
2461756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
246244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SweepSpace(heap_, heap_->map_space());
24637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
246444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->IterateDirtyRegions(heap_->map_space(),
246544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             &heap_->IteratePointersInDirtyMapsRegion,
246644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             &UpdatePointerToNewGen,
246744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             heap_->WATERMARK_SHOULD_BE_VALID);
24687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
246944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t live_maps_size = heap_->map_space()->Size();
2470f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  int live_maps = static_cast<int>(live_maps_size / Map::kSize);
24716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_map_objects_size_ == live_maps_size);
2472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
247344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (heap_->map_space()->NeedsCompaction(live_maps)) {
247444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MapCompact map_compact(heap_, live_maps);
2475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_compact.CompactMaps();
2477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_compact.UpdateMapPointersInRoots();
2478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    PagedSpaces spaces;
2480d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    for (PagedSpace* space = spaces.next();
2481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke         space != NULL; space = spaces.next()) {
248244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (space == heap_->map_space()) continue;
2483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      map_compact.UpdateMapPointersInPagedSpace(space);
2484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_compact.UpdateMapPointersInNewSpace();
2486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_compact.UpdateMapPointersInLargeObjectSpace();
2487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    map_compact.Finish();
2489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Iterate the live objects in a range of addresses (eg, a page or a
2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// semispace).  The live regions of the range have been linked into a list.
2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The first live region is [first_live_start, first_live_end), and the last
2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// address in the range is top.  The callback function is used to get the
2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// size of each live object.
2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::IterateLiveObjectsInRange(
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address start,
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address end,
250144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LiveObjectCallback size_func) {
25026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int live_objects_size = 0;
2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address current = start;
2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (current < end) {
2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t encoded_map = Memory::uint32_at(current);
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (encoded_map == kSingleFreeEncoding) {
2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current += kPointerSize;
2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (encoded_map == kMultiFreeEncoding) {
2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current += Memory::int_at(current + kIntSize);
2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
251144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      int size = (this->*size_func)(HeapObject::FromAddress(current));
25126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      current += size;
25136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      live_objects_size += size;
2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
25166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return live_objects_size;
2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
252044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MarkCompactCollector::IterateLiveObjects(
252144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    NewSpace* space, LiveObjectCallback size_f) {
2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
2523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return IterateLiveObjectsInRange(space->bottom(), space->top(), size_f);
2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
252744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MarkCompactCollector::IterateLiveObjects(
252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PagedSpace* space, LiveObjectCallback size_f) {
2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int total = 0;
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PageIterator it(space, PageIterator::PAGES_IN_USE);
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (it.has_next()) {
2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Page* p = it.next();
2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    total += IterateLiveObjectsInRange(p->ObjectAreaStart(),
2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       p->AllocationTop(),
2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       size_f);
2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return total;
2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 3: Update pointers
2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class for updating pointers in HeapObjects.
2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass UpdatingVisitor: public ObjectVisitor {
2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
254844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit UpdatingVisitor(Heap* heap) : heap_(heap) {}
254944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitPointer(Object** p) {
2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UpdatePointer(p);
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitPointers(Object** start, Object** end) {
2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark all HeapObject pointers in [start, end)
2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Object** p = start; p < end; p++) UpdatePointer(p);
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitCodeTarget(RelocInfo* rinfo) {
2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    VisitPointer(&target);
2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rinfo->set_target_address(
2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        reinterpret_cast<Code*>(target)->instruction_start());
2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void VisitDebugTarget(RelocInfo* rinfo) {
25687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
25697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            rinfo->IsPatchedReturnSequence()) ||
25707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch           (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
25717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            rinfo->IsPatchedDebugBreakSlotSequence()));
25723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
25733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    VisitPointer(&target);
25743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    rinfo->set_call_address(
25753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        reinterpret_cast<Code*>(target)->instruction_start());
25763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
25773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdatePointer(Object** p) {
2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!(*p)->IsHeapObject()) return;
2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapObject* obj = HeapObject::cast(*p);
2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address old_addr = obj->address();
2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address new_addr;
258544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(!heap_->InFromSpace(obj));
2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (heap_->new_space()->Contains(obj)) {
2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Address forwarding_pointer_addr =
258944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          heap_->new_space()->FromSpaceLow() +
259044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          heap_->new_space()->ToSpaceOffsetForAddress(old_addr);
2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      new_addr = Memory::Address_at(forwarding_pointer_addr);
2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
259444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(heap_->old_pointer_space()->Contains(new_addr) ||
259544f0eee88ff00398ff7f715fab053374d808c90dSteve Block             heap_->old_data_space()->Contains(new_addr) ||
259644f0eee88ff00398ff7f715fab053374d808c90dSteve Block             heap_->new_space()->FromSpaceContains(new_addr) ||
259744f0eee88ff00398ff7f715fab053374d808c90dSteve Block             heap_->lo_space()->Contains(HeapObject::FromAddress(new_addr)));
259844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
259944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (heap_->new_space()->FromSpaceContains(new_addr)) {
260044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ASSERT(heap_->new_space()->FromSpaceOffsetForAddress(new_addr) <=
260144f0eee88ff00398ff7f715fab053374d808c90dSteve Block               heap_->new_space()->ToSpaceOffsetForAddress(old_addr));
2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
260544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (heap_->lo_space()->Contains(obj)) {
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Don't move objects in the large object space.
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PagedSpaces spaces;
2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PagedSpace* original_space = spaces.next();
2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      while (original_space != NULL) {
2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (original_space->Contains(obj)) break;
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        original_space = spaces.next();
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(original_space != NULL);
2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      new_addr = MarkCompactCollector::GetForwardingAddressInOldSpace(obj);
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(original_space->Contains(new_addr));
2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(original_space->MCSpaceOffsetForAddress(new_addr) <=
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             original_space->MCSpaceOffsetForAddress(old_addr));
2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *p = HeapObject::FromAddress(new_addr);
2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (FLAG_gc_verbose) {
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("update %p : %p -> %p\n",
2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             reinterpret_cast<Address>(p), old_addr, new_addr);
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
263444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
263544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap_;
2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::UpdatePointers() {
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state_ = UPDATE_POINTERS;
2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
264444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  UpdatingVisitor updating_visitor(heap_);
264544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->isolate()->runtime_profiler()->UpdateSamplesAfterCompact(
264644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &updating_visitor);
264744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->IterateRoots(&updating_visitor, VISIT_ONLY_STRONG);
264844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->isolate()->global_handles()->IterateWeakRoots(&updating_visitor);
2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2650f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Update the pointer to the head of the weak list of global contexts.
265144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  updating_visitor.VisitPointer(&heap_->global_contexts_list_);
2652f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
26531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LiveObjectList::IterateElements(&updating_visitor);
26541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
265544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_maps_size = IterateLiveObjects(
265644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->map_space(), &MarkCompactCollector::UpdatePointersInOldObject);
265744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_pointer_olds_size = IterateLiveObjects(
265844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->old_pointer_space(),
265944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &MarkCompactCollector::UpdatePointersInOldObject);
266044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_data_olds_size = IterateLiveObjects(
266144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->old_data_space(),
266244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &MarkCompactCollector::UpdatePointersInOldObject);
266344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_codes_size = IterateLiveObjects(
266444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->code_space(), &MarkCompactCollector::UpdatePointersInOldObject);
266544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_cells_size = IterateLiveObjects(
266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->cell_space(), &MarkCompactCollector::UpdatePointersInOldObject);
266744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_news_size = IterateLiveObjects(
266844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->new_space(), &MarkCompactCollector::UpdatePointersInNewObject);
2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Large objects do not move, the map word can be updated directly.
267144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LargeObjectIterator it(heap_->lo_space());
2672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
2673d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    UpdatePointersInNewObject(obj);
2674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_maps_size);
26776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_pointer_olds_size);
26786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_data_olds_size);
26796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_codes_size);
26806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_cells_size);
26816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_news_size);
26826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_maps_size == live_map_objects_size_);
26836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_data_olds_size == live_old_data_objects_size_);
26846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_);
26856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_codes_size == live_code_objects_size_);
26866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_cells_size == live_cell_objects_size_);
26876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_news_size == live_young_objects_size_);
2688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) {
2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Keep old map pointers
2693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Map* old_map = obj->map();
2694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(old_map->IsHeapObject());
2695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address forwarded = GetForwardingAddressInOldSpace(old_map);
2697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
269844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(heap_->map_space()->Contains(old_map));
269944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(heap_->map_space()->Contains(forwarded));
2700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_gc_verbose) {
2702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("update %p : %p -> %p\n", obj->address(), old_map->address(),
2703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           forwarded);
2704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the map pointer.
2707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(forwarded)));
2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We have to compute the object size relying on the old map because
2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // map objects are not relocated yet.
2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int obj_size = obj->SizeFromMap(old_map);
2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update pointers in the object body.
271444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  UpdatingVisitor updating_visitor(heap_);
2715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->IterateBody(old_map->instance_type(), obj_size, &updating_visitor);
2716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
2717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::UpdatePointersInOldObject(HeapObject* obj) {
2721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Decode the map pointer.
2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding = obj->map_word();
272344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Address map_addr = encoding.DecodeMapAddress(heap_->map_space());
272444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(heap_->map_space()->Contains(HeapObject::FromAddress(map_addr)));
2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // At this point, the first word of map_addr is also encoded, cannot
2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // cast it to Map* using Map::cast.
2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr));
2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int obj_size = obj->SizeFromMap(map);
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstanceType type = map->instance_type();
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update map pointer.
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address new_map_addr = GetForwardingAddressInOldSpace(map);
2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = encoding.DecodeOffset();
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->set_map_word(MapWord::EncodeAddress(new_map_addr, offset));
2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_gc_verbose) {
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("update %p : %p -> %p\n", obj->address(),
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           map_addr, new_map_addr);
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update pointers in the object body.
274544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  UpdatingVisitor updating_visitor(heap_);
2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->IterateBody(type, obj_size, &updating_visitor);
2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) {
2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Object should either in old or map space.
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding = obj->map_word();
2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Offset to the first live object's forwarding address.
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = encoding.DecodeOffset();
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address obj_addr = obj->address();
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find the first live object's forwarding address.
2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Page* p = Page::FromAddress(obj_addr);
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address first_forwarded = p->mc_first_forwarded;
2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Page start address of forwarded address.
2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Page* forwarded_page = Page::FromAddress(first_forwarded);
2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int forwarded_offset = forwarded_page->Offset(first_forwarded);
2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Find end of allocation in the page of first_forwarded.
27687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int mc_top_offset = forwarded_page->AllocationWatermarkOffset();
2769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if current object's forward pointer is in the same page
2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // as the first live object's forwarding pointer
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (forwarded_offset + offset < mc_top_offset) {
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // In the same page.
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return first_forwarded + offset;
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Must be in the next page, NOTE: this may cross chunks.
2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Page* next_page = forwarded_page->next_page();
2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(next_page->is_valid());
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset -= (mc_top_offset - forwarded_offset);
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset += Page::kObjectStartOffset;
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_PAGE_OFFSET(offset);
27857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(next_page->OffsetToAddress(offset) < next_page->AllocationTop());
2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return next_page->OffsetToAddress(offset);
2788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Phase 4: Relocate objects
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MarkCompactCollector::RelocateObjects() {
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(state_ == UPDATE_POINTERS);
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state_ = RELOCATE_OBJECTS;
2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Relocates objects, always relocate map objects first. Relocating
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // objects in other space relies on map objects to get object size.
280144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_maps_size = IterateLiveObjects(
280244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->map_space(), &MarkCompactCollector::RelocateMapObject);
280344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_pointer_olds_size = IterateLiveObjects(
280444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->old_pointer_space(),
280544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &MarkCompactCollector::RelocateOldPointerObject);
280644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_data_olds_size = IterateLiveObjects(
280744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->old_data_space(), &MarkCompactCollector::RelocateOldDataObject);
280844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_codes_size = IterateLiveObjects(
280944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->code_space(), &MarkCompactCollector::RelocateCodeObject);
281044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_cells_size = IterateLiveObjects(
281144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->cell_space(), &MarkCompactCollector::RelocateCellObject);
281244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int live_news_size = IterateLiveObjects(
281344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->new_space(), &MarkCompactCollector::RelocateNewObject);
28146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_maps_size);
28166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_pointer_olds_size);
28176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_data_olds_size);
28186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_codes_size);
28196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_cells_size);
28206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  USE(live_news_size);
28216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_maps_size == live_map_objects_size_);
28226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_data_olds_size == live_old_data_objects_size_);
28236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_);
28246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_codes_size == live_code_objects_size_);
28256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_cells_size == live_cell_objects_size_);
28266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(live_news_size == live_young_objects_size_);
2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Flip from and to spaces
282944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->new_space()->Flip();
2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->new_space()->MCCommitRelocationInfo();
28327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set age_mark to bottom in to space
283444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Address mark = heap_->new_space()->bottom();
283544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->new_space()->set_age_mark(mark);
2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PagedSpaces spaces;
2838d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next())
2839d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    space->MCCommitRelocationInfo();
28406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
284144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->CheckNewSpaceExpansionCriteria();
284244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  heap_->IncrementYoungSurvivorsCounter(live_news_size);
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateMapObject(HeapObject* obj) {
2847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Recover map pointer.
2848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding = obj->map_word();
284944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Address map_addr = encoding.DecodeMapAddress(heap_->map_space());
285044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(heap_->map_space()->Contains(HeapObject::FromAddress(map_addr)));
2851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get forwarding address before resetting map pointer
2853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address new_addr = GetForwardingAddressInOldSpace(obj);
2854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset map pointer.  The meta map object may not be copied yet so
2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Map::cast does not yet work.
2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)));
2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address old_addr = obj->address();
2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (new_addr != old_addr) {
28626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Move contents.
286344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap_->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
286444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   old_addr,
286544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   Map::kSize);
2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_gc_verbose) {
2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("relocate %p -> %p\n", old_addr, new_addr);
2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Map::kSize;
2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline int RestoreMap(HeapObject* obj,
2879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             PagedSpace* space,
2880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             Address new_addr,
2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             Address map_addr) {
2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This must be a non-map object, and the function relies on the
2883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // assumption that the Map space is compacted before the other paged
2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // spaces (see RelocateObjects).
2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset map pointer.
2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj->set_map(Map::cast(HeapObject::FromAddress(map_addr)));
2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int obj_size = obj->Size();
2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_OBJECT_SIZE(obj_size);
2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(space->MCSpaceOffsetForAddress(new_addr) <=
2893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         space->MCSpaceOffsetForAddress(obj->address()));
2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_gc_verbose) {
2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("relocate %p -> %p\n", obj->address(), new_addr);
2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj,
2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   PagedSpace* space) {
2907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Recover map pointer.
2908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding = obj->map_word();
290944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Address map_addr = encoding.DecodeMapAddress(heap_->map_space());
291044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(heap_->map_space()->Contains(map_addr));
2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get forwarding address before resetting map pointer.
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address new_addr = GetForwardingAddressInOldSpace(obj);
2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset the map pointer.
2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int obj_size = RestoreMap(obj, space, new_addr, map_addr);
2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address old_addr = obj->address();
2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (new_addr != old_addr) {
29216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Move contents.
292244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (space == heap_->old_data_space()) {
292344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->MoveBlock(new_addr, old_addr, obj_size);
29247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
292544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      heap_->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
292644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                     old_addr,
292744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                     obj_size);
29287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!HeapObject::FromAddress(new_addr)->IsCode());
2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2933d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  HeapObject* copied_to = HeapObject::FromAddress(new_addr);
2934e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (copied_to->IsSharedFunctionInfo()) {
293544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PROFILE(heap_->isolate(),
293644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            SharedFunctionInfoMoveEvent(old_addr, new_addr));
2937d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
293844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP_PROFILE(heap_, ObjectMoveEvent(old_addr, new_addr));
2939d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) {
294544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return RelocateOldNonCodeObject(obj, heap_->old_pointer_space());
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) {
295044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return RelocateOldNonCodeObject(obj, heap_->old_data_space());
2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateCellObject(HeapObject* obj) {
295544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return RelocateOldNonCodeObject(obj, heap_->cell_space());
2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateCodeObject(HeapObject* obj) {
2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Recover map pointer.
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MapWord encoding = obj->map_word();
296244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Address map_addr = encoding.DecodeMapAddress(heap_->map_space());
296344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(heap_->map_space()->Contains(HeapObject::FromAddress(map_addr)));
2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get forwarding address before resetting map pointer
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address new_addr = GetForwardingAddressInOldSpace(obj);
2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset the map pointer.
296944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int obj_size = RestoreMap(obj, heap_->code_space(), new_addr, map_addr);
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address old_addr = obj->address();
2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (new_addr != old_addr) {
29746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Move contents.
297544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap_->MoveBlock(new_addr, old_addr, obj_size);
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapObject* copied_to = HeapObject::FromAddress(new_addr);
2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (copied_to->IsCode()) {
2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // May also update inline cache target.
2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Code::cast(copied_to)->Relocate(new_addr - old_addr);
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Notify the logger that compiled code has moved.
298344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PROFILE(heap_->isolate(), CodeMoveEvent(old_addr, new_addr));
2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
298544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP_PROFILE(heap_, ObjectMoveEvent(old_addr, new_addr));
2986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int obj_size = obj->Size();
2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get forwarding address
2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address old_addr = obj->address();
299644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int offset = heap_->new_space()->ToSpaceOffsetForAddress(old_addr);
2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address new_addr =
299944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Memory::Address_at(heap_->new_space()->FromSpaceLow() + offset);
3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
300244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (heap_->new_space()->FromSpaceContains(new_addr)) {
300344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(heap_->new_space()->FromSpaceOffsetForAddress(new_addr) <=
300444f0eee88ff00398ff7f715fab053374d808c90dSteve Block           heap_->new_space()->ToSpaceOffsetForAddress(old_addr));
3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
300644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(heap_->TargetSpace(obj) == heap_->old_pointer_space() ||
300744f0eee88ff00398ff7f715fab053374d808c90dSteve Block           heap_->TargetSpace(obj) == heap_->old_data_space());
3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // New and old addresses cannot overlap.
301244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (heap_->InNewSpace(HeapObject::FromAddress(new_addr))) {
301344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap_->CopyBlock(new_addr, old_addr, obj_size);
30147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
301544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    heap_->CopyBlockToOldSpaceAndUpdateRegionMarks(new_addr,
301644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   old_addr,
301744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   obj_size);
30187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
3019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_gc_verbose) {
3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("relocate %p -> %p\n", old_addr, new_addr);
3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3026d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  HeapObject* copied_to = HeapObject::FromAddress(new_addr);
3027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (copied_to->IsSharedFunctionInfo()) {
302844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PROFILE(heap_->isolate(),
302944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            SharedFunctionInfoMoveEvent(old_addr, new_addr));
3030d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
303144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP_PROFILE(heap_, ObjectMoveEvent(old_addr, new_addr));
3032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return obj_size;
3034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MarkCompactCollector::EnableCodeFlushing(bool enable) {
303844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (enable) {
303944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (code_flusher_ != NULL) return;
304044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    code_flusher_ = new CodeFlusher(heap_->isolate());
304144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
304244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (code_flusher_ == NULL) return;
304344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    delete code_flusher_;
304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    code_flusher_ = NULL;
304544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
304644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
304744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
304844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3049d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) {
3050b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#ifdef ENABLE_GDB_JIT_INTERFACE
3051b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (obj->IsCode()) {
3052b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    GDBJITInterface::RemoveCode(reinterpret_cast<Code*>(obj));
3053b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
3054b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif
3055d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING
3056d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (obj->IsCode()) {
305744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PROFILE(ISOLATE, CodeDeleteEvent(obj->address()));
3058d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
3059d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif
3060d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
3061d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3062756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
30638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangint MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) {
30648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  MapWord map_word = obj->map_word();
30658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  map_word.ClearMark();
30668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return obj->SizeFromMap(map_word.ToMap());
30678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
30688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
30698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3070756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MarkCompactCollector::Initialize() {
3071756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  StaticPointersToNewGenUpdatingVisitor::Initialize();
3072756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  StaticMarkingVisitor::Initialize();
3073756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
3074756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3075756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
3077