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