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