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