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