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 <unordered_map>
      8 #include <unordered_set>
      9 
     10 #include "src/accessors.h"
     11 #include "src/api-inl.h"
     12 #include "src/assembler-inl.h"
     13 #include "src/ast/context-slot-cache.h"
     14 #include "src/base/bits.h"
     15 #include "src/base/once.h"
     16 #include "src/base/utils/random-number-generator.h"
     17 #include "src/bootstrapper.h"
     18 #include "src/code-stubs.h"
     19 #include "src/compilation-cache.h"
     20 #include "src/conversions.h"
     21 #include "src/debug/debug.h"
     22 #include "src/deoptimizer.h"
     23 #include "src/feedback-vector.h"
     24 #include "src/global-handles.h"
     25 #include "src/heap/array-buffer-collector.h"
     26 #include "src/heap/array-buffer-tracker-inl.h"
     27 #include "src/heap/barrier.h"
     28 #include "src/heap/code-stats.h"
     29 #include "src/heap/concurrent-marking.h"
     30 #include "src/heap/embedder-tracing.h"
     31 #include "src/heap/gc-idle-time-handler.h"
     32 #include "src/heap/gc-tracer.h"
     33 #include "src/heap/heap-controller.h"
     34 #include "src/heap/heap-write-barrier-inl.h"
     35 #include "src/heap/incremental-marking.h"
     36 #include "src/heap/item-parallel-job.h"
     37 #include "src/heap/mark-compact-inl.h"
     38 #include "src/heap/mark-compact.h"
     39 #include "src/heap/memory-reducer.h"
     40 #include "src/heap/object-stats.h"
     41 #include "src/heap/objects-visiting-inl.h"
     42 #include "src/heap/objects-visiting.h"
     43 #include "src/heap/remembered-set.h"
     44 #include "src/heap/scavenge-job.h"
     45 #include "src/heap/scavenger-inl.h"
     46 #include "src/heap/store-buffer.h"
     47 #include "src/heap/stress-marking-observer.h"
     48 #include "src/heap/stress-scavenge-observer.h"
     49 #include "src/heap/sweeper.h"
     50 #include "src/instruction-stream.h"
     51 #include "src/interpreter/interpreter.h"
     52 #include "src/objects/data-handler.h"
     53 #include "src/objects/hash-table-inl.h"
     54 #include "src/objects/maybe-object.h"
     55 #include "src/objects/shared-function-info.h"
     56 #include "src/regexp/jsregexp.h"
     57 #include "src/runtime-profiler.h"
     58 #include "src/snapshot/natives.h"
     59 #include "src/snapshot/serializer-common.h"
     60 #include "src/snapshot/snapshot.h"
     61 #include "src/tracing/trace-event.h"
     62 #include "src/unicode-decoder.h"
     63 #include "src/unicode-inl.h"
     64 #include "src/utils-inl.h"
     65 #include "src/utils.h"
     66 #include "src/v8.h"
     67 #include "src/vm-state-inl.h"
     68 
     69 // Has to be the last include (doesn't have include guards):
     70 #include "src/objects/object-macros.h"
     71 
     72 namespace v8 {
     73 namespace internal {
     74 
     75 void Heap::SetArgumentsAdaptorDeoptPCOffset(int pc_offset) {
     76   DCHECK_EQ(Smi::kZero, arguments_adaptor_deopt_pc_offset());
     77   set_arguments_adaptor_deopt_pc_offset(Smi::FromInt(pc_offset));
     78 }
     79 
     80 void Heap::SetConstructStubCreateDeoptPCOffset(int pc_offset) {
     81   DCHECK(construct_stub_create_deopt_pc_offset() == Smi::kZero);
     82   set_construct_stub_create_deopt_pc_offset(Smi::FromInt(pc_offset));
     83 }
     84 
     85 void Heap::SetConstructStubInvokeDeoptPCOffset(int pc_offset) {
     86   DCHECK(construct_stub_invoke_deopt_pc_offset() == Smi::kZero);
     87   set_construct_stub_invoke_deopt_pc_offset(Smi::FromInt(pc_offset));
     88 }
     89 
     90 void Heap::SetInterpreterEntryReturnPCOffset(int pc_offset) {
     91   DCHECK_EQ(Smi::kZero, interpreter_entry_return_pc_offset());
     92   set_interpreter_entry_return_pc_offset(Smi::FromInt(pc_offset));
     93 }
     94 
     95 void Heap::SetSerializedObjects(FixedArray* objects) {
     96   DCHECK(isolate()->serializer_enabled());
     97   set_serialized_objects(objects);
     98 }
     99 
    100 void Heap::SetSerializedGlobalProxySizes(FixedArray* sizes) {
    101   DCHECK(isolate()->serializer_enabled());
    102   set_serialized_global_proxy_sizes(sizes);
    103 }
    104 
    105 bool Heap::GCCallbackTuple::operator==(
    106     const Heap::GCCallbackTuple& other) const {
    107   return other.callback == callback && other.data == data;
    108 }
    109 
    110 Heap::GCCallbackTuple& Heap::GCCallbackTuple::operator=(
    111     const Heap::GCCallbackTuple& other) {
    112   callback = other.callback;
    113   gc_type = other.gc_type;
    114   data = other.data;
    115   return *this;
    116 }
    117 
    118 struct Heap::StrongRootsList {
    119   Object** start;
    120   Object** end;
    121   StrongRootsList* next;
    122 };
    123 
    124 class IdleScavengeObserver : public AllocationObserver {
    125  public:
    126   IdleScavengeObserver(Heap& heap, intptr_t step_size)
    127       : AllocationObserver(step_size), heap_(heap) {}
    128 
    129   void Step(int bytes_allocated, Address, size_t) override {
    130     heap_.ScheduleIdleScavengeIfNeeded(bytes_allocated);
    131   }
    132 
    133  private:
    134   Heap& heap_;
    135 };
    136 
    137 Heap::Heap()
    138     : external_memory_(0),
    139       external_memory_limit_(kExternalAllocationSoftLimit),
    140       external_memory_at_last_mark_compact_(0),
    141       external_memory_concurrently_freed_(0),
    142       isolate_(nullptr),
    143       code_range_size_(0),
    144       // semispace_size_ should be a power of 2 and old_generation_size_ should
    145       // be a multiple of Page::kPageSize.
    146       max_semi_space_size_(8 * (kPointerSize / 4) * MB),
    147       initial_semispace_size_(kMinSemiSpaceSizeInKB * KB),
    148       max_old_generation_size_(700ul * (kPointerSize / 4) * MB),
    149       initial_max_old_generation_size_(max_old_generation_size_),
    150       initial_old_generation_size_(max_old_generation_size_ /
    151                                    kInitalOldGenerationLimitFactor),
    152       old_generation_size_configured_(false),
    153       // Variables set based on semispace_size_ and old_generation_size_ in
    154       // ConfigureHeap.
    155       // Will be 4 * reserved_semispace_size_ to ensure that young
    156       // generation can be aligned to its size.
    157       maximum_committed_(0),
    158       survived_since_last_expansion_(0),
    159       survived_last_scavenge_(0),
    160       always_allocate_scope_count_(0),
    161       memory_pressure_level_(MemoryPressureLevel::kNone),
    162       contexts_disposed_(0),
    163       number_of_disposed_maps_(0),
    164       new_space_(nullptr),
    165       old_space_(nullptr),
    166       code_space_(nullptr),
    167       map_space_(nullptr),
    168       lo_space_(nullptr),
    169       new_lo_space_(nullptr),
    170       read_only_space_(nullptr),
    171       write_protect_code_memory_(false),
    172       code_space_memory_modification_scope_depth_(0),
    173       gc_state_(NOT_IN_GC),
    174       gc_post_processing_depth_(0),
    175       allocations_count_(0),
    176       raw_allocations_hash_(0),
    177       stress_marking_observer_(nullptr),
    178       stress_scavenge_observer_(nullptr),
    179       allocation_step_in_progress_(false),
    180       max_marking_limit_reached_(0.0),
    181       ms_count_(0),
    182       gc_count_(0),
    183       consecutive_ineffective_mark_compacts_(0),
    184       mmap_region_base_(0),
    185       remembered_unmapped_pages_index_(0),
    186       old_generation_allocation_limit_(initial_old_generation_size_),
    187       inline_allocation_disabled_(false),
    188       tracer_(nullptr),
    189       promoted_objects_size_(0),
    190       promotion_ratio_(0),
    191       semi_space_copied_object_size_(0),
    192       previous_semi_space_copied_object_size_(0),
    193       semi_space_copied_rate_(0),
    194       nodes_died_in_new_space_(0),
    195       nodes_copied_in_new_space_(0),
    196       nodes_promoted_(0),
    197       maximum_size_scavenges_(0),
    198       last_idle_notification_time_(0.0),
    199       last_gc_time_(0.0),
    200       mark_compact_collector_(nullptr),
    201       minor_mark_compact_collector_(nullptr),
    202       array_buffer_collector_(nullptr),
    203       memory_allocator_(nullptr),
    204       store_buffer_(nullptr),
    205       incremental_marking_(nullptr),
    206       concurrent_marking_(nullptr),
    207       gc_idle_time_handler_(nullptr),
    208       memory_reducer_(nullptr),
    209       live_object_stats_(nullptr),
    210       dead_object_stats_(nullptr),
    211       scavenge_job_(nullptr),
    212       parallel_scavenge_semaphore_(0),
    213       idle_scavenge_observer_(nullptr),
    214       new_space_allocation_counter_(0),
    215       old_generation_allocation_counter_at_last_gc_(0),
    216       old_generation_size_at_last_gc_(0),
    217       global_pretenuring_feedback_(kInitialFeedbackCapacity),
    218       is_marking_flag_(false),
    219       ring_buffer_full_(false),
    220       ring_buffer_end_(0),
    221       configured_(false),
    222       current_gc_flags_(Heap::kNoGCFlags),
    223       current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags),
    224       external_string_table_(this),
    225       gc_callbacks_depth_(0),
    226       deserialization_complete_(false),
    227       strong_roots_list_(nullptr),
    228       heap_iterator_depth_(0),
    229       local_embedder_heap_tracer_(nullptr),
    230       fast_promotion_mode_(false),
    231       force_oom_(false),
    232       delay_sweeper_tasks_for_testing_(false),
    233       pending_layout_change_object_(nullptr),
    234       unprotected_memory_chunks_registry_enabled_(false)
    235 #ifdef V8_ENABLE_ALLOCATION_TIMEOUT
    236       ,
    237       allocation_timeout_(0)
    238 #endif  // V8_ENABLE_ALLOCATION_TIMEOUT
    239 {
    240   // Ensure old_generation_size_ is a multiple of kPageSize.
    241   DCHECK_EQ(0, max_old_generation_size_ & (Page::kPageSize - 1));
    242 
    243   memset(roots_, 0, sizeof(roots_[0]) * kRootListLength);
    244   set_native_contexts_list(nullptr);
    245   set_allocation_sites_list(Smi::kZero);
    246   // Put a dummy entry in the remembered pages so we can find the list the
    247   // minidump even if there are no real unmapped pages.
    248   RememberUnmappedPage(kNullAddress, false);
    249 }
    250 
    251 size_t Heap::MaxReserved() {
    252   const double kFactor = Page::kPageSize * 1.0 / Page::kAllocatableMemory;
    253   return static_cast<size_t>(
    254       (2 * max_semi_space_size_ + max_old_generation_size_) * kFactor);
    255 }
    256 
    257 size_t Heap::ComputeMaxOldGenerationSize(uint64_t physical_memory) {
    258   const size_t old_space_physical_memory_factor = 4;
    259   size_t computed_size = static_cast<size_t>(physical_memory / i::MB /
    260                                              old_space_physical_memory_factor *
    261                                              kPointerMultiplier);
    262   return Max(Min(computed_size, HeapController::kMaxHeapSize),
    263              HeapController::kMinHeapSize);
    264 }
    265 
    266 size_t Heap::Capacity() {
    267   if (!HasBeenSetUp()) return 0;
    268 
    269   return new_space_->Capacity() + OldGenerationCapacity();
    270 }
    271 
    272 size_t Heap::OldGenerationCapacity() {
    273   if (!HasBeenSetUp()) return 0;
    274   PagedSpaces spaces(this, PagedSpaces::SpacesSpecifier::kAllPagedSpaces);
    275   size_t total = 0;
    276   for (PagedSpace* space = spaces.next(); space != nullptr;
    277        space = spaces.next()) {
    278     total += space->Capacity();
    279   }
    280   return total + lo_space_->SizeOfObjects();
    281 }
    282 
    283 size_t Heap::CommittedOldGenerationMemory() {
    284   if (!HasBeenSetUp()) return 0;
    285 
    286   PagedSpaces spaces(this, PagedSpaces::SpacesSpecifier::kAllPagedSpaces);
    287   size_t total = 0;
    288   for (PagedSpace* space = spaces.next(); space != nullptr;
    289        space = spaces.next()) {
    290     total += space->CommittedMemory();
    291   }
    292   return total + lo_space_->Size();
    293 }
    294 
    295 size_t Heap::CommittedMemoryOfHeapAndUnmapper() {
    296   if (!HasBeenSetUp()) return 0;
    297 
    298   return CommittedMemory() +
    299          memory_allocator()->unmapper()->CommittedBufferedMemory();
    300 }
    301 
    302 size_t Heap::CommittedMemory() {
    303   if (!HasBeenSetUp()) return 0;
    304 
    305   return new_space_->CommittedMemory() + CommittedOldGenerationMemory();
    306 }
    307 
    308 
    309 size_t Heap::CommittedPhysicalMemory() {
    310   if (!HasBeenSetUp()) return 0;
    311 
    312   size_t total = 0;
    313   for (SpaceIterator it(this); it.has_next();) {
    314     total += it.next()->CommittedPhysicalMemory();
    315   }
    316 
    317   return total;
    318 }
    319 
    320 size_t Heap::CommittedMemoryExecutable() {
    321   if (!HasBeenSetUp()) return 0;
    322 
    323   return static_cast<size_t>(memory_allocator()->SizeExecutable());
    324 }
    325 
    326 
    327 void Heap::UpdateMaximumCommitted() {
    328   if (!HasBeenSetUp()) return;
    329 
    330   const size_t current_committed_memory = CommittedMemory();
    331   if (current_committed_memory > maximum_committed_) {
    332     maximum_committed_ = current_committed_memory;
    333   }
    334 }
    335 
    336 size_t Heap::Available() {
    337   if (!HasBeenSetUp()) return 0;
    338 
    339   size_t total = 0;
    340 
    341   for (SpaceIterator it(this); it.has_next();) {
    342     total += it.next()->Available();
    343   }
    344   return total;
    345 }
    346 
    347 bool Heap::CanExpandOldGeneration(size_t size) {
    348   if (force_oom_) return false;
    349   if (OldGenerationCapacity() + size > MaxOldGenerationSize()) return false;
    350   // The OldGenerationCapacity does not account compaction spaces used
    351   // during evacuation. Ensure that expanding the old generation does push
    352   // the total allocated memory size over the maximum heap size.
    353   return memory_allocator()->Size() + size <= MaxReserved();
    354 }
    355 
    356 bool Heap::HasBeenSetUp() {
    357   // We will always have a new space when the heap is set up.
    358   return new_space_ != nullptr;
    359 }
    360 
    361 
    362 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space,
    363                                               const char** reason) {
    364   // Is global GC requested?
    365   if (space != NEW_SPACE) {
    366     isolate_->counters()->gc_compactor_caused_by_request()->Increment();
    367     *reason = "GC in old space requested";
    368     return MARK_COMPACTOR;
    369   }
    370 
    371   if (FLAG_gc_global || (FLAG_stress_compaction && (gc_count_ & 1) != 0)) {
    372     *reason = "GC in old space forced by flags";
    373     return MARK_COMPACTOR;
    374   }
    375 
    376   if (incremental_marking()->NeedsFinalization() &&
    377       AllocationLimitOvershotByLargeMargin()) {
    378     *reason = "Incremental marking needs finalization";
    379     return MARK_COMPACTOR;
    380   }
    381 
    382   // Over-estimate the new space size using capacity to allow some slack.
    383   if (!CanExpandOldGeneration(new_space_->TotalCapacity())) {
    384     isolate_->counters()
    385         ->gc_compactor_caused_by_oldspace_exhaustion()
    386         ->Increment();
    387     *reason = "scavenge might not succeed";
    388     return MARK_COMPACTOR;
    389   }
    390 
    391   // Default
    392   *reason = nullptr;
    393   return YoungGenerationCollector();
    394 }
    395 
    396 void Heap::SetGCState(HeapState state) {
    397   gc_state_ = state;
    398 }
    399 
    400 void Heap::PrintShortHeapStatistics() {
    401   if (!FLAG_trace_gc_verbose) return;
    402   PrintIsolate(isolate_,
    403                "Memory allocator,       used: %6" PRIuS
    404                " KB,"
    405                " available: %6" PRIuS " KB\n",
    406                memory_allocator()->Size() / KB,
    407                memory_allocator()->Available() / KB);
    408   PrintIsolate(isolate_,
    409                "Read-only space,        used: %6" PRIuS
    410                " KB"
    411                ", available: %6" PRIuS
    412                " KB"
    413                ", committed: %6" PRIuS " KB\n",
    414                read_only_space_->Size() / KB,
    415                read_only_space_->Available() / KB,
    416                read_only_space_->CommittedMemory() / KB);
    417   PrintIsolate(isolate_,
    418                "New space,              used: %6" PRIuS
    419                " KB"
    420                ", available: %6" PRIuS
    421                " KB"
    422                ", committed: %6" PRIuS " KB\n",
    423                new_space_->Size() / KB, new_space_->Available() / KB,
    424                new_space_->CommittedMemory() / KB);
    425   PrintIsolate(isolate_,
    426                "New large object space, used: %6" PRIuS
    427                " KB"
    428                ", available: %6" PRIuS
    429                " KB"
    430                ", committed: %6" PRIuS " KB\n",
    431                new_lo_space_->SizeOfObjects() / KB,
    432                new_lo_space_->Available() / KB,
    433                new_lo_space_->CommittedMemory() / KB);
    434   PrintIsolate(isolate_,
    435                "Old space,              used: %6" PRIuS
    436                " KB"
    437                ", available: %6" PRIuS
    438                " KB"
    439                ", committed: %6" PRIuS " KB\n",
    440                old_space_->SizeOfObjects() / KB, old_space_->Available() / KB,
    441                old_space_->CommittedMemory() / KB);
    442   PrintIsolate(isolate_,
    443                "Code space,             used: %6" PRIuS
    444                " KB"
    445                ", available: %6" PRIuS
    446                " KB"
    447                ", committed: %6" PRIuS "KB\n",
    448                code_space_->SizeOfObjects() / KB, code_space_->Available() / KB,
    449                code_space_->CommittedMemory() / KB);
    450   PrintIsolate(isolate_,
    451                "Map space,              used: %6" PRIuS
    452                " KB"
    453                ", available: %6" PRIuS
    454                " KB"
    455                ", committed: %6" PRIuS " KB\n",
    456                map_space_->SizeOfObjects() / KB, map_space_->Available() / KB,
    457                map_space_->CommittedMemory() / KB);
    458   PrintIsolate(isolate_,
    459                "Large object space,     used: %6" PRIuS
    460                " KB"
    461                ", available: %6" PRIuS
    462                " KB"
    463                ", committed: %6" PRIuS " KB\n",
    464                lo_space_->SizeOfObjects() / KB, lo_space_->Available() / KB,
    465                lo_space_->CommittedMemory() / KB);
    466   PrintIsolate(isolate_,
    467                "All spaces,             used: %6" PRIuS
    468                " KB"
    469                ", available: %6" PRIuS
    470                " KB"
    471                ", committed: %6" PRIuS "KB\n",
    472                this->SizeOfObjects() / KB, this->Available() / KB,
    473                this->CommittedMemory() / KB);
    474   PrintIsolate(isolate_,
    475                "Unmapper buffering %d chunks of committed: %6" PRIuS " KB\n",
    476                memory_allocator()->unmapper()->NumberOfChunks(),
    477                CommittedMemoryOfHeapAndUnmapper() / KB);
    478   PrintIsolate(isolate_, "External memory reported: %6" PRId64 " KB\n",
    479                external_memory_ / KB);
    480   PrintIsolate(isolate_, "External memory global %zu KB\n",
    481                external_memory_callback_() / KB);
    482   PrintIsolate(isolate_, "Total time spent in GC  : %.1f ms\n",
    483                total_gc_time_ms_);
    484 }
    485 
    486 void Heap::ReportStatisticsAfterGC() {
    487   for (int i = 0; i < static_cast<int>(v8::Isolate::kUseCounterFeatureCount);
    488        ++i) {
    489     int count = deferred_counters_[i];
    490     deferred_counters_[i] = 0;
    491     while (count > 0) {
    492       count--;
    493       isolate()->CountUsage(static_cast<v8::Isolate::UseCounterFeature>(i));
    494     }
    495   }
    496 }
    497 
    498 void Heap::AddHeapObjectAllocationTracker(
    499     HeapObjectAllocationTracker* tracker) {
    500   if (allocation_trackers_.empty()) DisableInlineAllocation();
    501   allocation_trackers_.push_back(tracker);
    502 }
    503 
    504 void Heap::RemoveHeapObjectAllocationTracker(
    505     HeapObjectAllocationTracker* tracker) {
    506   allocation_trackers_.erase(std::remove(allocation_trackers_.begin(),
    507                                          allocation_trackers_.end(), tracker),
    508                              allocation_trackers_.end());
    509   if (allocation_trackers_.empty()) EnableInlineAllocation();
    510 }
    511 
    512 void Heap::AddRetainingPathTarget(Handle<HeapObject> object,
    513                                   RetainingPathOption option) {
    514   if (!FLAG_track_retaining_path) {
    515     PrintF("Retaining path tracking requires --track-retaining-path\n");
    516   } else {
    517     Handle<WeakArrayList> array(retaining_path_targets(), isolate());
    518     int index = array->length();
    519     array = WeakArrayList::AddToEnd(isolate(), array,
    520                                     MaybeObjectHandle::Weak(object));
    521     set_retaining_path_targets(*array);
    522     DCHECK_EQ(array->length(), index + 1);
    523     retaining_path_target_option_[index] = option;
    524   }
    525 }
    526 
    527 bool Heap::IsRetainingPathTarget(HeapObject* object,
    528                                  RetainingPathOption* option) {
    529   WeakArrayList* targets = retaining_path_targets();
    530   int length = targets->length();
    531   MaybeObject* object_to_check = HeapObjectReference::Weak(object);
    532   for (int i = 0; i < length; i++) {
    533     MaybeObject* target = targets->Get(i);
    534     DCHECK(target->IsWeakOrClearedHeapObject());
    535     if (target == object_to_check) {
    536       DCHECK(retaining_path_target_option_.count(i));
    537       *option = retaining_path_target_option_[i];
    538       return true;
    539     }
    540   }
    541   return false;
    542 }
    543 
    544 void Heap::PrintRetainingPath(HeapObject* target, RetainingPathOption option) {
    545   PrintF("\n\n\n");
    546   PrintF("#################################################\n");
    547   PrintF("Retaining path for %p:\n", static_cast<void*>(target));
    548   HeapObject* object = target;
    549   std::vector<std::pair<HeapObject*, bool>> retaining_path;
    550   Root root = Root::kUnknown;
    551   bool ephemeron = false;
    552   while (true) {
    553     retaining_path.push_back(std::make_pair(object, ephemeron));
    554     if (option == RetainingPathOption::kTrackEphemeronPath &&
    555         ephemeron_retainer_.count(object)) {
    556       object = ephemeron_retainer_[object];
    557       ephemeron = true;
    558     } else if (retainer_.count(object)) {
    559       object = retainer_[object];
    560       ephemeron = false;
    561     } else {
    562       if (retaining_root_.count(object)) {
    563         root = retaining_root_[object];
    564       }
    565       break;
    566     }
    567   }
    568   int distance = static_cast<int>(retaining_path.size());
    569   for (auto node : retaining_path) {
    570     HeapObject* object = node.first;
    571     bool ephemeron = node.second;
    572     PrintF("\n");
    573     PrintF("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
    574     PrintF("Distance from root %d%s: ", distance,
    575            ephemeron ? " (ephemeron)" : "");
    576     object->ShortPrint();
    577     PrintF("\n");
    578 #ifdef OBJECT_PRINT
    579     object->Print();
    580     PrintF("\n");
    581 #endif
    582     --distance;
    583   }
    584   PrintF("\n");
    585   PrintF("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
    586   PrintF("Root: %s\n", RootVisitor::RootName(root));
    587   PrintF("-------------------------------------------------\n");
    588 }
    589 
    590 void Heap::AddRetainer(HeapObject* retainer, HeapObject* object) {
    591   if (retainer_.count(object)) return;
    592   retainer_[object] = retainer;
    593   RetainingPathOption option = RetainingPathOption::kDefault;
    594   if (IsRetainingPathTarget(object, &option)) {
    595     // Check if the retaining path was already printed in
    596     // AddEphemeronRetainer().
    597     if (ephemeron_retainer_.count(object) == 0 ||
    598         option == RetainingPathOption::kDefault) {
    599       PrintRetainingPath(object, option);
    600     }
    601   }
    602 }
    603 
    604 void Heap::AddEphemeronRetainer(HeapObject* retainer, HeapObject* object) {
    605   if (ephemeron_retainer_.count(object)) return;
    606   ephemeron_retainer_[object] = retainer;
    607   RetainingPathOption option = RetainingPathOption::kDefault;
    608   if (IsRetainingPathTarget(object, &option) &&
    609       option == RetainingPathOption::kTrackEphemeronPath) {
    610     // Check if the retaining path was already printed in AddRetainer().
    611     if (retainer_.count(object) == 0) {
    612       PrintRetainingPath(object, option);
    613     }
    614   }
    615 }
    616 
    617 void Heap::AddRetainingRoot(Root root, HeapObject* object) {
    618   if (retaining_root_.count(object)) return;
    619   retaining_root_[object] = root;
    620   RetainingPathOption option = RetainingPathOption::kDefault;
    621   if (IsRetainingPathTarget(object, &option)) {
    622     PrintRetainingPath(object, option);
    623   }
    624 }
    625 
    626 void Heap::IncrementDeferredCount(v8::Isolate::UseCounterFeature feature) {
    627   deferred_counters_[feature]++;
    628 }
    629 
    630 bool Heap::UncommitFromSpace() { return new_space_->UncommitFromSpace(); }
    631 
    632 void Heap::GarbageCollectionPrologue() {
    633   TRACE_GC(tracer(), GCTracer::Scope::HEAP_PROLOGUE);
    634   {
    635     AllowHeapAllocation for_the_first_part_of_prologue;
    636     gc_count_++;
    637 
    638 #ifdef VERIFY_HEAP
    639     if (FLAG_verify_heap) {
    640       Verify();
    641     }
    642 #endif
    643   }
    644 
    645   // Reset GC statistics.
    646   promoted_objects_size_ = 0;
    647   previous_semi_space_copied_object_size_ = semi_space_copied_object_size_;
    648   semi_space_copied_object_size_ = 0;
    649   nodes_died_in_new_space_ = 0;
    650   nodes_copied_in_new_space_ = 0;
    651   nodes_promoted_ = 0;
    652 
    653   UpdateMaximumCommitted();
    654 
    655 #ifdef DEBUG
    656   DCHECK(!AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC);
    657 
    658   if (FLAG_gc_verbose) Print();
    659 #endif  // DEBUG
    660 
    661   if (new_space_->IsAtMaximumCapacity()) {
    662     maximum_size_scavenges_++;
    663   } else {
    664     maximum_size_scavenges_ = 0;
    665   }
    666   CheckNewSpaceExpansionCriteria();
    667   UpdateNewSpaceAllocationCounter();
    668   if (FLAG_track_retaining_path) {
    669     retainer_.clear();
    670     ephemeron_retainer_.clear();
    671     retaining_root_.clear();
    672   }
    673 }
    674 
    675 size_t Heap::SizeOfObjects() {
    676   size_t total = 0;
    677 
    678   for (SpaceIterator it(this); it.has_next();) {
    679     total += it.next()->SizeOfObjects();
    680   }
    681   return total;
    682 }
    683 
    684 
    685 const char* Heap::GetSpaceName(int idx) {
    686   switch (idx) {
    687     case NEW_SPACE:
    688       return "new_space";
    689     case OLD_SPACE:
    690       return "old_space";
    691     case MAP_SPACE:
    692       return "map_space";
    693     case CODE_SPACE:
    694       return "code_space";
    695     case LO_SPACE:
    696       return "large_object_space";
    697     case NEW_LO_SPACE:
    698       return "new_large_object_space";
    699     case RO_SPACE:
    700       return "read_only_space";
    701     default:
    702       UNREACHABLE();
    703   }
    704   return nullptr;
    705 }
    706 
    707 void Heap::SetRootCodeStubs(SimpleNumberDictionary* value) {
    708   roots_[kCodeStubsRootIndex] = value;
    709 }
    710 
    711 void Heap::RepairFreeListsAfterDeserialization() {
    712   PagedSpaces spaces(this);
    713   for (PagedSpace* space = spaces.next(); space != nullptr;
    714        space = spaces.next()) {
    715     space->RepairFreeListsAfterDeserialization();
    716   }
    717 }
    718 
    719 void Heap::MergeAllocationSitePretenuringFeedback(
    720     const PretenuringFeedbackMap& local_pretenuring_feedback) {
    721   AllocationSite* site = nullptr;
    722   for (auto& site_and_count : local_pretenuring_feedback) {
    723     site = site_and_count.first;
    724     MapWord map_word = site_and_count.first->map_word();
    725     if (map_word.IsForwardingAddress()) {
    726       site = AllocationSite::cast(map_word.ToForwardingAddress());
    727     }
    728 
    729     // We have not validated the allocation site yet, since we have not
    730     // dereferenced the site during collecting information.
    731     // This is an inlined check of AllocationMemento::IsValid.
    732     if (!site->IsAllocationSite() || site->IsZombie()) continue;
    733 
    734     const int value = static_cast<int>(site_and_count.second);
    735     DCHECK_LT(0, value);
    736     if (site->IncrementMementoFoundCount(value)) {
    737       // For sites in the global map the count is accessed through the site.
    738       global_pretenuring_feedback_.insert(std::make_pair(site, 0));
    739     }
    740   }
    741 }
    742 
    743 void Heap::AddAllocationObserversToAllSpaces(
    744     AllocationObserver* observer, AllocationObserver* new_space_observer) {
    745   DCHECK(observer && new_space_observer);
    746 
    747   for (SpaceIterator it(this); it.has_next();) {
    748     Space* space = it.next();
    749     if (space == new_space()) {
    750       space->AddAllocationObserver(new_space_observer);
    751     } else {
    752       space->AddAllocationObserver(observer);
    753     }
    754   }
    755 }
    756 
    757 void Heap::RemoveAllocationObserversFromAllSpaces(
    758     AllocationObserver* observer, AllocationObserver* new_space_observer) {
    759   DCHECK(observer && new_space_observer);
    760 
    761   for (SpaceIterator it(this); it.has_next();) {
    762     Space* space = it.next();
    763     if (space == new_space()) {
    764       space->RemoveAllocationObserver(new_space_observer);
    765     } else {
    766       space->RemoveAllocationObserver(observer);
    767     }
    768   }
    769 }
    770 
    771 class Heap::SkipStoreBufferScope {
    772  public:
    773   explicit SkipStoreBufferScope(StoreBuffer* store_buffer)
    774       : store_buffer_(store_buffer) {
    775     store_buffer_->MoveAllEntriesToRememberedSet();
    776     store_buffer_->SetMode(StoreBuffer::IN_GC);
    777   }
    778 
    779   ~SkipStoreBufferScope() {
    780     DCHECK(store_buffer_->Empty());
    781     store_buffer_->SetMode(StoreBuffer::NOT_IN_GC);
    782   }
    783 
    784  private:
    785   StoreBuffer* store_buffer_;
    786 };
    787 
    788 namespace {
    789 inline bool MakePretenureDecision(
    790     AllocationSite* site, AllocationSite::PretenureDecision current_decision,
    791     double ratio, bool maximum_size_scavenge) {
    792   // Here we just allow state transitions from undecided or maybe tenure
    793   // to don't tenure, maybe tenure, or tenure.
    794   if ((current_decision == AllocationSite::kUndecided ||
    795        current_decision == AllocationSite::kMaybeTenure)) {
    796     if (ratio >= AllocationSite::kPretenureRatio) {
    797       // We just transition into tenure state when the semi-space was at
    798       // maximum capacity.
    799       if (maximum_size_scavenge) {
    800         site->set_deopt_dependent_code(true);
    801         site->set_pretenure_decision(AllocationSite::kTenure);
    802         // Currently we just need to deopt when we make a state transition to
    803         // tenure.
    804         return true;
    805       }
    806       site->set_pretenure_decision(AllocationSite::kMaybeTenure);
    807     } else {
    808       site->set_pretenure_decision(AllocationSite::kDontTenure);
    809     }
    810   }
    811   return false;
    812 }
    813 
    814 inline bool DigestPretenuringFeedback(Isolate* isolate, AllocationSite* site,
    815                                       bool maximum_size_scavenge) {
    816   bool deopt = false;
    817   int create_count = site->memento_create_count();
    818   int found_count = site->memento_found_count();
    819   bool minimum_mementos_created =
    820       create_count >= AllocationSite::kPretenureMinimumCreated;
    821   double ratio = minimum_mementos_created || FLAG_trace_pretenuring_statistics
    822                      ? static_cast<double>(found_count) / create_count
    823                      : 0.0;
    824   AllocationSite::PretenureDecision current_decision =
    825       site->pretenure_decision();
    826 
    827   if (minimum_mementos_created) {
    828     deopt = MakePretenureDecision(site, current_decision, ratio,
    829                                   maximum_size_scavenge);
    830   }
    831 
    832   if (FLAG_trace_pretenuring_statistics) {
    833     PrintIsolate(isolate,
    834                  "pretenuring: AllocationSite(%p): (created, found, ratio) "
    835                  "(%d, %d, %f) %s => %s\n",
    836                  static_cast<void*>(site), create_count, found_count, ratio,
    837                  site->PretenureDecisionName(current_decision),
    838                  site->PretenureDecisionName(site->pretenure_decision()));
    839   }
    840 
    841   // Clear feedback calculation fields until the next gc.
    842   site->set_memento_found_count(0);
    843   site->set_memento_create_count(0);
    844   return deopt;
    845 }
    846 }  // namespace
    847 
    848 void Heap::RemoveAllocationSitePretenuringFeedback(AllocationSite* site) {
    849   global_pretenuring_feedback_.erase(site);
    850 }
    851 
    852 bool Heap::DeoptMaybeTenuredAllocationSites() {
    853   return new_space_->IsAtMaximumCapacity() && maximum_size_scavenges_ == 0;
    854 }
    855 
    856 void Heap::ProcessPretenuringFeedback() {
    857   bool trigger_deoptimization = false;
    858   if (FLAG_allocation_site_pretenuring) {
    859     int tenure_decisions = 0;
    860     int dont_tenure_decisions = 0;
    861     int allocation_mementos_found = 0;
    862     int allocation_sites = 0;
    863     int active_allocation_sites = 0;
    864 
    865     AllocationSite* site = nullptr;
    866 
    867     // Step 1: Digest feedback for recorded allocation sites.
    868     bool maximum_size_scavenge = MaximumSizeScavenge();
    869     for (auto& site_and_count : global_pretenuring_feedback_) {
    870       allocation_sites++;
    871       site = site_and_count.first;
    872       // Count is always access through the site.
    873       DCHECK_EQ(0, site_and_count.second);
    874       int found_count = site->memento_found_count();
    875       // An entry in the storage does not imply that the count is > 0 because
    876       // allocation sites might have been reset due to too many objects dying
    877       // in old space.
    878       if (found_count > 0) {
    879         DCHECK(site->IsAllocationSite());
    880         active_allocation_sites++;
    881         allocation_mementos_found += found_count;
    882         if (DigestPretenuringFeedback(isolate_, site, maximum_size_scavenge)) {
    883           trigger_deoptimization = true;
    884         }
    885         if (site->GetPretenureMode() == TENURED) {
    886           tenure_decisions++;
    887         } else {
    888           dont_tenure_decisions++;
    889         }
    890       }
    891     }
    892 
    893     // Step 2: Deopt maybe tenured allocation sites if necessary.
    894     bool deopt_maybe_tenured = DeoptMaybeTenuredAllocationSites();
    895     if (deopt_maybe_tenured) {
    896       ForeachAllocationSite(
    897           allocation_sites_list(),
    898           [&allocation_sites, &trigger_deoptimization](AllocationSite* site) {
    899             DCHECK(site->IsAllocationSite());
    900             allocation_sites++;
    901             if (site->IsMaybeTenure()) {
    902               site->set_deopt_dependent_code(true);
    903               trigger_deoptimization = true;
    904             }
    905           });
    906     }
    907 
    908     if (trigger_deoptimization) {
    909       isolate_->stack_guard()->RequestDeoptMarkedAllocationSites();
    910     }
    911 
    912     if (FLAG_trace_pretenuring_statistics &&
    913         (allocation_mementos_found > 0 || tenure_decisions > 0 ||
    914          dont_tenure_decisions > 0)) {
    915       PrintIsolate(isolate(),
    916                    "pretenuring: deopt_maybe_tenured=%d visited_sites=%d "
    917                    "active_sites=%d "
    918                    "mementos=%d tenured=%d not_tenured=%d\n",
    919                    deopt_maybe_tenured ? 1 : 0, allocation_sites,
    920                    active_allocation_sites, allocation_mementos_found,
    921                    tenure_decisions, dont_tenure_decisions);
    922     }
    923 
    924     global_pretenuring_feedback_.clear();
    925     global_pretenuring_feedback_.reserve(kInitialFeedbackCapacity);
    926   }
    927 }
    928 
    929 void Heap::InvalidateCodeEmbeddedObjects(Code* code) {
    930   MemoryChunk* chunk = MemoryChunk::FromAddress(code->address());
    931   CodePageMemoryModificationScope modification_scope(chunk);
    932   code->InvalidateEmbeddedObjects(this);
    933 }
    934 
    935 void Heap::InvalidateCodeDeoptimizationData(Code* code) {
    936   MemoryChunk* chunk = MemoryChunk::FromAddress(code->address());
    937   CodePageMemoryModificationScope modification_scope(chunk);
    938   code->set_deoptimization_data(ReadOnlyRoots(this).empty_fixed_array());
    939 }
    940 
    941 void Heap::DeoptMarkedAllocationSites() {
    942   // TODO(hpayer): If iterating over the allocation sites list becomes a
    943   // performance issue, use a cache data structure in heap instead.
    944 
    945   ForeachAllocationSite(allocation_sites_list(), [this](AllocationSite* site) {
    946     if (site->deopt_dependent_code()) {
    947       site->dependent_code()->MarkCodeForDeoptimization(
    948           isolate_, DependentCode::kAllocationSiteTenuringChangedGroup);
    949       site->set_deopt_dependent_code(false);
    950     }
    951   });
    952 
    953   Deoptimizer::DeoptimizeMarkedCode(isolate_);
    954 }
    955 
    956 
    957 void Heap::GarbageCollectionEpilogue() {
    958   TRACE_GC(tracer(), GCTracer::Scope::HEAP_EPILOGUE);
    959   if (Heap::ShouldZapGarbage() || FLAG_clear_free_memory) {
    960     ZapFromSpace();
    961   }
    962 
    963 #ifdef VERIFY_HEAP
    964   if (FLAG_verify_heap) {
    965     Verify();
    966   }
    967 #endif
    968 
    969   AllowHeapAllocation for_the_rest_of_the_epilogue;
    970 
    971 #ifdef DEBUG
    972   if (FLAG_print_global_handles) isolate_->global_handles()->Print();
    973   if (FLAG_print_handles) PrintHandles();
    974   if (FLAG_gc_verbose) Print();
    975   if (FLAG_code_stats) ReportCodeStatistics("After GC");
    976   if (FLAG_check_handle_count) CheckHandleCount();
    977 #endif
    978 
    979   UpdateMaximumCommitted();
    980 
    981   isolate_->counters()->alive_after_last_gc()->Set(
    982       static_cast<int>(SizeOfObjects()));
    983 
    984   isolate_->counters()->string_table_capacity()->Set(
    985       string_table()->Capacity());
    986   isolate_->counters()->number_of_symbols()->Set(
    987       string_table()->NumberOfElements());
    988 
    989   if (CommittedMemory() > 0) {
    990     isolate_->counters()->external_fragmentation_total()->AddSample(
    991         static_cast<int>(100 - (SizeOfObjects() * 100.0) / CommittedMemory()));
    992 
    993     isolate_->counters()->heap_sample_total_committed()->AddSample(
    994         static_cast<int>(CommittedMemory() / KB));
    995     isolate_->counters()->heap_sample_total_used()->AddSample(
    996         static_cast<int>(SizeOfObjects() / KB));
    997     isolate_->counters()->heap_sample_map_space_committed()->AddSample(
    998         static_cast<int>(map_space()->CommittedMemory() / KB));
    999     isolate_->counters()->heap_sample_code_space_committed()->AddSample(
   1000         static_cast<int>(code_space()->CommittedMemory() / KB));
   1001 
   1002     isolate_->counters()->heap_sample_maximum_committed()->AddSample(
   1003         static_cast<int>(MaximumCommittedMemory() / KB));
   1004   }
   1005 
   1006 #define UPDATE_COUNTERS_FOR_SPACE(space)                \
   1007   isolate_->counters()->space##_bytes_available()->Set( \
   1008       static_cast<int>(space()->Available()));          \
   1009   isolate_->counters()->space##_bytes_committed()->Set( \
   1010       static_cast<int>(space()->CommittedMemory()));    \
   1011   isolate_->counters()->space##_bytes_used()->Set(      \
   1012       static_cast<int>(space()->SizeOfObjects()));
   1013 #define UPDATE_FRAGMENTATION_FOR_SPACE(space)                          \
   1014   if (space()->CommittedMemory() > 0) {                                \
   1015     isolate_->counters()->external_fragmentation_##space()->AddSample( \
   1016         static_cast<int>(100 -                                         \
   1017                          (space()->SizeOfObjects() * 100.0) /          \
   1018                              space()->CommittedMemory()));             \
   1019   }
   1020 #define UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(space) \
   1021   UPDATE_COUNTERS_FOR_SPACE(space)                         \
   1022   UPDATE_FRAGMENTATION_FOR_SPACE(space)
   1023 
   1024   UPDATE_COUNTERS_FOR_SPACE(new_space)
   1025   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(old_space)
   1026   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(code_space)
   1027   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(map_space)
   1028   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(lo_space)
   1029 #undef UPDATE_COUNTERS_FOR_SPACE
   1030 #undef UPDATE_FRAGMENTATION_FOR_SPACE
   1031 #undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE
   1032 
   1033 #ifdef DEBUG
   1034   ReportStatisticsAfterGC();
   1035 #endif  // DEBUG
   1036 
   1037   last_gc_time_ = MonotonicallyIncreasingTimeInMs();
   1038 
   1039   {
   1040     TRACE_GC(tracer(), GCTracer::Scope::HEAP_EPILOGUE_REDUCE_NEW_SPACE);
   1041     ReduceNewSpaceSize();
   1042   }
   1043 }
   1044 
   1045 class GCCallbacksScope {
   1046  public:
   1047   explicit GCCallbacksScope(Heap* heap) : heap_(heap) {
   1048     heap_->gc_callbacks_depth_++;
   1049   }
   1050   ~GCCallbacksScope() { heap_->gc_callbacks_depth_--; }
   1051 
   1052   bool CheckReenter() { return heap_->gc_callbacks_depth_ == 1; }
   1053 
   1054  private:
   1055   Heap* heap_;
   1056 };
   1057 
   1058 
   1059 void Heap::HandleGCRequest() {
   1060   if (FLAG_stress_scavenge > 0 && stress_scavenge_observer_->HasRequestedGC()) {
   1061     CollectAllGarbage(NEW_SPACE, GarbageCollectionReason::kTesting);
   1062     stress_scavenge_observer_->RequestedGCDone();
   1063   } else if (HighMemoryPressure()) {
   1064     incremental_marking()->reset_request_type();
   1065     CheckMemoryPressure();
   1066   } else if (incremental_marking()->request_type() ==
   1067              IncrementalMarking::COMPLETE_MARKING) {
   1068     incremental_marking()->reset_request_type();
   1069     CollectAllGarbage(current_gc_flags_,
   1070                       GarbageCollectionReason::kFinalizeMarkingViaStackGuard,
   1071                       current_gc_callback_flags_);
   1072   } else if (incremental_marking()->request_type() ==
   1073                  IncrementalMarking::FINALIZATION &&
   1074              incremental_marking()->IsMarking() &&
   1075              !incremental_marking()->finalize_marking_completed()) {
   1076     incremental_marking()->reset_request_type();
   1077     FinalizeIncrementalMarkingIncrementally(
   1078         GarbageCollectionReason::kFinalizeMarkingViaStackGuard);
   1079   }
   1080 }
   1081 
   1082 
   1083 void Heap::ScheduleIdleScavengeIfNeeded(int bytes_allocated) {
   1084   scavenge_job_->ScheduleIdleTaskIfNeeded(this, bytes_allocated);
   1085 }
   1086 
   1087 HistogramTimer* Heap::GCTypePriorityTimer(GarbageCollector collector) {
   1088   if (IsYoungGenerationCollector(collector)) {
   1089     if (isolate_->IsIsolateInBackground()) {
   1090       return isolate_->counters()->gc_scavenger_background();
   1091     }
   1092     return isolate_->counters()->gc_scavenger_foreground();
   1093   } else {
   1094     if (!incremental_marking()->IsStopped()) {
   1095       if (ShouldReduceMemory()) {
   1096         if (isolate_->IsIsolateInBackground()) {
   1097           return isolate_->counters()->gc_finalize_reduce_memory_background();
   1098         }
   1099         return isolate_->counters()->gc_finalize_reduce_memory_foreground();
   1100       } else {
   1101         if (isolate_->IsIsolateInBackground()) {
   1102           return isolate_->counters()->gc_finalize_background();
   1103         }
   1104         return isolate_->counters()->gc_finalize_foreground();
   1105       }
   1106     } else {
   1107       if (isolate_->IsIsolateInBackground()) {
   1108         return isolate_->counters()->gc_compactor_background();
   1109       }
   1110       return isolate_->counters()->gc_compactor_foreground();
   1111     }
   1112   }
   1113 }
   1114 
   1115 HistogramTimer* Heap::GCTypeTimer(GarbageCollector collector) {
   1116   if (IsYoungGenerationCollector(collector)) {
   1117     return isolate_->counters()->gc_scavenger();
   1118   } else {
   1119     if (!incremental_marking()->IsStopped()) {
   1120       if (ShouldReduceMemory()) {
   1121         return isolate_->counters()->gc_finalize_reduce_memory();
   1122       } else {
   1123         return isolate_->counters()->gc_finalize();
   1124       }
   1125     } else {
   1126       return isolate_->counters()->gc_compactor();
   1127     }
   1128   }
   1129 }
   1130 
   1131 void Heap::CollectAllGarbage(int flags, GarbageCollectionReason gc_reason,
   1132                              const v8::GCCallbackFlags gc_callback_flags) {
   1133   // Since we are ignoring the return value, the exact choice of space does
   1134   // not matter, so long as we do not specify NEW_SPACE, which would not
   1135   // cause a full GC.
   1136   set_current_gc_flags(flags);
   1137   CollectGarbage(OLD_SPACE, gc_reason, gc_callback_flags);
   1138   set_current_gc_flags(kNoGCFlags);
   1139 }
   1140 
   1141 namespace {
   1142 
   1143 intptr_t CompareWords(int size, HeapObject* a, HeapObject* b) {
   1144   int words = size / kPointerSize;
   1145   DCHECK_EQ(a->Size(), size);
   1146   DCHECK_EQ(b->Size(), size);
   1147   intptr_t* slot_a = reinterpret_cast<intptr_t*>(a->address());
   1148   intptr_t* slot_b = reinterpret_cast<intptr_t*>(b->address());
   1149   for (int i = 0; i < words; i++) {
   1150     if (*slot_a != *slot_b) {
   1151       return *slot_a - *slot_b;
   1152     }
   1153     slot_a++;
   1154     slot_b++;
   1155   }
   1156   return 0;
   1157 }
   1158 
   1159 void ReportDuplicates(int size, std::vector<HeapObject*>& objects) {
   1160   if (objects.size() == 0) return;
   1161 
   1162   sort(objects.begin(), objects.end(), [size](HeapObject* a, HeapObject* b) {
   1163     intptr_t c = CompareWords(size, a, b);
   1164     if (c != 0) return c < 0;
   1165     return a < b;
   1166   });
   1167 
   1168   std::vector<std::pair<int, HeapObject*>> duplicates;
   1169   HeapObject* current = objects[0];
   1170   int count = 1;
   1171   for (size_t i = 1; i < objects.size(); i++) {
   1172     if (CompareWords(size, current, objects[i]) == 0) {
   1173       count++;
   1174     } else {
   1175       if (count > 1) {
   1176         duplicates.push_back(std::make_pair(count - 1, current));
   1177       }
   1178       count = 1;
   1179       current = objects[i];
   1180     }
   1181   }
   1182   if (count > 1) {
   1183     duplicates.push_back(std::make_pair(count - 1, current));
   1184   }
   1185 
   1186   int threshold = FLAG_trace_duplicate_threshold_kb * KB;
   1187 
   1188   sort(duplicates.begin(), duplicates.end());
   1189   for (auto it = duplicates.rbegin(); it != duplicates.rend(); ++it) {
   1190     int duplicate_bytes = it->first * size;
   1191     if (duplicate_bytes < threshold) break;
   1192     PrintF("%d duplicates of size %d each (%dKB)\n", it->first, size,
   1193            duplicate_bytes / KB);
   1194     PrintF("Sample object: ");
   1195     it->second->Print();
   1196     PrintF("============================\n");
   1197   }
   1198 }
   1199 }  // anonymous namespace
   1200 
   1201 void Heap::CollectAllAvailableGarbage(GarbageCollectionReason gc_reason) {
   1202   // Since we are ignoring the return value, the exact choice of space does
   1203   // not matter, so long as we do not specify NEW_SPACE, which would not
   1204   // cause a full GC.
   1205   // Major GC would invoke weak handle callbacks on weakly reachable
   1206   // handles, but won't collect weakly reachable objects until next
   1207   // major GC.  Therefore if we collect aggressively and weak handle callback
   1208   // has been invoked, we rerun major GC to release objects which become
   1209   // garbage.
   1210   // Note: as weak callbacks can execute arbitrary code, we cannot
   1211   // hope that eventually there will be no weak callbacks invocations.
   1212   // Therefore stop recollecting after several attempts.
   1213   if (gc_reason == GarbageCollectionReason::kLastResort) {
   1214     InvokeNearHeapLimitCallback();
   1215   }
   1216   RuntimeCallTimerScope runtime_timer(
   1217       isolate(), RuntimeCallCounterId::kGC_Custom_AllAvailableGarbage);
   1218 
   1219   // The optimizing compiler may be unnecessarily holding on to memory.
   1220   isolate()->AbortConcurrentOptimization(BlockingBehavior::kDontBlock);
   1221   isolate()->ClearSerializerData();
   1222   set_current_gc_flags(kMakeHeapIterableMask | kReduceMemoryFootprintMask);
   1223   isolate_->compilation_cache()->Clear();
   1224   const int kMaxNumberOfAttempts = 7;
   1225   const int kMinNumberOfAttempts = 2;
   1226   for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) {
   1227     if (!CollectGarbage(OLD_SPACE, gc_reason,
   1228                         v8::kGCCallbackFlagCollectAllAvailableGarbage) &&
   1229         attempt + 1 >= kMinNumberOfAttempts) {
   1230       break;
   1231     }
   1232   }
   1233 
   1234   set_current_gc_flags(kNoGCFlags);
   1235   new_space_->Shrink();
   1236   UncommitFromSpace();
   1237   memory_allocator()->unmapper()->EnsureUnmappingCompleted();
   1238 
   1239   if (FLAG_trace_duplicate_threshold_kb) {
   1240     std::map<int, std::vector<HeapObject*>> objects_by_size;
   1241     PagedSpaces spaces(this);
   1242     for (PagedSpace* space = spaces.next(); space != nullptr;
   1243          space = spaces.next()) {
   1244       HeapObjectIterator it(space);
   1245       for (HeapObject* obj = it.Next(); obj != nullptr; obj = it.Next()) {
   1246         objects_by_size[obj->Size()].push_back(obj);
   1247       }
   1248     }
   1249     {
   1250       LargeObjectIterator it(lo_space());
   1251       for (HeapObject* obj = it.Next(); obj != nullptr; obj = it.Next()) {
   1252         objects_by_size[obj->Size()].push_back(obj);
   1253       }
   1254     }
   1255     for (auto it = objects_by_size.rbegin(); it != objects_by_size.rend();
   1256          ++it) {
   1257       ReportDuplicates(it->first, it->second);
   1258     }
   1259   }
   1260 }
   1261 
   1262 void Heap::ReportExternalMemoryPressure() {
   1263   const GCCallbackFlags kGCCallbackFlagsForExternalMemory =
   1264       static_cast<GCCallbackFlags>(
   1265           kGCCallbackFlagSynchronousPhantomCallbackProcessing |
   1266           kGCCallbackFlagCollectAllExternalMemory);
   1267   if (external_memory_ >
   1268       (external_memory_at_last_mark_compact_ + external_memory_hard_limit())) {
   1269     CollectAllGarbage(
   1270         kReduceMemoryFootprintMask | kFinalizeIncrementalMarkingMask,
   1271         GarbageCollectionReason::kExternalMemoryPressure,
   1272         static_cast<GCCallbackFlags>(kGCCallbackFlagCollectAllAvailableGarbage |
   1273                                      kGCCallbackFlagsForExternalMemory));
   1274     return;
   1275   }
   1276   if (incremental_marking()->IsStopped()) {
   1277     if (incremental_marking()->CanBeActivated()) {
   1278       StartIncrementalMarking(GCFlagsForIncrementalMarking(),
   1279                               GarbageCollectionReason::kExternalMemoryPressure,
   1280                               kGCCallbackFlagsForExternalMemory);
   1281     } else {
   1282       CollectAllGarbage(i::Heap::kNoGCFlags,
   1283                         GarbageCollectionReason::kExternalMemoryPressure,
   1284                         kGCCallbackFlagsForExternalMemory);
   1285     }
   1286   } else {
   1287     // Incremental marking is turned on an has already been started.
   1288     const double kMinStepSize = 5;
   1289     const double kMaxStepSize = 10;
   1290     const double ms_step =
   1291         Min(kMaxStepSize,
   1292             Max(kMinStepSize, static_cast<double>(external_memory_) /
   1293                                   external_memory_limit_ * kMinStepSize));
   1294     const double deadline = MonotonicallyIncreasingTimeInMs() + ms_step;
   1295     // Extend the gc callback flags with external memory flags.
   1296     current_gc_callback_flags_ = static_cast<GCCallbackFlags>(
   1297         current_gc_callback_flags_ | kGCCallbackFlagsForExternalMemory);
   1298     incremental_marking()->AdvanceIncrementalMarking(
   1299         deadline, IncrementalMarking::GC_VIA_STACK_GUARD, StepOrigin::kV8);
   1300   }
   1301 }
   1302 
   1303 void Heap::EnsureFillerObjectAtTop() {
   1304   // There may be an allocation memento behind objects in new space. Upon
   1305   // evacuation of a non-full new space (or if we are on the last page) there
   1306   // may be uninitialized memory behind top. We fill the remainder of the page
   1307   // with a filler.
   1308   Address to_top = new_space_->top();
   1309   Page* page = Page::FromAddress(to_top - kPointerSize);
   1310   if (page->Contains(to_top)) {
   1311     int remaining_in_page = static_cast<int>(page->area_end() - to_top);
   1312     CreateFillerObjectAt(to_top, remaining_in_page, ClearRecordedSlots::kNo);
   1313   }
   1314 }
   1315 
   1316 bool Heap::CollectGarbage(AllocationSpace space,
   1317                           GarbageCollectionReason gc_reason,
   1318                           const v8::GCCallbackFlags gc_callback_flags) {
   1319   const char* collector_reason = nullptr;
   1320   GarbageCollector collector = SelectGarbageCollector(space, &collector_reason);
   1321 
   1322   if (!CanExpandOldGeneration(new_space()->Capacity())) {
   1323     InvokeNearHeapLimitCallback();
   1324   }
   1325 
   1326   // Ensure that all pending phantom callbacks are invoked.
   1327   isolate()->global_handles()->InvokeSecondPassPhantomCallbacks();
   1328 
   1329   // The VM is in the GC state until exiting this function.
   1330   VMState<GC> state(isolate());
   1331 
   1332 #ifdef V8_ENABLE_ALLOCATION_TIMEOUT
   1333   // Reset the allocation timeout, but make sure to allow at least a few
   1334   // allocations after a collection. The reason for this is that we have a lot
   1335   // of allocation sequences and we assume that a garbage collection will allow
   1336   // the subsequent allocation attempts to go through.
   1337   if (FLAG_random_gc_interval > 0 || FLAG_gc_interval >= 0) {
   1338     allocation_timeout_ = Max(6, NextAllocationTimeout(allocation_timeout_));
   1339   }
   1340 #endif
   1341 
   1342   EnsureFillerObjectAtTop();
   1343 
   1344   if (IsYoungGenerationCollector(collector) &&
   1345       !incremental_marking()->IsStopped()) {
   1346     if (FLAG_trace_incremental_marking) {
   1347       isolate()->PrintWithTimestamp(
   1348           "[IncrementalMarking] Scavenge during marking.\n");
   1349     }
   1350   }
   1351 
   1352   bool next_gc_likely_to_collect_more = false;
   1353   size_t committed_memory_before = 0;
   1354 
   1355   if (collector == MARK_COMPACTOR) {
   1356     committed_memory_before = CommittedOldGenerationMemory();
   1357   }
   1358 
   1359   {
   1360     tracer()->Start(collector, gc_reason, collector_reason);
   1361     DCHECK(AllowHeapAllocation::IsAllowed());
   1362     DisallowHeapAllocation no_allocation_during_gc;
   1363     GarbageCollectionPrologue();
   1364 
   1365     {
   1366       HistogramTimer* gc_type_timer = GCTypeTimer(collector);
   1367       HistogramTimerScope histogram_timer_scope(gc_type_timer);
   1368       TRACE_EVENT0("v8", gc_type_timer->name());
   1369 
   1370       HistogramTimer* gc_type_priority_timer = GCTypePriorityTimer(collector);
   1371       OptionalHistogramTimerScopeMode mode =
   1372           isolate_->IsMemorySavingsModeActive()
   1373               ? OptionalHistogramTimerScopeMode::DONT_TAKE_TIME
   1374               : OptionalHistogramTimerScopeMode::TAKE_TIME;
   1375       OptionalHistogramTimerScope histogram_timer_priority_scope(
   1376           gc_type_priority_timer, mode);
   1377 
   1378       next_gc_likely_to_collect_more =
   1379           PerformGarbageCollection(collector, gc_callback_flags);
   1380       if (collector == MARK_COMPACTOR) {
   1381         tracer()->RecordMarkCompactHistograms(gc_type_timer);
   1382       }
   1383     }
   1384 
   1385     GarbageCollectionEpilogue();
   1386     if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) {
   1387       isolate()->CheckDetachedContextsAfterGC();
   1388     }
   1389 
   1390     if (collector == MARK_COMPACTOR) {
   1391       size_t committed_memory_after = CommittedOldGenerationMemory();
   1392       size_t used_memory_after = OldGenerationSizeOfObjects();
   1393       MemoryReducer::Event event;
   1394       event.type = MemoryReducer::kMarkCompact;
   1395       event.time_ms = MonotonicallyIncreasingTimeInMs();
   1396       // Trigger one more GC if
   1397       // - this GC decreased committed memory,
   1398       // - there is high fragmentation,
   1399       // - there are live detached contexts.
   1400       event.next_gc_likely_to_collect_more =
   1401           (committed_memory_before > committed_memory_after + MB) ||
   1402           HasHighFragmentation(used_memory_after, committed_memory_after) ||
   1403           (detached_contexts()->length() > 0);
   1404       event.committed_memory = committed_memory_after;
   1405       if (deserialization_complete_) {
   1406         memory_reducer_->NotifyMarkCompact(event);
   1407       }
   1408     }
   1409 
   1410     tracer()->Stop(collector);
   1411   }
   1412 
   1413   if (collector == MARK_COMPACTOR &&
   1414       (gc_callback_flags & (kGCCallbackFlagForced |
   1415                             kGCCallbackFlagCollectAllAvailableGarbage)) != 0) {
   1416     isolate()->CountUsage(v8::Isolate::kForcedGC);
   1417   }
   1418 
   1419   // Start incremental marking for the next cycle. The heap snapshot
   1420   // generator needs incremental marking to stay off after it aborted.
   1421   // We do this only for scavenger to avoid a loop where mark-compact
   1422   // causes another mark-compact.
   1423   if (IsYoungGenerationCollector(collector) &&
   1424       !ShouldAbortIncrementalMarking()) {
   1425     StartIncrementalMarkingIfAllocationLimitIsReached(
   1426         GCFlagsForIncrementalMarking(),
   1427         kGCCallbackScheduleIdleGarbageCollection);
   1428   }
   1429 
   1430   return next_gc_likely_to_collect_more;
   1431 }
   1432 
   1433 
   1434 int Heap::NotifyContextDisposed(bool dependant_context) {
   1435   if (!dependant_context) {
   1436     tracer()->ResetSurvivalEvents();
   1437     old_generation_size_configured_ = false;
   1438     MemoryReducer::Event event;
   1439     event.type = MemoryReducer::kPossibleGarbage;
   1440     event.time_ms = MonotonicallyIncreasingTimeInMs();
   1441     memory_reducer_->NotifyPossibleGarbage(event);
   1442   }
   1443   isolate()->AbortConcurrentOptimization(BlockingBehavior::kDontBlock);
   1444 
   1445   number_of_disposed_maps_ = retained_maps()->length();
   1446   tracer()->AddContextDisposalTime(MonotonicallyIncreasingTimeInMs());
   1447   return ++contexts_disposed_;
   1448 }
   1449 
   1450 void Heap::StartIncrementalMarking(int gc_flags,
   1451                                    GarbageCollectionReason gc_reason,
   1452                                    GCCallbackFlags gc_callback_flags) {
   1453   DCHECK(incremental_marking()->IsStopped());
   1454   set_current_gc_flags(gc_flags);
   1455   current_gc_callback_flags_ = gc_callback_flags;
   1456   incremental_marking()->Start(gc_reason);
   1457 }
   1458 
   1459 void Heap::StartIncrementalMarkingIfAllocationLimitIsReached(
   1460     int gc_flags, const GCCallbackFlags gc_callback_flags) {
   1461   if (incremental_marking()->IsStopped()) {
   1462     IncrementalMarkingLimit reached_limit = IncrementalMarkingLimitReached();
   1463     if (reached_limit == IncrementalMarkingLimit::kSoftLimit) {
   1464       incremental_marking()->incremental_marking_job()->ScheduleTask(this);
   1465     } else if (reached_limit == IncrementalMarkingLimit::kHardLimit) {
   1466       StartIncrementalMarking(gc_flags,
   1467                               GarbageCollectionReason::kAllocationLimit,
   1468                               gc_callback_flags);
   1469     }
   1470   }
   1471 }
   1472 
   1473 void Heap::StartIdleIncrementalMarking(
   1474     GarbageCollectionReason gc_reason,
   1475     const GCCallbackFlags gc_callback_flags) {
   1476   gc_idle_time_handler_->ResetNoProgressCounter();
   1477   StartIncrementalMarking(kReduceMemoryFootprintMask, gc_reason,
   1478                           gc_callback_flags);
   1479 }
   1480 
   1481 void Heap::MoveElements(FixedArray* array, int dst_index, int src_index,
   1482                         int len, WriteBarrierMode mode) {
   1483   if (len == 0) return;
   1484 
   1485   DCHECK(array->map() != ReadOnlyRoots(this).fixed_cow_array_map());
   1486   Object** dst = array->data_start() + dst_index;
   1487   Object** src = array->data_start() + src_index;
   1488   if (FLAG_concurrent_marking && incremental_marking()->IsMarking()) {
   1489     if (dst < src) {
   1490       for (int i = 0; i < len; i++) {
   1491         base::AsAtomicPointer::Relaxed_Store(
   1492             dst + i, base::AsAtomicPointer::Relaxed_Load(src + i));
   1493       }
   1494     } else {
   1495       for (int i = len - 1; i >= 0; i--) {
   1496         base::AsAtomicPointer::Relaxed_Store(
   1497             dst + i, base::AsAtomicPointer::Relaxed_Load(src + i));
   1498       }
   1499     }
   1500   } else {
   1501     MemMove(dst, src, len * kPointerSize);
   1502   }
   1503   if (mode == SKIP_WRITE_BARRIER) return;
   1504   FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(this, array, dst_index, len);
   1505 }
   1506 
   1507 
   1508 #ifdef VERIFY_HEAP
   1509 // Helper class for verifying the string table.
   1510 class StringTableVerifier : public ObjectVisitor {
   1511  public:
   1512   explicit StringTableVerifier(Isolate* isolate) : isolate_(isolate) {}
   1513 
   1514   void VisitPointers(HeapObject* host, Object** start, Object** end) override {
   1515     // Visit all HeapObject pointers in [start, end).
   1516     for (Object** p = start; p < end; p++) {
   1517       DCHECK(!HasWeakHeapObjectTag(*p));
   1518       if ((*p)->IsHeapObject()) {
   1519         HeapObject* object = HeapObject::cast(*p);
   1520         // Check that the string is actually internalized.
   1521         CHECK(object->IsTheHole(isolate_) || object->IsUndefined(isolate_) ||
   1522               object->IsInternalizedString());
   1523       }
   1524     }
   1525   }
   1526   void VisitPointers(HeapObject* host, MaybeObject** start,
   1527                      MaybeObject** end) override {
   1528     UNREACHABLE();
   1529   }
   1530 
   1531  private:
   1532   Isolate* isolate_;
   1533 };
   1534 
   1535 static void VerifyStringTable(Isolate* isolate) {
   1536   StringTableVerifier verifier(isolate);
   1537   isolate->heap()->string_table()->IterateElements(&verifier);
   1538 }
   1539 #endif  // VERIFY_HEAP
   1540 
   1541 bool Heap::ReserveSpace(Reservation* reservations, std::vector<Address>* maps) {
   1542   bool gc_performed = true;
   1543   int counter = 0;
   1544   static const int kThreshold = 20;
   1545   while (gc_performed && counter++ < kThreshold) {
   1546     gc_performed = false;
   1547     for (int space = FIRST_SPACE;
   1548          space < SerializerDeserializer::kNumberOfSpaces; space++) {
   1549       Reservation* reservation = &reservations[space];
   1550       DCHECK_LE(1, reservation->size());
   1551       if (reservation->at(0).size == 0) {
   1552         DCHECK_EQ(1, reservation->size());
   1553         continue;
   1554       }
   1555       bool perform_gc = false;
   1556       if (space == MAP_SPACE) {
   1557         // We allocate each map individually to avoid fragmentation.
   1558         maps->clear();
   1559         DCHECK_LE(reservation->size(), 2);
   1560         int reserved_size = 0;
   1561         for (const Chunk& c : *reservation) reserved_size += c.size;
   1562         DCHECK_EQ(0, reserved_size % Map::kSize);
   1563         int num_maps = reserved_size / Map::kSize;
   1564         for (int i = 0; i < num_maps; i++) {
   1565           // The deserializer will update the skip list.
   1566           AllocationResult allocation = map_space()->AllocateRawUnaligned(
   1567               Map::kSize, PagedSpace::IGNORE_SKIP_LIST);
   1568           HeapObject* free_space = nullptr;
   1569           if (allocation.To(&free_space)) {
   1570             // Mark with a free list node, in case we have a GC before
   1571             // deserializing.
   1572             Address free_space_address = free_space->address();
   1573             CreateFillerObjectAt(free_space_address, Map::kSize,
   1574                                  ClearRecordedSlots::kNo);
   1575             maps->push_back(free_space_address);
   1576           } else {
   1577             perform_gc = true;
   1578             break;
   1579           }
   1580         }
   1581       } else if (space == LO_SPACE) {
   1582         // Just check that we can allocate during deserialization.
   1583         DCHECK_LE(reservation->size(), 2);
   1584         int reserved_size = 0;
   1585         for (const Chunk& c : *reservation) reserved_size += c.size;
   1586         perform_gc = !CanExpandOldGeneration(reserved_size);
   1587       } else {
   1588         for (auto& chunk : *reservation) {
   1589           AllocationResult allocation;
   1590           int size = chunk.size;
   1591           DCHECK_LE(static_cast<size_t>(size),
   1592                     MemoryAllocator::PageAreaSize(
   1593                         static_cast<AllocationSpace>(space)));
   1594           if (space == NEW_SPACE) {
   1595             allocation = new_space()->AllocateRawUnaligned(size);
   1596           } else {
   1597             // The deserializer will update the skip list.
   1598             allocation = paged_space(space)->AllocateRawUnaligned(
   1599                 size, PagedSpace::IGNORE_SKIP_LIST);
   1600           }
   1601           HeapObject* free_space = nullptr;
   1602           if (allocation.To(&free_space)) {
   1603             // Mark with a free list node, in case we have a GC before
   1604             // deserializing.
   1605             Address free_space_address = free_space->address();
   1606             CreateFillerObjectAt(free_space_address, size,
   1607                                  ClearRecordedSlots::kNo);
   1608             DCHECK_GT(SerializerDeserializer::kNumberOfPreallocatedSpaces,
   1609                       space);
   1610             chunk.start = free_space_address;
   1611             chunk.end = free_space_address + size;
   1612           } else {
   1613             perform_gc = true;
   1614             break;
   1615           }
   1616         }
   1617       }
   1618       if (perform_gc) {
   1619         // We cannot perfom a GC with an uninitialized isolate. This check
   1620         // fails for example if the max old space size is chosen unwisely,
   1621         // so that we cannot allocate space to deserialize the initial heap.
   1622         if (!deserialization_complete_) {
   1623           V8::FatalProcessOutOfMemory(
   1624               isolate(), "insufficient memory to create an Isolate");
   1625         }
   1626         if (space == NEW_SPACE) {
   1627           CollectGarbage(NEW_SPACE, GarbageCollectionReason::kDeserializer);
   1628         } else {
   1629           if (counter > 1) {
   1630             CollectAllGarbage(
   1631                 kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask,
   1632                 GarbageCollectionReason::kDeserializer);
   1633           } else {
   1634             CollectAllGarbage(kAbortIncrementalMarkingMask,
   1635                               GarbageCollectionReason::kDeserializer);
   1636           }
   1637         }
   1638         gc_performed = true;
   1639         break;  // Abort for-loop over spaces and retry.
   1640       }
   1641     }
   1642   }
   1643 
   1644   return !gc_performed;
   1645 }
   1646 
   1647 
   1648 void Heap::EnsureFromSpaceIsCommitted() {
   1649   if (new_space_->CommitFromSpaceIfNeeded()) return;
   1650 
   1651   // Committing memory to from space failed.
   1652   // Memory is exhausted and we will die.
   1653   FatalProcessOutOfMemory("Committing semi space failed.");
   1654 }
   1655 
   1656 
   1657 void Heap::UpdateSurvivalStatistics(int start_new_space_size) {
   1658   if (start_new_space_size == 0) return;
   1659 
   1660   promotion_ratio_ = (static_cast<double>(promoted_objects_size_) /
   1661                       static_cast<double>(start_new_space_size) * 100);
   1662 
   1663   if (previous_semi_space_copied_object_size_ > 0) {
   1664     promotion_rate_ =
   1665         (static_cast<double>(promoted_objects_size_) /
   1666          static_cast<double>(previous_semi_space_copied_object_size_) * 100);
   1667   } else {
   1668     promotion_rate_ = 0;
   1669   }
   1670 
   1671   semi_space_copied_rate_ =
   1672       (static_cast<double>(semi_space_copied_object_size_) /
   1673        static_cast<double>(start_new_space_size) * 100);
   1674 
   1675   double survival_rate = promotion_ratio_ + semi_space_copied_rate_;
   1676   tracer()->AddSurvivalRatio(survival_rate);
   1677 }
   1678 
   1679 bool Heap::PerformGarbageCollection(
   1680     GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) {
   1681   int freed_global_handles = 0;
   1682 
   1683   if (!IsYoungGenerationCollector(collector)) {
   1684     PROFILE(isolate_, CodeMovingGCEvent());
   1685   }
   1686 
   1687 #ifdef VERIFY_HEAP
   1688   if (FLAG_verify_heap) {
   1689     VerifyStringTable(this->isolate());
   1690   }
   1691 #endif
   1692 
   1693   GCType gc_type =
   1694       collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge;
   1695 
   1696   {
   1697     GCCallbacksScope scope(this);
   1698     if (scope.CheckReenter()) {
   1699       AllowHeapAllocation allow_allocation;
   1700       TRACE_GC(tracer(), GCTracer::Scope::HEAP_EXTERNAL_PROLOGUE);
   1701       VMState<EXTERNAL> state(isolate_);
   1702       HandleScope handle_scope(isolate_);
   1703       CallGCPrologueCallbacks(gc_type, kNoGCCallbackFlags);
   1704     }
   1705   }
   1706 
   1707   EnsureFromSpaceIsCommitted();
   1708 
   1709   size_t start_new_space_size = Heap::new_space()->Size();
   1710 
   1711   {
   1712     Heap::SkipStoreBufferScope skip_store_buffer_scope(store_buffer_);
   1713 
   1714     switch (collector) {
   1715       case MARK_COMPACTOR:
   1716         UpdateOldGenerationAllocationCounter();
   1717         // Perform mark-sweep with optional compaction.
   1718         MarkCompact();
   1719         old_generation_size_configured_ = true;
   1720         // This should be updated before PostGarbageCollectionProcessing, which
   1721         // can cause another GC. Take into account the objects promoted during
   1722         // GC.
   1723         old_generation_allocation_counter_at_last_gc_ +=
   1724             static_cast<size_t>(promoted_objects_size_);
   1725         old_generation_size_at_last_gc_ = OldGenerationSizeOfObjects();
   1726         break;
   1727       case MINOR_MARK_COMPACTOR:
   1728         MinorMarkCompact();
   1729         break;
   1730       case SCAVENGER:
   1731         if ((fast_promotion_mode_ &&
   1732              CanExpandOldGeneration(new_space()->Size()))) {
   1733           tracer()->NotifyYoungGenerationHandling(
   1734               YoungGenerationHandling::kFastPromotionDuringScavenge);
   1735           EvacuateYoungGeneration();
   1736         } else {
   1737           tracer()->NotifyYoungGenerationHandling(
   1738               YoungGenerationHandling::kRegularScavenge);
   1739 
   1740           Scavenge();
   1741         }
   1742         break;
   1743     }
   1744 
   1745     ProcessPretenuringFeedback();
   1746   }
   1747 
   1748   UpdateSurvivalStatistics(static_cast<int>(start_new_space_size));
   1749   ConfigureInitialOldGenerationSize();
   1750 
   1751   if (collector != MARK_COMPACTOR) {
   1752     // Objects that died in the new space might have been accounted
   1753     // as bytes marked ahead of schedule by the incremental marker.
   1754     incremental_marking()->UpdateMarkedBytesAfterScavenge(
   1755         start_new_space_size - SurvivedNewSpaceObjectSize());
   1756   }
   1757 
   1758   if (!fast_promotion_mode_ || collector == MARK_COMPACTOR) {
   1759     ComputeFastPromotionMode();
   1760   }
   1761 
   1762   isolate_->counters()->objs_since_last_young()->Set(0);
   1763 
   1764   gc_post_processing_depth_++;
   1765   {
   1766     AllowHeapAllocation allow_allocation;
   1767     TRACE_GC(tracer(), GCTracer::Scope::HEAP_EXTERNAL_WEAK_GLOBAL_HANDLES);
   1768     freed_global_handles =
   1769         isolate_->global_handles()->PostGarbageCollectionProcessing(
   1770             collector, gc_callback_flags);
   1771   }
   1772   gc_post_processing_depth_--;
   1773 
   1774   isolate_->eternal_handles()->PostGarbageCollectionProcessing();
   1775 
   1776   // Update relocatables.
   1777   Relocatable::PostGarbageCollectionProcessing(isolate_);
   1778 
   1779   double gc_speed = tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond();
   1780   double mutator_speed =
   1781       tracer()->CurrentOldGenerationAllocationThroughputInBytesPerMillisecond();
   1782   size_t old_gen_size = OldGenerationSizeOfObjects();
   1783   if (collector == MARK_COMPACTOR) {
   1784     // Register the amount of external allocated memory.
   1785     external_memory_at_last_mark_compact_ = external_memory_;
   1786     external_memory_limit_ = external_memory_ + kExternalAllocationSoftLimit;
   1787 
   1788     size_t new_limit = heap_controller()->CalculateAllocationLimit(
   1789         old_gen_size, max_old_generation_size_, gc_speed, mutator_speed,
   1790         new_space()->Capacity(), CurrentHeapGrowingMode());
   1791     old_generation_allocation_limit_ = new_limit;
   1792 
   1793     CheckIneffectiveMarkCompact(
   1794         old_gen_size, tracer()->AverageMarkCompactMutatorUtilization());
   1795   } else if (HasLowYoungGenerationAllocationRate() &&
   1796              old_generation_size_configured_) {
   1797     size_t new_limit = heap_controller()->CalculateAllocationLimit(
   1798         old_gen_size, max_old_generation_size_, gc_speed, mutator_speed,
   1799         new_space()->Capacity(), CurrentHeapGrowingMode());
   1800     if (new_limit < old_generation_allocation_limit_) {
   1801       old_generation_allocation_limit_ = new_limit;
   1802     }
   1803   }
   1804 
   1805   {
   1806     GCCallbacksScope scope(this);
   1807     if (scope.CheckReenter()) {
   1808       AllowHeapAllocation allow_allocation;
   1809       TRACE_GC(tracer(), GCTracer::Scope::HEAP_EXTERNAL_EPILOGUE);
   1810       VMState<EXTERNAL> state(isolate_);
   1811       HandleScope handle_scope(isolate_);
   1812       CallGCEpilogueCallbacks(gc_type, gc_callback_flags);
   1813     }
   1814   }
   1815 
   1816 #ifdef VERIFY_HEAP
   1817   if (FLAG_verify_heap) {
   1818     VerifyStringTable(this->isolate());
   1819   }
   1820 #endif
   1821 
   1822   return freed_global_handles > 0;
   1823 }
   1824 
   1825 
   1826 void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) {
   1827   RuntimeCallTimerScope runtime_timer(
   1828       isolate(), RuntimeCallCounterId::kGCPrologueCallback);
   1829   for (const GCCallbackTuple& info : gc_prologue_callbacks_) {
   1830     if (gc_type & info.gc_type) {
   1831       v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
   1832       info.callback(isolate, gc_type, flags, info.data);
   1833     }
   1834   }
   1835 }
   1836 
   1837 void Heap::CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags) {
   1838   RuntimeCallTimerScope runtime_timer(
   1839       isolate(), RuntimeCallCounterId::kGCEpilogueCallback);
   1840   for (const GCCallbackTuple& info : gc_epilogue_callbacks_) {
   1841     if (gc_type & info.gc_type) {
   1842       v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
   1843       info.callback(isolate, gc_type, flags, info.data);
   1844     }
   1845   }
   1846 }
   1847 
   1848 
   1849 void Heap::MarkCompact() {
   1850   PauseAllocationObserversScope pause_observers(this);
   1851 
   1852   SetGCState(MARK_COMPACT);
   1853 
   1854   LOG(isolate_, ResourceEvent("markcompact", "begin"));
   1855 
   1856   uint64_t size_of_objects_before_gc = SizeOfObjects();
   1857 
   1858   CodeSpaceMemoryModificationScope code_modifcation(this);
   1859 
   1860   mark_compact_collector()->Prepare();
   1861 
   1862   ms_count_++;
   1863 
   1864   MarkCompactPrologue();
   1865 
   1866   mark_compact_collector()->CollectGarbage();
   1867 
   1868   LOG(isolate_, ResourceEvent("markcompact", "end"));
   1869 
   1870   MarkCompactEpilogue();
   1871 
   1872   if (FLAG_allocation_site_pretenuring) {
   1873     EvaluateOldSpaceLocalPretenuring(size_of_objects_before_gc);
   1874   }
   1875 }
   1876 
   1877 void Heap::MinorMarkCompact() {
   1878 #ifdef ENABLE_MINOR_MC
   1879   DCHECK(FLAG_minor_mc);
   1880 
   1881   PauseAllocationObserversScope pause_observers(this);
   1882   SetGCState(MINOR_MARK_COMPACT);
   1883   LOG(isolate_, ResourceEvent("MinorMarkCompact", "begin"));
   1884 
   1885   TRACE_GC(tracer(), GCTracer::Scope::MINOR_MC);
   1886   AlwaysAllocateScope always_allocate(isolate());
   1887   IncrementalMarking::PauseBlackAllocationScope pause_black_allocation(
   1888       incremental_marking());
   1889   ConcurrentMarking::PauseScope pause_scope(concurrent_marking());
   1890 
   1891   minor_mark_compact_collector()->CollectGarbage();
   1892 
   1893   LOG(isolate_, ResourceEvent("MinorMarkCompact", "end"));
   1894   SetGCState(NOT_IN_GC);
   1895 #else
   1896   UNREACHABLE();
   1897 #endif  // ENABLE_MINOR_MC
   1898 }
   1899 
   1900 void Heap::MarkCompactEpilogue() {
   1901   TRACE_GC(tracer(), GCTracer::Scope::MC_EPILOGUE);
   1902   SetGCState(NOT_IN_GC);
   1903 
   1904   isolate_->counters()->objs_since_last_full()->Set(0);
   1905 
   1906   incremental_marking()->Epilogue();
   1907 
   1908   DCHECK(incremental_marking()->IsStopped());
   1909 }
   1910 
   1911 
   1912 void Heap::MarkCompactPrologue() {
   1913   TRACE_GC(tracer(), GCTracer::Scope::MC_PROLOGUE);
   1914   isolate_->context_slot_cache()->Clear();
   1915   isolate_->descriptor_lookup_cache()->Clear();
   1916   RegExpResultsCache::Clear(string_split_cache());
   1917   RegExpResultsCache::Clear(regexp_multiple_cache());
   1918 
   1919   isolate_->compilation_cache()->MarkCompactPrologue();
   1920 
   1921   FlushNumberStringCache();
   1922 }
   1923 
   1924 
   1925 void Heap::CheckNewSpaceExpansionCriteria() {
   1926   if (FLAG_experimental_new_space_growth_heuristic) {
   1927     if (new_space_->TotalCapacity() < new_space_->MaximumCapacity() &&
   1928         survived_last_scavenge_ * 100 / new_space_->TotalCapacity() >= 10) {
   1929       // Grow the size of new space if there is room to grow, and more than 10%
   1930       // have survived the last scavenge.
   1931       new_space_->Grow();
   1932       survived_since_last_expansion_ = 0;
   1933     }
   1934   } else if (new_space_->TotalCapacity() < new_space_->MaximumCapacity() &&
   1935              survived_since_last_expansion_ > new_space_->TotalCapacity()) {
   1936     // Grow the size of new space if there is room to grow, and enough data
   1937     // has survived scavenge since the last expansion.
   1938     new_space_->Grow();
   1939     survived_since_last_expansion_ = 0;
   1940   }
   1941 }
   1942 
   1943 static bool IsUnscavengedHeapObject(Heap* heap, Object** p) {
   1944   return Heap::InFromSpace(*p) &&
   1945          !HeapObject::cast(*p)->map_word().IsForwardingAddress();
   1946 }
   1947 
   1948 class ScavengeWeakObjectRetainer : public WeakObjectRetainer {
   1949  public:
   1950   virtual Object* RetainAs(Object* object) {
   1951     if (!Heap::InFromSpace(object)) {
   1952       return object;
   1953     }
   1954 
   1955     MapWord map_word = HeapObject::cast(object)->map_word();
   1956     if (map_word.IsForwardingAddress()) {
   1957       return map_word.ToForwardingAddress();
   1958     }
   1959     return nullptr;
   1960   }
   1961 };
   1962 
   1963 void Heap::EvacuateYoungGeneration() {
   1964   TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_FAST_PROMOTE);
   1965   base::LockGuard<base::Mutex> guard(relocation_mutex());
   1966   ConcurrentMarking::PauseScope pause_scope(concurrent_marking());
   1967   if (!FLAG_concurrent_marking) {
   1968     DCHECK(fast_promotion_mode_);
   1969     DCHECK(CanExpandOldGeneration(new_space()->Size()));
   1970   }
   1971 
   1972   mark_compact_collector()->sweeper()->EnsureIterabilityCompleted();
   1973 
   1974   SetGCState(SCAVENGE);
   1975   LOG(isolate_, ResourceEvent("scavenge", "begin"));
   1976 
   1977   // Move pages from new->old generation.
   1978   PageRange range(new_space()->first_allocatable_address(), new_space()->top());
   1979   for (auto it = range.begin(); it != range.end();) {
   1980     Page* p = (*++it)->prev_page();
   1981     new_space()->from_space().RemovePage(p);
   1982     Page::ConvertNewToOld(p);
   1983     if (incremental_marking()->IsMarking())
   1984       mark_compact_collector()->RecordLiveSlotsOnPage(p);
   1985   }
   1986 
   1987   // Reset new space.
   1988   if (!new_space()->Rebalance()) {
   1989     FatalProcessOutOfMemory("NewSpace::Rebalance");
   1990   }
   1991   new_space()->ResetLinearAllocationArea();
   1992   new_space()->set_age_mark(new_space()->top());
   1993 
   1994   // Fix up special trackers.
   1995   external_string_table_.PromoteAllNewSpaceStrings();
   1996   // GlobalHandles are updated in PostGarbageCollectonProcessing
   1997 
   1998   IncrementYoungSurvivorsCounter(new_space()->Size());
   1999   IncrementPromotedObjectsSize(new_space()->Size());
   2000   IncrementSemiSpaceCopiedObjectSize(0);
   2001 
   2002   LOG(isolate_, ResourceEvent("scavenge", "end"));
   2003   SetGCState(NOT_IN_GC);
   2004 }
   2005 
   2006 static bool IsLogging(Isolate* isolate) {
   2007   return FLAG_verify_predictable || isolate->logger()->is_logging() ||
   2008          isolate->is_profiling() ||
   2009          (isolate->heap_profiler() != nullptr &&
   2010           isolate->heap_profiler()->is_tracking_object_moves()) ||
   2011          isolate->heap()->has_heap_object_allocation_tracker();
   2012 }
   2013 
   2014 class PageScavengingItem final : public ItemParallelJob::Item {
   2015  public:
   2016   explicit PageScavengingItem(MemoryChunk* chunk) : chunk_(chunk) {}
   2017   virtual ~PageScavengingItem() {}
   2018 
   2019   void Process(Scavenger* scavenger) { scavenger->ScavengePage(chunk_); }
   2020 
   2021  private:
   2022   MemoryChunk* const chunk_;
   2023 };
   2024 
   2025 class ScavengingTask final : public ItemParallelJob::Task {
   2026  public:
   2027   ScavengingTask(Heap* heap, Scavenger* scavenger, OneshotBarrier* barrier)
   2028       : ItemParallelJob::Task(heap->isolate()),
   2029         heap_(heap),
   2030         scavenger_(scavenger),
   2031         barrier_(barrier) {}
   2032 
   2033   void RunInParallel() final {
   2034     TRACE_BACKGROUND_GC(
   2035         heap_->tracer(),
   2036         GCTracer::BackgroundScope::SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL);
   2037     double scavenging_time = 0.0;
   2038     {
   2039       barrier_->Start();
   2040       TimedScope scope(&scavenging_time);
   2041       PageScavengingItem* item = nullptr;
   2042       while ((item = GetItem<PageScavengingItem>()) != nullptr) {
   2043         item->Process(scavenger_);
   2044         item->MarkFinished();
   2045       }
   2046       do {
   2047         scavenger_->Process(barrier_);
   2048       } while (!barrier_->Wait());
   2049       scavenger_->Process();
   2050     }
   2051     if (FLAG_trace_parallel_scavenge) {
   2052       PrintIsolate(heap_->isolate(),
   2053                    "scavenge[%p]: time=%.2f copied=%zu promoted=%zu\n",
   2054                    static_cast<void*>(this), scavenging_time,
   2055                    scavenger_->bytes_copied(), scavenger_->bytes_promoted());
   2056     }
   2057   };
   2058 
   2059  private:
   2060   Heap* const heap_;
   2061   Scavenger* const scavenger_;
   2062   OneshotBarrier* const barrier_;
   2063 };
   2064 
   2065 int Heap::NumberOfScavengeTasks() {
   2066   if (!FLAG_parallel_scavenge) return 1;
   2067   const int num_scavenge_tasks =
   2068       static_cast<int>(new_space()->TotalCapacity()) / MB;
   2069   static int num_cores = V8::GetCurrentPlatform()->NumberOfWorkerThreads() + 1;
   2070   int tasks =
   2071       Max(1, Min(Min(num_scavenge_tasks, kMaxScavengerTasks), num_cores));
   2072   if (!CanExpandOldGeneration(static_cast<size_t>(tasks * Page::kPageSize))) {
   2073     // Optimize for memory usage near the heap limit.
   2074     tasks = 1;
   2075   }
   2076   return tasks;
   2077 }
   2078 
   2079 void Heap::Scavenge() {
   2080   TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SCAVENGE);
   2081   base::LockGuard<base::Mutex> guard(relocation_mutex());
   2082   ConcurrentMarking::PauseScope pause_scope(concurrent_marking());
   2083   // There are soft limits in the allocation code, designed to trigger a mark
   2084   // sweep collection by failing allocations. There is no sense in trying to
   2085   // trigger one during scavenge: scavenges allocation should always succeed.
   2086   AlwaysAllocateScope scope(isolate());
   2087 
   2088   // Bump-pointer allocations done during scavenge are not real allocations.
   2089   // Pause the inline allocation steps.
   2090   PauseAllocationObserversScope pause_observers(this);
   2091 
   2092   IncrementalMarking::PauseBlackAllocationScope pause_black_allocation(
   2093       incremental_marking());
   2094 
   2095 
   2096   mark_compact_collector()->sweeper()->EnsureIterabilityCompleted();
   2097 
   2098   SetGCState(SCAVENGE);
   2099 
   2100   // Implements Cheney's copying algorithm
   2101   LOG(isolate_, ResourceEvent("scavenge", "begin"));
   2102 
   2103   // Flip the semispaces.  After flipping, to space is empty, from space has
   2104   // live objects.
   2105   new_space_->Flip();
   2106   new_space_->ResetLinearAllocationArea();
   2107 
   2108   ItemParallelJob job(isolate()->cancelable_task_manager(),
   2109                       &parallel_scavenge_semaphore_);
   2110   const int kMainThreadId = 0;
   2111   Scavenger* scavengers[kMaxScavengerTasks];
   2112   const bool is_logging = IsLogging(isolate());
   2113   const int num_scavenge_tasks = NumberOfScavengeTasks();
   2114   OneshotBarrier barrier;
   2115   Scavenger::CopiedList copied_list(num_scavenge_tasks);
   2116   Scavenger::PromotionList promotion_list(num_scavenge_tasks);
   2117   for (int i = 0; i < num_scavenge_tasks; i++) {
   2118     scavengers[i] =
   2119         new Scavenger(this, is_logging, &copied_list, &promotion_list, i);
   2120     job.AddTask(new ScavengingTask(this, scavengers[i], &barrier));
   2121   }
   2122 
   2123   {
   2124     Sweeper* sweeper = mark_compact_collector()->sweeper();
   2125     // Pause the concurrent sweeper.
   2126     Sweeper::PauseOrCompleteScope pause_scope(sweeper);
   2127     // Filter out pages from the sweeper that need to be processed for old to
   2128     // new slots by the Scavenger. After processing, the Scavenger adds back
   2129     // pages that are still unsweeped. This way the Scavenger has exclusive
   2130     // access to the slots of a page and can completely avoid any locks on
   2131     // the page itself.
   2132     Sweeper::FilterSweepingPagesScope filter_scope(sweeper, pause_scope);
   2133     filter_scope.FilterOldSpaceSweepingPages(
   2134         [](Page* page) { return !page->ContainsSlots<OLD_TO_NEW>(); });
   2135     RememberedSet<OLD_TO_NEW>::IterateMemoryChunks(
   2136         this, [&job](MemoryChunk* chunk) {
   2137           job.AddItem(new PageScavengingItem(chunk));
   2138         });
   2139 
   2140     RootScavengeVisitor root_scavenge_visitor(scavengers[kMainThreadId]);
   2141 
   2142     {
   2143       // Identify weak unmodified handles. Requires an unmodified graph.
   2144       TRACE_GC(
   2145           tracer(),
   2146           GCTracer::Scope::SCAVENGER_SCAVENGE_WEAK_GLOBAL_HANDLES_IDENTIFY);
   2147       isolate()->global_handles()->IdentifyWeakUnmodifiedObjects(
   2148           &JSObject::IsUnmodifiedApiObject);
   2149     }
   2150     {
   2151       // Copy roots.
   2152       TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SCAVENGE_ROOTS);
   2153       IterateRoots(&root_scavenge_visitor, VISIT_ALL_IN_SCAVENGE);
   2154     }
   2155     {
   2156       // Parallel phase scavenging all copied and promoted objects.
   2157       TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SCAVENGE_PARALLEL);
   2158       job.Run(isolate()->async_counters());
   2159       DCHECK(copied_list.IsEmpty());
   2160       DCHECK(promotion_list.IsEmpty());
   2161     }
   2162     {
   2163       // Scavenge weak global handles.
   2164       TRACE_GC(tracer(),
   2165                GCTracer::Scope::SCAVENGER_SCAVENGE_WEAK_GLOBAL_HANDLES_PROCESS);
   2166       isolate()->global_handles()->MarkNewSpaceWeakUnmodifiedObjectsPending(
   2167           &IsUnscavengedHeapObject);
   2168       isolate()
   2169           ->global_handles()
   2170           ->IterateNewSpaceWeakUnmodifiedRootsForFinalizers(
   2171               &root_scavenge_visitor);
   2172       scavengers[kMainThreadId]->Process();
   2173 
   2174       DCHECK(copied_list.IsEmpty());
   2175       DCHECK(promotion_list.IsEmpty());
   2176       isolate()
   2177           ->global_handles()
   2178           ->IterateNewSpaceWeakUnmodifiedRootsForPhantomHandles(
   2179               &root_scavenge_visitor, &IsUnscavengedHeapObject);
   2180     }
   2181 
   2182     for (int i = 0; i < num_scavenge_tasks; i++) {
   2183       scavengers[i]->Finalize();
   2184       delete scavengers[i];
   2185     }
   2186   }
   2187 
   2188   {
   2189     // Update references into new space
   2190     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SCAVENGE_UPDATE_REFS);
   2191     UpdateNewSpaceReferencesInExternalStringTable(
   2192         &UpdateNewSpaceReferenceInExternalStringTableEntry);
   2193 
   2194     incremental_marking()->UpdateMarkingWorklistAfterScavenge();
   2195   }
   2196 
   2197   if (FLAG_concurrent_marking) {
   2198     // Ensure that concurrent marker does not track pages that are
   2199     // going to be unmapped.
   2200     for (Page* p : PageRange(new_space()->from_space().first_page(), nullptr)) {
   2201       concurrent_marking()->ClearLiveness(p);
   2202     }
   2203   }
   2204 
   2205   ScavengeWeakObjectRetainer weak_object_retainer;
   2206   ProcessYoungWeakReferences(&weak_object_retainer);
   2207 
   2208   // Set age mark.
   2209   new_space_->set_age_mark(new_space_->top());
   2210 
   2211   {
   2212     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_PROCESS_ARRAY_BUFFERS);
   2213     ArrayBufferTracker::PrepareToFreeDeadInNewSpace(this);
   2214   }
   2215   array_buffer_collector()->FreeAllocationsOnBackgroundThread();
   2216 
   2217   RememberedSet<OLD_TO_NEW>::IterateMemoryChunks(this, [](MemoryChunk* chunk) {
   2218     if (chunk->SweepingDone()) {
   2219       RememberedSet<OLD_TO_NEW>::FreeEmptyBuckets(chunk);
   2220     } else {
   2221       RememberedSet<OLD_TO_NEW>::PreFreeEmptyBuckets(chunk);
   2222     }
   2223   });
   2224 
   2225   // Update how much has survived scavenge.
   2226   IncrementYoungSurvivorsCounter(SurvivedNewSpaceObjectSize());
   2227 
   2228   // Scavenger may find new wrappers by iterating objects promoted onto a black
   2229   // page.
   2230   local_embedder_heap_tracer()->RegisterWrappersWithRemoteTracer();
   2231 
   2232   LOG(isolate_, ResourceEvent("scavenge", "end"));
   2233 
   2234   SetGCState(NOT_IN_GC);
   2235 }
   2236 
   2237 void Heap::ComputeFastPromotionMode() {
   2238   const size_t survived_in_new_space =
   2239       survived_last_scavenge_ * 100 / new_space_->Capacity();
   2240   fast_promotion_mode_ =
   2241       !FLAG_optimize_for_size && FLAG_fast_promotion_new_space &&
   2242       !ShouldReduceMemory() && new_space_->IsAtMaximumCapacity() &&
   2243       survived_in_new_space >= kMinPromotedPercentForFastPromotionMode;
   2244   if (FLAG_trace_gc_verbose && !FLAG_trace_gc_ignore_scavenger) {
   2245     PrintIsolate(
   2246         isolate(), "Fast promotion mode: %s survival rate: %" PRIuS "%%\n",
   2247         fast_promotion_mode_ ? "true" : "false", survived_in_new_space);
   2248   }
   2249 }
   2250 
   2251 void Heap::UnprotectAndRegisterMemoryChunk(MemoryChunk* chunk) {
   2252   if (unprotected_memory_chunks_registry_enabled_) {
   2253     base::LockGuard<base::Mutex> guard(&unprotected_memory_chunks_mutex_);
   2254     if (unprotected_memory_chunks_.insert(chunk).second) {
   2255       chunk->SetReadAndWritable();
   2256     }
   2257   }
   2258 }
   2259 
   2260 void Heap::UnprotectAndRegisterMemoryChunk(HeapObject* object) {
   2261   UnprotectAndRegisterMemoryChunk(MemoryChunk::FromAddress(object->address()));
   2262 }
   2263 
   2264 void Heap::UnregisterUnprotectedMemoryChunk(MemoryChunk* chunk) {
   2265   unprotected_memory_chunks_.erase(chunk);
   2266 }
   2267 
   2268 void Heap::ProtectUnprotectedMemoryChunks() {
   2269   DCHECK(unprotected_memory_chunks_registry_enabled_);
   2270   for (auto chunk = unprotected_memory_chunks_.begin();
   2271        chunk != unprotected_memory_chunks_.end(); chunk++) {
   2272     CHECK(memory_allocator()->IsMemoryChunkExecutable(*chunk));
   2273     (*chunk)->SetReadAndExecutable();
   2274   }
   2275   unprotected_memory_chunks_.clear();
   2276 }
   2277 
   2278 bool Heap::ExternalStringTable::Contains(HeapObject* obj) {
   2279   for (size_t i = 0; i < new_space_strings_.size(); ++i) {
   2280     if (new_space_strings_[i] == obj) return true;
   2281   }
   2282   for (size_t i = 0; i < old_space_strings_.size(); ++i) {
   2283     if (old_space_strings_[i] == obj) return true;
   2284   }
   2285   return false;
   2286 }
   2287 
   2288 void Heap::ProcessMovedExternalString(Page* old_page, Page* new_page,
   2289                                       ExternalString* string) {
   2290   size_t size = string->ExternalPayloadSize();
   2291   new_page->IncrementExternalBackingStoreBytes(
   2292       ExternalBackingStoreType::kExternalString, size);
   2293   old_page->DecrementExternalBackingStoreBytes(
   2294       ExternalBackingStoreType::kExternalString, size);
   2295 }
   2296 
   2297 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
   2298                                                                 Object** p) {
   2299   MapWord first_word = HeapObject::cast(*p)->map_word();
   2300 
   2301   if (!first_word.IsForwardingAddress()) {
   2302     // Unreachable external string can be finalized.
   2303     String* string = String::cast(*p);
   2304     if (!string->IsExternalString()) {
   2305       // Original external string has been internalized.
   2306       DCHECK(string->IsThinString());
   2307       return nullptr;
   2308     }
   2309     heap->FinalizeExternalString(string);
   2310     return nullptr;
   2311   }
   2312 
   2313   // String is still reachable.
   2314   String* new_string = String::cast(first_word.ToForwardingAddress());
   2315   String* original_string = reinterpret_cast<String*>(*p);
   2316   // The length of the original string is used to disambiguate the scenario
   2317   // of a ThingString being forwarded to an ExternalString (which already exists
   2318   // in the OLD space), and an ExternalString being forwarded to its promoted
   2319   // copy. See Scavenger::EvacuateThinString.
   2320   if (new_string->IsThinString() || original_string->length() == 0) {
   2321     // Filtering Thin strings out of the external string table.
   2322     return nullptr;
   2323   } else if (new_string->IsExternalString()) {
   2324     heap->ProcessMovedExternalString(
   2325         Page::FromAddress(reinterpret_cast<Address>(*p)),
   2326         Page::FromHeapObject(new_string), ExternalString::cast(new_string));
   2327     return new_string;
   2328   }
   2329 
   2330   // Internalization can replace external strings with non-external strings.
   2331   return new_string->IsExternalString() ? new_string : nullptr;
   2332 }
   2333 
   2334 void Heap::ExternalStringTable::VerifyNewSpace() {
   2335 #ifdef DEBUG
   2336   std::set<String*> visited_map;
   2337   std::map<MemoryChunk*, size_t> size_map;
   2338   ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;
   2339   for (size_t i = 0; i < new_space_strings_.size(); ++i) {
   2340     String* obj = String::cast(new_space_strings_[i]);
   2341     MemoryChunk* mc = MemoryChunk::FromHeapObject(obj);
   2342     DCHECK(mc->InNewSpace());
   2343     DCHECK(heap_->InNewSpace(obj));
   2344     DCHECK(!obj->IsTheHole(heap_->isolate()));
   2345     DCHECK(obj->IsExternalString());
   2346     // Note: we can have repeated elements in the table.
   2347     DCHECK_EQ(0, visited_map.count(obj));
   2348     visited_map.insert(obj);
   2349     size_map[mc] += ExternalString::cast(obj)->ExternalPayloadSize();
   2350   }
   2351   for (std::map<MemoryChunk*, size_t>::iterator it = size_map.begin();
   2352        it != size_map.end(); it++)
   2353     DCHECK_EQ(it->first->ExternalBackingStoreBytes(type), it->second);
   2354 #endif
   2355 }
   2356 
   2357 void Heap::ExternalStringTable::Verify() {
   2358 #ifdef DEBUG
   2359   std::set<String*> visited_map;
   2360   std::map<MemoryChunk*, size_t> size_map;
   2361   ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;
   2362   VerifyNewSpace();
   2363   for (size_t i = 0; i < old_space_strings_.size(); ++i) {
   2364     String* obj = String::cast(old_space_strings_[i]);
   2365     MemoryChunk* mc = MemoryChunk::FromHeapObject(obj);
   2366     DCHECK(!mc->InNewSpace());
   2367     DCHECK(!heap_->InNewSpace(obj));
   2368     DCHECK(!obj->IsTheHole(heap_->isolate()));
   2369     DCHECK(obj->IsExternalString());
   2370     // Note: we can have repeated elements in the table.
   2371     DCHECK_EQ(0, visited_map.count(obj));
   2372     visited_map.insert(obj);
   2373     size_map[mc] += ExternalString::cast(obj)->ExternalPayloadSize();
   2374   }
   2375   for (std::map<MemoryChunk*, size_t>::iterator it = size_map.begin();
   2376        it != size_map.end(); it++)
   2377     DCHECK_EQ(it->first->ExternalBackingStoreBytes(type), it->second);
   2378 #endif
   2379 }
   2380 
   2381 void Heap::ExternalStringTable::UpdateNewSpaceReferences(
   2382     Heap::ExternalStringTableUpdaterCallback updater_func) {
   2383   if (new_space_strings_.empty()) return;
   2384 
   2385   Object** start = new_space_strings_.data();
   2386   Object** end = start + new_space_strings_.size();
   2387   Object** last = start;
   2388 
   2389   for (Object** p = start; p < end; ++p) {
   2390     String* target = updater_func(heap_, p);
   2391 
   2392     if (target == nullptr) continue;
   2393 
   2394     DCHECK(target->IsExternalString());
   2395 
   2396     if (InNewSpace(target)) {
   2397       // String is still in new space. Update the table entry.
   2398       *last = target;
   2399       ++last;
   2400     } else {
   2401       // String got promoted. Move it to the old string list.
   2402       old_space_strings_.push_back(target);
   2403     }
   2404   }
   2405 
   2406   DCHECK_LE(last, end);
   2407   new_space_strings_.resize(static_cast<size_t>(last - start));
   2408 #ifdef VERIFY_HEAP
   2409   if (FLAG_verify_heap) {
   2410     VerifyNewSpace();
   2411   }
   2412 #endif
   2413 }
   2414 
   2415 void Heap::ExternalStringTable::PromoteAllNewSpaceStrings() {
   2416   old_space_strings_.reserve(old_space_strings_.size() +
   2417                              new_space_strings_.size());
   2418   std::move(std::begin(new_space_strings_), std::end(new_space_strings_),
   2419             std::back_inserter(old_space_strings_));
   2420   new_space_strings_.clear();
   2421 }
   2422 
   2423 void Heap::ExternalStringTable::IterateNewSpaceStrings(RootVisitor* v) {
   2424   if (!new_space_strings_.empty()) {
   2425     v->VisitRootPointers(Root::kExternalStringsTable, nullptr,
   2426                          new_space_strings_.data(),
   2427                          new_space_strings_.data() + new_space_strings_.size());
   2428   }
   2429 }
   2430 
   2431 void Heap::ExternalStringTable::IterateAll(RootVisitor* v) {
   2432   IterateNewSpaceStrings(v);
   2433   if (!old_space_strings_.empty()) {
   2434     v->VisitRootPointers(Root::kExternalStringsTable, nullptr,
   2435                          old_space_strings_.data(),
   2436                          old_space_strings_.data() + old_space_strings_.size());
   2437   }
   2438 }
   2439 
   2440 void Heap::UpdateNewSpaceReferencesInExternalStringTable(
   2441     ExternalStringTableUpdaterCallback updater_func) {
   2442   external_string_table_.UpdateNewSpaceReferences(updater_func);
   2443 }
   2444 
   2445 void Heap::ExternalStringTable::UpdateReferences(
   2446     Heap::ExternalStringTableUpdaterCallback updater_func) {
   2447   if (old_space_strings_.size() > 0) {
   2448     Object** start = old_space_strings_.data();
   2449     Object** end = start + old_space_strings_.size();
   2450     for (Object** p = start; p < end; ++p) *p = updater_func(heap_, p);
   2451   }
   2452 
   2453   UpdateNewSpaceReferences(updater_func);
   2454 }
   2455 
   2456 void Heap::UpdateReferencesInExternalStringTable(
   2457     ExternalStringTableUpdaterCallback updater_func) {
   2458   external_string_table_.UpdateReferences(updater_func);
   2459 }
   2460 
   2461 
   2462 void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) {
   2463   ProcessNativeContexts(retainer);
   2464   ProcessAllocationSites(retainer);
   2465 }
   2466 
   2467 
   2468 void Heap::ProcessYoungWeakReferences(WeakObjectRetainer* retainer) {
   2469   ProcessNativeContexts(retainer);
   2470 }
   2471 
   2472 
   2473 void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) {
   2474   Object* head = VisitWeakList<Context>(this, native_contexts_list(), retainer);
   2475   // Update the head of the list of contexts.
   2476   set_native_contexts_list(head);
   2477 }
   2478 
   2479 
   2480 void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) {
   2481   Object* allocation_site_obj =
   2482       VisitWeakList<AllocationSite>(this, allocation_sites_list(), retainer);
   2483   set_allocation_sites_list(allocation_site_obj);
   2484 }
   2485 
   2486 void Heap::ProcessWeakListRoots(WeakObjectRetainer* retainer) {
   2487   set_native_contexts_list(retainer->RetainAs(native_contexts_list()));
   2488   set_allocation_sites_list(retainer->RetainAs(allocation_sites_list()));
   2489 }
   2490 
   2491 void Heap::ForeachAllocationSite(Object* list,
   2492                                  std::function<void(AllocationSite*)> visitor) {
   2493   DisallowHeapAllocation disallow_heap_allocation;
   2494   Object* current = list;
   2495   while (current->IsAllocationSite()) {
   2496     AllocationSite* site = AllocationSite::cast(current);
   2497     visitor(site);
   2498     Object* current_nested = site->nested_site();
   2499     while (current_nested->IsAllocationSite()) {
   2500       AllocationSite* nested_site = AllocationSite::cast(current_nested);
   2501       visitor(nested_site);
   2502       current_nested = nested_site->nested_site();
   2503     }
   2504     current = site->weak_next();
   2505   }
   2506 }
   2507 
   2508 void Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) {
   2509   DisallowHeapAllocation no_allocation_scope;
   2510   bool marked = false;
   2511 
   2512   ForeachAllocationSite(allocation_sites_list(),
   2513                         [&marked, flag, this](AllocationSite* site) {
   2514                           if (site->GetPretenureMode() == flag) {
   2515                             site->ResetPretenureDecision();
   2516                             site->set_deopt_dependent_code(true);
   2517                             marked = true;
   2518                             RemoveAllocationSitePretenuringFeedback(site);
   2519                             return;
   2520                           }
   2521                         });
   2522   if (marked) isolate_->stack_guard()->RequestDeoptMarkedAllocationSites();
   2523 }
   2524 
   2525 
   2526 void Heap::EvaluateOldSpaceLocalPretenuring(
   2527     uint64_t size_of_objects_before_gc) {
   2528   uint64_t size_of_objects_after_gc = SizeOfObjects();
   2529   double old_generation_survival_rate =
   2530       (static_cast<double>(size_of_objects_after_gc) * 100) /
   2531       static_cast<double>(size_of_objects_before_gc);
   2532 
   2533   if (old_generation_survival_rate < kOldSurvivalRateLowThreshold) {
   2534     // Too many objects died in the old generation, pretenuring of wrong
   2535     // allocation sites may be the cause for that. We have to deopt all
   2536     // dependent code registered in the allocation sites to re-evaluate
   2537     // our pretenuring decisions.
   2538     ResetAllAllocationSitesDependentCode(TENURED);
   2539     if (FLAG_trace_pretenuring) {
   2540       PrintF(
   2541           "Deopt all allocation sites dependent code due to low survival "
   2542           "rate in the old generation %f\n",
   2543           old_generation_survival_rate);
   2544     }
   2545   }
   2546 }
   2547 
   2548 
   2549 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
   2550   DisallowHeapAllocation no_allocation;
   2551   // All external strings are listed in the external string table.
   2552 
   2553   class ExternalStringTableVisitorAdapter : public RootVisitor {
   2554    public:
   2555     explicit ExternalStringTableVisitorAdapter(
   2556         Isolate* isolate, v8::ExternalResourceVisitor* visitor)
   2557         : isolate_(isolate), visitor_(visitor) {}
   2558     virtual void VisitRootPointers(Root root, const char* description,
   2559                                    Object** start, Object** end) {
   2560       for (Object** p = start; p < end; p++) {
   2561         DCHECK((*p)->IsExternalString());
   2562         visitor_->VisitExternalString(
   2563             Utils::ToLocal(Handle<String>(String::cast(*p), isolate_)));
   2564       }
   2565     }
   2566 
   2567    private:
   2568     Isolate* isolate_;
   2569     v8::ExternalResourceVisitor* visitor_;
   2570   } external_string_table_visitor(isolate(), visitor);
   2571 
   2572   external_string_table_.IterateAll(&external_string_table_visitor);
   2573 }
   2574 
   2575 STATIC_ASSERT((FixedDoubleArray::kHeaderSize & kDoubleAlignmentMask) ==
   2576               0);  // NOLINT
   2577 STATIC_ASSERT((FixedTypedArrayBase::kDataOffset & kDoubleAlignmentMask) ==
   2578               0);  // NOLINT
   2579 #ifdef V8_HOST_ARCH_32_BIT
   2580 STATIC_ASSERT((HeapNumber::kValueOffset & kDoubleAlignmentMask) !=
   2581               0);  // NOLINT
   2582 #endif
   2583 
   2584 
   2585 int Heap::GetMaximumFillToAlign(AllocationAlignment alignment) {
   2586   switch (alignment) {
   2587     case kWordAligned:
   2588       return 0;
   2589     case kDoubleAligned:
   2590     case kDoubleUnaligned:
   2591       return kDoubleSize - kPointerSize;
   2592     default:
   2593       UNREACHABLE();
   2594   }
   2595   return 0;
   2596 }
   2597 
   2598 
   2599 int Heap::GetFillToAlign(Address address, AllocationAlignment alignment) {
   2600   intptr_t offset = OffsetFrom(address);
   2601   if (alignment == kDoubleAligned && (offset & kDoubleAlignmentMask) != 0)
   2602     return kPointerSize;
   2603   if (alignment == kDoubleUnaligned && (offset & kDoubleAlignmentMask) == 0)
   2604     return kDoubleSize - kPointerSize;  // No fill if double is always aligned.
   2605   return 0;
   2606 }
   2607 
   2608 
   2609 HeapObject* Heap::PrecedeWithFiller(HeapObject* object, int filler_size) {
   2610   CreateFillerObjectAt(object->address(), filler_size, ClearRecordedSlots::kNo);
   2611   return HeapObject::FromAddress(object->address() + filler_size);
   2612 }
   2613 
   2614 
   2615 HeapObject* Heap::AlignWithFiller(HeapObject* object, int object_size,
   2616                                   int allocation_size,
   2617                                   AllocationAlignment alignment) {
   2618   int filler_size = allocation_size - object_size;
   2619   DCHECK_LT(0, filler_size);
   2620   int pre_filler = GetFillToAlign(object->address(), alignment);
   2621   if (pre_filler) {
   2622     object = PrecedeWithFiller(object, pre_filler);
   2623     filler_size -= pre_filler;
   2624   }
   2625   if (filler_size)
   2626     CreateFillerObjectAt(object->address() + object_size, filler_size,
   2627                          ClearRecordedSlots::kNo);
   2628   return object;
   2629 }
   2630 
   2631 void Heap::RegisterNewArrayBuffer(JSArrayBuffer* buffer) {
   2632   ArrayBufferTracker::RegisterNew(this, buffer);
   2633 }
   2634 
   2635 
   2636 void Heap::UnregisterArrayBuffer(JSArrayBuffer* buffer) {
   2637   ArrayBufferTracker::Unregister(this, buffer);
   2638 }
   2639 
   2640 void Heap::ConfigureInitialOldGenerationSize() {
   2641   if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) {
   2642     old_generation_allocation_limit_ =
   2643         Max(heap_controller()->MinimumAllocationLimitGrowingStep(
   2644                 CurrentHeapGrowingMode()),
   2645             static_cast<size_t>(
   2646                 static_cast<double>(old_generation_allocation_limit_) *
   2647                 (tracer()->AverageSurvivalRatio() / 100)));
   2648   }
   2649 }
   2650 
   2651 void Heap::CreateJSEntryStub() {
   2652   JSEntryStub stub(isolate(), StackFrame::ENTRY);
   2653   set_js_entry_code(*stub.GetCode());
   2654 }
   2655 
   2656 
   2657 void Heap::CreateJSConstructEntryStub() {
   2658   JSEntryStub stub(isolate(), StackFrame::CONSTRUCT_ENTRY);
   2659   set_js_construct_entry_code(*stub.GetCode());
   2660 }
   2661 
   2662 void Heap::CreateJSRunMicrotasksEntryStub() {
   2663   JSEntryStub stub(isolate(), JSEntryStub::SpecialTarget::kRunMicrotasks);
   2664   set_js_run_microtasks_entry_code(*stub.GetCode());
   2665 }
   2666 
   2667 void Heap::CreateFixedStubs() {
   2668   // Here we create roots for fixed stubs. They are needed at GC
   2669   // for cooking and uncooking (check out frames.cc).
   2670   // The eliminates the need for doing dictionary lookup in the
   2671   // stub cache for these stubs.
   2672   HandleScope scope(isolate());
   2673   // Canonicalize handles, so that we can share constant pool entries pointing
   2674   // to code targets without dereferencing their handles.
   2675   CanonicalHandleScope canonical(isolate());
   2676 
   2677   // Create stubs that should be there, so we don't unexpectedly have to
   2678   // create them if we need them during the creation of another stub.
   2679   // Stub creation mixes raw pointers and handles in an unsafe manner so
   2680   // we cannot create stubs while we are creating stubs.
   2681   CodeStub::GenerateStubsAheadOfTime(isolate());
   2682 
   2683   // gcc-4.4 has problem generating correct code of following snippet:
   2684   // {  JSEntryStub stub;
   2685   //    js_entry_code_ = *stub.GetCode();
   2686   // }
   2687   // {  JSConstructEntryStub stub;
   2688   //    js_construct_entry_code_ = *stub.GetCode();
   2689   // }
   2690   // To workaround the problem, make separate functions without inlining.
   2691   Heap::CreateJSEntryStub();
   2692   Heap::CreateJSConstructEntryStub();
   2693   Heap::CreateJSRunMicrotasksEntryStub();
   2694 }
   2695 
   2696 bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
   2697   switch (root_index) {
   2698     case kNumberStringCacheRootIndex:
   2699     case kCodeStubsRootIndex:
   2700     case kScriptListRootIndex:
   2701     case kMaterializedObjectsRootIndex:
   2702     case kMicrotaskQueueRootIndex:
   2703     case kDetachedContextsRootIndex:
   2704     case kRetainedMapsRootIndex:
   2705     case kRetainingPathTargetsRootIndex:
   2706     case kFeedbackVectorsForProfilingToolsRootIndex:
   2707     case kNoScriptSharedFunctionInfosRootIndex:
   2708     case kSerializedObjectsRootIndex:
   2709     case kSerializedGlobalProxySizesRootIndex:
   2710     case kPublicSymbolTableRootIndex:
   2711     case kApiSymbolTableRootIndex:
   2712     case kApiPrivateSymbolTableRootIndex:
   2713     case kMessageListenersRootIndex:
   2714     case kDeserializeLazyHandlerRootIndex:
   2715     case kDeserializeLazyHandlerWideRootIndex:
   2716     case kDeserializeLazyHandlerExtraWideRootIndex:
   2717 // Smi values
   2718 #define SMI_ENTRY(type, name, Name) case k##Name##RootIndex:
   2719       SMI_ROOT_LIST(SMI_ENTRY)
   2720 #undef SMI_ENTRY
   2721     // String table
   2722     case kStringTableRootIndex:
   2723       return true;
   2724 
   2725     default:
   2726       return false;
   2727   }
   2728 }
   2729 
   2730 bool Heap::RootCanBeTreatedAsConstant(RootListIndex root_index) {
   2731   bool can_be = !RootCanBeWrittenAfterInitialization(root_index) &&
   2732                 !InNewSpace(root(root_index));
   2733   DCHECK_IMPLIES(can_be, IsImmovable(HeapObject::cast(root(root_index))));
   2734   return can_be;
   2735 }
   2736 
   2737 
   2738 void Heap::FlushNumberStringCache() {
   2739   // Flush the number to string cache.
   2740   int len = number_string_cache()->length();
   2741   for (int i = 0; i < len; i++) {
   2742     number_string_cache()->set_undefined(i);
   2743   }
   2744 }
   2745 
   2746 namespace {
   2747 
   2748 Heap::RootListIndex RootIndexForFixedTypedArray(ExternalArrayType array_type) {
   2749   switch (array_type) {
   2750 #define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype) \
   2751   case kExternal##Type##Array:                            \
   2752     return Heap::kFixed##Type##ArrayMapRootIndex;
   2753 
   2754     TYPED_ARRAYS(ARRAY_TYPE_TO_ROOT_INDEX)
   2755 #undef ARRAY_TYPE_TO_ROOT_INDEX
   2756   }
   2757   UNREACHABLE();
   2758 }
   2759 
   2760 Heap::RootListIndex RootIndexForFixedTypedArray(ElementsKind elements_kind) {
   2761   switch (elements_kind) {
   2762 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
   2763   case TYPE##_ELEMENTS:                           \
   2764     return Heap::kFixed##Type##ArrayMapRootIndex;
   2765     TYPED_ARRAYS(TYPED_ARRAY_CASE)
   2766     default:
   2767       UNREACHABLE();
   2768 #undef TYPED_ARRAY_CASE
   2769   }
   2770 }
   2771 
   2772 Heap::RootListIndex RootIndexForEmptyFixedTypedArray(
   2773     ElementsKind elements_kind) {
   2774   switch (elements_kind) {
   2775 #define ELEMENT_KIND_TO_ROOT_INDEX(Type, type, TYPE, ctype) \
   2776   case TYPE##_ELEMENTS:                                     \
   2777     return Heap::kEmptyFixed##Type##ArrayRootIndex;
   2778 
   2779     TYPED_ARRAYS(ELEMENT_KIND_TO_ROOT_INDEX)
   2780 #undef ELEMENT_KIND_TO_ROOT_INDEX
   2781     default:
   2782       UNREACHABLE();
   2783   }
   2784 }
   2785 
   2786 }  // namespace
   2787 
   2788 Map* Heap::MapForFixedTypedArray(ExternalArrayType array_type) {
   2789   return Map::cast(roots_[RootIndexForFixedTypedArray(array_type)]);
   2790 }
   2791 
   2792 Map* Heap::MapForFixedTypedArray(ElementsKind elements_kind) {
   2793   return Map::cast(roots_[RootIndexForFixedTypedArray(elements_kind)]);
   2794 }
   2795 
   2796 FixedTypedArrayBase* Heap::EmptyFixedTypedArrayForMap(const Map* map) {
   2797   return FixedTypedArrayBase::cast(
   2798       roots_[RootIndexForEmptyFixedTypedArray(map->elements_kind())]);
   2799 }
   2800 
   2801 HeapObject* Heap::CreateFillerObjectAt(Address addr, int size,
   2802                                        ClearRecordedSlots clear_slots_mode,
   2803                                        ClearFreedMemoryMode clear_memory_mode) {
   2804   if (size == 0) return nullptr;
   2805   HeapObject* filler = HeapObject::FromAddress(addr);
   2806   if (size == kPointerSize) {
   2807     filler->set_map_after_allocation(
   2808         reinterpret_cast<Map*>(root(kOnePointerFillerMapRootIndex)),
   2809         SKIP_WRITE_BARRIER);
   2810   } else if (size == 2 * kPointerSize) {
   2811     filler->set_map_after_allocation(
   2812         reinterpret_cast<Map*>(root(kTwoPointerFillerMapRootIndex)),
   2813         SKIP_WRITE_BARRIER);
   2814     if (clear_memory_mode == ClearFreedMemoryMode::kClearFreedMemory) {
   2815       Memory<Address>(addr + kPointerSize) =
   2816           static_cast<Address>(kClearedFreeMemoryValue);
   2817     }
   2818   } else {
   2819     DCHECK_GT(size, 2 * kPointerSize);
   2820     filler->set_map_after_allocation(
   2821         reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex)),
   2822         SKIP_WRITE_BARRIER);
   2823     FreeSpace::cast(filler)->relaxed_write_size(size);
   2824     if (clear_memory_mode == ClearFreedMemoryMode::kClearFreedMemory) {
   2825       memset(reinterpret_cast<void*>(addr + 2 * kPointerSize),
   2826              kClearedFreeMemoryValue, size - 2 * kPointerSize);
   2827     }
   2828   }
   2829   if (clear_slots_mode == ClearRecordedSlots::kYes) {
   2830     ClearRecordedSlotRange(addr, addr + size);
   2831   }
   2832 
   2833   // At this point, we may be deserializing the heap from a snapshot, and
   2834   // none of the maps have been created yet and are nullptr.
   2835   DCHECK((filler->map() == nullptr && !deserialization_complete_) ||
   2836          filler->map()->IsMap());
   2837   return filler;
   2838 }
   2839 
   2840 
   2841 bool Heap::CanMoveObjectStart(HeapObject* object) {
   2842   if (!FLAG_move_object_start) return false;
   2843 
   2844   // Sampling heap profiler may have a reference to the object.
   2845   if (isolate()->heap_profiler()->is_sampling_allocations()) return false;
   2846 
   2847   Address address = object->address();
   2848 
   2849   if (lo_space()->Contains(object)) return false;
   2850 
   2851   // We can move the object start if the page was already swept.
   2852   return Page::FromAddress(address)->SweepingDone();
   2853 }
   2854 
   2855 bool Heap::IsImmovable(HeapObject* object) {
   2856   MemoryChunk* chunk = MemoryChunk::FromAddress(object->address());
   2857   return chunk->NeverEvacuate() || chunk->owner()->identity() == LO_SPACE;
   2858 }
   2859 
   2860 #ifdef ENABLE_SLOW_DCHECKS
   2861 namespace {
   2862 
   2863 class LeftTrimmerVerifierRootVisitor : public RootVisitor {
   2864  public:
   2865   explicit LeftTrimmerVerifierRootVisitor(FixedArrayBase* to_check)
   2866       : to_check_(to_check) {}
   2867 
   2868   virtual void VisitRootPointers(Root root, const char* description,
   2869                                  Object** start, Object** end) {
   2870     for (Object** p = start; p < end; ++p) {
   2871       DCHECK_NE(*p, to_check_);
   2872     }
   2873   }
   2874 
   2875  private:
   2876   FixedArrayBase* to_check_;
   2877 
   2878   DISALLOW_COPY_AND_ASSIGN(LeftTrimmerVerifierRootVisitor);
   2879 };
   2880 }  // namespace
   2881 #endif  // ENABLE_SLOW_DCHECKS
   2882 
   2883 namespace {
   2884 bool MayContainRecordedSlots(HeapObject* object) {
   2885   // New space object do not have recorded slots.
   2886   if (MemoryChunk::FromHeapObject(object)->InNewSpace()) return false;
   2887   // Whitelist objects that definitely do not have pointers.
   2888   if (object->IsByteArray() || object->IsFixedDoubleArray()) return false;
   2889   // Conservatively return true for other objects.
   2890   return true;
   2891 }
   2892 }  // namespace
   2893 
   2894 FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object,
   2895                                          int elements_to_trim) {
   2896   if (elements_to_trim == 0) {
   2897     // This simplifies reasoning in the rest of the function.
   2898     return object;
   2899   }
   2900   CHECK_NOT_NULL(object);
   2901   DCHECK(CanMoveObjectStart(object));
   2902   // Add custom visitor to concurrent marker if new left-trimmable type
   2903   // is added.
   2904   DCHECK(object->IsFixedArray() || object->IsFixedDoubleArray());
   2905   const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize;
   2906   const int bytes_to_trim = elements_to_trim * element_size;
   2907   Map* map = object->map();
   2908 
   2909   // For now this trick is only applied to objects in new and paged space.
   2910   // In large object space the object's start must coincide with chunk
   2911   // and thus the trick is just not applicable.
   2912   DCHECK(!lo_space()->Contains(object));
   2913   DCHECK(object->map() != ReadOnlyRoots(this).fixed_cow_array_map());
   2914 
   2915   STATIC_ASSERT(FixedArrayBase::kMapOffset == 0);
   2916   STATIC_ASSERT(FixedArrayBase::kLengthOffset == kPointerSize);
   2917   STATIC_ASSERT(FixedArrayBase::kHeaderSize == 2 * kPointerSize);
   2918 
   2919   const int len = object->length();
   2920   DCHECK(elements_to_trim <= len);
   2921 
   2922   // Calculate location of new array start.
   2923   Address old_start = object->address();
   2924   Address new_start = old_start + bytes_to_trim;
   2925 
   2926   if (incremental_marking()->IsMarking()) {
   2927     incremental_marking()->NotifyLeftTrimming(
   2928         object, HeapObject::FromAddress(new_start));
   2929   }
   2930 
   2931   // Technically in new space this write might be omitted (except for
   2932   // debug mode which iterates through the heap), but to play safer
   2933   // we still do it.
   2934   HeapObject* filler =
   2935       CreateFillerObjectAt(old_start, bytes_to_trim, ClearRecordedSlots::kYes);
   2936 
   2937   // Initialize header of the trimmed array. Since left trimming is only
   2938   // performed on pages which are not concurrently swept creating a filler
   2939   // object does not require synchronization.
   2940   RELAXED_WRITE_FIELD(object, bytes_to_trim, map);
   2941   RELAXED_WRITE_FIELD(object, bytes_to_trim + kPointerSize,
   2942                       Smi::FromInt(len - elements_to_trim));
   2943 
   2944   FixedArrayBase* new_object =
   2945       FixedArrayBase::cast(HeapObject::FromAddress(new_start));
   2946 
   2947   // Remove recorded slots for the new map and length offset.
   2948   ClearRecordedSlot(new_object, HeapObject::RawField(new_object, 0));
   2949   ClearRecordedSlot(new_object, HeapObject::RawField(
   2950                                     new_object, FixedArrayBase::kLengthOffset));
   2951 
   2952   // Handle invalidated old-to-old slots.
   2953   if (incremental_marking()->IsCompacting() &&
   2954       MayContainRecordedSlots(new_object)) {
   2955     // If the array was right-trimmed before, then it is registered in
   2956     // the invalidated_slots.
   2957     MemoryChunk::FromHeapObject(new_object)
   2958         ->MoveObjectWithInvalidatedSlots(filler, new_object);
   2959     // We have to clear slots in the free space to avoid stale old-to-old slots.
   2960     // Note we cannot use ClearFreedMemoryMode of CreateFillerObjectAt because
   2961     // we need pointer granularity writes to avoid race with the concurrent
   2962     // marking.
   2963     if (filler->Size() > FreeSpace::kSize) {
   2964       MemsetPointer(HeapObject::RawField(filler, FreeSpace::kSize),
   2965                     ReadOnlyRoots(this).undefined_value(),
   2966                     (filler->Size() - FreeSpace::kSize) / kPointerSize);
   2967     }
   2968   }
   2969   // Notify the heap profiler of change in object layout.
   2970   OnMoveEvent(new_object, object, new_object->Size());
   2971 
   2972 #ifdef ENABLE_SLOW_DCHECKS
   2973   if (FLAG_enable_slow_asserts) {
   2974     // Make sure the stack or other roots (e.g., Handles) don't contain pointers
   2975     // to the original FixedArray (which is now the filler object).
   2976     LeftTrimmerVerifierRootVisitor root_visitor(object);
   2977     IterateRoots(&root_visitor, VISIT_ALL);
   2978   }
   2979 #endif  // ENABLE_SLOW_DCHECKS
   2980 
   2981   return new_object;
   2982 }
   2983 
   2984 void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) {
   2985   const int len = object->length();
   2986   DCHECK_LE(elements_to_trim, len);
   2987   DCHECK_GE(elements_to_trim, 0);
   2988 
   2989   int bytes_to_trim;
   2990   DCHECK(!object->IsFixedTypedArrayBase());
   2991   if (object->IsByteArray()) {
   2992     int new_size = ByteArray::SizeFor(len - elements_to_trim);
   2993     bytes_to_trim = ByteArray::SizeFor(len) - new_size;
   2994     DCHECK_GE(bytes_to_trim, 0);
   2995   } else if (object->IsFixedArray()) {
   2996     CHECK_NE(elements_to_trim, len);
   2997     bytes_to_trim = elements_to_trim * kPointerSize;
   2998   } else {
   2999     DCHECK(object->IsFixedDoubleArray());
   3000     CHECK_NE(elements_to_trim, len);
   3001     bytes_to_trim = elements_to_trim * kDoubleSize;
   3002   }
   3003 
   3004   CreateFillerForArray<FixedArrayBase>(object, elements_to_trim, bytes_to_trim);
   3005 }
   3006 
   3007 void Heap::RightTrimWeakFixedArray(WeakFixedArray* object,
   3008                                    int elements_to_trim) {
   3009   // This function is safe to use only at the end of the mark compact
   3010   // collection: When marking, we record the weak slots, and shrinking
   3011   // invalidates them.
   3012   DCHECK_EQ(gc_state(), MARK_COMPACT);
   3013   CreateFillerForArray<WeakFixedArray>(object, elements_to_trim,
   3014                                        elements_to_trim * kPointerSize);
   3015 }
   3016 
   3017 template <typename T>
   3018 void Heap::CreateFillerForArray(T* object, int elements_to_trim,
   3019                                 int bytes_to_trim) {
   3020   DCHECK(object->IsFixedArrayBase() || object->IsByteArray() ||
   3021          object->IsWeakFixedArray());
   3022 
   3023   // For now this trick is only applied to objects in new and paged space.
   3024   DCHECK(object->map() != ReadOnlyRoots(this).fixed_cow_array_map());
   3025 
   3026   if (bytes_to_trim == 0) {
   3027     DCHECK_EQ(elements_to_trim, 0);
   3028     // No need to create filler and update live bytes counters.
   3029     return;
   3030   }
   3031 
   3032   // Calculate location of new array end.
   3033   int old_size = object->Size();
   3034   Address old_end = object->address() + old_size;
   3035   Address new_end = old_end - bytes_to_trim;
   3036 
   3037   // Register the array as an object with invalidated old-to-old slots. We
   3038   // cannot use NotifyObjectLayoutChange as it would mark the array black,
   3039   // which is not safe for left-trimming because left-trimming re-pushes
   3040   // only grey arrays onto the marking worklist.
   3041   if (incremental_marking()->IsCompacting() &&
   3042       MayContainRecordedSlots(object)) {
   3043     // Ensure that the object survives because the InvalidatedSlotsFilter will
   3044     // compute its size from its map during pointers updating phase.
   3045     incremental_marking()->WhiteToGreyAndPush(object);
   3046     MemoryChunk::FromHeapObject(object)->RegisterObjectWithInvalidatedSlots(
   3047         object, old_size);
   3048   }
   3049 
   3050   // Technically in new space this write might be omitted (except for
   3051   // debug mode which iterates through the heap), but to play safer
   3052   // we still do it.
   3053   // We do not create a filler for objects in large object space.
   3054   // TODO(hpayer): We should shrink the large object page if the size
   3055   // of the object changed significantly.
   3056   if (!lo_space()->Contains(object)) {
   3057     HeapObject* filler =
   3058         CreateFillerObjectAt(new_end, bytes_to_trim, ClearRecordedSlots::kYes);
   3059     DCHECK_NOT_NULL(filler);
   3060     // Clear the mark bits of the black area that belongs now to the filler.
   3061     // This is an optimization. The sweeper will release black fillers anyway.
   3062     if (incremental_marking()->black_allocation() &&
   3063         incremental_marking()->marking_state()->IsBlackOrGrey(filler)) {
   3064       Page* page = Page::FromAddress(new_end);
   3065       incremental_marking()->marking_state()->bitmap(page)->ClearRange(
   3066           page->AddressToMarkbitIndex(new_end),
   3067           page->AddressToMarkbitIndex(new_end + bytes_to_trim));
   3068     }
   3069   }
   3070 
   3071   // Initialize header of the trimmed array. We are storing the new length
   3072   // using release store after creating a filler for the left-over space to
   3073   // avoid races with the sweeper thread.
   3074   object->synchronized_set_length(object->length() - elements_to_trim);
   3075 
   3076   // Notify the heap object allocation tracker of change in object layout. The
   3077   // array may not be moved during GC, and size has to be adjusted nevertheless.
   3078   for (auto& tracker : allocation_trackers_) {
   3079     tracker->UpdateObjectSizeEvent(object->address(), object->Size());
   3080   }
   3081 }
   3082 
   3083 void Heap::MakeHeapIterable() {
   3084   mark_compact_collector()->EnsureSweepingCompleted();
   3085 }
   3086 
   3087 
   3088 static double ComputeMutatorUtilization(double mutator_speed, double gc_speed) {
   3089   const double kMinMutatorUtilization = 0.0;
   3090   const double kConservativeGcSpeedInBytesPerMillisecond = 200000;
   3091   if (mutator_speed == 0) return kMinMutatorUtilization;
   3092   if (gc_speed == 0) gc_speed = kConservativeGcSpeedInBytesPerMillisecond;
   3093   // Derivation:
   3094   // mutator_utilization = mutator_time / (mutator_time + gc_time)
   3095   // mutator_time = 1 / mutator_speed
   3096   // gc_time = 1 / gc_speed
   3097   // mutator_utilization = (1 / mutator_speed) /
   3098   //                       (1 / mutator_speed + 1 / gc_speed)
   3099   // mutator_utilization = gc_speed / (mutator_speed + gc_speed)
   3100   return gc_speed / (mutator_speed + gc_speed);
   3101 }
   3102 
   3103 
   3104 double Heap::YoungGenerationMutatorUtilization() {
   3105   double mutator_speed = static_cast<double>(
   3106       tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond());
   3107   double gc_speed =
   3108       tracer()->ScavengeSpeedInBytesPerMillisecond(kForSurvivedObjects);
   3109   double result = ComputeMutatorUtilization(mutator_speed, gc_speed);
   3110   if (FLAG_trace_mutator_utilization) {
   3111     isolate()->PrintWithTimestamp(
   3112         "Young generation mutator utilization = %.3f ("
   3113         "mutator_speed=%.f, gc_speed=%.f)\n",
   3114         result, mutator_speed, gc_speed);
   3115   }
   3116   return result;
   3117 }
   3118 
   3119 
   3120 double Heap::OldGenerationMutatorUtilization() {
   3121   double mutator_speed = static_cast<double>(
   3122       tracer()->OldGenerationAllocationThroughputInBytesPerMillisecond());
   3123   double gc_speed = static_cast<double>(
   3124       tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond());
   3125   double result = ComputeMutatorUtilization(mutator_speed, gc_speed);
   3126   if (FLAG_trace_mutator_utilization) {
   3127     isolate()->PrintWithTimestamp(
   3128         "Old generation mutator utilization = %.3f ("
   3129         "mutator_speed=%.f, gc_speed=%.f)\n",
   3130         result, mutator_speed, gc_speed);
   3131   }
   3132   return result;
   3133 }
   3134 
   3135 
   3136 bool Heap::HasLowYoungGenerationAllocationRate() {
   3137   const double high_mutator_utilization = 0.993;
   3138   return YoungGenerationMutatorUtilization() > high_mutator_utilization;
   3139 }
   3140 
   3141 
   3142 bool Heap::HasLowOldGenerationAllocationRate() {
   3143   const double high_mutator_utilization = 0.993;
   3144   return OldGenerationMutatorUtilization() > high_mutator_utilization;
   3145 }
   3146 
   3147 
   3148 bool Heap::HasLowAllocationRate() {
   3149   return HasLowYoungGenerationAllocationRate() &&
   3150          HasLowOldGenerationAllocationRate();
   3151 }
   3152 
   3153 bool Heap::IsIneffectiveMarkCompact(size_t old_generation_size,
   3154                                     double mutator_utilization) {
   3155   const double kHighHeapPercentage = 0.8;
   3156   const double kLowMutatorUtilization = 0.4;
   3157   return old_generation_size >=
   3158              kHighHeapPercentage * max_old_generation_size_ &&
   3159          mutator_utilization < kLowMutatorUtilization;
   3160 }
   3161 
   3162 void Heap::CheckIneffectiveMarkCompact(size_t old_generation_size,
   3163                                        double mutator_utilization) {
   3164   const int kMaxConsecutiveIneffectiveMarkCompacts = 4;
   3165   if (!FLAG_detect_ineffective_gcs_near_heap_limit) return;
   3166   if (!IsIneffectiveMarkCompact(old_generation_size, mutator_utilization)) {
   3167     consecutive_ineffective_mark_compacts_ = 0;
   3168     return;
   3169   }
   3170   ++consecutive_ineffective_mark_compacts_;
   3171   if (consecutive_ineffective_mark_compacts_ ==
   3172       kMaxConsecutiveIneffectiveMarkCompacts) {
   3173     if (InvokeNearHeapLimitCallback()) {
   3174       // The callback increased the heap limit.
   3175       consecutive_ineffective_mark_compacts_ = 0;
   3176       return;
   3177     }
   3178     FatalProcessOutOfMemory("Ineffective mark-compacts near heap limit");
   3179   }
   3180 }
   3181 
   3182 bool Heap::HasHighFragmentation() {
   3183   size_t used = OldGenerationSizeOfObjects();
   3184   size_t committed = CommittedOldGenerationMemory();
   3185   return HasHighFragmentation(used, committed);
   3186 }
   3187 
   3188 bool Heap::HasHighFragmentation(size_t used, size_t committed) {
   3189   const size_t kSlack = 16 * MB;
   3190   // Fragmentation is high if committed > 2 * used + kSlack.
   3191   // Rewrite the exression to avoid overflow.
   3192   DCHECK_GE(committed, used);
   3193   return committed - used > used + kSlack;
   3194 }
   3195 
   3196 bool Heap::ShouldOptimizeForMemoryUsage() {
   3197   const size_t kOldGenerationSlack = max_old_generation_size_ / 8;
   3198   return FLAG_optimize_for_size || isolate()->IsIsolateInBackground() ||
   3199          isolate()->IsMemorySavingsModeActive() || HighMemoryPressure() ||
   3200          !CanExpandOldGeneration(kOldGenerationSlack);
   3201 }
   3202 
   3203 void Heap::ActivateMemoryReducerIfNeeded() {
   3204   // Activate memory reducer when switching to background if
   3205   // - there was no mark compact since the start.
   3206   // - the committed memory can be potentially reduced.
   3207   // 2 pages for the old, code, and map space + 1 page for new space.
   3208   const int kMinCommittedMemory = 7 * Page::kPageSize;
   3209   if (ms_count_ == 0 && CommittedMemory() > kMinCommittedMemory &&
   3210       isolate()->IsIsolateInBackground()) {
   3211     MemoryReducer::Event event;
   3212     event.type = MemoryReducer::kPossibleGarbage;
   3213     event.time_ms = MonotonicallyIncreasingTimeInMs();
   3214     memory_reducer_->NotifyPossibleGarbage(event);
   3215   }
   3216 }
   3217 
   3218 void Heap::ReduceNewSpaceSize() {
   3219   // TODO(ulan): Unify this constant with the similar constant in
   3220   // GCIdleTimeHandler once the change is merged to 4.5.
   3221   static const size_t kLowAllocationThroughput = 1000;
   3222   const double allocation_throughput =
   3223       tracer()->CurrentAllocationThroughputInBytesPerMillisecond();
   3224 
   3225   if (FLAG_predictable) return;
   3226 
   3227   if (ShouldReduceMemory() ||
   3228       ((allocation_throughput != 0) &&
   3229        (allocation_throughput < kLowAllocationThroughput))) {
   3230     new_space_->Shrink();
   3231     UncommitFromSpace();
   3232   }
   3233 }
   3234 
   3235 void Heap::FinalizeIncrementalMarkingIfComplete(
   3236     GarbageCollectionReason gc_reason) {
   3237   if (incremental_marking()->IsMarking() &&
   3238       (incremental_marking()->IsReadyToOverApproximateWeakClosure() ||
   3239        (!incremental_marking()->finalize_marking_completed() &&
   3240         mark_compact_collector()->marking_worklist()->IsEmpty() &&
   3241         local_embedder_heap_tracer()->ShouldFinalizeIncrementalMarking()))) {
   3242     FinalizeIncrementalMarkingIncrementally(gc_reason);
   3243   } else if (incremental_marking()->IsComplete() ||
   3244              (mark_compact_collector()->marking_worklist()->IsEmpty() &&
   3245               local_embedder_heap_tracer()
   3246                   ->ShouldFinalizeIncrementalMarking())) {
   3247     CollectAllGarbage(current_gc_flags_, gc_reason, current_gc_callback_flags_);
   3248   }
   3249 }
   3250 
   3251 void Heap::FinalizeIncrementalMarkingAtomically(
   3252     GarbageCollectionReason gc_reason) {
   3253   DCHECK(!incremental_marking()->IsStopped());
   3254   CollectAllGarbage(current_gc_flags_, gc_reason, current_gc_callback_flags_);
   3255 }
   3256 
   3257 void Heap::FinalizeIncrementalMarkingIncrementally(
   3258     GarbageCollectionReason gc_reason) {
   3259   if (FLAG_trace_incremental_marking) {
   3260     isolate()->PrintWithTimestamp(
   3261         "[IncrementalMarking] (%s).\n",
   3262         Heap::GarbageCollectionReasonToString(gc_reason));
   3263   }
   3264 
   3265   HistogramTimerScope incremental_marking_scope(
   3266       isolate()->counters()->gc_incremental_marking_finalize());
   3267   TRACE_EVENT0("v8", "V8.GCIncrementalMarkingFinalize");
   3268   TRACE_GC(tracer(), GCTracer::Scope::MC_INCREMENTAL_FINALIZE);
   3269 
   3270   {
   3271     GCCallbacksScope scope(this);
   3272     if (scope.CheckReenter()) {
   3273       AllowHeapAllocation allow_allocation;
   3274       TRACE_GC(tracer(), GCTracer::Scope::MC_INCREMENTAL_EXTERNAL_PROLOGUE);
   3275       VMState<EXTERNAL> state(isolate_);
   3276       HandleScope handle_scope(isolate_);
   3277       CallGCPrologueCallbacks(kGCTypeIncrementalMarking, kNoGCCallbackFlags);
   3278     }
   3279   }
   3280   incremental_marking()->FinalizeIncrementally();
   3281   {
   3282     GCCallbacksScope scope(this);
   3283     if (scope.CheckReenter()) {
   3284       AllowHeapAllocation allow_allocation;
   3285       TRACE_GC(tracer(), GCTracer::Scope::MC_INCREMENTAL_EXTERNAL_EPILOGUE);
   3286       VMState<EXTERNAL> state(isolate_);
   3287       HandleScope handle_scope(isolate_);
   3288       CallGCEpilogueCallbacks(kGCTypeIncrementalMarking, kNoGCCallbackFlags);
   3289     }
   3290   }
   3291 }
   3292 
   3293 void Heap::RegisterDeserializedObjectsForBlackAllocation(
   3294     Reservation* reservations, const std::vector<HeapObject*>& large_objects,
   3295     const std::vector<Address>& maps) {
   3296   // TODO(ulan): pause black allocation during deserialization to avoid
   3297   // iterating all these objects in one go.
   3298 
   3299   if (!incremental_marking()->black_allocation()) return;
   3300 
   3301   // Iterate black objects in old space, code space, map space, and large
   3302   // object space for side effects.
   3303   IncrementalMarking::MarkingState* marking_state =
   3304       incremental_marking()->marking_state();
   3305   for (int i = OLD_SPACE; i < Serializer<>::kNumberOfSpaces; i++) {
   3306     const Heap::Reservation& res = reservations[i];
   3307     for (auto& chunk : res) {
   3308       Address addr = chunk.start;
   3309       while (addr < chunk.end) {
   3310         HeapObject* obj = HeapObject::FromAddress(addr);
   3311         // Objects can have any color because incremental marking can
   3312         // start in the middle of Heap::ReserveSpace().
   3313         if (marking_state->IsBlack(obj)) {
   3314           incremental_marking()->ProcessBlackAllocatedObject(obj);
   3315         }
   3316         addr += obj->Size();
   3317       }
   3318     }
   3319   }
   3320   // We potentially deserialized wrappers which require registering with the
   3321   // embedder as the marker will not find them.
   3322   local_embedder_heap_tracer()->RegisterWrappersWithRemoteTracer();
   3323 
   3324   // Large object space doesn't use reservations, so it needs custom handling.
   3325   for (HeapObject* object : large_objects) {
   3326     incremental_marking()->ProcessBlackAllocatedObject(object);
   3327   }
   3328 
   3329   // Map space doesn't use reservations, so it needs custom handling.
   3330   for (Address addr : maps) {
   3331     incremental_marking()->ProcessBlackAllocatedObject(
   3332         HeapObject::FromAddress(addr));
   3333   }
   3334 }
   3335 
   3336 void Heap::NotifyObjectLayoutChange(HeapObject* object, int size,
   3337                                     const DisallowHeapAllocation&) {
   3338   if (incremental_marking()->IsMarking()) {
   3339     incremental_marking()->MarkBlackAndPush(object);
   3340     if (incremental_marking()->IsCompacting() &&
   3341         MayContainRecordedSlots(object)) {
   3342       MemoryChunk::FromHeapObject(object)->RegisterObjectWithInvalidatedSlots(
   3343           object, size);
   3344     }
   3345   }
   3346 #ifdef VERIFY_HEAP
   3347   if (FLAG_verify_heap) {
   3348     DCHECK_NULL(pending_layout_change_object_);
   3349     pending_layout_change_object_ = object;
   3350   }
   3351 #endif
   3352 }
   3353 
   3354 #ifdef VERIFY_HEAP
   3355 // Helper class for collecting slot addresses.
   3356 class SlotCollectingVisitor final : public ObjectVisitor {
   3357  public:
   3358   void VisitPointers(HeapObject* host, Object** start, Object** end) override {
   3359     VisitPointers(host, reinterpret_cast<MaybeObject**>(start),
   3360                   reinterpret_cast<MaybeObject**>(end));
   3361   }
   3362   void VisitPointers(HeapObject* host, MaybeObject** start,
   3363                      MaybeObject** end) final {
   3364     for (MaybeObject** p = start; p < end; p++) {
   3365       slots_.push_back(p);
   3366     }
   3367   }
   3368 
   3369   int number_of_slots() { return static_cast<int>(slots_.size()); }
   3370 
   3371   MaybeObject** slot(int i) { return slots_[i]; }
   3372 
   3373  private:
   3374   std::vector<MaybeObject**> slots_;
   3375 };
   3376 
   3377 void Heap::VerifyObjectLayoutChange(HeapObject* object, Map* new_map) {
   3378   if (!FLAG_verify_heap) return;
   3379 
   3380   // Check that Heap::NotifyObjectLayout was called for object transitions
   3381   // that are not safe for concurrent marking.
   3382   // If you see this check triggering for a freshly allocated object,
   3383   // use object->set_map_after_allocation() to initialize its map.
   3384   if (pending_layout_change_object_ == nullptr) {
   3385     if (object->IsJSObject()) {
   3386       DCHECK(!object->map()->TransitionRequiresSynchronizationWithGC(new_map));
   3387     } else {
   3388       // Check that the set of slots before and after the transition match.
   3389       SlotCollectingVisitor old_visitor;
   3390       object->IterateFast(&old_visitor);
   3391       MapWord old_map_word = object->map_word();
   3392       // Temporarily set the new map to iterate new slots.
   3393       object->set_map_word(MapWord::FromMap(new_map));
   3394       SlotCollectingVisitor new_visitor;
   3395       object->IterateFast(&new_visitor);
   3396       // Restore the old map.
   3397       object->set_map_word(old_map_word);
   3398       DCHECK_EQ(new_visitor.number_of_slots(), old_visitor.number_of_slots());
   3399       for (int i = 0; i < new_visitor.number_of_slots(); i++) {
   3400         DCHECK_EQ(new_visitor.slot(i), old_visitor.slot(i));
   3401       }
   3402     }
   3403   } else {
   3404     DCHECK_EQ(pending_layout_change_object_, object);
   3405     pending_layout_change_object_ = nullptr;
   3406   }
   3407 }
   3408 #endif
   3409 
   3410 GCIdleTimeHeapState Heap::ComputeHeapState() {
   3411   GCIdleTimeHeapState heap_state;
   3412   heap_state.contexts_disposed = contexts_disposed_;
   3413   heap_state.contexts_disposal_rate =
   3414       tracer()->ContextDisposalRateInMilliseconds();
   3415   heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects());
   3416   heap_state.incremental_marking_stopped = incremental_marking()->IsStopped();
   3417   return heap_state;
   3418 }
   3419 
   3420 
   3421 bool Heap::PerformIdleTimeAction(GCIdleTimeAction action,
   3422                                  GCIdleTimeHeapState heap_state,
   3423                                  double deadline_in_ms) {
   3424   bool result = false;
   3425   switch (action.type) {
   3426     case DONE:
   3427       result = true;
   3428       break;
   3429     case DO_INCREMENTAL_STEP: {
   3430       const double remaining_idle_time_in_ms =
   3431           incremental_marking()->AdvanceIncrementalMarking(
   3432               deadline_in_ms, IncrementalMarking::NO_GC_VIA_STACK_GUARD,
   3433               StepOrigin::kTask);
   3434       if (remaining_idle_time_in_ms > 0.0) {
   3435         FinalizeIncrementalMarkingIfComplete(
   3436             GarbageCollectionReason::kFinalizeMarkingViaTask);
   3437       }
   3438       result = incremental_marking()->IsStopped();
   3439       break;
   3440     }
   3441     case DO_FULL_GC: {
   3442       DCHECK_LT(0, contexts_disposed_);
   3443       HistogramTimerScope scope(isolate_->counters()->gc_context());
   3444       TRACE_EVENT0("v8", "V8.GCContext");
   3445       CollectAllGarbage(kNoGCFlags, GarbageCollectionReason::kContextDisposal);
   3446       break;
   3447     }
   3448     case DO_NOTHING:
   3449       break;
   3450   }
   3451 
   3452   return result;
   3453 }
   3454 
   3455 void Heap::IdleNotificationEpilogue(GCIdleTimeAction action,
   3456                                     GCIdleTimeHeapState heap_state,
   3457                                     double start_ms, double deadline_in_ms) {
   3458   double idle_time_in_ms = deadline_in_ms - start_ms;
   3459   double current_time = MonotonicallyIncreasingTimeInMs();
   3460   last_idle_notification_time_ = current_time;
   3461   double deadline_difference = deadline_in_ms - current_time;
   3462 
   3463   contexts_disposed_ = 0;
   3464 
   3465   if ((FLAG_trace_idle_notification && action.type > DO_NOTHING) ||
   3466       FLAG_trace_idle_notification_verbose) {
   3467     isolate_->PrintWithTimestamp(
   3468         "Idle notification: requested idle time %.2f ms, used idle time %.2f "
   3469         "ms, deadline usage %.2f ms [",
   3470         idle_time_in_ms, idle_time_in_ms - deadline_difference,
   3471         deadline_difference);
   3472     action.Print();
   3473     PrintF("]");
   3474     if (FLAG_trace_idle_notification_verbose) {
   3475       PrintF("[");
   3476       heap_state.Print();
   3477       PrintF("]");
   3478     }
   3479     PrintF("\n");
   3480   }
   3481 }
   3482 
   3483 
   3484 double Heap::MonotonicallyIncreasingTimeInMs() {
   3485   return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() *
   3486          static_cast<double>(base::Time::kMillisecondsPerSecond);
   3487 }
   3488 
   3489 
   3490 bool Heap::IdleNotification(int idle_time_in_ms) {
   3491   return IdleNotification(
   3492       V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() +
   3493       (static_cast<double>(idle_time_in_ms) /
   3494        static_cast<double>(base::Time::kMillisecondsPerSecond)));
   3495 }
   3496 
   3497 
   3498 bool Heap::IdleNotification(double deadline_in_seconds) {
   3499   CHECK(HasBeenSetUp());
   3500   double deadline_in_ms =
   3501       deadline_in_seconds *
   3502       static_cast<double>(base::Time::kMillisecondsPerSecond);
   3503   HistogramTimerScope idle_notification_scope(
   3504       isolate_->counters()->gc_idle_notification());
   3505   TRACE_EVENT0("v8", "V8.GCIdleNotification");
   3506   double start_ms = MonotonicallyIncreasingTimeInMs();
   3507   double idle_time_in_ms = deadline_in_ms - start_ms;
   3508 
   3509   tracer()->SampleAllocation(start_ms, NewSpaceAllocationCounter(),
   3510                              OldGenerationAllocationCounter());
   3511 
   3512   GCIdleTimeHeapState heap_state = ComputeHeapState();
   3513 
   3514   GCIdleTimeAction action =
   3515       gc_idle_time_handler_->Compute(idle_time_in_ms, heap_state);
   3516 
   3517   bool result = PerformIdleTimeAction(action, heap_state, deadline_in_ms);
   3518 
   3519   IdleNotificationEpilogue(action, heap_state, start_ms, deadline_in_ms);
   3520   return result;
   3521 }
   3522 
   3523 
   3524 bool Heap::RecentIdleNotificationHappened() {
   3525   return (last_idle_notification_time_ +
   3526           GCIdleTimeHandler::kMaxScheduledIdleTime) >
   3527          MonotonicallyIncreasingTimeInMs();
   3528 }
   3529 
   3530 class MemoryPressureInterruptTask : public CancelableTask {
   3531  public:
   3532   explicit MemoryPressureInterruptTask(Heap* heap)
   3533       : CancelableTask(heap->isolate()), heap_(heap) {}
   3534 
   3535   virtual ~MemoryPressureInterruptTask() {}
   3536 
   3537  private:
   3538   // v8::internal::CancelableTask overrides.
   3539   void RunInternal() override { heap_->CheckMemoryPressure(); }
   3540 
   3541   Heap* heap_;
   3542   DISALLOW_COPY_AND_ASSIGN(MemoryPressureInterruptTask);
   3543 };
   3544 
   3545 void Heap::CheckMemoryPressure() {
   3546   if (HighMemoryPressure()) {
   3547     // The optimizing compiler may be unnecessarily holding on to memory.
   3548     isolate()->AbortConcurrentOptimization(BlockingBehavior::kDontBlock);
   3549   }
   3550   MemoryPressureLevel memory_pressure_level = memory_pressure_level_;
   3551   // Reset the memory pressure level to avoid recursive GCs triggered by
   3552   // CheckMemoryPressure from AdjustAmountOfExternalMemory called by
   3553   // the finalizers.
   3554   memory_pressure_level_ = MemoryPressureLevel::kNone;
   3555   if (memory_pressure_level == MemoryPressureLevel::kCritical) {
   3556     CollectGarbageOnMemoryPressure();
   3557   } else if (memory_pressure_level == MemoryPressureLevel::kModerate) {
   3558     if (FLAG_incremental_marking && incremental_marking()->IsStopped()) {
   3559       StartIncrementalMarking(kReduceMemoryFootprintMask,
   3560                               GarbageCollectionReason::kMemoryPressure);
   3561     }
   3562   }
   3563   if (memory_reducer_) {
   3564     MemoryReducer::Event event;
   3565     event.type = MemoryReducer::kPossibleGarbage;
   3566     event.time_ms = MonotonicallyIncreasingTimeInMs();
   3567     memory_reducer_->NotifyPossibleGarbage(event);
   3568   }
   3569 }
   3570 
   3571 void Heap::CollectGarbageOnMemoryPressure() {
   3572   const int kGarbageThresholdInBytes = 8 * MB;
   3573   const double kGarbageThresholdAsFractionOfTotalMemory = 0.1;
   3574   // This constant is the maximum response time in RAIL performance model.
   3575   const double kMaxMemoryPressurePauseMs = 100;
   3576 
   3577   double start = MonotonicallyIncreasingTimeInMs();
   3578   CollectAllGarbage(kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask,
   3579                     GarbageCollectionReason::kMemoryPressure,
   3580                     kGCCallbackFlagCollectAllAvailableGarbage);
   3581   double end = MonotonicallyIncreasingTimeInMs();
   3582 
   3583   // Estimate how much memory we can free.
   3584   int64_t potential_garbage =
   3585       (CommittedMemory() - SizeOfObjects()) + external_memory_;
   3586   // If we can potentially free large amount of memory, then start GC right
   3587   // away instead of waiting for memory reducer.
   3588   if (potential_garbage >= kGarbageThresholdInBytes &&
   3589       potential_garbage >=
   3590           CommittedMemory() * kGarbageThresholdAsFractionOfTotalMemory) {
   3591     // If we spent less than half of the time budget, then perform full GC
   3592     // Otherwise, start incremental marking.
   3593     if (end - start < kMaxMemoryPressurePauseMs / 2) {
   3594       CollectAllGarbage(
   3595           kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask,
   3596           GarbageCollectionReason::kMemoryPressure,
   3597           kGCCallbackFlagCollectAllAvailableGarbage);
   3598     } else {
   3599       if (FLAG_incremental_marking && incremental_marking()->IsStopped()) {
   3600         StartIncrementalMarking(kReduceMemoryFootprintMask,
   3601                                 GarbageCollectionReason::kMemoryPressure);
   3602       }
   3603     }
   3604   }
   3605 }
   3606 
   3607 void Heap::MemoryPressureNotification(MemoryPressureLevel level,
   3608                                       bool is_isolate_locked) {
   3609   MemoryPressureLevel previous = memory_pressure_level_;
   3610   memory_pressure_level_ = level;
   3611   if ((previous != MemoryPressureLevel::kCritical &&
   3612        level == MemoryPressureLevel::kCritical) ||
   3613       (previous == MemoryPressureLevel::kNone &&
   3614        level == MemoryPressureLevel::kModerate)) {
   3615     if (is_isolate_locked) {
   3616       CheckMemoryPressure();
   3617     } else {
   3618       ExecutionAccess access(isolate());
   3619       isolate()->stack_guard()->RequestGC();
   3620       V8::GetCurrentPlatform()->CallOnForegroundThread(
   3621           reinterpret_cast<v8::Isolate*>(isolate()),
   3622           new MemoryPressureInterruptTask(this));
   3623     }
   3624   }
   3625 }
   3626 
   3627 void Heap::AddNearHeapLimitCallback(v8::NearHeapLimitCallback callback,
   3628                                     void* data) {
   3629   const size_t kMaxCallbacks = 100;
   3630   CHECK_LT(near_heap_limit_callbacks_.size(), kMaxCallbacks);
   3631   for (auto callback_data : near_heap_limit_callbacks_) {
   3632     CHECK_NE(callback_data.first, callback);
   3633   }
   3634   near_heap_limit_callbacks_.push_back(std::make_pair(callback, data));
   3635 }
   3636 
   3637 void Heap::RemoveNearHeapLimitCallback(v8::NearHeapLimitCallback callback,
   3638                                        size_t heap_limit) {
   3639   for (size_t i = 0; i < near_heap_limit_callbacks_.size(); i++) {
   3640     if (near_heap_limit_callbacks_[i].first == callback) {
   3641       near_heap_limit_callbacks_.erase(near_heap_limit_callbacks_.begin() + i);
   3642       if (heap_limit) {
   3643         RestoreHeapLimit(heap_limit);
   3644       }
   3645       return;
   3646     }
   3647   }
   3648   UNREACHABLE();
   3649 }
   3650 
   3651 bool Heap::InvokeNearHeapLimitCallback() {
   3652   if (near_heap_limit_callbacks_.size() > 0) {
   3653     HandleScope scope(isolate());
   3654     v8::NearHeapLimitCallback callback =
   3655         near_heap_limit_callbacks_.back().first;
   3656     void* data = near_heap_limit_callbacks_.back().second;
   3657     size_t heap_limit = callback(data, max_old_generation_size_,
   3658                                  initial_max_old_generation_size_);
   3659     if (heap_limit > max_old_generation_size_) {
   3660       max_old_generation_size_ = heap_limit;
   3661       return true;
   3662     }
   3663   }
   3664   return false;
   3665 }
   3666 
   3667 void Heap::CollectCodeStatistics() {
   3668   TRACE_EVENT0("v8", "Heap::CollectCodeStatistics");
   3669   CodeStatistics::ResetCodeAndMetadataStatistics(isolate());
   3670   // We do not look for code in new space, or map space.  If code
   3671   // somehow ends up in those spaces, we would miss it here.
   3672   CodeStatistics::CollectCodeStatistics(code_space_, isolate());
   3673   CodeStatistics::CollectCodeStatistics(old_space_, isolate());
   3674   CodeStatistics::CollectCodeStatistics(lo_space_, isolate());
   3675 }
   3676 
   3677 #ifdef DEBUG
   3678 
   3679 void Heap::Print() {
   3680   if (!HasBeenSetUp()) return;
   3681   isolate()->PrintStack(stdout);
   3682 
   3683   for (SpaceIterator it(this); it.has_next();) {
   3684     it.next()->Print();
   3685   }
   3686 }
   3687 
   3688 
   3689 void Heap::ReportCodeStatistics(const char* title) {
   3690   PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title);
   3691   CollectCodeStatistics();
   3692   CodeStatistics::ReportCodeStatistics(isolate());
   3693 }
   3694 
   3695 #endif  // DEBUG
   3696 
   3697 const char* Heap::GarbageCollectionReasonToString(
   3698     GarbageCollectionReason gc_reason) {
   3699   switch (gc_reason) {
   3700     case GarbageCollectionReason::kAllocationFailure:
   3701       return "allocation failure";
   3702     case GarbageCollectionReason::kAllocationLimit:
   3703       return "allocation limit";
   3704     case GarbageCollectionReason::kContextDisposal:
   3705       return "context disposal";
   3706     case GarbageCollectionReason::kCountersExtension:
   3707       return "counters extension";
   3708     case GarbageCollectionReason::kDebugger:
   3709       return "debugger";
   3710     case GarbageCollectionReason::kDeserializer:
   3711       return "deserialize";
   3712     case GarbageCollectionReason::kExternalMemoryPressure:
   3713       return "external memory pressure";
   3714     case GarbageCollectionReason::kFinalizeMarkingViaStackGuard:
   3715       return "finalize incremental marking via stack guard";
   3716     case GarbageCollectionReason::kFinalizeMarkingViaTask:
   3717       return "finalize incremental marking via task";
   3718     case GarbageCollectionReason::kFullHashtable:
   3719       return "full hash-table";
   3720     case GarbageCollectionReason::kHeapProfiler:
   3721       return "heap profiler";
   3722     case GarbageCollectionReason::kIdleTask:
   3723       return "idle task";
   3724     case GarbageCollectionReason::kLastResort:
   3725       return "last resort";
   3726     case GarbageCollectionReason::kLowMemoryNotification:
   3727       return "low memory notification";
   3728     case GarbageCollectionReason::kMakeHeapIterable:
   3729       return "make heap iterable";
   3730     case GarbageCollectionReason::kMemoryPressure:
   3731       return "memory pressure";
   3732     case GarbageCollectionReason::kMemoryReducer:
   3733       return "memory reducer";
   3734     case GarbageCollectionReason::kRuntime:
   3735       return "runtime";
   3736     case GarbageCollectionReason::kSamplingProfiler:
   3737       return "sampling profiler";
   3738     case GarbageCollectionReason::kSnapshotCreator:
   3739       return "snapshot creator";
   3740     case GarbageCollectionReason::kTesting:
   3741       return "testing";
   3742     case GarbageCollectionReason::kExternalFinalize:
   3743       return "external finalize";
   3744     case GarbageCollectionReason::kUnknown:
   3745       return "unknown";
   3746   }
   3747   UNREACHABLE();
   3748 }
   3749 
   3750 bool Heap::Contains(HeapObject* value) {
   3751   if (memory_allocator()->IsOutsideAllocatedSpace(value->address())) {
   3752     return false;
   3753   }
   3754   return HasBeenSetUp() &&
   3755          (new_space_->ToSpaceContains(value) || old_space_->Contains(value) ||
   3756           code_space_->Contains(value) || map_space_->Contains(value) ||
   3757           lo_space_->Contains(value) || read_only_space_->Contains(value));
   3758 }
   3759 
   3760 bool Heap::ContainsSlow(Address addr) {
   3761   if (memory_allocator()->IsOutsideAllocatedSpace(addr)) {
   3762     return false;
   3763   }
   3764   return HasBeenSetUp() &&
   3765          (new_space_->ToSpaceContainsSlow(addr) ||
   3766           old_space_->ContainsSlow(addr) || code_space_->ContainsSlow(addr) ||
   3767           map_space_->ContainsSlow(addr) || lo_space_->ContainsSlow(addr) ||
   3768           read_only_space_->Contains(addr));
   3769 }
   3770 
   3771 bool Heap::InSpace(HeapObject* value, AllocationSpace space) {
   3772   if (memory_allocator()->IsOutsideAllocatedSpace(value->address())) {
   3773     return false;
   3774   }
   3775   if (!HasBeenSetUp()) return false;
   3776 
   3777   switch (space) {
   3778     case NEW_SPACE:
   3779       return new_space_->ToSpaceContains(value);
   3780     case OLD_SPACE:
   3781       return old_space_->Contains(value);
   3782     case CODE_SPACE:
   3783       return code_space_->Contains(value);
   3784     case MAP_SPACE:
   3785       return map_space_->Contains(value);
   3786     case LO_SPACE:
   3787       return lo_space_->Contains(value);
   3788     case NEW_LO_SPACE:
   3789       return new_lo_space_->Contains(value);
   3790     case RO_SPACE:
   3791       return read_only_space_->Contains(value);
   3792   }
   3793   UNREACHABLE();
   3794 }
   3795 
   3796 bool Heap::InSpaceSlow(Address addr, AllocationSpace space) {
   3797   if (memory_allocator()->IsOutsideAllocatedSpace(addr)) {
   3798     return false;
   3799   }
   3800   if (!HasBeenSetUp()) return false;
   3801 
   3802   switch (space) {
   3803     case NEW_SPACE:
   3804       return new_space_->ToSpaceContainsSlow(addr);
   3805     case OLD_SPACE:
   3806       return old_space_->ContainsSlow(addr);
   3807     case CODE_SPACE:
   3808       return code_space_->ContainsSlow(addr);
   3809     case MAP_SPACE:
   3810       return map_space_->ContainsSlow(addr);
   3811     case LO_SPACE:
   3812       return lo_space_->ContainsSlow(addr);
   3813     case NEW_LO_SPACE:
   3814       return new_lo_space_->ContainsSlow(addr);
   3815     case RO_SPACE:
   3816       return read_only_space_->ContainsSlow(addr);
   3817   }
   3818   UNREACHABLE();
   3819 }
   3820 
   3821 bool Heap::IsValidAllocationSpace(AllocationSpace space) {
   3822   switch (space) {
   3823     case NEW_SPACE:
   3824     case OLD_SPACE:
   3825     case CODE_SPACE:
   3826     case MAP_SPACE:
   3827     case LO_SPACE:
   3828     case NEW_LO_SPACE:
   3829     case RO_SPACE:
   3830       return true;
   3831     default:
   3832       return false;
   3833   }
   3834 }
   3835 
   3836 
   3837 bool Heap::RootIsImmortalImmovable(int root_index) {
   3838   switch (root_index) {
   3839 #define IMMORTAL_IMMOVABLE_ROOT(name) case Heap::k##name##RootIndex:
   3840     IMMORTAL_IMMOVABLE_ROOT_LIST(IMMORTAL_IMMOVABLE_ROOT)
   3841 #undef IMMORTAL_IMMOVABLE_ROOT
   3842 #define INTERNALIZED_STRING(name, value) case Heap::k##name##RootIndex:
   3843     INTERNALIZED_STRING_LIST(INTERNALIZED_STRING)
   3844 #undef INTERNALIZED_STRING
   3845 #define STRING_TYPE(NAME, size, name, Name) case Heap::k##Name##MapRootIndex:
   3846     STRING_TYPE_LIST(STRING_TYPE)
   3847 #undef STRING_TYPE
   3848     return true;
   3849     default:
   3850       return false;
   3851   }
   3852 }
   3853 
   3854 #ifdef VERIFY_HEAP
   3855 class VerifyReadOnlyPointersVisitor : public VerifyPointersVisitor {
   3856  public:
   3857   explicit VerifyReadOnlyPointersVisitor(Heap* heap)
   3858       : VerifyPointersVisitor(heap) {}
   3859 
   3860  protected:
   3861   void VerifyPointers(HeapObject* host, MaybeObject** start,
   3862                       MaybeObject** end) override {
   3863     if (host != nullptr) {
   3864       CHECK(heap_->InReadOnlySpace(host->map()));
   3865     }
   3866     VerifyPointersVisitor::VerifyPointers(host, start, end);
   3867 
   3868     for (MaybeObject** current = start; current < end; current++) {
   3869       HeapObject* object;
   3870       if ((*current)->ToStrongOrWeakHeapObject(&object)) {
   3871         CHECK(heap_->InReadOnlySpace(object));
   3872       }
   3873     }
   3874   }
   3875 };
   3876 
   3877 void Heap::Verify() {
   3878   CHECK(HasBeenSetUp());
   3879   HandleScope scope(isolate());
   3880 
   3881   // We have to wait here for the sweeper threads to have an iterable heap.
   3882   mark_compact_collector()->EnsureSweepingCompleted();
   3883 
   3884   VerifyPointersVisitor visitor(this);
   3885   IterateRoots(&visitor, VISIT_ONLY_STRONG);
   3886 
   3887   VerifySmisVisitor smis_visitor;
   3888   IterateSmiRoots(&smis_visitor);
   3889 
   3890   new_space_->Verify(isolate());
   3891 
   3892   old_space_->Verify(isolate(), &visitor);
   3893   map_space_->Verify(isolate(), &visitor);
   3894 
   3895   VerifyPointersVisitor no_dirty_regions_visitor(this);
   3896   code_space_->Verify(isolate(), &no_dirty_regions_visitor);
   3897 
   3898   lo_space_->Verify(isolate());
   3899 
   3900   VerifyReadOnlyPointersVisitor read_only_visitor(this);
   3901   read_only_space_->Verify(isolate(), &read_only_visitor);
   3902 }
   3903 
   3904 class SlotVerifyingVisitor : public ObjectVisitor {
   3905  public:
   3906   SlotVerifyingVisitor(std::set<Address>* untyped,
   3907                        std::set<std::pair<SlotType, Address> >* typed)
   3908       : untyped_(untyped), typed_(typed) {}
   3909 
   3910   virtual bool ShouldHaveBeenRecorded(HeapObject* host,
   3911                                       MaybeObject* target) = 0;
   3912 
   3913   void VisitPointers(HeapObject* host, Object** start, Object** end) override {
   3914 #ifdef DEBUG
   3915     for (Object** slot = start; slot < end; slot++) {
   3916       DCHECK(!HasWeakHeapObjectTag(*slot));
   3917     }
   3918 #endif  // DEBUG
   3919     VisitPointers(host, reinterpret_cast<MaybeObject**>(start),
   3920                   reinterpret_cast<MaybeObject**>(end));
   3921   }
   3922 
   3923   void VisitPointers(HeapObject* host, MaybeObject** start,
   3924                      MaybeObject** end) final {
   3925     for (MaybeObject** slot = start; slot < end; slot++) {
   3926       if (ShouldHaveBeenRecorded(host, *slot)) {
   3927         CHECK_GT(untyped_->count(reinterpret_cast<Address>(slot)), 0);
   3928       }
   3929     }
   3930   }
   3931 
   3932   void VisitCodeTarget(Code* host, RelocInfo* rinfo) override {
   3933     Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
   3934     if (ShouldHaveBeenRecorded(host, MaybeObject::FromObject(target))) {
   3935       CHECK(
   3936           InTypedSet(CODE_TARGET_SLOT, rinfo->pc()) ||
   3937           (rinfo->IsInConstantPool() &&
   3938            InTypedSet(CODE_ENTRY_SLOT, rinfo->constant_pool_entry_address())));
   3939     }
   3940   }
   3941 
   3942   void VisitEmbeddedPointer(Code* host, RelocInfo* rinfo) override {
   3943     Object* target = rinfo->target_object();
   3944     if (ShouldHaveBeenRecorded(host, MaybeObject::FromObject(target))) {
   3945       CHECK(InTypedSet(EMBEDDED_OBJECT_SLOT, rinfo->pc()) ||
   3946             (rinfo->IsInConstantPool() &&
   3947              InTypedSet(OBJECT_SLOT, rinfo->constant_pool_entry_address())));
   3948     }
   3949   }
   3950 
   3951  private:
   3952   bool InTypedSet(SlotType type, Address slot) {
   3953     return typed_->count(std::make_pair(type, slot)) > 0;
   3954   }
   3955   std::set<Address>* untyped_;
   3956   std::set<std::pair<SlotType, Address> >* typed_;
   3957 };
   3958 
   3959 class OldToNewSlotVerifyingVisitor : public SlotVerifyingVisitor {
   3960  public:
   3961   OldToNewSlotVerifyingVisitor(std::set<Address>* untyped,
   3962                                std::set<std::pair<SlotType, Address>>* typed)
   3963       : SlotVerifyingVisitor(untyped, typed) {}
   3964 
   3965   bool ShouldHaveBeenRecorded(HeapObject* host, MaybeObject* target) override {
   3966     DCHECK_IMPLIES(
   3967         target->IsStrongOrWeakHeapObject() && Heap::InNewSpace(target),
   3968         Heap::InToSpace(target));
   3969     return target->IsStrongOrWeakHeapObject() && Heap::InNewSpace(target) &&
   3970            !Heap::InNewSpace(host);
   3971   }
   3972 };
   3973 
   3974 template <RememberedSetType direction>
   3975 void CollectSlots(MemoryChunk* chunk, Address start, Address end,
   3976                   std::set<Address>* untyped,
   3977                   std::set<std::pair<SlotType, Address> >* typed) {
   3978   RememberedSet<direction>::Iterate(chunk,
   3979                                     [start, end, untyped](Address slot) {
   3980                                       if (start <= slot && slot < end) {
   3981                                         untyped->insert(slot);
   3982                                       }
   3983                                       return KEEP_SLOT;
   3984                                     },
   3985                                     SlotSet::PREFREE_EMPTY_BUCKETS);
   3986   RememberedSet<direction>::IterateTyped(
   3987       chunk, [start, end, typed](SlotType type, Address host, Address slot) {
   3988         if (start <= slot && slot < end) {
   3989           typed->insert(std::make_pair(type, slot));
   3990         }
   3991         return KEEP_SLOT;
   3992       });
   3993 }
   3994 
   3995 void Heap::VerifyRememberedSetFor(HeapObject* object) {
   3996   MemoryChunk* chunk = MemoryChunk::FromAddress(object->address());
   3997   DCHECK_IMPLIES(chunk->mutex() == nullptr, InReadOnlySpace(object));
   3998   // In RO_SPACE chunk->mutex() may be nullptr, so just ignore it.
   3999   base::LockGuard<base::Mutex, base::NullBehavior::kIgnoreIfNull> lock_guard(
   4000       chunk->mutex());
   4001   Address start = object->address();
   4002   Address end = start + object->Size();
   4003   std::set<Address> old_to_new;
   4004   std::set<std::pair<SlotType, Address> > typed_old_to_new;
   4005   if (!InNewSpace(object)) {
   4006     store_buffer()->MoveAllEntriesToRememberedSet();
   4007     CollectSlots<OLD_TO_NEW>(chunk, start, end, &old_to_new, &typed_old_to_new);
   4008     OldToNewSlotVerifyingVisitor visitor(&old_to_new, &typed_old_to_new);
   4009     object->IterateBody(&visitor);
   4010   }
   4011   // TODO(ulan): Add old to old slot set verification once all weak objects
   4012   // have their own instance types and slots are recorded for all weal fields.
   4013 }
   4014 #endif
   4015 
   4016 #ifdef DEBUG
   4017 void Heap::VerifyCountersAfterSweeping() {
   4018   PagedSpaces spaces(this);
   4019   for (PagedSpace* space = spaces.next(); space != nullptr;
   4020        space = spaces.next()) {
   4021     space->VerifyCountersAfterSweeping();
   4022   }
   4023 }
   4024 
   4025 void Heap::VerifyCountersBeforeConcurrentSweeping() {
   4026   PagedSpaces spaces(this);
   4027   for (PagedSpace* space = spaces.next(); space != nullptr;
   4028        space = spaces.next()) {
   4029     space->VerifyCountersBeforeConcurrentSweeping();
   4030   }
   4031 }
   4032 #endif
   4033 
   4034 void Heap::ZapFromSpace() {
   4035   if (!new_space_->IsFromSpaceCommitted()) return;
   4036   for (Page* page : PageRange(new_space_->from_space().first_page(), nullptr)) {
   4037     memory_allocator()->ZapBlock(page->area_start(),
   4038                                  page->HighWaterMark() - page->area_start(),
   4039                                  ZapValue());
   4040   }
   4041 }
   4042 
   4043 void Heap::ZapCodeObject(Address start_address, int size_in_bytes) {
   4044 #ifdef DEBUG
   4045   for (int i = 0; i < size_in_bytes / kPointerSize; i++) {
   4046     reinterpret_cast<Object**>(start_address)[i] = Smi::FromInt(kCodeZapValue);
   4047   }
   4048 #endif
   4049 }
   4050 
   4051 Code* Heap::builtin(int index) {
   4052   DCHECK(Builtins::IsBuiltinId(index));
   4053   // Code::cast cannot be used here since we access builtins
   4054   // during the marking phase of mark sweep. See IC::Clear.
   4055   return reinterpret_cast<Code*>(builtins_[index]);
   4056 }
   4057 
   4058 Address Heap::builtin_address(int index) {
   4059   DCHECK(Builtins::IsBuiltinId(index) || index == Builtins::builtin_count);
   4060   return reinterpret_cast<Address>(&builtins_[index]);
   4061 }
   4062 
   4063 void Heap::set_builtin(int index, HeapObject* builtin) {
   4064   DCHECK(Builtins::IsBuiltinId(index));
   4065   DCHECK(Internals::HasHeapObjectTag(builtin));
   4066   // The given builtin may be completely uninitialized thus we cannot check its
   4067   // type here.
   4068   builtins_[index] = builtin;
   4069 }
   4070 
   4071 void Heap::IterateRoots(RootVisitor* v, VisitMode mode) {
   4072   IterateStrongRoots(v, mode);
   4073   IterateWeakRoots(v, mode);
   4074 }
   4075 
   4076 void Heap::IterateWeakRoots(RootVisitor* v, VisitMode mode) {
   4077   const bool isMinorGC = mode == VISIT_ALL_IN_SCAVENGE ||
   4078                          mode == VISIT_ALL_IN_MINOR_MC_MARK ||
   4079                          mode == VISIT_ALL_IN_MINOR_MC_UPDATE;
   4080   v->VisitRootPointer(
   4081       Root::kStringTable, nullptr,
   4082       reinterpret_cast<Object**>(&roots_[kStringTableRootIndex]));
   4083   v->Synchronize(VisitorSynchronization::kStringTable);
   4084   if (!isMinorGC && mode != VISIT_ALL_IN_SWEEP_NEWSPACE &&
   4085       mode != VISIT_FOR_SERIALIZATION) {
   4086     // Scavenge collections have special processing for this.
   4087     // Do not visit for serialization, since the external string table will
   4088     // be populated from scratch upon deserialization.
   4089     external_string_table_.IterateAll(v);
   4090   }
   4091   v->Synchronize(VisitorSynchronization::kExternalStringsTable);
   4092 }
   4093 
   4094 void Heap::IterateSmiRoots(RootVisitor* v) {
   4095   // Acquire execution access since we are going to read stack limit values.
   4096   ExecutionAccess access(isolate());
   4097   v->VisitRootPointers(Root::kSmiRootList, nullptr, &roots_[kSmiRootsStart],
   4098                        &roots_[kRootListLength]);
   4099   v->Synchronize(VisitorSynchronization::kSmiRootList);
   4100 }
   4101 
   4102 // We cannot avoid stale handles to left-trimmed objects, but can only make
   4103 // sure all handles still needed are updated. Filter out a stale pointer
   4104 // and clear the slot to allow post processing of handles (needed because
   4105 // the sweeper might actually free the underlying page).
   4106 class FixStaleLeftTrimmedHandlesVisitor : public RootVisitor {
   4107  public:
   4108   explicit FixStaleLeftTrimmedHandlesVisitor(Heap* heap) : heap_(heap) {
   4109     USE(heap_);
   4110   }
   4111 
   4112   void VisitRootPointer(Root root, const char* description,
   4113                         Object** p) override {
   4114     FixHandle(p);
   4115   }
   4116 
   4117   void VisitRootPointers(Root root, const char* description, Object** start,
   4118                          Object** end) override {
   4119     for (Object** p = start; p < end; p++) FixHandle(p);
   4120   }
   4121 
   4122  private:
   4123   inline void FixHandle(Object** p) {
   4124     if (!(*p)->IsHeapObject()) return;
   4125     HeapObject* current = reinterpret_cast<HeapObject*>(*p);
   4126     const MapWord map_word = current->map_word();
   4127     if (!map_word.IsForwardingAddress() && current->IsFiller()) {
   4128 #ifdef DEBUG
   4129       // We need to find a FixedArrayBase map after walking the fillers.
   4130       while (current->IsFiller()) {
   4131         Address next = reinterpret_cast<Address>(current);
   4132         if (current->map() == ReadOnlyRoots(heap_).one_pointer_filler_map()) {
   4133           next += kPointerSize;
   4134         } else if (current->map() ==
   4135                    ReadOnlyRoots(heap_).two_pointer_filler_map()) {
   4136           next += 2 * kPointerSize;
   4137         } else {
   4138           next += current->Size();
   4139         }
   4140         current = reinterpret_cast<HeapObject*>(next);
   4141       }
   4142       DCHECK(current->IsFixedArrayBase());
   4143 #endif  // DEBUG
   4144       *p = nullptr;
   4145     }
   4146   }
   4147 
   4148   Heap* heap_;
   4149 };
   4150 
   4151 void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) {
   4152   const bool isMinorGC = mode == VISIT_ALL_IN_SCAVENGE ||
   4153                          mode == VISIT_ALL_IN_MINOR_MC_MARK ||
   4154                          mode == VISIT_ALL_IN_MINOR_MC_UPDATE;
   4155   v->VisitRootPointers(Root::kStrongRootList, nullptr, &roots_[0],
   4156                        &roots_[kStrongRootListLength]);
   4157   v->Synchronize(VisitorSynchronization::kStrongRootList);
   4158 
   4159   isolate_->bootstrapper()->Iterate(v);
   4160   v->Synchronize(VisitorSynchronization::kBootstrapper);
   4161   isolate_->Iterate(v);
   4162   v->Synchronize(VisitorSynchronization::kTop);
   4163   Relocatable::Iterate(isolate_, v);
   4164   v->Synchronize(VisitorSynchronization::kRelocatable);
   4165   isolate_->debug()->Iterate(v);
   4166   v->Synchronize(VisitorSynchronization::kDebug);
   4167 
   4168   isolate_->compilation_cache()->Iterate(v);
   4169   v->Synchronize(VisitorSynchronization::kCompilationCache);
   4170 
   4171   // Iterate over local handles in handle scopes.
   4172   FixStaleLeftTrimmedHandlesVisitor left_trim_visitor(this);
   4173   isolate_->handle_scope_implementer()->Iterate(&left_trim_visitor);
   4174   isolate_->handle_scope_implementer()->Iterate(v);
   4175   isolate_->IterateDeferredHandles(v);
   4176   v->Synchronize(VisitorSynchronization::kHandleScope);
   4177 
   4178   // Iterate over the builtin code objects and code stubs in the
   4179   // heap. Note that it is not necessary to iterate over code objects
   4180   // on scavenge collections.
   4181   if (!isMinorGC) {
   4182     IterateBuiltins(v);
   4183     v->Synchronize(VisitorSynchronization::kBuiltins);
   4184     isolate_->interpreter()->IterateDispatchTable(v);
   4185     v->Synchronize(VisitorSynchronization::kDispatchTable);
   4186   }
   4187 
   4188   // Iterate over global handles.
   4189   switch (mode) {
   4190     case VISIT_FOR_SERIALIZATION:
   4191       // Global handles are not iterated by the serializer. Values referenced by
   4192       // global handles need to be added manually.
   4193       break;
   4194     case VISIT_ONLY_STRONG:
   4195       isolate_->global_handles()->IterateStrongRoots(v);
   4196       break;
   4197     case VISIT_ALL_IN_SCAVENGE:
   4198       isolate_->global_handles()->IterateNewSpaceStrongAndDependentRoots(v);
   4199       break;
   4200     case VISIT_ALL_IN_MINOR_MC_MARK:
   4201       // Global handles are processed manually be the minor MC.
   4202       break;
   4203     case VISIT_ALL_IN_MINOR_MC_UPDATE:
   4204       // Global handles are processed manually be the minor MC.
   4205       break;
   4206     case VISIT_ALL_IN_SWEEP_NEWSPACE:
   4207     case VISIT_ALL:
   4208       isolate_->global_handles()->IterateAllRoots(v);
   4209       break;
   4210   }
   4211   v->Synchronize(VisitorSynchronization::kGlobalHandles);
   4212 
   4213   // Iterate over eternal handles. Eternal handles are not iterated by the
   4214   // serializer. Values referenced by eternal handles need to be added manually.
   4215   if (mode != VISIT_FOR_SERIALIZATION) {
   4216     if (isMinorGC) {
   4217       isolate_->eternal_handles()->IterateNewSpaceRoots(v);
   4218     } else {
   4219       isolate_->eternal_handles()->IterateAllRoots(v);
   4220     }
   4221   }
   4222   v->Synchronize(VisitorSynchronization::kEternalHandles);
   4223 
   4224   // Iterate over pointers being held by inactive threads.
   4225   isolate_->thread_manager()->Iterate(v);
   4226   v->Synchronize(VisitorSynchronization::kThreadManager);
   4227 
   4228   // Iterate over other strong roots (currently only identity maps).
   4229   for (StrongRootsList* list = strong_roots_list_; list; list = list->next) {
   4230     v->VisitRootPointers(Root::kStrongRoots, nullptr, list->start, list->end);
   4231   }
   4232   v->Synchronize(VisitorSynchronization::kStrongRoots);
   4233 
   4234   // Iterate over the partial snapshot cache unless serializing.
   4235   if (mode != VISIT_FOR_SERIALIZATION) {
   4236     SerializerDeserializer::Iterate(isolate_, v);
   4237     // We don't do a v->Synchronize call here because the serializer and the
   4238     // deserializer are deliberately out of sync here.
   4239   }
   4240 }
   4241 
   4242 void Heap::IterateWeakGlobalHandles(RootVisitor* v) {
   4243   isolate_->global_handles()->IterateWeakRoots(v);
   4244 }
   4245 
   4246 void Heap::IterateBuiltins(RootVisitor* v) {
   4247   for (int i = 0; i < Builtins::builtin_count; i++) {
   4248     v->VisitRootPointer(Root::kBuiltins, Builtins::name(i), &builtins_[i]);
   4249   }
   4250 }
   4251 
   4252 // TODO(1236194): Since the heap size is configurable on the command line
   4253 // and through the API, we should gracefully handle the case that the heap
   4254 // size is not big enough to fit all the initial objects.
   4255 void Heap::ConfigureHeap(size_t max_semi_space_size_in_kb,
   4256                          size_t max_old_generation_size_in_mb,
   4257                          size_t code_range_size_in_mb) {
   4258   // Overwrite default configuration.
   4259   if (max_semi_space_size_in_kb != 0) {
   4260     max_semi_space_size_ =
   4261         RoundUp<Page::kPageSize>(max_semi_space_size_in_kb * KB);
   4262   }
   4263   if (max_old_generation_size_in_mb != 0) {
   4264     max_old_generation_size_ = max_old_generation_size_in_mb * MB;
   4265   }
   4266 
   4267   // If max space size flags are specified overwrite the configuration.
   4268   if (FLAG_max_semi_space_size > 0) {
   4269     max_semi_space_size_ = static_cast<size_t>(FLAG_max_semi_space_size) * MB;
   4270   }
   4271   if (FLAG_max_old_space_size > 0) {
   4272     max_old_generation_size_ =
   4273         static_cast<size_t>(FLAG_max_old_space_size) * MB;
   4274   }
   4275 
   4276   if (Page::kPageSize > MB) {
   4277     max_semi_space_size_ = RoundUp<Page::kPageSize>(max_semi_space_size_);
   4278     max_old_generation_size_ =
   4279         RoundUp<Page::kPageSize>(max_old_generation_size_);
   4280   }
   4281 
   4282   if (FLAG_stress_compaction) {
   4283     // This will cause more frequent GCs when stressing.
   4284     max_semi_space_size_ = MB;
   4285   }
   4286 
   4287   // The new space size must be a power of two to support single-bit testing
   4288   // for containment.
   4289   max_semi_space_size_ = static_cast<size_t>(base::bits::RoundUpToPowerOfTwo64(
   4290       static_cast<uint64_t>(max_semi_space_size_)));
   4291 
   4292   if (max_semi_space_size_ == kMaxSemiSpaceSizeInKB * KB) {
   4293     // Start with at least 1*MB semi-space on machines with a lot of memory.
   4294     initial_semispace_size_ =
   4295         Max(initial_semispace_size_, static_cast<size_t>(1 * MB));
   4296   }
   4297 
   4298   if (FLAG_min_semi_space_size > 0) {
   4299     size_t initial_semispace_size =
   4300         static_cast<size_t>(FLAG_min_semi_space_size) * MB;
   4301     if (initial_semispace_size > max_semi_space_size_) {
   4302       initial_semispace_size_ = max_semi_space_size_;
   4303       if (FLAG_trace_gc) {
   4304         PrintIsolate(isolate_,
   4305                      "Min semi-space size cannot be more than the maximum "
   4306                      "semi-space size of %" PRIuS " MB\n",
   4307                      max_semi_space_size_ / MB);
   4308       }
   4309     } else {
   4310       initial_semispace_size_ =
   4311           RoundUp<Page::kPageSize>(initial_semispace_size);
   4312     }
   4313   }
   4314 
   4315   initial_semispace_size_ = Min(initial_semispace_size_, max_semi_space_size_);
   4316 
   4317   if (FLAG_semi_space_growth_factor < 2) {
   4318     FLAG_semi_space_growth_factor = 2;
   4319   }
   4320 
   4321   // The old generation is paged and needs at least one page for each space.
   4322   int paged_space_count =
   4323       LAST_GROWABLE_PAGED_SPACE - FIRST_GROWABLE_PAGED_SPACE + 1;
   4324   initial_max_old_generation_size_ = max_old_generation_size_ =
   4325       Max(static_cast<size_t>(paged_space_count * Page::kPageSize),
   4326           max_old_generation_size_);
   4327 
   4328   if (FLAG_initial_old_space_size > 0) {
   4329     initial_old_generation_size_ = FLAG_initial_old_space_size * MB;
   4330   } else {
   4331     initial_old_generation_size_ =
   4332         max_old_generation_size_ / kInitalOldGenerationLimitFactor;
   4333   }
   4334   old_generation_allocation_limit_ = initial_old_generation_size_;
   4335 
   4336   // We rely on being able to allocate new arrays in paged spaces.
   4337   DCHECK(kMaxRegularHeapObjectSize >=
   4338          (JSArray::kSize +
   4339           FixedArray::SizeFor(JSArray::kInitialMaxFastElementArray) +
   4340           AllocationMemento::kSize));
   4341 
   4342   code_range_size_ = code_range_size_in_mb * MB;
   4343 
   4344   configured_ = true;
   4345 }
   4346 
   4347 
   4348 void Heap::AddToRingBuffer(const char* string) {
   4349   size_t first_part =
   4350       Min(strlen(string), kTraceRingBufferSize - ring_buffer_end_);
   4351   memcpy(trace_ring_buffer_ + ring_buffer_end_, string, first_part);
   4352   ring_buffer_end_ += first_part;
   4353   if (first_part < strlen(string)) {
   4354     ring_buffer_full_ = true;
   4355     size_t second_part = strlen(string) - first_part;
   4356     memcpy(trace_ring_buffer_, string + first_part, second_part);
   4357     ring_buffer_end_ = second_part;
   4358   }
   4359 }
   4360 
   4361 
   4362 void Heap::GetFromRingBuffer(char* buffer) {
   4363   size_t copied = 0;
   4364   if (ring_buffer_full_) {
   4365     copied = kTraceRingBufferSize - ring_buffer_end_;
   4366     memcpy(buffer, trace_ring_buffer_ + ring_buffer_end_, copied);
   4367   }
   4368   memcpy(buffer + copied, trace_ring_buffer_, ring_buffer_end_);
   4369 }
   4370 
   4371 void Heap::ConfigureHeapDefault() { ConfigureHeap(0, 0, 0); }
   4372 
   4373 void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
   4374   *stats->start_marker = HeapStats::kStartMarker;
   4375   *stats->end_marker = HeapStats::kEndMarker;
   4376   *stats->ro_space_size = read_only_space_->Size();
   4377   *stats->ro_space_capacity = read_only_space_->Capacity();
   4378   *stats->new_space_size = new_space_->Size();
   4379   *stats->new_space_capacity = new_space_->Capacity();
   4380   *stats->old_space_size = old_space_->SizeOfObjects();
   4381   *stats->old_space_capacity = old_space_->Capacity();
   4382   *stats->code_space_size = code_space_->SizeOfObjects();
   4383   *stats->code_space_capacity = code_space_->Capacity();
   4384   *stats->map_space_size = map_space_->SizeOfObjects();
   4385   *stats->map_space_capacity = map_space_->Capacity();
   4386   *stats->lo_space_size = lo_space_->Size();
   4387   isolate_->global_handles()->RecordStats(stats);
   4388   *stats->memory_allocator_size = memory_allocator()->Size();
   4389   *stats->memory_allocator_capacity =
   4390       memory_allocator()->Size() + memory_allocator()->Available();
   4391   *stats->os_error = base::OS::GetLastError();
   4392   *stats->malloced_memory = isolate_->allocator()->GetCurrentMemoryUsage();
   4393   *stats->malloced_peak_memory = isolate_->allocator()->GetMaxMemoryUsage();
   4394   if (take_snapshot) {
   4395     HeapIterator iterator(this);
   4396     for (HeapObject* obj = iterator.next(); obj != nullptr;
   4397          obj = iterator.next()) {
   4398       InstanceType type = obj->map()->instance_type();
   4399       DCHECK(0 <= type && type <= LAST_TYPE);
   4400       stats->objects_per_type[type]++;
   4401       stats->size_per_type[type] += obj->Size();
   4402     }
   4403   }
   4404   if (stats->last_few_messages != nullptr)
   4405     GetFromRingBuffer(stats->last_few_messages);
   4406   if (stats->js_stacktrace != nullptr) {
   4407     FixedStringAllocator fixed(stats->js_stacktrace, kStacktraceBufferSize - 1);
   4408     StringStream accumulator(&fixed, StringStream::kPrintObjectConcise);
   4409     if (gc_state() == Heap::NOT_IN_GC) {
   4410       isolate()->PrintStack(&accumulator, Isolate::kPrintStackVerbose);
   4411     } else {
   4412       accumulator.Add("Cannot get stack trace in GC.");
   4413     }
   4414   }
   4415 }
   4416 
   4417 size_t Heap::OldGenerationSizeOfObjects() {
   4418   PagedSpaces spaces(this, PagedSpaces::SpacesSpecifier::kAllPagedSpaces);
   4419   size_t total = 0;
   4420   for (PagedSpace* space = spaces.next(); space != nullptr;
   4421        space = spaces.next()) {
   4422     total += space->SizeOfObjects();
   4423   }
   4424   return total + lo_space_->SizeOfObjects();
   4425 }
   4426 
   4427 uint64_t Heap::PromotedExternalMemorySize() {
   4428   if (external_memory_ <= external_memory_at_last_mark_compact_) return 0;
   4429   return static_cast<uint64_t>(external_memory_ -
   4430                                external_memory_at_last_mark_compact_);
   4431 }
   4432 
   4433 bool Heap::ShouldOptimizeForLoadTime() {
   4434   return isolate()->rail_mode() == PERFORMANCE_LOAD &&
   4435          !AllocationLimitOvershotByLargeMargin() &&
   4436          MonotonicallyIncreasingTimeInMs() <
   4437              isolate()->LoadStartTimeMs() + kMaxLoadTimeMs;
   4438 }
   4439 
   4440 // This predicate is called when an old generation space cannot allocated from
   4441 // the free list and is about to add a new page. Returning false will cause a
   4442 // major GC. It happens when the old generation allocation limit is reached and
   4443 // - either we need to optimize for memory usage,
   4444 // - or the incremental marking is not in progress and we cannot start it.
   4445 bool Heap::ShouldExpandOldGenerationOnSlowAllocation() {
   4446   if (always_allocate() || OldGenerationSpaceAvailable() > 0) return true;
   4447   // We reached the old generation allocation limit.
   4448 
   4449   if (ShouldOptimizeForMemoryUsage()) return false;
   4450 
   4451   if (ShouldOptimizeForLoadTime()) return true;
   4452 
   4453   if (incremental_marking()->NeedsFinalization()) {
   4454     return !AllocationLimitOvershotByLargeMargin();
   4455   }
   4456 
   4457   if (incremental_marking()->IsStopped() &&
   4458       IncrementalMarkingLimitReached() == IncrementalMarkingLimit::kNoLimit) {
   4459     // We cannot start incremental marking.
   4460     return false;
   4461   }
   4462   return true;
   4463 }
   4464 
   4465 Heap::HeapGrowingMode Heap::CurrentHeapGrowingMode() {
   4466   if (ShouldReduceMemory() || FLAG_stress_compaction) {
   4467     return Heap::HeapGrowingMode::kMinimal;
   4468   }
   4469 
   4470   if (ShouldOptimizeForMemoryUsage()) {
   4471     return Heap::HeapGrowingMode::kConservative;
   4472   }
   4473 
   4474   if (memory_reducer()->ShouldGrowHeapSlowly()) {
   4475     return Heap::HeapGrowingMode::kSlow;
   4476   }
   4477 
   4478   return Heap::HeapGrowingMode::kDefault;
   4479 }
   4480 
   4481 // This function returns either kNoLimit, kSoftLimit, or kHardLimit.
   4482 // The kNoLimit means that either incremental marking is disabled or it is too
   4483 // early to start incremental marking.
   4484 // The kSoftLimit means that incremental marking should be started soon.
   4485 // The kHardLimit means that incremental marking should be started immediately.
   4486 Heap::IncrementalMarkingLimit Heap::IncrementalMarkingLimitReached() {
   4487   // Code using an AlwaysAllocateScope assumes that the GC state does not
   4488   // change; that implies that no marking steps must be performed.
   4489   if (!incremental_marking()->CanBeActivated() || always_allocate()) {
   4490     // Incremental marking is disabled or it is too early to start.
   4491     return IncrementalMarkingLimit::kNoLimit;
   4492   }
   4493   if (FLAG_stress_incremental_marking) {
   4494     return IncrementalMarkingLimit::kHardLimit;
   4495   }
   4496   if (OldGenerationSizeOfObjects() <=
   4497       IncrementalMarking::kActivationThreshold) {
   4498     // Incremental marking is disabled or it is too early to start.
   4499     return IncrementalMarkingLimit::kNoLimit;
   4500   }
   4501   if ((FLAG_stress_compaction && (gc_count_ & 1) != 0) ||
   4502       HighMemoryPressure()) {
   4503     // If there is high memory pressure or stress testing is enabled, then
   4504     // start marking immediately.
   4505     return IncrementalMarkingLimit::kHardLimit;
   4506   }
   4507 
   4508   if (FLAG_stress_marking > 0) {
   4509     double gained_since_last_gc =
   4510         PromotedSinceLastGC() +
   4511         (external_memory_ - external_memory_at_last_mark_compact_);
   4512     double size_before_gc =
   4513         OldGenerationObjectsAndPromotedExternalMemorySize() -
   4514         gained_since_last_gc;
   4515     double bytes_to_limit = old_generation_allocation_limit_ - size_before_gc;
   4516     if (bytes_to_limit > 0) {
   4517       double current_percent = (gained_since_last_gc / bytes_to_limit) * 100.0;
   4518 
   4519       if (FLAG_trace_stress_marking) {
   4520         isolate()->PrintWithTimestamp(
   4521             "[IncrementalMarking] %.2lf%% of the memory limit reached\n",
   4522             current_percent);
   4523       }
   4524 
   4525       if (FLAG_fuzzer_gc_analysis) {
   4526         // Skips values >=100% since they already trigger marking.
   4527         if (current_percent < 100.0) {
   4528           max_marking_limit_reached_ =
   4529               std::max(max_marking_limit_reached_, current_percent);
   4530         }
   4531       } else if (static_cast<int>(current_percent) >=
   4532                  stress_marking_percentage_) {
   4533         stress_marking_percentage_ = NextStressMarkingLimit();
   4534         return IncrementalMarkingLimit::kHardLimit;
   4535       }
   4536     }
   4537   }
   4538 
   4539   size_t old_generation_space_available = OldGenerationSpaceAvailable();
   4540 
   4541   if (old_generation_space_available > new_space_->Capacity()) {
   4542     return IncrementalMarkingLimit::kNoLimit;
   4543   }
   4544   if (ShouldOptimizeForMemoryUsage()) {
   4545     return IncrementalMarkingLimit::kHardLimit;
   4546   }
   4547   if (ShouldOptimizeForLoadTime()) {
   4548     return IncrementalMarkingLimit::kNoLimit;
   4549   }
   4550   if (old_generation_space_available == 0) {
   4551     return IncrementalMarkingLimit::kHardLimit;
   4552   }
   4553   return IncrementalMarkingLimit::kSoftLimit;
   4554 }
   4555 
   4556 void Heap::EnableInlineAllocation() {
   4557   if (!inline_allocation_disabled_) return;
   4558   inline_allocation_disabled_ = false;
   4559 
   4560   // Update inline allocation limit for new space.
   4561   new_space()->UpdateInlineAllocationLimit(0);
   4562 }
   4563 
   4564 
   4565 void Heap::DisableInlineAllocation() {
   4566   if (inline_allocation_disabled_) return;
   4567   inline_allocation_disabled_ = true;
   4568 
   4569   // Update inline allocation limit for new space.
   4570   new_space()->UpdateInlineAllocationLimit(0);
   4571 
   4572   // Update inline allocation limit for old spaces.
   4573   PagedSpaces spaces(this);
   4574   CodeSpaceMemoryModificationScope modification_scope(this);
   4575   for (PagedSpace* space = spaces.next(); space != nullptr;
   4576        space = spaces.next()) {
   4577     space->FreeLinearAllocationArea();
   4578   }
   4579 }
   4580 
   4581 HeapObject* Heap::EnsureImmovableCode(HeapObject* heap_object,
   4582                                       int object_size) {
   4583   // Code objects which should stay at a fixed address are allocated either
   4584   // in the first page of code space, in large object space, or (during
   4585   // snapshot creation) the containing page is marked as immovable.
   4586   DCHECK(heap_object);
   4587   DCHECK(code_space_->Contains(heap_object));
   4588   DCHECK_GE(object_size, 0);
   4589   if (!Heap::IsImmovable(heap_object)) {
   4590     if (isolate()->serializer_enabled() ||
   4591         code_space_->first_page()->Contains(heap_object->address())) {
   4592       MemoryChunk::FromAddress(heap_object->address())->MarkNeverEvacuate();
   4593     } else {
   4594       // Discard the first code allocation, which was on a page where it could
   4595       // be moved.
   4596       CreateFillerObjectAt(heap_object->address(), object_size,
   4597                            ClearRecordedSlots::kNo);
   4598       heap_object = AllocateRawCodeInLargeObjectSpace(object_size);
   4599       UnprotectAndRegisterMemoryChunk(heap_object);
   4600       ZapCodeObject(heap_object->address(), object_size);
   4601       OnAllocationEvent(heap_object, object_size);
   4602     }
   4603   }
   4604   return heap_object;
   4605 }
   4606 
   4607 HeapObject* Heap::AllocateRawWithLightRetry(int size, AllocationSpace space,
   4608                                             AllocationAlignment alignment) {
   4609   HeapObject* result;
   4610   AllocationResult alloc = AllocateRaw(size, space, alignment);
   4611   if (alloc.To(&result)) {
   4612     DCHECK(result != ReadOnlyRoots(this).exception());
   4613     return result;
   4614   }
   4615   // Two GCs before panicking. In newspace will almost always succeed.
   4616   for (int i = 0; i < 2; i++) {
   4617     CollectGarbage(alloc.RetrySpace(),
   4618                    GarbageCollectionReason::kAllocationFailure);
   4619     alloc = AllocateRaw(size, space, alignment);
   4620     if (alloc.To(&result)) {
   4621       DCHECK(result != ReadOnlyRoots(this).exception());
   4622       return result;
   4623     }
   4624   }
   4625   return nullptr;
   4626 }
   4627 
   4628 HeapObject* Heap::AllocateRawWithRetryOrFail(int size, AllocationSpace space,
   4629                                              AllocationAlignment alignment) {
   4630   AllocationResult alloc;
   4631   HeapObject* result = AllocateRawWithLightRetry(size, space, alignment);
   4632   if (result) return result;
   4633 
   4634   isolate()->counters()->gc_last_resort_from_handles()->Increment();
   4635   CollectAllAvailableGarbage(GarbageCollectionReason::kLastResort);
   4636   {
   4637     AlwaysAllocateScope scope(isolate());
   4638     alloc = AllocateRaw(size, space, alignment);
   4639   }
   4640   if (alloc.To(&result)) {
   4641     DCHECK(result != ReadOnlyRoots(this).exception());
   4642     return result;
   4643   }
   4644   // TODO(1181417): Fix this.
   4645   FatalProcessOutOfMemory("CALL_AND_RETRY_LAST");
   4646   return nullptr;
   4647 }
   4648 
   4649 // TODO(jkummerow): Refactor this. AllocateRaw should take an "immovability"
   4650 // parameter and just do what's necessary.
   4651 HeapObject* Heap::AllocateRawCodeInLargeObjectSpace(int size) {
   4652   AllocationResult alloc = lo_space()->AllocateRaw(size, EXECUTABLE);
   4653   HeapObject* result;
   4654   if (alloc.To(&result)) {
   4655     DCHECK(result != ReadOnlyRoots(this).exception());
   4656     return result;
   4657   }
   4658   // Two GCs before panicking.
   4659   for (int i = 0; i < 2; i++) {
   4660     CollectGarbage(alloc.RetrySpace(),
   4661                    GarbageCollectionReason::kAllocationFailure);
   4662     alloc = lo_space()->AllocateRaw(size, EXECUTABLE);
   4663     if (alloc.To(&result)) {
   4664       DCHECK(result != ReadOnlyRoots(this).exception());
   4665       return result;
   4666     }
   4667   }
   4668   isolate()->counters()->gc_last_resort_from_handles()->Increment();
   4669   CollectAllAvailableGarbage(GarbageCollectionReason::kLastResort);
   4670   {
   4671     AlwaysAllocateScope scope(isolate());
   4672     alloc = lo_space()->AllocateRaw(size, EXECUTABLE);
   4673   }
   4674   if (alloc.To(&result)) {
   4675     DCHECK(result != ReadOnlyRoots(this).exception());
   4676     return result;
   4677   }
   4678   // TODO(1181417): Fix this.
   4679   FatalProcessOutOfMemory("CALL_AND_RETRY_LAST");
   4680   return nullptr;
   4681 }
   4682 
   4683 void Heap::SetUp() {
   4684 #ifdef V8_ENABLE_ALLOCATION_TIMEOUT
   4685   allocation_timeout_ = NextAllocationTimeout();
   4686 #endif
   4687 
   4688   // Initialize heap spaces and initial maps and objects.
   4689   //
   4690   // If the heap is not yet configured (e.g. through the API), configure it.
   4691   // Configuration is based on the flags new-space-size (really the semispace
   4692   // size) and old-space-size if set or the initial values of semispace_size_
   4693   // and old_generation_size_ otherwise.
   4694   if (!configured_) ConfigureHeapDefault();
   4695 
   4696   mmap_region_base_ =
   4697       reinterpret_cast<uintptr_t>(v8::internal::GetRandomMmapAddr()) &
   4698       ~kMmapRegionMask;
   4699 
   4700   // Set up memory allocator.
   4701   memory_allocator_ =
   4702       new MemoryAllocator(isolate_, MaxReserved(), code_range_size_);
   4703 
   4704   store_buffer_ = new StoreBuffer(this);
   4705 
   4706   heap_controller_ = new HeapController(this);
   4707 
   4708   mark_compact_collector_ = new MarkCompactCollector(this);
   4709   incremental_marking_ =
   4710       new IncrementalMarking(this, mark_compact_collector_->marking_worklist(),
   4711                              mark_compact_collector_->weak_objects());
   4712 
   4713   if (FLAG_concurrent_marking) {
   4714     MarkCompactCollector::MarkingWorklist* marking_worklist =
   4715         mark_compact_collector_->marking_worklist();
   4716     concurrent_marking_ = new ConcurrentMarking(
   4717         this, marking_worklist->shared(), marking_worklist->bailout(),
   4718         marking_worklist->on_hold(), mark_compact_collector_->weak_objects());
   4719   } else {
   4720     concurrent_marking_ =
   4721         new ConcurrentMarking(this, nullptr, nullptr, nullptr, nullptr);
   4722   }
   4723 
   4724   for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
   4725     space_[i] = nullptr;
   4726   }
   4727 
   4728   space_[RO_SPACE] = read_only_space_ = new ReadOnlySpace(this);
   4729   space_[NEW_SPACE] = new_space_ =
   4730       new NewSpace(this, initial_semispace_size_, max_semi_space_size_);
   4731   space_[OLD_SPACE] = old_space_ = new OldSpace(this);
   4732   space_[CODE_SPACE] = code_space_ = new CodeSpace(this);
   4733   space_[MAP_SPACE] = map_space_ = new MapSpace(this);
   4734   space_[LO_SPACE] = lo_space_ = new LargeObjectSpace(this);
   4735   space_[NEW_LO_SPACE] = new_lo_space_ = new NewLargeObjectSpace(this);
   4736 
   4737   for (int i = 0; i < static_cast<int>(v8::Isolate::kUseCounterFeatureCount);
   4738        i++) {
   4739     deferred_counters_[i] = 0;
   4740   }
   4741 
   4742   tracer_ = new GCTracer(this);
   4743 #ifdef ENABLE_MINOR_MC
   4744   minor_mark_compact_collector_ = new MinorMarkCompactCollector(this);
   4745 #else
   4746   minor_mark_compact_collector_ = nullptr;
   4747 #endif  // ENABLE_MINOR_MC
   4748   array_buffer_collector_ = new ArrayBufferCollector(this);
   4749   gc_idle_time_handler_ = new GCIdleTimeHandler();
   4750   memory_reducer_ = new MemoryReducer(this);
   4751   if (V8_UNLIKELY(FLAG_gc_stats)) {
   4752     live_object_stats_ = new ObjectStats(this);
   4753     dead_object_stats_ = new ObjectStats(this);
   4754   }
   4755   scavenge_job_ = new ScavengeJob();
   4756   local_embedder_heap_tracer_ = new LocalEmbedderHeapTracer(isolate());
   4757 
   4758   LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity()));
   4759   LOG(isolate_, IntPtrTEvent("heap-available", Available()));
   4760 
   4761   store_buffer()->SetUp();
   4762 
   4763   mark_compact_collector()->SetUp();
   4764 #ifdef ENABLE_MINOR_MC
   4765   if (minor_mark_compact_collector() != nullptr) {
   4766     minor_mark_compact_collector()->SetUp();
   4767   }
   4768 #endif  // ENABLE_MINOR_MC
   4769 
   4770   idle_scavenge_observer_ = new IdleScavengeObserver(
   4771       *this, ScavengeJob::kBytesAllocatedBeforeNextIdleTask);
   4772   new_space()->AddAllocationObserver(idle_scavenge_observer_);
   4773 
   4774   SetGetExternallyAllocatedMemoryInBytesCallback(
   4775       DefaultGetExternallyAllocatedMemoryInBytesCallback);
   4776 
   4777   if (FLAG_stress_marking > 0) {
   4778     stress_marking_percentage_ = NextStressMarkingLimit();
   4779     stress_marking_observer_ = new StressMarkingObserver(*this);
   4780     AddAllocationObserversToAllSpaces(stress_marking_observer_,
   4781                                       stress_marking_observer_);
   4782   }
   4783   if (FLAG_stress_scavenge > 0) {
   4784     stress_scavenge_observer_ = new StressScavengeObserver(*this);
   4785     new_space()->AddAllocationObserver(stress_scavenge_observer_);
   4786   }
   4787 
   4788   write_protect_code_memory_ = FLAG_write_protect_code_memory;
   4789 
   4790   external_reference_table_.Init(isolate_);
   4791 }
   4792 
   4793 void Heap::InitializeHashSeed() {
   4794   uint64_t new_hash_seed;
   4795   if (FLAG_hash_seed == 0) {
   4796     int64_t rnd = isolate()->random_number_generator()->NextInt64();
   4797     new_hash_seed = static_cast<uint64_t>(rnd);
   4798   } else {
   4799     new_hash_seed = static_cast<uint64_t>(FLAG_hash_seed);
   4800   }
   4801   hash_seed()->copy_in(0, reinterpret_cast<byte*>(&new_hash_seed), kInt64Size);
   4802 }
   4803 
   4804 void Heap::SetStackLimits() {
   4805   DCHECK_NOT_NULL(isolate_);
   4806   DCHECK(isolate_ == isolate());
   4807   // On 64 bit machines, pointers are generally out of range of Smis.  We write
   4808   // something that looks like an out of range Smi to the GC.
   4809 
   4810   // Set up the special root array entries containing the stack limits.
   4811   // These are actually addresses, but the tag makes the GC ignore it.
   4812   roots_[kStackLimitRootIndex] = reinterpret_cast<Object*>(
   4813       (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag);
   4814   roots_[kRealStackLimitRootIndex] = reinterpret_cast<Object*>(
   4815       (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag);
   4816 }
   4817 
   4818 void Heap::ClearStackLimits() {
   4819   roots_[kStackLimitRootIndex] = Smi::kZero;
   4820   roots_[kRealStackLimitRootIndex] = Smi::kZero;
   4821 }
   4822 
   4823 int Heap::NextAllocationTimeout(int current_timeout) {
   4824   if (FLAG_random_gc_interval > 0) {
   4825     // If current timeout hasn't reached 0 the GC was caused by something
   4826     // different than --stress-atomic-gc flag and we don't update the timeout.
   4827     if (current_timeout <= 0) {
   4828       return isolate()->fuzzer_rng()->NextInt(FLAG_random_gc_interval + 1);
   4829     } else {
   4830       return current_timeout;
   4831     }
   4832   }
   4833   return FLAG_gc_interval;
   4834 }
   4835 
   4836 void Heap::PrintAllocationsHash() {
   4837   uint32_t hash = StringHasher::GetHashCore(raw_allocations_hash_);
   4838   PrintF("\n### Allocations = %u, hash = 0x%08x\n", allocations_count(), hash);
   4839 }
   4840 
   4841 void Heap::PrintMaxMarkingLimitReached() {
   4842   PrintF("\n### Maximum marking limit reached = %.02lf\n",
   4843          max_marking_limit_reached_);
   4844 }
   4845 
   4846 void Heap::PrintMaxNewSpaceSizeReached() {
   4847   PrintF("\n### Maximum new space size reached = %.02lf\n",
   4848          stress_scavenge_observer_->MaxNewSpaceSizeReached());
   4849 }
   4850 
   4851 int Heap::NextStressMarkingLimit() {
   4852   return isolate()->fuzzer_rng()->NextInt(FLAG_stress_marking + 1);
   4853 }
   4854 
   4855 void Heap::NotifyDeserializationComplete() {
   4856   PagedSpaces spaces(this);
   4857   for (PagedSpace* s = spaces.next(); s != nullptr; s = spaces.next()) {
   4858     if (isolate()->snapshot_available()) s->ShrinkImmortalImmovablePages();
   4859 #ifdef DEBUG
   4860     // All pages right after bootstrapping must be marked as never-evacuate.
   4861     for (Page* p : *s) {
   4862       DCHECK(p->NeverEvacuate());
   4863     }
   4864 #endif  // DEBUG
   4865   }
   4866 
   4867   read_only_space()->MarkAsReadOnly();
   4868   deserialization_complete_ = true;
   4869 }
   4870 
   4871 void Heap::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {
   4872   DCHECK_EQ(gc_state_, HeapState::NOT_IN_GC);
   4873   local_embedder_heap_tracer()->SetRemoteTracer(tracer);
   4874 }
   4875 
   4876 void Heap::TracePossibleWrapper(JSObject* js_object) {
   4877   DCHECK(js_object->IsApiWrapper());
   4878   if (js_object->GetEmbedderFieldCount() >= 2 &&
   4879       js_object->GetEmbedderField(0) &&
   4880       js_object->GetEmbedderField(0) != ReadOnlyRoots(this).undefined_value() &&
   4881       js_object->GetEmbedderField(1) != ReadOnlyRoots(this).undefined_value()) {
   4882     DCHECK_EQ(0,
   4883               reinterpret_cast<intptr_t>(js_object->GetEmbedderField(0)) % 2);
   4884     local_embedder_heap_tracer()->AddWrapperToTrace(std::pair<void*, void*>(
   4885         reinterpret_cast<void*>(js_object->GetEmbedderField(0)),
   4886         reinterpret_cast<void*>(js_object->GetEmbedderField(1))));
   4887   }
   4888 }
   4889 
   4890 void Heap::RegisterExternallyReferencedObject(Object** object) {
   4891   // The embedder is not aware of whether numbers are materialized as heap
   4892   // objects are just passed around as Smis.
   4893   if (!(*object)->IsHeapObject()) return;
   4894   HeapObject* heap_object = HeapObject::cast(*object);
   4895   DCHECK(Contains(heap_object));
   4896   if (FLAG_incremental_marking_wrappers && incremental_marking()->IsMarking()) {
   4897     incremental_marking()->WhiteToGreyAndPush(heap_object);
   4898   } else {
   4899     DCHECK(mark_compact_collector()->in_use());
   4900     mark_compact_collector()->MarkExternallyReferencedObject(heap_object);
   4901   }
   4902 }
   4903 
   4904 void Heap::StartTearDown() { SetGCState(TEAR_DOWN); }
   4905 
   4906 void Heap::TearDown() {
   4907   DCHECK_EQ(gc_state_, TEAR_DOWN);
   4908 #ifdef VERIFY_HEAP
   4909   if (FLAG_verify_heap) {
   4910     Verify();
   4911   }
   4912 #endif
   4913 
   4914   UpdateMaximumCommitted();
   4915 
   4916   if (FLAG_verify_predictable || FLAG_fuzzer_gc_analysis) {
   4917     PrintAllocationsHash();
   4918   }
   4919 
   4920   if (FLAG_fuzzer_gc_analysis) {
   4921     if (FLAG_stress_marking > 0) {
   4922       PrintMaxMarkingLimitReached();
   4923     }
   4924     if (FLAG_stress_scavenge > 0) {
   4925       PrintMaxNewSpaceSizeReached();
   4926     }
   4927   }
   4928 
   4929   new_space()->RemoveAllocationObserver(idle_scavenge_observer_);
   4930   delete idle_scavenge_observer_;
   4931   idle_scavenge_observer_ = nullptr;
   4932 
   4933   if (FLAG_stress_marking > 0) {
   4934     RemoveAllocationObserversFromAllSpaces(stress_marking_observer_,
   4935                                            stress_marking_observer_);
   4936     delete stress_marking_observer_;
   4937     stress_marking_observer_ = nullptr;
   4938   }
   4939   if (FLAG_stress_scavenge > 0) {
   4940     new_space()->RemoveAllocationObserver(stress_scavenge_observer_);
   4941     delete stress_scavenge_observer_;
   4942     stress_scavenge_observer_ = nullptr;
   4943   }
   4944 
   4945   if (heap_controller_ != nullptr) {
   4946     delete heap_controller_;
   4947     heap_controller_ = nullptr;
   4948   }
   4949 
   4950   if (mark_compact_collector_ != nullptr) {
   4951     mark_compact_collector_->TearDown();
   4952     delete mark_compact_collector_;
   4953     mark_compact_collector_ = nullptr;
   4954   }
   4955 
   4956 #ifdef ENABLE_MINOR_MC
   4957   if (minor_mark_compact_collector_ != nullptr) {
   4958     minor_mark_compact_collector_->TearDown();
   4959     delete minor_mark_compact_collector_;
   4960     minor_mark_compact_collector_ = nullptr;
   4961   }
   4962 #endif  // ENABLE_MINOR_MC
   4963 
   4964   if (array_buffer_collector_ != nullptr) {
   4965     delete array_buffer_collector_;
   4966     array_buffer_collector_ = nullptr;
   4967   }
   4968 
   4969   delete incremental_marking_;
   4970   incremental_marking_ = nullptr;
   4971 
   4972   delete concurrent_marking_;
   4973   concurrent_marking_ = nullptr;
   4974 
   4975   delete gc_idle_time_handler_;
   4976   gc_idle_time_handler_ = nullptr;
   4977 
   4978   if (memory_reducer_ != nullptr) {
   4979     memory_reducer_->TearDown();
   4980     delete memory_reducer_;
   4981     memory_reducer_ = nullptr;
   4982   }
   4983 
   4984   if (live_object_stats_ != nullptr) {
   4985     delete live_object_stats_;
   4986     live_object_stats_ = nullptr;
   4987   }
   4988 
   4989   if (dead_object_stats_ != nullptr) {
   4990     delete dead_object_stats_;
   4991     dead_object_stats_ = nullptr;
   4992   }
   4993 
   4994   delete local_embedder_heap_tracer_;
   4995   local_embedder_heap_tracer_ = nullptr;
   4996 
   4997   delete scavenge_job_;
   4998   scavenge_job_ = nullptr;
   4999 
   5000   isolate_->global_handles()->TearDown();
   5001 
   5002   external_string_table_.TearDown();
   5003 
   5004   // Tear down all ArrayBuffers before tearing down the heap since  their
   5005   // byte_length may be a HeapNumber which is required for freeing the backing
   5006   // store.
   5007   ArrayBufferTracker::TearDown(this);
   5008 
   5009   delete tracer_;
   5010   tracer_ = nullptr;
   5011 
   5012   for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
   5013     delete space_[i];
   5014     space_[i] = nullptr;
   5015   }
   5016 
   5017   store_buffer()->TearDown();
   5018 
   5019   memory_allocator()->TearDown();
   5020 
   5021   StrongRootsList* next = nullptr;
   5022   for (StrongRootsList* list = strong_roots_list_; list; list = next) {
   5023     next = list->next;
   5024     delete list;
   5025   }
   5026   strong_roots_list_ = nullptr;
   5027 
   5028   delete store_buffer_;
   5029   store_buffer_ = nullptr;
   5030 
   5031   delete memory_allocator_;
   5032   memory_allocator_ = nullptr;
   5033 }
   5034 
   5035 void Heap::AddGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
   5036                                  GCType gc_type, void* data) {
   5037   DCHECK_NOT_NULL(callback);
   5038   DCHECK(gc_prologue_callbacks_.end() ==
   5039          std::find(gc_prologue_callbacks_.begin(), gc_prologue_callbacks_.end(),
   5040                    GCCallbackTuple(callback, gc_type, data)));
   5041   gc_prologue_callbacks_.emplace_back(callback, gc_type, data);
   5042 }
   5043 
   5044 void Heap::RemoveGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
   5045                                     void* data) {
   5046   DCHECK_NOT_NULL(callback);
   5047   for (size_t i = 0; i < gc_prologue_callbacks_.size(); i++) {
   5048     if (gc_prologue_callbacks_[i].callback == callback &&
   5049         gc_prologue_callbacks_[i].data == data) {
   5050       gc_prologue_callbacks_[i] = gc_prologue_callbacks_.back();
   5051       gc_prologue_callbacks_.pop_back();
   5052       return;
   5053     }
   5054   }
   5055   UNREACHABLE();
   5056 }
   5057 
   5058 void Heap::AddGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback,
   5059                                  GCType gc_type, void* data) {
   5060   DCHECK_NOT_NULL(callback);
   5061   DCHECK(gc_epilogue_callbacks_.end() ==
   5062          std::find(gc_epilogue_callbacks_.begin(), gc_epilogue_callbacks_.end(),
   5063                    GCCallbackTuple(callback, gc_type, data)));
   5064   gc_epilogue_callbacks_.emplace_back(callback, gc_type, data);
   5065 }
   5066 
   5067 void Heap::RemoveGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback,
   5068                                     void* data) {
   5069   DCHECK_NOT_NULL(callback);
   5070   for (size_t i = 0; i < gc_epilogue_callbacks_.size(); i++) {
   5071     if (gc_epilogue_callbacks_[i].callback == callback &&
   5072         gc_epilogue_callbacks_[i].data == data) {
   5073       gc_epilogue_callbacks_[i] = gc_epilogue_callbacks_.back();
   5074       gc_epilogue_callbacks_.pop_back();
   5075       return;
   5076     }
   5077   }
   5078   UNREACHABLE();
   5079 }
   5080 
   5081 namespace {
   5082 Handle<WeakArrayList> CompactWeakArrayList(Heap* heap,
   5083                                            Handle<WeakArrayList> array,
   5084                                            PretenureFlag pretenure) {
   5085   if (array->length() == 0) {
   5086     return array;
   5087   }
   5088   int new_length = array->CountLiveWeakReferences();
   5089   if (new_length == array->length()) {
   5090     return array;
   5091   }
   5092 
   5093   Handle<WeakArrayList> new_array = WeakArrayList::EnsureSpace(
   5094       heap->isolate(),
   5095       handle(ReadOnlyRoots(heap).empty_weak_array_list(), heap->isolate()),
   5096       new_length, pretenure);
   5097   // Allocation might have caused GC and turned some of the elements into
   5098   // cleared weak heap objects. Count the number of live references again and
   5099   // fill in the new array.
   5100   int copy_to = 0;
   5101   for (int i = 0; i < array->length(); i++) {
   5102     MaybeObject* element = array->Get(i);
   5103     if (element->IsClearedWeakHeapObject()) continue;
   5104     new_array->Set(copy_to++, element);
   5105   }
   5106   new_array->set_length(copy_to);
   5107   return new_array;
   5108 }
   5109 
   5110 }  // anonymous namespace
   5111 
   5112 void Heap::CompactWeakArrayLists(PretenureFlag pretenure) {
   5113   // Find known PrototypeUsers and compact them.
   5114   std::vector<Handle<PrototypeInfo>> prototype_infos;
   5115   {
   5116     HeapIterator iterator(this);
   5117     for (HeapObject* o = iterator.next(); o != nullptr; o = iterator.next()) {
   5118       if (o->IsPrototypeInfo()) {
   5119         PrototypeInfo* prototype_info = PrototypeInfo::cast(o);
   5120         if (prototype_info->prototype_users()->IsWeakArrayList()) {
   5121           prototype_infos.emplace_back(handle(prototype_info, isolate()));
   5122         }
   5123       }
   5124     }
   5125   }
   5126   for (auto& prototype_info : prototype_infos) {
   5127     Handle<WeakArrayList> array(
   5128         WeakArrayList::cast(prototype_info->prototype_users()), isolate());
   5129     DCHECK_IMPLIES(pretenure == TENURED,
   5130                    InOldSpace(*array) ||
   5131                        *array == ReadOnlyRoots(this).empty_weak_array_list());
   5132     WeakArrayList* new_array = PrototypeUsers::Compact(
   5133         array, this, JSObject::PrototypeRegistryCompactionCallback, pretenure);
   5134     prototype_info->set_prototype_users(new_array);
   5135   }
   5136 
   5137   // Find known WeakArrayLists and compact them.
   5138   Handle<WeakArrayList> scripts(script_list(), isolate());
   5139   DCHECK_IMPLIES(pretenure == TENURED, InOldSpace(*scripts));
   5140   scripts = CompactWeakArrayList(this, scripts, pretenure);
   5141   set_script_list(*scripts);
   5142 
   5143   Handle<WeakArrayList> no_script_list(noscript_shared_function_infos(),
   5144                                        isolate());
   5145   DCHECK_IMPLIES(pretenure == TENURED, InOldSpace(*no_script_list));
   5146   no_script_list = CompactWeakArrayList(this, no_script_list, pretenure);
   5147   set_noscript_shared_function_infos(*no_script_list);
   5148 }
   5149 
   5150 void Heap::AddRetainedMap(Handle<Map> map) {
   5151   if (map->is_in_retained_map_list()) {
   5152     return;
   5153   }
   5154   Handle<WeakArrayList> array(retained_maps(), isolate());
   5155   if (array->IsFull()) {
   5156     CompactRetainedMaps(*array);
   5157   }
   5158   array =
   5159       WeakArrayList::AddToEnd(isolate(), array, MaybeObjectHandle::Weak(map));
   5160   array = WeakArrayList::AddToEnd(
   5161       isolate(), array,
   5162       MaybeObjectHandle(Smi::FromInt(FLAG_retain_maps_for_n_gc), isolate()));
   5163   if (*array != retained_maps()) {
   5164     set_retained_maps(*array);
   5165   }
   5166   map->set_is_in_retained_map_list(true);
   5167 }
   5168 
   5169 void Heap::CompactRetainedMaps(WeakArrayList* retained_maps) {
   5170   DCHECK_EQ(retained_maps, this->retained_maps());
   5171   int length = retained_maps->length();
   5172   int new_length = 0;
   5173   int new_number_of_disposed_maps = 0;
   5174   // This loop compacts the array by removing cleared weak cells.
   5175   for (int i = 0; i < length; i += 2) {
   5176     MaybeObject* maybe_object = retained_maps->Get(i);
   5177     if (maybe_object->IsClearedWeakHeapObject()) {
   5178       continue;
   5179     }
   5180 
   5181     DCHECK(maybe_object->IsWeakHeapObject());
   5182 
   5183     MaybeObject* age = retained_maps->Get(i + 1);
   5184     DCHECK(age->IsSmi());
   5185     if (i != new_length) {
   5186       retained_maps->Set(new_length, maybe_object);
   5187       retained_maps->Set(new_length + 1, age);
   5188     }
   5189     if (i < number_of_disposed_maps_) {
   5190       new_number_of_disposed_maps += 2;
   5191     }
   5192     new_length += 2;
   5193   }
   5194   number_of_disposed_maps_ = new_number_of_disposed_maps;
   5195   HeapObject* undefined = ReadOnlyRoots(this).undefined_value();
   5196   for (int i = new_length; i < length; i++) {
   5197     retained_maps->Set(i, HeapObjectReference::Strong(undefined));
   5198   }
   5199   if (new_length != length) retained_maps->set_length(new_length);
   5200 }
   5201 
   5202 void Heap::FatalProcessOutOfMemory(const char* location) {
   5203   v8::internal::V8::FatalProcessOutOfMemory(isolate(), location, true);
   5204 }
   5205 
   5206 #ifdef DEBUG
   5207 
   5208 class PrintHandleVisitor : public RootVisitor {
   5209  public:
   5210   void VisitRootPointers(Root root, const char* description, Object** start,
   5211                          Object** end) override {
   5212     for (Object** p = start; p < end; p++)
   5213       PrintF("  handle %p to %p\n", reinterpret_cast<void*>(p),
   5214              reinterpret_cast<void*>(*p));
   5215   }
   5216 };
   5217 
   5218 
   5219 void Heap::PrintHandles() {
   5220   PrintF("Handles:\n");
   5221   PrintHandleVisitor v;
   5222   isolate_->handle_scope_implementer()->Iterate(&v);
   5223 }
   5224 
   5225 #endif
   5226 
   5227 class CheckHandleCountVisitor : public RootVisitor {
   5228  public:
   5229   CheckHandleCountVisitor() : handle_count_(0) {}
   5230   ~CheckHandleCountVisitor() override {
   5231     CHECK_GT(HandleScope::kCheckHandleThreshold, handle_count_);
   5232   }
   5233   void VisitRootPointers(Root root, const char* description, Object** start,
   5234                          Object** end) override {
   5235     handle_count_ += end - start;
   5236   }
   5237 
   5238  private:
   5239   ptrdiff_t handle_count_;
   5240 };
   5241 
   5242 
   5243 void Heap::CheckHandleCount() {
   5244   CheckHandleCountVisitor v;
   5245   isolate_->handle_scope_implementer()->Iterate(&v);
   5246 }
   5247 
   5248 Address* Heap::store_buffer_top_address() {
   5249   return store_buffer()->top_address();
   5250 }
   5251 
   5252 // static
   5253 intptr_t Heap::store_buffer_mask_constant() {
   5254   return StoreBuffer::kStoreBufferMask;
   5255 }
   5256 
   5257 // static
   5258 Address Heap::store_buffer_overflow_function_address() {
   5259   return FUNCTION_ADDR(StoreBuffer::StoreBufferOverflow);
   5260 }
   5261 
   5262 void Heap::ClearRecordedSlot(HeapObject* object, Object** slot) {
   5263   Address slot_addr = reinterpret_cast<Address>(slot);
   5264   Page* page = Page::FromAddress(slot_addr);
   5265   if (!page->InNewSpace()) {
   5266     DCHECK_EQ(page->owner()->identity(), OLD_SPACE);
   5267     store_buffer()->DeleteEntry(slot_addr);
   5268   }
   5269 }
   5270 
   5271 bool Heap::HasRecordedSlot(HeapObject* object, Object** slot) {
   5272   if (InNewSpace(object)) {
   5273     return false;
   5274   }
   5275   Address slot_addr = reinterpret_cast<Address>(slot);
   5276   Page* page = Page::FromAddress(slot_addr);
   5277   DCHECK_EQ(page->owner()->identity(), OLD_SPACE);
   5278   store_buffer()->MoveAllEntriesToRememberedSet();
   5279   return RememberedSet<OLD_TO_NEW>::Contains(page, slot_addr) ||
   5280          RememberedSet<OLD_TO_OLD>::Contains(page, slot_addr);
   5281 }
   5282 
   5283 void Heap::ClearRecordedSlotRange(Address start, Address end) {
   5284   Page* page = Page::FromAddress(start);
   5285   if (!page->InNewSpace()) {
   5286     DCHECK_EQ(page->owner()->identity(), OLD_SPACE);
   5287     store_buffer()->DeleteEntry(start, end);
   5288   }
   5289 }
   5290 
   5291 PagedSpace* PagedSpaces::next() {
   5292   switch (counter_++) {
   5293     case RO_SPACE:
   5294       // skip NEW_SPACE
   5295       counter_++;
   5296       return heap_->read_only_space();
   5297     case OLD_SPACE:
   5298       return heap_->old_space();
   5299     case CODE_SPACE:
   5300       return heap_->code_space();
   5301     case MAP_SPACE:
   5302       return heap_->map_space();
   5303     default:
   5304       return nullptr;
   5305   }
   5306 }
   5307 
   5308 SpaceIterator::SpaceIterator(Heap* heap)
   5309     : heap_(heap), current_space_(FIRST_SPACE - 1) {}
   5310 
   5311 SpaceIterator::~SpaceIterator() {
   5312 }
   5313 
   5314 
   5315 bool SpaceIterator::has_next() {
   5316   // Iterate until no more spaces.
   5317   return current_space_ != LAST_SPACE;
   5318 }
   5319 
   5320 Space* SpaceIterator::next() {
   5321   DCHECK(has_next());
   5322   return heap_->space(++current_space_);
   5323 }
   5324 
   5325 
   5326 class HeapObjectsFilter {
   5327  public:
   5328   virtual ~HeapObjectsFilter() {}
   5329   virtual bool SkipObject(HeapObject* object) = 0;
   5330 };
   5331 
   5332 
   5333 class UnreachableObjectsFilter : public HeapObjectsFilter {
   5334  public:
   5335   explicit UnreachableObjectsFilter(Heap* heap) : heap_(heap) {
   5336     MarkReachableObjects();
   5337   }
   5338 
   5339   ~UnreachableObjectsFilter() {
   5340     for (auto it : reachable_) {
   5341       delete it.second;
   5342       it.second = nullptr;
   5343     }
   5344   }
   5345 
   5346   bool SkipObject(HeapObject* object) {
   5347     if (object->IsFiller()) return true;
   5348     MemoryChunk* chunk = MemoryChunk::FromAddress(object->address());
   5349     if (reachable_.count(chunk) == 0) return true;
   5350     return reachable_[chunk]->count(object) == 0;
   5351   }
   5352 
   5353  private:
   5354   bool MarkAsReachable(HeapObject* object) {
   5355     MemoryChunk* chunk = MemoryChunk::FromAddress(object->address());
   5356     if (reachable_.count(chunk) == 0) {
   5357       reachable_[chunk] = new std::unordered_set<HeapObject*>();
   5358     }
   5359     if (reachable_[chunk]->count(object)) return false;
   5360     reachable_[chunk]->insert(object);
   5361     return true;
   5362   }
   5363 
   5364   class MarkingVisitor : public ObjectVisitor, public RootVisitor {
   5365    public:
   5366     explicit MarkingVisitor(UnreachableObjectsFilter* filter)
   5367         : filter_(filter) {}
   5368 
   5369     void VisitPointers(HeapObject* host, Object** start,
   5370                        Object** end) override {
   5371       MarkPointers(reinterpret_cast<MaybeObject**>(start),
   5372                    reinterpret_cast<MaybeObject**>(end));
   5373     }
   5374 
   5375     void VisitPointers(HeapObject* host, MaybeObject** start,
   5376                        MaybeObject** end) final {
   5377       MarkPointers(start, end);
   5378     }
   5379 
   5380     void VisitRootPointers(Root root, const char* description, Object** start,
   5381                            Object** end) override {
   5382       MarkPointers(reinterpret_cast<MaybeObject**>(start),
   5383                    reinterpret_cast<MaybeObject**>(end));
   5384     }
   5385 
   5386     void TransitiveClosure() {
   5387       while (!marking_stack_.empty()) {
   5388         HeapObject* obj = marking_stack_.back();
   5389         marking_stack_.pop_back();
   5390         obj->Iterate(this);
   5391       }
   5392     }
   5393 
   5394    private:
   5395     void MarkPointers(MaybeObject** start, MaybeObject** end) {
   5396       // Treat weak references as strong.
   5397       for (MaybeObject** p = start; p < end; p++) {
   5398         HeapObject* heap_object;
   5399         if ((*p)->ToStrongOrWeakHeapObject(&heap_object)) {
   5400           if (filter_->MarkAsReachable(heap_object)) {
   5401             marking_stack_.push_back(heap_object);
   5402           }
   5403         }
   5404       }
   5405     }
   5406     UnreachableObjectsFilter* filter_;
   5407     std::vector<HeapObject*> marking_stack_;
   5408   };
   5409 
   5410   friend class MarkingVisitor;
   5411 
   5412   void MarkReachableObjects() {
   5413     MarkingVisitor visitor(this);
   5414     heap_->IterateRoots(&visitor, VISIT_ALL);
   5415     visitor.TransitiveClosure();
   5416   }
   5417 
   5418   Heap* heap_;
   5419   DisallowHeapAllocation no_allocation_;
   5420   std::unordered_map<MemoryChunk*, std::unordered_set<HeapObject*>*> reachable_;
   5421 };
   5422 
   5423 HeapIterator::HeapIterator(Heap* heap,
   5424                            HeapIterator::HeapObjectsFiltering filtering)
   5425     : no_heap_allocation_(),
   5426       heap_(heap),
   5427       filtering_(filtering),
   5428       filter_(nullptr),
   5429       space_iterator_(nullptr),
   5430       object_iterator_(nullptr) {
   5431   heap_->MakeHeapIterable();
   5432   heap_->heap_iterator_start();
   5433   // Start the iteration.
   5434   space_iterator_ = new SpaceIterator(heap_);
   5435   switch (filtering_) {
   5436     case kFilterUnreachable:
   5437       filter_ = new UnreachableObjectsFilter(heap_);
   5438       break;
   5439     default:
   5440       break;
   5441   }
   5442   object_iterator_ = space_iterator_->next()->GetObjectIterator();
   5443 }
   5444 
   5445 
   5446 HeapIterator::~HeapIterator() {
   5447   heap_->heap_iterator_end();
   5448 #ifdef DEBUG
   5449   // Assert that in filtering mode we have iterated through all
   5450   // objects. Otherwise, heap will be left in an inconsistent state.
   5451   if (filtering_ != kNoFiltering) {
   5452     DCHECK_NULL(object_iterator_);
   5453   }
   5454 #endif
   5455   delete space_iterator_;
   5456   delete filter_;
   5457 }
   5458 
   5459 
   5460 HeapObject* HeapIterator::next() {
   5461   if (filter_ == nullptr) return NextObject();
   5462 
   5463   HeapObject* obj = NextObject();
   5464   while ((obj != nullptr) && (filter_->SkipObject(obj))) obj = NextObject();
   5465   return obj;
   5466 }
   5467 
   5468 
   5469 HeapObject* HeapIterator::NextObject() {
   5470   // No iterator means we are done.
   5471   if (object_iterator_.get() == nullptr) return nullptr;
   5472 
   5473   if (HeapObject* obj = object_iterator_.get()->Next()) {
   5474     // If the current iterator has more objects we are fine.
   5475     return obj;
   5476   } else {
   5477     // Go though the spaces looking for one that has objects.
   5478     while (space_iterator_->has_next()) {
   5479       object_iterator_ = space_iterator_->next()->GetObjectIterator();
   5480       if (HeapObject* obj = object_iterator_.get()->Next()) {
   5481         return obj;
   5482       }
   5483     }
   5484   }
   5485   // Done with the last space.
   5486   object_iterator_.reset(nullptr);
   5487   return nullptr;
   5488 }
   5489 
   5490 
   5491 void Heap::UpdateTotalGCTime(double duration) {
   5492   if (FLAG_trace_gc_verbose) {
   5493     total_gc_time_ms_ += duration;
   5494   }
   5495 }
   5496 
   5497 void Heap::ExternalStringTable::CleanUpNewSpaceStrings() {
   5498   int last = 0;
   5499   Isolate* isolate = heap_->isolate();
   5500   for (size_t i = 0; i < new_space_strings_.size(); ++i) {
   5501     Object* o = new_space_strings_[i];
   5502     if (o->IsTheHole(isolate)) {
   5503       continue;
   5504     }
   5505     // The real external string is already in one of these vectors and was or
   5506     // will be processed. Re-processing it will add a duplicate to the vector.
   5507     if (o->IsThinString()) continue;
   5508     DCHECK(o->IsExternalString());
   5509     if (InNewSpace(o)) {
   5510       new_space_strings_[last++] = o;
   5511     } else {
   5512       old_space_strings_.push_back(o);
   5513     }
   5514   }
   5515   new_space_strings_.resize(last);
   5516 }
   5517 
   5518 void Heap::ExternalStringTable::CleanUpAll() {
   5519   CleanUpNewSpaceStrings();
   5520   int last = 0;
   5521   Isolate* isolate = heap_->isolate();
   5522   for (size_t i = 0; i < old_space_strings_.size(); ++i) {
   5523     Object* o = old_space_strings_[i];
   5524     if (o->IsTheHole(isolate)) {
   5525       continue;
   5526     }
   5527     // The real external string is already in one of these vectors and was or
   5528     // will be processed. Re-processing it will add a duplicate to the vector.
   5529     if (o->IsThinString()) continue;
   5530     DCHECK(o->IsExternalString());
   5531     DCHECK(!InNewSpace(o));
   5532     old_space_strings_[last++] = o;
   5533   }
   5534   old_space_strings_.resize(last);
   5535 #ifdef VERIFY_HEAP
   5536   if (FLAG_verify_heap) {
   5537     Verify();
   5538   }
   5539 #endif
   5540 }
   5541 
   5542 void Heap::ExternalStringTable::TearDown() {
   5543   for (size_t i = 0; i < new_space_strings_.size(); ++i) {
   5544     Object* o = new_space_strings_[i];
   5545     // Dont finalize thin strings.
   5546     if (o->IsThinString()) continue;
   5547     heap_->FinalizeExternalString(ExternalString::cast(o));
   5548   }
   5549   new_space_strings_.clear();
   5550   for (size_t i = 0; i < old_space_strings_.size(); ++i) {
   5551     Object* o = old_space_strings_[i];
   5552     // Dont finalize thin strings.
   5553     if (o->IsThinString()) continue;
   5554     heap_->FinalizeExternalString(ExternalString::cast(o));
   5555   }
   5556   old_space_strings_.clear();
   5557 }
   5558 
   5559 
   5560 void Heap::RememberUnmappedPage(Address page, bool compacted) {
   5561   // Tag the page pointer to make it findable in the dump file.
   5562   if (compacted) {
   5563     page ^= 0xC1EAD & (Page::kPageSize - 1);  // Cleared.
   5564   } else {
   5565     page ^= 0x1D1ED & (Page::kPageSize - 1);  // I died.
   5566   }
   5567   remembered_unmapped_pages_[remembered_unmapped_pages_index_] = page;
   5568   remembered_unmapped_pages_index_++;
   5569   remembered_unmapped_pages_index_ %= kRememberedUnmappedPages;
   5570 }
   5571 
   5572 void Heap::RegisterStrongRoots(Object** start, Object** end) {
   5573   StrongRootsList* list = new StrongRootsList();
   5574   list->next = strong_roots_list_;
   5575   list->start = start;
   5576   list->end = end;
   5577   strong_roots_list_ = list;
   5578 }
   5579 
   5580 
   5581 void Heap::UnregisterStrongRoots(Object** start) {
   5582   StrongRootsList* prev = nullptr;
   5583   StrongRootsList* list = strong_roots_list_;
   5584   while (list != nullptr) {
   5585     StrongRootsList* next = list->next;
   5586     if (list->start == start) {
   5587       if (prev) {
   5588         prev->next = next;
   5589       } else {
   5590         strong_roots_list_ = next;
   5591       }
   5592       delete list;
   5593     } else {
   5594       prev = list;
   5595     }
   5596     list = next;
   5597   }
   5598 }
   5599 
   5600 bool Heap::IsDeserializeLazyHandler(Code* code) {
   5601   return (code == deserialize_lazy_handler() ||
   5602           code == deserialize_lazy_handler_wide() ||
   5603           code == deserialize_lazy_handler_extra_wide());
   5604 }
   5605 
   5606 void Heap::SetDeserializeLazyHandler(Code* code) {
   5607   set_deserialize_lazy_handler(code);
   5608 }
   5609 
   5610 void Heap::SetDeserializeLazyHandlerWide(Code* code) {
   5611   set_deserialize_lazy_handler_wide(code);
   5612 }
   5613 
   5614 void Heap::SetDeserializeLazyHandlerExtraWide(Code* code) {
   5615   set_deserialize_lazy_handler_extra_wide(code);
   5616 }
   5617 
   5618 void Heap::SetBuiltinsConstantsTable(FixedArray* cache) {
   5619   set_builtins_constants_table(cache);
   5620 }
   5621 
   5622 size_t Heap::NumberOfTrackedHeapObjectTypes() {
   5623   return ObjectStats::OBJECT_STATS_COUNT;
   5624 }
   5625 
   5626 
   5627 size_t Heap::ObjectCountAtLastGC(size_t index) {
   5628   if (live_object_stats_ == nullptr || index >= ObjectStats::OBJECT_STATS_COUNT)
   5629     return 0;
   5630   return live_object_stats_->object_count_last_gc(index);
   5631 }
   5632 
   5633 
   5634 size_t Heap::ObjectSizeAtLastGC(size_t index) {
   5635   if (live_object_stats_ == nullptr || index >= ObjectStats::OBJECT_STATS_COUNT)
   5636     return 0;
   5637   return live_object_stats_->object_size_last_gc(index);
   5638 }
   5639 
   5640 
   5641 bool Heap::GetObjectTypeName(size_t index, const char** object_type,
   5642                              const char** object_sub_type) {
   5643   if (index >= ObjectStats::OBJECT_STATS_COUNT) return false;
   5644 
   5645   switch (static_cast<int>(index)) {
   5646 #define COMPARE_AND_RETURN_NAME(name) \
   5647   case name:                          \
   5648     *object_type = #name;             \
   5649     *object_sub_type = "";            \
   5650     return true;
   5651     INSTANCE_TYPE_LIST(COMPARE_AND_RETURN_NAME)
   5652 #undef COMPARE_AND_RETURN_NAME
   5653 
   5654 #define COMPARE_AND_RETURN_NAME(name)                       \
   5655   case ObjectStats::FIRST_VIRTUAL_TYPE + ObjectStats::name: \
   5656     *object_type = #name;                                   \
   5657     *object_sub_type = "";                                  \
   5658     return true;
   5659     VIRTUAL_INSTANCE_TYPE_LIST(COMPARE_AND_RETURN_NAME)
   5660 #undef COMPARE_AND_RETURN_NAME
   5661   }
   5662   return false;
   5663 }
   5664 
   5665 size_t Heap::NumberOfNativeContexts() {
   5666   int result = 0;
   5667   Object* context = native_contexts_list();
   5668   while (!context->IsUndefined(isolate())) {
   5669     ++result;
   5670     Context* native_context = Context::cast(context);
   5671     context = native_context->next_context_link();
   5672   }
   5673   return result;
   5674 }
   5675 
   5676 size_t Heap::NumberOfDetachedContexts() {
   5677   // The detached_contexts() array has two entries per detached context.
   5678   return detached_contexts()->length() / 2;
   5679 }
   5680 
   5681 const char* AllocationSpaceName(AllocationSpace space) {
   5682   switch (space) {
   5683     case NEW_SPACE:
   5684       return "NEW_SPACE";
   5685     case OLD_SPACE:
   5686       return "OLD_SPACE";
   5687     case CODE_SPACE:
   5688       return "CODE_SPACE";
   5689     case MAP_SPACE:
   5690       return "MAP_SPACE";
   5691     case LO_SPACE:
   5692       return "LO_SPACE";
   5693     case NEW_LO_SPACE:
   5694       return "NEW_LO_SPACE";
   5695     case RO_SPACE:
   5696       return "RO_SPACE";
   5697     default:
   5698       UNREACHABLE();
   5699   }
   5700   return nullptr;
   5701 }
   5702 
   5703 void VerifyPointersVisitor::VisitPointers(HeapObject* host, Object** start,
   5704                                           Object** end) {
   5705   VerifyPointers(host, reinterpret_cast<MaybeObject**>(start),
   5706                  reinterpret_cast<MaybeObject**>(end));
   5707 }
   5708 
   5709 void VerifyPointersVisitor::VisitPointers(HeapObject* host, MaybeObject** start,
   5710                                           MaybeObject** end) {
   5711   VerifyPointers(host, start, end);
   5712 }
   5713 
   5714 void VerifyPointersVisitor::VisitRootPointers(Root root,
   5715                                               const char* description,
   5716                                               Object** start, Object** end) {
   5717   VerifyPointers(nullptr, reinterpret_cast<MaybeObject**>(start),
   5718                  reinterpret_cast<MaybeObject**>(end));
   5719 }
   5720 
   5721 void VerifyPointersVisitor::VerifyPointers(HeapObject* host,
   5722                                            MaybeObject** start,
   5723                                            MaybeObject** end) {
   5724   for (MaybeObject** current = start; current < end; current++) {
   5725     HeapObject* object;
   5726     if ((*current)->ToStrongOrWeakHeapObject(&object)) {
   5727       CHECK(heap_->Contains(object));
   5728       CHECK(object->map()->IsMap());
   5729     } else {
   5730       CHECK((*current)->IsSmi() || (*current)->IsClearedWeakHeapObject());
   5731     }
   5732   }
   5733 }
   5734 
   5735 void VerifySmisVisitor::VisitRootPointers(Root root, const char* description,
   5736                                           Object** start, Object** end) {
   5737   for (Object** current = start; current < end; current++) {
   5738     CHECK((*current)->IsSmi());
   5739   }
   5740 }
   5741 
   5742 bool Heap::AllowedToBeMigrated(HeapObject* obj, AllocationSpace dst) {
   5743   // Object migration is governed by the following rules:
   5744   //
   5745   // 1) Objects in new-space can be migrated to the old space
   5746   //    that matches their target space or they stay in new-space.
   5747   // 2) Objects in old-space stay in the same space when migrating.
   5748   // 3) Fillers (two or more words) can migrate due to left-trimming of
   5749   //    fixed arrays in new-space or old space.
   5750   // 4) Fillers (one word) can never migrate, they are skipped by
   5751   //    incremental marking explicitly to prevent invalid pattern.
   5752   //
   5753   // Since this function is used for debugging only, we do not place
   5754   // asserts here, but check everything explicitly.
   5755   if (obj->map() == ReadOnlyRoots(this).one_pointer_filler_map()) return false;
   5756   InstanceType type = obj->map()->instance_type();
   5757   MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
   5758   AllocationSpace src = chunk->owner()->identity();
   5759   switch (src) {
   5760     case NEW_SPACE:
   5761       return dst == NEW_SPACE || dst == OLD_SPACE;
   5762     case OLD_SPACE:
   5763       return dst == OLD_SPACE;
   5764     case CODE_SPACE:
   5765       return dst == CODE_SPACE && type == CODE_TYPE;
   5766     case MAP_SPACE:
   5767     case LO_SPACE:
   5768     case NEW_LO_SPACE:
   5769     case RO_SPACE:
   5770       return false;
   5771   }
   5772   UNREACHABLE();
   5773 }
   5774 
   5775 void Heap::CreateObjectStats() {
   5776   if (V8_LIKELY(FLAG_gc_stats == 0)) return;
   5777   if (!live_object_stats_) {
   5778     live_object_stats_ = new ObjectStats(this);
   5779   }
   5780   if (!dead_object_stats_) {
   5781     dead_object_stats_ = new ObjectStats(this);
   5782   }
   5783 }
   5784 
   5785 void AllocationObserver::AllocationStep(int bytes_allocated,
   5786                                         Address soon_object, size_t size) {
   5787   DCHECK_GE(bytes_allocated, 0);
   5788   bytes_to_next_step_ -= bytes_allocated;
   5789   if (bytes_to_next_step_ <= 0) {
   5790     Step(static_cast<int>(step_size_ - bytes_to_next_step_), soon_object, size);
   5791     step_size_ = GetNextStepSize();
   5792     bytes_to_next_step_ = step_size_;
   5793   }
   5794   DCHECK_GE(bytes_to_next_step_, 0);
   5795 }
   5796 
   5797 namespace {
   5798 
   5799 Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
   5800   MapWord map_word = object->map_word();
   5801   return map_word.IsForwardingAddress() ? map_word.ToForwardingAddress()->map()
   5802                                         : map_word.ToMap();
   5803 }
   5804 
   5805 int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
   5806   return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
   5807 }
   5808 
   5809 Code* GcSafeCastToCode(Heap* heap, HeapObject* object, Address inner_pointer) {
   5810   Code* code = reinterpret_cast<Code*>(object);
   5811   DCHECK_NOT_NULL(code);
   5812   DCHECK(heap->GcSafeCodeContains(code, inner_pointer));
   5813   return code;
   5814 }
   5815 
   5816 }  // namespace
   5817 
   5818 bool Heap::GcSafeCodeContains(HeapObject* code, Address addr) {
   5819   Map* map = GcSafeMapOfCodeSpaceObject(code);
   5820   DCHECK(map == ReadOnlyRoots(this).code_map());
   5821   if (InstructionStream::TryLookupCode(isolate(), addr) == code) return true;
   5822   Address start = code->address();
   5823   Address end = code->address() + code->SizeFromMap(map);
   5824   return start <= addr && addr < end;
   5825 }
   5826 
   5827 Code* Heap::GcSafeFindCodeForInnerPointer(Address inner_pointer) {
   5828   Code* code = InstructionStream::TryLookupCode(isolate(), inner_pointer);
   5829   if (code != nullptr) return code;
   5830 
   5831   // Check if the inner pointer points into a large object chunk.
   5832   LargePage* large_page = lo_space()->FindPage(inner_pointer);
   5833   if (large_page != nullptr) {
   5834     return GcSafeCastToCode(this, large_page->GetObject(), inner_pointer);
   5835   }
   5836 
   5837   DCHECK(code_space()->Contains(inner_pointer));
   5838 
   5839   // Iterate through the page until we reach the end or find an object starting
   5840   // after the inner pointer.
   5841   Page* page = Page::FromAddress(inner_pointer);
   5842   DCHECK_EQ(page->owner(), code_space());
   5843   mark_compact_collector()->sweeper()->EnsurePageIsIterable(page);
   5844 
   5845   Address addr = page->skip_list()->StartFor(inner_pointer);
   5846   Address top = code_space()->top();
   5847   Address limit = code_space()->limit();
   5848 
   5849   while (true) {
   5850     if (addr == top && addr != limit) {
   5851       addr = limit;
   5852       continue;
   5853     }
   5854 
   5855     HeapObject* obj = HeapObject::FromAddress(addr);
   5856     int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
   5857     Address next_addr = addr + obj_size;
   5858     if (next_addr > inner_pointer)
   5859       return GcSafeCastToCode(this, obj, inner_pointer);
   5860     addr = next_addr;
   5861   }
   5862 }
   5863 
   5864 void Heap::WriteBarrierForCodeSlow(Code* code) {
   5865   for (RelocIterator it(code, RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT));
   5866        !it.done(); it.next()) {
   5867     GenerationalBarrierForCode(code, it.rinfo(), it.rinfo()->target_object());
   5868     MarkingBarrierForCode(code, it.rinfo(), it.rinfo()->target_object());
   5869   }
   5870 }
   5871 
   5872 void Heap::GenerationalBarrierSlow(HeapObject* object, Address slot,
   5873                                    HeapObject* value) {
   5874   Heap* heap = Heap::FromWritableHeapObject(object);
   5875   heap->store_buffer()->InsertEntry(slot);
   5876 }
   5877 
   5878 void Heap::GenerationalBarrierForElementsSlow(Heap* heap, FixedArray* array,
   5879                                               int offset, int length) {
   5880   for (int i = 0; i < length; i++) {
   5881     if (!InNewSpace(array->get(offset + i))) continue;
   5882     heap->store_buffer()->InsertEntry(
   5883         reinterpret_cast<Address>(array->RawFieldOfElementAt(offset + i)));
   5884   }
   5885 }
   5886 
   5887 void Heap::GenerationalBarrierForCodeSlow(Code* host, RelocInfo* rinfo,
   5888                                           HeapObject* object) {
   5889   DCHECK(InNewSpace(object));
   5890   Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host));
   5891   RelocInfo::Mode rmode = rinfo->rmode();
   5892   Address addr = rinfo->pc();
   5893   SlotType slot_type = SlotTypeForRelocInfoMode(rmode);
   5894   if (rinfo->IsInConstantPool()) {
   5895     addr = rinfo->constant_pool_entry_address();
   5896     if (RelocInfo::IsCodeTargetMode(rmode)) {
   5897       slot_type = CODE_ENTRY_SLOT;
   5898     } else {
   5899       DCHECK(RelocInfo::IsEmbeddedObject(rmode));
   5900       slot_type = OBJECT_SLOT;
   5901     }
   5902   }
   5903   RememberedSet<OLD_TO_NEW>::InsertTyped(
   5904       source_page, reinterpret_cast<Address>(host), slot_type, addr);
   5905 }
   5906 
   5907 void Heap::MarkingBarrierSlow(HeapObject* object, Address slot,
   5908                               HeapObject* value) {
   5909   Heap* heap = Heap::FromWritableHeapObject(object);
   5910   heap->incremental_marking()->RecordWriteSlow(
   5911       object, reinterpret_cast<HeapObjectReference**>(slot), value);
   5912 }
   5913 
   5914 void Heap::MarkingBarrierForElementsSlow(Heap* heap, HeapObject* object) {
   5915   if (FLAG_concurrent_marking ||
   5916       heap->incremental_marking()->marking_state()->IsBlack(object)) {
   5917     heap->incremental_marking()->RevisitObject(object);
   5918   }
   5919 }
   5920 
   5921 void Heap::MarkingBarrierForCodeSlow(Code* host, RelocInfo* rinfo,
   5922                                      HeapObject* object) {
   5923   Heap* heap = Heap::FromWritableHeapObject(host);
   5924   DCHECK(heap->incremental_marking()->IsMarking());
   5925   heap->incremental_marking()->RecordWriteIntoCode(host, rinfo, object);
   5926 }
   5927 
   5928 bool Heap::PageFlagsAreConsistent(HeapObject* object) {
   5929   Heap* heap = Heap::FromWritableHeapObject(object);
   5930   MemoryChunk* chunk = MemoryChunk::FromHeapObject(object);
   5931   heap_internals::MemoryChunk* slim_chunk =
   5932       heap_internals::MemoryChunk::FromHeapObject(object);
   5933 
   5934   const bool generation_consistency =
   5935       chunk->owner()->identity() != NEW_SPACE ||
   5936       (chunk->InNewSpace() && slim_chunk->InNewSpace());
   5937   const bool marking_consistency =
   5938       !heap->incremental_marking()->IsMarking() ||
   5939       (chunk->IsFlagSet(MemoryChunk::INCREMENTAL_MARKING) &&
   5940        slim_chunk->IsMarking());
   5941 
   5942   return generation_consistency && marking_consistency;
   5943 }
   5944 
   5945 static_assert(MemoryChunk::Flag::INCREMENTAL_MARKING ==
   5946                   heap_internals::MemoryChunk::kMarkingBit,
   5947               "Incremental marking flag inconsistent");
   5948 static_assert(MemoryChunk::Flag::IN_FROM_SPACE ==
   5949                   heap_internals::MemoryChunk::kFromSpaceBit,
   5950               "From space flag inconsistent");
   5951 static_assert(MemoryChunk::Flag::IN_TO_SPACE ==
   5952                   heap_internals::MemoryChunk::kToSpaceBit,
   5953               "To space flag inconsistent");
   5954 static_assert(MemoryChunk::kFlagsOffset ==
   5955                   heap_internals::MemoryChunk::kFlagsOffset,
   5956               "Flag offset inconsistent");
   5957 
   5958 void Heap::SetEmbedderStackStateForNextFinalizaton(
   5959     EmbedderHeapTracer::EmbedderStackState stack_state) {
   5960   local_embedder_heap_tracer()->SetEmbedderStackStateForNextFinalization(
   5961       stack_state);
   5962 }
   5963 
   5964 }  // namespace internal
   5965 }  // namespace v8
   5966