Home | History | Annotate | Download | only in heap
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/heap/heap.h"
      6 
      7 #include "src/accessors.h"
      8 #include "src/api.h"
      9 #include "src/ast/context-slot-cache.h"
     10 #include "src/base/bits.h"
     11 #include "src/base/once.h"
     12 #include "src/base/utils/random-number-generator.h"
     13 #include "src/bootstrapper.h"
     14 #include "src/codegen.h"
     15 #include "src/compilation-cache.h"
     16 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
     17 #include "src/conversions.h"
     18 #include "src/debug/debug.h"
     19 #include "src/deoptimizer.h"
     20 #include "src/global-handles.h"
     21 #include "src/heap/array-buffer-tracker-inl.h"
     22 #include "src/heap/code-stats.h"
     23 #include "src/heap/gc-idle-time-handler.h"
     24 #include "src/heap/gc-tracer.h"
     25 #include "src/heap/incremental-marking.h"
     26 #include "src/heap/mark-compact-inl.h"
     27 #include "src/heap/mark-compact.h"
     28 #include "src/heap/memory-reducer.h"
     29 #include "src/heap/object-stats.h"
     30 #include "src/heap/objects-visiting-inl.h"
     31 #include "src/heap/objects-visiting.h"
     32 #include "src/heap/remembered-set.h"
     33 #include "src/heap/scavenge-job.h"
     34 #include "src/heap/scavenger-inl.h"
     35 #include "src/heap/store-buffer.h"
     36 #include "src/interpreter/interpreter.h"
     37 #include "src/regexp/jsregexp.h"
     38 #include "src/runtime-profiler.h"
     39 #include "src/snapshot/natives.h"
     40 #include "src/snapshot/serializer-common.h"
     41 #include "src/snapshot/snapshot.h"
     42 #include "src/tracing/trace-event.h"
     43 #include "src/type-feedback-vector.h"
     44 #include "src/utils.h"
     45 #include "src/v8.h"
     46 #include "src/v8threads.h"
     47 #include "src/vm-state-inl.h"
     48 
     49 namespace v8 {
     50 namespace internal {
     51 
     52 
     53 struct Heap::StrongRootsList {
     54   Object** start;
     55   Object** end;
     56   StrongRootsList* next;
     57 };
     58 
     59 class IdleScavengeObserver : public AllocationObserver {
     60  public:
     61   IdleScavengeObserver(Heap& heap, intptr_t step_size)
     62       : AllocationObserver(step_size), heap_(heap) {}
     63 
     64   void Step(int bytes_allocated, Address, size_t) override {
     65     heap_.ScheduleIdleScavengeIfNeeded(bytes_allocated);
     66   }
     67 
     68  private:
     69   Heap& heap_;
     70 };
     71 
     72 Heap::Heap()
     73     : external_memory_(0),
     74       external_memory_limit_(kExternalAllocationSoftLimit),
     75       external_memory_at_last_mark_compact_(0),
     76       isolate_(nullptr),
     77       code_range_size_(0),
     78       // semispace_size_ should be a power of 2 and old_generation_size_ should
     79       // be a multiple of Page::kPageSize.
     80       max_semi_space_size_(8 * (kPointerSize / 4) * MB),
     81       initial_semispace_size_(MB),
     82       max_old_generation_size_(700ul * (kPointerSize / 4) * MB),
     83       initial_old_generation_size_(max_old_generation_size_ /
     84                                    kInitalOldGenerationLimitFactor),
     85       old_generation_size_configured_(false),
     86       max_executable_size_(256ul * (kPointerSize / 4) * MB),
     87       // Variables set based on semispace_size_ and old_generation_size_ in
     88       // ConfigureHeap.
     89       // Will be 4 * reserved_semispace_size_ to ensure that young
     90       // generation can be aligned to its size.
     91       maximum_committed_(0),
     92       survived_since_last_expansion_(0),
     93       survived_last_scavenge_(0),
     94       always_allocate_scope_count_(0),
     95       memory_pressure_level_(MemoryPressureLevel::kNone),
     96       contexts_disposed_(0),
     97       number_of_disposed_maps_(0),
     98       global_ic_age_(0),
     99       new_space_(nullptr),
    100       old_space_(NULL),
    101       code_space_(NULL),
    102       map_space_(NULL),
    103       lo_space_(NULL),
    104       gc_state_(NOT_IN_GC),
    105       gc_post_processing_depth_(0),
    106       allocations_count_(0),
    107       raw_allocations_hash_(0),
    108       ms_count_(0),
    109       gc_count_(0),
    110       remembered_unmapped_pages_index_(0),
    111 #ifdef DEBUG
    112       allocation_timeout_(0),
    113 #endif  // DEBUG
    114       old_generation_allocation_limit_(initial_old_generation_size_),
    115       inline_allocation_disabled_(false),
    116       total_regexp_code_generated_(0),
    117       tracer_(nullptr),
    118       promoted_objects_size_(0),
    119       promotion_ratio_(0),
    120       semi_space_copied_object_size_(0),
    121       previous_semi_space_copied_object_size_(0),
    122       semi_space_copied_rate_(0),
    123       nodes_died_in_new_space_(0),
    124       nodes_copied_in_new_space_(0),
    125       nodes_promoted_(0),
    126       maximum_size_scavenges_(0),
    127       last_idle_notification_time_(0.0),
    128       last_gc_time_(0.0),
    129       scavenge_collector_(nullptr),
    130       mark_compact_collector_(nullptr),
    131       memory_allocator_(nullptr),
    132       store_buffer_(nullptr),
    133       incremental_marking_(nullptr),
    134       gc_idle_time_handler_(nullptr),
    135       memory_reducer_(nullptr),
    136       live_object_stats_(nullptr),
    137       dead_object_stats_(nullptr),
    138       scavenge_job_(nullptr),
    139       idle_scavenge_observer_(nullptr),
    140       full_codegen_bytes_generated_(0),
    141       crankshaft_codegen_bytes_generated_(0),
    142       new_space_allocation_counter_(0),
    143       old_generation_allocation_counter_at_last_gc_(0),
    144       old_generation_size_at_last_gc_(0),
    145       gcs_since_last_deopt_(0),
    146       global_pretenuring_feedback_(nullptr),
    147       ring_buffer_full_(false),
    148       ring_buffer_end_(0),
    149       promotion_queue_(this),
    150       configured_(false),
    151       current_gc_flags_(Heap::kNoGCFlags),
    152       current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags),
    153       external_string_table_(this),
    154       gc_callbacks_depth_(0),
    155       deserialization_complete_(false),
    156       strong_roots_list_(NULL),
    157       heap_iterator_depth_(0),
    158       embedder_heap_tracer_(nullptr),
    159       force_oom_(false),
    160       delay_sweeper_tasks_for_testing_(false) {
    161 // Allow build-time customization of the max semispace size. Building
    162 // V8 with snapshots and a non-default max semispace size is much
    163 // easier if you can define it as part of the build environment.
    164 #if defined(V8_MAX_SEMISPACE_SIZE)
    165   max_semi_space_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE;
    166 #endif
    167 
    168   // Ensure old_generation_size_ is a multiple of kPageSize.
    169   DCHECK((max_old_generation_size_ & (Page::kPageSize - 1)) == 0);
    170 
    171   memset(roots_, 0, sizeof(roots_[0]) * kRootListLength);
    172   set_native_contexts_list(NULL);
    173   set_allocation_sites_list(Smi::kZero);
    174   set_encountered_weak_collections(Smi::kZero);
    175   set_encountered_weak_cells(Smi::kZero);
    176   set_encountered_transition_arrays(Smi::kZero);
    177   // Put a dummy entry in the remembered pages so we can find the list the
    178   // minidump even if there are no real unmapped pages.
    179   RememberUnmappedPage(NULL, false);
    180 }
    181 
    182 size_t Heap::Capacity() {
    183   if (!HasBeenSetUp()) return 0;
    184 
    185   return new_space_->Capacity() + OldGenerationCapacity();
    186 }
    187 
    188 size_t Heap::OldGenerationCapacity() {
    189   if (!HasBeenSetUp()) return 0;
    190 
    191   return old_space_->Capacity() + code_space_->Capacity() +
    192          map_space_->Capacity() + lo_space_->SizeOfObjects();
    193 }
    194 
    195 size_t Heap::CommittedOldGenerationMemory() {
    196   if (!HasBeenSetUp()) return 0;
    197 
    198   return old_space_->CommittedMemory() + code_space_->CommittedMemory() +
    199          map_space_->CommittedMemory() + lo_space_->Size();
    200 }
    201 
    202 size_t Heap::CommittedMemory() {
    203   if (!HasBeenSetUp()) return 0;
    204 
    205   return new_space_->CommittedMemory() + CommittedOldGenerationMemory();
    206 }
    207 
    208 
    209 size_t Heap::CommittedPhysicalMemory() {
    210   if (!HasBeenSetUp()) return 0;
    211 
    212   return new_space_->CommittedPhysicalMemory() +
    213          old_space_->CommittedPhysicalMemory() +
    214          code_space_->CommittedPhysicalMemory() +
    215          map_space_->CommittedPhysicalMemory() +
    216          lo_space_->CommittedPhysicalMemory();
    217 }
    218 
    219 size_t Heap::CommittedMemoryExecutable() {
    220   if (!HasBeenSetUp()) return 0;
    221 
    222   return static_cast<size_t>(memory_allocator()->SizeExecutable());
    223 }
    224 
    225 
    226 void Heap::UpdateMaximumCommitted() {
    227   if (!HasBeenSetUp()) return;
    228 
    229   const size_t current_committed_memory = CommittedMemory();
    230   if (current_committed_memory > maximum_committed_) {
    231     maximum_committed_ = current_committed_memory;
    232   }
    233 }
    234 
    235 size_t Heap::Available() {
    236   if (!HasBeenSetUp()) return 0;
    237 
    238   size_t total = 0;
    239   AllSpaces spaces(this);
    240   for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
    241     total += space->Available();
    242   }
    243   return total;
    244 }
    245 
    246 
    247 bool Heap::HasBeenSetUp() {
    248   return old_space_ != NULL && code_space_ != NULL && map_space_ != NULL &&
    249          lo_space_ != NULL;
    250 }
    251 
    252 
    253 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space,
    254                                               const char** reason) {
    255   // Is global GC requested?
    256   if (space != NEW_SPACE) {
    257     isolate_->counters()->gc_compactor_caused_by_request()->Increment();
    258     *reason = "GC in old space requested";
    259     return MARK_COMPACTOR;
    260   }
    261 
    262   if (FLAG_gc_global || (FLAG_stress_compaction && (gc_count_ & 1) != 0)) {
    263     *reason = "GC in old space forced by flags";
    264     return MARK_COMPACTOR;
    265   }
    266 
    267   if (incremental_marking()->NeedsFinalization() &&
    268       AllocationLimitOvershotByLargeMargin()) {
    269     *reason = "Incremental marking needs finalization";
    270     return MARK_COMPACTOR;
    271   }
    272 
    273   // Is there enough space left in OLD to guarantee that a scavenge can
    274   // succeed?
    275   //
    276   // Note that MemoryAllocator->MaxAvailable() undercounts the memory available
    277   // for object promotion. It counts only the bytes that the memory
    278   // allocator has not yet allocated from the OS and assigned to any space,
    279   // and does not count available bytes already in the old space or code
    280   // space.  Undercounting is safe---we may get an unrequested full GC when
    281   // a scavenge would have succeeded.
    282   if (memory_allocator()->MaxAvailable() <= new_space_->Size()) {
    283     isolate_->counters()
    284         ->gc_compactor_caused_by_oldspace_exhaustion()
    285         ->Increment();
    286     *reason = "scavenge might not succeed";
    287     return MARK_COMPACTOR;
    288   }
    289 
    290   // Default
    291   *reason = NULL;
    292   return YoungGenerationCollector();
    293 }
    294 
    295 
    296 // TODO(1238405): Combine the infrastructure for --heap-stats and
    297 // --log-gc to avoid the complicated preprocessor and flag testing.
    298 void Heap::ReportStatisticsBeforeGC() {
    299 // Heap::ReportHeapStatistics will also log NewSpace statistics when
    300 // compiled --log-gc is set.  The following logic is used to avoid
    301 // double logging.
    302 #ifdef DEBUG
    303   if (FLAG_heap_stats || FLAG_log_gc) new_space_->CollectStatistics();
    304   if (FLAG_heap_stats) {
    305     ReportHeapStatistics("Before GC");
    306   } else if (FLAG_log_gc) {
    307     new_space_->ReportStatistics();
    308   }
    309   if (FLAG_heap_stats || FLAG_log_gc) new_space_->ClearHistograms();
    310 #else
    311   if (FLAG_log_gc) {
    312     new_space_->CollectStatistics();
    313     new_space_->ReportStatistics();
    314     new_space_->ClearHistograms();
    315   }
    316 #endif  // DEBUG
    317 }
    318 
    319 
    320 void Heap::PrintShortHeapStatistics() {
    321   if (!FLAG_trace_gc_verbose) return;
    322   PrintIsolate(isolate_, "Memory allocator,   used: %6" PRIuS
    323                          " KB,"
    324                          " available: %6" PRIuS " KB\n",
    325                memory_allocator()->Size() / KB,
    326                memory_allocator()->Available() / KB);
    327   PrintIsolate(isolate_, "New space,          used: %6" PRIuS
    328                          " KB"
    329                          ", available: %6" PRIuS
    330                          " KB"
    331                          ", committed: %6" PRIuS " KB\n",
    332                new_space_->Size() / KB, new_space_->Available() / KB,
    333                new_space_->CommittedMemory() / KB);
    334   PrintIsolate(isolate_, "Old space,          used: %6" PRIuS
    335                          " KB"
    336                          ", available: %6" PRIuS
    337                          " KB"
    338                          ", committed: %6" PRIuS " KB\n",
    339                old_space_->SizeOfObjects() / KB, old_space_->Available() / KB,
    340                old_space_->CommittedMemory() / KB);
    341   PrintIsolate(isolate_, "Code space,         used: %6" PRIuS
    342                          " KB"
    343                          ", available: %6" PRIuS
    344                          " KB"
    345                          ", committed: %6" PRIuS "KB\n",
    346                code_space_->SizeOfObjects() / KB, code_space_->Available() / KB,
    347                code_space_->CommittedMemory() / KB);
    348   PrintIsolate(isolate_, "Map space,          used: %6" PRIuS
    349                          " KB"
    350                          ", available: %6" PRIuS
    351                          " KB"
    352                          ", committed: %6" PRIuS " KB\n",
    353                map_space_->SizeOfObjects() / KB, map_space_->Available() / KB,
    354                map_space_->CommittedMemory() / KB);
    355   PrintIsolate(isolate_, "Large object space, used: %6" PRIuS
    356                          " KB"
    357                          ", available: %6" PRIuS
    358                          " KB"
    359                          ", committed: %6" PRIuS " KB\n",
    360                lo_space_->SizeOfObjects() / KB, lo_space_->Available() / KB,
    361                lo_space_->CommittedMemory() / KB);
    362   PrintIsolate(isolate_, "All spaces,         used: %6" PRIuS
    363                          " KB"
    364                          ", available: %6" PRIuS
    365                          " KB"
    366                          ", committed: %6" PRIuS "KB\n",
    367                this->SizeOfObjects() / KB, this->Available() / KB,
    368                this->CommittedMemory() / KB);
    369   PrintIsolate(isolate_, "External memory reported: %6" PRId64 " KB\n",
    370                external_memory_ / KB);
    371   PrintIsolate(isolate_, "Total time spent in GC  : %.1f ms\n",
    372                total_gc_time_ms_);
    373 }
    374 
    375 // TODO(1238405): Combine the infrastructure for --heap-stats and
    376 // --log-gc to avoid the complicated preprocessor and flag testing.
    377 void Heap::ReportStatisticsAfterGC() {
    378 // Similar to the before GC, we use some complicated logic to ensure that
    379 // NewSpace statistics are logged exactly once when --log-gc is turned on.
    380 #if defined(DEBUG)
    381   if (FLAG_heap_stats) {
    382     new_space_->CollectStatistics();
    383     ReportHeapStatistics("After GC");
    384   } else if (FLAG_log_gc) {
    385     new_space_->ReportStatistics();
    386   }
    387 #else
    388   if (FLAG_log_gc) new_space_->ReportStatistics();
    389 #endif  // DEBUG
    390   for (int i = 0; i < static_cast<int>(v8::Isolate::kUseCounterFeatureCount);
    391        ++i) {
    392     int count = deferred_counters_[i];
    393     deferred_counters_[i] = 0;
    394     while (count > 0) {
    395       count--;
    396       isolate()->CountUsage(static_cast<v8::Isolate::UseCounterFeature>(i));
    397     }
    398   }
    399 }
    400 
    401 
    402 void Heap::IncrementDeferredCount(v8::Isolate::UseCounterFeature feature) {
    403   deferred_counters_[feature]++;
    404 }
    405 
    406 bool Heap::UncommitFromSpace() { return new_space_->UncommitFromSpace(); }
    407 
    408 void Heap::GarbageCollectionPrologue() {
    409   {
    410     AllowHeapAllocation for_the_first_part_of_prologue;
    411     gc_count_++;
    412 
    413 #ifdef VERIFY_HEAP
    414     if (FLAG_verify_heap) {
    415       Verify();
    416     }
    417 #endif
    418   }
    419 
    420   // Reset GC statistics.
    421   promoted_objects_size_ = 0;
    422   previous_semi_space_copied_object_size_ = semi_space_copied_object_size_;
    423   semi_space_copied_object_size_ = 0;
    424   nodes_died_in_new_space_ = 0;
    425   nodes_copied_in_new_space_ = 0;
    426   nodes_promoted_ = 0;
    427 
    428   UpdateMaximumCommitted();
    429 
    430 #ifdef DEBUG
    431   DCHECK(!AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC);
    432 
    433   if (FLAG_gc_verbose) Print();
    434 
    435   ReportStatisticsBeforeGC();
    436 #endif  // DEBUG
    437 
    438   if (new_space_->IsAtMaximumCapacity()) {
    439     maximum_size_scavenges_++;
    440   } else {
    441     maximum_size_scavenges_ = 0;
    442   }
    443   CheckNewSpaceExpansionCriteria();
    444   UpdateNewSpaceAllocationCounter();
    445   store_buffer()->MoveAllEntriesToRememberedSet();
    446 }
    447 
    448 size_t Heap::SizeOfObjects() {
    449   size_t total = 0;
    450   AllSpaces spaces(this);
    451   for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
    452     total += space->SizeOfObjects();
    453   }
    454   return total;
    455 }
    456 
    457 
    458 const char* Heap::GetSpaceName(int idx) {
    459   switch (idx) {
    460     case NEW_SPACE:
    461       return "new_space";
    462     case OLD_SPACE:
    463       return "old_space";
    464     case MAP_SPACE:
    465       return "map_space";
    466     case CODE_SPACE:
    467       return "code_space";
    468     case LO_SPACE:
    469       return "large_object_space";
    470     default:
    471       UNREACHABLE();
    472   }
    473   return nullptr;
    474 }
    475 
    476 
    477 void Heap::RepairFreeListsAfterDeserialization() {
    478   PagedSpaces spaces(this);
    479   for (PagedSpace* space = spaces.next(); space != NULL;
    480        space = spaces.next()) {
    481     space->RepairFreeListsAfterDeserialization();
    482   }
    483 }
    484 
    485 void Heap::MergeAllocationSitePretenuringFeedback(
    486     const base::HashMap& local_pretenuring_feedback) {
    487   AllocationSite* site = nullptr;
    488   for (base::HashMap::Entry* local_entry = local_pretenuring_feedback.Start();
    489        local_entry != nullptr;
    490        local_entry = local_pretenuring_feedback.Next(local_entry)) {
    491     site = reinterpret_cast<AllocationSite*>(local_entry->key);
    492     MapWord map_word = site->map_word();
    493     if (map_word.IsForwardingAddress()) {
    494       site = AllocationSite::cast(map_word.ToForwardingAddress());
    495     }
    496 
    497     // We have not validated the allocation site yet, since we have not
    498     // dereferenced the site during collecting information.
    499     // This is an inlined check of AllocationMemento::IsValid.
    500     if (!site->IsAllocationSite() || site->IsZombie()) continue;
    501 
    502     int value =
    503         static_cast<int>(reinterpret_cast<intptr_t>(local_entry->value));
    504     DCHECK_GT(value, 0);
    505 
    506     if (site->IncrementMementoFoundCount(value)) {
    507       global_pretenuring_feedback_->LookupOrInsert(site,
    508                                                    ObjectHash(site->address()));
    509     }
    510   }
    511 }
    512 
    513 
    514 class Heap::PretenuringScope {
    515  public:
    516   explicit PretenuringScope(Heap* heap) : heap_(heap) {
    517     heap_->global_pretenuring_feedback_ =
    518         new base::HashMap(kInitialFeedbackCapacity);
    519   }
    520 
    521   ~PretenuringScope() {
    522     delete heap_->global_pretenuring_feedback_;
    523     heap_->global_pretenuring_feedback_ = nullptr;
    524   }
    525 
    526  private:
    527   Heap* heap_;
    528 };
    529 
    530 
    531 void Heap::ProcessPretenuringFeedback() {
    532   bool trigger_deoptimization = false;
    533   if (FLAG_allocation_site_pretenuring) {
    534     int tenure_decisions = 0;
    535     int dont_tenure_decisions = 0;
    536     int allocation_mementos_found = 0;
    537     int allocation_sites = 0;
    538     int active_allocation_sites = 0;
    539 
    540     AllocationSite* site = nullptr;
    541 
    542     // Step 1: Digest feedback for recorded allocation sites.
    543     bool maximum_size_scavenge = MaximumSizeScavenge();
    544     for (base::HashMap::Entry* e = global_pretenuring_feedback_->Start();
    545          e != nullptr; e = global_pretenuring_feedback_->Next(e)) {
    546       allocation_sites++;
    547       site = reinterpret_cast<AllocationSite*>(e->key);
    548       int found_count = site->memento_found_count();
    549       // An entry in the storage does not imply that the count is > 0 because
    550       // allocation sites might have been reset due to too many objects dying
    551       // in old space.
    552       if (found_count > 0) {
    553         DCHECK(site->IsAllocationSite());
    554         active_allocation_sites++;
    555         allocation_mementos_found += found_count;
    556         if (site->DigestPretenuringFeedback(maximum_size_scavenge)) {
    557           trigger_deoptimization = true;
    558         }
    559         if (site->GetPretenureMode() == TENURED) {
    560           tenure_decisions++;
    561         } else {
    562           dont_tenure_decisions++;
    563         }
    564       }
    565     }
    566 
    567     // Step 2: Deopt maybe tenured allocation sites if necessary.
    568     bool deopt_maybe_tenured = DeoptMaybeTenuredAllocationSites();
    569     if (deopt_maybe_tenured) {
    570       Object* list_element = allocation_sites_list();
    571       while (list_element->IsAllocationSite()) {
    572         site = AllocationSite::cast(list_element);
    573         DCHECK(site->IsAllocationSite());
    574         allocation_sites++;
    575         if (site->IsMaybeTenure()) {
    576           site->set_deopt_dependent_code(true);
    577           trigger_deoptimization = true;
    578         }
    579         list_element = site->weak_next();
    580       }
    581     }
    582 
    583     if (trigger_deoptimization) {
    584       isolate_->stack_guard()->RequestDeoptMarkedAllocationSites();
    585     }
    586 
    587     if (FLAG_trace_pretenuring_statistics &&
    588         (allocation_mementos_found > 0 || tenure_decisions > 0 ||
    589          dont_tenure_decisions > 0)) {
    590       PrintIsolate(isolate(),
    591                    "pretenuring: deopt_maybe_tenured=%d visited_sites=%d "
    592                    "active_sites=%d "
    593                    "mementos=%d tenured=%d not_tenured=%d\n",
    594                    deopt_maybe_tenured ? 1 : 0, allocation_sites,
    595                    active_allocation_sites, allocation_mementos_found,
    596                    tenure_decisions, dont_tenure_decisions);
    597     }
    598   }
    599 }
    600 
    601 
    602 void Heap::DeoptMarkedAllocationSites() {
    603   // TODO(hpayer): If iterating over the allocation sites list becomes a
    604   // performance issue, use a cache data structure in heap instead.
    605   Object* list_element = allocation_sites_list();
    606   while (list_element->IsAllocationSite()) {
    607     AllocationSite* site = AllocationSite::cast(list_element);
    608     if (site->deopt_dependent_code()) {
    609       site->dependent_code()->MarkCodeForDeoptimization(
    610           isolate_, DependentCode::kAllocationSiteTenuringChangedGroup);
    611       site->set_deopt_dependent_code(false);
    612     }
    613     list_element = site->weak_next();
    614   }
    615   Deoptimizer::DeoptimizeMarkedCode(isolate_);
    616 }
    617 
    618 
    619 void Heap::GarbageCollectionEpilogue() {
    620   // In release mode, we only zap the from space under heap verification.
    621   if (Heap::ShouldZapGarbage()) {
    622     ZapFromSpace();
    623   }
    624 
    625 #ifdef VERIFY_HEAP
    626   if (FLAG_verify_heap) {
    627     Verify();
    628   }
    629 #endif
    630 
    631   AllowHeapAllocation for_the_rest_of_the_epilogue;
    632 
    633 #ifdef DEBUG
    634   if (FLAG_print_global_handles) isolate_->global_handles()->Print();
    635   if (FLAG_print_handles) PrintHandles();
    636   if (FLAG_gc_verbose) Print();
    637   if (FLAG_code_stats) ReportCodeStatistics("After GC");
    638   if (FLAG_check_handle_count) CheckHandleCount();
    639 #endif
    640   if (FLAG_deopt_every_n_garbage_collections > 0) {
    641     // TODO(jkummerow/ulan/jarin): This is not safe! We can't assume that
    642     // the topmost optimized frame can be deoptimized safely, because it
    643     // might not have a lazy bailout point right after its current PC.
    644     if (++gcs_since_last_deopt_ == FLAG_deopt_every_n_garbage_collections) {
    645       Deoptimizer::DeoptimizeAll(isolate());
    646       gcs_since_last_deopt_ = 0;
    647     }
    648   }
    649 
    650   UpdateMaximumCommitted();
    651 
    652   isolate_->counters()->alive_after_last_gc()->Set(
    653       static_cast<int>(SizeOfObjects()));
    654 
    655   isolate_->counters()->string_table_capacity()->Set(
    656       string_table()->Capacity());
    657   isolate_->counters()->number_of_symbols()->Set(
    658       string_table()->NumberOfElements());
    659 
    660   if (CommittedMemory() > 0) {
    661     isolate_->counters()->external_fragmentation_total()->AddSample(
    662         static_cast<int>(100 - (SizeOfObjects() * 100.0) / CommittedMemory()));
    663 
    664     isolate_->counters()->heap_fraction_new_space()->AddSample(static_cast<int>(
    665         (new_space()->CommittedMemory() * 100.0) / CommittedMemory()));
    666     isolate_->counters()->heap_fraction_old_space()->AddSample(static_cast<int>(
    667         (old_space()->CommittedMemory() * 100.0) / CommittedMemory()));
    668     isolate_->counters()->heap_fraction_code_space()->AddSample(
    669         static_cast<int>((code_space()->CommittedMemory() * 100.0) /
    670                          CommittedMemory()));
    671     isolate_->counters()->heap_fraction_map_space()->AddSample(static_cast<int>(
    672         (map_space()->CommittedMemory() * 100.0) / CommittedMemory()));
    673     isolate_->counters()->heap_fraction_lo_space()->AddSample(static_cast<int>(
    674         (lo_space()->CommittedMemory() * 100.0) / CommittedMemory()));
    675 
    676     isolate_->counters()->heap_sample_total_committed()->AddSample(
    677         static_cast<int>(CommittedMemory() / KB));
    678     isolate_->counters()->heap_sample_total_used()->AddSample(
    679         static_cast<int>(SizeOfObjects() / KB));
    680     isolate_->counters()->heap_sample_map_space_committed()->AddSample(
    681         static_cast<int>(map_space()->CommittedMemory() / KB));
    682     isolate_->counters()->heap_sample_code_space_committed()->AddSample(
    683         static_cast<int>(code_space()->CommittedMemory() / KB));
    684 
    685     isolate_->counters()->heap_sample_maximum_committed()->AddSample(
    686         static_cast<int>(MaximumCommittedMemory() / KB));
    687   }
    688 
    689 #define UPDATE_COUNTERS_FOR_SPACE(space)                \
    690   isolate_->counters()->space##_bytes_available()->Set( \
    691       static_cast<int>(space()->Available()));          \
    692   isolate_->counters()->space##_bytes_committed()->Set( \
    693       static_cast<int>(space()->CommittedMemory()));    \
    694   isolate_->counters()->space##_bytes_used()->Set(      \
    695       static_cast<int>(space()->SizeOfObjects()));
    696 #define UPDATE_FRAGMENTATION_FOR_SPACE(space)                          \
    697   if (space()->CommittedMemory() > 0) {                                \
    698     isolate_->counters()->external_fragmentation_##space()->AddSample( \
    699         static_cast<int>(100 -                                         \
    700                          (space()->SizeOfObjects() * 100.0) /          \
    701                              space()->CommittedMemory()));             \
    702   }
    703 #define UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(space) \
    704   UPDATE_COUNTERS_FOR_SPACE(space)                         \
    705   UPDATE_FRAGMENTATION_FOR_SPACE(space)
    706 
    707   UPDATE_COUNTERS_FOR_SPACE(new_space)
    708   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(old_space)
    709   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(code_space)
    710   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(map_space)
    711   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(lo_space)
    712 #undef UPDATE_COUNTERS_FOR_SPACE
    713 #undef UPDATE_FRAGMENTATION_FOR_SPACE
    714 #undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE
    715 
    716 #ifdef DEBUG
    717   ReportStatisticsAfterGC();
    718 #endif  // DEBUG
    719 
    720   // Remember the last top pointer so that we can later find out
    721   // whether we allocated in new space since the last GC.
    722   new_space_top_after_last_gc_ = new_space()->top();
    723   last_gc_time_ = MonotonicallyIncreasingTimeInMs();
    724 
    725   ReduceNewSpaceSize();
    726 }
    727 
    728 
    729 void Heap::PreprocessStackTraces() {
    730   WeakFixedArray::Iterator iterator(weak_stack_trace_list());
    731   FixedArray* elements;
    732   while ((elements = iterator.Next<FixedArray>())) {
    733     for (int j = 1; j < elements->length(); j += 4) {
    734       Object* maybe_code = elements->get(j + 2);
    735       // If GC happens while adding a stack trace to the weak fixed array,
    736       // which has been copied into a larger backing store, we may run into
    737       // a stack trace that has already been preprocessed. Guard against this.
    738       if (!maybe_code->IsAbstractCode()) break;
    739       AbstractCode* abstract_code = AbstractCode::cast(maybe_code);
    740       int offset = Smi::cast(elements->get(j + 3))->value();
    741       int pos = abstract_code->SourcePosition(offset);
    742       elements->set(j + 2, Smi::FromInt(pos));
    743     }
    744   }
    745   // We must not compact the weak fixed list here, as we may be in the middle
    746   // of writing to it, when the GC triggered. Instead, we reset the root value.
    747   set_weak_stack_trace_list(Smi::kZero);
    748 }
    749 
    750 
    751 class GCCallbacksScope {
    752  public:
    753   explicit GCCallbacksScope(Heap* heap) : heap_(heap) {
    754     heap_->gc_callbacks_depth_++;
    755   }
    756   ~GCCallbacksScope() { heap_->gc_callbacks_depth_--; }
    757 
    758   bool CheckReenter() { return heap_->gc_callbacks_depth_ == 1; }
    759 
    760  private:
    761   Heap* heap_;
    762 };
    763 
    764 
    765 void Heap::HandleGCRequest() {
    766   if (HighMemoryPressure()) {
    767     incremental_marking()->reset_request_type();
    768     CheckMemoryPressure();
    769   } else if (incremental_marking()->request_type() ==
    770              IncrementalMarking::COMPLETE_MARKING) {
    771     incremental_marking()->reset_request_type();
    772     CollectAllGarbage(current_gc_flags_,
    773                       GarbageCollectionReason::kFinalizeMarkingViaStackGuard,
    774                       current_gc_callback_flags_);
    775   } else if (incremental_marking()->request_type() ==
    776                  IncrementalMarking::FINALIZATION &&
    777              incremental_marking()->IsMarking() &&
    778              !incremental_marking()->finalize_marking_completed()) {
    779     incremental_marking()->reset_request_type();
    780     FinalizeIncrementalMarking(
    781         GarbageCollectionReason::kFinalizeMarkingViaStackGuard);
    782   }
    783 }
    784 
    785 
    786 void Heap::ScheduleIdleScavengeIfNeeded(int bytes_allocated) {
    787   scavenge_job_->ScheduleIdleTaskIfNeeded(this, bytes_allocated);
    788 }
    789 
    790 void Heap::FinalizeIncrementalMarking(GarbageCollectionReason gc_reason) {
    791   if (FLAG_trace_incremental_marking) {
    792     isolate()->PrintWithTimestamp(
    793         "[IncrementalMarking] (%s).\n",
    794         Heap::GarbageCollectionReasonToString(gc_reason));
    795   }
    796 
    797   HistogramTimerScope incremental_marking_scope(
    798       isolate()->counters()->gc_incremental_marking_finalize());
    799   TRACE_EVENT0("v8", "V8.GCIncrementalMarkingFinalize");
    800   TRACE_GC(tracer(), GCTracer::Scope::MC_INCREMENTAL_FINALIZE);
    801 
    802   {
    803     GCCallbacksScope scope(this);
    804     if (scope.CheckReenter()) {
    805       AllowHeapAllocation allow_allocation;
    806       TRACE_GC(tracer(), GCTracer::Scope::MC_INCREMENTAL_EXTERNAL_PROLOGUE);
    807       VMState<EXTERNAL> state(isolate_);
    808       HandleScope handle_scope(isolate_);
    809       CallGCPrologueCallbacks(kGCTypeIncrementalMarking, kNoGCCallbackFlags);
    810     }
    811   }
    812   incremental_marking()->FinalizeIncrementally();
    813   {
    814     GCCallbacksScope scope(this);
    815     if (scope.CheckReenter()) {
    816       AllowHeapAllocation allow_allocation;
    817       TRACE_GC(tracer(), GCTracer::Scope::MC_INCREMENTAL_EXTERNAL_EPILOGUE);
    818       VMState<EXTERNAL> state(isolate_);
    819       HandleScope handle_scope(isolate_);
    820       CallGCEpilogueCallbacks(kGCTypeIncrementalMarking, kNoGCCallbackFlags);
    821     }
    822   }
    823 }
    824 
    825 
    826 HistogramTimer* Heap::GCTypeTimer(GarbageCollector collector) {
    827   if (IsYoungGenerationCollector(collector)) {
    828     return isolate_->counters()->gc_scavenger();
    829   } else {
    830     if (!incremental_marking()->IsStopped()) {
    831       if (ShouldReduceMemory()) {
    832         return isolate_->counters()->gc_finalize_reduce_memory();
    833       } else {
    834         return isolate_->counters()->gc_finalize();
    835       }
    836     } else {
    837       return isolate_->counters()->gc_compactor();
    838     }
    839   }
    840 }
    841 
    842 void Heap::CollectAllGarbage(int flags, GarbageCollectionReason gc_reason,
    843                              const v8::GCCallbackFlags gc_callback_flags) {
    844   // Since we are ignoring the return value, the exact choice of space does
    845   // not matter, so long as we do not specify NEW_SPACE, which would not
    846   // cause a full GC.
    847   set_current_gc_flags(flags);
    848   CollectGarbage(OLD_SPACE, gc_reason, gc_callback_flags);
    849   set_current_gc_flags(kNoGCFlags);
    850 }
    851 
    852 void Heap::CollectAllAvailableGarbage(GarbageCollectionReason gc_reason) {
    853   // Since we are ignoring the return value, the exact choice of space does
    854   // not matter, so long as we do not specify NEW_SPACE, which would not
    855   // cause a full GC.
    856   // Major GC would invoke weak handle callbacks on weakly reachable
    857   // handles, but won't collect weakly reachable objects until next
    858   // major GC.  Therefore if we collect aggressively and weak handle callback
    859   // has been invoked, we rerun major GC to release objects which become
    860   // garbage.
    861   // Note: as weak callbacks can execute arbitrary code, we cannot
    862   // hope that eventually there will be no weak callbacks invocations.
    863   // Therefore stop recollecting after several attempts.
    864   if (isolate()->concurrent_recompilation_enabled()) {
    865     // The optimizing compiler may be unnecessarily holding on to memory.
    866     DisallowHeapAllocation no_recursive_gc;
    867     isolate()->optimizing_compile_dispatcher()->Flush(
    868         OptimizingCompileDispatcher::BlockingBehavior::kDontBlock);
    869   }
    870   isolate()->ClearSerializerData();
    871   set_current_gc_flags(kMakeHeapIterableMask | kReduceMemoryFootprintMask);
    872   isolate_->compilation_cache()->Clear();
    873   const int kMaxNumberOfAttempts = 7;
    874   const int kMinNumberOfAttempts = 2;
    875   for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) {
    876     if (!CollectGarbage(MARK_COMPACTOR, gc_reason, NULL,
    877                         v8::kGCCallbackFlagCollectAllAvailableGarbage) &&
    878         attempt + 1 >= kMinNumberOfAttempts) {
    879       break;
    880     }
    881   }
    882   set_current_gc_flags(kNoGCFlags);
    883   new_space_->Shrink();
    884   UncommitFromSpace();
    885 }
    886 
    887 void Heap::ReportExternalMemoryPressure() {
    888   if (external_memory_ >
    889       (external_memory_at_last_mark_compact_ + external_memory_hard_limit())) {
    890     CollectAllGarbage(
    891         kReduceMemoryFootprintMask | kFinalizeIncrementalMarkingMask,
    892         GarbageCollectionReason::kExternalMemoryPressure,
    893         static_cast<GCCallbackFlags>(kGCCallbackFlagCollectAllAvailableGarbage |
    894                                      kGCCallbackFlagCollectAllExternalMemory));
    895     return;
    896   }
    897   if (incremental_marking()->IsStopped()) {
    898     if (incremental_marking()->CanBeActivated()) {
    899       StartIncrementalMarking(
    900           i::Heap::kNoGCFlags, GarbageCollectionReason::kExternalMemoryPressure,
    901           static_cast<GCCallbackFlags>(
    902               kGCCallbackFlagSynchronousPhantomCallbackProcessing |
    903               kGCCallbackFlagCollectAllExternalMemory));
    904     } else {
    905       CollectAllGarbage(i::Heap::kNoGCFlags,
    906                         GarbageCollectionReason::kExternalMemoryPressure,
    907                         kGCCallbackFlagSynchronousPhantomCallbackProcessing);
    908     }
    909   } else {
    910     // Incremental marking is turned on an has already been started.
    911     const double pressure =
    912         static_cast<double>(external_memory_ -
    913                             external_memory_at_last_mark_compact_ -
    914                             kExternalAllocationSoftLimit) /
    915         external_memory_hard_limit();
    916     DCHECK_GE(1, pressure);
    917     const double kMaxStepSizeOnExternalLimit = 25;
    918     const double deadline = MonotonicallyIncreasingTimeInMs() +
    919                             pressure * kMaxStepSizeOnExternalLimit;
    920     incremental_marking()->AdvanceIncrementalMarking(
    921         deadline, IncrementalMarking::GC_VIA_STACK_GUARD,
    922         IncrementalMarking::FORCE_COMPLETION, StepOrigin::kV8);
    923   }
    924 }
    925 
    926 
    927 void Heap::EnsureFillerObjectAtTop() {
    928   // There may be an allocation memento behind objects in new space. Upon
    929   // evacuation of a non-full new space (or if we are on the last page) there
    930   // may be uninitialized memory behind top. We fill the remainder of the page
    931   // with a filler.
    932   Address to_top = new_space_->top();
    933   Page* page = Page::FromAddress(to_top - kPointerSize);
    934   if (page->Contains(to_top)) {
    935     int remaining_in_page = static_cast<int>(page->area_end() - to_top);
    936     CreateFillerObjectAt(to_top, remaining_in_page, ClearRecordedSlots::kNo);
    937   }
    938 }
    939 
    940 bool Heap::CollectGarbage(GarbageCollector collector,
    941                           GarbageCollectionReason gc_reason,
    942                           const char* collector_reason,
    943                           const v8::GCCallbackFlags gc_callback_flags) {
    944   // The VM is in the GC state until exiting this function.
    945   VMState<GC> state(isolate_);
    946 
    947 #ifdef DEBUG
    948   // Reset the allocation timeout to the GC interval, but make sure to
    949   // allow at least a few allocations after a collection. The reason
    950   // for this is that we have a lot of allocation sequences and we
    951   // assume that a garbage collection will allow the subsequent
    952   // allocation attempts to go through.
    953   allocation_timeout_ = Max(6, FLAG_gc_interval);
    954 #endif
    955 
    956   EnsureFillerObjectAtTop();
    957 
    958   if (IsYoungGenerationCollector(collector) &&
    959       !incremental_marking()->IsStopped()) {
    960     if (FLAG_trace_incremental_marking) {
    961       isolate()->PrintWithTimestamp(
    962           "[IncrementalMarking] Scavenge during marking.\n");
    963     }
    964   }
    965 
    966   if (collector == MARK_COMPACTOR && FLAG_incremental_marking &&
    967       !ShouldFinalizeIncrementalMarking() && !ShouldAbortIncrementalMarking() &&
    968       !incremental_marking()->IsStopped() &&
    969       !incremental_marking()->should_hurry() &&
    970       !incremental_marking()->NeedsFinalization() &&
    971       !IsCloseToOutOfMemory(new_space_->Capacity())) {
    972     if (!incremental_marking()->IsComplete() &&
    973         !mark_compact_collector()->marking_deque()->IsEmpty() &&
    974         !FLAG_gc_global) {
    975       if (FLAG_trace_incremental_marking) {
    976         isolate()->PrintWithTimestamp(
    977             "[IncrementalMarking] Delaying MarkSweep.\n");
    978       }
    979       collector = YoungGenerationCollector();
    980       collector_reason = "incremental marking delaying mark-sweep";
    981     }
    982   }
    983 
    984   bool next_gc_likely_to_collect_more = false;
    985   size_t committed_memory_before = 0;
    986 
    987   if (collector == MARK_COMPACTOR) {
    988     committed_memory_before = CommittedOldGenerationMemory();
    989   }
    990 
    991   {
    992     tracer()->Start(collector, gc_reason, collector_reason);
    993     DCHECK(AllowHeapAllocation::IsAllowed());
    994     DisallowHeapAllocation no_allocation_during_gc;
    995     GarbageCollectionPrologue();
    996 
    997     {
    998       HistogramTimer* gc_type_timer = GCTypeTimer(collector);
    999       HistogramTimerScope histogram_timer_scope(gc_type_timer);
   1000       TRACE_EVENT0("v8", gc_type_timer->name());
   1001 
   1002       next_gc_likely_to_collect_more =
   1003           PerformGarbageCollection(collector, gc_callback_flags);
   1004     }
   1005 
   1006     GarbageCollectionEpilogue();
   1007     if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) {
   1008       isolate()->CheckDetachedContextsAfterGC();
   1009     }
   1010 
   1011     if (collector == MARK_COMPACTOR) {
   1012       size_t committed_memory_after = CommittedOldGenerationMemory();
   1013       size_t used_memory_after = PromotedSpaceSizeOfObjects();
   1014       MemoryReducer::Event event;
   1015       event.type = MemoryReducer::kMarkCompact;
   1016       event.time_ms = MonotonicallyIncreasingTimeInMs();
   1017       // Trigger one more GC if
   1018       // - this GC decreased committed memory,
   1019       // - there is high fragmentation,
   1020       // - there are live detached contexts.
   1021       event.next_gc_likely_to_collect_more =
   1022           (committed_memory_before > committed_memory_after + MB) ||
   1023           HasHighFragmentation(used_memory_after, committed_memory_after) ||
   1024           (detached_contexts()->length() > 0);
   1025       if (deserialization_complete_) {
   1026         memory_reducer_->NotifyMarkCompact(event);
   1027       }
   1028       memory_pressure_level_.SetValue(MemoryPressureLevel::kNone);
   1029     }
   1030 
   1031     tracer()->Stop(collector);
   1032   }
   1033 
   1034   if (collector == MARK_COMPACTOR &&
   1035       (gc_callback_flags & (kGCCallbackFlagForced |
   1036                             kGCCallbackFlagCollectAllAvailableGarbage)) != 0) {
   1037     isolate()->CountUsage(v8::Isolate::kForcedGC);
   1038   }
   1039 
   1040   // Start incremental marking for the next cycle. The heap snapshot
   1041   // generator needs incremental marking to stay off after it aborted.
   1042   // We do this only for scavenger to avoid a loop where mark-compact
   1043   // causes another mark-compact.
   1044   if (IsYoungGenerationCollector(collector) &&
   1045       !ShouldAbortIncrementalMarking()) {
   1046     StartIncrementalMarkingIfAllocationLimitIsReached(kNoGCFlags,
   1047                                                       kNoGCCallbackFlags);
   1048   }
   1049 
   1050   return next_gc_likely_to_collect_more;
   1051 }
   1052 
   1053 
   1054 int Heap::NotifyContextDisposed(bool dependant_context) {
   1055   if (!dependant_context) {
   1056     tracer()->ResetSurvivalEvents();
   1057     old_generation_size_configured_ = false;
   1058     MemoryReducer::Event event;
   1059     event.type = MemoryReducer::kPossibleGarbage;
   1060     event.time_ms = MonotonicallyIncreasingTimeInMs();
   1061     memory_reducer_->NotifyPossibleGarbage(event);
   1062   }
   1063   if (isolate()->concurrent_recompilation_enabled()) {
   1064     // Flush the queued recompilation tasks.
   1065     isolate()->optimizing_compile_dispatcher()->Flush(
   1066         OptimizingCompileDispatcher::BlockingBehavior::kDontBlock);
   1067   }
   1068   AgeInlineCaches();
   1069   number_of_disposed_maps_ = retained_maps()->Length();
   1070   tracer()->AddContextDisposalTime(MonotonicallyIncreasingTimeInMs());
   1071   return ++contexts_disposed_;
   1072 }
   1073 
   1074 void Heap::StartIncrementalMarking(int gc_flags,
   1075                                    GarbageCollectionReason gc_reason,
   1076                                    GCCallbackFlags gc_callback_flags) {
   1077   DCHECK(incremental_marking()->IsStopped());
   1078   set_current_gc_flags(gc_flags);
   1079   current_gc_callback_flags_ = gc_callback_flags;
   1080   incremental_marking()->Start(gc_reason);
   1081 }
   1082 
   1083 void Heap::StartIncrementalMarkingIfAllocationLimitIsReached(
   1084     int gc_flags, const GCCallbackFlags gc_callback_flags) {
   1085   if (incremental_marking()->IsStopped()) {
   1086     IncrementalMarkingLimit reached_limit = IncrementalMarkingLimitReached();
   1087     if (reached_limit == IncrementalMarkingLimit::kSoftLimit) {
   1088       incremental_marking()->incremental_marking_job()->ScheduleTask(this);
   1089     } else if (reached_limit == IncrementalMarkingLimit::kHardLimit) {
   1090       StartIncrementalMarking(gc_flags,
   1091                               GarbageCollectionReason::kAllocationLimit,
   1092                               gc_callback_flags);
   1093     }
   1094   }
   1095 }
   1096 
   1097 void Heap::StartIdleIncrementalMarking(GarbageCollectionReason gc_reason) {
   1098   gc_idle_time_handler_->ResetNoProgressCounter();
   1099   StartIncrementalMarking(kReduceMemoryFootprintMask, gc_reason,
   1100                           kNoGCCallbackFlags);
   1101 }
   1102 
   1103 
   1104 void Heap::MoveElements(FixedArray* array, int dst_index, int src_index,
   1105                         int len) {
   1106   if (len == 0) return;
   1107 
   1108   DCHECK(array->map() != fixed_cow_array_map());
   1109   Object** dst_objects = array->data_start() + dst_index;
   1110   MemMove(dst_objects, array->data_start() + src_index, len * kPointerSize);
   1111   FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(this, array, dst_index, len);
   1112 }
   1113 
   1114 
   1115 #ifdef VERIFY_HEAP
   1116 // Helper class for verifying the string table.
   1117 class StringTableVerifier : public ObjectVisitor {
   1118  public:
   1119   void VisitPointers(Object** start, Object** end) override {
   1120     // Visit all HeapObject pointers in [start, end).
   1121     for (Object** p = start; p < end; p++) {
   1122       if ((*p)->IsHeapObject()) {
   1123         HeapObject* object = HeapObject::cast(*p);
   1124         Isolate* isolate = object->GetIsolate();
   1125         // Check that the string is actually internalized.
   1126         CHECK(object->IsTheHole(isolate) || object->IsUndefined(isolate) ||
   1127               object->IsInternalizedString());
   1128       }
   1129     }
   1130   }
   1131 };
   1132 
   1133 
   1134 static void VerifyStringTable(Heap* heap) {
   1135   StringTableVerifier verifier;
   1136   heap->string_table()->IterateElements(&verifier);
   1137 }
   1138 #endif  // VERIFY_HEAP
   1139 
   1140 bool Heap::ReserveSpace(Reservation* reservations, List<Address>* maps) {
   1141   bool gc_performed = true;
   1142   int counter = 0;
   1143   static const int kThreshold = 20;
   1144   while (gc_performed && counter++ < kThreshold) {
   1145     gc_performed = false;
   1146     for (int space = NEW_SPACE; space < SerializerDeserializer::kNumberOfSpaces;
   1147          space++) {
   1148       Reservation* reservation = &reservations[space];
   1149       DCHECK_LE(1, reservation->length());
   1150       if (reservation->at(0).size == 0) continue;
   1151       bool perform_gc = false;
   1152       if (space == MAP_SPACE) {
   1153         // We allocate each map individually to avoid fragmentation.
   1154         maps->Clear();
   1155         DCHECK_EQ(1, reservation->length());
   1156         int num_maps = reservation->at(0).size / Map::kSize;
   1157         for (int i = 0; i < num_maps; i++) {
   1158           // The deserializer will update the skip list.
   1159           AllocationResult allocation = map_space()->AllocateRawUnaligned(
   1160               Map::kSize, PagedSpace::IGNORE_SKIP_LIST);
   1161           HeapObject* free_space = nullptr;
   1162           if (allocation.To(&free_space)) {
   1163             // Mark with a free list node, in case we have a GC before
   1164             // deserializing.
   1165             Address free_space_address = free_space->address();
   1166             CreateFillerObjectAt(free_space_address, Map::kSize,
   1167                                  ClearRecordedSlots::kNo, ClearBlackArea::kNo);
   1168             maps->Add(free_space_address);
   1169           } else {
   1170             perform_gc = true;
   1171             break;
   1172           }
   1173         }
   1174       } else if (space == LO_SPACE) {
   1175         // Just check that we can allocate during deserialization.
   1176         DCHECK_EQ(1, reservation->length());
   1177         perform_gc = !CanExpandOldGeneration(reservation->at(0).size);
   1178       } else {
   1179         for (auto& chunk : *reservation) {
   1180           AllocationResult allocation;
   1181           int size = chunk.size;
   1182           DCHECK_LE(static_cast<size_t>(size),
   1183                     MemoryAllocator::PageAreaSize(
   1184                         static_cast<AllocationSpace>(space)));
   1185           if (space == NEW_SPACE) {
   1186             allocation = new_space()->AllocateRawUnaligned(size);
   1187           } else {
   1188             // The deserializer will update the skip list.
   1189             allocation = paged_space(space)->AllocateRawUnaligned(
   1190                 size, PagedSpace::IGNORE_SKIP_LIST);
   1191           }
   1192           HeapObject* free_space = nullptr;
   1193           if (allocation.To(&free_space)) {
   1194             // Mark with a free list node, in case we have a GC before
   1195             // deserializing.
   1196             Address free_space_address = free_space->address();
   1197             CreateFillerObjectAt(free_space_address, size,
   1198                                  ClearRecordedSlots::kNo, ClearBlackArea::kNo);
   1199             DCHECK(space < SerializerDeserializer::kNumberOfPreallocatedSpaces);
   1200             chunk.start = free_space_address;
   1201             chunk.end = free_space_address + size;
   1202           } else {
   1203             perform_gc = true;
   1204             break;
   1205           }
   1206         }
   1207       }
   1208       if (perform_gc) {
   1209         if (space == NEW_SPACE) {
   1210           CollectGarbage(NEW_SPACE, GarbageCollectionReason::kDeserializer);
   1211         } else {
   1212           if (counter > 1) {
   1213             CollectAllGarbage(
   1214                 kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask,
   1215                 GarbageCollectionReason::kDeserializer);
   1216           } else {
   1217             CollectAllGarbage(kAbortIncrementalMarkingMask,
   1218                               GarbageCollectionReason::kDeserializer);
   1219           }
   1220         }
   1221         gc_performed = true;
   1222         break;  // Abort for-loop over spaces and retry.
   1223       }
   1224     }
   1225   }
   1226 
   1227   return !gc_performed;
   1228 }
   1229 
   1230 
   1231 void Heap::EnsureFromSpaceIsCommitted() {
   1232   if (new_space_->CommitFromSpaceIfNeeded()) return;
   1233 
   1234   // Committing memory to from space failed.
   1235   // Memory is exhausted and we will die.
   1236   V8::FatalProcessOutOfMemory("Committing semi space failed.");
   1237 }
   1238 
   1239 
   1240 void Heap::ClearNormalizedMapCaches() {
   1241   if (isolate_->bootstrapper()->IsActive() &&
   1242       !incremental_marking()->IsMarking()) {
   1243     return;
   1244   }
   1245 
   1246   Object* context = native_contexts_list();
   1247   while (!context->IsUndefined(isolate())) {
   1248     // GC can happen when the context is not fully initialized,
   1249     // so the cache can be undefined.
   1250     Object* cache =
   1251         Context::cast(context)->get(Context::NORMALIZED_MAP_CACHE_INDEX);
   1252     if (!cache->IsUndefined(isolate())) {
   1253       NormalizedMapCache::cast(cache)->Clear();
   1254     }
   1255     context = Context::cast(context)->next_context_link();
   1256   }
   1257 }
   1258 
   1259 
   1260 void Heap::UpdateSurvivalStatistics(int start_new_space_size) {
   1261   if (start_new_space_size == 0) return;
   1262 
   1263   promotion_ratio_ = (static_cast<double>(promoted_objects_size_) /
   1264                       static_cast<double>(start_new_space_size) * 100);
   1265 
   1266   if (previous_semi_space_copied_object_size_ > 0) {
   1267     promotion_rate_ =
   1268         (static_cast<double>(promoted_objects_size_) /
   1269          static_cast<double>(previous_semi_space_copied_object_size_) * 100);
   1270   } else {
   1271     promotion_rate_ = 0;
   1272   }
   1273 
   1274   semi_space_copied_rate_ =
   1275       (static_cast<double>(semi_space_copied_object_size_) /
   1276        static_cast<double>(start_new_space_size) * 100);
   1277 
   1278   double survival_rate = promotion_ratio_ + semi_space_copied_rate_;
   1279   tracer()->AddSurvivalRatio(survival_rate);
   1280 }
   1281 
   1282 bool Heap::PerformGarbageCollection(
   1283     GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) {
   1284   int freed_global_handles = 0;
   1285 
   1286   if (!IsYoungGenerationCollector(collector)) {
   1287     PROFILE(isolate_, CodeMovingGCEvent());
   1288   }
   1289 
   1290 #ifdef VERIFY_HEAP
   1291   if (FLAG_verify_heap) {
   1292     VerifyStringTable(this);
   1293   }
   1294 #endif
   1295 
   1296   GCType gc_type =
   1297       collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge;
   1298 
   1299   {
   1300     GCCallbacksScope scope(this);
   1301     if (scope.CheckReenter()) {
   1302       AllowHeapAllocation allow_allocation;
   1303       TRACE_GC(tracer(), GCTracer::Scope::EXTERNAL_PROLOGUE);
   1304       VMState<EXTERNAL> state(isolate_);
   1305       HandleScope handle_scope(isolate_);
   1306       CallGCPrologueCallbacks(gc_type, kNoGCCallbackFlags);
   1307     }
   1308   }
   1309 
   1310   EnsureFromSpaceIsCommitted();
   1311 
   1312   int start_new_space_size = static_cast<int>(Heap::new_space()->Size());
   1313 
   1314   {
   1315     Heap::PretenuringScope pretenuring_scope(this);
   1316 
   1317     switch (collector) {
   1318       case MARK_COMPACTOR:
   1319         UpdateOldGenerationAllocationCounter();
   1320         // Perform mark-sweep with optional compaction.
   1321         MarkCompact();
   1322         old_generation_size_configured_ = true;
   1323         // This should be updated before PostGarbageCollectionProcessing, which
   1324         // can cause another GC. Take into account the objects promoted during
   1325         // GC.
   1326         old_generation_allocation_counter_at_last_gc_ +=
   1327             static_cast<size_t>(promoted_objects_size_);
   1328         old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects();
   1329         break;
   1330       case MINOR_MARK_COMPACTOR:
   1331         MinorMarkCompact();
   1332         break;
   1333       case SCAVENGER:
   1334         Scavenge();
   1335         break;
   1336     }
   1337 
   1338     ProcessPretenuringFeedback();
   1339   }
   1340 
   1341   UpdateSurvivalStatistics(start_new_space_size);
   1342   ConfigureInitialOldGenerationSize();
   1343 
   1344   isolate_->counters()->objs_since_last_young()->Set(0);
   1345 
   1346   gc_post_processing_depth_++;
   1347   {
   1348     AllowHeapAllocation allow_allocation;
   1349     TRACE_GC(tracer(), GCTracer::Scope::EXTERNAL_WEAK_GLOBAL_HANDLES);
   1350     freed_global_handles =
   1351         isolate_->global_handles()->PostGarbageCollectionProcessing(
   1352             collector, gc_callback_flags);
   1353   }
   1354   gc_post_processing_depth_--;
   1355 
   1356   isolate_->eternal_handles()->PostGarbageCollectionProcessing(this);
   1357 
   1358   // Update relocatables.
   1359   Relocatable::PostGarbageCollectionProcessing(isolate_);
   1360 
   1361   double gc_speed = tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond();
   1362   double mutator_speed =
   1363       tracer()->CurrentOldGenerationAllocationThroughputInBytesPerMillisecond();
   1364   size_t old_gen_size = PromotedSpaceSizeOfObjects();
   1365   if (collector == MARK_COMPACTOR) {
   1366     // Register the amount of external allocated memory.
   1367     external_memory_at_last_mark_compact_ = external_memory_;
   1368     external_memory_limit_ = external_memory_ + kExternalAllocationSoftLimit;
   1369     SetOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed);
   1370   } else if (HasLowYoungGenerationAllocationRate() &&
   1371              old_generation_size_configured_) {
   1372     DampenOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed);
   1373   }
   1374 
   1375   {
   1376     GCCallbacksScope scope(this);
   1377     if (scope.CheckReenter()) {
   1378       AllowHeapAllocation allow_allocation;
   1379       TRACE_GC(tracer(), GCTracer::Scope::EXTERNAL_EPILOGUE);
   1380       VMState<EXTERNAL> state(isolate_);
   1381       HandleScope handle_scope(isolate_);
   1382       CallGCEpilogueCallbacks(gc_type, gc_callback_flags);
   1383     }
   1384   }
   1385 
   1386 #ifdef VERIFY_HEAP
   1387   if (FLAG_verify_heap) {
   1388     VerifyStringTable(this);
   1389   }
   1390 #endif
   1391 
   1392   return freed_global_handles > 0;
   1393 }
   1394 
   1395 
   1396 void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) {
   1397   for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) {
   1398     if (gc_type & gc_prologue_callbacks_[i].gc_type) {
   1399       if (!gc_prologue_callbacks_[i].pass_isolate) {
   1400         v8::GCCallback callback = reinterpret_cast<v8::GCCallback>(
   1401             gc_prologue_callbacks_[i].callback);
   1402         callback(gc_type, flags);
   1403       } else {
   1404         v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
   1405         gc_prologue_callbacks_[i].callback(isolate, gc_type, flags);
   1406       }
   1407     }
   1408   }
   1409   if (FLAG_trace_object_groups && (gc_type == kGCTypeIncrementalMarking ||
   1410                                    gc_type == kGCTypeMarkSweepCompact)) {
   1411     isolate_->global_handles()->PrintObjectGroups();
   1412   }
   1413 }
   1414 
   1415 
   1416 void Heap::CallGCEpilogueCallbacks(GCType gc_type,
   1417                                    GCCallbackFlags gc_callback_flags) {
   1418   for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) {
   1419     if (gc_type & gc_epilogue_callbacks_[i].gc_type) {
   1420       if (!gc_epilogue_callbacks_[i].pass_isolate) {
   1421         v8::GCCallback callback = reinterpret_cast<v8::GCCallback>(
   1422             gc_epilogue_callbacks_[i].callback);
   1423         callback(gc_type, gc_callback_flags);
   1424       } else {
   1425         v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
   1426         gc_epilogue_callbacks_[i].callback(isolate, gc_type, gc_callback_flags);
   1427       }
   1428     }
   1429   }
   1430 }
   1431 
   1432 
   1433 void Heap::MarkCompact() {
   1434   PauseAllocationObserversScope pause_observers(this);
   1435 
   1436   gc_state_ = MARK_COMPACT;
   1437   LOG(isolate_, ResourceEvent("markcompact", "begin"));
   1438 
   1439   uint64_t size_of_objects_before_gc = SizeOfObjects();
   1440 
   1441   mark_compact_collector()->Prepare();
   1442 
   1443   ms_count_++;
   1444 
   1445   MarkCompactPrologue();
   1446 
   1447   mark_compact_collector()->CollectGarbage();
   1448 
   1449   LOG(isolate_, ResourceEvent("markcompact", "end"));
   1450 
   1451   MarkCompactEpilogue();
   1452 
   1453   if (FLAG_allocation_site_pretenuring) {
   1454     EvaluateOldSpaceLocalPretenuring(size_of_objects_before_gc);
   1455   }
   1456 }
   1457 
   1458 void Heap::MinorMarkCompact() { UNREACHABLE(); }
   1459 
   1460 void Heap::MarkCompactEpilogue() {
   1461   TRACE_GC(tracer(), GCTracer::Scope::MC_EPILOGUE);
   1462   gc_state_ = NOT_IN_GC;
   1463 
   1464   isolate_->counters()->objs_since_last_full()->Set(0);
   1465 
   1466   incremental_marking()->Epilogue();
   1467 
   1468   PreprocessStackTraces();
   1469   DCHECK(incremental_marking()->IsStopped());
   1470 
   1471   mark_compact_collector()->marking_deque()->StopUsing();
   1472 }
   1473 
   1474 
   1475 void Heap::MarkCompactPrologue() {
   1476   TRACE_GC(tracer(), GCTracer::Scope::MC_PROLOGUE);
   1477   isolate_->context_slot_cache()->Clear();
   1478   isolate_->descriptor_lookup_cache()->Clear();
   1479   RegExpResultsCache::Clear(string_split_cache());
   1480   RegExpResultsCache::Clear(regexp_multiple_cache());
   1481 
   1482   isolate_->compilation_cache()->MarkCompactPrologue();
   1483 
   1484   CompletelyClearInstanceofCache();
   1485 
   1486   FlushNumberStringCache();
   1487   ClearNormalizedMapCaches();
   1488 }
   1489 
   1490 
   1491 void Heap::CheckNewSpaceExpansionCriteria() {
   1492   if (FLAG_experimental_new_space_growth_heuristic) {
   1493     if (new_space_->TotalCapacity() < new_space_->MaximumCapacity() &&
   1494         survived_last_scavenge_ * 100 / new_space_->TotalCapacity() >= 10) {
   1495       // Grow the size of new space if there is room to grow, and more than 10%
   1496       // have survived the last scavenge.
   1497       new_space_->Grow();
   1498       survived_since_last_expansion_ = 0;
   1499     }
   1500   } else if (new_space_->TotalCapacity() < new_space_->MaximumCapacity() &&
   1501              survived_since_last_expansion_ > new_space_->TotalCapacity()) {
   1502     // Grow the size of new space if there is room to grow, and enough data
   1503     // has survived scavenge since the last expansion.
   1504     new_space_->Grow();
   1505     survived_since_last_expansion_ = 0;
   1506   }
   1507 }
   1508 
   1509 
   1510 static bool IsUnscavengedHeapObject(Heap* heap, Object** p) {
   1511   return heap->InNewSpace(*p) &&
   1512          !HeapObject::cast(*p)->map_word().IsForwardingAddress();
   1513 }
   1514 
   1515 
   1516 static bool IsUnmodifiedHeapObject(Object** p) {
   1517   Object* object = *p;
   1518   if (object->IsSmi()) return false;
   1519   HeapObject* heap_object = HeapObject::cast(object);
   1520   if (!object->IsJSObject()) return false;
   1521   JSObject* js_object = JSObject::cast(object);
   1522   if (!js_object->WasConstructedFromApiFunction()) return false;
   1523   JSFunction* constructor =
   1524       JSFunction::cast(js_object->map()->GetConstructor());
   1525 
   1526   return constructor->initial_map() == heap_object->map();
   1527 }
   1528 
   1529 
   1530 void PromotionQueue::Initialize() {
   1531   // The last to-space page may be used for promotion queue. On promotion
   1532   // conflict, we use the emergency stack.
   1533   DCHECK((Page::kPageSize - MemoryChunk::kBodyOffset) % (2 * kPointerSize) ==
   1534          0);
   1535   front_ = rear_ =
   1536       reinterpret_cast<struct Entry*>(heap_->new_space()->ToSpaceEnd());
   1537   limit_ = reinterpret_cast<struct Entry*>(
   1538       Page::FromAllocationAreaAddress(reinterpret_cast<Address>(rear_))
   1539           ->area_start());
   1540   emergency_stack_ = NULL;
   1541 }
   1542 
   1543 void PromotionQueue::Destroy() {
   1544   DCHECK(is_empty());
   1545   delete emergency_stack_;
   1546   emergency_stack_ = NULL;
   1547 }
   1548 
   1549 void PromotionQueue::RelocateQueueHead() {
   1550   DCHECK(emergency_stack_ == NULL);
   1551 
   1552   Page* p = Page::FromAllocationAreaAddress(reinterpret_cast<Address>(rear_));
   1553   struct Entry* head_start = rear_;
   1554   struct Entry* head_end =
   1555       Min(front_, reinterpret_cast<struct Entry*>(p->area_end()));
   1556 
   1557   int entries_count =
   1558       static_cast<int>(head_end - head_start) / sizeof(struct Entry);
   1559 
   1560   emergency_stack_ = new List<Entry>(2 * entries_count);
   1561 
   1562   while (head_start != head_end) {
   1563     struct Entry* entry = head_start++;
   1564     // New space allocation in SemiSpaceCopyObject marked the region
   1565     // overlapping with promotion queue as uninitialized.
   1566     MSAN_MEMORY_IS_INITIALIZED(entry, sizeof(struct Entry));
   1567     emergency_stack_->Add(*entry);
   1568   }
   1569   rear_ = head_end;
   1570 }
   1571 
   1572 
   1573 class ScavengeWeakObjectRetainer : public WeakObjectRetainer {
   1574  public:
   1575   explicit ScavengeWeakObjectRetainer(Heap* heap) : heap_(heap) {}
   1576 
   1577   virtual Object* RetainAs(Object* object) {
   1578     if (!heap_->InFromSpace(object)) {
   1579       return object;
   1580     }
   1581 
   1582     MapWord map_word = HeapObject::cast(object)->map_word();
   1583     if (map_word.IsForwardingAddress()) {
   1584       return map_word.ToForwardingAddress();
   1585     }
   1586     return NULL;
   1587   }
   1588 
   1589  private:
   1590   Heap* heap_;
   1591 };
   1592 
   1593 
   1594 void Heap::Scavenge() {
   1595   TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SCAVENGE);
   1596   RelocationLock relocation_lock(this);
   1597   // There are soft limits in the allocation code, designed to trigger a mark
   1598   // sweep collection by failing allocations. There is no sense in trying to
   1599   // trigger one during scavenge: scavenges allocation should always succeed.
   1600   AlwaysAllocateScope scope(isolate());
   1601 
   1602   // Bump-pointer allocations done during scavenge are not real allocations.
   1603   // Pause the inline allocation steps.
   1604   PauseAllocationObserversScope pause_observers(this);
   1605 
   1606   mark_compact_collector()->sweeper().EnsureNewSpaceCompleted();
   1607 
   1608   gc_state_ = SCAVENGE;
   1609 
   1610   // Implements Cheney's copying algorithm
   1611   LOG(isolate_, ResourceEvent("scavenge", "begin"));
   1612 
   1613   // Used for updating survived_since_last_expansion_ at function end.
   1614   size_t survived_watermark = PromotedSpaceSizeOfObjects();
   1615 
   1616   scavenge_collector_->SelectScavengingVisitorsTable();
   1617 
   1618   if (UsingEmbedderHeapTracer()) {
   1619     // Register found wrappers with embedder so it can add them to its marking
   1620     // deque and correctly manage the case when v8 scavenger collects the
   1621     // wrappers by either keeping wrappables alive, or cleaning marking deque.
   1622     RegisterWrappersWithEmbedderHeapTracer();
   1623   }
   1624 
   1625   // Flip the semispaces.  After flipping, to space is empty, from space has
   1626   // live objects.
   1627   new_space_->Flip();
   1628   new_space_->ResetAllocationInfo();
   1629 
   1630   // We need to sweep newly copied objects which can be either in the
   1631   // to space or promoted to the old generation.  For to-space
   1632   // objects, we treat the bottom of the to space as a queue.  Newly
   1633   // copied and unswept objects lie between a 'front' mark and the
   1634   // allocation pointer.
   1635   //
   1636   // Promoted objects can go into various old-generation spaces, and
   1637   // can be allocated internally in the spaces (from the free list).
   1638   // We treat the top of the to space as a queue of addresses of
   1639   // promoted objects.  The addresses of newly promoted and unswept
   1640   // objects lie between a 'front' mark and a 'rear' mark that is
   1641   // updated as a side effect of promoting an object.
   1642   //
   1643   // There is guaranteed to be enough room at the top of the to space
   1644   // for the addresses of promoted objects: every object promoted
   1645   // frees up its size in bytes from the top of the new space, and
   1646   // objects are at least one pointer in size.
   1647   Address new_space_front = new_space_->ToSpaceStart();
   1648   promotion_queue_.Initialize();
   1649 
   1650   ScavengeVisitor scavenge_visitor(this);
   1651 
   1652   isolate()->global_handles()->IdentifyWeakUnmodifiedObjects(
   1653       &IsUnmodifiedHeapObject);
   1654 
   1655   {
   1656     // Copy roots.
   1657     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_ROOTS);
   1658     IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE);
   1659   }
   1660 
   1661   {
   1662     // Copy objects reachable from the old generation.
   1663     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS);
   1664     RememberedSet<OLD_TO_NEW>::Iterate(this, [this](Address addr) {
   1665       return Scavenger::CheckAndScavengeObject(this, addr);
   1666     });
   1667 
   1668     RememberedSet<OLD_TO_NEW>::IterateTyped(
   1669         this, [this](SlotType type, Address host_addr, Address addr) {
   1670           return UpdateTypedSlotHelper::UpdateTypedSlot(
   1671               isolate(), type, addr, [this](Object** addr) {
   1672                 // We expect that objects referenced by code are long living.
   1673                 // If we do not force promotion, then we need to clear
   1674                 // old_to_new slots in dead code objects after mark-compact.
   1675                 return Scavenger::CheckAndScavengeObject(
   1676                     this, reinterpret_cast<Address>(addr));
   1677               });
   1678         });
   1679   }
   1680 
   1681   {
   1682     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_WEAK);
   1683     // Copy objects reachable from the encountered weak collections list.
   1684     scavenge_visitor.VisitPointer(&encountered_weak_collections_);
   1685   }
   1686 
   1687   {
   1688     // Copy objects reachable from the code flushing candidates list.
   1689     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_CODE_FLUSH_CANDIDATES);
   1690     MarkCompactCollector* collector = mark_compact_collector();
   1691     if (collector->is_code_flushing_enabled()) {
   1692       collector->code_flusher()->IteratePointersToFromSpace(&scavenge_visitor);
   1693     }
   1694   }
   1695 
   1696   {
   1697     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SEMISPACE);
   1698     new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
   1699   }
   1700 
   1701   isolate()->global_handles()->MarkNewSpaceWeakUnmodifiedObjectsPending(
   1702       &IsUnscavengedHeapObject);
   1703 
   1704   isolate()->global_handles()->IterateNewSpaceWeakUnmodifiedRoots(
   1705       &scavenge_visitor);
   1706   new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
   1707 
   1708   UpdateNewSpaceReferencesInExternalStringTable(
   1709       &UpdateNewSpaceReferenceInExternalStringTableEntry);
   1710 
   1711   promotion_queue_.Destroy();
   1712 
   1713   incremental_marking()->UpdateMarkingDequeAfterScavenge();
   1714 
   1715   ScavengeWeakObjectRetainer weak_object_retainer(this);
   1716   ProcessYoungWeakReferences(&weak_object_retainer);
   1717 
   1718   DCHECK(new_space_front == new_space_->top());
   1719 
   1720   // Set age mark.
   1721   new_space_->set_age_mark(new_space_->top());
   1722 
   1723   ArrayBufferTracker::FreeDeadInNewSpace(this);
   1724 
   1725   // Update how much has survived scavenge.
   1726   DCHECK_GE(PromotedSpaceSizeOfObjects(), survived_watermark);
   1727   IncrementYoungSurvivorsCounter(PromotedSpaceSizeOfObjects() +
   1728                                  new_space_->Size() - survived_watermark);
   1729 
   1730   LOG(isolate_, ResourceEvent("scavenge", "end"));
   1731 
   1732   gc_state_ = NOT_IN_GC;
   1733 }
   1734 
   1735 
   1736 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
   1737                                                                 Object** p) {
   1738   MapWord first_word = HeapObject::cast(*p)->map_word();
   1739 
   1740   if (!first_word.IsForwardingAddress()) {
   1741     // Unreachable external string can be finalized.
   1742     heap->FinalizeExternalString(String::cast(*p));
   1743     return NULL;
   1744   }
   1745 
   1746   // String is still reachable.
   1747   return String::cast(first_word.ToForwardingAddress());
   1748 }
   1749 
   1750 
   1751 void Heap::UpdateNewSpaceReferencesInExternalStringTable(
   1752     ExternalStringTableUpdaterCallback updater_func) {
   1753   if (external_string_table_.new_space_strings_.is_empty()) return;
   1754 
   1755   Object** start = &external_string_table_.new_space_strings_[0];
   1756   Object** end = start + external_string_table_.new_space_strings_.length();
   1757   Object** last = start;
   1758 
   1759   for (Object** p = start; p < end; ++p) {
   1760     String* target = updater_func(this, p);
   1761 
   1762     if (target == NULL) continue;
   1763 
   1764     DCHECK(target->IsExternalString());
   1765 
   1766     if (InNewSpace(target)) {
   1767       // String is still in new space.  Update the table entry.
   1768       *last = target;
   1769       ++last;
   1770     } else {
   1771       // String got promoted.  Move it to the old string list.
   1772       external_string_table_.AddOldString(target);
   1773     }
   1774   }
   1775 
   1776   DCHECK(last <= end);
   1777   external_string_table_.ShrinkNewStrings(static_cast<int>(last - start));
   1778 }
   1779 
   1780 
   1781 void Heap::UpdateReferencesInExternalStringTable(
   1782     ExternalStringTableUpdaterCallback updater_func) {
   1783   // Update old space string references.
   1784   if (external_string_table_.old_space_strings_.length() > 0) {
   1785     Object** start = &external_string_table_.old_space_strings_[0];
   1786     Object** end = start + external_string_table_.old_space_strings_.length();
   1787     for (Object** p = start; p < end; ++p) *p = updater_func(this, p);
   1788   }
   1789 
   1790   UpdateNewSpaceReferencesInExternalStringTable(updater_func);
   1791 }
   1792 
   1793 
   1794 void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) {
   1795   ProcessNativeContexts(retainer);
   1796   ProcessAllocationSites(retainer);
   1797 }
   1798 
   1799 
   1800 void Heap::ProcessYoungWeakReferences(WeakObjectRetainer* retainer) {
   1801   ProcessNativeContexts(retainer);
   1802 }
   1803 
   1804 
   1805 void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) {
   1806   Object* head = VisitWeakList<Context>(this, native_contexts_list(), retainer);
   1807   // Update the head of the list of contexts.
   1808   set_native_contexts_list(head);
   1809 }
   1810 
   1811 
   1812 void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) {
   1813   Object* allocation_site_obj =
   1814       VisitWeakList<AllocationSite>(this, allocation_sites_list(), retainer);
   1815   set_allocation_sites_list(allocation_site_obj);
   1816 }
   1817 
   1818 void Heap::ProcessWeakListRoots(WeakObjectRetainer* retainer) {
   1819   set_native_contexts_list(retainer->RetainAs(native_contexts_list()));
   1820   set_allocation_sites_list(retainer->RetainAs(allocation_sites_list()));
   1821 }
   1822 
   1823 void Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) {
   1824   DisallowHeapAllocation no_allocation_scope;
   1825   Object* cur = allocation_sites_list();
   1826   bool marked = false;
   1827   while (cur->IsAllocationSite()) {
   1828     AllocationSite* casted = AllocationSite::cast(cur);
   1829     if (casted->GetPretenureMode() == flag) {
   1830       casted->ResetPretenureDecision();
   1831       casted->set_deopt_dependent_code(true);
   1832       marked = true;
   1833       RemoveAllocationSitePretenuringFeedback(casted);
   1834     }
   1835     cur = casted->weak_next();
   1836   }
   1837   if (marked) isolate_->stack_guard()->RequestDeoptMarkedAllocationSites();
   1838 }
   1839 
   1840 
   1841 void Heap::EvaluateOldSpaceLocalPretenuring(
   1842     uint64_t size_of_objects_before_gc) {
   1843   uint64_t size_of_objects_after_gc = SizeOfObjects();
   1844   double old_generation_survival_rate =
   1845       (static_cast<double>(size_of_objects_after_gc) * 100) /
   1846       static_cast<double>(size_of_objects_before_gc);
   1847 
   1848   if (old_generation_survival_rate < kOldSurvivalRateLowThreshold) {
   1849     // Too many objects died in the old generation, pretenuring of wrong
   1850     // allocation sites may be the cause for that. We have to deopt all
   1851     // dependent code registered in the allocation sites to re-evaluate
   1852     // our pretenuring decisions.
   1853     ResetAllAllocationSitesDependentCode(TENURED);
   1854     if (FLAG_trace_pretenuring) {
   1855       PrintF(
   1856           "Deopt all allocation sites dependent code due to low survival "
   1857           "rate in the old generation %f\n",
   1858           old_generation_survival_rate);
   1859     }
   1860   }
   1861 }
   1862 
   1863 
   1864 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
   1865   DisallowHeapAllocation no_allocation;
   1866   // All external strings are listed in the external string table.
   1867 
   1868   class ExternalStringTableVisitorAdapter : public ObjectVisitor {
   1869    public:
   1870     explicit ExternalStringTableVisitorAdapter(
   1871         v8::ExternalResourceVisitor* visitor)
   1872         : visitor_(visitor) {}
   1873     virtual void VisitPointers(Object** start, Object** end) {
   1874       for (Object** p = start; p < end; p++) {
   1875         DCHECK((*p)->IsExternalString());
   1876         visitor_->VisitExternalString(
   1877             Utils::ToLocal(Handle<String>(String::cast(*p))));
   1878       }
   1879     }
   1880 
   1881    private:
   1882     v8::ExternalResourceVisitor* visitor_;
   1883   } external_string_table_visitor(visitor);
   1884 
   1885   external_string_table_.Iterate(&external_string_table_visitor);
   1886 }
   1887 
   1888 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
   1889                          Address new_space_front) {
   1890   do {
   1891     SemiSpace::AssertValidRange(new_space_front, new_space_->top());
   1892     // The addresses new_space_front and new_space_.top() define a
   1893     // queue of unprocessed copied objects.  Process them until the
   1894     // queue is empty.
   1895     while (new_space_front != new_space_->top()) {
   1896       if (!Page::IsAlignedToPageSize(new_space_front)) {
   1897         HeapObject* object = HeapObject::FromAddress(new_space_front);
   1898         new_space_front +=
   1899             StaticScavengeVisitor::IterateBody(object->map(), object);
   1900       } else {
   1901         new_space_front = Page::FromAllocationAreaAddress(new_space_front)
   1902                               ->next_page()
   1903                               ->area_start();
   1904       }
   1905     }
   1906 
   1907     // Promote and process all the to-be-promoted objects.
   1908     {
   1909       while (!promotion_queue()->is_empty()) {
   1910         HeapObject* target;
   1911         int32_t size;
   1912         bool was_marked_black;
   1913         promotion_queue()->remove(&target, &size, &was_marked_black);
   1914 
   1915         // Promoted object might be already partially visited
   1916         // during old space pointer iteration. Thus we search specifically
   1917         // for pointers to from semispace instead of looking for pointers
   1918         // to new space.
   1919         DCHECK(!target->IsMap());
   1920 
   1921         IterateAndScavengePromotedObject(target, static_cast<int>(size),
   1922                                          was_marked_black);
   1923       }
   1924     }
   1925 
   1926     // Take another spin if there are now unswept objects in new space
   1927     // (there are currently no more unswept promoted objects).
   1928   } while (new_space_front != new_space_->top());
   1929 
   1930   return new_space_front;
   1931 }
   1932 
   1933 
   1934 STATIC_ASSERT((FixedDoubleArray::kHeaderSize & kDoubleAlignmentMask) ==
   1935               0);  // NOLINT
   1936 STATIC_ASSERT((FixedTypedArrayBase::kDataOffset & kDoubleAlignmentMask) ==
   1937               0);  // NOLINT
   1938 #ifdef V8_HOST_ARCH_32_BIT
   1939 STATIC_ASSERT((HeapNumber::kValueOffset & kDoubleAlignmentMask) !=
   1940               0);  // NOLINT
   1941 #endif
   1942 
   1943 
   1944 int Heap::GetMaximumFillToAlign(AllocationAlignment alignment) {
   1945   switch (alignment) {
   1946     case kWordAligned:
   1947       return 0;
   1948     case kDoubleAligned:
   1949     case kDoubleUnaligned:
   1950       return kDoubleSize - kPointerSize;
   1951     case kSimd128Unaligned:
   1952       return kSimd128Size - kPointerSize;
   1953     default:
   1954       UNREACHABLE();
   1955   }
   1956   return 0;
   1957 }
   1958 
   1959 
   1960 int Heap::GetFillToAlign(Address address, AllocationAlignment alignment) {
   1961   intptr_t offset = OffsetFrom(address);
   1962   if (alignment == kDoubleAligned && (offset & kDoubleAlignmentMask) != 0)
   1963     return kPointerSize;
   1964   if (alignment == kDoubleUnaligned && (offset & kDoubleAlignmentMask) == 0)
   1965     return kDoubleSize - kPointerSize;  // No fill if double is always aligned.
   1966   if (alignment == kSimd128Unaligned) {
   1967     return (kSimd128Size - (static_cast<int>(offset) + kPointerSize)) &
   1968            kSimd128AlignmentMask;
   1969   }
   1970   return 0;
   1971 }
   1972 
   1973 
   1974 HeapObject* Heap::PrecedeWithFiller(HeapObject* object, int filler_size) {
   1975   CreateFillerObjectAt(object->address(), filler_size, ClearRecordedSlots::kNo);
   1976   return HeapObject::FromAddress(object->address() + filler_size);
   1977 }
   1978 
   1979 
   1980 HeapObject* Heap::AlignWithFiller(HeapObject* object, int object_size,
   1981                                   int allocation_size,
   1982                                   AllocationAlignment alignment) {
   1983   int filler_size = allocation_size - object_size;
   1984   DCHECK(filler_size > 0);
   1985   int pre_filler = GetFillToAlign(object->address(), alignment);
   1986   if (pre_filler) {
   1987     object = PrecedeWithFiller(object, pre_filler);
   1988     filler_size -= pre_filler;
   1989   }
   1990   if (filler_size)
   1991     CreateFillerObjectAt(object->address() + object_size, filler_size,
   1992                          ClearRecordedSlots::kNo);
   1993   return object;
   1994 }
   1995 
   1996 
   1997 HeapObject* Heap::DoubleAlignForDeserialization(HeapObject* object, int size) {
   1998   return AlignWithFiller(object, size - kPointerSize, size, kDoubleAligned);
   1999 }
   2000 
   2001 
   2002 void Heap::RegisterNewArrayBuffer(JSArrayBuffer* buffer) {
   2003   ArrayBufferTracker::RegisterNew(this, buffer);
   2004 }
   2005 
   2006 
   2007 void Heap::UnregisterArrayBuffer(JSArrayBuffer* buffer) {
   2008   ArrayBufferTracker::Unregister(this, buffer);
   2009 }
   2010 
   2011 
   2012 void Heap::ConfigureInitialOldGenerationSize() {
   2013   if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) {
   2014     old_generation_allocation_limit_ =
   2015         Max(MinimumAllocationLimitGrowingStep(),
   2016             static_cast<size_t>(
   2017                 static_cast<double>(old_generation_allocation_limit_) *
   2018                 (tracer()->AverageSurvivalRatio() / 100)));
   2019   }
   2020 }
   2021 
   2022 
   2023 AllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
   2024                                           int instance_size) {
   2025   Object* result = nullptr;
   2026   AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE);
   2027   if (!allocation.To(&result)) return allocation;
   2028 
   2029   // Map::cast cannot be used due to uninitialized map field.
   2030   reinterpret_cast<Map*>(result)->set_map(
   2031       reinterpret_cast<Map*>(root(kMetaMapRootIndex)));
   2032   reinterpret_cast<Map*>(result)->set_instance_type(instance_type);
   2033   reinterpret_cast<Map*>(result)->set_instance_size(instance_size);
   2034   // Initialize to only containing tagged fields.
   2035   reinterpret_cast<Map*>(result)->set_visitor_id(
   2036       StaticVisitorBase::GetVisitorId(instance_type, instance_size, false));
   2037   if (FLAG_unbox_double_fields) {
   2038     reinterpret_cast<Map*>(result)
   2039         ->set_layout_descriptor(LayoutDescriptor::FastPointerLayout());
   2040   }
   2041   reinterpret_cast<Map*>(result)->clear_unused();
   2042   reinterpret_cast<Map*>(result)
   2043       ->set_inobject_properties_or_constructor_function_index(0);
   2044   reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
   2045   reinterpret_cast<Map*>(result)->set_bit_field(0);
   2046   reinterpret_cast<Map*>(result)->set_bit_field2(0);
   2047   int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) |
   2048                    Map::OwnsDescriptors::encode(true) |
   2049                    Map::ConstructionCounter::encode(Map::kNoSlackTracking);
   2050   reinterpret_cast<Map*>(result)->set_bit_field3(bit_field3);
   2051   reinterpret_cast<Map*>(result)->set_weak_cell_cache(Smi::kZero);
   2052   return result;
   2053 }
   2054 
   2055 
   2056 AllocationResult Heap::AllocateMap(InstanceType instance_type,
   2057                                    int instance_size,
   2058                                    ElementsKind elements_kind) {
   2059   HeapObject* result = nullptr;
   2060   AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE);
   2061   if (!allocation.To(&result)) return allocation;
   2062 
   2063   isolate()->counters()->maps_created()->Increment();
   2064   result->set_map_no_write_barrier(meta_map());
   2065   Map* map = Map::cast(result);
   2066   map->set_instance_type(instance_type);
   2067   map->set_prototype(null_value(), SKIP_WRITE_BARRIER);
   2068   map->set_constructor_or_backpointer(null_value(), SKIP_WRITE_BARRIER);
   2069   map->set_instance_size(instance_size);
   2070   map->clear_unused();
   2071   map->set_inobject_properties_or_constructor_function_index(0);
   2072   map->set_code_cache(empty_fixed_array(), SKIP_WRITE_BARRIER);
   2073   map->set_dependent_code(DependentCode::cast(empty_fixed_array()),
   2074                           SKIP_WRITE_BARRIER);
   2075   map->set_weak_cell_cache(Smi::kZero);
   2076   map->set_raw_transitions(Smi::kZero);
   2077   map->set_unused_property_fields(0);
   2078   map->set_instance_descriptors(empty_descriptor_array());
   2079   if (FLAG_unbox_double_fields) {
   2080     map->set_layout_descriptor(LayoutDescriptor::FastPointerLayout());
   2081   }
   2082   // Must be called only after |instance_type|, |instance_size| and
   2083   // |layout_descriptor| are set.
   2084   map->set_visitor_id(Heap::GetStaticVisitorIdForMap(map));
   2085   map->set_bit_field(0);
   2086   map->set_bit_field2(1 << Map::kIsExtensible);
   2087   int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) |
   2088                    Map::OwnsDescriptors::encode(true) |
   2089                    Map::ConstructionCounter::encode(Map::kNoSlackTracking);
   2090   map->set_bit_field3(bit_field3);
   2091   map->set_elements_kind(elements_kind);
   2092   map->set_new_target_is_base(true);
   2093 
   2094   return map;
   2095 }
   2096 
   2097 
   2098 AllocationResult Heap::AllocateFillerObject(int size, bool double_align,
   2099                                             AllocationSpace space) {
   2100   HeapObject* obj = nullptr;
   2101   {
   2102     AllocationAlignment align = double_align ? kDoubleAligned : kWordAligned;
   2103     AllocationResult allocation = AllocateRaw(size, space, align);
   2104     if (!allocation.To(&obj)) return allocation;
   2105   }
   2106 #ifdef DEBUG
   2107   MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
   2108   DCHECK(chunk->owner()->identity() == space);
   2109 #endif
   2110   CreateFillerObjectAt(obj->address(), size, ClearRecordedSlots::kNo,
   2111                        ClearBlackArea::kNo);
   2112   return obj;
   2113 }
   2114 
   2115 
   2116 const Heap::StringTypeTable Heap::string_type_table[] = {
   2117 #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \
   2118   { type, size, k##camel_name##MapRootIndex }             \
   2119   ,
   2120     STRING_TYPE_LIST(STRING_TYPE_ELEMENT)
   2121 #undef STRING_TYPE_ELEMENT
   2122 };
   2123 
   2124 
   2125 const Heap::ConstantStringTable Heap::constant_string_table[] = {
   2126     {"", kempty_stringRootIndex},
   2127 #define CONSTANT_STRING_ELEMENT(name, contents) \
   2128   { contents, k##name##RootIndex }              \
   2129   ,
   2130     INTERNALIZED_STRING_LIST(CONSTANT_STRING_ELEMENT)
   2131 #undef CONSTANT_STRING_ELEMENT
   2132 };
   2133 
   2134 
   2135 const Heap::StructTable Heap::struct_table[] = {
   2136 #define STRUCT_TABLE_ELEMENT(NAME, Name, name)        \
   2137   { NAME##_TYPE, Name::kSize, k##Name##MapRootIndex } \
   2138   ,
   2139     STRUCT_LIST(STRUCT_TABLE_ELEMENT)
   2140 #undef STRUCT_TABLE_ELEMENT
   2141 };
   2142 
   2143 namespace {
   2144 
   2145 void FinalizePartialMap(Heap* heap, Map* map) {
   2146   map->set_code_cache(heap->empty_fixed_array());
   2147   map->set_dependent_code(DependentCode::cast(heap->empty_fixed_array()));
   2148   map->set_raw_transitions(Smi::kZero);
   2149   map->set_instance_descriptors(heap->empty_descriptor_array());
   2150   if (FLAG_unbox_double_fields) {
   2151     map->set_layout_descriptor(LayoutDescriptor::FastPointerLayout());
   2152   }
   2153   map->set_prototype(heap->null_value());
   2154   map->set_constructor_or_backpointer(heap->null_value());
   2155 }
   2156 
   2157 }  // namespace
   2158 
   2159 bool Heap::CreateInitialMaps() {
   2160   HeapObject* obj = nullptr;
   2161   {
   2162     AllocationResult allocation = AllocatePartialMap(MAP_TYPE, Map::kSize);
   2163     if (!allocation.To(&obj)) return false;
   2164   }
   2165   // Map::cast cannot be used due to uninitialized map field.
   2166   Map* new_meta_map = reinterpret_cast<Map*>(obj);
   2167   set_meta_map(new_meta_map);
   2168   new_meta_map->set_map(new_meta_map);
   2169 
   2170   {  // Partial map allocation
   2171 #define ALLOCATE_PARTIAL_MAP(instance_type, size, field_name)                \
   2172   {                                                                          \
   2173     Map* map;                                                                \
   2174     if (!AllocatePartialMap((instance_type), (size)).To(&map)) return false; \
   2175     set_##field_name##_map(map);                                             \
   2176   }
   2177 
   2178     ALLOCATE_PARTIAL_MAP(FIXED_ARRAY_TYPE, kVariableSizeSentinel, fixed_array);
   2179     fixed_array_map()->set_elements_kind(FAST_HOLEY_ELEMENTS);
   2180     ALLOCATE_PARTIAL_MAP(ODDBALL_TYPE, Oddball::kSize, undefined);
   2181     ALLOCATE_PARTIAL_MAP(ODDBALL_TYPE, Oddball::kSize, null);
   2182     ALLOCATE_PARTIAL_MAP(ODDBALL_TYPE, Oddball::kSize, the_hole);
   2183 
   2184 #undef ALLOCATE_PARTIAL_MAP
   2185   }
   2186 
   2187   // Allocate the empty array.
   2188   {
   2189     AllocationResult allocation = AllocateEmptyFixedArray();
   2190     if (!allocation.To(&obj)) return false;
   2191   }
   2192   set_empty_fixed_array(FixedArray::cast(obj));
   2193 
   2194   {
   2195     AllocationResult allocation = Allocate(null_map(), OLD_SPACE);
   2196     if (!allocation.To(&obj)) return false;
   2197   }
   2198   set_null_value(Oddball::cast(obj));
   2199   Oddball::cast(obj)->set_kind(Oddball::kNull);
   2200 
   2201   {
   2202     AllocationResult allocation = Allocate(undefined_map(), OLD_SPACE);
   2203     if (!allocation.To(&obj)) return false;
   2204   }
   2205   set_undefined_value(Oddball::cast(obj));
   2206   Oddball::cast(obj)->set_kind(Oddball::kUndefined);
   2207   DCHECK(!InNewSpace(undefined_value()));
   2208   {
   2209     AllocationResult allocation = Allocate(the_hole_map(), OLD_SPACE);
   2210     if (!allocation.To(&obj)) return false;
   2211   }
   2212   set_the_hole_value(Oddball::cast(obj));
   2213   Oddball::cast(obj)->set_kind(Oddball::kTheHole);
   2214 
   2215   // Set preliminary exception sentinel value before actually initializing it.
   2216   set_exception(null_value());
   2217 
   2218   // Allocate the empty descriptor array.
   2219   {
   2220     AllocationResult allocation = AllocateEmptyFixedArray();
   2221     if (!allocation.To(&obj)) return false;
   2222   }
   2223   set_empty_descriptor_array(DescriptorArray::cast(obj));
   2224 
   2225   // Fix the instance_descriptors for the existing maps.
   2226   FinalizePartialMap(this, meta_map());
   2227   FinalizePartialMap(this, fixed_array_map());
   2228   FinalizePartialMap(this, undefined_map());
   2229   undefined_map()->set_is_undetectable();
   2230   FinalizePartialMap(this, null_map());
   2231   null_map()->set_is_undetectable();
   2232   FinalizePartialMap(this, the_hole_map());
   2233 
   2234   {  // Map allocation
   2235 #define ALLOCATE_MAP(instance_type, size, field_name)               \
   2236   {                                                                 \
   2237     Map* map;                                                       \
   2238     if (!AllocateMap((instance_type), size).To(&map)) return false; \
   2239     set_##field_name##_map(map);                                    \
   2240   }
   2241 
   2242 #define ALLOCATE_VARSIZE_MAP(instance_type, field_name) \
   2243   ALLOCATE_MAP(instance_type, kVariableSizeSentinel, field_name)
   2244 
   2245 #define ALLOCATE_PRIMITIVE_MAP(instance_type, size, field_name, \
   2246                                constructor_function_index)      \
   2247   {                                                             \
   2248     ALLOCATE_MAP((instance_type), (size), field_name);          \
   2249     field_name##_map()->SetConstructorFunctionIndex(            \
   2250         (constructor_function_index));                          \
   2251   }
   2252 
   2253     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, fixed_cow_array)
   2254     fixed_cow_array_map()->set_elements_kind(FAST_HOLEY_ELEMENTS);
   2255     DCHECK_NE(fixed_array_map(), fixed_cow_array_map());
   2256 
   2257     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, scope_info)
   2258     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, module_info)
   2259     ALLOCATE_PRIMITIVE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number,
   2260                            Context::NUMBER_FUNCTION_INDEX)
   2261     ALLOCATE_MAP(MUTABLE_HEAP_NUMBER_TYPE, HeapNumber::kSize,
   2262                  mutable_heap_number)
   2263     ALLOCATE_PRIMITIVE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol,
   2264                            Context::SYMBOL_FUNCTION_INDEX)
   2265 #define ALLOCATE_SIMD128_MAP(TYPE, Type, type, lane_count, lane_type) \
   2266   ALLOCATE_PRIMITIVE_MAP(SIMD128_VALUE_TYPE, Type::kSize, type,       \
   2267                          Context::TYPE##_FUNCTION_INDEX)
   2268     SIMD128_TYPES(ALLOCATE_SIMD128_MAP)
   2269 #undef ALLOCATE_SIMD128_MAP
   2270     ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign)
   2271 
   2272     ALLOCATE_PRIMITIVE_MAP(ODDBALL_TYPE, Oddball::kSize, boolean,
   2273                            Context::BOOLEAN_FUNCTION_INDEX);
   2274     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, uninitialized);
   2275     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, arguments_marker);
   2276     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, no_interceptor_result_sentinel);
   2277     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, exception);
   2278     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, termination_exception);
   2279     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, optimized_out);
   2280     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, stale_register);
   2281 
   2282     for (unsigned i = 0; i < arraysize(string_type_table); i++) {
   2283       const StringTypeTable& entry = string_type_table[i];
   2284       {
   2285         AllocationResult allocation = AllocateMap(entry.type, entry.size);
   2286         if (!allocation.To(&obj)) return false;
   2287       }
   2288       Map* map = Map::cast(obj);
   2289       map->SetConstructorFunctionIndex(Context::STRING_FUNCTION_INDEX);
   2290       // Mark cons string maps as unstable, because their objects can change
   2291       // maps during GC.
   2292       if (StringShape(entry.type).IsCons()) map->mark_unstable();
   2293       roots_[entry.index] = map;
   2294     }
   2295 
   2296     {  // Create a separate external one byte string map for native sources.
   2297       AllocationResult allocation =
   2298           AllocateMap(SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE,
   2299                       ExternalOneByteString::kShortSize);
   2300       if (!allocation.To(&obj)) return false;
   2301       Map* map = Map::cast(obj);
   2302       map->SetConstructorFunctionIndex(Context::STRING_FUNCTION_INDEX);
   2303       set_native_source_string_map(map);
   2304     }
   2305 
   2306     ALLOCATE_VARSIZE_MAP(FIXED_DOUBLE_ARRAY_TYPE, fixed_double_array)
   2307     fixed_double_array_map()->set_elements_kind(FAST_HOLEY_DOUBLE_ELEMENTS);
   2308     ALLOCATE_VARSIZE_MAP(BYTE_ARRAY_TYPE, byte_array)
   2309     ALLOCATE_VARSIZE_MAP(BYTECODE_ARRAY_TYPE, bytecode_array)
   2310     ALLOCATE_VARSIZE_MAP(FREE_SPACE_TYPE, free_space)
   2311 
   2312 #define ALLOCATE_FIXED_TYPED_ARRAY_MAP(Type, type, TYPE, ctype, size) \
   2313   ALLOCATE_VARSIZE_MAP(FIXED_##TYPE##_ARRAY_TYPE, fixed_##type##_array)
   2314 
   2315     TYPED_ARRAYS(ALLOCATE_FIXED_TYPED_ARRAY_MAP)
   2316 #undef ALLOCATE_FIXED_TYPED_ARRAY_MAP
   2317 
   2318     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, sloppy_arguments_elements)
   2319 
   2320     ALLOCATE_VARSIZE_MAP(CODE_TYPE, code)
   2321 
   2322     ALLOCATE_MAP(CELL_TYPE, Cell::kSize, cell)
   2323     ALLOCATE_MAP(PROPERTY_CELL_TYPE, PropertyCell::kSize, global_property_cell)
   2324     ALLOCATE_MAP(WEAK_CELL_TYPE, WeakCell::kSize, weak_cell)
   2325     ALLOCATE_MAP(FILLER_TYPE, kPointerSize, one_pointer_filler)
   2326     ALLOCATE_MAP(FILLER_TYPE, 2 * kPointerSize, two_pointer_filler)
   2327 
   2328     ALLOCATE_VARSIZE_MAP(TRANSITION_ARRAY_TYPE, transition_array)
   2329 
   2330     for (unsigned i = 0; i < arraysize(struct_table); i++) {
   2331       const StructTable& entry = struct_table[i];
   2332       Map* map;
   2333       if (!AllocateMap(entry.type, entry.size).To(&map)) return false;
   2334       roots_[entry.index] = map;
   2335     }
   2336 
   2337     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, hash_table)
   2338     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, ordered_hash_table)
   2339     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, unseeded_number_dictionary)
   2340 
   2341     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, function_context)
   2342     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, catch_context)
   2343     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, with_context)
   2344     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, debug_evaluate_context)
   2345     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, block_context)
   2346     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, module_context)
   2347     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, script_context)
   2348     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, script_context_table)
   2349 
   2350     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, native_context)
   2351     native_context_map()->set_dictionary_map(true);
   2352     native_context_map()->set_visitor_id(
   2353         StaticVisitorBase::kVisitNativeContext);
   2354 
   2355     ALLOCATE_MAP(SHARED_FUNCTION_INFO_TYPE, SharedFunctionInfo::kAlignedSize,
   2356                  shared_function_info)
   2357 
   2358     ALLOCATE_MAP(JS_MESSAGE_OBJECT_TYPE, JSMessageObject::kSize, message_object)
   2359     ALLOCATE_MAP(JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize, external)
   2360     external_map()->set_is_extensible(false);
   2361 #undef ALLOCATE_PRIMITIVE_MAP
   2362 #undef ALLOCATE_VARSIZE_MAP
   2363 #undef ALLOCATE_MAP
   2364   }
   2365 
   2366   {
   2367     AllocationResult allocation = AllocateEmptyScopeInfo();
   2368     if (!allocation.To(&obj)) return false;
   2369   }
   2370 
   2371   set_empty_scope_info(ScopeInfo::cast(obj));
   2372   {
   2373     AllocationResult allocation = Allocate(boolean_map(), OLD_SPACE);
   2374     if (!allocation.To(&obj)) return false;
   2375   }
   2376   set_true_value(Oddball::cast(obj));
   2377   Oddball::cast(obj)->set_kind(Oddball::kTrue);
   2378 
   2379   {
   2380     AllocationResult allocation = Allocate(boolean_map(), OLD_SPACE);
   2381     if (!allocation.To(&obj)) return false;
   2382   }
   2383   set_false_value(Oddball::cast(obj));
   2384   Oddball::cast(obj)->set_kind(Oddball::kFalse);
   2385 
   2386   {  // Empty arrays
   2387     {
   2388       ByteArray* byte_array;
   2389       if (!AllocateByteArray(0, TENURED).To(&byte_array)) return false;
   2390       set_empty_byte_array(byte_array);
   2391     }
   2392 
   2393 #define ALLOCATE_EMPTY_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
   2394   {                                                                     \
   2395     FixedTypedArrayBase* obj;                                           \
   2396     if (!AllocateEmptyFixedTypedArray(kExternal##Type##Array).To(&obj)) \
   2397       return false;                                                     \
   2398     set_empty_fixed_##type##_array(obj);                                \
   2399   }
   2400 
   2401     TYPED_ARRAYS(ALLOCATE_EMPTY_FIXED_TYPED_ARRAY)
   2402 #undef ALLOCATE_EMPTY_FIXED_TYPED_ARRAY
   2403   }
   2404   DCHECK(!InNewSpace(empty_fixed_array()));
   2405   return true;
   2406 }
   2407 
   2408 
   2409 AllocationResult Heap::AllocateHeapNumber(double value, MutableMode mode,
   2410                                           PretenureFlag pretenure) {
   2411   // Statically ensure that it is safe to allocate heap numbers in paged
   2412   // spaces.
   2413   int size = HeapNumber::kSize;
   2414   STATIC_ASSERT(HeapNumber::kSize <= kMaxRegularHeapObjectSize);
   2415 
   2416   AllocationSpace space = SelectSpace(pretenure);
   2417 
   2418   HeapObject* result = nullptr;
   2419   {
   2420     AllocationResult allocation = AllocateRaw(size, space, kDoubleUnaligned);
   2421     if (!allocation.To(&result)) return allocation;
   2422   }
   2423 
   2424   Map* map = mode == MUTABLE ? mutable_heap_number_map() : heap_number_map();
   2425   HeapObject::cast(result)->set_map_no_write_barrier(map);
   2426   HeapNumber::cast(result)->set_value(value);
   2427   return result;
   2428 }
   2429 
   2430 #define SIMD_ALLOCATE_DEFINITION(TYPE, Type, type, lane_count, lane_type) \
   2431   AllocationResult Heap::Allocate##Type(lane_type lanes[lane_count],      \
   2432                                         PretenureFlag pretenure) {        \
   2433     int size = Type::kSize;                                               \
   2434     STATIC_ASSERT(Type::kSize <= kMaxRegularHeapObjectSize);              \
   2435                                                                           \
   2436     AllocationSpace space = SelectSpace(pretenure);                       \
   2437                                                                           \
   2438     HeapObject* result = nullptr;                                         \
   2439     {                                                                     \
   2440       AllocationResult allocation =                                       \
   2441           AllocateRaw(size, space, kSimd128Unaligned);                    \
   2442       if (!allocation.To(&result)) return allocation;                     \
   2443     }                                                                     \
   2444                                                                           \
   2445     result->set_map_no_write_barrier(type##_map());                       \
   2446     Type* instance = Type::cast(result);                                  \
   2447     for (int i = 0; i < lane_count; i++) {                                \
   2448       instance->set_lane(i, lanes[i]);                                    \
   2449     }                                                                     \
   2450     return result;                                                        \
   2451   }
   2452 SIMD128_TYPES(SIMD_ALLOCATE_DEFINITION)
   2453 #undef SIMD_ALLOCATE_DEFINITION
   2454 
   2455 
   2456 AllocationResult Heap::AllocateCell(Object* value) {
   2457   int size = Cell::kSize;
   2458   STATIC_ASSERT(Cell::kSize <= kMaxRegularHeapObjectSize);
   2459 
   2460   HeapObject* result = nullptr;
   2461   {
   2462     AllocationResult allocation = AllocateRaw(size, OLD_SPACE);
   2463     if (!allocation.To(&result)) return allocation;
   2464   }
   2465   result->set_map_no_write_barrier(cell_map());
   2466   Cell::cast(result)->set_value(value);
   2467   return result;
   2468 }
   2469 
   2470 AllocationResult Heap::AllocatePropertyCell() {
   2471   int size = PropertyCell::kSize;
   2472   STATIC_ASSERT(PropertyCell::kSize <= kMaxRegularHeapObjectSize);
   2473 
   2474   HeapObject* result = nullptr;
   2475   AllocationResult allocation = AllocateRaw(size, OLD_SPACE);
   2476   if (!allocation.To(&result)) return allocation;
   2477 
   2478   result->set_map_no_write_barrier(global_property_cell_map());
   2479   PropertyCell* cell = PropertyCell::cast(result);
   2480   cell->set_dependent_code(DependentCode::cast(empty_fixed_array()),
   2481                            SKIP_WRITE_BARRIER);
   2482   cell->set_property_details(PropertyDetails(Smi::kZero));
   2483   cell->set_value(the_hole_value());
   2484   return result;
   2485 }
   2486 
   2487 
   2488 AllocationResult Heap::AllocateWeakCell(HeapObject* value) {
   2489   int size = WeakCell::kSize;
   2490   STATIC_ASSERT(WeakCell::kSize <= kMaxRegularHeapObjectSize);
   2491   HeapObject* result = nullptr;
   2492   {
   2493     AllocationResult allocation = AllocateRaw(size, OLD_SPACE);
   2494     if (!allocation.To(&result)) return allocation;
   2495   }
   2496   result->set_map_no_write_barrier(weak_cell_map());
   2497   WeakCell::cast(result)->initialize(value);
   2498   WeakCell::cast(result)->clear_next(the_hole_value());
   2499   return result;
   2500 }
   2501 
   2502 
   2503 AllocationResult Heap::AllocateTransitionArray(int capacity) {
   2504   DCHECK(capacity > 0);
   2505   HeapObject* raw_array = nullptr;
   2506   {
   2507     AllocationResult allocation = AllocateRawFixedArray(capacity, TENURED);
   2508     if (!allocation.To(&raw_array)) return allocation;
   2509   }
   2510   raw_array->set_map_no_write_barrier(transition_array_map());
   2511   TransitionArray* array = TransitionArray::cast(raw_array);
   2512   array->set_length(capacity);
   2513   MemsetPointer(array->data_start(), undefined_value(), capacity);
   2514   // Transition arrays are tenured. When black allocation is on we have to
   2515   // add the transition array to the list of encountered_transition_arrays.
   2516   if (incremental_marking()->black_allocation()) {
   2517     array->set_next_link(encountered_transition_arrays(),
   2518                          UPDATE_WEAK_WRITE_BARRIER);
   2519     set_encountered_transition_arrays(array);
   2520   } else {
   2521     array->set_next_link(undefined_value(), SKIP_WRITE_BARRIER);
   2522   }
   2523   return array;
   2524 }
   2525 
   2526 
   2527 void Heap::CreateApiObjects() {
   2528   HandleScope scope(isolate());
   2529   set_message_listeners(*TemplateList::New(isolate(), 2));
   2530 }
   2531 
   2532 
   2533 void Heap::CreateJSEntryStub() {
   2534   JSEntryStub stub(isolate(), StackFrame::ENTRY);
   2535   set_js_entry_code(*stub.GetCode());
   2536 }
   2537 
   2538 
   2539 void Heap::CreateJSConstructEntryStub() {
   2540   JSEntryStub stub(isolate(), StackFrame::ENTRY_CONSTRUCT);
   2541   set_js_construct_entry_code(*stub.GetCode());
   2542 }
   2543 
   2544 
   2545 void Heap::CreateFixedStubs() {
   2546   // Here we create roots for fixed stubs. They are needed at GC
   2547   // for cooking and uncooking (check out frames.cc).
   2548   // The eliminates the need for doing dictionary lookup in the
   2549   // stub cache for these stubs.
   2550   HandleScope scope(isolate());
   2551 
   2552   // Create stubs that should be there, so we don't unexpectedly have to
   2553   // create them if we need them during the creation of another stub.
   2554   // Stub creation mixes raw pointers and handles in an unsafe manner so
   2555   // we cannot create stubs while we are creating stubs.
   2556   CodeStub::GenerateStubsAheadOfTime(isolate());
   2557 
   2558   // MacroAssembler::Abort calls (usually enabled with --debug-code) depend on
   2559   // CEntryStub, so we need to call GenerateStubsAheadOfTime before JSEntryStub
   2560   // is created.
   2561 
   2562   // gcc-4.4 has problem generating correct code of following snippet:
   2563   // {  JSEntryStub stub;
   2564   //    js_entry_code_ = *stub.GetCode();
   2565   // }
   2566   // {  JSConstructEntryStub stub;
   2567   //    js_construct_entry_code_ = *stub.GetCode();
   2568   // }
   2569   // To workaround the problem, make separate functions without inlining.
   2570   Heap::CreateJSEntryStub();
   2571   Heap::CreateJSConstructEntryStub();
   2572 }
   2573 
   2574 
   2575 void Heap::CreateInitialObjects() {
   2576   HandleScope scope(isolate());
   2577   Factory* factory = isolate()->factory();
   2578 
   2579   // The -0 value must be set before NewNumber works.
   2580   set_minus_zero_value(*factory->NewHeapNumber(-0.0, IMMUTABLE, TENURED));
   2581   DCHECK(std::signbit(minus_zero_value()->Number()) != 0);
   2582 
   2583   set_nan_value(*factory->NewHeapNumber(
   2584       std::numeric_limits<double>::quiet_NaN(), IMMUTABLE, TENURED));
   2585   set_hole_nan_value(*factory->NewHeapNumber(bit_cast<double>(kHoleNanInt64),
   2586                                              IMMUTABLE, TENURED));
   2587   set_infinity_value(*factory->NewHeapNumber(V8_INFINITY, IMMUTABLE, TENURED));
   2588   set_minus_infinity_value(
   2589       *factory->NewHeapNumber(-V8_INFINITY, IMMUTABLE, TENURED));
   2590 
   2591   // Allocate initial string table.
   2592   set_string_table(*StringTable::New(isolate(), kInitialStringTableSize));
   2593 
   2594   // Allocate
   2595 
   2596   // Finish initializing oddballs after creating the string table.
   2597   Oddball::Initialize(isolate(), factory->undefined_value(), "undefined",
   2598                       factory->nan_value(), "undefined", Oddball::kUndefined);
   2599 
   2600   // Initialize the null_value.
   2601   Oddball::Initialize(isolate(), factory->null_value(), "null",
   2602                       handle(Smi::kZero, isolate()), "object", Oddball::kNull);
   2603 
   2604   // Initialize the_hole_value.
   2605   Oddball::Initialize(isolate(), factory->the_hole_value(), "hole",
   2606                       factory->hole_nan_value(), "undefined",
   2607                       Oddball::kTheHole);
   2608 
   2609   // Initialize the true_value.
   2610   Oddball::Initialize(isolate(), factory->true_value(), "true",
   2611                       handle(Smi::FromInt(1), isolate()), "boolean",
   2612                       Oddball::kTrue);
   2613 
   2614   // Initialize the false_value.
   2615   Oddball::Initialize(isolate(), factory->false_value(), "false",
   2616                       handle(Smi::kZero, isolate()), "boolean",
   2617                       Oddball::kFalse);
   2618 
   2619   set_uninitialized_value(
   2620       *factory->NewOddball(factory->uninitialized_map(), "uninitialized",
   2621                            handle(Smi::FromInt(-1), isolate()), "undefined",
   2622                            Oddball::kUninitialized));
   2623 
   2624   set_arguments_marker(
   2625       *factory->NewOddball(factory->arguments_marker_map(), "arguments_marker",
   2626                            handle(Smi::FromInt(-4), isolate()), "undefined",
   2627                            Oddball::kArgumentsMarker));
   2628 
   2629   set_no_interceptor_result_sentinel(*factory->NewOddball(
   2630       factory->no_interceptor_result_sentinel_map(),
   2631       "no_interceptor_result_sentinel", handle(Smi::FromInt(-2), isolate()),
   2632       "undefined", Oddball::kOther));
   2633 
   2634   set_termination_exception(*factory->NewOddball(
   2635       factory->termination_exception_map(), "termination_exception",
   2636       handle(Smi::FromInt(-3), isolate()), "undefined", Oddball::kOther));
   2637 
   2638   set_exception(*factory->NewOddball(factory->exception_map(), "exception",
   2639                                      handle(Smi::FromInt(-5), isolate()),
   2640                                      "undefined", Oddball::kException));
   2641 
   2642   set_optimized_out(*factory->NewOddball(factory->optimized_out_map(),
   2643                                          "optimized_out",
   2644                                          handle(Smi::FromInt(-6), isolate()),
   2645                                          "undefined", Oddball::kOptimizedOut));
   2646 
   2647   set_stale_register(
   2648       *factory->NewOddball(factory->stale_register_map(), "stale_register",
   2649                            handle(Smi::FromInt(-7), isolate()), "undefined",
   2650                            Oddball::kStaleRegister));
   2651 
   2652   for (unsigned i = 0; i < arraysize(constant_string_table); i++) {
   2653     Handle<String> str =
   2654         factory->InternalizeUtf8String(constant_string_table[i].contents);
   2655     roots_[constant_string_table[i].index] = *str;
   2656   }
   2657 
   2658   // Create the code_stubs dictionary. The initial size is set to avoid
   2659   // expanding the dictionary during bootstrapping.
   2660   set_code_stubs(*UnseededNumberDictionary::New(isolate(), 128));
   2661 
   2662   set_instanceof_cache_function(Smi::kZero);
   2663   set_instanceof_cache_map(Smi::kZero);
   2664   set_instanceof_cache_answer(Smi::kZero);
   2665 
   2666   {
   2667     HandleScope scope(isolate());
   2668 #define SYMBOL_INIT(name)                                              \
   2669   {                                                                    \
   2670     Handle<String> name##d = factory->NewStringFromStaticChars(#name); \
   2671     Handle<Symbol> symbol(isolate()->factory()->NewPrivateSymbol());   \
   2672     symbol->set_name(*name##d);                                        \
   2673     roots_[k##name##RootIndex] = *symbol;                              \
   2674   }
   2675     PRIVATE_SYMBOL_LIST(SYMBOL_INIT)
   2676 #undef SYMBOL_INIT
   2677   }
   2678 
   2679   {
   2680     HandleScope scope(isolate());
   2681 #define SYMBOL_INIT(name, description)                                      \
   2682   Handle<Symbol> name = factory->NewSymbol();                               \
   2683   Handle<String> name##d = factory->NewStringFromStaticChars(#description); \
   2684   name->set_name(*name##d);                                                 \
   2685   roots_[k##name##RootIndex] = *name;
   2686     PUBLIC_SYMBOL_LIST(SYMBOL_INIT)
   2687 #undef SYMBOL_INIT
   2688 
   2689 #define SYMBOL_INIT(name, description)                                      \
   2690   Handle<Symbol> name = factory->NewSymbol();                               \
   2691   Handle<String> name##d = factory->NewStringFromStaticChars(#description); \
   2692   name->set_is_well_known_symbol(true);                                     \
   2693   name->set_name(*name##d);                                                 \
   2694   roots_[k##name##RootIndex] = *name;
   2695     WELL_KNOWN_SYMBOL_LIST(SYMBOL_INIT)
   2696 #undef SYMBOL_INIT
   2697   }
   2698 
   2699   Handle<NameDictionary> empty_properties_dictionary =
   2700       NameDictionary::New(isolate(), 0, TENURED);
   2701   empty_properties_dictionary->SetRequiresCopyOnCapacityChange();
   2702   set_empty_properties_dictionary(*empty_properties_dictionary);
   2703 
   2704   set_number_string_cache(
   2705       *factory->NewFixedArray(kInitialNumberStringCacheSize * 2, TENURED));
   2706 
   2707   // Allocate cache for single character one byte strings.
   2708   set_single_character_string_cache(
   2709       *factory->NewFixedArray(String::kMaxOneByteCharCode + 1, TENURED));
   2710 
   2711   // Allocate cache for string split and regexp-multiple.
   2712   set_string_split_cache(*factory->NewFixedArray(
   2713       RegExpResultsCache::kRegExpResultsCacheSize, TENURED));
   2714   set_regexp_multiple_cache(*factory->NewFixedArray(
   2715       RegExpResultsCache::kRegExpResultsCacheSize, TENURED));
   2716 
   2717   // Allocate cache for external strings pointing to native source code.
   2718   set_natives_source_cache(
   2719       *factory->NewFixedArray(Natives::GetBuiltinsCount()));
   2720 
   2721   set_experimental_natives_source_cache(
   2722       *factory->NewFixedArray(ExperimentalNatives::GetBuiltinsCount()));
   2723 
   2724   set_extra_natives_source_cache(
   2725       *factory->NewFixedArray(ExtraNatives::GetBuiltinsCount()));
   2726 
   2727   set_experimental_extra_natives_source_cache(
   2728       *factory->NewFixedArray(ExperimentalExtraNatives::GetBuiltinsCount()));
   2729 
   2730   set_undefined_cell(*factory->NewCell(factory->undefined_value()));
   2731 
   2732   // The symbol registry is initialized lazily.
   2733   set_symbol_registry(Smi::kZero);
   2734 
   2735   // Microtask queue uses the empty fixed array as a sentinel for "empty".
   2736   // Number of queued microtasks stored in Isolate::pending_microtask_count().
   2737   set_microtask_queue(empty_fixed_array());
   2738 
   2739   {
   2740     StaticFeedbackVectorSpec spec;
   2741     FeedbackVectorSlot slot = spec.AddLoadICSlot();
   2742     DCHECK_EQ(slot, FeedbackVectorSlot(TypeFeedbackVector::kDummyLoadICSlot));
   2743 
   2744     slot = spec.AddKeyedLoadICSlot();
   2745     DCHECK_EQ(slot,
   2746               FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedLoadICSlot));
   2747 
   2748     slot = spec.AddStoreICSlot();
   2749     DCHECK_EQ(slot, FeedbackVectorSlot(TypeFeedbackVector::kDummyStoreICSlot));
   2750 
   2751     slot = spec.AddKeyedStoreICSlot();
   2752     DCHECK_EQ(slot,
   2753               FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot));
   2754 
   2755     Handle<TypeFeedbackMetadata> dummy_metadata =
   2756         TypeFeedbackMetadata::New(isolate(), &spec);
   2757     Handle<TypeFeedbackVector> dummy_vector =
   2758         TypeFeedbackVector::New(isolate(), dummy_metadata);
   2759 
   2760     set_dummy_vector(*dummy_vector);
   2761 
   2762     // Now initialize dummy vector's entries.
   2763     LoadICNexus(isolate()).ConfigureMegamorphic();
   2764     StoreICNexus(isolate()).ConfigureMegamorphic();
   2765     KeyedLoadICNexus(isolate()).ConfigureMegamorphicKeyed(PROPERTY);
   2766     KeyedStoreICNexus(isolate()).ConfigureMegamorphicKeyed(PROPERTY);
   2767   }
   2768 
   2769   {
   2770     // Create a canonical empty TypeFeedbackVector, which is shared by all
   2771     // functions that don't need actual type feedback slots. Note however
   2772     // that all these functions will share the same invocation count, but
   2773     // that shouldn't matter since we only use the invocation count to
   2774     // relativize the absolute call counts, but we can only have call counts
   2775     // if we have actual feedback slots.
   2776     Handle<FixedArray> empty_type_feedback_vector = factory->NewFixedArray(
   2777         TypeFeedbackVector::kReservedIndexCount, TENURED);
   2778     empty_type_feedback_vector->set(TypeFeedbackVector::kMetadataIndex,
   2779                                     empty_fixed_array());
   2780     empty_type_feedback_vector->set(TypeFeedbackVector::kInvocationCountIndex,
   2781                                     Smi::kZero);
   2782     set_empty_type_feedback_vector(*empty_type_feedback_vector);
   2783 
   2784     // We use a canonical empty LiteralsArray for all functions that neither
   2785     // have literals nor need a TypeFeedbackVector (besides the invocation
   2786     // count special slot).
   2787     Handle<FixedArray> empty_literals_array =
   2788         factory->NewFixedArray(1, TENURED);
   2789     empty_literals_array->set(0, *empty_type_feedback_vector);
   2790     set_empty_literals_array(*empty_literals_array);
   2791   }
   2792 
   2793   {
   2794     Handle<FixedArray> empty_sloppy_arguments_elements =
   2795         factory->NewFixedArray(2, TENURED);
   2796     empty_sloppy_arguments_elements->set_map(sloppy_arguments_elements_map());
   2797     set_empty_sloppy_arguments_elements(*empty_sloppy_arguments_elements);
   2798   }
   2799 
   2800   {
   2801     Handle<WeakCell> cell = factory->NewWeakCell(factory->undefined_value());
   2802     set_empty_weak_cell(*cell);
   2803     cell->clear();
   2804   }
   2805 
   2806   set_detached_contexts(empty_fixed_array());
   2807   set_retained_maps(ArrayList::cast(empty_fixed_array()));
   2808 
   2809   set_weak_object_to_code_table(
   2810       *WeakHashTable::New(isolate(), 16, USE_DEFAULT_MINIMUM_CAPACITY,
   2811                           TENURED));
   2812 
   2813   set_weak_new_space_object_to_code_list(
   2814       ArrayList::cast(*(factory->NewFixedArray(16, TENURED))));
   2815   weak_new_space_object_to_code_list()->SetLength(0);
   2816 
   2817   set_script_list(Smi::kZero);
   2818 
   2819   Handle<SeededNumberDictionary> slow_element_dictionary =
   2820       SeededNumberDictionary::New(isolate(), 0, TENURED);
   2821   slow_element_dictionary->set_requires_slow_elements();
   2822   set_empty_slow_element_dictionary(*slow_element_dictionary);
   2823 
   2824   set_materialized_objects(*factory->NewFixedArray(0, TENURED));
   2825 
   2826   // Handling of script id generation is in Heap::NextScriptId().
   2827   set_last_script_id(Smi::FromInt(v8::UnboundScript::kNoScriptId));
   2828   set_next_template_serial_number(Smi::kZero);
   2829 
   2830   // Allocate the empty script.
   2831   Handle<Script> script = factory->NewScript(factory->empty_string());
   2832   script->set_type(Script::TYPE_NATIVE);
   2833   set_empty_script(*script);
   2834 
   2835   Handle<PropertyCell> cell = factory->NewPropertyCell();
   2836   cell->set_value(Smi::FromInt(Isolate::kProtectorValid));
   2837   set_array_protector(*cell);
   2838 
   2839   cell = factory->NewPropertyCell();
   2840   cell->set_value(the_hole_value());
   2841   set_empty_property_cell(*cell);
   2842 
   2843   cell = factory->NewPropertyCell();
   2844   cell->set_value(Smi::FromInt(Isolate::kProtectorValid));
   2845   set_has_instance_protector(*cell);
   2846 
   2847   Handle<Cell> is_concat_spreadable_cell = factory->NewCell(
   2848       handle(Smi::FromInt(Isolate::kProtectorValid), isolate()));
   2849   set_is_concat_spreadable_protector(*is_concat_spreadable_cell);
   2850 
   2851   Handle<Cell> species_cell = factory->NewCell(
   2852       handle(Smi::FromInt(Isolate::kProtectorValid), isolate()));
   2853   set_species_protector(*species_cell);
   2854 
   2855   cell = factory->NewPropertyCell();
   2856   cell->set_value(Smi::FromInt(Isolate::kProtectorValid));
   2857   set_string_length_protector(*cell);
   2858 
   2859   Handle<Cell> fast_array_iteration_cell = factory->NewCell(
   2860       handle(Smi::FromInt(Isolate::kProtectorValid), isolate()));
   2861   set_fast_array_iteration_protector(*fast_array_iteration_cell);
   2862 
   2863   Handle<Cell> array_iterator_cell = factory->NewCell(
   2864       handle(Smi::FromInt(Isolate::kProtectorValid), isolate()));
   2865   set_array_iterator_protector(*array_iterator_cell);
   2866 
   2867   set_serialized_templates(empty_fixed_array());
   2868 
   2869   set_weak_stack_trace_list(Smi::kZero);
   2870 
   2871   set_noscript_shared_function_infos(Smi::kZero);
   2872 
   2873   // Initialize context slot cache.
   2874   isolate_->context_slot_cache()->Clear();
   2875 
   2876   // Initialize descriptor cache.
   2877   isolate_->descriptor_lookup_cache()->Clear();
   2878 
   2879   // Initialize compilation cache.
   2880   isolate_->compilation_cache()->Clear();
   2881 }
   2882 
   2883 bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
   2884   switch (root_index) {
   2885     case kNumberStringCacheRootIndex:
   2886     case kInstanceofCacheFunctionRootIndex:
   2887     case kInstanceofCacheMapRootIndex:
   2888     case kInstanceofCacheAnswerRootIndex:
   2889     case kCodeStubsRootIndex:
   2890     case kEmptyScriptRootIndex:
   2891     case kSymbolRegistryRootIndex:
   2892     case kScriptListRootIndex:
   2893     case kMaterializedObjectsRootIndex:
   2894     case kMicrotaskQueueRootIndex:
   2895     case kDetachedContextsRootIndex:
   2896     case kWeakObjectToCodeTableRootIndex:
   2897     case kWeakNewSpaceObjectToCodeListRootIndex:
   2898     case kRetainedMapsRootIndex:
   2899     case kNoScriptSharedFunctionInfosRootIndex:
   2900     case kWeakStackTraceListRootIndex:
   2901     case kSerializedTemplatesRootIndex:
   2902 // Smi values
   2903 #define SMI_ENTRY(type, name, Name) case k##Name##RootIndex:
   2904       SMI_ROOT_LIST(SMI_ENTRY)
   2905 #undef SMI_ENTRY
   2906     // String table
   2907     case kStringTableRootIndex:
   2908       return true;
   2909 
   2910     default:
   2911       return false;
   2912   }
   2913 }
   2914 
   2915 
   2916 bool Heap::RootCanBeTreatedAsConstant(RootListIndex root_index) {
   2917   return !RootCanBeWrittenAfterInitialization(root_index) &&
   2918          !InNewSpace(root(root_index));
   2919 }
   2920 
   2921 
   2922 int Heap::FullSizeNumberStringCacheLength() {
   2923   // Compute the size of the number string cache based on the max newspace size.
   2924   // The number string cache has a minimum size based on twice the initial cache
   2925   // size to ensure that it is bigger after being made 'full size'.
   2926   size_t number_string_cache_size = max_semi_space_size_ / 512;
   2927   number_string_cache_size =
   2928       Max(static_cast<size_t>(kInitialNumberStringCacheSize * 2),
   2929           Min<size_t>(0x4000u, number_string_cache_size));
   2930   // There is a string and a number per entry so the length is twice the number
   2931   // of entries.
   2932   return static_cast<int>(number_string_cache_size * 2);
   2933 }
   2934 
   2935 
   2936 void Heap::FlushNumberStringCache() {
   2937   // Flush the number to string cache.
   2938   int len = number_string_cache()->length();
   2939   for (int i = 0; i < len; i++) {
   2940     number_string_cache()->set_undefined(i);
   2941   }
   2942 }
   2943 
   2944 
   2945 Map* Heap::MapForFixedTypedArray(ExternalArrayType array_type) {
   2946   return Map::cast(roots_[RootIndexForFixedTypedArray(array_type)]);
   2947 }
   2948 
   2949 
   2950 Heap::RootListIndex Heap::RootIndexForFixedTypedArray(
   2951     ExternalArrayType array_type) {
   2952   switch (array_type) {
   2953 #define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \
   2954   case kExternal##Type##Array:                                  \
   2955     return kFixed##Type##ArrayMapRootIndex;
   2956 
   2957     TYPED_ARRAYS(ARRAY_TYPE_TO_ROOT_INDEX)
   2958 #undef ARRAY_TYPE_TO_ROOT_INDEX
   2959 
   2960     default:
   2961       UNREACHABLE();
   2962       return kUndefinedValueRootIndex;
   2963   }
   2964 }
   2965 
   2966 
   2967 Heap::RootListIndex Heap::RootIndexForEmptyFixedTypedArray(
   2968     ElementsKind elementsKind) {
   2969   switch (elementsKind) {
   2970 #define ELEMENT_KIND_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \
   2971   case TYPE##_ELEMENTS:                                           \
   2972     return kEmptyFixed##Type##ArrayRootIndex;
   2973 
   2974     TYPED_ARRAYS(ELEMENT_KIND_TO_ROOT_INDEX)
   2975 #undef ELEMENT_KIND_TO_ROOT_INDEX
   2976     default:
   2977       UNREACHABLE();
   2978       return kUndefinedValueRootIndex;
   2979   }
   2980 }
   2981 
   2982 
   2983 FixedTypedArrayBase* Heap::EmptyFixedTypedArrayForMap(Map* map) {
   2984   return FixedTypedArrayBase::cast(
   2985       roots_[RootIndexForEmptyFixedTypedArray(map->elements_kind())]);
   2986 }
   2987 
   2988 
   2989 AllocationResult Heap::AllocateForeign(Address address,
   2990                                        PretenureFlag pretenure) {
   2991   // Statically ensure that it is safe to allocate foreigns in paged spaces.
   2992   STATIC_ASSERT(Foreign::kSize <= kMaxRegularHeapObjectSize);
   2993   AllocationSpace space = (pretenure == TENURED) ? OLD_SPACE : NEW_SPACE;
   2994   Foreign* result = nullptr;
   2995   AllocationResult allocation = Allocate(foreign_map(), space);
   2996   if (!allocation.To(&result)) return allocation;
   2997   result->set_foreign_address(address);
   2998   return result;
   2999 }
   3000 
   3001 
   3002 AllocationResult Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
   3003   if (length < 0 || length > ByteArray::kMaxLength) {
   3004     v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
   3005   }
   3006   int size = ByteArray::SizeFor(length);
   3007   AllocationSpace space = SelectSpace(pretenure);
   3008   HeapObject* result = nullptr;
   3009   {
   3010     AllocationResult allocation = AllocateRaw(size, space);
   3011     if (!allocation.To(&result)) return allocation;
   3012   }
   3013 
   3014   result->set_map_no_write_barrier(byte_array_map());
   3015   ByteArray::cast(result)->set_length(length);
   3016   return result;
   3017 }
   3018 
   3019 
   3020 AllocationResult Heap::AllocateBytecodeArray(int length,
   3021                                              const byte* const raw_bytecodes,
   3022                                              int frame_size,
   3023                                              int parameter_count,
   3024                                              FixedArray* constant_pool) {
   3025   if (length < 0 || length > BytecodeArray::kMaxLength) {
   3026     v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
   3027   }
   3028   // Bytecode array is pretenured, so constant pool array should be to.
   3029   DCHECK(!InNewSpace(constant_pool));
   3030 
   3031   int size = BytecodeArray::SizeFor(length);
   3032   HeapObject* result = nullptr;
   3033   {
   3034     AllocationResult allocation = AllocateRaw(size, OLD_SPACE);
   3035     if (!allocation.To(&result)) return allocation;
   3036   }
   3037 
   3038   result->set_map_no_write_barrier(bytecode_array_map());
   3039   BytecodeArray* instance = BytecodeArray::cast(result);
   3040   instance->set_length(length);
   3041   instance->set_frame_size(frame_size);
   3042   instance->set_parameter_count(parameter_count);
   3043   instance->set_interrupt_budget(interpreter::Interpreter::InterruptBudget());
   3044   instance->set_osr_loop_nesting_level(0);
   3045   instance->set_constant_pool(constant_pool);
   3046   instance->set_handler_table(empty_fixed_array());
   3047   instance->set_source_position_table(empty_byte_array());
   3048   CopyBytes(instance->GetFirstBytecodeAddress(), raw_bytecodes, length);
   3049 
   3050   return result;
   3051 }
   3052 
   3053 void Heap::CreateFillerObjectAt(Address addr, int size, ClearRecordedSlots mode,
   3054                                 ClearBlackArea black_area_mode) {
   3055   if (size == 0) return;
   3056   HeapObject* filler = HeapObject::FromAddress(addr);
   3057   if (size == kPointerSize) {
   3058     filler->set_map_no_write_barrier(
   3059         reinterpret_cast<Map*>(root(kOnePointerFillerMapRootIndex)));
   3060   } else if (size == 2 * kPointerSize) {
   3061     filler->set_map_no_write_barrier(
   3062         reinterpret_cast<Map*>(root(kTwoPointerFillerMapRootIndex)));
   3063   } else {
   3064     DCHECK_GT(size, 2 * kPointerSize);
   3065     filler->set_map_no_write_barrier(
   3066         reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex)));
   3067     FreeSpace::cast(filler)->nobarrier_set_size(size);
   3068   }
   3069   if (mode == ClearRecordedSlots::kYes) {
   3070     ClearRecordedSlotRange(addr, addr + size);
   3071   }
   3072 
   3073   // If the location where the filler is created is within a black area we have
   3074   // to clear the mark bits of the filler space.
   3075   if (black_area_mode == ClearBlackArea::kYes &&
   3076       incremental_marking()->black_allocation() &&
   3077       Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(addr))) {
   3078     Page* page = Page::FromAddress(addr);
   3079     page->markbits()->ClearRange(page->AddressToMarkbitIndex(addr),
   3080                                  page->AddressToMarkbitIndex(addr + size));
   3081   }
   3082 
   3083   // At this point, we may be deserializing the heap from a snapshot, and
   3084   // none of the maps have been created yet and are NULL.
   3085   DCHECK((filler->map() == NULL && !deserialization_complete_) ||
   3086          filler->map()->IsMap());
   3087 }
   3088 
   3089 
   3090 bool Heap::CanMoveObjectStart(HeapObject* object) {
   3091   if (!FLAG_move_object_start) return false;
   3092 
   3093   // Sampling heap profiler may have a reference to the object.
   3094   if (isolate()->heap_profiler()->is_sampling_allocations()) return false;
   3095 
   3096   Address address = object->address();
   3097 
   3098   if (lo_space()->Contains(object)) return false;
   3099 
   3100   // We can move the object start if the page was already swept.
   3101   return Page::FromAddress(address)->SweepingDone();
   3102 }
   3103 
   3104 
   3105 void Heap::AdjustLiveBytes(HeapObject* object, int by, InvocationMode mode) {
   3106   // As long as the inspected object is black and we are currently not iterating
   3107   // the heap using HeapIterator, we can update the live byte count. We cannot
   3108   // update while using HeapIterator because the iterator is temporarily
   3109   // marking the whole object graph, without updating live bytes.
   3110   if (lo_space()->Contains(object)) {
   3111     lo_space()->AdjustLiveBytes(by);
   3112   } else if (!in_heap_iterator() &&
   3113              !mark_compact_collector()->sweeping_in_progress() &&
   3114              Marking::IsBlack(ObjectMarking::MarkBitFrom(object->address()))) {
   3115     if (mode == SEQUENTIAL_TO_SWEEPER) {
   3116       MemoryChunk::IncrementLiveBytesFromGC(object, by);
   3117     } else {
   3118       MemoryChunk::IncrementLiveBytesFromMutator(object, by);
   3119     }
   3120   }
   3121 }
   3122 
   3123 
   3124 FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object,
   3125                                          int elements_to_trim) {
   3126   CHECK_NOT_NULL(object);
   3127   DCHECK(!object->IsFixedTypedArrayBase());
   3128   DCHECK(!object->IsByteArray());
   3129   const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize;
   3130   const int bytes_to_trim = elements_to_trim * element_size;
   3131   Map* map = object->map();
   3132 
   3133   // For now this trick is only applied to objects in new and paged space.
   3134   // In large object space the object's start must coincide with chunk
   3135   // and thus the trick is just not applicable.
   3136   DCHECK(!lo_space()->Contains(object));
   3137   DCHECK(object->map() != fixed_cow_array_map());
   3138 
   3139   STATIC_ASSERT(FixedArrayBase::kMapOffset == 0);
   3140   STATIC_ASSERT(FixedArrayBase::kLengthOffset == kPointerSize);
   3141   STATIC_ASSERT(FixedArrayBase::kHeaderSize == 2 * kPointerSize);
   3142 
   3143   const int len = object->length();
   3144   DCHECK(elements_to_trim <= len);
   3145 
   3146   // Calculate location of new array start.
   3147   Address old_start = object->address();
   3148   Address new_start = old_start + bytes_to_trim;
   3149 
   3150   // Transfer the mark bits to their new location if the object is not within
   3151   // a black area.
   3152   if (!incremental_marking()->black_allocation() ||
   3153       !Marking::IsBlack(ObjectMarking::MarkBitFrom(new_start))) {
   3154     IncrementalMarking::TransferMark(this, old_start, new_start);
   3155   }
   3156 
   3157   // Technically in new space this write might be omitted (except for
   3158   // debug mode which iterates through the heap), but to play safer
   3159   // we still do it.
   3160   CreateFillerObjectAt(old_start, bytes_to_trim, ClearRecordedSlots::kYes);
   3161   // Initialize header of the trimmed array. Since left trimming is only
   3162   // performed on pages which are not concurrently swept creating a filler
   3163   // object does not require synchronization.
   3164   DCHECK(CanMoveObjectStart(object));
   3165   Object** former_start = HeapObject::RawField(object, 0);
   3166   int new_start_index = elements_to_trim * (element_size / kPointerSize);
   3167   former_start[new_start_index] = map;
   3168   former_start[new_start_index + 1] = Smi::FromInt(len - elements_to_trim);
   3169 
   3170   FixedArrayBase* new_object =
   3171       FixedArrayBase::cast(HeapObject::FromAddress(new_start));
   3172 
   3173   // Maintain consistency of live bytes during incremental marking
   3174   AdjustLiveBytes(new_object, -bytes_to_trim, Heap::CONCURRENT_TO_SWEEPER);
   3175 
   3176   // Remove recorded slots for the new map and length offset.
   3177   ClearRecordedSlot(new_object, HeapObject::RawField(new_object, 0));
   3178   ClearRecordedSlot(new_object, HeapObject::RawField(
   3179                                     new_object, FixedArrayBase::kLengthOffset));
   3180 
   3181   // Notify the heap profiler of change in object layout.
   3182   OnMoveEvent(new_object, object, new_object->Size());
   3183   return new_object;
   3184 }
   3185 
   3186 
   3187 // Force instantiation of templatized method.
   3188 template void Heap::RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(
   3189     FixedArrayBase*, int);
   3190 template void Heap::RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
   3191     FixedArrayBase*, int);
   3192 
   3193 
   3194 template<Heap::InvocationMode mode>
   3195 void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) {
   3196   const int len = object->length();
   3197   DCHECK_LE(elements_to_trim, len);
   3198   DCHECK_GE(elements_to_trim, 0);
   3199 
   3200   int bytes_to_trim;
   3201   if (object->IsFixedTypedArrayBase()) {
   3202     InstanceType type = object->map()->instance_type();
   3203     bytes_to_trim =
   3204         FixedTypedArrayBase::TypedArraySize(type, len) -
   3205         FixedTypedArrayBase::TypedArraySize(type, len - elements_to_trim);
   3206   } else if (object->IsByteArray()) {
   3207     int new_size = ByteArray::SizeFor(len - elements_to_trim);
   3208     bytes_to_trim = ByteArray::SizeFor(len) - new_size;
   3209     DCHECK_GE(bytes_to_trim, 0);
   3210   } else {
   3211     const int element_size =
   3212         object->IsFixedArray() ? kPointerSize : kDoubleSize;
   3213     bytes_to_trim = elements_to_trim * element_size;
   3214   }
   3215 
   3216 
   3217   // For now this trick is only applied to objects in new and paged space.
   3218   DCHECK(object->map() != fixed_cow_array_map());
   3219 
   3220   if (bytes_to_trim == 0) {
   3221     // No need to create filler and update live bytes counters, just initialize
   3222     // header of the trimmed array.
   3223     object->synchronized_set_length(len - elements_to_trim);
   3224     return;
   3225   }
   3226 
   3227   // Calculate location of new array end.
   3228   Address old_end = object->address() + object->Size();
   3229   Address new_end = old_end - bytes_to_trim;
   3230 
   3231   // Technically in new space this write might be omitted (except for
   3232   // debug mode which iterates through the heap), but to play safer
   3233   // we still do it.
   3234   // We do not create a filler for objects in large object space.
   3235   // TODO(hpayer): We should shrink the large object page if the size
   3236   // of the object changed significantly.
   3237   if (!lo_space()->Contains(object)) {
   3238     CreateFillerObjectAt(new_end, bytes_to_trim, ClearRecordedSlots::kYes);
   3239   }
   3240 
   3241   // Initialize header of the trimmed array. We are storing the new length
   3242   // using release store after creating a filler for the left-over space to
   3243   // avoid races with the sweeper thread.
   3244   object->synchronized_set_length(len - elements_to_trim);
   3245 
   3246   // Maintain consistency of live bytes during incremental marking
   3247   AdjustLiveBytes(object, -bytes_to_trim, mode);
   3248 
   3249   // Notify the heap profiler of change in object layout. The array may not be
   3250   // moved during GC, and size has to be adjusted nevertheless.
   3251   HeapProfiler* profiler = isolate()->heap_profiler();
   3252   if (profiler->is_tracking_allocations()) {
   3253     profiler->UpdateObjectSizeEvent(object->address(), object->Size());
   3254   }
   3255 }
   3256 
   3257 
   3258 AllocationResult Heap::AllocateFixedTypedArrayWithExternalPointer(
   3259     int length, ExternalArrayType array_type, void* external_pointer,
   3260     PretenureFlag pretenure) {
   3261   int size = FixedTypedArrayBase::kHeaderSize;
   3262   AllocationSpace space = SelectSpace(pretenure);
   3263   HeapObject* result = nullptr;
   3264   {
   3265     AllocationResult allocation = AllocateRaw(size, space);
   3266     if (!allocation.To(&result)) return allocation;
   3267   }
   3268 
   3269   result->set_map_no_write_barrier(MapForFixedTypedArray(array_type));
   3270   FixedTypedArrayBase* elements = FixedTypedArrayBase::cast(result);
   3271   elements->set_base_pointer(Smi::kZero, SKIP_WRITE_BARRIER);
   3272   elements->set_external_pointer(external_pointer, SKIP_WRITE_BARRIER);
   3273   elements->set_length(length);
   3274   return elements;
   3275 }
   3276 
   3277 static void ForFixedTypedArray(ExternalArrayType array_type, int* element_size,
   3278                                ElementsKind* element_kind) {
   3279   switch (array_type) {
   3280 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
   3281   case kExternal##Type##Array:                          \
   3282     *element_size = size;                               \
   3283     *element_kind = TYPE##_ELEMENTS;                    \
   3284     return;
   3285 
   3286     TYPED_ARRAYS(TYPED_ARRAY_CASE)
   3287 #undef TYPED_ARRAY_CASE
   3288 
   3289     default:
   3290       *element_size = 0;               // Bogus
   3291       *element_kind = UINT8_ELEMENTS;  // Bogus
   3292       UNREACHABLE();
   3293   }
   3294 }
   3295 
   3296 
   3297 AllocationResult Heap::AllocateFixedTypedArray(int length,
   3298                                                ExternalArrayType array_type,
   3299                                                bool initialize,
   3300                                                PretenureFlag pretenure) {
   3301   int element_size;
   3302   ElementsKind elements_kind;
   3303   ForFixedTypedArray(array_type, &element_size, &elements_kind);
   3304   int size = OBJECT_POINTER_ALIGN(length * element_size +
   3305                                   FixedTypedArrayBase::kDataOffset);
   3306   AllocationSpace space = SelectSpace(pretenure);
   3307 
   3308   HeapObject* object = nullptr;
   3309   AllocationResult allocation = AllocateRaw(
   3310       size, space,
   3311       array_type == kExternalFloat64Array ? kDoubleAligned : kWordAligned);
   3312   if (!allocation.To(&object)) return allocation;
   3313 
   3314   object->set_map_no_write_barrier(MapForFixedTypedArray(array_type));
   3315   FixedTypedArrayBase* elements = FixedTypedArrayBase::cast(object);
   3316   elements->set_base_pointer(elements, SKIP_WRITE_BARRIER);
   3317   elements->set_external_pointer(
   3318       ExternalReference::fixed_typed_array_base_data_offset().address(),
   3319       SKIP_WRITE_BARRIER);
   3320   elements->set_length(length);
   3321   if (initialize) memset(elements->DataPtr(), 0, elements->DataSize());
   3322   return elements;
   3323 }
   3324 
   3325 
   3326 AllocationResult Heap::AllocateCode(int object_size, bool immovable) {
   3327   DCHECK(IsAligned(static_cast<intptr_t>(object_size), kCodeAlignment));
   3328   AllocationResult allocation = AllocateRaw(object_size, CODE_SPACE);
   3329 
   3330   HeapObject* result = nullptr;
   3331   if (!allocation.To(&result)) return allocation;
   3332   if (immovable) {
   3333     Address address = result->address();
   3334     // Code objects which should stay at a fixed address are allocated either
   3335     // in the first page of code space (objects on the first page of each space
   3336     // are never moved) or in large object space.
   3337     if (!code_space_->FirstPage()->Contains(address) &&
   3338         MemoryChunk::FromAddress(address)->owner()->identity() != LO_SPACE) {
   3339       // Discard the first code allocation, which was on a page where it could
   3340       // be moved.
   3341       CreateFillerObjectAt(result->address(), object_size,
   3342                            ClearRecordedSlots::kNo);
   3343       allocation = lo_space_->AllocateRaw(object_size, EXECUTABLE);
   3344       if (!allocation.To(&result)) return allocation;
   3345       OnAllocationEvent(result, object_size);
   3346     }
   3347   }
   3348 
   3349   result->set_map_no_write_barrier(code_map());
   3350   Code* code = Code::cast(result);
   3351   DCHECK(IsAligned(bit_cast<intptr_t>(code->address()), kCodeAlignment));
   3352   DCHECK(!memory_allocator()->code_range()->valid() ||
   3353          memory_allocator()->code_range()->contains(code->address()) ||
   3354          object_size <= code_space()->AreaSize());
   3355   code->set_gc_metadata(Smi::kZero);
   3356   code->set_ic_age(global_ic_age_);
   3357   return code;
   3358 }
   3359 
   3360 
   3361 AllocationResult Heap::CopyCode(Code* code) {
   3362   AllocationResult allocation;
   3363 
   3364   HeapObject* result = nullptr;
   3365   // Allocate an object the same size as the code object.
   3366   int obj_size = code->Size();
   3367   allocation = AllocateRaw(obj_size, CODE_SPACE);
   3368   if (!allocation.To(&result)) return allocation;
   3369 
   3370   // Copy code object.
   3371   Address old_addr = code->address();
   3372   Address new_addr = result->address();
   3373   CopyBlock(new_addr, old_addr, obj_size);
   3374   Code* new_code = Code::cast(result);
   3375 
   3376   // Relocate the copy.
   3377   DCHECK(IsAligned(bit_cast<intptr_t>(new_code->address()), kCodeAlignment));
   3378   DCHECK(!memory_allocator()->code_range()->valid() ||
   3379          memory_allocator()->code_range()->contains(code->address()) ||
   3380          obj_size <= code_space()->AreaSize());
   3381   new_code->Relocate(new_addr - old_addr);
   3382   // We have to iterate over the object and process its pointers when black
   3383   // allocation is on.
   3384   incremental_marking()->IterateBlackObject(new_code);
   3385   // Record all references to embedded objects in the new code object.
   3386   RecordWritesIntoCode(new_code);
   3387   return new_code;
   3388 }
   3389 
   3390 AllocationResult Heap::CopyBytecodeArray(BytecodeArray* bytecode_array) {
   3391   int size = BytecodeArray::SizeFor(bytecode_array->length());
   3392   HeapObject* result = nullptr;
   3393   {
   3394     AllocationResult allocation = AllocateRaw(size, OLD_SPACE);
   3395     if (!allocation.To(&result)) return allocation;
   3396   }
   3397 
   3398   result->set_map_no_write_barrier(bytecode_array_map());
   3399   BytecodeArray* copy = BytecodeArray::cast(result);
   3400   copy->set_length(bytecode_array->length());
   3401   copy->set_frame_size(bytecode_array->frame_size());
   3402   copy->set_parameter_count(bytecode_array->parameter_count());
   3403   copy->set_constant_pool(bytecode_array->constant_pool());
   3404   copy->set_handler_table(bytecode_array->handler_table());
   3405   copy->set_source_position_table(bytecode_array->source_position_table());
   3406   copy->set_interrupt_budget(bytecode_array->interrupt_budget());
   3407   copy->set_osr_loop_nesting_level(bytecode_array->osr_loop_nesting_level());
   3408   bytecode_array->CopyBytecodesTo(copy);
   3409   return copy;
   3410 }
   3411 
   3412 void Heap::InitializeAllocationMemento(AllocationMemento* memento,
   3413                                        AllocationSite* allocation_site) {
   3414   memento->set_map_no_write_barrier(allocation_memento_map());
   3415   DCHECK(allocation_site->map() == allocation_site_map());
   3416   memento->set_allocation_site(allocation_site, SKIP_WRITE_BARRIER);
   3417   if (FLAG_allocation_site_pretenuring) {
   3418     allocation_site->IncrementMementoCreateCount();
   3419   }
   3420 }
   3421 
   3422 
   3423 AllocationResult Heap::Allocate(Map* map, AllocationSpace space,
   3424                                 AllocationSite* allocation_site) {
   3425   DCHECK(gc_state_ == NOT_IN_GC);
   3426   DCHECK(map->instance_type() != MAP_TYPE);
   3427   int size = map->instance_size();
   3428   if (allocation_site != NULL) {
   3429     size += AllocationMemento::kSize;
   3430   }
   3431   HeapObject* result = nullptr;
   3432   AllocationResult allocation = AllocateRaw(size, space);
   3433   if (!allocation.To(&result)) return allocation;
   3434   // No need for write barrier since object is white and map is in old space.
   3435   result->set_map_no_write_barrier(map);
   3436   if (allocation_site != NULL) {
   3437     AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
   3438         reinterpret_cast<Address>(result) + map->instance_size());
   3439     InitializeAllocationMemento(alloc_memento, allocation_site);
   3440   }
   3441   return result;
   3442 }
   3443 
   3444 
   3445 void Heap::InitializeJSObjectFromMap(JSObject* obj, FixedArray* properties,
   3446                                      Map* map) {
   3447   obj->set_properties(properties);
   3448   obj->initialize_elements();
   3449   // TODO(1240798): Initialize the object's body using valid initial values
   3450   // according to the object's initial map.  For example, if the map's
   3451   // instance type is JS_ARRAY_TYPE, the length field should be initialized
   3452   // to a number (e.g. Smi::kZero) and the elements initialized to a
   3453   // fixed array (e.g. Heap::empty_fixed_array()).  Currently, the object
   3454   // verification code has to cope with (temporarily) invalid objects.  See
   3455   // for example, JSArray::JSArrayVerify).
   3456   InitializeJSObjectBody(obj, map, JSObject::kHeaderSize);
   3457 }
   3458 
   3459 
   3460 void Heap::InitializeJSObjectBody(JSObject* obj, Map* map, int start_offset) {
   3461   if (start_offset == map->instance_size()) return;
   3462   DCHECK_LT(start_offset, map->instance_size());
   3463 
   3464   // We cannot always fill with one_pointer_filler_map because objects
   3465   // created from API functions expect their internal fields to be initialized
   3466   // with undefined_value.
   3467   // Pre-allocated fields need to be initialized with undefined_value as well
   3468   // so that object accesses before the constructor completes (e.g. in the
   3469   // debugger) will not cause a crash.
   3470 
   3471   // In case of Array subclassing the |map| could already be transitioned
   3472   // to different elements kind from the initial map on which we track slack.
   3473   bool in_progress = map->IsInobjectSlackTrackingInProgress();
   3474   Object* filler;
   3475   if (in_progress) {
   3476     filler = one_pointer_filler_map();
   3477   } else {
   3478     filler = undefined_value();
   3479   }
   3480   obj->InitializeBody(map, start_offset, Heap::undefined_value(), filler);
   3481   if (in_progress) {
   3482     map->FindRootMap()->InobjectSlackTrackingStep();
   3483   }
   3484 }
   3485 
   3486 
   3487 AllocationResult Heap::AllocateJSObjectFromMap(
   3488     Map* map, PretenureFlag pretenure, AllocationSite* allocation_site) {
   3489   // JSFunctions should be allocated using AllocateFunction to be
   3490   // properly initialized.
   3491   DCHECK(map->instance_type() != JS_FUNCTION_TYPE);
   3492 
   3493   // Both types of global objects should be allocated using
   3494   // AllocateGlobalObject to be properly initialized.
   3495   DCHECK(map->instance_type() != JS_GLOBAL_OBJECT_TYPE);
   3496 
   3497   // Allocate the backing storage for the properties.
   3498   FixedArray* properties = empty_fixed_array();
   3499 
   3500   // Allocate the JSObject.
   3501   AllocationSpace space = SelectSpace(pretenure);
   3502   JSObject* js_obj = nullptr;
   3503   AllocationResult allocation = Allocate(map, space, allocation_site);
   3504   if (!allocation.To(&js_obj)) return allocation;
   3505 
   3506   // Initialize the JSObject.
   3507   InitializeJSObjectFromMap(js_obj, properties, map);
   3508   DCHECK(js_obj->HasFastElements() || js_obj->HasFixedTypedArrayElements() ||
   3509          js_obj->HasFastStringWrapperElements() ||
   3510          js_obj->HasFastArgumentsElements());
   3511   return js_obj;
   3512 }
   3513 
   3514 
   3515 AllocationResult Heap::AllocateJSObject(JSFunction* constructor,
   3516                                         PretenureFlag pretenure,
   3517                                         AllocationSite* allocation_site) {
   3518   DCHECK(constructor->has_initial_map());
   3519 
   3520   // Allocate the object based on the constructors initial map.
   3521   AllocationResult allocation = AllocateJSObjectFromMap(
   3522       constructor->initial_map(), pretenure, allocation_site);
   3523 #ifdef DEBUG
   3524   // Make sure result is NOT a global object if valid.
   3525   HeapObject* obj = nullptr;
   3526   DCHECK(!allocation.To(&obj) || !obj->IsJSGlobalObject());
   3527 #endif
   3528   return allocation;
   3529 }
   3530 
   3531 
   3532 AllocationResult Heap::CopyJSObject(JSObject* source, AllocationSite* site) {
   3533   // Make the clone.
   3534   Map* map = source->map();
   3535 
   3536   // We can only clone regexps, normal objects, api objects, errors or arrays.
   3537   // Copying anything else will break invariants.
   3538   CHECK(map->instance_type() == JS_REGEXP_TYPE ||
   3539         map->instance_type() == JS_OBJECT_TYPE ||
   3540         map->instance_type() == JS_ERROR_TYPE ||
   3541         map->instance_type() == JS_ARRAY_TYPE ||
   3542         map->instance_type() == JS_API_OBJECT_TYPE ||
   3543         map->instance_type() == JS_SPECIAL_API_OBJECT_TYPE);
   3544 
   3545   int object_size = map->instance_size();
   3546   HeapObject* clone = nullptr;
   3547 
   3548   DCHECK(site == NULL || AllocationSite::CanTrack(map->instance_type()));
   3549 
   3550   int adjusted_object_size =
   3551       site != NULL ? object_size + AllocationMemento::kSize : object_size;
   3552   AllocationResult allocation = AllocateRaw(adjusted_object_size, NEW_SPACE);
   3553   if (!allocation.To(&clone)) return allocation;
   3554 
   3555   SLOW_DCHECK(InNewSpace(clone));
   3556   // Since we know the clone is allocated in new space, we can copy
   3557   // the contents without worrying about updating the write barrier.
   3558   CopyBlock(clone->address(), source->address(), object_size);
   3559 
   3560   if (site != NULL) {
   3561     AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
   3562         reinterpret_cast<Address>(clone) + object_size);
   3563     InitializeAllocationMemento(alloc_memento, site);
   3564   }
   3565 
   3566   SLOW_DCHECK(JSObject::cast(clone)->GetElementsKind() ==
   3567               source->GetElementsKind());
   3568   FixedArrayBase* elements = FixedArrayBase::cast(source->elements());
   3569   FixedArray* properties = FixedArray::cast(source->properties());
   3570   // Update elements if necessary.
   3571   if (elements->length() > 0) {
   3572     FixedArrayBase* elem = nullptr;
   3573     {
   3574       AllocationResult allocation;
   3575       if (elements->map() == fixed_cow_array_map()) {
   3576         allocation = FixedArray::cast(elements);
   3577       } else if (source->HasFastDoubleElements()) {
   3578         allocation = CopyFixedDoubleArray(FixedDoubleArray::cast(elements));
   3579       } else {
   3580         allocation = CopyFixedArray(FixedArray::cast(elements));
   3581       }
   3582       if (!allocation.To(&elem)) return allocation;
   3583     }
   3584     JSObject::cast(clone)->set_elements(elem, SKIP_WRITE_BARRIER);
   3585   }
   3586   // Update properties if necessary.
   3587   if (properties->length() > 0) {
   3588     FixedArray* prop = nullptr;
   3589     {
   3590       AllocationResult allocation = CopyFixedArray(properties);
   3591       if (!allocation.To(&prop)) return allocation;
   3592     }
   3593     JSObject::cast(clone)->set_properties(prop, SKIP_WRITE_BARRIER);
   3594   }
   3595   // Return the new clone.
   3596   return clone;
   3597 }
   3598 
   3599 
   3600 static inline void WriteOneByteData(Vector<const char> vector, uint8_t* chars,
   3601                                     int len) {
   3602   // Only works for one byte strings.
   3603   DCHECK(vector.length() == len);
   3604   MemCopy(chars, vector.start(), len);
   3605 }
   3606 
   3607 static inline void WriteTwoByteData(Vector<const char> vector, uint16_t* chars,
   3608                                     int len) {
   3609   const uint8_t* stream = reinterpret_cast<const uint8_t*>(vector.start());
   3610   size_t stream_length = vector.length();
   3611   while (stream_length != 0) {
   3612     size_t consumed = 0;
   3613     uint32_t c = unibrow::Utf8::ValueOf(stream, stream_length, &consumed);
   3614     DCHECK(c != unibrow::Utf8::kBadChar);
   3615     DCHECK(consumed <= stream_length);
   3616     stream_length -= consumed;
   3617     stream += consumed;
   3618     if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
   3619       len -= 2;
   3620       if (len < 0) break;
   3621       *chars++ = unibrow::Utf16::LeadSurrogate(c);
   3622       *chars++ = unibrow::Utf16::TrailSurrogate(c);
   3623     } else {
   3624       len -= 1;
   3625       if (len < 0) break;
   3626       *chars++ = c;
   3627     }
   3628   }
   3629   DCHECK(stream_length == 0);
   3630   DCHECK(len == 0);
   3631 }
   3632 
   3633 
   3634 static inline void WriteOneByteData(String* s, uint8_t* chars, int len) {
   3635   DCHECK(s->length() == len);
   3636   String::WriteToFlat(s, chars, 0, len);
   3637 }
   3638 
   3639 
   3640 static inline void WriteTwoByteData(String* s, uint16_t* chars, int len) {
   3641   DCHECK(s->length() == len);
   3642   String::WriteToFlat(s, chars, 0, len);
   3643 }
   3644 
   3645 
   3646 template <bool is_one_byte, typename T>
   3647 AllocationResult Heap::AllocateInternalizedStringImpl(T t, int chars,
   3648                                                       uint32_t hash_field) {
   3649   DCHECK(chars >= 0);
   3650   // Compute map and object size.
   3651   int size;
   3652   Map* map;
   3653 
   3654   DCHECK_LE(0, chars);
   3655   DCHECK_GE(String::kMaxLength, chars);
   3656   if (is_one_byte) {
   3657     map = one_byte_internalized_string_map();
   3658     size = SeqOneByteString::SizeFor(chars);
   3659   } else {
   3660     map = internalized_string_map();
   3661     size = SeqTwoByteString::SizeFor(chars);
   3662   }
   3663 
   3664   // Allocate string.
   3665   HeapObject* result = nullptr;
   3666   {
   3667     AllocationResult allocation = AllocateRaw(size, OLD_SPACE);
   3668     if (!allocation.To(&result)) return allocation;
   3669   }
   3670 
   3671   result->set_map_no_write_barrier(map);
   3672   // Set length and hash fields of the allocated string.
   3673   String* answer = String::cast(result);
   3674   answer->set_length(chars);
   3675   answer->set_hash_field(hash_field);
   3676 
   3677   DCHECK_EQ(size, answer->Size());
   3678 
   3679   if (is_one_byte) {
   3680     WriteOneByteData(t, SeqOneByteString::cast(answer)->GetChars(), chars);
   3681   } else {
   3682     WriteTwoByteData(t, SeqTwoByteString::cast(answer)->GetChars(), chars);
   3683   }
   3684   return answer;
   3685 }
   3686 
   3687 
   3688 // Need explicit instantiations.
   3689 template AllocationResult Heap::AllocateInternalizedStringImpl<true>(String*,
   3690                                                                      int,
   3691                                                                      uint32_t);
   3692 template AllocationResult Heap::AllocateInternalizedStringImpl<false>(String*,
   3693                                                                       int,
   3694                                                                       uint32_t);
   3695 template AllocationResult Heap::AllocateInternalizedStringImpl<false>(
   3696     Vector<const char>, int, uint32_t);
   3697 
   3698 
   3699 AllocationResult Heap::AllocateRawOneByteString(int length,
   3700                                                 PretenureFlag pretenure) {
   3701   DCHECK_LE(0, length);
   3702   DCHECK_GE(String::kMaxLength, length);
   3703   int size = SeqOneByteString::SizeFor(length);
   3704   DCHECK(size <= SeqOneByteString::kMaxSize);
   3705   AllocationSpace space = SelectSpace(pretenure);
   3706 
   3707   HeapObject* result = nullptr;
   3708   {
   3709     AllocationResult allocation = AllocateRaw(size, space);
   3710     if (!allocation.To(&result)) return allocation;
   3711   }
   3712 
   3713   // Partially initialize the object.
   3714   result->set_map_no_write_barrier(one_byte_string_map());
   3715   String::cast(result)->set_length(length);
   3716   String::cast(result)->set_hash_field(String::kEmptyHashField);
   3717   DCHECK_EQ(size, HeapObject::cast(result)->Size());
   3718 
   3719   return result;
   3720 }
   3721 
   3722 
   3723 AllocationResult Heap::AllocateRawTwoByteString(int length,
   3724                                                 PretenureFlag pretenure) {
   3725   DCHECK_LE(0, length);
   3726   DCHECK_GE(String::kMaxLength, length);
   3727   int size = SeqTwoByteString::SizeFor(length);
   3728   DCHECK(size <= SeqTwoByteString::kMaxSize);
   3729   AllocationSpace space = SelectSpace(pretenure);
   3730 
   3731   HeapObject* result = nullptr;
   3732   {
   3733     AllocationResult allocation = AllocateRaw(size, space);
   3734     if (!allocation.To(&result)) return allocation;
   3735   }
   3736 
   3737   // Partially initialize the object.
   3738   result->set_map_no_write_barrier(string_map());
   3739   String::cast(result)->set_length(length);
   3740   String::cast(result)->set_hash_field(String::kEmptyHashField);
   3741   DCHECK_EQ(size, HeapObject::cast(result)->Size());
   3742   return result;
   3743 }
   3744 
   3745 
   3746 AllocationResult Heap::AllocateEmptyFixedArray() {
   3747   int size = FixedArray::SizeFor(0);
   3748   HeapObject* result = nullptr;
   3749   {
   3750     AllocationResult allocation = AllocateRaw(size, OLD_SPACE);
   3751     if (!allocation.To(&result)) return allocation;
   3752   }
   3753   // Initialize the object.
   3754   result->set_map_no_write_barrier(fixed_array_map());
   3755   FixedArray::cast(result)->set_length(0);
   3756   return result;
   3757 }
   3758 
   3759 AllocationResult Heap::AllocateEmptyScopeInfo() {
   3760   int size = FixedArray::SizeFor(0);
   3761   HeapObject* result = nullptr;
   3762   {
   3763     AllocationResult allocation = AllocateRaw(size, OLD_SPACE);
   3764     if (!allocation.To(&result)) return allocation;
   3765   }
   3766   // Initialize the object.
   3767   result->set_map_no_write_barrier(scope_info_map());
   3768   FixedArray::cast(result)->set_length(0);
   3769   return result;
   3770 }
   3771 
   3772 AllocationResult Heap::CopyAndTenureFixedCOWArray(FixedArray* src) {
   3773   if (!InNewSpace(src)) {
   3774     return src;
   3775   }
   3776 
   3777   int len = src->length();
   3778   HeapObject* obj = nullptr;
   3779   {
   3780     AllocationResult allocation = AllocateRawFixedArray(len, TENURED);
   3781     if (!allocation.To(&obj)) return allocation;
   3782   }
   3783   obj->set_map_no_write_barrier(fixed_array_map());
   3784   FixedArray* result = FixedArray::cast(obj);
   3785   result->set_length(len);
   3786 
   3787   // Copy the content.
   3788   DisallowHeapAllocation no_gc;
   3789   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   3790   for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
   3791 
   3792   // TODO(mvstanton): The map is set twice because of protection against calling
   3793   // set() on a COW FixedArray. Issue v8:3221 created to track this, and
   3794   // we might then be able to remove this whole method.
   3795   HeapObject::cast(obj)->set_map_no_write_barrier(fixed_cow_array_map());
   3796   return result;
   3797 }
   3798 
   3799 
   3800 AllocationResult Heap::AllocateEmptyFixedTypedArray(
   3801     ExternalArrayType array_type) {
   3802   return AllocateFixedTypedArray(0, array_type, false, TENURED);
   3803 }
   3804 
   3805 
   3806 AllocationResult Heap::CopyFixedArrayAndGrow(FixedArray* src, int grow_by,
   3807                                              PretenureFlag pretenure) {
   3808   int old_len = src->length();
   3809   int new_len = old_len + grow_by;
   3810   DCHECK(new_len >= old_len);
   3811   HeapObject* obj = nullptr;
   3812   {
   3813     AllocationResult allocation = AllocateRawFixedArray(new_len, pretenure);
   3814     if (!allocation.To(&obj)) return allocation;
   3815   }
   3816 
   3817   obj->set_map_no_write_barrier(fixed_array_map());
   3818   FixedArray* result = FixedArray::cast(obj);
   3819   result->set_length(new_len);
   3820 
   3821   // Copy the content.
   3822   DisallowHeapAllocation no_gc;
   3823   WriteBarrierMode mode = obj->GetWriteBarrierMode(no_gc);
   3824   for (int i = 0; i < old_len; i++) result->set(i, src->get(i), mode);
   3825   MemsetPointer(result->data_start() + old_len, undefined_value(), grow_by);
   3826   return result;
   3827 }
   3828 
   3829 AllocationResult Heap::CopyFixedArrayUpTo(FixedArray* src, int new_len,
   3830                                           PretenureFlag pretenure) {
   3831   if (new_len == 0) return empty_fixed_array();
   3832 
   3833   DCHECK_LE(new_len, src->length());
   3834 
   3835   HeapObject* obj = nullptr;
   3836   {
   3837     AllocationResult allocation = AllocateRawFixedArray(new_len, pretenure);
   3838     if (!allocation.To(&obj)) return allocation;
   3839   }
   3840   obj->set_map_no_write_barrier(fixed_array_map());
   3841 
   3842   FixedArray* result = FixedArray::cast(obj);
   3843   result->set_length(new_len);
   3844 
   3845   // Copy the content.
   3846   DisallowHeapAllocation no_gc;
   3847   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   3848   for (int i = 0; i < new_len; i++) result->set(i, src->get(i), mode);
   3849   return result;
   3850 }
   3851 
   3852 AllocationResult Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) {
   3853   int len = src->length();
   3854   HeapObject* obj = nullptr;
   3855   {
   3856     AllocationResult allocation = AllocateRawFixedArray(len, NOT_TENURED);
   3857     if (!allocation.To(&obj)) return allocation;
   3858   }
   3859   obj->set_map_no_write_barrier(map);
   3860 
   3861   FixedArray* result = FixedArray::cast(obj);
   3862   DisallowHeapAllocation no_gc;
   3863   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   3864 
   3865   // Eliminate the write barrier if possible.
   3866   if (mode == SKIP_WRITE_BARRIER) {
   3867     CopyBlock(obj->address() + kPointerSize, src->address() + kPointerSize,
   3868               FixedArray::SizeFor(len) - kPointerSize);
   3869     return obj;
   3870   }
   3871 
   3872   // Slow case: Just copy the content one-by-one.
   3873   result->set_length(len);
   3874   for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
   3875   return result;
   3876 }
   3877 
   3878 
   3879 AllocationResult Heap::CopyFixedDoubleArrayWithMap(FixedDoubleArray* src,
   3880                                                    Map* map) {
   3881   int len = src->length();
   3882   HeapObject* obj = nullptr;
   3883   {
   3884     AllocationResult allocation = AllocateRawFixedDoubleArray(len, NOT_TENURED);
   3885     if (!allocation.To(&obj)) return allocation;
   3886   }
   3887   obj->set_map_no_write_barrier(map);
   3888   CopyBlock(obj->address() + FixedDoubleArray::kLengthOffset,
   3889             src->address() + FixedDoubleArray::kLengthOffset,
   3890             FixedDoubleArray::SizeFor(len) - FixedDoubleArray::kLengthOffset);
   3891   return obj;
   3892 }
   3893 
   3894 
   3895 AllocationResult Heap::AllocateRawFixedArray(int length,
   3896                                              PretenureFlag pretenure) {
   3897   if (length < 0 || length > FixedArray::kMaxLength) {
   3898     v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
   3899   }
   3900   int size = FixedArray::SizeFor(length);
   3901   AllocationSpace space = SelectSpace(pretenure);
   3902 
   3903   AllocationResult result = AllocateRaw(size, space);
   3904   if (!result.IsRetry() && size > kMaxRegularHeapObjectSize &&
   3905       FLAG_use_marking_progress_bar) {
   3906     MemoryChunk* chunk =
   3907         MemoryChunk::FromAddress(result.ToObjectChecked()->address());
   3908     chunk->SetFlag(MemoryChunk::HAS_PROGRESS_BAR);
   3909   }
   3910   return result;
   3911 }
   3912 
   3913 
   3914 AllocationResult Heap::AllocateFixedArrayWithFiller(int length,
   3915                                                     PretenureFlag pretenure,
   3916                                                     Object* filler) {
   3917   DCHECK(length >= 0);
   3918   DCHECK(empty_fixed_array()->IsFixedArray());
   3919   if (length == 0) return empty_fixed_array();
   3920 
   3921   DCHECK(!InNewSpace(filler));
   3922   HeapObject* result = nullptr;
   3923   {
   3924     AllocationResult allocation = AllocateRawFixedArray(length, pretenure);
   3925     if (!allocation.To(&result)) return allocation;
   3926   }
   3927 
   3928   result->set_map_no_write_barrier(fixed_array_map());
   3929   FixedArray* array = FixedArray::cast(result);
   3930   array->set_length(length);
   3931   MemsetPointer(array->data_start(), filler, length);
   3932   return array;
   3933 }
   3934 
   3935 
   3936 AllocationResult Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
   3937   return AllocateFixedArrayWithFiller(length, pretenure, undefined_value());
   3938 }
   3939 
   3940 
   3941 AllocationResult Heap::AllocateUninitializedFixedArray(int length) {
   3942   if (length == 0) return empty_fixed_array();
   3943 
   3944   HeapObject* obj = nullptr;
   3945   {
   3946     AllocationResult allocation = AllocateRawFixedArray(length, NOT_TENURED);
   3947     if (!allocation.To(&obj)) return allocation;
   3948   }
   3949 
   3950   obj->set_map_no_write_barrier(fixed_array_map());
   3951   FixedArray::cast(obj)->set_length(length);
   3952   return obj;
   3953 }
   3954 
   3955 
   3956 AllocationResult Heap::AllocateUninitializedFixedDoubleArray(
   3957     int length, PretenureFlag pretenure) {
   3958   if (length == 0) return empty_fixed_array();
   3959 
   3960   HeapObject* elements = nullptr;
   3961   AllocationResult allocation = AllocateRawFixedDoubleArray(length, pretenure);
   3962   if (!allocation.To(&elements)) return allocation;
   3963 
   3964   elements->set_map_no_write_barrier(fixed_double_array_map());
   3965   FixedDoubleArray::cast(elements)->set_length(length);
   3966   return elements;
   3967 }
   3968 
   3969 
   3970 AllocationResult Heap::AllocateRawFixedDoubleArray(int length,
   3971                                                    PretenureFlag pretenure) {
   3972   if (length < 0 || length > FixedDoubleArray::kMaxLength) {
   3973     v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
   3974   }
   3975   int size = FixedDoubleArray::SizeFor(length);
   3976   AllocationSpace space = SelectSpace(pretenure);
   3977 
   3978   HeapObject* object = nullptr;
   3979   {
   3980     AllocationResult allocation = AllocateRaw(size, space, kDoubleAligned);
   3981     if (!allocation.To(&object)) return allocation;
   3982   }
   3983 
   3984   return object;
   3985 }
   3986 
   3987 
   3988 AllocationResult Heap::AllocateSymbol() {
   3989   // Statically ensure that it is safe to allocate symbols in paged spaces.
   3990   STATIC_ASSERT(Symbol::kSize <= kMaxRegularHeapObjectSize);
   3991 
   3992   HeapObject* result = nullptr;
   3993   AllocationResult allocation = AllocateRaw(Symbol::kSize, OLD_SPACE);
   3994   if (!allocation.To(&result)) return allocation;
   3995 
   3996   result->set_map_no_write_barrier(symbol_map());
   3997 
   3998   // Generate a random hash value.
   3999   int hash = isolate()->GenerateIdentityHash(Name::kHashBitMask);
   4000 
   4001   Symbol::cast(result)
   4002       ->set_hash_field(Name::kIsNotArrayIndexMask | (hash << Name::kHashShift));
   4003   Symbol::cast(result)->set_name(undefined_value());
   4004   Symbol::cast(result)->set_flags(0);
   4005 
   4006   DCHECK(!Symbol::cast(result)->is_private());
   4007   return result;
   4008 }
   4009 
   4010 
   4011 AllocationResult Heap::AllocateStruct(InstanceType type) {
   4012   Map* map;
   4013   switch (type) {
   4014 #define MAKE_CASE(NAME, Name, name) \
   4015   case NAME##_TYPE:                 \
   4016     map = name##_map();             \
   4017     break;
   4018     STRUCT_LIST(MAKE_CASE)
   4019 #undef MAKE_CASE
   4020     default:
   4021       UNREACHABLE();
   4022       return exception();
   4023   }
   4024   int size = map->instance_size();
   4025   Struct* result = nullptr;
   4026   {
   4027     AllocationResult allocation = Allocate(map, OLD_SPACE);
   4028     if (!allocation.To(&result)) return allocation;
   4029   }
   4030   result->InitializeBody(size);
   4031   return result;
   4032 }
   4033 
   4034 
   4035 bool Heap::IsHeapIterable() {
   4036   // TODO(hpayer): This function is not correct. Allocation folding in old
   4037   // space breaks the iterability.
   4038   return new_space_top_after_last_gc_ == new_space()->top();
   4039 }
   4040 
   4041 
   4042 void Heap::MakeHeapIterable() {
   4043   DCHECK(AllowHeapAllocation::IsAllowed());
   4044   if (!IsHeapIterable()) {
   4045     CollectAllGarbage(kMakeHeapIterableMask,
   4046                       GarbageCollectionReason::kMakeHeapIterable);
   4047   }
   4048   if (mark_compact_collector()->sweeping_in_progress()) {
   4049     mark_compact_collector()->EnsureSweepingCompleted();
   4050   }
   4051   DCHECK(IsHeapIterable());
   4052 }
   4053 
   4054 
   4055 static double ComputeMutatorUtilization(double mutator_speed, double gc_speed) {
   4056   const double kMinMutatorUtilization = 0.0;
   4057   const double kConservativeGcSpeedInBytesPerMillisecond = 200000;
   4058   if (mutator_speed == 0) return kMinMutatorUtilization;
   4059   if (gc_speed == 0) gc_speed = kConservativeGcSpeedInBytesPerMillisecond;
   4060   // Derivation:
   4061   // mutator_utilization = mutator_time / (mutator_time + gc_time)
   4062   // mutator_time = 1 / mutator_speed
   4063   // gc_time = 1 / gc_speed
   4064   // mutator_utilization = (1 / mutator_speed) /
   4065   //                       (1 / mutator_speed + 1 / gc_speed)
   4066   // mutator_utilization = gc_speed / (mutator_speed + gc_speed)
   4067   return gc_speed / (mutator_speed + gc_speed);
   4068 }
   4069 
   4070 
   4071 double Heap::YoungGenerationMutatorUtilization() {
   4072   double mutator_speed = static_cast<double>(
   4073       tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond());
   4074   double gc_speed =
   4075       tracer()->ScavengeSpeedInBytesPerMillisecond(kForSurvivedObjects);
   4076   double result = ComputeMutatorUtilization(mutator_speed, gc_speed);
   4077   if (FLAG_trace_mutator_utilization) {
   4078     isolate()->PrintWithTimestamp(
   4079         "Young generation mutator utilization = %.3f ("
   4080         "mutator_speed=%.f, gc_speed=%.f)\n",
   4081         result, mutator_speed, gc_speed);
   4082   }
   4083   return result;
   4084 }
   4085 
   4086 
   4087 double Heap::OldGenerationMutatorUtilization() {
   4088   double mutator_speed = static_cast<double>(
   4089       tracer()->OldGenerationAllocationThroughputInBytesPerMillisecond());
   4090   double gc_speed = static_cast<double>(
   4091       tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond());
   4092   double result = ComputeMutatorUtilization(mutator_speed, gc_speed);
   4093   if (FLAG_trace_mutator_utilization) {
   4094     isolate()->PrintWithTimestamp(
   4095         "Old generation mutator utilization = %.3f ("
   4096         "mutator_speed=%.f, gc_speed=%.f)\n",
   4097         result, mutator_speed, gc_speed);
   4098   }
   4099   return result;
   4100 }
   4101 
   4102 
   4103 bool Heap::HasLowYoungGenerationAllocationRate() {
   4104   const double high_mutator_utilization = 0.993;
   4105   return YoungGenerationMutatorUtilization() > high_mutator_utilization;
   4106 }
   4107 
   4108 
   4109 bool Heap::HasLowOldGenerationAllocationRate() {
   4110   const double high_mutator_utilization = 0.993;
   4111   return OldGenerationMutatorUtilization() > high_mutator_utilization;
   4112 }
   4113 
   4114 
   4115 bool Heap::HasLowAllocationRate() {
   4116   return HasLowYoungGenerationAllocationRate() &&
   4117          HasLowOldGenerationAllocationRate();
   4118 }
   4119 
   4120 
   4121 bool Heap::HasHighFragmentation() {
   4122   size_t used = PromotedSpaceSizeOfObjects();
   4123   size_t committed = CommittedOldGenerationMemory();
   4124   return HasHighFragmentation(used, committed);
   4125 }
   4126 
   4127 bool Heap::HasHighFragmentation(size_t used, size_t committed) {
   4128   const size_t kSlack = 16 * MB;
   4129   // Fragmentation is high if committed > 2 * used + kSlack.
   4130   // Rewrite the exression to avoid overflow.
   4131   DCHECK_GE(committed, used);
   4132   return committed - used > used + kSlack;
   4133 }
   4134 
   4135 bool Heap::ShouldOptimizeForMemoryUsage() {
   4136   return FLAG_optimize_for_size || isolate()->IsIsolateInBackground() ||
   4137          HighMemoryPressure() || IsLowMemoryDevice();
   4138 }
   4139 
   4140 void Heap::ActivateMemoryReducerIfNeeded() {
   4141   // Activate memory reducer when switching to background if
   4142   // - there was no mark compact since the start.
   4143   // - the committed memory can be potentially reduced.
   4144   // 2 pages for the old, code, and map space + 1 page for new space.
   4145   const int kMinCommittedMemory = 7 * Page::kPageSize;
   4146   if (ms_count_ == 0 && CommittedMemory() > kMinCommittedMemory &&
   4147       isolate()->IsIsolateInBackground()) {
   4148     MemoryReducer::Event event;
   4149     event.type = MemoryReducer::kPossibleGarbage;
   4150     event.time_ms = MonotonicallyIncreasingTimeInMs();
   4151     memory_reducer_->NotifyPossibleGarbage(event);
   4152   }
   4153 }
   4154 
   4155 void Heap::ReduceNewSpaceSize() {
   4156   // TODO(ulan): Unify this constant with the similar constant in
   4157   // GCIdleTimeHandler once the change is merged to 4.5.
   4158   static const size_t kLowAllocationThroughput = 1000;
   4159   const double allocation_throughput =
   4160       tracer()->CurrentAllocationThroughputInBytesPerMillisecond();
   4161 
   4162   if (FLAG_predictable) return;
   4163 
   4164   if (ShouldReduceMemory() ||
   4165       ((allocation_throughput != 0) &&
   4166        (allocation_throughput < kLowAllocationThroughput))) {
   4167     new_space_->Shrink();
   4168     UncommitFromSpace();
   4169   }
   4170 }
   4171 
   4172 bool Heap::MarkingDequesAreEmpty() {
   4173   return mark_compact_collector()->marking_deque()->IsEmpty() &&
   4174          (!UsingEmbedderHeapTracer() ||
   4175           (wrappers_to_trace() == 0 &&
   4176            embedder_heap_tracer()->NumberOfWrappersToTrace() == 0));
   4177 }
   4178 
   4179 void Heap::FinalizeIncrementalMarkingIfComplete(
   4180     GarbageCollectionReason gc_reason) {
   4181   if (incremental_marking()->IsMarking() &&
   4182       (incremental_marking()->IsReadyToOverApproximateWeakClosure() ||
   4183        (!incremental_marking()->finalize_marking_completed() &&
   4184         MarkingDequesAreEmpty()))) {
   4185     FinalizeIncrementalMarking(gc_reason);
   4186   } else if (incremental_marking()->IsComplete() || MarkingDequesAreEmpty()) {
   4187     CollectAllGarbage(current_gc_flags_, gc_reason);
   4188   }
   4189 }
   4190 
   4191 bool Heap::TryFinalizeIdleIncrementalMarking(
   4192     double idle_time_in_ms, GarbageCollectionReason gc_reason) {
   4193   size_t size_of_objects = static_cast<size_t>(SizeOfObjects());
   4194   double final_incremental_mark_compact_speed_in_bytes_per_ms =
   4195       tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond();
   4196   if (incremental_marking()->IsReadyToOverApproximateWeakClosure() ||
   4197       (!incremental_marking()->finalize_marking_completed() &&
   4198        MarkingDequesAreEmpty() &&
   4199        gc_idle_time_handler_->ShouldDoOverApproximateWeakClosure(
   4200            idle_time_in_ms))) {
   4201     FinalizeIncrementalMarking(gc_reason);
   4202     return true;
   4203   } else if (incremental_marking()->IsComplete() ||
   4204              (MarkingDequesAreEmpty() &&
   4205               gc_idle_time_handler_->ShouldDoFinalIncrementalMarkCompact(
   4206                   idle_time_in_ms, size_of_objects,
   4207                   final_incremental_mark_compact_speed_in_bytes_per_ms))) {
   4208     CollectAllGarbage(current_gc_flags_, gc_reason);
   4209     return true;
   4210   }
   4211   return false;
   4212 }
   4213 
   4214 void Heap::RegisterReservationsForBlackAllocation(Reservation* reservations) {
   4215   // TODO(hpayer): We do not have to iterate reservations on black objects
   4216   // for marking. We just have to execute the special visiting side effect
   4217   // code that adds objects to global data structures, e.g. for array buffers.
   4218 
   4219   // Code space, map space, and large object space do not use black pages.
   4220   // Hence we have to color all objects of the reservation first black to avoid
   4221   // unnecessary marking deque load.
   4222   if (incremental_marking()->black_allocation()) {
   4223     for (int i = OLD_SPACE; i < Serializer::kNumberOfSpaces; i++) {
   4224       const Heap::Reservation& res = reservations[i];
   4225       for (auto& chunk : res) {
   4226         Address addr = chunk.start;
   4227         while (addr < chunk.end) {
   4228           HeapObject* obj = HeapObject::FromAddress(addr);
   4229           Marking::MarkBlack(ObjectMarking::MarkBitFrom(obj));
   4230           addr += obj->Size();
   4231         }
   4232       }
   4233     }
   4234     for (int i = OLD_SPACE; i < Serializer::kNumberOfSpaces; i++) {
   4235       const Heap::Reservation& res = reservations[i];
   4236       for (auto& chunk : res) {
   4237         Address addr = chunk.start;
   4238         while (addr < chunk.end) {
   4239           HeapObject* obj = HeapObject::FromAddress(addr);
   4240           incremental_marking()->IterateBlackObject(obj);
   4241           addr += obj->Size();
   4242         }
   4243       }
   4244     }
   4245   }
   4246 }
   4247 
   4248 GCIdleTimeHeapState Heap::ComputeHeapState() {
   4249   GCIdleTimeHeapState heap_state;
   4250   heap_state.contexts_disposed = contexts_disposed_;
   4251   heap_state.contexts_disposal_rate =
   4252       tracer()->ContextDisposalRateInMilliseconds();
   4253   heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects());
   4254   heap_state.incremental_marking_stopped = incremental_marking()->IsStopped();
   4255   return heap_state;
   4256 }
   4257 
   4258 
   4259 bool Heap::PerformIdleTimeAction(GCIdleTimeAction action,
   4260                                  GCIdleTimeHeapState heap_state,
   4261                                  double deadline_in_ms) {
   4262   bool result = false;
   4263   switch (action.type) {
   4264     case DONE:
   4265       result = true;
   4266       break;
   4267     case DO_INCREMENTAL_STEP: {
   4268       const double remaining_idle_time_in_ms =
   4269           incremental_marking()->AdvanceIncrementalMarking(
   4270               deadline_in_ms, IncrementalMarking::NO_GC_VIA_STACK_GUARD,
   4271               IncrementalMarking::FORCE_COMPLETION, StepOrigin::kTask);
   4272       if (remaining_idle_time_in_ms > 0.0) {
   4273         TryFinalizeIdleIncrementalMarking(
   4274             remaining_idle_time_in_ms,
   4275             GarbageCollectionReason::kFinalizeMarkingViaTask);
   4276       }
   4277       result = incremental_marking()->IsStopped();
   4278       break;
   4279     }
   4280     case DO_FULL_GC: {
   4281       DCHECK(contexts_disposed_ > 0);
   4282       HistogramTimerScope scope(isolate_->counters()->gc_context());
   4283       TRACE_EVENT0("v8", "V8.GCContext");
   4284       CollectAllGarbage(kNoGCFlags, GarbageCollectionReason::kContextDisposal);
   4285       break;
   4286     }
   4287     case DO_NOTHING:
   4288       break;
   4289   }
   4290 
   4291   return result;
   4292 }
   4293 
   4294 
   4295 void Heap::IdleNotificationEpilogue(GCIdleTimeAction action,
   4296                                     GCIdleTimeHeapState heap_state,
   4297                                     double start_ms, double deadline_in_ms) {
   4298   double idle_time_in_ms = deadline_in_ms - start_ms;
   4299   double current_time = MonotonicallyIncreasingTimeInMs();
   4300   last_idle_notification_time_ = current_time;
   4301   double deadline_difference = deadline_in_ms - current_time;
   4302 
   4303   contexts_disposed_ = 0;
   4304 
   4305   isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample(
   4306       static_cast<int>(idle_time_in_ms));
   4307 
   4308   if (deadline_in_ms - start_ms >
   4309       GCIdleTimeHandler::kMaxFrameRenderingIdleTime) {
   4310     int committed_memory = static_cast<int>(CommittedMemory() / KB);
   4311     int used_memory = static_cast<int>(heap_state.size_of_objects / KB);
   4312     isolate()->counters()->aggregated_memory_heap_committed()->AddSample(
   4313         start_ms, committed_memory);
   4314     isolate()->counters()->aggregated_memory_heap_used()->AddSample(
   4315         start_ms, used_memory);
   4316   }
   4317 
   4318   if (deadline_difference >= 0) {
   4319     if (action.type != DONE && action.type != DO_NOTHING) {
   4320       isolate()->counters()->gc_idle_time_limit_undershot()->AddSample(
   4321           static_cast<int>(deadline_difference));
   4322     }
   4323   } else {
   4324     isolate()->counters()->gc_idle_time_limit_overshot()->AddSample(
   4325         static_cast<int>(-deadline_difference));
   4326   }
   4327 
   4328   if ((FLAG_trace_idle_notification && action.type > DO_NOTHING) ||
   4329       FLAG_trace_idle_notification_verbose) {
   4330     isolate_->PrintWithTimestamp(
   4331         "Idle notification: requested idle time %.2f ms, used idle time %.2f "
   4332         "ms, deadline usage %.2f ms [",
   4333         idle_time_in_ms, idle_time_in_ms - deadline_difference,
   4334         deadline_difference);
   4335     action.Print();
   4336     PrintF("]");
   4337     if (FLAG_trace_idle_notification_verbose) {
   4338       PrintF("[");
   4339       heap_state.Print();
   4340       PrintF("]");
   4341     }
   4342     PrintF("\n");
   4343   }
   4344 }
   4345 
   4346 
   4347 double Heap::MonotonicallyIncreasingTimeInMs() {
   4348   return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() *
   4349          static_cast<double>(base::Time::kMillisecondsPerSecond);
   4350 }
   4351 
   4352 
   4353 bool Heap::IdleNotification(int idle_time_in_ms) {
   4354   return IdleNotification(
   4355       V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() +
   4356       (static_cast<double>(idle_time_in_ms) /
   4357        static_cast<double>(base::Time::kMillisecondsPerSecond)));
   4358 }
   4359 
   4360 
   4361 bool Heap::IdleNotification(double deadline_in_seconds) {
   4362   CHECK(HasBeenSetUp());
   4363   double deadline_in_ms =
   4364       deadline_in_seconds *
   4365       static_cast<double>(base::Time::kMillisecondsPerSecond);
   4366   HistogramTimerScope idle_notification_scope(
   4367       isolate_->counters()->gc_idle_notification());
   4368   TRACE_EVENT0("v8", "V8.GCIdleNotification");
   4369   double start_ms = MonotonicallyIncreasingTimeInMs();
   4370   double idle_time_in_ms = deadline_in_ms - start_ms;
   4371 
   4372   tracer()->SampleAllocation(start_ms, NewSpaceAllocationCounter(),
   4373                              OldGenerationAllocationCounter());
   4374 
   4375   GCIdleTimeHeapState heap_state = ComputeHeapState();
   4376 
   4377   GCIdleTimeAction action =
   4378       gc_idle_time_handler_->Compute(idle_time_in_ms, heap_state);
   4379 
   4380   bool result = PerformIdleTimeAction(action, heap_state, deadline_in_ms);
   4381 
   4382   IdleNotificationEpilogue(action, heap_state, start_ms, deadline_in_ms);
   4383   return result;
   4384 }
   4385 
   4386 
   4387 bool Heap::RecentIdleNotificationHappened() {
   4388   return (last_idle_notification_time_ +
   4389           GCIdleTimeHandler::kMaxScheduledIdleTime) >
   4390          MonotonicallyIncreasingTimeInMs();
   4391 }
   4392 
   4393 class MemoryPressureInterruptTask : public CancelableTask {
   4394  public:
   4395   explicit MemoryPressureInterruptTask(Heap* heap)
   4396       : CancelableTask(heap->isolate()), heap_(heap) {}
   4397 
   4398   virtual ~MemoryPressureInterruptTask() {}
   4399 
   4400  private:
   4401   // v8::internal::CancelableTask overrides.
   4402   void RunInternal() override { heap_->CheckMemoryPressure(); }
   4403 
   4404   Heap* heap_;
   4405   DISALLOW_COPY_AND_ASSIGN(MemoryPressureInterruptTask);
   4406 };
   4407 
   4408 void Heap::CheckMemoryPressure() {
   4409   if (HighMemoryPressure()) {
   4410     if (isolate()->concurrent_recompilation_enabled()) {
   4411       // The optimizing compiler may be unnecessarily holding on to memory.
   4412       DisallowHeapAllocation no_recursive_gc;
   4413       isolate()->optimizing_compile_dispatcher()->Flush(
   4414           OptimizingCompileDispatcher::BlockingBehavior::kDontBlock);
   4415     }
   4416   }
   4417   if (memory_pressure_level_.Value() == MemoryPressureLevel::kCritical) {
   4418     CollectGarbageOnMemoryPressure();
   4419   } else if (memory_pressure_level_.Value() == MemoryPressureLevel::kModerate) {
   4420     if (FLAG_incremental_marking && incremental_marking()->IsStopped()) {
   4421       StartIncrementalMarking(kReduceMemoryFootprintMask,
   4422                               GarbageCollectionReason::kMemoryPressure);
   4423     }
   4424   }
   4425   MemoryReducer::Event event;
   4426   event.type = MemoryReducer::kPossibleGarbage;
   4427   event.time_ms = MonotonicallyIncreasingTimeInMs();
   4428   memory_reducer_->NotifyPossibleGarbage(event);
   4429 }
   4430 
   4431 void Heap::CollectGarbageOnMemoryPressure() {
   4432   const int kGarbageThresholdInBytes = 8 * MB;
   4433   const double kGarbageThresholdAsFractionOfTotalMemory = 0.1;
   4434   // This constant is the maximum response time in RAIL performance model.
   4435   const double kMaxMemoryPressurePauseMs = 100;
   4436 
   4437   double start = MonotonicallyIncreasingTimeInMs();
   4438   CollectAllGarbage(kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask,
   4439                     GarbageCollectionReason::kMemoryPressure,
   4440                     kGCCallbackFlagCollectAllAvailableGarbage);
   4441   double end = MonotonicallyIncreasingTimeInMs();
   4442 
   4443   // Estimate how much memory we can free.
   4444   int64_t potential_garbage =
   4445       (CommittedMemory() - SizeOfObjects()) + external_memory_;
   4446   // If we can potentially free large amount of memory, then start GC right
   4447   // away instead of waiting for memory reducer.
   4448   if (potential_garbage >= kGarbageThresholdInBytes &&
   4449       potential_garbage >=
   4450           CommittedMemory() * kGarbageThresholdAsFractionOfTotalMemory) {
   4451     // If we spent less than half of the time budget, then perform full GC
   4452     // Otherwise, start incremental marking.
   4453     if (end - start < kMaxMemoryPressurePauseMs / 2) {
   4454       CollectAllGarbage(
   4455           kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask,
   4456           GarbageCollectionReason::kMemoryPressure,
   4457           kGCCallbackFlagCollectAllAvailableGarbage);
   4458     } else {
   4459       if (FLAG_incremental_marking && incremental_marking()->IsStopped()) {
   4460         StartIncrementalMarking(kReduceMemoryFootprintMask,
   4461                                 GarbageCollectionReason::kMemoryPressure);
   4462       }
   4463     }
   4464   }
   4465 }
   4466 
   4467 void Heap::MemoryPressureNotification(MemoryPressureLevel level,
   4468                                       bool is_isolate_locked) {
   4469   MemoryPressureLevel previous = memory_pressure_level_.Value();
   4470   memory_pressure_level_.SetValue(level);
   4471   if ((previous != MemoryPressureLevel::kCritical &&
   4472        level == MemoryPressureLevel::kCritical) ||
   4473       (previous == MemoryPressureLevel::kNone &&
   4474        level == MemoryPressureLevel::kModerate)) {
   4475     if (is_isolate_locked) {
   4476       CheckMemoryPressure();
   4477     } else {
   4478       ExecutionAccess access(isolate());
   4479       isolate()->stack_guard()->RequestGC();
   4480       V8::GetCurrentPlatform()->CallOnForegroundThread(
   4481           reinterpret_cast<v8::Isolate*>(isolate()),
   4482           new MemoryPressureInterruptTask(this));
   4483     }
   4484   }
   4485 }
   4486 
   4487 void Heap::CollectCodeStatistics() {
   4488   CodeStatistics::ResetCodeAndMetadataStatistics(isolate());
   4489   // We do not look for code in new space, or map space.  If code
   4490   // somehow ends up in those spaces, we would miss it here.
   4491   CodeStatistics::CollectCodeStatistics(code_space_, isolate());
   4492   CodeStatistics::CollectCodeStatistics(old_space_, isolate());
   4493   CodeStatistics::CollectCodeStatistics(lo_space_, isolate());
   4494 }
   4495 
   4496 #ifdef DEBUG
   4497 
   4498 void Heap::Print() {
   4499   if (!HasBeenSetUp()) return;
   4500   isolate()->PrintStack(stdout);
   4501   AllSpaces spaces(this);
   4502   for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
   4503     space->Print();
   4504   }
   4505 }
   4506 
   4507 
   4508 void Heap::ReportCodeStatistics(const char* title) {
   4509   PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title);
   4510   CollectCodeStatistics();
   4511   CodeStatistics::ReportCodeStatistics(isolate());
   4512 }
   4513 
   4514 
   4515 // This function expects that NewSpace's allocated objects histogram is
   4516 // populated (via a call to CollectStatistics or else as a side effect of a
   4517 // just-completed scavenge collection).
   4518 void Heap::ReportHeapStatistics(const char* title) {
   4519   USE(title);
   4520   PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n", title,
   4521          gc_count_);
   4522   PrintF("old_generation_allocation_limit_ %" V8PRIdPTR "\n",
   4523          old_generation_allocation_limit_);
   4524 
   4525   PrintF("\n");
   4526   PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles(isolate_));
   4527   isolate_->global_handles()->PrintStats();
   4528   PrintF("\n");
   4529 
   4530   PrintF("Heap statistics : ");
   4531   memory_allocator()->ReportStatistics();
   4532   PrintF("To space : ");
   4533   new_space_->ReportStatistics();
   4534   PrintF("Old space : ");
   4535   old_space_->ReportStatistics();
   4536   PrintF("Code space : ");
   4537   code_space_->ReportStatistics();
   4538   PrintF("Map space : ");
   4539   map_space_->ReportStatistics();
   4540   PrintF("Large object space : ");
   4541   lo_space_->ReportStatistics();
   4542   PrintF(">>>>>> ========================================= >>>>>>\n");
   4543 }
   4544 
   4545 #endif  // DEBUG
   4546 
   4547 const char* Heap::GarbageCollectionReasonToString(
   4548     GarbageCollectionReason gc_reason) {
   4549   switch (gc_reason) {
   4550     case GarbageCollectionReason::kAllocationFailure:
   4551       return "allocation failure";
   4552     case GarbageCollectionReason::kAllocationLimit:
   4553       return "allocation limit";
   4554     case GarbageCollectionReason::kContextDisposal:
   4555       return "context disposal";
   4556     case GarbageCollectionReason::kCountersExtension:
   4557       return "counters extension";
   4558     case GarbageCollectionReason::kDebugger:
   4559       return "debugger";
   4560     case GarbageCollectionReason::kDeserializer:
   4561       return "deserialize";
   4562     case GarbageCollectionReason::kExternalMemoryPressure:
   4563       return "external memory pressure";
   4564     case GarbageCollectionReason::kFinalizeMarkingViaStackGuard:
   4565       return "finalize incremental marking via stack guard";
   4566     case GarbageCollectionReason::kFinalizeMarkingViaTask:
   4567       return "finalize incremental marking via task";
   4568     case GarbageCollectionReason::kFullHashtable:
   4569       return "full hash-table";
   4570     case GarbageCollectionReason::kHeapProfiler:
   4571       return "heap profiler";
   4572     case GarbageCollectionReason::kIdleTask:
   4573       return "idle task";
   4574     case GarbageCollectionReason::kLastResort:
   4575       return "last resort";
   4576     case GarbageCollectionReason::kLowMemoryNotification:
   4577       return "low memory notification";
   4578     case GarbageCollectionReason::kMakeHeapIterable:
   4579       return "make heap iterable";
   4580     case GarbageCollectionReason::kMemoryPressure:
   4581       return "memory pressure";
   4582     case GarbageCollectionReason::kMemoryReducer:
   4583       return "memory reducer";
   4584     case GarbageCollectionReason::kRuntime:
   4585       return "runtime";
   4586     case GarbageCollectionReason::kSamplingProfiler:
   4587       return "sampling profiler";
   4588     case GarbageCollectionReason::kSnapshotCreator:
   4589       return "snapshot creator";
   4590     case GarbageCollectionReason::kTesting:
   4591       return "testing";
   4592     case GarbageCollectionReason::kUnknown:
   4593       return "unknown";
   4594   }
   4595   UNREACHABLE();
   4596   return "";
   4597 }
   4598 
   4599 bool Heap::Contains(HeapObject* value) {
   4600   if (memory_allocator()->IsOutsideAllocatedSpace(value->address())) {
   4601     return false;
   4602   }
   4603   return HasBeenSetUp() &&
   4604          (new_space_->ToSpaceContains(value) || old_space_->Contains(value) ||
   4605           code_space_->Contains(value) || map_space_->Contains(value) ||
   4606           lo_space_->Contains(value));
   4607 }
   4608 
   4609 bool Heap::ContainsSlow(Address addr) {
   4610   if (memory_allocator()->IsOutsideAllocatedSpace(addr)) {
   4611     return false;
   4612   }
   4613   return HasBeenSetUp() &&
   4614          (new_space_->ToSpaceContainsSlow(addr) ||
   4615           old_space_->ContainsSlow(addr) || code_space_->ContainsSlow(addr) ||
   4616           map_space_->ContainsSlow(addr) || lo_space_->ContainsSlow(addr));
   4617 }
   4618 
   4619 bool Heap::InSpace(HeapObject* value, AllocationSpace space) {
   4620   if (memory_allocator()->IsOutsideAllocatedSpace(value->address())) {
   4621     return false;
   4622   }
   4623   if (!HasBeenSetUp()) return false;
   4624 
   4625   switch (space) {
   4626     case NEW_SPACE:
   4627       return new_space_->ToSpaceContains(value);
   4628     case OLD_SPACE:
   4629       return old_space_->Contains(value);
   4630     case CODE_SPACE:
   4631       return code_space_->Contains(value);
   4632     case MAP_SPACE:
   4633       return map_space_->Contains(value);
   4634     case LO_SPACE:
   4635       return lo_space_->Contains(value);
   4636   }
   4637   UNREACHABLE();
   4638   return false;
   4639 }
   4640 
   4641 bool Heap::InSpaceSlow(Address addr, AllocationSpace space) {
   4642   if (memory_allocator()->IsOutsideAllocatedSpace(addr)) {
   4643     return false;
   4644   }
   4645   if (!HasBeenSetUp()) return false;
   4646 
   4647   switch (space) {
   4648     case NEW_SPACE:
   4649       return new_space_->ToSpaceContainsSlow(addr);
   4650     case OLD_SPACE:
   4651       return old_space_->ContainsSlow(addr);
   4652     case CODE_SPACE:
   4653       return code_space_->ContainsSlow(addr);
   4654     case MAP_SPACE:
   4655       return map_space_->ContainsSlow(addr);
   4656     case LO_SPACE:
   4657       return lo_space_->ContainsSlow(addr);
   4658   }
   4659   UNREACHABLE();
   4660   return false;
   4661 }
   4662 
   4663 
   4664 bool Heap::IsValidAllocationSpace(AllocationSpace space) {
   4665   switch (space) {
   4666     case NEW_SPACE:
   4667     case OLD_SPACE:
   4668     case CODE_SPACE:
   4669     case MAP_SPACE:
   4670     case LO_SPACE:
   4671       return true;
   4672     default:
   4673       return false;
   4674   }
   4675 }
   4676 
   4677 
   4678 bool Heap::RootIsImmortalImmovable(int root_index) {
   4679   switch (root_index) {
   4680 #define IMMORTAL_IMMOVABLE_ROOT(name) case Heap::k##name##RootIndex:
   4681     IMMORTAL_IMMOVABLE_ROOT_LIST(IMMORTAL_IMMOVABLE_ROOT)
   4682 #undef IMMORTAL_IMMOVABLE_ROOT
   4683 #define INTERNALIZED_STRING(name, value) case Heap::k##name##RootIndex:
   4684     INTERNALIZED_STRING_LIST(INTERNALIZED_STRING)
   4685 #undef INTERNALIZED_STRING
   4686 #define STRING_TYPE(NAME, size, name, Name) case Heap::k##Name##MapRootIndex:
   4687     STRING_TYPE_LIST(STRING_TYPE)
   4688 #undef STRING_TYPE
   4689     return true;
   4690     default:
   4691       return false;
   4692   }
   4693 }
   4694 
   4695 
   4696 #ifdef VERIFY_HEAP
   4697 void Heap::Verify() {
   4698   CHECK(HasBeenSetUp());
   4699   HandleScope scope(isolate());
   4700 
   4701   if (mark_compact_collector()->sweeping_in_progress()) {
   4702     // We have to wait here for the sweeper threads to have an iterable heap.
   4703     mark_compact_collector()->EnsureSweepingCompleted();
   4704   }
   4705 
   4706   VerifyPointersVisitor visitor;
   4707   IterateRoots(&visitor, VISIT_ONLY_STRONG);
   4708 
   4709   VerifySmisVisitor smis_visitor;
   4710   IterateSmiRoots(&smis_visitor);
   4711 
   4712   new_space_->Verify();
   4713 
   4714   old_space_->Verify(&visitor);
   4715   map_space_->Verify(&visitor);
   4716 
   4717   VerifyPointersVisitor no_dirty_regions_visitor;
   4718   code_space_->Verify(&no_dirty_regions_visitor);
   4719 
   4720   lo_space_->Verify();
   4721 
   4722   mark_compact_collector()->VerifyWeakEmbeddedObjectsInCode();
   4723   if (FLAG_omit_map_checks_for_leaf_maps) {
   4724     mark_compact_collector()->VerifyOmittedMapChecks();
   4725   }
   4726 }
   4727 #endif
   4728 
   4729 
   4730 void Heap::ZapFromSpace() {
   4731   if (!new_space_->IsFromSpaceCommitted()) return;
   4732   for (Page* page : NewSpacePageRange(new_space_->FromSpaceStart(),
   4733                                       new_space_->FromSpaceEnd())) {
   4734     for (Address cursor = page->area_start(), limit = page->area_end();
   4735          cursor < limit; cursor += kPointerSize) {
   4736       Memory::Address_at(cursor) = kFromSpaceZapValue;
   4737     }
   4738   }
   4739 }
   4740 
   4741 class IterateAndScavengePromotedObjectsVisitor final : public ObjectVisitor {
   4742  public:
   4743   IterateAndScavengePromotedObjectsVisitor(Heap* heap, HeapObject* target,
   4744                                            bool record_slots)
   4745       : heap_(heap), target_(target), record_slots_(record_slots) {}
   4746 
   4747   inline void VisitPointers(Object** start, Object** end) override {
   4748     Address slot_address = reinterpret_cast<Address>(start);
   4749     Page* page = Page::FromAddress(slot_address);
   4750 
   4751     while (slot_address < reinterpret_cast<Address>(end)) {
   4752       Object** slot = reinterpret_cast<Object**>(slot_address);
   4753       Object* target = *slot;
   4754 
   4755       if (target->IsHeapObject()) {
   4756         if (heap_->InFromSpace(target)) {
   4757           Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(slot),
   4758                                     HeapObject::cast(target));
   4759           target = *slot;
   4760           if (heap_->InNewSpace(target)) {
   4761             SLOW_DCHECK(heap_->InToSpace(target));
   4762             SLOW_DCHECK(target->IsHeapObject());
   4763             RememberedSet<OLD_TO_NEW>::Insert(page, slot_address);
   4764           }
   4765           SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(
   4766               HeapObject::cast(target)));
   4767         } else if (record_slots_ &&
   4768                    MarkCompactCollector::IsOnEvacuationCandidate(
   4769                        HeapObject::cast(target))) {
   4770           heap_->mark_compact_collector()->RecordSlot(target_, slot, target);
   4771         }
   4772       }
   4773 
   4774       slot_address += kPointerSize;
   4775     }
   4776   }
   4777 
   4778   inline void VisitCodeEntry(Address code_entry_slot) override {
   4779     // Black allocation requires us to process objects referenced by
   4780     // promoted objects.
   4781     if (heap_->incremental_marking()->black_allocation()) {
   4782       Code* code = Code::cast(Code::GetObjectFromEntryAddress(code_entry_slot));
   4783       IncrementalMarking::MarkGrey(heap_, code);
   4784     }
   4785   }
   4786 
   4787  private:
   4788   Heap* heap_;
   4789   HeapObject* target_;
   4790   bool record_slots_;
   4791 };
   4792 
   4793 void Heap::IterateAndScavengePromotedObject(HeapObject* target, int size,
   4794                                             bool was_marked_black) {
   4795   // We are not collecting slots on new space objects during mutation
   4796   // thus we have to scan for pointers to evacuation candidates when we
   4797   // promote objects. But we should not record any slots in non-black
   4798   // objects. Grey object's slots would be rescanned.
   4799   // White object might not survive until the end of collection
   4800   // it would be a violation of the invariant to record it's slots.
   4801   bool record_slots = false;
   4802   if (incremental_marking()->IsCompacting()) {
   4803     MarkBit mark_bit = ObjectMarking::MarkBitFrom(target);
   4804     record_slots = Marking::IsBlack(mark_bit);
   4805   }
   4806 
   4807   IterateAndScavengePromotedObjectsVisitor visitor(this, target, record_slots);
   4808   if (target->IsJSFunction()) {
   4809     // JSFunctions reachable through kNextFunctionLinkOffset are weak. Slots for
   4810     // this links are recorded during processing of weak lists.
   4811     JSFunction::BodyDescriptorWeakCode::IterateBody(target, size, &visitor);
   4812   } else {
   4813     target->IterateBody(target->map()->instance_type(), size, &visitor);
   4814   }
   4815 
   4816   // When black allocations is on, we have to visit not already marked black
   4817   // objects (in new space) promoted to black pages to keep their references
   4818   // alive.
   4819   // TODO(hpayer): Implement a special promotion visitor that incorporates
   4820   // regular visiting and IteratePromotedObjectPointers.
   4821   if (!was_marked_black) {
   4822     if (incremental_marking()->black_allocation()) {
   4823       IncrementalMarking::MarkGrey(this, target->map());
   4824       incremental_marking()->IterateBlackObject(target);
   4825     }
   4826   }
   4827 }
   4828 
   4829 
   4830 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) {
   4831   IterateStrongRoots(v, mode);
   4832   IterateWeakRoots(v, mode);
   4833 }
   4834 
   4835 
   4836 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) {
   4837   v->VisitPointer(reinterpret_cast<Object**>(&roots_[kStringTableRootIndex]));
   4838   v->Synchronize(VisitorSynchronization::kStringTable);
   4839   if (mode != VISIT_ALL_IN_SCAVENGE && mode != VISIT_ALL_IN_SWEEP_NEWSPACE) {
   4840     // Scavenge collections have special processing for this.
   4841     external_string_table_.Iterate(v);
   4842   }
   4843   v->Synchronize(VisitorSynchronization::kExternalStringsTable);
   4844 }
   4845 
   4846 
   4847 void Heap::IterateSmiRoots(ObjectVisitor* v) {
   4848   // Acquire execution access since we are going to read stack limit values.
   4849   ExecutionAccess access(isolate());
   4850   v->VisitPointers(&roots_[kSmiRootsStart], &roots_[kRootListLength]);
   4851   v->Synchronize(VisitorSynchronization::kSmiRootList);
   4852 }
   4853 
   4854 // We cannot avoid stale handles to left-trimmed objects, but can only make
   4855 // sure all handles still needed are updated. Filter out a stale pointer
   4856 // and clear the slot to allow post processing of handles (needed because
   4857 // the sweeper might actually free the underlying page).
   4858 class FixStaleLeftTrimmedHandlesVisitor : public ObjectVisitor {
   4859  public:
   4860   explicit FixStaleLeftTrimmedHandlesVisitor(Heap* heap) : heap_(heap) {
   4861     USE(heap_);
   4862   }
   4863 
   4864   void VisitPointer(Object** p) override { FixHandle(p); }
   4865 
   4866   void VisitPointers(Object** start, Object** end) override {
   4867     for (Object** p = start; p < end; p++) FixHandle(p);
   4868   }
   4869 
   4870  private:
   4871   inline void FixHandle(Object** p) {
   4872     HeapObject* current = reinterpret_cast<HeapObject*>(*p);
   4873     if (!current->IsHeapObject()) return;
   4874     const MapWord map_word = current->map_word();
   4875     if (!map_word.IsForwardingAddress() && current->IsFiller()) {
   4876 #ifdef DEBUG
   4877       // We need to find a FixedArrayBase map after walking the fillers.
   4878       while (current->IsFiller()) {
   4879         Address next = reinterpret_cast<Address>(current);
   4880         if (current->map() == heap_->one_pointer_filler_map()) {
   4881           next += kPointerSize;
   4882         } else if (current->map() == heap_->two_pointer_filler_map()) {
   4883           next += 2 * kPointerSize;
   4884         } else {
   4885           next += current->Size();
   4886         }
   4887         current = reinterpret_cast<HeapObject*>(next);
   4888       }
   4889       DCHECK(current->IsFixedArrayBase());
   4890 #endif  // DEBUG
   4891       *p = nullptr;
   4892     }
   4893   }
   4894 
   4895   Heap* heap_;
   4896 };
   4897 
   4898 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
   4899   v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]);
   4900   v->Synchronize(VisitorSynchronization::kStrongRootList);
   4901   // The serializer/deserializer iterates the root list twice, first to pick
   4902   // off immortal immovable roots to make sure they end up on the first page,
   4903   // and then again for the rest.
   4904   if (mode == VISIT_ONLY_STRONG_ROOT_LIST) return;
   4905 
   4906   isolate_->bootstrapper()->Iterate(v);
   4907   v->Synchronize(VisitorSynchronization::kBootstrapper);
   4908   isolate_->Iterate(v);
   4909   v->Synchronize(VisitorSynchronization::kTop);
   4910   Relocatable::Iterate(isolate_, v);
   4911   v->Synchronize(VisitorSynchronization::kRelocatable);
   4912   isolate_->debug()->Iterate(v);
   4913   v->Synchronize(VisitorSynchronization::kDebug);
   4914 
   4915   isolate_->compilation_cache()->Iterate(v);
   4916   v->Synchronize(VisitorSynchronization::kCompilationCache);
   4917 
   4918   // Iterate over local handles in handle scopes.
   4919   FixStaleLeftTrimmedHandlesVisitor left_trim_visitor(this);
   4920   isolate_->handle_scope_implementer()->Iterate(&left_trim_visitor);
   4921   isolate_->handle_scope_implementer()->Iterate(v);
   4922   isolate_->IterateDeferredHandles(v);
   4923   v->Synchronize(VisitorSynchronization::kHandleScope);
   4924 
   4925   // Iterate over the builtin code objects and code stubs in the
   4926   // heap. Note that it is not necessary to iterate over code objects
   4927   // on scavenge collections.
   4928   if (mode != VISIT_ALL_IN_SCAVENGE) {
   4929     isolate_->builtins()->IterateBuiltins(v);
   4930     v->Synchronize(VisitorSynchronization::kBuiltins);
   4931     isolate_->interpreter()->IterateDispatchTable(v);
   4932     v->Synchronize(VisitorSynchronization::kDispatchTable);
   4933   }
   4934 
   4935   // Iterate over global handles.
   4936   switch (mode) {
   4937     case VISIT_ONLY_STRONG_ROOT_LIST:
   4938       UNREACHABLE();
   4939       break;
   4940     case VISIT_ONLY_STRONG:
   4941     case VISIT_ONLY_STRONG_FOR_SERIALIZATION:
   4942       isolate_->global_handles()->IterateStrongRoots(v);
   4943       break;
   4944     case VISIT_ALL_IN_SCAVENGE:
   4945       isolate_->global_handles()->IterateNewSpaceStrongAndDependentRoots(v);
   4946       break;
   4947     case VISIT_ALL_IN_SWEEP_NEWSPACE:
   4948     case VISIT_ALL:
   4949       isolate_->global_handles()->IterateAllRoots(v);
   4950       break;
   4951   }
   4952   v->Synchronize(VisitorSynchronization::kGlobalHandles);
   4953 
   4954   // Iterate over eternal handles.
   4955   if (mode == VISIT_ALL_IN_SCAVENGE) {
   4956     isolate_->eternal_handles()->IterateNewSpaceRoots(v);
   4957   } else {
   4958     isolate_->eternal_handles()->IterateAllRoots(v);
   4959   }
   4960   v->Synchronize(VisitorSynchronization::kEternalHandles);
   4961 
   4962   // Iterate over pointers being held by inactive threads.
   4963   isolate_->thread_manager()->Iterate(v);
   4964   v->Synchronize(VisitorSynchronization::kThreadManager);
   4965 
   4966   // Iterate over other strong roots (currently only identity maps).
   4967   for (StrongRootsList* list = strong_roots_list_; list; list = list->next) {
   4968     v->VisitPointers(list->start, list->end);
   4969   }
   4970   v->Synchronize(VisitorSynchronization::kStrongRoots);
   4971 
   4972   // Iterate over the partial snapshot cache unless serializing.
   4973   if (mode != VISIT_ONLY_STRONG_FOR_SERIALIZATION) {
   4974     SerializerDeserializer::Iterate(isolate_, v);
   4975   }
   4976   // We don't do a v->Synchronize call here, because in debug mode that will
   4977   // output a flag to the snapshot.  However at this point the serializer and
   4978   // deserializer are deliberately a little unsynchronized (see above) so the
   4979   // checking of the sync flag in the snapshot would fail.
   4980 }
   4981 
   4982 
   4983 // TODO(1236194): Since the heap size is configurable on the command line
   4984 // and through the API, we should gracefully handle the case that the heap
   4985 // size is not big enough to fit all the initial objects.
   4986 bool Heap::ConfigureHeap(size_t max_semi_space_size, size_t max_old_space_size,
   4987                          size_t max_executable_size, size_t code_range_size) {
   4988   if (HasBeenSetUp()) return false;
   4989 
   4990   // Overwrite default configuration.
   4991   if (max_semi_space_size != 0) {
   4992     max_semi_space_size_ = max_semi_space_size * MB;
   4993   }
   4994   if (max_old_space_size != 0) {
   4995     max_old_generation_size_ = max_old_space_size * MB;
   4996   }
   4997   if (max_executable_size != 0) {
   4998     max_executable_size_ = max_executable_size * MB;
   4999   }
   5000 
   5001   // If max space size flags are specified overwrite the configuration.
   5002   if (FLAG_max_semi_space_size > 0) {
   5003     max_semi_space_size_ = static_cast<size_t>(FLAG_max_semi_space_size) * MB;
   5004   }
   5005   if (FLAG_max_old_space_size > 0) {
   5006     max_old_generation_size_ =
   5007         static_cast<size_t>(FLAG_max_old_space_size) * MB;
   5008   }
   5009   if (FLAG_max_executable_size > 0) {
   5010     max_executable_size_ = static_cast<size_t>(FLAG_max_executable_size) * MB;
   5011   }
   5012 
   5013   if (Page::kPageSize > MB) {
   5014     max_semi_space_size_ = ROUND_UP(max_semi_space_size_, Page::kPageSize);
   5015     max_old_generation_size_ =
   5016         ROUND_UP(max_old_generation_size_, Page::kPageSize);
   5017     max_executable_size_ = ROUND_UP(max_executable_size_, Page::kPageSize);
   5018   }
   5019 
   5020   if (FLAG_stress_compaction) {
   5021     // This will cause more frequent GCs when stressing.
   5022     max_semi_space_size_ = MB;
   5023   }
   5024 
   5025   // The new space size must be a power of two to support single-bit testing
   5026   // for containment.
   5027   max_semi_space_size_ = base::bits::RoundUpToPowerOfTwo32(
   5028       static_cast<uint32_t>(max_semi_space_size_));
   5029 
   5030   if (FLAG_min_semi_space_size > 0) {
   5031     size_t initial_semispace_size =
   5032         static_cast<size_t>(FLAG_min_semi_space_size) * MB;
   5033     if (initial_semispace_size > max_semi_space_size_) {
   5034       initial_semispace_size_ = max_semi_space_size_;
   5035       if (FLAG_trace_gc) {
   5036         PrintIsolate(isolate_,
   5037                      "Min semi-space size cannot be more than the maximum "
   5038                      "semi-space size of %" PRIuS " MB\n",
   5039                      max_semi_space_size_ / MB);
   5040       }
   5041     } else {
   5042       initial_semispace_size_ =
   5043           ROUND_UP(initial_semispace_size, Page::kPageSize);
   5044     }
   5045   }
   5046 
   5047   initial_semispace_size_ = Min(initial_semispace_size_, max_semi_space_size_);
   5048 
   5049   if (FLAG_semi_space_growth_factor < 2) {
   5050     FLAG_semi_space_growth_factor = 2;
   5051   }
   5052 
   5053   // The old generation is paged and needs at least one page for each space.
   5054   int paged_space_count = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1;
   5055   max_old_generation_size_ =
   5056       Max(static_cast<size_t>(paged_space_count * Page::kPageSize),
   5057           max_old_generation_size_);
   5058 
   5059   // The max executable size must be less than or equal to the max old
   5060   // generation size.
   5061   if (max_executable_size_ > max_old_generation_size_) {
   5062     max_executable_size_ = max_old_generation_size_;
   5063   }
   5064 
   5065   if (FLAG_initial_old_space_size > 0) {
   5066     initial_old_generation_size_ = FLAG_initial_old_space_size * MB;
   5067   } else {
   5068     initial_old_generation_size_ =
   5069         max_old_generation_size_ / kInitalOldGenerationLimitFactor;
   5070   }
   5071   old_generation_allocation_limit_ = initial_old_generation_size_;
   5072 
   5073   // We rely on being able to allocate new arrays in paged spaces.
   5074   DCHECK(kMaxRegularHeapObjectSize >=
   5075          (JSArray::kSize +
   5076           FixedArray::SizeFor(JSArray::kInitialMaxFastElementArray) +
   5077           AllocationMemento::kSize));
   5078 
   5079   code_range_size_ = code_range_size * MB;
   5080 
   5081   configured_ = true;
   5082   return true;
   5083 }
   5084 
   5085 
   5086 void Heap::AddToRingBuffer(const char* string) {
   5087   size_t first_part =
   5088       Min(strlen(string), kTraceRingBufferSize - ring_buffer_end_);
   5089   memcpy(trace_ring_buffer_ + ring_buffer_end_, string, first_part);
   5090   ring_buffer_end_ += first_part;
   5091   if (first_part < strlen(string)) {
   5092     ring_buffer_full_ = true;
   5093     size_t second_part = strlen(string) - first_part;
   5094     memcpy(trace_ring_buffer_, string + first_part, second_part);
   5095     ring_buffer_end_ = second_part;
   5096   }
   5097 }
   5098 
   5099 
   5100 void Heap::GetFromRingBuffer(char* buffer) {
   5101   size_t copied = 0;
   5102   if (ring_buffer_full_) {
   5103     copied = kTraceRingBufferSize - ring_buffer_end_;
   5104     memcpy(buffer, trace_ring_buffer_ + ring_buffer_end_, copied);
   5105   }
   5106   memcpy(buffer + copied, trace_ring_buffer_, ring_buffer_end_);
   5107 }
   5108 
   5109 
   5110 bool Heap::ConfigureHeapDefault() { return ConfigureHeap(0, 0, 0, 0); }
   5111 
   5112 
   5113 void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
   5114   *stats->start_marker = HeapStats::kStartMarker;
   5115   *stats->end_marker = HeapStats::kEndMarker;
   5116   *stats->new_space_size = new_space_->Size();
   5117   *stats->new_space_capacity = new_space_->Capacity();
   5118   *stats->old_space_size = old_space_->SizeOfObjects();
   5119   *stats->old_space_capacity = old_space_->Capacity();
   5120   *stats->code_space_size = code_space_->SizeOfObjects();
   5121   *stats->code_space_capacity = code_space_->Capacity();
   5122   *stats->map_space_size = map_space_->SizeOfObjects();
   5123   *stats->map_space_capacity = map_space_->Capacity();
   5124   *stats->lo_space_size = lo_space_->Size();
   5125   isolate_->global_handles()->RecordStats(stats);
   5126   *stats->memory_allocator_size = memory_allocator()->Size();
   5127   *stats->memory_allocator_capacity =
   5128       memory_allocator()->Size() + memory_allocator()->Available();
   5129   *stats->os_error = base::OS::GetLastError();
   5130   *stats->malloced_memory = isolate_->allocator()->GetCurrentMemoryUsage();
   5131   *stats->malloced_peak_memory = isolate_->allocator()->GetMaxMemoryUsage();
   5132   if (take_snapshot) {
   5133     HeapIterator iterator(this);
   5134     for (HeapObject* obj = iterator.next(); obj != NULL;
   5135          obj = iterator.next()) {
   5136       InstanceType type = obj->map()->instance_type();
   5137       DCHECK(0 <= type && type <= LAST_TYPE);
   5138       stats->objects_per_type[type]++;
   5139       stats->size_per_type[type] += obj->Size();
   5140     }
   5141   }
   5142   if (stats->last_few_messages != NULL)
   5143     GetFromRingBuffer(stats->last_few_messages);
   5144   if (stats->js_stacktrace != NULL) {
   5145     FixedStringAllocator fixed(stats->js_stacktrace, kStacktraceBufferSize - 1);
   5146     StringStream accumulator(&fixed, StringStream::kPrintObjectConcise);
   5147     if (gc_state() == Heap::NOT_IN_GC) {
   5148       isolate()->PrintStack(&accumulator, Isolate::kPrintStackVerbose);
   5149     } else {
   5150       accumulator.Add("Cannot get stack trace in GC.");
   5151     }
   5152   }
   5153 }
   5154 
   5155 size_t Heap::PromotedSpaceSizeOfObjects() {
   5156   return old_space_->SizeOfObjects() + code_space_->SizeOfObjects() +
   5157          map_space_->SizeOfObjects() + lo_space_->SizeOfObjects();
   5158 }
   5159 
   5160 uint64_t Heap::PromotedExternalMemorySize() {
   5161   if (external_memory_ <= external_memory_at_last_mark_compact_) return 0;
   5162   return static_cast<uint64_t>(external_memory_ -
   5163                                external_memory_at_last_mark_compact_);
   5164 }
   5165 
   5166 
   5167 const double Heap::kMinHeapGrowingFactor = 1.1;
   5168 const double Heap::kMaxHeapGrowingFactor = 4.0;
   5169 const double Heap::kMaxHeapGrowingFactorMemoryConstrained = 2.0;
   5170 const double Heap::kMaxHeapGrowingFactorIdle = 1.5;
   5171 const double Heap::kConservativeHeapGrowingFactor = 1.3;
   5172 const double Heap::kTargetMutatorUtilization = 0.97;
   5173 
   5174 
   5175 // Given GC speed in bytes per ms, the allocation throughput in bytes per ms
   5176 // (mutator speed), this function returns the heap growing factor that will
   5177 // achieve the kTargetMutatorUtilisation if the GC speed and the mutator speed
   5178 // remain the same until the next GC.
   5179 //
   5180 // For a fixed time-frame T = TM + TG, the mutator utilization is the ratio
   5181 // TM / (TM + TG), where TM is the time spent in the mutator and TG is the
   5182 // time spent in the garbage collector.
   5183 //
   5184 // Let MU be kTargetMutatorUtilisation, the desired mutator utilization for the
   5185 // time-frame from the end of the current GC to the end of the next GC. Based
   5186 // on the MU we can compute the heap growing factor F as
   5187 //
   5188 // F = R * (1 - MU) / (R * (1 - MU) - MU), where R = gc_speed / mutator_speed.
   5189 //
   5190 // This formula can be derived as follows.
   5191 //
   5192 // F = Limit / Live by definition, where the Limit is the allocation limit,
   5193 // and the Live is size of live objects.
   5194 // Lets assume that we already know the Limit. Then:
   5195 //   TG = Limit / gc_speed
   5196 //   TM = (TM + TG) * MU, by definition of MU.
   5197 //   TM = TG * MU / (1 - MU)
   5198 //   TM = Limit *  MU / (gc_speed * (1 - MU))
   5199 // On the other hand, if the allocation throughput remains constant:
   5200 //   Limit = Live + TM * allocation_throughput = Live + TM * mutator_speed
   5201 // Solving it for TM, we get
   5202 //   TM = (Limit - Live) / mutator_speed
   5203 // Combining the two equation for TM:
   5204 //   (Limit - Live) / mutator_speed = Limit * MU / (gc_speed * (1 - MU))
   5205 //   (Limit - Live) = Limit * MU * mutator_speed / (gc_speed * (1 - MU))
   5206 // substitute R = gc_speed / mutator_speed
   5207 //   (Limit - Live) = Limit * MU  / (R * (1 - MU))
   5208 // substitute F = Limit / Live
   5209 //   F - 1 = F * MU  / (R * (1 - MU))
   5210 //   F - F * MU / (R * (1 - MU)) = 1
   5211 //   F * (1 - MU / (R * (1 - MU))) = 1
   5212 //   F * (R * (1 - MU) - MU) / (R * (1 - MU)) = 1
   5213 //   F = R * (1 - MU) / (R * (1 - MU) - MU)
   5214 double Heap::HeapGrowingFactor(double gc_speed, double mutator_speed) {
   5215   if (gc_speed == 0 || mutator_speed == 0) return kMaxHeapGrowingFactor;
   5216 
   5217   const double speed_ratio = gc_speed / mutator_speed;
   5218   const double mu = kTargetMutatorUtilization;
   5219 
   5220   const double a = speed_ratio * (1 - mu);
   5221   const double b = speed_ratio * (1 - mu) - mu;
   5222 
   5223   // The factor is a / b, but we need to check for small b first.
   5224   double factor =
   5225       (a < b * kMaxHeapGrowingFactor) ? a / b : kMaxHeapGrowingFactor;
   5226   factor = Min(factor, kMaxHeapGrowingFactor);
   5227   factor = Max(factor, kMinHeapGrowingFactor);
   5228   return factor;
   5229 }
   5230 
   5231 size_t Heap::CalculateOldGenerationAllocationLimit(double factor,
   5232                                                    size_t old_gen_size) {
   5233   CHECK(factor > 1.0);
   5234   CHECK(old_gen_size > 0);
   5235   uint64_t limit = static_cast<uint64_t>(old_gen_size * factor);
   5236   limit = Max(limit, static_cast<uint64_t>(old_gen_size) +
   5237                          MinimumAllocationLimitGrowingStep());
   5238   limit += new_space_->Capacity();
   5239   uint64_t halfway_to_the_max =
   5240       (static_cast<uint64_t>(old_gen_size) + max_old_generation_size_) / 2;
   5241   return static_cast<size_t>(Min(limit, halfway_to_the_max));
   5242 }
   5243 
   5244 size_t Heap::MinimumAllocationLimitGrowingStep() {
   5245   const size_t kRegularAllocationLimitGrowingStep = 8;
   5246   const size_t kLowMemoryAllocationLimitGrowingStep = 2;
   5247   size_t limit = (Page::kPageSize > MB ? Page::kPageSize : MB);
   5248   return limit * (ShouldOptimizeForMemoryUsage()
   5249                       ? kLowMemoryAllocationLimitGrowingStep
   5250                       : kRegularAllocationLimitGrowingStep);
   5251 }
   5252 
   5253 void Heap::SetOldGenerationAllocationLimit(size_t old_gen_size, double gc_speed,
   5254                                            double mutator_speed) {
   5255   double factor = HeapGrowingFactor(gc_speed, mutator_speed);
   5256 
   5257   if (FLAG_trace_gc_verbose) {
   5258     isolate_->PrintWithTimestamp(
   5259         "Heap growing factor %.1f based on mu=%.3f, speed_ratio=%.f "
   5260         "(gc=%.f, mutator=%.f)\n",
   5261         factor, kTargetMutatorUtilization, gc_speed / mutator_speed, gc_speed,
   5262         mutator_speed);
   5263   }
   5264 
   5265   if (IsMemoryConstrainedDevice()) {
   5266     factor = Min(factor, kMaxHeapGrowingFactorMemoryConstrained);
   5267   }
   5268 
   5269   if (memory_reducer_->ShouldGrowHeapSlowly() ||
   5270       ShouldOptimizeForMemoryUsage()) {
   5271     factor = Min(factor, kConservativeHeapGrowingFactor);
   5272   }
   5273 
   5274   if (FLAG_stress_compaction || ShouldReduceMemory()) {
   5275     factor = kMinHeapGrowingFactor;
   5276   }
   5277 
   5278   if (FLAG_heap_growing_percent > 0) {
   5279     factor = 1.0 + FLAG_heap_growing_percent / 100.0;
   5280   }
   5281 
   5282   old_generation_allocation_limit_ =
   5283       CalculateOldGenerationAllocationLimit(factor, old_gen_size);
   5284 
   5285   if (FLAG_trace_gc_verbose) {
   5286     isolate_->PrintWithTimestamp(
   5287         "Grow: old size: %" PRIuS " KB, new limit: %" PRIuS " KB (%.1f)\n",
   5288         old_gen_size / KB, old_generation_allocation_limit_ / KB, factor);
   5289   }
   5290 }
   5291 
   5292 void Heap::DampenOldGenerationAllocationLimit(size_t old_gen_size,
   5293                                               double gc_speed,
   5294                                               double mutator_speed) {
   5295   double factor = HeapGrowingFactor(gc_speed, mutator_speed);
   5296   size_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size);
   5297   if (limit < old_generation_allocation_limit_) {
   5298     if (FLAG_trace_gc_verbose) {
   5299       isolate_->PrintWithTimestamp(
   5300           "Dampen: old size: %" PRIuS " KB, old limit: %" PRIuS
   5301           " KB, "
   5302           "new limit: %" PRIuS " KB (%.1f)\n",
   5303           old_gen_size / KB, old_generation_allocation_limit_ / KB, limit / KB,
   5304           factor);
   5305     }
   5306     old_generation_allocation_limit_ = limit;
   5307   }
   5308 }
   5309 
   5310 // This predicate is called when an old generation space cannot allocated from
   5311 // the free list and is about to add a new page. Returning false will cause a
   5312 // major GC. It happens when the old generation allocation limit is reached and
   5313 // - either we need to optimize for memory usage,
   5314 // - or the incremental marking is not in progress and we cannot start it.
   5315 bool Heap::ShouldExpandOldGenerationOnSlowAllocation() {
   5316   if (always_allocate() || OldGenerationSpaceAvailable() > 0) return true;
   5317   // We reached the old generation allocation limit.
   5318 
   5319   if (ShouldOptimizeForMemoryUsage()) return false;
   5320 
   5321   if (incremental_marking()->NeedsFinalization()) {
   5322     return !AllocationLimitOvershotByLargeMargin();
   5323   }
   5324 
   5325   if (incremental_marking()->IsStopped() &&
   5326       IncrementalMarkingLimitReached() == IncrementalMarkingLimit::kNoLimit) {
   5327     // We cannot start incremental marking.
   5328     return false;
   5329   }
   5330   return true;
   5331 }
   5332 
   5333 // This function returns either kNoLimit, kSoftLimit, or kHardLimit.
   5334 // The kNoLimit means that either incremental marking is disabled or it is too
   5335 // early to start incremental marking.
   5336 // The kSoftLimit means that incremental marking should be started soon.
   5337 // The kHardLimit means that incremental marking should be started immediately.
   5338 Heap::IncrementalMarkingLimit Heap::IncrementalMarkingLimitReached() {
   5339   if (!incremental_marking()->CanBeActivated() ||
   5340       PromotedSpaceSizeOfObjects() <=
   5341           IncrementalMarking::kActivationThreshold) {
   5342     // Incremental marking is disabled or it is too early to start.
   5343     return IncrementalMarkingLimit::kNoLimit;
   5344   }
   5345   if ((FLAG_stress_compaction && (gc_count_ & 1) != 0) ||
   5346       HighMemoryPressure()) {
   5347     // If there is high memory pressure or stress testing is enabled, then
   5348     // start marking immediately.
   5349     return IncrementalMarkingLimit::kHardLimit;
   5350   }
   5351   size_t old_generation_space_available = OldGenerationSpaceAvailable();
   5352   if (old_generation_space_available > new_space_->Capacity()) {
   5353     return IncrementalMarkingLimit::kNoLimit;
   5354   }
   5355   // We are close to the allocation limit.
   5356   // Choose between the hard and the soft limits.
   5357   if (old_generation_space_available == 0 || ShouldOptimizeForMemoryUsage()) {
   5358     return IncrementalMarkingLimit::kHardLimit;
   5359   }
   5360   return IncrementalMarkingLimit::kSoftLimit;
   5361 }
   5362 
   5363 void Heap::EnableInlineAllocation() {
   5364   if (!inline_allocation_disabled_) return;
   5365   inline_allocation_disabled_ = false;
   5366 
   5367   // Update inline allocation limit for new space.
   5368   new_space()->UpdateInlineAllocationLimit(0);
   5369 }
   5370 
   5371 
   5372 void Heap::DisableInlineAllocation() {
   5373   if (inline_allocation_disabled_) return;
   5374   inline_allocation_disabled_ = true;
   5375 
   5376   // Update inline allocation limit for new space.
   5377   new_space()->UpdateInlineAllocationLimit(0);
   5378 
   5379   // Update inline allocation limit for old spaces.
   5380   PagedSpaces spaces(this);
   5381   for (PagedSpace* space = spaces.next(); space != NULL;
   5382        space = spaces.next()) {
   5383     space->EmptyAllocationInfo();
   5384   }
   5385 }
   5386 
   5387 
   5388 V8_DECLARE_ONCE(initialize_gc_once);
   5389 
   5390 static void InitializeGCOnce() {
   5391   Scavenger::Initialize();
   5392   StaticScavengeVisitor::Initialize();
   5393   MarkCompactCollector::Initialize();
   5394 }
   5395 
   5396 
   5397 bool Heap::SetUp() {
   5398 #ifdef DEBUG
   5399   allocation_timeout_ = FLAG_gc_interval;
   5400 #endif
   5401 
   5402   // Initialize heap spaces and initial maps and objects. Whenever something
   5403   // goes wrong, just return false. The caller should check the results and
   5404   // call Heap::TearDown() to release allocated memory.
   5405   //
   5406   // If the heap is not yet configured (e.g. through the API), configure it.
   5407   // Configuration is based on the flags new-space-size (really the semispace
   5408   // size) and old-space-size if set or the initial values of semispace_size_
   5409   // and old_generation_size_ otherwise.
   5410   if (!configured_) {
   5411     if (!ConfigureHeapDefault()) return false;
   5412   }
   5413 
   5414   base::CallOnce(&initialize_gc_once, &InitializeGCOnce);
   5415 
   5416   // Set up memory allocator.
   5417   memory_allocator_ = new MemoryAllocator(isolate_);
   5418   if (!memory_allocator_->SetUp(MaxReserved(), MaxExecutableSize(),
   5419                                 code_range_size_))
   5420     return false;
   5421 
   5422   // Initialize store buffer.
   5423   store_buffer_ = new StoreBuffer(this);
   5424 
   5425   // Initialize incremental marking.
   5426   incremental_marking_ = new IncrementalMarking(this);
   5427 
   5428   for (int i = 0; i <= LAST_SPACE; i++) {
   5429     space_[i] = nullptr;
   5430   }
   5431 
   5432   space_[NEW_SPACE] = new_space_ = new NewSpace(this);
   5433   if (!new_space_->SetUp(initial_semispace_size_, max_semi_space_size_)) {
   5434     return false;
   5435   }
   5436   new_space_top_after_last_gc_ = new_space()->top();
   5437 
   5438   space_[OLD_SPACE] = old_space_ =
   5439       new OldSpace(this, OLD_SPACE, NOT_EXECUTABLE);
   5440   if (!old_space_->SetUp()) return false;
   5441 
   5442   space_[CODE_SPACE] = code_space_ = new OldSpace(this, CODE_SPACE, EXECUTABLE);
   5443   if (!code_space_->SetUp()) return false;
   5444 
   5445   space_[MAP_SPACE] = map_space_ = new MapSpace(this, MAP_SPACE);
   5446   if (!map_space_->SetUp()) return false;
   5447 
   5448   // The large object code space may contain code or data.  We set the memory
   5449   // to be non-executable here for safety, but this means we need to enable it
   5450   // explicitly when allocating large code objects.
   5451   space_[LO_SPACE] = lo_space_ = new LargeObjectSpace(this, LO_SPACE);
   5452   if (!lo_space_->SetUp()) return false;
   5453 
   5454   // Set up the seed that is used to randomize the string hash function.
   5455   DCHECK(hash_seed() == 0);
   5456   if (FLAG_randomize_hashes) {
   5457     if (FLAG_hash_seed == 0) {
   5458       int rnd = isolate()->random_number_generator()->NextInt();
   5459       set_hash_seed(Smi::FromInt(rnd & Name::kHashBitMask));
   5460     } else {
   5461       set_hash_seed(Smi::FromInt(FLAG_hash_seed));
   5462     }
   5463   }
   5464 
   5465   for (int i = 0; i < static_cast<int>(v8::Isolate::kUseCounterFeatureCount);
   5466        i++) {
   5467     deferred_counters_[i] = 0;
   5468   }
   5469 
   5470   tracer_ = new GCTracer(this);
   5471   scavenge_collector_ = new Scavenger(this);
   5472   mark_compact_collector_ = new MarkCompactCollector(this);
   5473   gc_idle_time_handler_ = new GCIdleTimeHandler();
   5474   memory_reducer_ = new MemoryReducer(this);
   5475   if (V8_UNLIKELY(FLAG_gc_stats)) {
   5476     live_object_stats_ = new ObjectStats(this);
   5477     dead_object_stats_ = new ObjectStats(this);
   5478   }
   5479   scavenge_job_ = new ScavengeJob();
   5480 
   5481   LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity()));
   5482   LOG(isolate_, IntPtrTEvent("heap-available", Available()));
   5483 
   5484   store_buffer()->SetUp();
   5485 
   5486   mark_compact_collector()->SetUp();
   5487 
   5488   idle_scavenge_observer_ = new IdleScavengeObserver(
   5489       *this, ScavengeJob::kBytesAllocatedBeforeNextIdleTask);
   5490   new_space()->AddAllocationObserver(idle_scavenge_observer_);
   5491 
   5492   return true;
   5493 }
   5494 
   5495 
   5496 bool Heap::CreateHeapObjects() {
   5497   // Create initial maps.
   5498   if (!CreateInitialMaps()) return false;
   5499   CreateApiObjects();
   5500 
   5501   // Create initial objects
   5502   CreateInitialObjects();
   5503   CHECK_EQ(0u, gc_count_);
   5504 
   5505   set_native_contexts_list(undefined_value());
   5506   set_allocation_sites_list(undefined_value());
   5507 
   5508   return true;
   5509 }
   5510 
   5511 
   5512 void Heap::SetStackLimits() {
   5513   DCHECK(isolate_ != NULL);
   5514   DCHECK(isolate_ == isolate());
   5515   // On 64 bit machines, pointers are generally out of range of Smis.  We write
   5516   // something that looks like an out of range Smi to the GC.
   5517 
   5518   // Set up the special root array entries containing the stack limits.
   5519   // These are actually addresses, but the tag makes the GC ignore it.
   5520   roots_[kStackLimitRootIndex] = reinterpret_cast<Object*>(
   5521       (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag);
   5522   roots_[kRealStackLimitRootIndex] = reinterpret_cast<Object*>(
   5523       (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag);
   5524 }
   5525 
   5526 void Heap::ClearStackLimits() {
   5527   roots_[kStackLimitRootIndex] = Smi::kZero;
   5528   roots_[kRealStackLimitRootIndex] = Smi::kZero;
   5529 }
   5530 
   5531 void Heap::PrintAlloctionsHash() {
   5532   uint32_t hash = StringHasher::GetHashCore(raw_allocations_hash_);
   5533   PrintF("\n### Allocations = %u, hash = 0x%08x\n", allocations_count(), hash);
   5534 }
   5535 
   5536 
   5537 void Heap::NotifyDeserializationComplete() {
   5538   DCHECK_EQ(0, gc_count());
   5539   PagedSpaces spaces(this);
   5540   for (PagedSpace* s = spaces.next(); s != NULL; s = spaces.next()) {
   5541     if (isolate()->snapshot_available()) s->ShrinkImmortalImmovablePages();
   5542 #ifdef DEBUG
   5543     // All pages right after bootstrapping must be marked as never-evacuate.
   5544     for (Page* p : *s) {
   5545       CHECK(p->NeverEvacuate());
   5546     }
   5547 #endif  // DEBUG
   5548   }
   5549 
   5550   deserialization_complete_ = true;
   5551 }
   5552 
   5553 void Heap::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {
   5554   DCHECK_EQ(gc_state_, HeapState::NOT_IN_GC);
   5555   embedder_heap_tracer_ = tracer;
   5556 }
   5557 
   5558 void Heap::RegisterWrappersWithEmbedderHeapTracer() {
   5559   DCHECK(UsingEmbedderHeapTracer());
   5560   if (wrappers_to_trace_.empty()) {
   5561     return;
   5562   }
   5563   embedder_heap_tracer()->RegisterV8References(wrappers_to_trace_);
   5564   wrappers_to_trace_.clear();
   5565 }
   5566 
   5567 void Heap::TracePossibleWrapper(JSObject* js_object) {
   5568   DCHECK(js_object->WasConstructedFromApiFunction());
   5569   if (js_object->GetInternalFieldCount() >= 2 &&
   5570       js_object->GetInternalField(0) &&
   5571       js_object->GetInternalField(0) != undefined_value() &&
   5572       js_object->GetInternalField(1) != undefined_value()) {
   5573     DCHECK(reinterpret_cast<intptr_t>(js_object->GetInternalField(0)) % 2 == 0);
   5574     wrappers_to_trace_.push_back(std::pair<void*, void*>(
   5575         reinterpret_cast<void*>(js_object->GetInternalField(0)),
   5576         reinterpret_cast<void*>(js_object->GetInternalField(1))));
   5577   }
   5578 }
   5579 
   5580 bool Heap::RequiresImmediateWrapperProcessing() {
   5581   const size_t kTooManyWrappers = 16000;
   5582   return wrappers_to_trace_.size() > kTooManyWrappers;
   5583 }
   5584 
   5585 void Heap::RegisterExternallyReferencedObject(Object** object) {
   5586   HeapObject* heap_object = HeapObject::cast(*object);
   5587   DCHECK(Contains(heap_object));
   5588   if (FLAG_incremental_marking_wrappers && incremental_marking()->IsMarking()) {
   5589     IncrementalMarking::MarkGrey(this, heap_object);
   5590   } else {
   5591     DCHECK(mark_compact_collector()->in_use());
   5592     MarkBit mark_bit = ObjectMarking::MarkBitFrom(heap_object);
   5593     mark_compact_collector()->MarkObject(heap_object, mark_bit);
   5594   }
   5595 }
   5596 
   5597 void Heap::TearDown() {
   5598 #ifdef VERIFY_HEAP
   5599   if (FLAG_verify_heap) {
   5600     Verify();
   5601   }
   5602 #endif
   5603 
   5604   UpdateMaximumCommitted();
   5605 
   5606   if (FLAG_print_max_heap_committed) {
   5607     PrintF("\n");
   5608     PrintF("maximum_committed_by_heap=%" PRIuS " ", MaximumCommittedMemory());
   5609     PrintF("maximum_committed_by_new_space=%" PRIuS " ",
   5610            new_space_->MaximumCommittedMemory());
   5611     PrintF("maximum_committed_by_old_space=%" PRIuS " ",
   5612            old_space_->MaximumCommittedMemory());
   5613     PrintF("maximum_committed_by_code_space=%" PRIuS " ",
   5614            code_space_->MaximumCommittedMemory());
   5615     PrintF("maximum_committed_by_map_space=%" PRIuS " ",
   5616            map_space_->MaximumCommittedMemory());
   5617     PrintF("maximum_committed_by_lo_space=%" PRIuS " ",
   5618            lo_space_->MaximumCommittedMemory());
   5619     PrintF("\n\n");
   5620   }
   5621 
   5622   if (FLAG_verify_predictable) {
   5623     PrintAlloctionsHash();
   5624   }
   5625 
   5626   new_space()->RemoveAllocationObserver(idle_scavenge_observer_);
   5627   delete idle_scavenge_observer_;
   5628   idle_scavenge_observer_ = nullptr;
   5629 
   5630   delete scavenge_collector_;
   5631   scavenge_collector_ = nullptr;
   5632 
   5633   if (mark_compact_collector_ != nullptr) {
   5634     mark_compact_collector_->TearDown();
   5635     delete mark_compact_collector_;
   5636     mark_compact_collector_ = nullptr;
   5637   }
   5638 
   5639   delete incremental_marking_;
   5640   incremental_marking_ = nullptr;
   5641 
   5642   delete gc_idle_time_handler_;
   5643   gc_idle_time_handler_ = nullptr;
   5644 
   5645   if (memory_reducer_ != nullptr) {
   5646     memory_reducer_->TearDown();
   5647     delete memory_reducer_;
   5648     memory_reducer_ = nullptr;
   5649   }
   5650 
   5651   if (live_object_stats_ != nullptr) {
   5652     delete live_object_stats_;
   5653     live_object_stats_ = nullptr;
   5654   }
   5655 
   5656   if (dead_object_stats_ != nullptr) {
   5657     delete dead_object_stats_;
   5658     dead_object_stats_ = nullptr;
   5659   }
   5660 
   5661   delete scavenge_job_;
   5662   scavenge_job_ = nullptr;
   5663 
   5664   isolate_->global_handles()->TearDown();
   5665 
   5666   external_string_table_.TearDown();
   5667 
   5668   delete tracer_;
   5669   tracer_ = nullptr;
   5670 
   5671   new_space_->TearDown();
   5672   delete new_space_;
   5673   new_space_ = nullptr;
   5674 
   5675   if (old_space_ != NULL) {
   5676     delete old_space_;
   5677     old_space_ = NULL;
   5678   }
   5679 
   5680   if (code_space_ != NULL) {
   5681     delete code_space_;
   5682     code_space_ = NULL;
   5683   }
   5684 
   5685   if (map_space_ != NULL) {
   5686     delete map_space_;
   5687     map_space_ = NULL;
   5688   }
   5689 
   5690   if (lo_space_ != NULL) {
   5691     lo_space_->TearDown();
   5692     delete lo_space_;
   5693     lo_space_ = NULL;
   5694   }
   5695 
   5696   store_buffer()->TearDown();
   5697 
   5698   memory_allocator()->TearDown();
   5699 
   5700   StrongRootsList* next = NULL;
   5701   for (StrongRootsList* list = strong_roots_list_; list; list = next) {
   5702     next = list->next;
   5703     delete list;
   5704   }
   5705   strong_roots_list_ = NULL;
   5706 
   5707   delete store_buffer_;
   5708   store_buffer_ = nullptr;
   5709 
   5710   delete memory_allocator_;
   5711   memory_allocator_ = nullptr;
   5712 }
   5713 
   5714 
   5715 void Heap::AddGCPrologueCallback(v8::Isolate::GCCallback callback,
   5716                                  GCType gc_type, bool pass_isolate) {
   5717   DCHECK(callback != NULL);
   5718   GCCallbackPair pair(callback, gc_type, pass_isolate);
   5719   DCHECK(!gc_prologue_callbacks_.Contains(pair));
   5720   return gc_prologue_callbacks_.Add(pair);
   5721 }
   5722 
   5723 
   5724 void Heap::RemoveGCPrologueCallback(v8::Isolate::GCCallback callback) {
   5725   DCHECK(callback != NULL);
   5726   for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) {
   5727     if (gc_prologue_callbacks_[i].callback == callback) {
   5728       gc_prologue_callbacks_.Remove(i);
   5729       return;
   5730     }
   5731   }
   5732   UNREACHABLE();
   5733 }
   5734 
   5735 
   5736 void Heap::AddGCEpilogueCallback(v8::Isolate::GCCallback callback,
   5737                                  GCType gc_type, bool pass_isolate) {
   5738   DCHECK(callback != NULL);
   5739   GCCallbackPair pair(callback, gc_type, pass_isolate);
   5740   DCHECK(!gc_epilogue_callbacks_.Contains(pair));
   5741   return gc_epilogue_callbacks_.Add(pair);
   5742 }
   5743 
   5744 
   5745 void Heap::RemoveGCEpilogueCallback(v8::Isolate::GCCallback callback) {
   5746   DCHECK(callback != NULL);
   5747   for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) {
   5748     if (gc_epilogue_callbacks_[i].callback == callback) {
   5749       gc_epilogue_callbacks_.Remove(i);
   5750       return;
   5751     }
   5752   }
   5753   UNREACHABLE();
   5754 }
   5755 
   5756 // TODO(ishell): Find a better place for this.
   5757 void Heap::AddWeakNewSpaceObjectToCodeDependency(Handle<HeapObject> obj,
   5758                                                  Handle<WeakCell> code) {
   5759   DCHECK(InNewSpace(*obj));
   5760   DCHECK(!InNewSpace(*code));
   5761   Handle<ArrayList> list(weak_new_space_object_to_code_list(), isolate());
   5762   list = ArrayList::Add(list, isolate()->factory()->NewWeakCell(obj), code);
   5763   if (*list != weak_new_space_object_to_code_list()) {
   5764     set_weak_new_space_object_to_code_list(*list);
   5765   }
   5766 }
   5767 
   5768 // TODO(ishell): Find a better place for this.
   5769 void Heap::AddWeakObjectToCodeDependency(Handle<HeapObject> obj,
   5770                                          Handle<DependentCode> dep) {
   5771   DCHECK(!InNewSpace(*obj));
   5772   DCHECK(!InNewSpace(*dep));
   5773   Handle<WeakHashTable> table(weak_object_to_code_table(), isolate());
   5774   table = WeakHashTable::Put(table, obj, dep);
   5775   if (*table != weak_object_to_code_table())
   5776     set_weak_object_to_code_table(*table);
   5777   DCHECK_EQ(*dep, LookupWeakObjectToCodeDependency(obj));
   5778 }
   5779 
   5780 
   5781 DependentCode* Heap::LookupWeakObjectToCodeDependency(Handle<HeapObject> obj) {
   5782   Object* dep = weak_object_to_code_table()->Lookup(obj);
   5783   if (dep->IsDependentCode()) return DependentCode::cast(dep);
   5784   return DependentCode::cast(empty_fixed_array());
   5785 }
   5786 
   5787 namespace {
   5788 void CompactWeakFixedArray(Object* object) {
   5789   if (object->IsWeakFixedArray()) {
   5790     WeakFixedArray* array = WeakFixedArray::cast(object);
   5791     array->Compact<WeakFixedArray::NullCallback>();
   5792   }
   5793 }
   5794 }  // anonymous namespace
   5795 
   5796 void Heap::CompactWeakFixedArrays() {
   5797   // Find known WeakFixedArrays and compact them.
   5798   HeapIterator iterator(this);
   5799   for (HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) {
   5800     if (o->IsPrototypeInfo()) {
   5801       Object* prototype_users = PrototypeInfo::cast(o)->prototype_users();
   5802       if (prototype_users->IsWeakFixedArray()) {
   5803         WeakFixedArray* array = WeakFixedArray::cast(prototype_users);
   5804         array->Compact<JSObject::PrototypeRegistryCompactionCallback>();
   5805       }
   5806     } else if (o->IsScript()) {
   5807       CompactWeakFixedArray(Script::cast(o)->shared_function_infos());
   5808     }
   5809   }
   5810   CompactWeakFixedArray(noscript_shared_function_infos());
   5811   CompactWeakFixedArray(script_list());
   5812   CompactWeakFixedArray(weak_stack_trace_list());
   5813 }
   5814 
   5815 void Heap::AddRetainedMap(Handle<Map> map) {
   5816   Handle<WeakCell> cell = Map::WeakCellForMap(map);
   5817   Handle<ArrayList> array(retained_maps(), isolate());
   5818   if (array->IsFull()) {
   5819     CompactRetainedMaps(*array);
   5820   }
   5821   array = ArrayList::Add(
   5822       array, cell, handle(Smi::FromInt(FLAG_retain_maps_for_n_gc), isolate()),
   5823       ArrayList::kReloadLengthAfterAllocation);
   5824   if (*array != retained_maps()) {
   5825     set_retained_maps(*array);
   5826   }
   5827 }
   5828 
   5829 
   5830 void Heap::CompactRetainedMaps(ArrayList* retained_maps) {
   5831   DCHECK_EQ(retained_maps, this->retained_maps());
   5832   int length = retained_maps->Length();
   5833   int new_length = 0;
   5834   int new_number_of_disposed_maps = 0;
   5835   // This loop compacts the array by removing cleared weak cells.
   5836   for (int i = 0; i < length; i += 2) {
   5837     DCHECK(retained_maps->Get(i)->IsWeakCell());
   5838     WeakCell* cell = WeakCell::cast(retained_maps->Get(i));
   5839     Object* age = retained_maps->Get(i + 1);
   5840     if (cell->cleared()) continue;
   5841     if (i != new_length) {
   5842       retained_maps->Set(new_length, cell);
   5843       retained_maps->Set(new_length + 1, age);
   5844     }
   5845     if (i < number_of_disposed_maps_) {
   5846       new_number_of_disposed_maps += 2;
   5847     }
   5848     new_length += 2;
   5849   }
   5850   number_of_disposed_maps_ = new_number_of_disposed_maps;
   5851   Object* undefined = undefined_value();
   5852   for (int i = new_length; i < length; i++) {
   5853     retained_maps->Clear(i, undefined);
   5854   }
   5855   if (new_length != length) retained_maps->SetLength(new_length);
   5856 }
   5857 
   5858 void Heap::FatalProcessOutOfMemory(const char* location, bool is_heap_oom) {
   5859   v8::internal::V8::FatalProcessOutOfMemory(location, is_heap_oom);
   5860 }
   5861 
   5862 #ifdef DEBUG
   5863 
   5864 class PrintHandleVisitor : public ObjectVisitor {
   5865  public:
   5866   void VisitPointers(Object** start, Object** end) override {
   5867     for (Object** p = start; p < end; p++)
   5868       PrintF("  handle %p to %p\n", reinterpret_cast<void*>(p),
   5869              reinterpret_cast<void*>(*p));
   5870   }
   5871 };
   5872 
   5873 
   5874 void Heap::PrintHandles() {
   5875   PrintF("Handles:\n");
   5876   PrintHandleVisitor v;
   5877   isolate_->handle_scope_implementer()->Iterate(&v);
   5878 }
   5879 
   5880 #endif
   5881 
   5882 class CheckHandleCountVisitor : public ObjectVisitor {
   5883  public:
   5884   CheckHandleCountVisitor() : handle_count_(0) {}
   5885   ~CheckHandleCountVisitor() override {
   5886     CHECK(handle_count_ < HandleScope::kCheckHandleThreshold);
   5887   }
   5888   void VisitPointers(Object** start, Object** end) override {
   5889     handle_count_ += end - start;
   5890   }
   5891 
   5892  private:
   5893   ptrdiff_t handle_count_;
   5894 };
   5895 
   5896 
   5897 void Heap::CheckHandleCount() {
   5898   CheckHandleCountVisitor v;
   5899   isolate_->handle_scope_implementer()->Iterate(&v);
   5900 }
   5901 
   5902 void Heap::ClearRecordedSlot(HeapObject* object, Object** slot) {
   5903   if (!InNewSpace(object)) {
   5904     Address slot_addr = reinterpret_cast<Address>(slot);
   5905     Page* page = Page::FromAddress(slot_addr);
   5906     DCHECK_EQ(page->owner()->identity(), OLD_SPACE);
   5907     store_buffer()->DeleteEntry(slot_addr);
   5908     RememberedSet<OLD_TO_OLD>::Remove(page, slot_addr);
   5909   }
   5910 }
   5911 
   5912 void Heap::ClearRecordedSlotRange(Address start, Address end) {
   5913   Page* page = Page::FromAddress(start);
   5914   if (!page->InNewSpace()) {
   5915     DCHECK_EQ(page->owner()->identity(), OLD_SPACE);
   5916     store_buffer()->DeleteEntry(start, end);
   5917     RememberedSet<OLD_TO_OLD>::RemoveRange(page, start, end,
   5918                                            SlotSet::FREE_EMPTY_BUCKETS);
   5919   }
   5920 }
   5921 
   5922 void Heap::RecordWriteIntoCodeSlow(Code* host, RelocInfo* rinfo,
   5923                                    Object* value) {
   5924   DCHECK(InNewSpace(value));
   5925   Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host));
   5926   RelocInfo::Mode rmode = rinfo->rmode();
   5927   Address addr = rinfo->pc();
   5928   SlotType slot_type = SlotTypeForRelocInfoMode(rmode);
   5929   if (rinfo->IsInConstantPool()) {
   5930     addr = rinfo->constant_pool_entry_address();
   5931     if (RelocInfo::IsCodeTarget(rmode)) {
   5932       slot_type = CODE_ENTRY_SLOT;
   5933     } else {
   5934       DCHECK(RelocInfo::IsEmbeddedObject(rmode));
   5935       slot_type = OBJECT_SLOT;
   5936     }
   5937   }
   5938   RememberedSet<OLD_TO_NEW>::InsertTyped(
   5939       source_page, reinterpret_cast<Address>(host), slot_type, addr);
   5940 }
   5941 
   5942 void Heap::RecordWritesIntoCode(Code* code) {
   5943   for (RelocIterator it(code, RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT));
   5944        !it.done(); it.next()) {
   5945     RecordWriteIntoCode(code, it.rinfo(), it.rinfo()->target_object());
   5946   }
   5947 }
   5948 
   5949 Space* AllSpaces::next() {
   5950   switch (counter_++) {
   5951     case NEW_SPACE:
   5952       return heap_->new_space();
   5953     case OLD_SPACE:
   5954       return heap_->old_space();
   5955     case CODE_SPACE:
   5956       return heap_->code_space();
   5957     case MAP_SPACE:
   5958       return heap_->map_space();
   5959     case LO_SPACE:
   5960       return heap_->lo_space();
   5961     default:
   5962       return NULL;
   5963   }
   5964 }
   5965 
   5966 PagedSpace* PagedSpaces::next() {
   5967   switch (counter_++) {
   5968     case OLD_SPACE:
   5969       return heap_->old_space();
   5970     case CODE_SPACE:
   5971       return heap_->code_space();
   5972     case MAP_SPACE:
   5973       return heap_->map_space();
   5974     default:
   5975       return NULL;
   5976   }
   5977 }
   5978 
   5979 
   5980 OldSpace* OldSpaces::next() {
   5981   switch (counter_++) {
   5982     case OLD_SPACE:
   5983       return heap_->old_space();
   5984     case CODE_SPACE:
   5985       return heap_->code_space();
   5986     default:
   5987       return NULL;
   5988   }
   5989 }
   5990 
   5991 SpaceIterator::SpaceIterator(Heap* heap)
   5992     : heap_(heap), current_space_(FIRST_SPACE - 1) {}
   5993 
   5994 SpaceIterator::~SpaceIterator() {
   5995 }
   5996 
   5997 
   5998 bool SpaceIterator::has_next() {
   5999   // Iterate until no more spaces.
   6000   return current_space_ != LAST_SPACE;
   6001 }
   6002 
   6003 Space* SpaceIterator::next() {
   6004   DCHECK(has_next());
   6005   return heap_->space(++current_space_);
   6006 }
   6007 
   6008 
   6009 class HeapObjectsFilter {
   6010  public:
   6011   virtual ~HeapObjectsFilter() {}
   6012   virtual bool SkipObject(HeapObject* object) = 0;
   6013 };
   6014 
   6015 
   6016 class UnreachableObjectsFilter : public HeapObjectsFilter {
   6017  public:
   6018   explicit UnreachableObjectsFilter(Heap* heap) : heap_(heap) {
   6019     MarkReachableObjects();
   6020   }
   6021 
   6022   ~UnreachableObjectsFilter() {
   6023     heap_->mark_compact_collector()->ClearMarkbits();
   6024   }
   6025 
   6026   bool SkipObject(HeapObject* object) {
   6027     if (object->IsFiller()) return true;
   6028     MarkBit mark_bit = ObjectMarking::MarkBitFrom(object);
   6029     return Marking::IsWhite(mark_bit);
   6030   }
   6031 
   6032  private:
   6033   class MarkingVisitor : public ObjectVisitor {
   6034    public:
   6035     MarkingVisitor() : marking_stack_(10) {}
   6036 
   6037     void VisitPointers(Object** start, Object** end) override {
   6038       for (Object** p = start; p < end; p++) {
   6039         if (!(*p)->IsHeapObject()) continue;
   6040         HeapObject* obj = HeapObject::cast(*p);
   6041         MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj);
   6042         if (Marking::IsWhite(mark_bit)) {
   6043           Marking::WhiteToBlack(mark_bit);
   6044           marking_stack_.Add(obj);
   6045         }
   6046       }
   6047     }
   6048 
   6049     void TransitiveClosure() {
   6050       while (!marking_stack_.is_empty()) {
   6051         HeapObject* obj = marking_stack_.RemoveLast();
   6052         obj->Iterate(this);
   6053       }
   6054     }
   6055 
   6056    private:
   6057     List<HeapObject*> marking_stack_;
   6058   };
   6059 
   6060   void MarkReachableObjects() {
   6061     MarkingVisitor visitor;
   6062     heap_->IterateRoots(&visitor, VISIT_ALL);
   6063     visitor.TransitiveClosure();
   6064   }
   6065 
   6066   Heap* heap_;
   6067   DisallowHeapAllocation no_allocation_;
   6068 };
   6069 
   6070 
   6071 HeapIterator::HeapIterator(Heap* heap,
   6072                            HeapIterator::HeapObjectsFiltering filtering)
   6073     : make_heap_iterable_helper_(heap),
   6074       no_heap_allocation_(),
   6075       heap_(heap),
   6076       filtering_(filtering),
   6077       filter_(nullptr),
   6078       space_iterator_(nullptr),
   6079       object_iterator_(nullptr) {
   6080   heap_->heap_iterator_start();
   6081   // Start the iteration.
   6082   space_iterator_ = new SpaceIterator(heap_);
   6083   switch (filtering_) {
   6084     case kFilterUnreachable:
   6085       filter_ = new UnreachableObjectsFilter(heap_);
   6086       break;
   6087     default:
   6088       break;
   6089   }
   6090   object_iterator_ = space_iterator_->next()->GetObjectIterator();
   6091 }
   6092 
   6093 
   6094 HeapIterator::~HeapIterator() {
   6095   heap_->heap_iterator_end();
   6096 #ifdef DEBUG
   6097   // Assert that in filtering mode we have iterated through all
   6098   // objects. Otherwise, heap will be left in an inconsistent state.
   6099   if (filtering_ != kNoFiltering) {
   6100     DCHECK(object_iterator_ == nullptr);
   6101   }
   6102 #endif
   6103   delete space_iterator_;
   6104   delete filter_;
   6105 }
   6106 
   6107 
   6108 HeapObject* HeapIterator::next() {
   6109   if (filter_ == nullptr) return NextObject();
   6110 
   6111   HeapObject* obj = NextObject();
   6112   while ((obj != nullptr) && (filter_->SkipObject(obj))) obj = NextObject();
   6113   return obj;
   6114 }
   6115 
   6116 
   6117 HeapObject* HeapIterator::NextObject() {
   6118   // No iterator means we are done.
   6119   if (object_iterator_.get() == nullptr) return nullptr;
   6120 
   6121   if (HeapObject* obj = object_iterator_.get()->Next()) {
   6122     // If the current iterator has more objects we are fine.
   6123     return obj;
   6124   } else {
   6125     // Go though the spaces looking for one that has objects.
   6126     while (space_iterator_->has_next()) {
   6127       object_iterator_ = space_iterator_->next()->GetObjectIterator();
   6128       if (HeapObject* obj = object_iterator_.get()->Next()) {
   6129         return obj;
   6130       }
   6131     }
   6132   }
   6133   // Done with the last space.
   6134   object_iterator_.reset(nullptr);
   6135   return nullptr;
   6136 }
   6137 
   6138 
   6139 #ifdef DEBUG
   6140 
   6141 Object* const PathTracer::kAnyGlobalObject = NULL;
   6142 
   6143 class PathTracer::MarkVisitor : public ObjectVisitor {
   6144  public:
   6145   explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
   6146 
   6147   void VisitPointers(Object** start, Object** end) override {
   6148     // Scan all HeapObject pointers in [start, end)
   6149     for (Object** p = start; !tracer_->found() && (p < end); p++) {
   6150       if ((*p)->IsHeapObject()) tracer_->MarkRecursively(p, this);
   6151     }
   6152   }
   6153 
   6154  private:
   6155   PathTracer* tracer_;
   6156 };
   6157 
   6158 
   6159 class PathTracer::UnmarkVisitor : public ObjectVisitor {
   6160  public:
   6161   explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
   6162 
   6163   void VisitPointers(Object** start, Object** end) override {
   6164     // Scan all HeapObject pointers in [start, end)
   6165     for (Object** p = start; p < end; p++) {
   6166       if ((*p)->IsHeapObject()) tracer_->UnmarkRecursively(p, this);
   6167     }
   6168   }
   6169 
   6170  private:
   6171   PathTracer* tracer_;
   6172 };
   6173 
   6174 
   6175 void PathTracer::VisitPointers(Object** start, Object** end) {
   6176   bool done = ((what_to_find_ == FIND_FIRST) && found_target_);
   6177   // Visit all HeapObject pointers in [start, end)
   6178   for (Object** p = start; !done && (p < end); p++) {
   6179     if ((*p)->IsHeapObject()) {
   6180       TracePathFrom(p);
   6181       done = ((what_to_find_ == FIND_FIRST) && found_target_);
   6182     }
   6183   }
   6184 }
   6185 
   6186 
   6187 void PathTracer::Reset() {
   6188   found_target_ = false;
   6189   object_stack_.Clear();
   6190 }
   6191 
   6192 
   6193 void PathTracer::TracePathFrom(Object** root) {
   6194   DCHECK((search_target_ == kAnyGlobalObject) ||
   6195          search_target_->IsHeapObject());
   6196   found_target_in_trace_ = false;
   6197   Reset();
   6198 
   6199   MarkVisitor mark_visitor(this);
   6200   MarkRecursively(root, &mark_visitor);
   6201 
   6202   UnmarkVisitor unmark_visitor(this);
   6203   UnmarkRecursively(root, &unmark_visitor);
   6204 
   6205   ProcessResults();
   6206 }
   6207 
   6208 
   6209 static bool SafeIsNativeContext(HeapObject* obj) {
   6210   return obj->map() == obj->GetHeap()->root(Heap::kNativeContextMapRootIndex);
   6211 }
   6212 
   6213 
   6214 void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) {
   6215   if (!(*p)->IsHeapObject()) return;
   6216 
   6217   HeapObject* obj = HeapObject::cast(*p);
   6218 
   6219   MapWord map_word = obj->map_word();
   6220   if (!map_word.ToMap()->IsHeapObject()) return;  // visited before
   6221 
   6222   if (found_target_in_trace_) return;  // stop if target found
   6223   object_stack_.Add(obj);
   6224   if (((search_target_ == kAnyGlobalObject) && obj->IsJSGlobalObject()) ||
   6225       (obj == search_target_)) {
   6226     found_target_in_trace_ = true;
   6227     found_target_ = true;
   6228     return;
   6229   }
   6230 
   6231   bool is_native_context = SafeIsNativeContext(obj);
   6232 
   6233   // not visited yet
   6234   Map* map = Map::cast(map_word.ToMap());
   6235 
   6236   MapWord marked_map_word =
   6237       MapWord::FromRawValue(obj->map_word().ToRawValue() + kMarkTag);
   6238   obj->set_map_word(marked_map_word);
   6239 
   6240   // Scan the object body.
   6241   if (is_native_context && (visit_mode_ == VISIT_ONLY_STRONG)) {
   6242     // This is specialized to scan Context's properly.
   6243     Object** start =
   6244         reinterpret_cast<Object**>(obj->address() + Context::kHeaderSize);
   6245     Object** end =
   6246         reinterpret_cast<Object**>(obj->address() + Context::kHeaderSize +
   6247                                    Context::FIRST_WEAK_SLOT * kPointerSize);
   6248     mark_visitor->VisitPointers(start, end);
   6249   } else {
   6250     obj->IterateBody(map->instance_type(), obj->SizeFromMap(map), mark_visitor);
   6251   }
   6252 
   6253   // Scan the map after the body because the body is a lot more interesting
   6254   // when doing leak detection.
   6255   MarkRecursively(reinterpret_cast<Object**>(&map), mark_visitor);
   6256 
   6257   if (!found_target_in_trace_) {  // don't pop if found the target
   6258     object_stack_.RemoveLast();
   6259   }
   6260 }
   6261 
   6262 
   6263 void PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) {
   6264   if (!(*p)->IsHeapObject()) return;
   6265 
   6266   HeapObject* obj = HeapObject::cast(*p);
   6267 
   6268   MapWord map_word = obj->map_word();
   6269   if (map_word.ToMap()->IsHeapObject()) return;  // unmarked already
   6270 
   6271   MapWord unmarked_map_word =
   6272       MapWord::FromRawValue(map_word.ToRawValue() - kMarkTag);
   6273   obj->set_map_word(unmarked_map_word);
   6274 
   6275   Map* map = Map::cast(unmarked_map_word.ToMap());
   6276 
   6277   UnmarkRecursively(reinterpret_cast<Object**>(&map), unmark_visitor);
   6278 
   6279   obj->IterateBody(map->instance_type(), obj->SizeFromMap(map), unmark_visitor);
   6280 }
   6281 
   6282 
   6283 void PathTracer::ProcessResults() {
   6284   if (found_target_) {
   6285     OFStream os(stdout);
   6286     os << "=====================================\n"
   6287        << "====        Path to object       ====\n"
   6288        << "=====================================\n\n";
   6289 
   6290     DCHECK(!object_stack_.is_empty());
   6291     for (int i = 0; i < object_stack_.length(); i++) {
   6292       if (i > 0) os << "\n     |\n     |\n     V\n\n";
   6293       object_stack_[i]->Print(os);
   6294     }
   6295     os << "=====================================\n";
   6296   }
   6297 }
   6298 
   6299 
   6300 // Triggers a depth-first traversal of reachable objects from one
   6301 // given root object and finds a path to a specific heap object and
   6302 // prints it.
   6303 void Heap::TracePathToObjectFrom(Object* target, Object* root) {
   6304   PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL);
   6305   tracer.VisitPointer(&root);
   6306 }
   6307 
   6308 
   6309 // Triggers a depth-first traversal of reachable objects from roots
   6310 // and finds a path to a specific heap object and prints it.
   6311 void Heap::TracePathToObject(Object* target) {
   6312   PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL);
   6313   IterateRoots(&tracer, VISIT_ONLY_STRONG);
   6314 }
   6315 
   6316 
   6317 // Triggers a depth-first traversal of reachable objects from roots
   6318 // and finds a path to any global object and prints it. Useful for
   6319 // determining the source for leaks of global objects.
   6320 void Heap::TracePathToGlobal() {
   6321   PathTracer tracer(PathTracer::kAnyGlobalObject, PathTracer::FIND_ALL,
   6322                     VISIT_ALL);
   6323   IterateRoots(&tracer, VISIT_ONLY_STRONG);
   6324 }
   6325 #endif
   6326 
   6327 void Heap::UpdateTotalGCTime(double duration) {
   6328   if (FLAG_trace_gc_verbose) {
   6329     total_gc_time_ms_ += duration;
   6330   }
   6331 }
   6332 
   6333 void Heap::ExternalStringTable::CleanUp() {
   6334   int last = 0;
   6335   Isolate* isolate = heap_->isolate();
   6336   for (int i = 0; i < new_space_strings_.length(); ++i) {
   6337     if (new_space_strings_[i]->IsTheHole(isolate)) {
   6338       continue;
   6339     }
   6340     DCHECK(new_space_strings_[i]->IsExternalString());
   6341     if (heap_->InNewSpace(new_space_strings_[i])) {
   6342       new_space_strings_[last++] = new_space_strings_[i];
   6343     } else {
   6344       old_space_strings_.Add(new_space_strings_[i]);
   6345     }
   6346   }
   6347   new_space_strings_.Rewind(last);
   6348   new_space_strings_.Trim();
   6349 
   6350   last = 0;
   6351   for (int i = 0; i < old_space_strings_.length(); ++i) {
   6352     if (old_space_strings_[i]->IsTheHole(isolate)) {
   6353       continue;
   6354     }
   6355     DCHECK(old_space_strings_[i]->IsExternalString());
   6356     DCHECK(!heap_->InNewSpace(old_space_strings_[i]));
   6357     old_space_strings_[last++] = old_space_strings_[i];
   6358   }
   6359   old_space_strings_.Rewind(last);
   6360   old_space_strings_.Trim();
   6361 #ifdef VERIFY_HEAP
   6362   if (FLAG_verify_heap) {
   6363     Verify();
   6364   }
   6365 #endif
   6366 }
   6367 
   6368 void Heap::ExternalStringTable::TearDown() {
   6369   for (int i = 0; i < new_space_strings_.length(); ++i) {
   6370     heap_->FinalizeExternalString(ExternalString::cast(new_space_strings_[i]));
   6371   }
   6372   new_space_strings_.Free();
   6373   for (int i = 0; i < old_space_strings_.length(); ++i) {
   6374     heap_->FinalizeExternalString(ExternalString::cast(old_space_strings_[i]));
   6375   }
   6376   old_space_strings_.Free();
   6377 }
   6378 
   6379 
   6380 void Heap::RememberUnmappedPage(Address page, bool compacted) {
   6381   uintptr_t p = reinterpret_cast<uintptr_t>(page);
   6382   // Tag the page pointer to make it findable in the dump file.
   6383   if (compacted) {
   6384     p ^= 0xc1ead & (Page::kPageSize - 1);  // Cleared.
   6385   } else {
   6386     p ^= 0x1d1ed & (Page::kPageSize - 1);  // I died.
   6387   }
   6388   remembered_unmapped_pages_[remembered_unmapped_pages_index_] =
   6389       reinterpret_cast<Address>(p);
   6390   remembered_unmapped_pages_index_++;
   6391   remembered_unmapped_pages_index_ %= kRememberedUnmappedPages;
   6392 }
   6393 
   6394 
   6395 void Heap::RegisterStrongRoots(Object** start, Object** end) {
   6396   StrongRootsList* list = new StrongRootsList();
   6397   list->next = strong_roots_list_;
   6398   list->start = start;
   6399   list->end = end;
   6400   strong_roots_list_ = list;
   6401 }
   6402 
   6403 
   6404 void Heap::UnregisterStrongRoots(Object** start) {
   6405   StrongRootsList* prev = NULL;
   6406   StrongRootsList* list = strong_roots_list_;
   6407   while (list != nullptr) {
   6408     StrongRootsList* next = list->next;
   6409     if (list->start == start) {
   6410       if (prev) {
   6411         prev->next = next;
   6412       } else {
   6413         strong_roots_list_ = next;
   6414       }
   6415       delete list;
   6416     } else {
   6417       prev = list;
   6418     }
   6419     list = next;
   6420   }
   6421 }
   6422 
   6423 
   6424 size_t Heap::NumberOfTrackedHeapObjectTypes() {
   6425   return ObjectStats::OBJECT_STATS_COUNT;
   6426 }
   6427 
   6428 
   6429 size_t Heap::ObjectCountAtLastGC(size_t index) {
   6430   if (live_object_stats_ == nullptr || index >= ObjectStats::OBJECT_STATS_COUNT)
   6431     return 0;
   6432   return live_object_stats_->object_count_last_gc(index);
   6433 }
   6434 
   6435 
   6436 size_t Heap::ObjectSizeAtLastGC(size_t index) {
   6437   if (live_object_stats_ == nullptr || index >= ObjectStats::OBJECT_STATS_COUNT)
   6438     return 0;
   6439   return live_object_stats_->object_size_last_gc(index);
   6440 }
   6441 
   6442 
   6443 bool Heap::GetObjectTypeName(size_t index, const char** object_type,
   6444                              const char** object_sub_type) {
   6445   if (index >= ObjectStats::OBJECT_STATS_COUNT) return false;
   6446 
   6447   switch (static_cast<int>(index)) {
   6448 #define COMPARE_AND_RETURN_NAME(name) \
   6449   case name:                          \
   6450     *object_type = #name;             \
   6451     *object_sub_type = "";            \
   6452     return true;
   6453     INSTANCE_TYPE_LIST(COMPARE_AND_RETURN_NAME)
   6454 #undef COMPARE_AND_RETURN_NAME
   6455 #define COMPARE_AND_RETURN_NAME(name)                      \
   6456   case ObjectStats::FIRST_CODE_KIND_SUB_TYPE + Code::name: \
   6457     *object_type = "CODE_TYPE";                            \
   6458     *object_sub_type = "CODE_KIND/" #name;                 \
   6459     return true;
   6460     CODE_KIND_LIST(COMPARE_AND_RETURN_NAME)
   6461 #undef COMPARE_AND_RETURN_NAME
   6462 #define COMPARE_AND_RETURN_NAME(name)                  \
   6463   case ObjectStats::FIRST_FIXED_ARRAY_SUB_TYPE + name: \
   6464     *object_type = "FIXED_ARRAY_TYPE";                 \
   6465     *object_sub_type = #name;                          \
   6466     return true;
   6467     FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(COMPARE_AND_RETURN_NAME)
   6468 #undef COMPARE_AND_RETURN_NAME
   6469 #define COMPARE_AND_RETURN_NAME(name)                                  \
   6470   case ObjectStats::FIRST_CODE_AGE_SUB_TYPE + Code::k##name##CodeAge - \
   6471       Code::kFirstCodeAge:                                             \
   6472     *object_type = "CODE_TYPE";                                        \
   6473     *object_sub_type = "CODE_AGE/" #name;                              \
   6474     return true;
   6475     CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME)
   6476 #undef COMPARE_AND_RETURN_NAME
   6477   }
   6478   return false;
   6479 }
   6480 
   6481 
   6482 // static
   6483 int Heap::GetStaticVisitorIdForMap(Map* map) {
   6484   return StaticVisitorBase::GetVisitorId(map);
   6485 }
   6486 
   6487 }  // namespace internal
   6488 }  // namespace v8
   6489