Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include "v8.h"
     29 
     30 #include "compilation-cache.h"
     31 #include "execution.h"
     32 #include "heap-profiler.h"
     33 #include "gdb-jit.h"
     34 #include "global-handles.h"
     35 #include "ic-inl.h"
     36 #include "liveobjectlist-inl.h"
     37 #include "mark-compact.h"
     38 #include "objects-visiting.h"
     39 #include "stub-cache.h"
     40 
     41 namespace v8 {
     42 namespace internal {
     43 
     44 // -------------------------------------------------------------------------
     45 // MarkCompactCollector
     46 
     47 MarkCompactCollector::MarkCompactCollector() :  // NOLINT
     48 #ifdef DEBUG
     49       state_(IDLE),
     50 #endif
     51       force_compaction_(false),
     52       compacting_collection_(false),
     53       compact_on_next_gc_(false),
     54       previous_marked_count_(0),
     55       tracer_(NULL),
     56 #ifdef DEBUG
     57       live_young_objects_size_(0),
     58       live_old_pointer_objects_size_(0),
     59       live_old_data_objects_size_(0),
     60       live_code_objects_size_(0),
     61       live_map_objects_size_(0),
     62       live_cell_objects_size_(0),
     63       live_lo_objects_size_(0),
     64       live_bytes_(0),
     65 #endif
     66       heap_(NULL),
     67       code_flusher_(NULL) { }
     68 
     69 
     70 void MarkCompactCollector::CollectGarbage() {
     71   // Make sure that Prepare() has been called. The individual steps below will
     72   // update the state as they proceed.
     73   ASSERT(state_ == PREPARE_GC);
     74 
     75   // Prepare has selected whether to compact the old generation or not.
     76   // Tell the tracer.
     77   if (IsCompacting()) tracer_->set_is_compacting();
     78 
     79   MarkLiveObjects();
     80 
     81   if (FLAG_collect_maps) ClearNonLiveTransitions();
     82 
     83   SweepLargeObjectSpace();
     84 
     85   if (IsCompacting()) {
     86     GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_COMPACT);
     87     EncodeForwardingAddresses();
     88 
     89     heap()->MarkMapPointersAsEncoded(true);
     90     UpdatePointers();
     91     heap()->MarkMapPointersAsEncoded(false);
     92     heap()->isolate()->pc_to_code_cache()->Flush();
     93 
     94     RelocateObjects();
     95   } else {
     96     SweepSpaces();
     97     heap()->isolate()->pc_to_code_cache()->Flush();
     98   }
     99 
    100   Finish();
    101 
    102   // Save the count of marked objects remaining after the collection and
    103   // null out the GC tracer.
    104   previous_marked_count_ = tracer_->marked_count();
    105   ASSERT(previous_marked_count_ == 0);
    106   tracer_ = NULL;
    107 }
    108 
    109 
    110 void MarkCompactCollector::Prepare(GCTracer* tracer) {
    111   // Rather than passing the tracer around we stash it in a static member
    112   // variable.
    113   tracer_ = tracer;
    114 
    115 #ifdef DEBUG
    116   ASSERT(state_ == IDLE);
    117   state_ = PREPARE_GC;
    118 #endif
    119   ASSERT(!FLAG_always_compact || !FLAG_never_compact);
    120 
    121   compacting_collection_ =
    122       FLAG_always_compact || force_compaction_ || compact_on_next_gc_;
    123   compact_on_next_gc_ = false;
    124 
    125   if (FLAG_never_compact) compacting_collection_ = false;
    126   if (!heap()->map_space()->MapPointersEncodable())
    127       compacting_collection_ = false;
    128   if (FLAG_collect_maps) CreateBackPointers();
    129 #ifdef ENABLE_GDB_JIT_INTERFACE
    130   if (FLAG_gdbjit) {
    131     // If GDBJIT interface is active disable compaction.
    132     compacting_collection_ = false;
    133   }
    134 #endif
    135 
    136   PagedSpaces spaces;
    137   for (PagedSpace* space = spaces.next();
    138        space != NULL; space = spaces.next()) {
    139     space->PrepareForMarkCompact(compacting_collection_);
    140   }
    141 
    142 #ifdef DEBUG
    143   live_bytes_ = 0;
    144   live_young_objects_size_ = 0;
    145   live_old_pointer_objects_size_ = 0;
    146   live_old_data_objects_size_ = 0;
    147   live_code_objects_size_ = 0;
    148   live_map_objects_size_ = 0;
    149   live_cell_objects_size_ = 0;
    150   live_lo_objects_size_ = 0;
    151 #endif
    152 }
    153 
    154 
    155 void MarkCompactCollector::Finish() {
    156 #ifdef DEBUG
    157   ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS);
    158   state_ = IDLE;
    159 #endif
    160   // The stub cache is not traversed during GC; clear the cache to
    161   // force lazy re-initialization of it. This must be done after the
    162   // GC, because it relies on the new address of certain old space
    163   // objects (empty string, illegal builtin).
    164   heap()->isolate()->stub_cache()->Clear();
    165 
    166   heap()->external_string_table_.CleanUp();
    167 
    168   // If we've just compacted old space there's no reason to check the
    169   // fragmentation limit. Just return.
    170   if (HasCompacted()) return;
    171 
    172   // We compact the old generation on the next GC if it has gotten too
    173   // fragmented (ie, we could recover an expected amount of space by
    174   // reclaiming the waste and free list blocks).
    175   static const int kFragmentationLimit = 15;        // Percent.
    176   static const int kFragmentationAllowed = 1 * MB;  // Absolute.
    177   intptr_t old_gen_recoverable = 0;
    178   intptr_t old_gen_used = 0;
    179 
    180   OldSpaces spaces;
    181   for (OldSpace* space = spaces.next(); space != NULL; space = spaces.next()) {
    182     old_gen_recoverable += space->Waste() + space->AvailableFree();
    183     old_gen_used += space->Size();
    184   }
    185 
    186   int old_gen_fragmentation =
    187       static_cast<int>((old_gen_recoverable * 100.0) / old_gen_used);
    188   if (old_gen_fragmentation > kFragmentationLimit &&
    189       old_gen_recoverable > kFragmentationAllowed) {
    190     compact_on_next_gc_ = true;
    191   }
    192 }
    193 
    194 
    195 // -------------------------------------------------------------------------
    196 // Phase 1: tracing and marking live objects.
    197 //   before: all objects are in normal state.
    198 //   after: a live object's map pointer is marked as '00'.
    199 
    200 // Marking all live objects in the heap as part of mark-sweep or mark-compact
    201 // collection.  Before marking, all objects are in their normal state.  After
    202 // marking, live objects' map pointers are marked indicating that the object
    203 // has been found reachable.
    204 //
    205 // The marking algorithm is a (mostly) depth-first (because of possible stack
    206 // overflow) traversal of the graph of objects reachable from the roots.  It
    207 // uses an explicit stack of pointers rather than recursion.  The young
    208 // generation's inactive ('from') space is used as a marking stack.  The
    209 // objects in the marking stack are the ones that have been reached and marked
    210 // but their children have not yet been visited.
    211 //
    212 // The marking stack can overflow during traversal.  In that case, we set an
    213 // overflow flag.  When the overflow flag is set, we continue marking objects
    214 // reachable from the objects on the marking stack, but no longer push them on
    215 // the marking stack.  Instead, we mark them as both marked and overflowed.
    216 // When the stack is in the overflowed state, objects marked as overflowed
    217 // have been reached and marked but their children have not been visited yet.
    218 // After emptying the marking stack, we clear the overflow flag and traverse
    219 // the heap looking for objects marked as overflowed, push them on the stack,
    220 // and continue with marking.  This process repeats until all reachable
    221 // objects have been marked.
    222 
    223 class CodeFlusher {
    224  public:
    225   explicit CodeFlusher(Isolate* isolate)
    226       : isolate_(isolate),
    227         jsfunction_candidates_head_(NULL),
    228         shared_function_info_candidates_head_(NULL) {}
    229 
    230   void AddCandidate(SharedFunctionInfo* shared_info) {
    231     SetNextCandidate(shared_info, shared_function_info_candidates_head_);
    232     shared_function_info_candidates_head_ = shared_info;
    233   }
    234 
    235   void AddCandidate(JSFunction* function) {
    236     ASSERT(function->unchecked_code() ==
    237            function->unchecked_shared()->unchecked_code());
    238 
    239     SetNextCandidate(function, jsfunction_candidates_head_);
    240     jsfunction_candidates_head_ = function;
    241   }
    242 
    243   void ProcessCandidates() {
    244     ProcessSharedFunctionInfoCandidates();
    245     ProcessJSFunctionCandidates();
    246   }
    247 
    248  private:
    249   void ProcessJSFunctionCandidates() {
    250     Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile);
    251 
    252     JSFunction* candidate = jsfunction_candidates_head_;
    253     JSFunction* next_candidate;
    254     while (candidate != NULL) {
    255       next_candidate = GetNextCandidate(candidate);
    256 
    257       SharedFunctionInfo* shared = candidate->unchecked_shared();
    258 
    259       Code* code = shared->unchecked_code();
    260       if (!code->IsMarked()) {
    261         shared->set_code(lazy_compile);
    262         candidate->set_code(lazy_compile);
    263       } else {
    264         candidate->set_code(shared->unchecked_code());
    265       }
    266 
    267       candidate = next_candidate;
    268     }
    269 
    270     jsfunction_candidates_head_ = NULL;
    271   }
    272 
    273 
    274   void ProcessSharedFunctionInfoCandidates() {
    275     Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile);
    276 
    277     SharedFunctionInfo* candidate = shared_function_info_candidates_head_;
    278     SharedFunctionInfo* next_candidate;
    279     while (candidate != NULL) {
    280       next_candidate = GetNextCandidate(candidate);
    281       SetNextCandidate(candidate, NULL);
    282 
    283       Code* code = candidate->unchecked_code();
    284       if (!code->IsMarked()) {
    285         candidate->set_code(lazy_compile);
    286       }
    287 
    288       candidate = next_candidate;
    289     }
    290 
    291     shared_function_info_candidates_head_ = NULL;
    292   }
    293 
    294   static JSFunction** GetNextCandidateField(JSFunction* candidate) {
    295     return reinterpret_cast<JSFunction**>(
    296         candidate->address() + JSFunction::kCodeEntryOffset);
    297   }
    298 
    299   static JSFunction* GetNextCandidate(JSFunction* candidate) {
    300     return *GetNextCandidateField(candidate);
    301   }
    302 
    303   static void SetNextCandidate(JSFunction* candidate,
    304                                JSFunction* next_candidate) {
    305     *GetNextCandidateField(candidate) = next_candidate;
    306   }
    307 
    308   STATIC_ASSERT(kPointerSize <= Code::kHeaderSize - Code::kHeaderPaddingStart);
    309 
    310   static SharedFunctionInfo** GetNextCandidateField(
    311       SharedFunctionInfo* candidate) {
    312     Code* code = candidate->unchecked_code();
    313     return reinterpret_cast<SharedFunctionInfo**>(
    314         code->address() + Code::kHeaderPaddingStart);
    315   }
    316 
    317   static SharedFunctionInfo* GetNextCandidate(SharedFunctionInfo* candidate) {
    318     return *GetNextCandidateField(candidate);
    319   }
    320 
    321   static void SetNextCandidate(SharedFunctionInfo* candidate,
    322                                SharedFunctionInfo* next_candidate) {
    323     *GetNextCandidateField(candidate) = next_candidate;
    324   }
    325 
    326   Isolate* isolate_;
    327   JSFunction* jsfunction_candidates_head_;
    328   SharedFunctionInfo* shared_function_info_candidates_head_;
    329 
    330   DISALLOW_COPY_AND_ASSIGN(CodeFlusher);
    331 };
    332 
    333 
    334 MarkCompactCollector::~MarkCompactCollector() {
    335   if (code_flusher_ != NULL) {
    336     delete code_flusher_;
    337     code_flusher_ = NULL;
    338   }
    339 }
    340 
    341 
    342 static inline HeapObject* ShortCircuitConsString(Object** p) {
    343   // Optimization: If the heap object pointed to by p is a non-symbol
    344   // cons string whose right substring is HEAP->empty_string, update
    345   // it in place to its left substring.  Return the updated value.
    346   //
    347   // Here we assume that if we change *p, we replace it with a heap object
    348   // (ie, the left substring of a cons string is always a heap object).
    349   //
    350   // The check performed is:
    351   //   object->IsConsString() && !object->IsSymbol() &&
    352   //   (ConsString::cast(object)->second() == HEAP->empty_string())
    353   // except the maps for the object and its possible substrings might be
    354   // marked.
    355   HeapObject* object = HeapObject::cast(*p);
    356   MapWord map_word = object->map_word();
    357   map_word.ClearMark();
    358   InstanceType type = map_word.ToMap()->instance_type();
    359   if ((type & kShortcutTypeMask) != kShortcutTypeTag) return object;
    360 
    361   Object* second = reinterpret_cast<ConsString*>(object)->unchecked_second();
    362   Heap* heap = map_word.ToMap()->heap();
    363   if (second != heap->raw_unchecked_empty_string()) {
    364     return object;
    365   }
    366 
    367   // Since we don't have the object's start, it is impossible to update the
    368   // page dirty marks. Therefore, we only replace the string with its left
    369   // substring when page dirty marks do not change.
    370   Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first();
    371   if (!heap->InNewSpace(object) && heap->InNewSpace(first)) return object;
    372 
    373   *p = first;
    374   return HeapObject::cast(first);
    375 }
    376 
    377 
    378 class StaticMarkingVisitor : public StaticVisitorBase {
    379  public:
    380   static inline void IterateBody(Map* map, HeapObject* obj) {
    381     table_.GetVisitor(map)(map, obj);
    382   }
    383 
    384   static void Initialize() {
    385     table_.Register(kVisitShortcutCandidate,
    386                     &FixedBodyVisitor<StaticMarkingVisitor,
    387                                       ConsString::BodyDescriptor,
    388                                       void>::Visit);
    389 
    390     table_.Register(kVisitConsString,
    391                     &FixedBodyVisitor<StaticMarkingVisitor,
    392                                       ConsString::BodyDescriptor,
    393                                       void>::Visit);
    394 
    395 
    396     table_.Register(kVisitFixedArray,
    397                     &FlexibleBodyVisitor<StaticMarkingVisitor,
    398                                          FixedArray::BodyDescriptor,
    399                                          void>::Visit);
    400 
    401     table_.Register(kVisitGlobalContext,
    402                     &FixedBodyVisitor<StaticMarkingVisitor,
    403                                       Context::MarkCompactBodyDescriptor,
    404                                       void>::Visit);
    405 
    406     table_.Register(kVisitByteArray, &DataObjectVisitor::Visit);
    407     table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit);
    408     table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit);
    409 
    410     table_.Register(kVisitOddball,
    411                     &FixedBodyVisitor<StaticMarkingVisitor,
    412                                       Oddball::BodyDescriptor,
    413                                       void>::Visit);
    414     table_.Register(kVisitMap,
    415                     &FixedBodyVisitor<StaticMarkingVisitor,
    416                                       Map::BodyDescriptor,
    417                                       void>::Visit);
    418 
    419     table_.Register(kVisitCode, &VisitCode);
    420 
    421     table_.Register(kVisitSharedFunctionInfo,
    422                     &VisitSharedFunctionInfoAndFlushCode);
    423 
    424     table_.Register(kVisitJSFunction,
    425                     &VisitJSFunctionAndFlushCode);
    426 
    427     table_.Register(kVisitPropertyCell,
    428                     &FixedBodyVisitor<StaticMarkingVisitor,
    429                                       JSGlobalPropertyCell::BodyDescriptor,
    430                                       void>::Visit);
    431 
    432     table_.RegisterSpecializations<DataObjectVisitor,
    433                                    kVisitDataObject,
    434                                    kVisitDataObjectGeneric>();
    435 
    436     table_.RegisterSpecializations<JSObjectVisitor,
    437                                    kVisitJSObject,
    438                                    kVisitJSObjectGeneric>();
    439 
    440     table_.RegisterSpecializations<StructObjectVisitor,
    441                                    kVisitStruct,
    442                                    kVisitStructGeneric>();
    443   }
    444 
    445   INLINE(static void VisitPointer(Heap* heap, Object** p)) {
    446     MarkObjectByPointer(heap, p);
    447   }
    448 
    449   INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) {
    450     // Mark all objects pointed to in [start, end).
    451     const int kMinRangeForMarkingRecursion = 64;
    452     if (end - start >= kMinRangeForMarkingRecursion) {
    453       if (VisitUnmarkedObjects(heap, start, end)) return;
    454       // We are close to a stack overflow, so just mark the objects.
    455     }
    456     for (Object** p = start; p < end; p++) MarkObjectByPointer(heap, p);
    457   }
    458 
    459   static inline void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) {
    460     ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
    461     Code* code = Code::GetCodeFromTargetAddress(rinfo->target_address());
    462     if (FLAG_cleanup_ics_at_gc && code->is_inline_cache_stub()) {
    463       IC::Clear(rinfo->pc());
    464       // Please note targets for cleared inline cached do not have to be
    465       // marked since they are contained in HEAP->non_monomorphic_cache().
    466     } else {
    467       heap->mark_compact_collector()->MarkObject(code);
    468     }
    469   }
    470 
    471   static void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo) {
    472     ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
    473     Object* cell = rinfo->target_cell();
    474     Object* old_cell = cell;
    475     VisitPointer(heap, &cell);
    476     if (cell != old_cell) {
    477       rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
    478     }
    479   }
    480 
    481   static inline void VisitDebugTarget(Heap* heap, RelocInfo* rinfo) {
    482     ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
    483             rinfo->IsPatchedReturnSequence()) ||
    484            (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
    485             rinfo->IsPatchedDebugBreakSlotSequence()));
    486     HeapObject* code = Code::GetCodeFromTargetAddress(rinfo->call_address());
    487     heap->mark_compact_collector()->MarkObject(code);
    488   }
    489 
    490   // Mark object pointed to by p.
    491   INLINE(static void MarkObjectByPointer(Heap* heap, Object** p)) {
    492     if (!(*p)->IsHeapObject()) return;
    493     HeapObject* object = ShortCircuitConsString(p);
    494     if (!object->IsMarked()) {
    495       heap->mark_compact_collector()->MarkUnmarkedObject(object);
    496     }
    497   }
    498 
    499 
    500   // Visit an unmarked object.
    501   INLINE(static void VisitUnmarkedObject(MarkCompactCollector* collector,
    502                                          HeapObject* obj)) {
    503 #ifdef DEBUG
    504     ASSERT(Isolate::Current()->heap()->Contains(obj));
    505     ASSERT(!obj->IsMarked());
    506 #endif
    507     Map* map = obj->map();
    508     collector->SetMark(obj);
    509     // Mark the map pointer and the body.
    510     if (!map->IsMarked()) collector->MarkUnmarkedObject(map);
    511     IterateBody(map, obj);
    512   }
    513 
    514   // Visit all unmarked objects pointed to by [start, end).
    515   // Returns false if the operation fails (lack of stack space).
    516   static inline bool VisitUnmarkedObjects(Heap* heap,
    517                                           Object** start,
    518                                           Object** end) {
    519     // Return false is we are close to the stack limit.
    520     StackLimitCheck check(heap->isolate());
    521     if (check.HasOverflowed()) return false;
    522 
    523     MarkCompactCollector* collector = heap->mark_compact_collector();
    524     // Visit the unmarked objects.
    525     for (Object** p = start; p < end; p++) {
    526       if (!(*p)->IsHeapObject()) continue;
    527       HeapObject* obj = HeapObject::cast(*p);
    528       if (obj->IsMarked()) continue;
    529       VisitUnmarkedObject(collector, obj);
    530     }
    531     return true;
    532   }
    533 
    534   static inline void VisitExternalReference(Address* p) { }
    535   static inline void VisitRuntimeEntry(RelocInfo* rinfo) { }
    536 
    537  private:
    538   class DataObjectVisitor {
    539    public:
    540     template<int size>
    541     static void VisitSpecialized(Map* map, HeapObject* object) {
    542     }
    543 
    544     static void Visit(Map* map, HeapObject* object) {
    545     }
    546   };
    547 
    548   typedef FlexibleBodyVisitor<StaticMarkingVisitor,
    549                               JSObject::BodyDescriptor,
    550                               void> JSObjectVisitor;
    551 
    552   typedef FlexibleBodyVisitor<StaticMarkingVisitor,
    553                               StructBodyDescriptor,
    554                               void> StructObjectVisitor;
    555 
    556   static void VisitCode(Map* map, HeapObject* object) {
    557     reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>(
    558         map->heap());
    559   }
    560 
    561   // Code flushing support.
    562 
    563   // How many collections newly compiled code object will survive before being
    564   // flushed.
    565   static const int kCodeAgeThreshold = 5;
    566 
    567   inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) {
    568     Object* undefined = heap->raw_unchecked_undefined_value();
    569     return (info->script() != undefined) &&
    570         (reinterpret_cast<Script*>(info->script())->source() != undefined);
    571   }
    572 
    573 
    574   inline static bool IsCompiled(JSFunction* function) {
    575     return function->unchecked_code() !=
    576         function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
    577   }
    578 
    579   inline static bool IsCompiled(SharedFunctionInfo* function) {
    580     return function->unchecked_code() !=
    581         function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
    582   }
    583 
    584   inline static bool IsFlushable(Heap* heap, JSFunction* function) {
    585     SharedFunctionInfo* shared_info = function->unchecked_shared();
    586 
    587     // Code is either on stack, in compilation cache or referenced
    588     // by optimized version of function.
    589     if (function->unchecked_code()->IsMarked()) {
    590       shared_info->set_code_age(0);
    591       return false;
    592     }
    593 
    594     // We do not flush code for optimized functions.
    595     if (function->code() != shared_info->unchecked_code()) {
    596       return false;
    597     }
    598 
    599     return IsFlushable(heap, shared_info);
    600   }
    601 
    602   inline static bool IsFlushable(Heap* heap, SharedFunctionInfo* shared_info) {
    603     // Code is either on stack, in compilation cache or referenced
    604     // by optimized version of function.
    605     if (shared_info->unchecked_code()->IsMarked()) {
    606       shared_info->set_code_age(0);
    607       return false;
    608     }
    609 
    610     // The function must be compiled and have the source code available,
    611     // to be able to recompile it in case we need the function again.
    612     if (!(shared_info->is_compiled() && HasSourceCode(heap, shared_info))) {
    613       return false;
    614     }
    615 
    616     // We never flush code for Api functions.
    617     Object* function_data = shared_info->function_data();
    618     if (function_data->IsHeapObject() &&
    619         (SafeMap(function_data)->instance_type() ==
    620          FUNCTION_TEMPLATE_INFO_TYPE)) {
    621       return false;
    622     }
    623 
    624     // Only flush code for functions.
    625     if (shared_info->code()->kind() != Code::FUNCTION) return false;
    626 
    627     // Function must be lazy compilable.
    628     if (!shared_info->allows_lazy_compilation()) return false;
    629 
    630     // If this is a full script wrapped in a function we do no flush the code.
    631     if (shared_info->is_toplevel()) return false;
    632 
    633     // Age this shared function info.
    634     if (shared_info->code_age() < kCodeAgeThreshold) {
    635       shared_info->set_code_age(shared_info->code_age() + 1);
    636       return false;
    637     }
    638 
    639     return true;
    640   }
    641 
    642 
    643   static bool FlushCodeForFunction(Heap* heap, JSFunction* function) {
    644     if (!IsFlushable(heap, function)) return false;
    645 
    646     // This function's code looks flushable. But we have to postpone the
    647     // decision until we see all functions that point to the same
    648     // SharedFunctionInfo because some of them might be optimized.
    649     // That would make the nonoptimized version of the code nonflushable,
    650     // because it is required for bailing out from optimized code.
    651     heap->mark_compact_collector()->code_flusher()->AddCandidate(function);
    652     return true;
    653   }
    654 
    655 
    656   static inline Map* SafeMap(Object* obj) {
    657     MapWord map_word = HeapObject::cast(obj)->map_word();
    658     map_word.ClearMark();
    659     map_word.ClearOverflow();
    660     return map_word.ToMap();
    661   }
    662 
    663 
    664   static inline bool IsJSBuiltinsObject(Object* obj) {
    665     return obj->IsHeapObject() &&
    666         (SafeMap(obj)->instance_type() == JS_BUILTINS_OBJECT_TYPE);
    667   }
    668 
    669 
    670   static inline bool IsValidNotBuiltinContext(Object* ctx) {
    671     if (!ctx->IsHeapObject()) return false;
    672 
    673     Map* map = SafeMap(ctx);
    674     Heap* heap = map->heap();
    675     if (!(map == heap->raw_unchecked_context_map() ||
    676           map == heap->raw_unchecked_catch_context_map() ||
    677           map == heap->raw_unchecked_global_context_map())) {
    678       return false;
    679     }
    680 
    681     Context* context = reinterpret_cast<Context*>(ctx);
    682 
    683     if (IsJSBuiltinsObject(context->global())) {
    684       return false;
    685     }
    686 
    687     return true;
    688   }
    689 
    690 
    691   static void VisitSharedFunctionInfoGeneric(Map* map, HeapObject* object) {
    692     SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object);
    693 
    694     if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap();
    695 
    696     FixedBodyVisitor<StaticMarkingVisitor,
    697                      SharedFunctionInfo::BodyDescriptor,
    698                      void>::Visit(map, object);
    699   }
    700 
    701 
    702   static void VisitSharedFunctionInfoAndFlushCode(Map* map,
    703                                                   HeapObject* object) {
    704     MarkCompactCollector* collector = map->heap()->mark_compact_collector();
    705     if (!collector->is_code_flushing_enabled()) {
    706       VisitSharedFunctionInfoGeneric(map, object);
    707       return;
    708     }
    709     VisitSharedFunctionInfoAndFlushCodeGeneric(map, object, false);
    710   }
    711 
    712 
    713   static void VisitSharedFunctionInfoAndFlushCodeGeneric(
    714       Map* map, HeapObject* object, bool known_flush_code_candidate) {
    715     Heap* heap = map->heap();
    716     SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object);
    717 
    718     if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap();
    719 
    720     if (!known_flush_code_candidate) {
    721       known_flush_code_candidate = IsFlushable(heap, shared);
    722       if (known_flush_code_candidate) {
    723         heap->mark_compact_collector()->code_flusher()->AddCandidate(shared);
    724       }
    725     }
    726 
    727     VisitSharedFunctionInfoFields(heap, object, known_flush_code_candidate);
    728   }
    729 
    730 
    731   static void VisitCodeEntry(Heap* heap, Address entry_address) {
    732     Object* code = Code::GetObjectFromEntryAddress(entry_address);
    733     Object* old_code = code;
    734     VisitPointer(heap, &code);
    735     if (code != old_code) {
    736       Memory::Address_at(entry_address) =
    737           reinterpret_cast<Code*>(code)->entry();
    738     }
    739   }
    740 
    741 
    742   static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) {
    743     Heap* heap = map->heap();
    744     MarkCompactCollector* collector = heap->mark_compact_collector();
    745     if (!collector->is_code_flushing_enabled()) {
    746       VisitJSFunction(map, object);
    747       return;
    748     }
    749 
    750     JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object);
    751     // The function must have a valid context and not be a builtin.
    752     bool flush_code_candidate = false;
    753     if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) {
    754       flush_code_candidate = FlushCodeForFunction(heap, jsfunction);
    755     }
    756 
    757     if (!flush_code_candidate) {
    758       collector->MarkObject(jsfunction->unchecked_shared()->unchecked_code());
    759 
    760       if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) {
    761         // For optimized functions we should retain both non-optimized version
    762         // of it's code and non-optimized version of all inlined functions.
    763         // This is required to support bailing out from inlined code.
    764         DeoptimizationInputData* data =
    765             reinterpret_cast<DeoptimizationInputData*>(
    766                 jsfunction->unchecked_code()->unchecked_deoptimization_data());
    767 
    768         FixedArray* literals = data->UncheckedLiteralArray();
    769 
    770         for (int i = 0, count = data->InlinedFunctionCount()->value();
    771              i < count;
    772              i++) {
    773           JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i));
    774           collector->MarkObject(inlined->unchecked_shared()->unchecked_code());
    775         }
    776       }
    777     }
    778 
    779     VisitJSFunctionFields(map,
    780                           reinterpret_cast<JSFunction*>(object),
    781                           flush_code_candidate);
    782   }
    783 
    784 
    785   static void VisitJSFunction(Map* map, HeapObject* object) {
    786     VisitJSFunctionFields(map,
    787                           reinterpret_cast<JSFunction*>(object),
    788                           false);
    789   }
    790 
    791 
    792 #define SLOT_ADDR(obj, offset) \
    793   reinterpret_cast<Object**>((obj)->address() + offset)
    794 
    795 
    796   static inline void VisitJSFunctionFields(Map* map,
    797                                            JSFunction* object,
    798                                            bool flush_code_candidate) {
    799     Heap* heap = map->heap();
    800     MarkCompactCollector* collector = heap->mark_compact_collector();
    801 
    802     VisitPointers(heap,
    803                   SLOT_ADDR(object, JSFunction::kPropertiesOffset),
    804                   SLOT_ADDR(object, JSFunction::kCodeEntryOffset));
    805 
    806     if (!flush_code_candidate) {
    807       VisitCodeEntry(heap, object->address() + JSFunction::kCodeEntryOffset);
    808     } else {
    809       // Don't visit code object.
    810 
    811       // Visit shared function info to avoid double checking of it's
    812       // flushability.
    813       SharedFunctionInfo* shared_info = object->unchecked_shared();
    814       if (!shared_info->IsMarked()) {
    815         Map* shared_info_map = shared_info->map();
    816         collector->SetMark(shared_info);
    817         collector->MarkObject(shared_info_map);
    818         VisitSharedFunctionInfoAndFlushCodeGeneric(shared_info_map,
    819                                                    shared_info,
    820                                                    true);
    821       }
    822     }
    823 
    824     VisitPointers(heap,
    825                   SLOT_ADDR(object,
    826                             JSFunction::kCodeEntryOffset + kPointerSize),
    827                   SLOT_ADDR(object, JSFunction::kNonWeakFieldsEndOffset));
    828 
    829     // Don't visit the next function list field as it is a weak reference.
    830   }
    831 
    832 
    833   static void VisitSharedFunctionInfoFields(Heap* heap,
    834                                             HeapObject* object,
    835                                             bool flush_code_candidate) {
    836     VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kNameOffset));
    837 
    838     if (!flush_code_candidate) {
    839       VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kCodeOffset));
    840     }
    841 
    842     VisitPointers(heap,
    843                   SLOT_ADDR(object, SharedFunctionInfo::kScopeInfoOffset),
    844                   SLOT_ADDR(object, SharedFunctionInfo::kSize));
    845   }
    846 
    847   #undef SLOT_ADDR
    848 
    849   typedef void (*Callback)(Map* map, HeapObject* object);
    850 
    851   static VisitorDispatchTable<Callback> table_;
    852 };
    853 
    854 
    855 VisitorDispatchTable<StaticMarkingVisitor::Callback>
    856   StaticMarkingVisitor::table_;
    857 
    858 
    859 class MarkingVisitor : public ObjectVisitor {
    860  public:
    861   explicit MarkingVisitor(Heap* heap) : heap_(heap) { }
    862 
    863   void VisitPointer(Object** p) {
    864     StaticMarkingVisitor::VisitPointer(heap_, p);
    865   }
    866 
    867   void VisitPointers(Object** start, Object** end) {
    868     StaticMarkingVisitor::VisitPointers(heap_, start, end);
    869   }
    870 
    871   void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) {
    872     StaticMarkingVisitor::VisitCodeTarget(heap, rinfo);
    873   }
    874 
    875   void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo) {
    876     StaticMarkingVisitor::VisitGlobalPropertyCell(heap, rinfo);
    877   }
    878 
    879   void VisitDebugTarget(Heap* heap, RelocInfo* rinfo) {
    880     StaticMarkingVisitor::VisitDebugTarget(heap, rinfo);
    881   }
    882 
    883  private:
    884   Heap* heap_;
    885 };
    886 
    887 
    888 class CodeMarkingVisitor : public ThreadVisitor {
    889  public:
    890   explicit CodeMarkingVisitor(MarkCompactCollector* collector)
    891       : collector_(collector) {}
    892 
    893   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
    894     for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
    895       collector_->MarkObject(it.frame()->unchecked_code());
    896     }
    897   }
    898 
    899  private:
    900   MarkCompactCollector* collector_;
    901 };
    902 
    903 
    904 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
    905  public:
    906   explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector)
    907       : collector_(collector) {}
    908 
    909   void VisitPointers(Object** start, Object** end) {
    910     for (Object** p = start; p < end; p++) VisitPointer(p);
    911   }
    912 
    913   void VisitPointer(Object** slot) {
    914     Object* obj = *slot;
    915     if (obj->IsSharedFunctionInfo()) {
    916       SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj);
    917       collector_->MarkObject(shared->unchecked_code());
    918       collector_->MarkObject(shared);
    919     }
    920   }
    921 
    922  private:
    923   MarkCompactCollector* collector_;
    924 };
    925 
    926 
    927 void MarkCompactCollector::PrepareForCodeFlushing() {
    928   ASSERT(heap() == Isolate::Current()->heap());
    929 
    930   if (!FLAG_flush_code) {
    931     EnableCodeFlushing(false);
    932     return;
    933   }
    934 
    935 #ifdef ENABLE_DEBUGGER_SUPPORT
    936   if (heap()->isolate()->debug()->IsLoaded() ||
    937       heap()->isolate()->debug()->has_break_points()) {
    938     EnableCodeFlushing(false);
    939     return;
    940   }
    941 #endif
    942   EnableCodeFlushing(true);
    943 
    944   // Ensure that empty descriptor array is marked. Method MarkDescriptorArray
    945   // relies on it being marked before any other descriptor array.
    946   MarkObject(heap()->raw_unchecked_empty_descriptor_array());
    947 
    948   // Make sure we are not referencing the code from the stack.
    949   ASSERT(this == heap()->mark_compact_collector());
    950   for (StackFrameIterator it; !it.done(); it.Advance()) {
    951     MarkObject(it.frame()->unchecked_code());
    952   }
    953 
    954   // Iterate the archived stacks in all threads to check if
    955   // the code is referenced.
    956   CodeMarkingVisitor code_marking_visitor(this);
    957   heap()->isolate()->thread_manager()->IterateArchivedThreads(
    958       &code_marking_visitor);
    959 
    960   SharedFunctionInfoMarkingVisitor visitor(this);
    961   heap()->isolate()->compilation_cache()->IterateFunctions(&visitor);
    962   heap()->isolate()->handle_scope_implementer()->Iterate(&visitor);
    963 
    964   ProcessMarkingStack();
    965 }
    966 
    967 
    968 // Visitor class for marking heap roots.
    969 class RootMarkingVisitor : public ObjectVisitor {
    970  public:
    971   explicit RootMarkingVisitor(Heap* heap)
    972     : collector_(heap->mark_compact_collector()) { }
    973 
    974   void VisitPointer(Object** p) {
    975     MarkObjectByPointer(p);
    976   }
    977 
    978   void VisitPointers(Object** start, Object** end) {
    979     for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
    980   }
    981 
    982  private:
    983   void MarkObjectByPointer(Object** p) {
    984     if (!(*p)->IsHeapObject()) return;
    985 
    986     // Replace flat cons strings in place.
    987     HeapObject* object = ShortCircuitConsString(p);
    988     if (object->IsMarked()) return;
    989 
    990     Map* map = object->map();
    991     // Mark the object.
    992     collector_->SetMark(object);
    993 
    994     // Mark the map pointer and body, and push them on the marking stack.
    995     collector_->MarkObject(map);
    996     StaticMarkingVisitor::IterateBody(map, object);
    997 
    998     // Mark all the objects reachable from the map and body.  May leave
    999     // overflowed objects in the heap.
   1000     collector_->EmptyMarkingStack();
   1001   }
   1002 
   1003   MarkCompactCollector* collector_;
   1004 };
   1005 
   1006 
   1007 // Helper class for pruning the symbol table.
   1008 class SymbolTableCleaner : public ObjectVisitor {
   1009  public:
   1010   explicit SymbolTableCleaner(Heap* heap)
   1011     : heap_(heap), pointers_removed_(0) { }
   1012 
   1013   virtual void VisitPointers(Object** start, Object** end) {
   1014     // Visit all HeapObject pointers in [start, end).
   1015     for (Object** p = start; p < end; p++) {
   1016       if ((*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked()) {
   1017         // Check if the symbol being pruned is an external symbol. We need to
   1018         // delete the associated external data as this symbol is going away.
   1019 
   1020         // Since no objects have yet been moved we can safely access the map of
   1021         // the object.
   1022         if ((*p)->IsExternalString()) {
   1023           heap_->FinalizeExternalString(String::cast(*p));
   1024         }
   1025         // Set the entry to null_value (as deleted).
   1026         *p = heap_->raw_unchecked_null_value();
   1027         pointers_removed_++;
   1028       }
   1029     }
   1030   }
   1031 
   1032   int PointersRemoved() {
   1033     return pointers_removed_;
   1034   }
   1035  private:
   1036   Heap* heap_;
   1037   int pointers_removed_;
   1038 };
   1039 
   1040 
   1041 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects
   1042 // are retained.
   1043 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
   1044  public:
   1045   virtual Object* RetainAs(Object* object) {
   1046     MapWord first_word = HeapObject::cast(object)->map_word();
   1047     if (first_word.IsMarked()) {
   1048       return object;
   1049     } else {
   1050       return NULL;
   1051     }
   1052   }
   1053 };
   1054 
   1055 
   1056 void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
   1057   ASSERT(!object->IsMarked());
   1058   ASSERT(HEAP->Contains(object));
   1059   if (object->IsMap()) {
   1060     Map* map = Map::cast(object);
   1061     if (FLAG_cleanup_caches_in_maps_at_gc) {
   1062       map->ClearCodeCache(heap());
   1063     }
   1064     SetMark(map);
   1065     if (FLAG_collect_maps &&
   1066         map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
   1067         map->instance_type() <= JS_FUNCTION_TYPE) {
   1068       MarkMapContents(map);
   1069     } else {
   1070       marking_stack_.Push(map);
   1071     }
   1072   } else {
   1073     SetMark(object);
   1074     marking_stack_.Push(object);
   1075   }
   1076 }
   1077 
   1078 
   1079 void MarkCompactCollector::MarkMapContents(Map* map) {
   1080   // Mark prototype transitions array but don't push it into marking stack.
   1081   // This will make references from it weak. We will clean dead prototype
   1082   // transitions in ClearNonLiveTransitions.
   1083   FixedArray* prototype_transitions = map->unchecked_prototype_transitions();
   1084   if (!prototype_transitions->IsMarked()) SetMark(prototype_transitions);
   1085 
   1086   MarkDescriptorArray(reinterpret_cast<DescriptorArray*>(
   1087       *HeapObject::RawField(map, Map::kInstanceDescriptorsOffset)));
   1088 
   1089   // Mark the Object* fields of the Map.
   1090   // Since the descriptor array has been marked already, it is fine
   1091   // that one of these fields contains a pointer to it.
   1092   Object** start_slot = HeapObject::RawField(map,
   1093                                              Map::kPointerFieldsBeginOffset);
   1094 
   1095   Object** end_slot = HeapObject::RawField(map, Map::kPointerFieldsEndOffset);
   1096 
   1097   StaticMarkingVisitor::VisitPointers(map->heap(), start_slot, end_slot);
   1098 }
   1099 
   1100 
   1101 void MarkCompactCollector::MarkDescriptorArray(
   1102     DescriptorArray* descriptors) {
   1103   if (descriptors->IsMarked()) return;
   1104   // Empty descriptor array is marked as a root before any maps are marked.
   1105   ASSERT(descriptors != HEAP->raw_unchecked_empty_descriptor_array());
   1106   SetMark(descriptors);
   1107 
   1108   FixedArray* contents = reinterpret_cast<FixedArray*>(
   1109       descriptors->get(DescriptorArray::kContentArrayIndex));
   1110   ASSERT(contents->IsHeapObject());
   1111   ASSERT(!contents->IsMarked());
   1112   ASSERT(contents->IsFixedArray());
   1113   ASSERT(contents->length() >= 2);
   1114   SetMark(contents);
   1115   // Contents contains (value, details) pairs.  If the details say that the type
   1116   // of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION,
   1117   // EXTERNAL_ARRAY_TRANSITION or NULL_DESCRIPTOR, we don't mark the value as
   1118   // live.  Only for MAP_TRANSITION, EXTERNAL_ARRAY_TRANSITION and
   1119   // CONSTANT_TRANSITION is the value an Object* (a Map*).
   1120   for (int i = 0; i < contents->length(); i += 2) {
   1121     // If the pair (value, details) at index i, i+1 is not
   1122     // a transition or null descriptor, mark the value.
   1123     PropertyDetails details(Smi::cast(contents->get(i + 1)));
   1124     if (details.type() < FIRST_PHANTOM_PROPERTY_TYPE) {
   1125       HeapObject* object = reinterpret_cast<HeapObject*>(contents->get(i));
   1126       if (object->IsHeapObject() && !object->IsMarked()) {
   1127         SetMark(object);
   1128         marking_stack_.Push(object);
   1129       }
   1130     }
   1131   }
   1132   // The DescriptorArray descriptors contains a pointer to its contents array,
   1133   // but the contents array is already marked.
   1134   marking_stack_.Push(descriptors);
   1135 }
   1136 
   1137 
   1138 void MarkCompactCollector::CreateBackPointers() {
   1139   HeapObjectIterator iterator(heap()->map_space());
   1140   for (HeapObject* next_object = iterator.next();
   1141        next_object != NULL; next_object = iterator.next()) {
   1142     if (next_object->IsMap()) {  // Could also be ByteArray on free list.
   1143       Map* map = Map::cast(next_object);
   1144       if (map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
   1145           map->instance_type() <= JS_FUNCTION_TYPE) {
   1146         map->CreateBackPointers();
   1147       } else {
   1148         ASSERT(map->instance_descriptors() == heap()->empty_descriptor_array());
   1149       }
   1150     }
   1151   }
   1152 }
   1153 
   1154 
   1155 static int OverflowObjectSize(HeapObject* obj) {
   1156   // Recover the normal map pointer, it might be marked as live and
   1157   // overflowed.
   1158   MapWord map_word = obj->map_word();
   1159   map_word.ClearMark();
   1160   map_word.ClearOverflow();
   1161   return obj->SizeFromMap(map_word.ToMap());
   1162 }
   1163 
   1164 
   1165 class OverflowedObjectsScanner : public AllStatic {
   1166  public:
   1167   // Fill the marking stack with overflowed objects returned by the given
   1168   // iterator.  Stop when the marking stack is filled or the end of the space
   1169   // is reached, whichever comes first.
   1170   template<class T>
   1171   static inline void ScanOverflowedObjects(MarkCompactCollector* collector,
   1172                                            T* it) {
   1173     // The caller should ensure that the marking stack is initially not full,
   1174     // so that we don't waste effort pointlessly scanning for objects.
   1175     ASSERT(!collector->marking_stack_.is_full());
   1176 
   1177     for (HeapObject* object = it->next(); object != NULL; object = it->next()) {
   1178       if (object->IsOverflowed()) {
   1179         object->ClearOverflow();
   1180         ASSERT(object->IsMarked());
   1181         ASSERT(HEAP->Contains(object));
   1182         collector->marking_stack_.Push(object);
   1183         if (collector->marking_stack_.is_full()) return;
   1184       }
   1185     }
   1186   }
   1187 };
   1188 
   1189 
   1190 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) {
   1191   return (*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked();
   1192 }
   1193 
   1194 
   1195 void MarkCompactCollector::MarkSymbolTable() {
   1196   SymbolTable* symbol_table = heap()->raw_unchecked_symbol_table();
   1197   // Mark the symbol table itself.
   1198   SetMark(symbol_table);
   1199   // Explicitly mark the prefix.
   1200   MarkingVisitor marker(heap());
   1201   symbol_table->IteratePrefix(&marker);
   1202   ProcessMarkingStack();
   1203 }
   1204 
   1205 
   1206 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) {
   1207   // Mark the heap roots including global variables, stack variables,
   1208   // etc., and all objects reachable from them.
   1209   heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG);
   1210 
   1211   // Handle the symbol table specially.
   1212   MarkSymbolTable();
   1213 
   1214   // There may be overflowed objects in the heap.  Visit them now.
   1215   while (marking_stack_.overflowed()) {
   1216     RefillMarkingStack();
   1217     EmptyMarkingStack();
   1218   }
   1219 }
   1220 
   1221 
   1222 void MarkCompactCollector::MarkObjectGroups() {
   1223   List<ObjectGroup*>* object_groups =
   1224       heap()->isolate()->global_handles()->object_groups();
   1225 
   1226   int last = 0;
   1227   for (int i = 0; i < object_groups->length(); i++) {
   1228     ObjectGroup* entry = object_groups->at(i);
   1229     ASSERT(entry != NULL);
   1230 
   1231     Object*** objects = entry->objects_;
   1232     bool group_marked = false;
   1233     for (size_t j = 0; j < entry->length_; j++) {
   1234       Object* object = *objects[j];
   1235       if (object->IsHeapObject() && HeapObject::cast(object)->IsMarked()) {
   1236         group_marked = true;
   1237         break;
   1238       }
   1239     }
   1240 
   1241     if (!group_marked) {
   1242       (*object_groups)[last++] = entry;
   1243       continue;
   1244     }
   1245 
   1246     // An object in the group is marked, so mark all heap objects in
   1247     // the group.
   1248     for (size_t j = 0; j < entry->length_; ++j) {
   1249       if ((*objects[j])->IsHeapObject()) {
   1250         MarkObject(HeapObject::cast(*objects[j]));
   1251       }
   1252     }
   1253 
   1254     // Once the entire group has been marked, dispose it because it's
   1255     // not needed anymore.
   1256     entry->Dispose();
   1257   }
   1258   object_groups->Rewind(last);
   1259 }
   1260 
   1261 
   1262 void MarkCompactCollector::MarkImplicitRefGroups() {
   1263   List<ImplicitRefGroup*>* ref_groups =
   1264       heap()->isolate()->global_handles()->implicit_ref_groups();
   1265 
   1266   int last = 0;
   1267   for (int i = 0; i < ref_groups->length(); i++) {
   1268     ImplicitRefGroup* entry = ref_groups->at(i);
   1269     ASSERT(entry != NULL);
   1270 
   1271     if (!(*entry->parent_)->IsMarked()) {
   1272       (*ref_groups)[last++] = entry;
   1273       continue;
   1274     }
   1275 
   1276     Object*** children = entry->children_;
   1277     // A parent object is marked, so mark all child heap objects.
   1278     for (size_t j = 0; j < entry->length_; ++j) {
   1279       if ((*children[j])->IsHeapObject()) {
   1280         MarkObject(HeapObject::cast(*children[j]));
   1281       }
   1282     }
   1283 
   1284     // Once the entire group has been marked, dispose it because it's
   1285     // not needed anymore.
   1286     entry->Dispose();
   1287   }
   1288   ref_groups->Rewind(last);
   1289 }
   1290 
   1291 
   1292 // Mark all objects reachable from the objects on the marking stack.
   1293 // Before: the marking stack contains zero or more heap object pointers.
   1294 // After: the marking stack is empty, and all objects reachable from the
   1295 // marking stack have been marked, or are overflowed in the heap.
   1296 void MarkCompactCollector::EmptyMarkingStack() {
   1297   while (!marking_stack_.is_empty()) {
   1298     HeapObject* object = marking_stack_.Pop();
   1299     ASSERT(object->IsHeapObject());
   1300     ASSERT(heap()->Contains(object));
   1301     ASSERT(object->IsMarked());
   1302     ASSERT(!object->IsOverflowed());
   1303 
   1304     // Because the object is marked, we have to recover the original map
   1305     // pointer and use it to mark the object's body.
   1306     MapWord map_word = object->map_word();
   1307     map_word.ClearMark();
   1308     Map* map = map_word.ToMap();
   1309     MarkObject(map);
   1310 
   1311     StaticMarkingVisitor::IterateBody(map, object);
   1312   }
   1313 }
   1314 
   1315 
   1316 // Sweep the heap for overflowed objects, clear their overflow bits, and
   1317 // push them on the marking stack.  Stop early if the marking stack fills
   1318 // before sweeping completes.  If sweeping completes, there are no remaining
   1319 // overflowed objects in the heap so the overflow flag on the markings stack
   1320 // is cleared.
   1321 void MarkCompactCollector::RefillMarkingStack() {
   1322   ASSERT(marking_stack_.overflowed());
   1323 
   1324   SemiSpaceIterator new_it(heap()->new_space(), &OverflowObjectSize);
   1325   OverflowedObjectsScanner::ScanOverflowedObjects(this, &new_it);
   1326   if (marking_stack_.is_full()) return;
   1327 
   1328   HeapObjectIterator old_pointer_it(heap()->old_pointer_space(),
   1329                                     &OverflowObjectSize);
   1330   OverflowedObjectsScanner::ScanOverflowedObjects(this, &old_pointer_it);
   1331   if (marking_stack_.is_full()) return;
   1332 
   1333   HeapObjectIterator old_data_it(heap()->old_data_space(), &OverflowObjectSize);
   1334   OverflowedObjectsScanner::ScanOverflowedObjects(this, &old_data_it);
   1335   if (marking_stack_.is_full()) return;
   1336 
   1337   HeapObjectIterator code_it(heap()->code_space(), &OverflowObjectSize);
   1338   OverflowedObjectsScanner::ScanOverflowedObjects(this, &code_it);
   1339   if (marking_stack_.is_full()) return;
   1340 
   1341   HeapObjectIterator map_it(heap()->map_space(), &OverflowObjectSize);
   1342   OverflowedObjectsScanner::ScanOverflowedObjects(this, &map_it);
   1343   if (marking_stack_.is_full()) return;
   1344 
   1345   HeapObjectIterator cell_it(heap()->cell_space(), &OverflowObjectSize);
   1346   OverflowedObjectsScanner::ScanOverflowedObjects(this, &cell_it);
   1347   if (marking_stack_.is_full()) return;
   1348 
   1349   LargeObjectIterator lo_it(heap()->lo_space(), &OverflowObjectSize);
   1350   OverflowedObjectsScanner::ScanOverflowedObjects(this, &lo_it);
   1351   if (marking_stack_.is_full()) return;
   1352 
   1353   marking_stack_.clear_overflowed();
   1354 }
   1355 
   1356 
   1357 // Mark all objects reachable (transitively) from objects on the marking
   1358 // stack.  Before: the marking stack contains zero or more heap object
   1359 // pointers.  After: the marking stack is empty and there are no overflowed
   1360 // objects in the heap.
   1361 void MarkCompactCollector::ProcessMarkingStack() {
   1362   EmptyMarkingStack();
   1363   while (marking_stack_.overflowed()) {
   1364     RefillMarkingStack();
   1365     EmptyMarkingStack();
   1366   }
   1367 }
   1368 
   1369 
   1370 void MarkCompactCollector::ProcessExternalMarking() {
   1371   bool work_to_do = true;
   1372   ASSERT(marking_stack_.is_empty());
   1373   while (work_to_do) {
   1374     MarkObjectGroups();
   1375     MarkImplicitRefGroups();
   1376     work_to_do = !marking_stack_.is_empty();
   1377     ProcessMarkingStack();
   1378   }
   1379 }
   1380 
   1381 
   1382 void MarkCompactCollector::MarkLiveObjects() {
   1383   GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_MARK);
   1384   // The recursive GC marker detects when it is nearing stack overflow,
   1385   // and switches to a different marking system.  JS interrupts interfere
   1386   // with the C stack limit check.
   1387   PostponeInterruptsScope postpone(heap()->isolate());
   1388 
   1389 #ifdef DEBUG
   1390   ASSERT(state_ == PREPARE_GC);
   1391   state_ = MARK_LIVE_OBJECTS;
   1392 #endif
   1393   // The to space contains live objects, the from space is used as a marking
   1394   // stack.
   1395   marking_stack_.Initialize(heap()->new_space()->FromSpaceLow(),
   1396                             heap()->new_space()->FromSpaceHigh());
   1397 
   1398   ASSERT(!marking_stack_.overflowed());
   1399 
   1400   PrepareForCodeFlushing();
   1401 
   1402   RootMarkingVisitor root_visitor(heap());
   1403   MarkRoots(&root_visitor);
   1404 
   1405   // The objects reachable from the roots are marked, yet unreachable
   1406   // objects are unmarked.  Mark objects reachable due to host
   1407   // application specific logic.
   1408   ProcessExternalMarking();
   1409 
   1410   // The objects reachable from the roots or object groups are marked,
   1411   // yet unreachable objects are unmarked.  Mark objects reachable
   1412   // only from weak global handles.
   1413   //
   1414   // First we identify nonlive weak handles and mark them as pending
   1415   // destruction.
   1416   heap()->isolate()->global_handles()->IdentifyWeakHandles(
   1417       &IsUnmarkedHeapObject);
   1418   // Then we mark the objects and process the transitive closure.
   1419   heap()->isolate()->global_handles()->IterateWeakRoots(&root_visitor);
   1420   while (marking_stack_.overflowed()) {
   1421     RefillMarkingStack();
   1422     EmptyMarkingStack();
   1423   }
   1424 
   1425   // Repeat host application specific marking to mark unmarked objects
   1426   // reachable from the weak roots.
   1427   ProcessExternalMarking();
   1428 
   1429   // Prune the symbol table removing all symbols only pointed to by the
   1430   // symbol table.  Cannot use symbol_table() here because the symbol
   1431   // table is marked.
   1432   SymbolTable* symbol_table = heap()->raw_unchecked_symbol_table();
   1433   SymbolTableCleaner v(heap());
   1434   symbol_table->IterateElements(&v);
   1435   symbol_table->ElementsRemoved(v.PointersRemoved());
   1436   heap()->external_string_table_.Iterate(&v);
   1437   heap()->external_string_table_.CleanUp();
   1438 
   1439   // Process the weak references.
   1440   MarkCompactWeakObjectRetainer mark_compact_object_retainer;
   1441   heap()->ProcessWeakReferences(&mark_compact_object_retainer);
   1442 
   1443   // Remove object groups after marking phase.
   1444   heap()->isolate()->global_handles()->RemoveObjectGroups();
   1445   heap()->isolate()->global_handles()->RemoveImplicitRefGroups();
   1446 
   1447   // Flush code from collected candidates.
   1448   if (is_code_flushing_enabled()) {
   1449     code_flusher_->ProcessCandidates();
   1450   }
   1451 
   1452   // Clean up dead objects from the runtime profiler.
   1453   heap()->isolate()->runtime_profiler()->RemoveDeadSamples();
   1454 }
   1455 
   1456 
   1457 #ifdef DEBUG
   1458 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) {
   1459   live_bytes_ += obj->Size();
   1460   if (heap()->new_space()->Contains(obj)) {
   1461     live_young_objects_size_ += obj->Size();
   1462   } else if (heap()->map_space()->Contains(obj)) {
   1463     ASSERT(obj->IsMap());
   1464     live_map_objects_size_ += obj->Size();
   1465   } else if (heap()->cell_space()->Contains(obj)) {
   1466     ASSERT(obj->IsJSGlobalPropertyCell());
   1467     live_cell_objects_size_ += obj->Size();
   1468   } else if (heap()->old_pointer_space()->Contains(obj)) {
   1469     live_old_pointer_objects_size_ += obj->Size();
   1470   } else if (heap()->old_data_space()->Contains(obj)) {
   1471     live_old_data_objects_size_ += obj->Size();
   1472   } else if (heap()->code_space()->Contains(obj)) {
   1473     live_code_objects_size_ += obj->Size();
   1474   } else if (heap()->lo_space()->Contains(obj)) {
   1475     live_lo_objects_size_ += obj->Size();
   1476   } else {
   1477     UNREACHABLE();
   1478   }
   1479 }
   1480 #endif  // DEBUG
   1481 
   1482 
   1483 void MarkCompactCollector::SweepLargeObjectSpace() {
   1484 #ifdef DEBUG
   1485   ASSERT(state_ == MARK_LIVE_OBJECTS);
   1486   state_ =
   1487       compacting_collection_ ? ENCODE_FORWARDING_ADDRESSES : SWEEP_SPACES;
   1488 #endif
   1489   // Deallocate unmarked objects and clear marked bits for marked objects.
   1490   heap()->lo_space()->FreeUnmarkedObjects();
   1491 }
   1492 
   1493 
   1494 // Safe to use during marking phase only.
   1495 bool MarkCompactCollector::SafeIsMap(HeapObject* object) {
   1496   MapWord metamap = object->map_word();
   1497   metamap.ClearMark();
   1498   return metamap.ToMap()->instance_type() == MAP_TYPE;
   1499 }
   1500 
   1501 
   1502 void MarkCompactCollector::ClearNonLiveTransitions() {
   1503   HeapObjectIterator map_iterator(heap()->map_space(), &SizeOfMarkedObject);
   1504   // Iterate over the map space, setting map transitions that go from
   1505   // a marked map to an unmarked map to null transitions.  At the same time,
   1506   // set all the prototype fields of maps back to their original value,
   1507   // dropping the back pointers temporarily stored in the prototype field.
   1508   // Setting the prototype field requires following the linked list of
   1509   // back pointers, reversing them all at once.  This allows us to find
   1510   // those maps with map transitions that need to be nulled, and only
   1511   // scan the descriptor arrays of those maps, not all maps.
   1512   // All of these actions are carried out only on maps of JSObjects
   1513   // and related subtypes.
   1514   for (HeapObject* obj = map_iterator.next();
   1515        obj != NULL; obj = map_iterator.next()) {
   1516     Map* map = reinterpret_cast<Map*>(obj);
   1517     if (!map->IsMarked() && map->IsByteArray()) continue;
   1518 
   1519     ASSERT(SafeIsMap(map));
   1520     // Only JSObject and subtypes have map transitions and back pointers.
   1521     if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue;
   1522     if (map->instance_type() > JS_FUNCTION_TYPE) continue;
   1523 
   1524     if (map->IsMarked() && map->attached_to_shared_function_info()) {
   1525       // This map is used for inobject slack tracking and has been detached
   1526       // from SharedFunctionInfo during the mark phase.
   1527       // Since it survived the GC, reattach it now.
   1528       map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map);
   1529     }
   1530 
   1531     // Clear dead prototype transitions.
   1532     FixedArray* prototype_transitions = map->unchecked_prototype_transitions();
   1533     if (prototype_transitions->length() > 0) {
   1534       int finger = Smi::cast(prototype_transitions->get(0))->value();
   1535       int new_finger = 1;
   1536       for (int i = 1; i < finger; i += 2) {
   1537         Object* prototype = prototype_transitions->get(i);
   1538         Object* cached_map = prototype_transitions->get(i + 1);
   1539         if (HeapObject::cast(prototype)->IsMarked() &&
   1540             HeapObject::cast(cached_map)->IsMarked()) {
   1541           if (new_finger != i) {
   1542             prototype_transitions->set_unchecked(heap_,
   1543                                                  new_finger,
   1544                                                  prototype,
   1545                                                  UPDATE_WRITE_BARRIER);
   1546             prototype_transitions->set_unchecked(heap_,
   1547                                                  new_finger + 1,
   1548                                                  cached_map,
   1549                                                  SKIP_WRITE_BARRIER);
   1550           }
   1551           new_finger += 2;
   1552         }
   1553       }
   1554 
   1555       // Fill slots that became free with undefined value.
   1556       Object* undefined = heap()->raw_unchecked_undefined_value();
   1557       for (int i = new_finger; i < finger; i++) {
   1558         prototype_transitions->set_unchecked(heap_,
   1559                                              i,
   1560                                              undefined,
   1561                                              SKIP_WRITE_BARRIER);
   1562       }
   1563       prototype_transitions->set_unchecked(0, Smi::FromInt(new_finger));
   1564     }
   1565 
   1566     // Follow the chain of back pointers to find the prototype.
   1567     Map* current = map;
   1568     while (SafeIsMap(current)) {
   1569       current = reinterpret_cast<Map*>(current->prototype());
   1570       ASSERT(current->IsHeapObject());
   1571     }
   1572     Object* real_prototype = current;
   1573 
   1574     // Follow back pointers, setting them to prototype,
   1575     // clearing map transitions when necessary.
   1576     current = map;
   1577     bool on_dead_path = !current->IsMarked();
   1578     Object* next;
   1579     while (SafeIsMap(current)) {
   1580       next = current->prototype();
   1581       // There should never be a dead map above a live map.
   1582       ASSERT(on_dead_path || current->IsMarked());
   1583 
   1584       // A live map above a dead map indicates a dead transition.
   1585       // This test will always be false on the first iteration.
   1586       if (on_dead_path && current->IsMarked()) {
   1587         on_dead_path = false;
   1588         current->ClearNonLiveTransitions(heap(), real_prototype);
   1589       }
   1590       *HeapObject::RawField(current, Map::kPrototypeOffset) =
   1591           real_prototype;
   1592       current = reinterpret_cast<Map*>(next);
   1593     }
   1594   }
   1595 }
   1596 
   1597 // -------------------------------------------------------------------------
   1598 // Phase 2: Encode forwarding addresses.
   1599 // When compacting, forwarding addresses for objects in old space and map
   1600 // space are encoded in their map pointer word (along with an encoding of
   1601 // their map pointers).
   1602 //
   1603 // The excact encoding is described in the comments for class MapWord in
   1604 // objects.h.
   1605 //
   1606 // An address range [start, end) can have both live and non-live objects.
   1607 // Maximal non-live regions are marked so they can be skipped on subsequent
   1608 // sweeps of the heap.  A distinguished map-pointer encoding is used to mark
   1609 // free regions of one-word size (in which case the next word is the start
   1610 // of a live object).  A second distinguished map-pointer encoding is used
   1611 // to mark free regions larger than one word, and the size of the free
   1612 // region (including the first word) is written to the second word of the
   1613 // region.
   1614 //
   1615 // Any valid map page offset must lie in the object area of the page, so map
   1616 // page offsets less than Page::kObjectStartOffset are invalid.  We use a
   1617 // pair of distinguished invalid map encodings (for single word and multiple
   1618 // words) to indicate free regions in the page found during computation of
   1619 // forwarding addresses and skipped over in subsequent sweeps.
   1620 
   1621 
   1622 // Encode a free region, defined by the given start address and size, in the
   1623 // first word or two of the region.
   1624 void EncodeFreeRegion(Address free_start, int free_size) {
   1625   ASSERT(free_size >= kIntSize);
   1626   if (free_size == kIntSize) {
   1627     Memory::uint32_at(free_start) = MarkCompactCollector::kSingleFreeEncoding;
   1628   } else {
   1629     ASSERT(free_size >= 2 * kIntSize);
   1630     Memory::uint32_at(free_start) = MarkCompactCollector::kMultiFreeEncoding;
   1631     Memory::int_at(free_start + kIntSize) = free_size;
   1632   }
   1633 
   1634 #ifdef DEBUG
   1635   // Zap the body of the free region.
   1636   if (FLAG_enable_slow_asserts) {
   1637     for (int offset = 2 * kIntSize;
   1638          offset < free_size;
   1639          offset += kPointerSize) {
   1640       Memory::Address_at(free_start + offset) = kZapValue;
   1641     }
   1642   }
   1643 #endif
   1644 }
   1645 
   1646 
   1647 // Try to promote all objects in new space.  Heap numbers and sequential
   1648 // strings are promoted to the code space, large objects to large object space,
   1649 // and all others to the old space.
   1650 inline MaybeObject* MCAllocateFromNewSpace(Heap* heap,
   1651                                            HeapObject* object,
   1652                                            int object_size) {
   1653   MaybeObject* forwarded;
   1654   if (object_size > heap->MaxObjectSizeInPagedSpace()) {
   1655     forwarded = Failure::Exception();
   1656   } else {
   1657     OldSpace* target_space = heap->TargetSpace(object);
   1658     ASSERT(target_space == heap->old_pointer_space() ||
   1659            target_space == heap->old_data_space());
   1660     forwarded = target_space->MCAllocateRaw(object_size);
   1661   }
   1662   Object* result;
   1663   if (!forwarded->ToObject(&result)) {
   1664     result = heap->new_space()->MCAllocateRaw(object_size)->ToObjectUnchecked();
   1665   }
   1666   return result;
   1667 }
   1668 
   1669 
   1670 // Allocation functions for the paged spaces call the space's MCAllocateRaw.
   1671 MUST_USE_RESULT inline MaybeObject* MCAllocateFromOldPointerSpace(
   1672     Heap *heap,
   1673     HeapObject* ignore,
   1674     int object_size) {
   1675   return heap->old_pointer_space()->MCAllocateRaw(object_size);
   1676 }
   1677 
   1678 
   1679 MUST_USE_RESULT inline MaybeObject* MCAllocateFromOldDataSpace(
   1680     Heap* heap,
   1681     HeapObject* ignore,
   1682     int object_size) {
   1683   return heap->old_data_space()->MCAllocateRaw(object_size);
   1684 }
   1685 
   1686 
   1687 MUST_USE_RESULT inline MaybeObject* MCAllocateFromCodeSpace(
   1688     Heap* heap,
   1689     HeapObject* ignore,
   1690     int object_size) {
   1691   return heap->code_space()->MCAllocateRaw(object_size);
   1692 }
   1693 
   1694 
   1695 MUST_USE_RESULT inline MaybeObject* MCAllocateFromMapSpace(
   1696     Heap* heap,
   1697     HeapObject* ignore,
   1698     int object_size) {
   1699   return heap->map_space()->MCAllocateRaw(object_size);
   1700 }
   1701 
   1702 
   1703 MUST_USE_RESULT inline MaybeObject* MCAllocateFromCellSpace(
   1704     Heap* heap, HeapObject* ignore, int object_size) {
   1705   return heap->cell_space()->MCAllocateRaw(object_size);
   1706 }
   1707 
   1708 
   1709 // The forwarding address is encoded at the same offset as the current
   1710 // to-space object, but in from space.
   1711 inline void EncodeForwardingAddressInNewSpace(Heap* heap,
   1712                                               HeapObject* old_object,
   1713                                               int object_size,
   1714                                               Object* new_object,
   1715                                               int* ignored) {
   1716   int offset =
   1717       heap->new_space()->ToSpaceOffsetForAddress(old_object->address());
   1718   Memory::Address_at(heap->new_space()->FromSpaceLow() + offset) =
   1719       HeapObject::cast(new_object)->address();
   1720 }
   1721 
   1722 
   1723 // The forwarding address is encoded in the map pointer of the object as an
   1724 // offset (in terms of live bytes) from the address of the first live object
   1725 // in the page.
   1726 inline void EncodeForwardingAddressInPagedSpace(Heap* heap,
   1727                                                 HeapObject* old_object,
   1728                                                 int object_size,
   1729                                                 Object* new_object,
   1730                                                 int* offset) {
   1731   // Record the forwarding address of the first live object if necessary.
   1732   if (*offset == 0) {
   1733     Page::FromAddress(old_object->address())->mc_first_forwarded =
   1734         HeapObject::cast(new_object)->address();
   1735   }
   1736 
   1737   MapWord encoding =
   1738       MapWord::EncodeAddress(old_object->map()->address(), *offset);
   1739   old_object->set_map_word(encoding);
   1740   *offset += object_size;
   1741   ASSERT(*offset <= Page::kObjectAreaSize);
   1742 }
   1743 
   1744 
   1745 // Most non-live objects are ignored.
   1746 inline void IgnoreNonLiveObject(HeapObject* object, Isolate* isolate) {}
   1747 
   1748 
   1749 // Function template that, given a range of addresses (eg, a semispace or a
   1750 // paged space page), iterates through the objects in the range to clear
   1751 // mark bits and compute and encode forwarding addresses.  As a side effect,
   1752 // maximal free chunks are marked so that they can be skipped on subsequent
   1753 // sweeps.
   1754 //
   1755 // The template parameters are an allocation function, a forwarding address
   1756 // encoding function, and a function to process non-live objects.
   1757 template<MarkCompactCollector::AllocationFunction Alloc,
   1758          MarkCompactCollector::EncodingFunction Encode,
   1759          MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
   1760 inline void EncodeForwardingAddressesInRange(MarkCompactCollector* collector,
   1761                                              Address start,
   1762                                              Address end,
   1763                                              int* offset) {
   1764   // The start address of the current free region while sweeping the space.
   1765   // This address is set when a transition from live to non-live objects is
   1766   // encountered.  A value (an encoding of the 'next free region' pointer)
   1767   // is written to memory at this address when a transition from non-live to
   1768   // live objects is encountered.
   1769   Address free_start = NULL;
   1770 
   1771   // A flag giving the state of the previously swept object.  Initially true
   1772   // to ensure that free_start is initialized to a proper address before
   1773   // trying to write to it.
   1774   bool is_prev_alive = true;
   1775 
   1776   int object_size;  // Will be set on each iteration of the loop.
   1777   for (Address current = start; current < end; current += object_size) {
   1778     HeapObject* object = HeapObject::FromAddress(current);
   1779     if (object->IsMarked()) {
   1780       object->ClearMark();
   1781       collector->tracer()->decrement_marked_count();
   1782       object_size = object->Size();
   1783 
   1784       Object* forwarded =
   1785           Alloc(collector->heap(), object, object_size)->ToObjectUnchecked();
   1786       Encode(collector->heap(), object, object_size, forwarded, offset);
   1787 
   1788 #ifdef DEBUG
   1789       if (FLAG_gc_verbose) {
   1790         PrintF("forward %p -> %p.\n", object->address(),
   1791                HeapObject::cast(forwarded)->address());
   1792       }
   1793 #endif
   1794       if (!is_prev_alive) {  // Transition from non-live to live.
   1795         EncodeFreeRegion(free_start, static_cast<int>(current - free_start));
   1796         is_prev_alive = true;
   1797       }
   1798     } else {  // Non-live object.
   1799       object_size = object->Size();
   1800       ProcessNonLive(object, collector->heap()->isolate());
   1801       if (is_prev_alive) {  // Transition from live to non-live.
   1802         free_start = current;
   1803         is_prev_alive = false;
   1804       }
   1805       LiveObjectList::ProcessNonLive(object);
   1806     }
   1807   }
   1808 
   1809   // If we ended on a free region, mark it.
   1810   if (!is_prev_alive) {
   1811     EncodeFreeRegion(free_start, static_cast<int>(end - free_start));
   1812   }
   1813 }
   1814 
   1815 
   1816 // Functions to encode the forwarding pointers in each compactable space.
   1817 void MarkCompactCollector::EncodeForwardingAddressesInNewSpace() {
   1818   int ignored;
   1819   EncodeForwardingAddressesInRange<MCAllocateFromNewSpace,
   1820                                    EncodeForwardingAddressInNewSpace,
   1821                                    IgnoreNonLiveObject>(
   1822       this,
   1823       heap()->new_space()->bottom(),
   1824       heap()->new_space()->top(),
   1825       &ignored);
   1826 }
   1827 
   1828 
   1829 template<MarkCompactCollector::AllocationFunction Alloc,
   1830          MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
   1831 void MarkCompactCollector::EncodeForwardingAddressesInPagedSpace(
   1832     PagedSpace* space) {
   1833   PageIterator it(space, PageIterator::PAGES_IN_USE);
   1834   while (it.has_next()) {
   1835     Page* p = it.next();
   1836 
   1837     // The offset of each live object in the page from the first live object
   1838     // in the page.
   1839     int offset = 0;
   1840     EncodeForwardingAddressesInRange<Alloc,
   1841                                      EncodeForwardingAddressInPagedSpace,
   1842                                      ProcessNonLive>(
   1843         this,
   1844         p->ObjectAreaStart(),
   1845         p->AllocationTop(),
   1846         &offset);
   1847   }
   1848 }
   1849 
   1850 
   1851 // We scavange new space simultaneously with sweeping. This is done in two
   1852 // passes.
   1853 // The first pass migrates all alive objects from one semispace to another or
   1854 // promotes them to old space. Forwading address is written directly into
   1855 // first word of object without any encoding. If object is dead we are writing
   1856 // NULL as a forwarding address.
   1857 // The second pass updates pointers to new space in all spaces. It is possible
   1858 // to encounter pointers to dead objects during traversal of dirty regions we
   1859 // should clear them to avoid encountering them during next dirty regions
   1860 // iteration.
   1861 static void MigrateObject(Heap* heap,
   1862                           Address dst,
   1863                           Address src,
   1864                           int size,
   1865                           bool to_old_space) {
   1866   if (to_old_space) {
   1867     heap->CopyBlockToOldSpaceAndUpdateRegionMarks(dst, src, size);
   1868   } else {
   1869     heap->CopyBlock(dst, src, size);
   1870   }
   1871 
   1872   Memory::Address_at(src) = dst;
   1873 }
   1874 
   1875 
   1876 class StaticPointersToNewGenUpdatingVisitor : public
   1877   StaticNewSpaceVisitor<StaticPointersToNewGenUpdatingVisitor> {
   1878  public:
   1879   static inline void VisitPointer(Heap* heap, Object** p) {
   1880     if (!(*p)->IsHeapObject()) return;
   1881 
   1882     HeapObject* obj = HeapObject::cast(*p);
   1883     Address old_addr = obj->address();
   1884 
   1885     if (heap->new_space()->Contains(obj)) {
   1886       ASSERT(heap->InFromSpace(*p));
   1887       *p = HeapObject::FromAddress(Memory::Address_at(old_addr));
   1888     }
   1889   }
   1890 };
   1891 
   1892 
   1893 // Visitor for updating pointers from live objects in old spaces to new space.
   1894 // It does not expect to encounter pointers to dead objects.
   1895 class PointersToNewGenUpdatingVisitor: public ObjectVisitor {
   1896  public:
   1897   explicit PointersToNewGenUpdatingVisitor(Heap* heap) : heap_(heap) { }
   1898 
   1899   void VisitPointer(Object** p) {
   1900     StaticPointersToNewGenUpdatingVisitor::VisitPointer(heap_, p);
   1901   }
   1902 
   1903   void VisitPointers(Object** start, Object** end) {
   1904     for (Object** p = start; p < end; p++) {
   1905       StaticPointersToNewGenUpdatingVisitor::VisitPointer(heap_, p);
   1906     }
   1907   }
   1908 
   1909   void VisitCodeTarget(RelocInfo* rinfo) {
   1910     ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
   1911     Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
   1912     VisitPointer(&target);
   1913     rinfo->set_target_address(Code::cast(target)->instruction_start());
   1914   }
   1915 
   1916   void VisitDebugTarget(RelocInfo* rinfo) {
   1917     ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
   1918             rinfo->IsPatchedReturnSequence()) ||
   1919            (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
   1920             rinfo->IsPatchedDebugBreakSlotSequence()));
   1921     Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
   1922     VisitPointer(&target);
   1923     rinfo->set_call_address(Code::cast(target)->instruction_start());
   1924   }
   1925  private:
   1926   Heap* heap_;
   1927 };
   1928 
   1929 
   1930 // Visitor for updating pointers from live objects in old spaces to new space.
   1931 // It can encounter pointers to dead objects in new space when traversing map
   1932 // space (see comment for MigrateObject).
   1933 static void UpdatePointerToNewGen(HeapObject** p) {
   1934   if (!(*p)->IsHeapObject()) return;
   1935 
   1936   Address old_addr = (*p)->address();
   1937   ASSERT(HEAP->InFromSpace(*p));
   1938 
   1939   Address new_addr = Memory::Address_at(old_addr);
   1940 
   1941   if (new_addr == NULL) {
   1942     // We encountered pointer to a dead object. Clear it so we will
   1943     // not visit it again during next iteration of dirty regions.
   1944     *p = NULL;
   1945   } else {
   1946     *p = HeapObject::FromAddress(new_addr);
   1947   }
   1948 }
   1949 
   1950 
   1951 static String* UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
   1952                                                                  Object** p) {
   1953   Address old_addr = HeapObject::cast(*p)->address();
   1954   Address new_addr = Memory::Address_at(old_addr);
   1955   return String::cast(HeapObject::FromAddress(new_addr));
   1956 }
   1957 
   1958 
   1959 static bool TryPromoteObject(Heap* heap, HeapObject* object, int object_size) {
   1960   Object* result;
   1961 
   1962   if (object_size > heap->MaxObjectSizeInPagedSpace()) {
   1963     MaybeObject* maybe_result =
   1964         heap->lo_space()->AllocateRawFixedArray(object_size);
   1965     if (maybe_result->ToObject(&result)) {
   1966       HeapObject* target = HeapObject::cast(result);
   1967       MigrateObject(heap, target->address(), object->address(), object_size,
   1968                     true);
   1969       heap->mark_compact_collector()->tracer()->
   1970           increment_promoted_objects_size(object_size);
   1971       return true;
   1972     }
   1973   } else {
   1974     OldSpace* target_space = heap->TargetSpace(object);
   1975 
   1976     ASSERT(target_space == heap->old_pointer_space() ||
   1977            target_space == heap->old_data_space());
   1978     MaybeObject* maybe_result = target_space->AllocateRaw(object_size);
   1979     if (maybe_result->ToObject(&result)) {
   1980       HeapObject* target = HeapObject::cast(result);
   1981       MigrateObject(heap,
   1982                     target->address(),
   1983                     object->address(),
   1984                     object_size,
   1985                     target_space == heap->old_pointer_space());
   1986       heap->mark_compact_collector()->tracer()->
   1987           increment_promoted_objects_size(object_size);
   1988       return true;
   1989     }
   1990   }
   1991 
   1992   return false;
   1993 }
   1994 
   1995 
   1996 static void SweepNewSpace(Heap* heap, NewSpace* space) {
   1997   heap->CheckNewSpaceExpansionCriteria();
   1998 
   1999   Address from_bottom = space->bottom();
   2000   Address from_top = space->top();
   2001 
   2002   // Flip the semispaces.  After flipping, to space is empty, from space has
   2003   // live objects.
   2004   space->Flip();
   2005   space->ResetAllocationInfo();
   2006 
   2007   int size = 0;
   2008   int survivors_size = 0;
   2009 
   2010   // First pass: traverse all objects in inactive semispace, remove marks,
   2011   // migrate live objects and write forwarding addresses.
   2012   for (Address current = from_bottom; current < from_top; current += size) {
   2013     HeapObject* object = HeapObject::FromAddress(current);
   2014 
   2015     if (object->IsMarked()) {
   2016       object->ClearMark();
   2017       heap->mark_compact_collector()->tracer()->decrement_marked_count();
   2018 
   2019       size = object->Size();
   2020       survivors_size += size;
   2021 
   2022       // Aggressively promote young survivors to the old space.
   2023       if (TryPromoteObject(heap, object, size)) {
   2024         continue;
   2025       }
   2026 
   2027       // Promotion failed. Just migrate object to another semispace.
   2028       // Allocation cannot fail at this point: semispaces are of equal size.
   2029       Object* target = space->AllocateRaw(size)->ToObjectUnchecked();
   2030 
   2031       MigrateObject(heap,
   2032                     HeapObject::cast(target)->address(),
   2033                     current,
   2034                     size,
   2035                     false);
   2036     } else {
   2037       // Process the dead object before we write a NULL into its header.
   2038       LiveObjectList::ProcessNonLive(object);
   2039 
   2040       size = object->Size();
   2041       Memory::Address_at(current) = NULL;
   2042     }
   2043   }
   2044 
   2045   // Second pass: find pointers to new space and update them.
   2046   PointersToNewGenUpdatingVisitor updating_visitor(heap);
   2047 
   2048   // Update pointers in to space.
   2049   Address current = space->bottom();
   2050   while (current < space->top()) {
   2051     HeapObject* object = HeapObject::FromAddress(current);
   2052     current +=
   2053         StaticPointersToNewGenUpdatingVisitor::IterateBody(object->map(),
   2054                                                            object);
   2055   }
   2056 
   2057   // Update roots.
   2058   heap->IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE);
   2059   LiveObjectList::IterateElements(&updating_visitor);
   2060 
   2061   // Update pointers in old spaces.
   2062   heap->IterateDirtyRegions(heap->old_pointer_space(),
   2063                             &Heap::IteratePointersInDirtyRegion,
   2064                             &UpdatePointerToNewGen,
   2065                             heap->WATERMARK_SHOULD_BE_VALID);
   2066 
   2067   heap->lo_space()->IterateDirtyRegions(&UpdatePointerToNewGen);
   2068 
   2069   // Update pointers from cells.
   2070   HeapObjectIterator cell_iterator(heap->cell_space());
   2071   for (HeapObject* cell = cell_iterator.next();
   2072        cell != NULL;
   2073        cell = cell_iterator.next()) {
   2074     if (cell->IsJSGlobalPropertyCell()) {
   2075       Address value_address =
   2076           reinterpret_cast<Address>(cell) +
   2077           (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag);
   2078       updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
   2079     }
   2080   }
   2081 
   2082   // Update pointer from the global contexts list.
   2083   updating_visitor.VisitPointer(heap->global_contexts_list_address());
   2084 
   2085   // Update pointers from external string table.
   2086   heap->UpdateNewSpaceReferencesInExternalStringTable(
   2087       &UpdateNewSpaceReferenceInExternalStringTableEntry);
   2088 
   2089   // All pointers were updated. Update auxiliary allocation info.
   2090   heap->IncrementYoungSurvivorsCounter(survivors_size);
   2091   space->set_age_mark(space->top());
   2092 
   2093   // Update JSFunction pointers from the runtime profiler.
   2094   heap->isolate()->runtime_profiler()->UpdateSamplesAfterScavenge();
   2095 }
   2096 
   2097 
   2098 static void SweepSpace(Heap* heap, PagedSpace* space) {
   2099   PageIterator it(space, PageIterator::PAGES_IN_USE);
   2100 
   2101   // During sweeping of paged space we are trying to find longest sequences
   2102   // of pages without live objects and free them (instead of putting them on
   2103   // the free list).
   2104 
   2105   // Page preceding current.
   2106   Page* prev = Page::FromAddress(NULL);
   2107 
   2108   // First empty page in a sequence.
   2109   Page* first_empty_page = Page::FromAddress(NULL);
   2110 
   2111   // Page preceding first empty page.
   2112   Page* prec_first_empty_page = Page::FromAddress(NULL);
   2113 
   2114   // If last used page of space ends with a sequence of dead objects
   2115   // we can adjust allocation top instead of puting this free area into
   2116   // the free list. Thus during sweeping we keep track of such areas
   2117   // and defer their deallocation until the sweeping of the next page
   2118   // is done: if one of the next pages contains live objects we have
   2119   // to put such area into the free list.
   2120   Address last_free_start = NULL;
   2121   int last_free_size = 0;
   2122 
   2123   while (it.has_next()) {
   2124     Page* p = it.next();
   2125 
   2126     bool is_previous_alive = true;
   2127     Address free_start = NULL;
   2128     HeapObject* object;
   2129 
   2130     for (Address current = p->ObjectAreaStart();
   2131          current < p->AllocationTop();
   2132          current += object->Size()) {
   2133       object = HeapObject::FromAddress(current);
   2134       if (object->IsMarked()) {
   2135         object->ClearMark();
   2136         heap->mark_compact_collector()->tracer()->decrement_marked_count();
   2137 
   2138         if (!is_previous_alive) {  // Transition from free to live.
   2139           space->DeallocateBlock(free_start,
   2140                                  static_cast<int>(current - free_start),
   2141                                  true);
   2142           is_previous_alive = true;
   2143         }
   2144       } else {
   2145         heap->mark_compact_collector()->ReportDeleteIfNeeded(
   2146             object, heap->isolate());
   2147         if (is_previous_alive) {  // Transition from live to free.
   2148           free_start = current;
   2149           is_previous_alive = false;
   2150         }
   2151         LiveObjectList::ProcessNonLive(object);
   2152       }
   2153       // The object is now unmarked for the call to Size() at the top of the
   2154       // loop.
   2155     }
   2156 
   2157     bool page_is_empty = (p->ObjectAreaStart() == p->AllocationTop())
   2158         || (!is_previous_alive && free_start == p->ObjectAreaStart());
   2159 
   2160     if (page_is_empty) {
   2161       // This page is empty. Check whether we are in the middle of
   2162       // sequence of empty pages and start one if not.
   2163       if (!first_empty_page->is_valid()) {
   2164         first_empty_page = p;
   2165         prec_first_empty_page = prev;
   2166       }
   2167 
   2168       if (!is_previous_alive) {
   2169         // There are dead objects on this page. Update space accounting stats
   2170         // without putting anything into free list.
   2171         int size_in_bytes = static_cast<int>(p->AllocationTop() - free_start);
   2172         if (size_in_bytes > 0) {
   2173           space->DeallocateBlock(free_start, size_in_bytes, false);
   2174         }
   2175       }
   2176     } else {
   2177       // This page is not empty. Sequence of empty pages ended on the previous
   2178       // one.
   2179       if (first_empty_page->is_valid()) {
   2180         space->FreePages(prec_first_empty_page, prev);
   2181         prec_first_empty_page = first_empty_page = Page::FromAddress(NULL);
   2182       }
   2183 
   2184       // If there is a free ending area on one of the previous pages we have
   2185       // deallocate that area and put it on the free list.
   2186       if (last_free_size > 0) {
   2187         Page::FromAddress(last_free_start)->
   2188             SetAllocationWatermark(last_free_start);
   2189         space->DeallocateBlock(last_free_start, last_free_size, true);
   2190         last_free_start = NULL;
   2191         last_free_size  = 0;
   2192       }
   2193 
   2194       // If the last region of this page was not live we remember it.
   2195       if (!is_previous_alive) {
   2196         ASSERT(last_free_size == 0);
   2197         last_free_size = static_cast<int>(p->AllocationTop() - free_start);
   2198         last_free_start = free_start;
   2199       }
   2200     }
   2201 
   2202     prev = p;
   2203   }
   2204 
   2205   // We reached end of space. See if we need to adjust allocation top.
   2206   Address new_allocation_top = NULL;
   2207 
   2208   if (first_empty_page->is_valid()) {
   2209     // Last used pages in space are empty. We can move allocation top backwards
   2210     // to the beginning of first empty page.
   2211     ASSERT(prev == space->AllocationTopPage());
   2212 
   2213     new_allocation_top = first_empty_page->ObjectAreaStart();
   2214   }
   2215 
   2216   if (last_free_size > 0) {
   2217     // There was a free ending area on the previous page.
   2218     // Deallocate it without putting it into freelist and move allocation
   2219     // top to the beginning of this free area.
   2220     space->DeallocateBlock(last_free_start, last_free_size, false);
   2221     new_allocation_top = last_free_start;
   2222   }
   2223 
   2224   if (new_allocation_top != NULL) {
   2225 #ifdef DEBUG
   2226     Page* new_allocation_top_page = Page::FromAllocationTop(new_allocation_top);
   2227     if (!first_empty_page->is_valid()) {
   2228       ASSERT(new_allocation_top_page == space->AllocationTopPage());
   2229     } else if (last_free_size > 0) {
   2230       ASSERT(new_allocation_top_page == prec_first_empty_page);
   2231     } else {
   2232       ASSERT(new_allocation_top_page == first_empty_page);
   2233     }
   2234 #endif
   2235 
   2236     space->SetTop(new_allocation_top);
   2237   }
   2238 }
   2239 
   2240 
   2241 void MarkCompactCollector::EncodeForwardingAddresses() {
   2242   ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
   2243   // Objects in the active semispace of the young generation may be
   2244   // relocated to the inactive semispace (if not promoted).  Set the
   2245   // relocation info to the beginning of the inactive semispace.
   2246   heap()->new_space()->MCResetRelocationInfo();
   2247 
   2248   // Compute the forwarding pointers in each space.
   2249   EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace,
   2250                                         ReportDeleteIfNeeded>(
   2251       heap()->old_pointer_space());
   2252 
   2253   EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace,
   2254                                         IgnoreNonLiveObject>(
   2255       heap()->old_data_space());
   2256 
   2257   EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace,
   2258                                         ReportDeleteIfNeeded>(
   2259       heap()->code_space());
   2260 
   2261   EncodeForwardingAddressesInPagedSpace<MCAllocateFromCellSpace,
   2262                                         IgnoreNonLiveObject>(
   2263       heap()->cell_space());
   2264 
   2265 
   2266   // Compute new space next to last after the old and code spaces have been
   2267   // compacted.  Objects in new space can be promoted to old or code space.
   2268   EncodeForwardingAddressesInNewSpace();
   2269 
   2270   // Compute map space last because computing forwarding addresses
   2271   // overwrites non-live objects.  Objects in the other spaces rely on
   2272   // non-live map pointers to get the sizes of non-live objects.
   2273   EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace,
   2274                                         IgnoreNonLiveObject>(
   2275       heap()->map_space());
   2276 
   2277   // Write relocation info to the top page, so we can use it later.  This is
   2278   // done after promoting objects from the new space so we get the correct
   2279   // allocation top.
   2280   heap()->old_pointer_space()->MCWriteRelocationInfoToPage();
   2281   heap()->old_data_space()->MCWriteRelocationInfoToPage();
   2282   heap()->code_space()->MCWriteRelocationInfoToPage();
   2283   heap()->map_space()->MCWriteRelocationInfoToPage();
   2284   heap()->cell_space()->MCWriteRelocationInfoToPage();
   2285 }
   2286 
   2287 
   2288 class MapIterator : public HeapObjectIterator {
   2289  public:
   2290   explicit MapIterator(Heap* heap)
   2291     : HeapObjectIterator(heap->map_space(), &SizeCallback) { }
   2292 
   2293   MapIterator(Heap* heap, Address start)
   2294       : HeapObjectIterator(heap->map_space(), start, &SizeCallback) { }
   2295 
   2296  private:
   2297   static int SizeCallback(HeapObject* unused) {
   2298     USE(unused);
   2299     return Map::kSize;
   2300   }
   2301 };
   2302 
   2303 
   2304 class MapCompact {
   2305  public:
   2306   explicit MapCompact(Heap* heap, int live_maps)
   2307     : heap_(heap),
   2308       live_maps_(live_maps),
   2309       to_evacuate_start_(heap->map_space()->TopAfterCompaction(live_maps)),
   2310       vacant_map_it_(heap),
   2311       map_to_evacuate_it_(heap, to_evacuate_start_),
   2312       first_map_to_evacuate_(
   2313           reinterpret_cast<Map*>(HeapObject::FromAddress(to_evacuate_start_))) {
   2314   }
   2315 
   2316   void CompactMaps() {
   2317     // As we know the number of maps to evacuate beforehand,
   2318     // we stop then there is no more vacant maps.
   2319     for (Map* next_vacant_map = NextVacantMap();
   2320          next_vacant_map;
   2321          next_vacant_map = NextVacantMap()) {
   2322       EvacuateMap(next_vacant_map, NextMapToEvacuate());
   2323     }
   2324 
   2325 #ifdef DEBUG
   2326     CheckNoMapsToEvacuate();
   2327 #endif
   2328   }
   2329 
   2330   void UpdateMapPointersInRoots() {
   2331     MapUpdatingVisitor map_updating_visitor;
   2332     heap()->IterateRoots(&map_updating_visitor, VISIT_ONLY_STRONG);
   2333     heap()->isolate()->global_handles()->IterateWeakRoots(
   2334         &map_updating_visitor);
   2335     LiveObjectList::IterateElements(&map_updating_visitor);
   2336   }
   2337 
   2338   void UpdateMapPointersInPagedSpace(PagedSpace* space) {
   2339     ASSERT(space != heap()->map_space());
   2340 
   2341     PageIterator it(space, PageIterator::PAGES_IN_USE);
   2342     while (it.has_next()) {
   2343       Page* p = it.next();
   2344       UpdateMapPointersInRange(heap(),
   2345                                p->ObjectAreaStart(),
   2346                                p->AllocationTop());
   2347     }
   2348   }
   2349 
   2350   void UpdateMapPointersInNewSpace() {
   2351     NewSpace* space = heap()->new_space();
   2352     UpdateMapPointersInRange(heap(), space->bottom(), space->top());
   2353   }
   2354 
   2355   void UpdateMapPointersInLargeObjectSpace() {
   2356     LargeObjectIterator it(heap()->lo_space());
   2357     for (HeapObject* obj = it.next(); obj != NULL; obj = it.next())
   2358       UpdateMapPointersInObject(heap(), obj);
   2359   }
   2360 
   2361   void Finish() {
   2362     heap()->map_space()->FinishCompaction(to_evacuate_start_, live_maps_);
   2363   }
   2364 
   2365   inline Heap* heap() const { return heap_; }
   2366 
   2367  private:
   2368   Heap* heap_;
   2369   int live_maps_;
   2370   Address to_evacuate_start_;
   2371   MapIterator vacant_map_it_;
   2372   MapIterator map_to_evacuate_it_;
   2373   Map* first_map_to_evacuate_;
   2374 
   2375   // Helper class for updating map pointers in HeapObjects.
   2376   class MapUpdatingVisitor: public ObjectVisitor {
   2377   public:
   2378     MapUpdatingVisitor() {}
   2379 
   2380     void VisitPointer(Object** p) {
   2381       UpdateMapPointer(p);
   2382     }
   2383 
   2384     void VisitPointers(Object** start, Object** end) {
   2385       for (Object** p = start; p < end; p++) UpdateMapPointer(p);
   2386     }
   2387 
   2388   private:
   2389     void UpdateMapPointer(Object** p) {
   2390       if (!(*p)->IsHeapObject()) return;
   2391       HeapObject* old_map = reinterpret_cast<HeapObject*>(*p);
   2392 
   2393       // Moved maps are tagged with overflowed map word.  They are the only
   2394       // objects those map word is overflowed as marking is already complete.
   2395       MapWord map_word = old_map->map_word();
   2396       if (!map_word.IsOverflowed()) return;
   2397 
   2398       *p = GetForwardedMap(map_word);
   2399     }
   2400   };
   2401 
   2402   static Map* NextMap(MapIterator* it, HeapObject* last, bool live) {
   2403     while (true) {
   2404       HeapObject* next = it->next();
   2405       ASSERT(next != NULL);
   2406       if (next == last)
   2407         return NULL;
   2408       ASSERT(!next->IsOverflowed());
   2409       ASSERT(!next->IsMarked());
   2410       ASSERT(next->IsMap() || FreeListNode::IsFreeListNode(next));
   2411       if (next->IsMap() == live)
   2412         return reinterpret_cast<Map*>(next);
   2413     }
   2414   }
   2415 
   2416   Map* NextVacantMap() {
   2417     Map* map = NextMap(&vacant_map_it_, first_map_to_evacuate_, false);
   2418     ASSERT(map == NULL || FreeListNode::IsFreeListNode(map));
   2419     return map;
   2420   }
   2421 
   2422   Map* NextMapToEvacuate() {
   2423     Map* map = NextMap(&map_to_evacuate_it_, NULL, true);
   2424     ASSERT(map != NULL);
   2425     ASSERT(map->IsMap());
   2426     return map;
   2427   }
   2428 
   2429   static void EvacuateMap(Map* vacant_map, Map* map_to_evacuate) {
   2430     ASSERT(FreeListNode::IsFreeListNode(vacant_map));
   2431     ASSERT(map_to_evacuate->IsMap());
   2432 
   2433     ASSERT(Map::kSize % 4 == 0);
   2434 
   2435     map_to_evacuate->heap()->CopyBlockToOldSpaceAndUpdateRegionMarks(
   2436         vacant_map->address(), map_to_evacuate->address(), Map::kSize);
   2437 
   2438     ASSERT(vacant_map->IsMap());  // Due to memcpy above.
   2439 
   2440     MapWord forwarding_map_word = MapWord::FromMap(vacant_map);
   2441     forwarding_map_word.SetOverflow();
   2442     map_to_evacuate->set_map_word(forwarding_map_word);
   2443 
   2444     ASSERT(map_to_evacuate->map_word().IsOverflowed());
   2445     ASSERT(GetForwardedMap(map_to_evacuate->map_word()) == vacant_map);
   2446   }
   2447 
   2448   static Map* GetForwardedMap(MapWord map_word) {
   2449     ASSERT(map_word.IsOverflowed());
   2450     map_word.ClearOverflow();
   2451     Map* new_map = map_word.ToMap();
   2452     ASSERT_MAP_ALIGNED(new_map->address());
   2453     return new_map;
   2454   }
   2455 
   2456   static int UpdateMapPointersInObject(Heap* heap, HeapObject* obj) {
   2457     ASSERT(!obj->IsMarked());
   2458     Map* map = obj->map();
   2459     ASSERT(heap->map_space()->Contains(map));
   2460     MapWord map_word = map->map_word();
   2461     ASSERT(!map_word.IsMarked());
   2462     if (map_word.IsOverflowed()) {
   2463       Map* new_map = GetForwardedMap(map_word);
   2464       ASSERT(heap->map_space()->Contains(new_map));
   2465       obj->set_map(new_map);
   2466 
   2467 #ifdef DEBUG
   2468       if (FLAG_gc_verbose) {
   2469         PrintF("update %p : %p -> %p\n",
   2470                obj->address(),
   2471                reinterpret_cast<void*>(map),
   2472                reinterpret_cast<void*>(new_map));
   2473       }
   2474 #endif
   2475     }
   2476 
   2477     int size = obj->SizeFromMap(map);
   2478     MapUpdatingVisitor map_updating_visitor;
   2479     obj->IterateBody(map->instance_type(), size, &map_updating_visitor);
   2480     return size;
   2481   }
   2482 
   2483   static void UpdateMapPointersInRange(Heap* heap, Address start, Address end) {
   2484     HeapObject* object;
   2485     int size;
   2486     for (Address current = start; current < end; current += size) {
   2487       object = HeapObject::FromAddress(current);
   2488       size = UpdateMapPointersInObject(heap, object);
   2489       ASSERT(size > 0);
   2490     }
   2491   }
   2492 
   2493 #ifdef DEBUG
   2494   void CheckNoMapsToEvacuate() {
   2495     if (!FLAG_enable_slow_asserts)
   2496       return;
   2497 
   2498     for (HeapObject* obj = map_to_evacuate_it_.next();
   2499          obj != NULL; obj = map_to_evacuate_it_.next())
   2500       ASSERT(FreeListNode::IsFreeListNode(obj));
   2501   }
   2502 #endif
   2503 };
   2504 
   2505 
   2506 void MarkCompactCollector::SweepSpaces() {
   2507   GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP);
   2508 
   2509   ASSERT(state_ == SWEEP_SPACES);
   2510   ASSERT(!IsCompacting());
   2511   // Noncompacting collections simply sweep the spaces to clear the mark
   2512   // bits and free the nonlive blocks (for old and map spaces).  We sweep
   2513   // the map space last because freeing non-live maps overwrites them and
   2514   // the other spaces rely on possibly non-live maps to get the sizes for
   2515   // non-live objects.
   2516   SweepSpace(heap(), heap()->old_pointer_space());
   2517   SweepSpace(heap(), heap()->old_data_space());
   2518   SweepSpace(heap(), heap()->code_space());
   2519   SweepSpace(heap(), heap()->cell_space());
   2520   { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE);
   2521     SweepNewSpace(heap(), heap()->new_space());
   2522   }
   2523   SweepSpace(heap(), heap()->map_space());
   2524 
   2525   heap()->IterateDirtyRegions(heap()->map_space(),
   2526                              &heap()->IteratePointersInDirtyMapsRegion,
   2527                              &UpdatePointerToNewGen,
   2528                              heap()->WATERMARK_SHOULD_BE_VALID);
   2529 
   2530   intptr_t live_maps_size = heap()->map_space()->Size();
   2531   int live_maps = static_cast<int>(live_maps_size / Map::kSize);
   2532   ASSERT(live_map_objects_size_ == live_maps_size);
   2533 
   2534   if (heap()->map_space()->NeedsCompaction(live_maps)) {
   2535     MapCompact map_compact(heap(), live_maps);
   2536 
   2537     map_compact.CompactMaps();
   2538     map_compact.UpdateMapPointersInRoots();
   2539 
   2540     PagedSpaces spaces;
   2541     for (PagedSpace* space = spaces.next();
   2542          space != NULL; space = spaces.next()) {
   2543       if (space == heap()->map_space()) continue;
   2544       map_compact.UpdateMapPointersInPagedSpace(space);
   2545     }
   2546     map_compact.UpdateMapPointersInNewSpace();
   2547     map_compact.UpdateMapPointersInLargeObjectSpace();
   2548 
   2549     map_compact.Finish();
   2550   }
   2551 }
   2552 
   2553 
   2554 // Iterate the live objects in a range of addresses (eg, a page or a
   2555 // semispace).  The live regions of the range have been linked into a list.
   2556 // The first live region is [first_live_start, first_live_end), and the last
   2557 // address in the range is top.  The callback function is used to get the
   2558 // size of each live object.
   2559 int MarkCompactCollector::IterateLiveObjectsInRange(
   2560     Address start,
   2561     Address end,
   2562     LiveObjectCallback size_func) {
   2563   int live_objects_size = 0;
   2564   Address current = start;
   2565   while (current < end) {
   2566     uint32_t encoded_map = Memory::uint32_at(current);
   2567     if (encoded_map == kSingleFreeEncoding) {
   2568       current += kPointerSize;
   2569     } else if (encoded_map == kMultiFreeEncoding) {
   2570       current += Memory::int_at(current + kIntSize);
   2571     } else {
   2572       int size = (this->*size_func)(HeapObject::FromAddress(current));
   2573       current += size;
   2574       live_objects_size += size;
   2575     }
   2576   }
   2577   return live_objects_size;
   2578 }
   2579 
   2580 
   2581 int MarkCompactCollector::IterateLiveObjects(
   2582     NewSpace* space, LiveObjectCallback size_f) {
   2583   ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
   2584   return IterateLiveObjectsInRange(space->bottom(), space->top(), size_f);
   2585 }
   2586 
   2587 
   2588 int MarkCompactCollector::IterateLiveObjects(
   2589     PagedSpace* space, LiveObjectCallback size_f) {
   2590   ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
   2591   int total = 0;
   2592   PageIterator it(space, PageIterator::PAGES_IN_USE);
   2593   while (it.has_next()) {
   2594     Page* p = it.next();
   2595     total += IterateLiveObjectsInRange(p->ObjectAreaStart(),
   2596                                        p->AllocationTop(),
   2597                                        size_f);
   2598   }
   2599   return total;
   2600 }
   2601 
   2602 
   2603 // -------------------------------------------------------------------------
   2604 // Phase 3: Update pointers
   2605 
   2606 // Helper class for updating pointers in HeapObjects.
   2607 class UpdatingVisitor: public ObjectVisitor {
   2608  public:
   2609   explicit UpdatingVisitor(Heap* heap) : heap_(heap) {}
   2610 
   2611   void VisitPointer(Object** p) {
   2612     UpdatePointer(p);
   2613   }
   2614 
   2615   void VisitPointers(Object** start, Object** end) {
   2616     // Mark all HeapObject pointers in [start, end)
   2617     for (Object** p = start; p < end; p++) UpdatePointer(p);
   2618   }
   2619 
   2620   void VisitCodeTarget(RelocInfo* rinfo) {
   2621     ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
   2622     Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
   2623     VisitPointer(&target);
   2624     rinfo->set_target_address(
   2625         reinterpret_cast<Code*>(target)->instruction_start());
   2626   }
   2627 
   2628   void VisitDebugTarget(RelocInfo* rinfo) {
   2629     ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
   2630             rinfo->IsPatchedReturnSequence()) ||
   2631            (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
   2632             rinfo->IsPatchedDebugBreakSlotSequence()));
   2633     Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
   2634     VisitPointer(&target);
   2635     rinfo->set_call_address(
   2636         reinterpret_cast<Code*>(target)->instruction_start());
   2637   }
   2638 
   2639   inline Heap* heap() const { return heap_; }
   2640 
   2641  private:
   2642   void UpdatePointer(Object** p) {
   2643     if (!(*p)->IsHeapObject()) return;
   2644 
   2645     HeapObject* obj = HeapObject::cast(*p);
   2646     Address old_addr = obj->address();
   2647     Address new_addr;
   2648     ASSERT(!heap()->InFromSpace(obj));
   2649 
   2650     if (heap()->new_space()->Contains(obj)) {
   2651       Address forwarding_pointer_addr =
   2652           heap()->new_space()->FromSpaceLow() +
   2653           heap()->new_space()->ToSpaceOffsetForAddress(old_addr);
   2654       new_addr = Memory::Address_at(forwarding_pointer_addr);
   2655 
   2656 #ifdef DEBUG
   2657       ASSERT(heap()->old_pointer_space()->Contains(new_addr) ||
   2658              heap()->old_data_space()->Contains(new_addr) ||
   2659              heap()->new_space()->FromSpaceContains(new_addr) ||
   2660              heap()->lo_space()->Contains(HeapObject::FromAddress(new_addr)));
   2661 
   2662       if (heap()->new_space()->FromSpaceContains(new_addr)) {
   2663         ASSERT(heap()->new_space()->FromSpaceOffsetForAddress(new_addr) <=
   2664                heap()->new_space()->ToSpaceOffsetForAddress(old_addr));
   2665       }
   2666 #endif
   2667 
   2668     } else if (heap()->lo_space()->Contains(obj)) {
   2669       // Don't move objects in the large object space.
   2670       return;
   2671 
   2672     } else {
   2673 #ifdef DEBUG
   2674       PagedSpaces spaces;
   2675       PagedSpace* original_space = spaces.next();
   2676       while (original_space != NULL) {
   2677         if (original_space->Contains(obj)) break;
   2678         original_space = spaces.next();
   2679       }
   2680       ASSERT(original_space != NULL);
   2681 #endif
   2682       new_addr = MarkCompactCollector::GetForwardingAddressInOldSpace(obj);
   2683       ASSERT(original_space->Contains(new_addr));
   2684       ASSERT(original_space->MCSpaceOffsetForAddress(new_addr) <=
   2685              original_space->MCSpaceOffsetForAddress(old_addr));
   2686     }
   2687 
   2688     *p = HeapObject::FromAddress(new_addr);
   2689 
   2690 #ifdef DEBUG
   2691     if (FLAG_gc_verbose) {
   2692       PrintF("update %p : %p -> %p\n",
   2693              reinterpret_cast<Address>(p), old_addr, new_addr);
   2694     }
   2695 #endif
   2696   }
   2697 
   2698   Heap* heap_;
   2699 };
   2700 
   2701 
   2702 void MarkCompactCollector::UpdatePointers() {
   2703 #ifdef DEBUG
   2704   ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
   2705   state_ = UPDATE_POINTERS;
   2706 #endif
   2707   UpdatingVisitor updating_visitor(heap());
   2708   heap()->isolate()->runtime_profiler()->UpdateSamplesAfterCompact(
   2709       &updating_visitor);
   2710   heap()->IterateRoots(&updating_visitor, VISIT_ONLY_STRONG);
   2711   heap()->isolate()->global_handles()->IterateWeakRoots(&updating_visitor);
   2712 
   2713   // Update the pointer to the head of the weak list of global contexts.
   2714   updating_visitor.VisitPointer(&heap()->global_contexts_list_);
   2715 
   2716   LiveObjectList::IterateElements(&updating_visitor);
   2717 
   2718   int live_maps_size = IterateLiveObjects(
   2719       heap()->map_space(), &MarkCompactCollector::UpdatePointersInOldObject);
   2720   int live_pointer_olds_size = IterateLiveObjects(
   2721       heap()->old_pointer_space(),
   2722       &MarkCompactCollector::UpdatePointersInOldObject);
   2723   int live_data_olds_size = IterateLiveObjects(
   2724       heap()->old_data_space(),
   2725       &MarkCompactCollector::UpdatePointersInOldObject);
   2726   int live_codes_size = IterateLiveObjects(
   2727       heap()->code_space(), &MarkCompactCollector::UpdatePointersInOldObject);
   2728   int live_cells_size = IterateLiveObjects(
   2729       heap()->cell_space(), &MarkCompactCollector::UpdatePointersInOldObject);
   2730   int live_news_size = IterateLiveObjects(
   2731       heap()->new_space(), &MarkCompactCollector::UpdatePointersInNewObject);
   2732 
   2733   // Large objects do not move, the map word can be updated directly.
   2734   LargeObjectIterator it(heap()->lo_space());
   2735   for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
   2736     UpdatePointersInNewObject(obj);
   2737   }
   2738 
   2739   USE(live_maps_size);
   2740   USE(live_pointer_olds_size);
   2741   USE(live_data_olds_size);
   2742   USE(live_codes_size);
   2743   USE(live_cells_size);
   2744   USE(live_news_size);
   2745   ASSERT(live_maps_size == live_map_objects_size_);
   2746   ASSERT(live_data_olds_size == live_old_data_objects_size_);
   2747   ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_);
   2748   ASSERT(live_codes_size == live_code_objects_size_);
   2749   ASSERT(live_cells_size == live_cell_objects_size_);
   2750   ASSERT(live_news_size == live_young_objects_size_);
   2751 }
   2752 
   2753 
   2754 int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) {
   2755   // Keep old map pointers
   2756   Map* old_map = obj->map();
   2757   ASSERT(old_map->IsHeapObject());
   2758 
   2759   Address forwarded = GetForwardingAddressInOldSpace(old_map);
   2760 
   2761   ASSERT(heap()->map_space()->Contains(old_map));
   2762   ASSERT(heap()->map_space()->Contains(forwarded));
   2763 #ifdef DEBUG
   2764   if (FLAG_gc_verbose) {
   2765     PrintF("update %p : %p -> %p\n", obj->address(), old_map->address(),
   2766            forwarded);
   2767   }
   2768 #endif
   2769   // Update the map pointer.
   2770   obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(forwarded)));
   2771 
   2772   // We have to compute the object size relying on the old map because
   2773   // map objects are not relocated yet.
   2774   int obj_size = obj->SizeFromMap(old_map);
   2775 
   2776   // Update pointers in the object body.
   2777   UpdatingVisitor updating_visitor(heap());
   2778   obj->IterateBody(old_map->instance_type(), obj_size, &updating_visitor);
   2779   return obj_size;
   2780 }
   2781 
   2782 
   2783 int MarkCompactCollector::UpdatePointersInOldObject(HeapObject* obj) {
   2784   // Decode the map pointer.
   2785   MapWord encoding = obj->map_word();
   2786   Address map_addr = encoding.DecodeMapAddress(heap()->map_space());
   2787   ASSERT(heap()->map_space()->Contains(HeapObject::FromAddress(map_addr)));
   2788 
   2789   // At this point, the first word of map_addr is also encoded, cannot
   2790   // cast it to Map* using Map::cast.
   2791   Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr));
   2792   int obj_size = obj->SizeFromMap(map);
   2793   InstanceType type = map->instance_type();
   2794 
   2795   // Update map pointer.
   2796   Address new_map_addr = GetForwardingAddressInOldSpace(map);
   2797   int offset = encoding.DecodeOffset();
   2798   obj->set_map_word(MapWord::EncodeAddress(new_map_addr, offset));
   2799 
   2800 #ifdef DEBUG
   2801   if (FLAG_gc_verbose) {
   2802     PrintF("update %p : %p -> %p\n", obj->address(),
   2803            map_addr, new_map_addr);
   2804   }
   2805 #endif
   2806 
   2807   // Update pointers in the object body.
   2808   UpdatingVisitor updating_visitor(heap());
   2809   obj->IterateBody(type, obj_size, &updating_visitor);
   2810   return obj_size;
   2811 }
   2812 
   2813 
   2814 Address MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) {
   2815   // Object should either in old or map space.
   2816   MapWord encoding = obj->map_word();
   2817 
   2818   // Offset to the first live object's forwarding address.
   2819   int offset = encoding.DecodeOffset();
   2820   Address obj_addr = obj->address();
   2821 
   2822   // Find the first live object's forwarding address.
   2823   Page* p = Page::FromAddress(obj_addr);
   2824   Address first_forwarded = p->mc_first_forwarded;
   2825 
   2826   // Page start address of forwarded address.
   2827   Page* forwarded_page = Page::FromAddress(first_forwarded);
   2828   int forwarded_offset = forwarded_page->Offset(first_forwarded);
   2829 
   2830   // Find end of allocation in the page of first_forwarded.
   2831   int mc_top_offset = forwarded_page->AllocationWatermarkOffset();
   2832 
   2833   // Check if current object's forward pointer is in the same page
   2834   // as the first live object's forwarding pointer
   2835   if (forwarded_offset + offset < mc_top_offset) {
   2836     // In the same page.
   2837     return first_forwarded + offset;
   2838   }
   2839 
   2840   // Must be in the next page, NOTE: this may cross chunks.
   2841   Page* next_page = forwarded_page->next_page();
   2842   ASSERT(next_page->is_valid());
   2843 
   2844   offset -= (mc_top_offset - forwarded_offset);
   2845   offset += Page::kObjectStartOffset;
   2846 
   2847   ASSERT_PAGE_OFFSET(offset);
   2848   ASSERT(next_page->OffsetToAddress(offset) < next_page->AllocationTop());
   2849 
   2850   return next_page->OffsetToAddress(offset);
   2851 }
   2852 
   2853 
   2854 // -------------------------------------------------------------------------
   2855 // Phase 4: Relocate objects
   2856 
   2857 void MarkCompactCollector::RelocateObjects() {
   2858 #ifdef DEBUG
   2859   ASSERT(state_ == UPDATE_POINTERS);
   2860   state_ = RELOCATE_OBJECTS;
   2861 #endif
   2862   // Relocates objects, always relocate map objects first. Relocating
   2863   // objects in other space relies on map objects to get object size.
   2864   int live_maps_size = IterateLiveObjects(
   2865       heap()->map_space(), &MarkCompactCollector::RelocateMapObject);
   2866   int live_pointer_olds_size = IterateLiveObjects(
   2867       heap()->old_pointer_space(),
   2868       &MarkCompactCollector::RelocateOldPointerObject);
   2869   int live_data_olds_size = IterateLiveObjects(
   2870       heap()->old_data_space(), &MarkCompactCollector::RelocateOldDataObject);
   2871   int live_codes_size = IterateLiveObjects(
   2872       heap()->code_space(), &MarkCompactCollector::RelocateCodeObject);
   2873   int live_cells_size = IterateLiveObjects(
   2874       heap()->cell_space(), &MarkCompactCollector::RelocateCellObject);
   2875   int live_news_size = IterateLiveObjects(
   2876       heap()->new_space(), &MarkCompactCollector::RelocateNewObject);
   2877 
   2878   USE(live_maps_size);
   2879   USE(live_pointer_olds_size);
   2880   USE(live_data_olds_size);
   2881   USE(live_codes_size);
   2882   USE(live_cells_size);
   2883   USE(live_news_size);
   2884   ASSERT(live_maps_size == live_map_objects_size_);
   2885   ASSERT(live_data_olds_size == live_old_data_objects_size_);
   2886   ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_);
   2887   ASSERT(live_codes_size == live_code_objects_size_);
   2888   ASSERT(live_cells_size == live_cell_objects_size_);
   2889   ASSERT(live_news_size == live_young_objects_size_);
   2890 
   2891   // Flip from and to spaces
   2892   heap()->new_space()->Flip();
   2893 
   2894   heap()->new_space()->MCCommitRelocationInfo();
   2895 
   2896   // Set age_mark to bottom in to space
   2897   Address mark = heap()->new_space()->bottom();
   2898   heap()->new_space()->set_age_mark(mark);
   2899 
   2900   PagedSpaces spaces;
   2901   for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next())
   2902     space->MCCommitRelocationInfo();
   2903 
   2904   heap()->CheckNewSpaceExpansionCriteria();
   2905   heap()->IncrementYoungSurvivorsCounter(live_news_size);
   2906 }
   2907 
   2908 
   2909 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) {
   2910   // Recover map pointer.
   2911   MapWord encoding = obj->map_word();
   2912   Address map_addr = encoding.DecodeMapAddress(heap()->map_space());
   2913   ASSERT(heap()->map_space()->Contains(HeapObject::FromAddress(map_addr)));
   2914 
   2915   // Get forwarding address before resetting map pointer
   2916   Address new_addr = GetForwardingAddressInOldSpace(obj);
   2917 
   2918   // Reset map pointer.  The meta map object may not be copied yet so
   2919   // Map::cast does not yet work.
   2920   obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)));
   2921 
   2922   Address old_addr = obj->address();
   2923 
   2924   if (new_addr != old_addr) {
   2925     // Move contents.
   2926     heap()->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
   2927                                                    old_addr,
   2928                                                    Map::kSize);
   2929   }
   2930 
   2931 #ifdef DEBUG
   2932   if (FLAG_gc_verbose) {
   2933     PrintF("relocate %p -> %p\n", old_addr, new_addr);
   2934   }
   2935 #endif
   2936 
   2937   return Map::kSize;
   2938 }
   2939 
   2940 
   2941 static inline int RestoreMap(HeapObject* obj,
   2942                              PagedSpace* space,
   2943                              Address new_addr,
   2944                              Address map_addr) {
   2945   // This must be a non-map object, and the function relies on the
   2946   // assumption that the Map space is compacted before the other paged
   2947   // spaces (see RelocateObjects).
   2948 
   2949   // Reset map pointer.
   2950   obj->set_map(Map::cast(HeapObject::FromAddress(map_addr)));
   2951 
   2952   int obj_size = obj->Size();
   2953   ASSERT_OBJECT_SIZE(obj_size);
   2954 
   2955   ASSERT(space->MCSpaceOffsetForAddress(new_addr) <=
   2956          space->MCSpaceOffsetForAddress(obj->address()));
   2957 
   2958 #ifdef DEBUG
   2959   if (FLAG_gc_verbose) {
   2960     PrintF("relocate %p -> %p\n", obj->address(), new_addr);
   2961   }
   2962 #endif
   2963 
   2964   return obj_size;
   2965 }
   2966 
   2967 
   2968 int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj,
   2969                                                    PagedSpace* space) {
   2970   // Recover map pointer.
   2971   MapWord encoding = obj->map_word();
   2972   Address map_addr = encoding.DecodeMapAddress(heap()->map_space());
   2973   ASSERT(heap()->map_space()->Contains(map_addr));
   2974 
   2975   // Get forwarding address before resetting map pointer.
   2976   Address new_addr = GetForwardingAddressInOldSpace(obj);
   2977 
   2978   // Reset the map pointer.
   2979   int obj_size = RestoreMap(obj, space, new_addr, map_addr);
   2980 
   2981   Address old_addr = obj->address();
   2982 
   2983   if (new_addr != old_addr) {
   2984     // Move contents.
   2985     if (space == heap()->old_data_space()) {
   2986       heap()->MoveBlock(new_addr, old_addr, obj_size);
   2987     } else {
   2988       heap()->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
   2989                                                      old_addr,
   2990                                                      obj_size);
   2991     }
   2992   }
   2993 
   2994   ASSERT(!HeapObject::FromAddress(new_addr)->IsCode());
   2995 
   2996   HeapObject* copied_to = HeapObject::FromAddress(new_addr);
   2997   if (copied_to->IsSharedFunctionInfo()) {
   2998     PROFILE(heap()->isolate(),
   2999             SharedFunctionInfoMoveEvent(old_addr, new_addr));
   3000   }
   3001   HEAP_PROFILE(heap(), ObjectMoveEvent(old_addr, new_addr));
   3002 
   3003   return obj_size;
   3004 }
   3005 
   3006 
   3007 int MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) {
   3008   return RelocateOldNonCodeObject(obj, heap()->old_pointer_space());
   3009 }
   3010 
   3011 
   3012 int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) {
   3013   return RelocateOldNonCodeObject(obj, heap()->old_data_space());
   3014 }
   3015 
   3016 
   3017 int MarkCompactCollector::RelocateCellObject(HeapObject* obj) {
   3018   return RelocateOldNonCodeObject(obj, heap()->cell_space());
   3019 }
   3020 
   3021 
   3022 int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) {
   3023   // Recover map pointer.
   3024   MapWord encoding = obj->map_word();
   3025   Address map_addr = encoding.DecodeMapAddress(heap()->map_space());
   3026   ASSERT(heap()->map_space()->Contains(HeapObject::FromAddress(map_addr)));
   3027 
   3028   // Get forwarding address before resetting map pointer
   3029   Address new_addr = GetForwardingAddressInOldSpace(obj);
   3030 
   3031   // Reset the map pointer.
   3032   int obj_size = RestoreMap(obj, heap()->code_space(), new_addr, map_addr);
   3033 
   3034   Address old_addr = obj->address();
   3035 
   3036   if (new_addr != old_addr) {
   3037     // Move contents.
   3038     heap()->MoveBlock(new_addr, old_addr, obj_size);
   3039   }
   3040 
   3041   HeapObject* copied_to = HeapObject::FromAddress(new_addr);
   3042   if (copied_to->IsCode()) {
   3043     // May also update inline cache target.
   3044     Code::cast(copied_to)->Relocate(new_addr - old_addr);
   3045     // Notify the logger that compiled code has moved.
   3046     PROFILE(heap()->isolate(), CodeMoveEvent(old_addr, new_addr));
   3047   }
   3048   HEAP_PROFILE(heap(), ObjectMoveEvent(old_addr, new_addr));
   3049 
   3050   return obj_size;
   3051 }
   3052 
   3053 
   3054 int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
   3055   int obj_size = obj->Size();
   3056 
   3057   // Get forwarding address
   3058   Address old_addr = obj->address();
   3059   int offset = heap()->new_space()->ToSpaceOffsetForAddress(old_addr);
   3060 
   3061   Address new_addr =
   3062     Memory::Address_at(heap()->new_space()->FromSpaceLow() + offset);
   3063 
   3064 #ifdef DEBUG
   3065   if (heap()->new_space()->FromSpaceContains(new_addr)) {
   3066     ASSERT(heap()->new_space()->FromSpaceOffsetForAddress(new_addr) <=
   3067            heap()->new_space()->ToSpaceOffsetForAddress(old_addr));
   3068   } else {
   3069     ASSERT(heap()->TargetSpace(obj) == heap()->old_pointer_space() ||
   3070            heap()->TargetSpace(obj) == heap()->old_data_space());
   3071   }
   3072 #endif
   3073 
   3074   // New and old addresses cannot overlap.
   3075   if (heap()->InNewSpace(HeapObject::FromAddress(new_addr))) {
   3076     heap()->CopyBlock(new_addr, old_addr, obj_size);
   3077   } else {
   3078     heap()->CopyBlockToOldSpaceAndUpdateRegionMarks(new_addr,
   3079                                                    old_addr,
   3080                                                    obj_size);
   3081   }
   3082 
   3083 #ifdef DEBUG
   3084   if (FLAG_gc_verbose) {
   3085     PrintF("relocate %p -> %p\n", old_addr, new_addr);
   3086   }
   3087 #endif
   3088 
   3089   HeapObject* copied_to = HeapObject::FromAddress(new_addr);
   3090   if (copied_to->IsSharedFunctionInfo()) {
   3091     PROFILE(heap()->isolate(),
   3092             SharedFunctionInfoMoveEvent(old_addr, new_addr));
   3093   }
   3094   HEAP_PROFILE(heap(), ObjectMoveEvent(old_addr, new_addr));
   3095 
   3096   return obj_size;
   3097 }
   3098 
   3099 
   3100 void MarkCompactCollector::EnableCodeFlushing(bool enable) {
   3101   if (enable) {
   3102     if (code_flusher_ != NULL) return;
   3103     code_flusher_ = new CodeFlusher(heap()->isolate());
   3104   } else {
   3105     if (code_flusher_ == NULL) return;
   3106     delete code_flusher_;
   3107     code_flusher_ = NULL;
   3108   }
   3109 }
   3110 
   3111 
   3112 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj,
   3113                                                 Isolate* isolate) {
   3114 #ifdef ENABLE_GDB_JIT_INTERFACE
   3115   if (obj->IsCode()) {
   3116     GDBJITInterface::RemoveCode(reinterpret_cast<Code*>(obj));
   3117   }
   3118 #endif
   3119 #ifdef ENABLE_LOGGING_AND_PROFILING
   3120   if (obj->IsCode()) {
   3121     PROFILE(isolate, CodeDeleteEvent(obj->address()));
   3122   }
   3123 #endif
   3124 }
   3125 
   3126 
   3127 int MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) {
   3128   MapWord map_word = obj->map_word();
   3129   map_word.ClearMark();
   3130   return obj->SizeFromMap(map_word.ToMap());
   3131 }
   3132 
   3133 
   3134 void MarkCompactCollector::Initialize() {
   3135   StaticPointersToNewGenUpdatingVisitor::Initialize();
   3136   StaticMarkingVisitor::Initialize();
   3137 }
   3138 
   3139 
   3140 } }  // namespace v8::internal
   3141