heap.h 86.5 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5 6
#ifndef V8_HEAP_HEAP_H_
#define V8_HEAP_HEAP_H_
7

8
#include <cmath>
9
#include <map>
10
#include <unordered_map>
11
#include <unordered_set>
12
#include <vector>
13

14 15
// Clients of this interface shouldn't depend on lots of heap internals.
// Do not include anything from src/heap here!
16
#include "include/v8-internal.h"
17
#include "include/v8.h"
18
#include "src/accessors.h"
19 20
#include "src/allocation.h"
#include "src/assert-scope.h"
lpy's avatar
lpy committed
21
#include "src/base/atomic-utils.h"
22
#include "src/globals.h"
23
#include "src/heap-symbols.h"
24
#include "src/objects.h"
25
#include "src/objects/allocation-site.h"
Marja Hölttä's avatar
Marja Hölttä committed
26
#include "src/objects/fixed-array.h"
27
#include "src/objects/heap-object.h"
28
#include "src/objects/smi.h"
29
#include "src/objects/string-table.h"
30
#include "src/roots.h"
31
#include "src/visitors.h"
32

33
namespace v8 {
34 35 36 37 38

namespace debug {
typedef void (*OutOfMemoryCallback)(void* data);
}  // namespace debug

39
namespace internal {
40

41 42 43 44 45
namespace heap {
class HeapTester;
class TestMemoryAllocatorScope;
}  // namespace heap

46
class ObjectBoilerplateDescription;
47
class BytecodeArray;
48
class CodeDataContainer;
49 50
class DeoptimizationData;
class HandlerTable;
51
class IncrementalMarking;
52
class JSArrayBuffer;
53
class ExternalString;
54 55
using v8::MemoryPressureLevel;

56
class AllocationObserver;
57
class ArrayBufferCollector;
58
class ArrayBufferTracker;
59
class CodeLargeObjectSpace;
60
class ConcurrentMarking;
61 62 63
class GCIdleTimeHandler;
class GCIdleTimeHeapState;
class GCTracer;
64
class HeapController;
65
class HeapObjectAllocationTracker;
66
class HeapObjectsFilter;
67
class HeapStats;
68
class HistogramTimer;
69
class Isolate;
70
class JSFinalizationGroup;
71
class LocalEmbedderHeapTracer;
mlippautz's avatar
mlippautz committed
72
class MemoryAllocator;
73
class MemoryReducer;
74
class MinorMarkCompactCollector;
75
class ObjectIterator;
76
class ObjectStats;
77
class Page;
mlippautz's avatar
mlippautz committed
78
class PagedSpace;
79
class ReadOnlyHeap;
80
class RootVisitor;
ulan's avatar
ulan committed
81
class ScavengeJob;
82
class Scavenger;
83
class ScavengerCollector;
mlippautz's avatar
mlippautz committed
84
class Space;
85
class StoreBuffer;
86
class StressScavengeObserver;
87
class TimedHistogram;
88
class TracePossibleWrapperReporter;
89
class WeakObjectRetainer;
90

91 92 93 94
enum ArrayStorageAllocationMode {
  DONT_INITIALIZE_ARRAY_ELEMENTS,
  INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE
};
95

96 97
enum class ClearRecordedSlots { kYes, kNo };

98 99
enum class ClearFreedMemoryMode { kClearFreedMemory, kDontClearFreedMemory };

100 101
enum ExternalBackingStoreType { kArrayBuffer, kExternalString, kNumTypes };

102 103 104 105
enum class FixedArrayVisitationMode { kRegular, kIncremental };

enum class TraceRetainingPathMode { kEnabled, kDisabled };

106
enum class RetainingPathOption { kDefault, kTrackEphemeronPath };
107

108
enum class GarbageCollectionReason {
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
  kUnknown = 0,
  kAllocationFailure = 1,
  kAllocationLimit = 2,
  kContextDisposal = 3,
  kCountersExtension = 4,
  kDebugger = 5,
  kDeserializer = 6,
  kExternalMemoryPressure = 7,
  kFinalizeMarkingViaStackGuard = 8,
  kFinalizeMarkingViaTask = 9,
  kFullHashtable = 10,
  kHeapProfiler = 11,
  kIdleTask = 12,
  kLastResort = 13,
  kLowMemoryNotification = 14,
  kMakeHeapIterable = 15,
  kMemoryPressure = 16,
  kMemoryReducer = 17,
  kRuntime = 18,
  kSamplingProfiler = 19,
  kSnapshotCreator = 20,
130
  kTesting = 21,
131
  kExternalFinalize = 22
132 133 134
  // If you add new items here, then update the incremental_marking_reason,
  // mark_compact_reason, and scavenge_reason counters in counters.h.
  // Also update src/tools/metrics/histograms/histograms.xml in chromium.
135 136
};

137 138 139 140 141 142 143 144 145 146 147
enum class YoungGenerationHandling {
  kRegularScavenge = 0,
  kFastPromotionDuringScavenge = 1,
  // Histogram::InspectConstructionArguments in chromium requires us to have at
  // least three buckets.
  kUnusedBucket = 2,
  // If you add new items here, then update the young_generation_handling in
  // counters.h.
  // Also update src/tools/metrics/histograms/histograms.xml in chromium.
};

148 149
enum class GCIdleTimeAction : uint8_t;

150 151
class AllocationResult {
 public:
152 153 154 155
  static inline AllocationResult Retry(AllocationSpace space = NEW_SPACE) {
    return AllocationResult(space);
  }

156
  // Implicit constructor from Object.
157
  AllocationResult(Object object)  // NOLINT
158 159 160 161 162 163 164 165 166
      : object_(object) {
    // AllocationResults can't return Smis, which are used to represent
    // failure and the space to retry in.
    CHECK(!object->IsSmi());
  }

  AllocationResult() : object_(Smi::FromInt(NEW_SPACE)) {}

  inline bool IsRetry() { return object_->IsSmi(); }
167
  inline HeapObject ToObjectChecked();
168
  inline AllocationSpace RetrySpace();
169

170
  template <typename T>
171 172 173 174 175 176
  bool To(T* obj) {
    if (IsRetry()) return false;
    *obj = T::cast(object_);
    return true;
  }

177 178 179 180
 private:
  explicit AllocationResult(AllocationSpace space)
      : object_(Smi::FromInt(static_cast<int>(space))) {}

181
  Object object_;
182 183
};

184
STATIC_ASSERT(sizeof(AllocationResult) == kSystemPointerSize);
185 186 187 188 189 190 191

#ifdef DEBUG
struct CommentStatistic {
  const char* comment;
  int size;
  int count;
  void Clear() {
192
    comment = nullptr;
193 194 195 196 197 198 199 200
    size = 0;
    count = 0;
  }
  // Must be small, since an iteration is used for lookup.
  static const int kMaxComments = 64;
};
#endif

201
class Heap {
202
 public:
203 204
  enum FindMementoMode { kForRuntime, kForGC };

205 206 207 208 209 210 211
  enum HeapState {
    NOT_IN_GC,
    SCAVENGE,
    MARK_COMPACT,
    MINOR_MARK_COMPACT,
    TEAR_DOWN
  };
212

213
  using PretenuringFeedbackMap =
214
      std::unordered_map<AllocationSite, size_t, Object::Hasher>;
215

216
  // Taking this mutex prevents the GC from entering a phase that relocates
217
  // object references.
218
  base::Mutex* relocation_mutex() { return &relocation_mutex_; }
219

220 221 222 223 224 225 226
  // Support for partial snapshots.  After calling this we have a linear
  // space to write objects in each space.
  struct Chunk {
    uint32_t size;
    Address start;
    Address end;
  };
227
  typedef std::vector<Chunk> Reservation;
228

229 230
  static const int kInitalOldGenerationLimitFactor = 2;

231 232 233 234 235
#if V8_OS_ANDROID
  // Don't apply pointer multiplier on Android since it has no swap space and
  // should instead adapt it's heap size based on available physical memory.
  static const int kPointerMultiplier = 1;
#else
236 237
  // TODO(ishell): kSystePointerMultiplier?
  static const int kPointerMultiplier = i::kSystemPointerSize / 4;
238 239
#endif

240
  // Semi-space size needs to be a multiple of page size.
241
  static const size_t kMinSemiSpaceSizeInKB =
242
      1 * kPointerMultiplier * ((1 << kPageSizeBits) / KB);
243
  static const size_t kMaxSemiSpaceSizeInKB =
244
      16 * kPointerMultiplier * ((1 << kPageSizeBits) / KB);
245 246 247 248

  static const int kTraceRingBufferSize = 512;
  static const int kStacktraceBufferSize = 512;

249 250 251
  static const int kNoGCFlags = 0;
  static const int kReduceMemoryFootprintMask = 1;

252
  // The minimum size of a HeapObject on the heap.
253
  static const int kMinObjectSizeInTaggedWords = 2;
254

255
  static const int kMinPromotedPercentForFastPromotionMode = 90;
256

257
  STATIC_ASSERT(static_cast<int>(RootIndex::kUndefinedValue) ==
258
                Internals::kUndefinedValueRootIndex);
259 260 261 262 263 264 265 266 267 268
  STATIC_ASSERT(static_cast<int>(RootIndex::kTheHoleValue) ==
                Internals::kTheHoleValueRootIndex);
  STATIC_ASSERT(static_cast<int>(RootIndex::kNullValue) ==
                Internals::kNullValueRootIndex);
  STATIC_ASSERT(static_cast<int>(RootIndex::kTrueValue) ==
                Internals::kTrueValueRootIndex);
  STATIC_ASSERT(static_cast<int>(RootIndex::kFalseValue) ==
                Internals::kFalseValueRootIndex);
  STATIC_ASSERT(static_cast<int>(RootIndex::kempty_string) ==
                Internals::kEmptyStringRootIndex);
269 270 271 272 273 274 275 276

  // Calculates the maximum amount of filler that could be required by the
  // given alignment.
  static int GetMaximumFillToAlign(AllocationAlignment alignment);
  // Calculates the actual amount of filler required for a given address at the
  // given alignment.
  static int GetFillToAlign(Address address, AllocationAlignment alignment);

277
  void FatalProcessOutOfMemory(const char* location);
278 279 280 281 282 283 284 285 286 287 288 289

  // Checks whether the space is valid.
  static bool IsValidAllocationSpace(AllocationSpace space);

  // Zapping is needed for verify heap, and always done in debug builds.
  static inline bool ShouldZapGarbage() {
#ifdef DEBUG
    return true;
#else
#ifdef VERIFY_HEAP
    return FLAG_verify_heap;
#else
290
    return false;
291 292
#endif
#endif
293 294
  }

295 296 297 298
  static uintptr_t ZapValue() {
    return FLAG_clear_free_memory ? kClearedFreeMemoryValue : kZapValue;
  }

299 300 301 302 303
  static inline bool IsYoungGenerationCollector(GarbageCollector collector) {
    return collector == SCAVENGER || collector == MINOR_MARK_COMPACTOR;
  }

  static inline GarbageCollector YoungGenerationCollector() {
304
#if ENABLE_MINOR_MC
305
    return (FLAG_minor_mc) ? MINOR_MARK_COMPACTOR : SCAVENGER;
306 307 308
#else
    return SCAVENGER;
#endif  // ENABLE_MINOR_MC
309 310 311 312 313 314 315 316 317 318 319 320 321 322
  }

  static inline const char* CollectorName(GarbageCollector collector) {
    switch (collector) {
      case SCAVENGER:
        return "Scavenger";
      case MARK_COMPACTOR:
        return "Mark-Compact";
      case MINOR_MARK_COMPACTOR:
        return "Minor Mark-Compact";
    }
    return "Unknown collector";
  }

323 324 325 326
  // Copy block of memory from src to dst. Size of block should be aligned
  // by pointer size.
  static inline void CopyBlock(Address dst, Address src, int byte_size);

327
  V8_EXPORT_PRIVATE static void WriteBarrierForCodeSlow(Code host);
328
  V8_EXPORT_PRIVATE static void GenerationalBarrierSlow(HeapObject object,
329
                                                        Address slot,
330
                                                        HeapObject value);
331
  V8_EXPORT_PRIVATE static void GenerationalBarrierForElementsSlow(
332
      Heap* heap, FixedArray array, int offset, int length);
333
  V8_EXPORT_PRIVATE static void GenerationalBarrierForCodeSlow(
334 335
      Code host, RelocInfo* rinfo, HeapObject value);
  V8_EXPORT_PRIVATE static void MarkingBarrierSlow(HeapObject object,
336
                                                   Address slot,
337
                                                   HeapObject value);
338
  V8_EXPORT_PRIVATE static void MarkingBarrierForElementsSlow(
339
      Heap* heap, HeapObject object);
340
  V8_EXPORT_PRIVATE static void MarkingBarrierForCodeSlow(Code host,
341
                                                          RelocInfo* rinfo,
342
                                                          HeapObject value);
343
  V8_EXPORT_PRIVATE static void MarkingBarrierForDescriptorArraySlow(
344 345
      Heap* heap, HeapObject host, HeapObject descriptor_array,
      int number_of_own_descriptors);
346
  V8_EXPORT_PRIVATE static bool PageFlagsAreConsistent(HeapObject object);
347

348 349 350 351
  // Notifies the heap that is ok to start marking or other activities that
  // should not happen during deserialization.
  void NotifyDeserializationComplete();

352 353 354 355
  void NotifyBootstrapComplete();

  void NotifyOldGenerationExpansion();

mlippautz's avatar
mlippautz committed
356 357 358 359
  inline Address* NewSpaceAllocationTopAddress();
  inline Address* NewSpaceAllocationLimitAddress();
  inline Address* OldSpaceAllocationTopAddress();
  inline Address* OldSpaceAllocationLimitAddress();
360

361 362
  // Move len elements within a given array from src_index index to dst_index
  // index.
363
  void MoveElements(FixedArray array, int dst_index, int src_index, int len,
364
                    WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
365

366
  // Initialize a filler object to keep the ability to iterate over the heap
367 368
  // when introducing gaps within pages. If slots could have been recorded in
  // the freed area, then pass ClearRecordedSlots::kYes as the mode. Otherwise,
369 370 371
  // pass ClearRecordedSlots::kNo. If the memory after the object header of
  // the filler should be cleared, pass in kClearFreedMemory. The default is
  // kDontClearFreedMemory.
372
  V8_EXPORT_PRIVATE HeapObject CreateFillerObjectAt(
373 374 375
      Address addr, int size, ClearRecordedSlots clear_slots_mode,
      ClearFreedMemoryMode clear_memory_mode =
          ClearFreedMemoryMode::kDontClearFreedMemory);
376

377
  template <typename T>
378
  void CreateFillerForArray(T object, int elements_to_trim, int bytes_to_trim);
379

380
  bool CanMoveObjectStart(HeapObject object);
381

382
  bool IsImmovable(HeapObject object);
383

384
  static bool IsLargeObject(HeapObject object);
385

386 387
  // Trim the given array from the left. Note that this relocates the object
  // start and hence is only valid if there is only a single reference to it.
388
  FixedArrayBase LeftTrimFixedArray(FixedArrayBase obj, int elements_to_trim);
389

390
  // Trim the given array from the right.
391
  void RightTrimFixedArray(FixedArrayBase obj, int elements_to_trim);
392
  void RightTrimWeakFixedArray(WeakFixedArray obj, int elements_to_trim);
393

394
  // Converts the given boolean condition to JavaScript boolean value.
395
  inline Oddball ToBoolean(bool condition);
396

397
  // Notify the heap that a context has been disposed.
398
  int NotifyContextDisposed(bool dependant_context);
399

400
  void set_native_contexts_list(Object object) {
401
    native_contexts_list_ = object;
402
  }
403
  Object native_contexts_list() const { return native_contexts_list_; }
404

405
  void set_allocation_sites_list(Object object) {
406 407
    allocation_sites_list_ = object;
  }
408
  Object allocation_sites_list() { return allocation_sites_list_; }
409 410

  // Used in CreateAllocationSiteStub and the (de)serializer.
411 412 413
  Address allocation_sites_list_address() {
    return reinterpret_cast<Address>(&allocation_sites_list_);
  }
414

415 416
  // Traverse all the allocaions_sites [nested_site and weak_next] in the list
  // and foreach call the visitor
417
  void ForeachAllocationSite(
418
      Object list, const std::function<void(AllocationSite)>& visitor);
419

420
  // Number of mark-sweeps.
421
  int ms_count() const { return ms_count_; }
422

423 424
  // Checks whether the given object is allowed to be migrated from it's
  // current space into the given destination space. Used for debugging.
425
  bool AllowedToBeMigrated(HeapObject object, AllocationSpace dest);
426

427
  void CheckHandleCount();
428

429 430 431
  // Number of "runtime allocations" done so far.
  uint32_t allocations_count() { return allocations_count_; }

432
  // Print short heap statistics.
433
  void PrintShortHeapStatistics();
434

435 436
  bool write_protect_code_memory() const { return write_protect_code_memory_; }

437 438 439 440 441 442 443 444 445 446 447 448
  uintptr_t code_space_memory_modification_scope_depth() {
    return code_space_memory_modification_scope_depth_;
  }

  void increment_code_space_memory_modification_scope_depth() {
    code_space_memory_modification_scope_depth_++;
  }

  void decrement_code_space_memory_modification_scope_depth() {
    code_space_memory_modification_scope_depth_--;
  }

449
  void UnprotectAndRegisterMemoryChunk(MemoryChunk* chunk);
450
  void UnprotectAndRegisterMemoryChunk(HeapObject object);
451
  void UnregisterUnprotectedMemoryChunk(MemoryChunk* chunk);
452
  V8_EXPORT_PRIVATE void ProtectUnprotectedMemoryChunks();
453 454 455 456 457 458 459 460 461 462 463 464 465

  void EnableUnprotectedMemoryChunksRegistry() {
    unprotected_memory_chunks_registry_enabled_ = true;
  }

  void DisableUnprotectedMemoryChunksRegistry() {
    unprotected_memory_chunks_registry_enabled_ = false;
  }

  bool unprotected_memory_chunks_registry_enabled() {
    return unprotected_memory_chunks_registry_enabled_;
  }

466
  inline HeapState gc_state() { return gc_state_; }
467
  void SetGCState(HeapState state);
468
  bool IsTearingDown() const { return gc_state_ == TEAR_DOWN; }
469

470
  inline bool IsInGCPostProcessing() { return gc_post_processing_depth_ > 0; }
471

472
  // If an object has an AllocationMemento trailing it, return it, otherwise
473
  // return a null AllocationMemento.
474
  template <FindMementoMode mode>
475
  inline AllocationMemento FindAllocationMemento(Map map, HeapObject object);
476

477
  // Returns false if not able to reserve.
478
  bool ReserveSpace(Reservation* reservations, std::vector<Address>* maps);
479

480 481 482 483
  //
  // Support for the API.
  //

484
  void CreateApiObjects();
485

486
  // Implements the corresponding V8 API function.
487
  bool IdleNotification(double deadline_in_seconds);
488
  bool IdleNotification(int idle_time_in_ms);
489

490 491 492 493
  void MemoryPressureNotification(MemoryPressureLevel level,
                                  bool is_isolate_locked);
  void CheckMemoryPressure();

494 495 496
  void AddNearHeapLimitCallback(v8::NearHeapLimitCallback, void* data);
  void RemoveNearHeapLimitCallback(v8::NearHeapLimitCallback callback,
                                   size_t heap_limit);
497
  void AutomaticallyRestoreInitialHeapLimit(double threshold_percent);
498

499 500
  double MonotonicallyIncreasingTimeInMs();

501
  void RecordStats(HeapStats* stats, bool take_snapshot = false);
502

503
  // Check new space expansion criteria and expand semispaces if it was hit.
504
  void CheckNewSpaceExpansionCriteria();
505

506 507
  void VisitExternalResources(v8::ExternalResourceVisitor* visitor);

508 509
  // An object should be promoted if the object has survived a
  // scavenge operation.
510
  inline bool ShouldBePromoted(Address old_address);
511

512 513
  void IncrementDeferredCount(v8::Isolate::UseCounterFeature feature);

514
  inline int NextScriptId();
515
  inline int NextDebuggingId();
516
  inline int GetNextTemplateSerialNumber();
517

518 519
  void SetSerializedObjects(FixedArray objects);
  void SetSerializedGlobalProxySizes(FixedArray sizes);
520

521 522 523
  // For post mortem debugging.
  void RememberUnmappedPage(Address page, bool compacted);

524 525
  int64_t external_memory_hard_limit() { return MaxOldGenerationSize() / 2; }

526 527 528 529
  V8_INLINE int64_t external_memory();
  V8_INLINE void update_external_memory(int64_t delta);
  V8_INLINE void update_external_memory_concurrently_freed(intptr_t freed);
  V8_INLINE void account_external_memory_concurrently_freed();
530

531
  size_t backing_store_bytes() const { return backing_store_bytes_; }
532

533
  void CompactWeakArrayLists(PretenureFlag pretenure);
534

535 536
  void AddRetainedMap(Handle<Map> map);

537 538 539
  // This event is triggered after successful allocation of a new object made
  // by runtime. Allocations of target space for object evacuation do not
  // trigger the event. In order to track ALL allocations one must turn off
540
  // FLAG_inline_new.
541
  inline void OnAllocationEvent(HeapObject object, int size_in_bytes);
542 543

  // This event is triggered after object is moved to a new place.
544
  void OnMoveEvent(HeapObject target, HeapObject source, int size_in_bytes);
545

546
  inline bool CanAllocateInReadOnlySpace();
547 548
  bool deserialization_complete() const { return deserialization_complete_; }

549 550
  bool HasLowAllocationRate();
  bool HasHighFragmentation();
551
  bool HasHighFragmentation(size_t used, size_t committed);
552

553 554 555 556
  void ActivateMemoryReducerIfNeeded();

  bool ShouldOptimizeForMemoryUsage();

557
  bool HighMemoryPressure() {
558
    return memory_pressure_level_ != MemoryPressureLevel::kNone;
559
  }
560

561
  void RestoreHeapLimit(size_t heap_limit) {
562 563 564
    // Do not set the limit lower than the live size + some slack.
    size_t min_limit = SizeOfObjects() + SizeOfObjects() / 4;
    max_old_generation_size_ =
565
        Min(max_old_generation_size_, Max(heap_limit, min_limit));
566 567
  }

568 569 570 571
  // ===========================================================================
  // Initialization. ===========================================================
  // ===========================================================================

572 573 574 575
  // Configure heap sizes
  // max_semi_space_size_in_kb: maximum semi-space size in KB
  // max_old_generation_size_in_mb: maximum old generation size in MB
  // code_range_size_in_mb: code range size in MB
576
  void ConfigureHeap(size_t max_semi_space_size_in_kb,
577 578
                     size_t max_old_generation_size_in_mb,
                     size_t code_range_size_in_mb);
579
  void ConfigureHeapDefault();
580 581 582

  // Prepares the heap, setting up memory areas that are needed in the isolate
  // without actually creating any objects.
583
  void SetUp(ReadOnlyHeap* ro_heap);
584

585 586 587
  // (Re-)Initialize hash seed from flag or RNG.
  void InitializeHashSeed();

588 589 590 591
  // Bootstraps the object heap with the core set of objects required to run.
  // Returns whether it succeeded.
  bool CreateHeapObjects();

592
  // Create ObjectStats if live_object_stats_ or dead_object_stats_ are nullptr.
593
  void CreateObjectStats();
594

595 596 597
  // Sets the TearDown state, so no new GC tasks get posted.
  void StartTearDown();

598 599 600
  // Destroys all memory allocated by the heap.
  void TearDown();

601 602 603
  // Returns whether SetUp has been called.
  bool HasBeenSetUp();

604 605 606 607
  // ===========================================================================
  // Getters for spaces. =======================================================
  // ===========================================================================

608
  inline Address NewSpaceTop();
609

610
  NewSpace* new_space() { return new_space_; }
611
  OldSpace* old_space() { return old_space_; }
612
  CodeSpace* code_space() { return code_space_; }
613 614
  MapSpace* map_space() { return map_space_; }
  LargeObjectSpace* lo_space() { return lo_space_; }
615
  CodeLargeObjectSpace* code_lo_space() { return code_lo_space_; }
616
  NewLargeObjectSpace* new_lo_space() { return new_lo_space_; }
617
  ReadOnlySpace* read_only_space() { return read_only_space_; }
618

mlippautz's avatar
mlippautz committed
619 620
  inline PagedSpace* paged_space(int idx);
  inline Space* space(int idx);
621 622 623 624 625 626 627 628

  // Returns name of the space.
  const char* GetSpaceName(int idx);

  // ===========================================================================
  // Getters to other components. ==============================================
  // ===========================================================================

629 630
  ReadOnlyHeap* read_only_heap() const { return read_only_heap_; }

631
  GCTracer* tracer() { return tracer_.get(); }
632

633
  MemoryAllocator* memory_allocator() { return memory_allocator_.get(); }
634

635 636 637
  inline Isolate* isolate();

  MarkCompactCollector* mark_compact_collector() {
638
    return mark_compact_collector_.get();
639 640
  }

641 642 643 644
  MinorMarkCompactCollector* minor_mark_compact_collector() {
    return minor_mark_compact_collector_;
  }

645
  ArrayBufferCollector* array_buffer_collector() {
646
    return array_buffer_collector_.get();
647 648
  }

649 650 651
  // ===========================================================================
  // Root set access. ==========================================================
  // ===========================================================================
652

653 654
  // Shortcut to the roots table stored in the Isolate.
  V8_INLINE RootsTable& roots_table();
655

656
// Heap root getters.
657
#define ROOT_ACCESSOR(type, name, CamelName) inline type name();
658
  MUTABLE_ROOT_LIST(ROOT_ACCESSOR)
659
#undef ROOT_ACCESSOR
660

661
  V8_INLINE void SetRootMaterializedObjects(FixedArray objects);
662
  V8_INLINE void SetRootScriptList(Object value);
663
  V8_INLINE void SetRootStringTable(StringTable value);
664
  V8_INLINE void SetRootNoScriptSharedFunctionInfos(Object value);
665
  V8_INLINE void SetMessageListeners(TemplateList value);
666
  V8_INLINE void SetPendingOptimizeForTestBytecode(Object bytecode);
667 668

  // Set the stack limit in the roots table.  Some architectures generate
669 670 671 672
  // code that looks here, because it is faster than loading from the static
  // jslimit_/real_jslimit_ variable in the StackGuard.
  void SetStackLimits();

673 674 675 676
  // The stack limit is thread-dependent. To be able to reproduce the same
  // snapshot blob, we need to reset it before serializing.
  void ClearStackLimits();

677 678
  void RegisterStrongRoots(FullObjectSlot start, FullObjectSlot end);
  void UnregisterStrongRoots(FullObjectSlot start);
679

680
  void SetBuiltinsConstantsTable(FixedArray cache);
681

682 683 684 685 686 687 688 689
  // A full copy of the interpreter entry trampoline, used as a template to
  // create copies of the builtin at runtime. The copies are used to create
  // better profiling information for ticks in bytecode execution. Note that
  // this is always a copy of the full builtin, i.e. not the off-heap
  // trampoline.
  // See also: FLAG_interpreted_frames_native_stack.
  void SetInterpreterEntryTrampolineForProfiling(Code code);

690 691 692
  // Add finalization_group into the dirty_js_finalization_groups list.
  void AddDirtyJSFinalizationGroup(
      JSFinalizationGroup finalization_group,
693
      std::function<void(HeapObject object, ObjectSlot slot, Object target)>
694 695
          gc_notify_updated_slot);

696 697 698
  void AddKeepDuringJobTarget(Handle<JSReceiver> target);
  void ClearKeepDuringJobSet();

699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
  // ===========================================================================
  // Inline allocation. ========================================================
  // ===========================================================================

  // Indicates whether inline bump-pointer allocation has been disabled.
  bool inline_allocation_disabled() { return inline_allocation_disabled_; }

  // Switch whether inline bump-pointer allocation should be used.
  void EnableInlineAllocation();
  void DisableInlineAllocation();

  // ===========================================================================
  // Methods triggering GCs. ===================================================
  // ===========================================================================

714
  // Performs garbage collection operation.
715 716
  // Returns whether there is a chance that another major GC could
  // collect more garbage.
717
  V8_EXPORT_PRIVATE bool CollectGarbage(
718
      AllocationSpace space, GarbageCollectionReason gc_reason,
719
      const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
720

721
  // Performs a full garbage collection.
722
  V8_EXPORT_PRIVATE void CollectAllGarbage(
723
      int flags, GarbageCollectionReason gc_reason,
724 725 726
      const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);

  // Last hope GC, should try to squeeze as much as possible.
727
  void CollectAllAvailableGarbage(GarbageCollectionReason gc_reason);
728

729 730 731 732 733 734 735
  // Precise garbage collection that potentially finalizes already running
  // incremental marking before performing an atomic garbage collection.
  // Only use if absolutely necessary or in tests to avoid floating garbage!
  void PreciseCollectAllGarbage(
      int flags, GarbageCollectionReason gc_reason,
      const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);

736 737
  // Reports and external memory pressure event, either performs a major GC or
  // completes incremental marking in order to free external resources.
738
  void ReportExternalMemoryPressure();
739

740 741 742 743 744 745 746 747
  typedef v8::Isolate::GetExternallyAllocatedMemoryInBytesCallback
      GetExternallyAllocatedMemoryInBytesCallback;

  void SetGetExternallyAllocatedMemoryInBytesCallback(
      GetExternallyAllocatedMemoryInBytesCallback callback) {
    external_memory_callback_ = callback;
  }

748 749 750
  // Invoked when GC was requested via the stack guard.
  void HandleGCRequest();

751 752 753 754
  // ===========================================================================
  // Builtins. =================================================================
  // ===========================================================================

755
  Code builtin(int index);
756
  Address builtin_address(int index);
757
  void set_builtin(int index, Code builtin);
758

759 760 761 762
  // ===========================================================================
  // Iterators. ================================================================
  // ===========================================================================

Dan Elphick's avatar
Dan Elphick committed
763 764 765 766 767 768
  // None of these methods iterate over the read-only roots. To do this use
  // ReadOnlyRoots::Iterate. Read-only root iteration is not necessary for
  // garbage collection and is usually only performed as part of
  // (de)serialization or heap verification.

  // Iterates over the strong roots and the weak roots.
769
  void IterateRoots(RootVisitor* v, VisitMode mode);
Dan Elphick's avatar
Dan Elphick committed
770
  // Iterates over the strong roots.
771
  void IterateStrongRoots(RootVisitor* v, VisitMode mode);
772 773
  // Iterates over entries in the smi roots list.  Only interesting to the
  // serializer/deserializer, since GC does not care about smis.
774
  void IterateSmiRoots(RootVisitor* v);
775
  // Iterates over weak string tables.
776
  void IterateWeakRoots(RootVisitor* v, VisitMode mode);
777 778
  // Iterates over weak global handles.
  void IterateWeakGlobalHandles(RootVisitor* v);
779 780
  // Iterates over builtins.
  void IterateBuiltins(RootVisitor* v);
781

782 783 784 785
  // ===========================================================================
  // Store buffer API. =========================================================
  // ===========================================================================

786 787 788 789 790 791 792
  // Used for query incremental marking status in generated code.
  Address* IsMarkingFlagAddress() {
    return reinterpret_cast<Address*>(&is_marking_flag_);
  }

  void SetIsMarkingFlag(uint8_t flag) { is_marking_flag_ = flag; }

793 794 795
  Address* store_buffer_top_address();
  static intptr_t store_buffer_mask_constant();
  static Address store_buffer_overflow_function_address();
796

797
  void ClearRecordedSlot(HeapObject object, ObjectSlot slot);
798
  void ClearRecordedSlotRange(Address start, Address end);
799

800
#ifdef DEBUG
801
  void VerifyClearedSlot(HeapObject object, ObjectSlot slot);
802
#endif
803

804 805 806 807
  // ===========================================================================
  // Incremental marking API. ==================================================
  // ===========================================================================

808 809 810 811 812
  int GCFlagsForIncrementalMarking() {
    return ShouldOptimizeForMemoryUsage() ? kReduceMemoryFootprintMask
                                          : kNoGCFlags;
  }

813 814
  // Start incremental marking and ensure that idle time handler can perform
  // incremental steps.
815 816 817
  void StartIdleIncrementalMarking(
      GarbageCollectionReason gc_reason,
      GCCallbackFlags gc_callback_flags = GCCallbackFlags::kNoGCCallbackFlags);
818 819 820

  // Starts incremental marking assuming incremental marking is currently
  // stopped.
821 822 823
  void StartIncrementalMarking(
      int gc_flags, GarbageCollectionReason gc_reason,
      GCCallbackFlags gc_callback_flags = GCCallbackFlags::kNoGCCallbackFlags);
824

825 826 827
  void StartIncrementalMarkingIfAllocationLimitIsReached(
      int gc_flags,
      GCCallbackFlags gc_callback_flags = GCCallbackFlags::kNoGCCallbackFlags);
828

829
  void FinalizeIncrementalMarkingIfComplete(GarbageCollectionReason gc_reason);
830 831
  // Synchronously finalizes incremental marking.
  void FinalizeIncrementalMarkingAtomically(GarbageCollectionReason gc_reason);
832

833
  void RegisterDeserializedObjectsForBlackAllocation(
834
      Reservation* reservations, const std::vector<HeapObject>& large_objects,
835
      const std::vector<Address>& maps);
hpayer's avatar
hpayer committed
836

837 838 839
  IncrementalMarking* incremental_marking() {
    return incremental_marking_.get();
  }
840

841 842 843 844
  // ===========================================================================
  // Concurrent marking API. ===================================================
  // ===========================================================================

845
  ConcurrentMarking* concurrent_marking() { return concurrent_marking_.get(); }
846

847 848
  // The runtime uses this function to notify potentially unsafe object layout
  // changes that require special synchronization with the concurrent marker.
849
  // The old size is the size of the object before layout change.
850
  void NotifyObjectLayoutChange(HeapObject object, int old_size,
851
                                const DisallowHeapAllocation&);
852

853 854 855 856
#ifdef VERIFY_HEAP
  // This function checks that either
  // - the map transition is safe,
  // - or it was communicated to GC using NotifyObjectLayoutChange.
857
  void VerifyObjectLayoutChange(HeapObject object, Map new_map);
858 859
#endif

860 861 862 863 864 865 866 867 868 869 870 871
  // ===========================================================================
  // Deoptimization support API. ===============================================
  // ===========================================================================

  // Setters for code offsets of well-known deoptimization targets.
  void SetArgumentsAdaptorDeoptPCOffset(int pc_offset);
  void SetConstructStubCreateDeoptPCOffset(int pc_offset);
  void SetConstructStubInvokeDeoptPCOffset(int pc_offset);
  void SetInterpreterEntryReturnPCOffset(int pc_offset);

  // Invalidates references in the given {code} object that are referenced
  // transitively from the deoptimization data. Mutates write-protected code.
872
  void InvalidateCodeDeoptimizationData(Code code);
873 874 875 876 877

  void DeoptMarkedAllocationSites();

  bool DeoptMaybeTenuredAllocationSites();

878 879 880 881
  // ===========================================================================
  // Embedder heap tracer support. =============================================
  // ===========================================================================

882
  LocalEmbedderHeapTracer* local_embedder_heap_tracer() const {
883
    return local_embedder_heap_tracer_.get();
884
  }
885

886
  void SetEmbedderHeapTracer(EmbedderHeapTracer* tracer);
887 888
  EmbedderHeapTracer* GetEmbedderHeapTracer() const;

889
  void RegisterExternallyReferencedObject(Address* location);
890 891
  void SetEmbedderStackStateForNextFinalizaton(
      EmbedderHeapTracer::EmbedderStackState stack_state);
892

893 894 895 896 897
  // ===========================================================================
  // External string table API. ================================================
  // ===========================================================================

  // Registers an external string.
898
  inline void RegisterExternalString(String string);
899

900 901
  // Called when a string's resource is changed. The size of the payload is sent
  // as argument of the method.
902 903
  void UpdateExternalString(String string, size_t old_payload,
                            size_t new_payload);
904

905 906
  // Finalizes an external string by deleting the associated external
  // data and clearing the resource pointer.
907
  inline void FinalizeExternalString(String string);
908

909
  static String UpdateYoungReferenceInExternalStringTableEntry(
910
      Heap* heap, FullObjectSlot pointer);
911

912 913 914 915 916
  // ===========================================================================
  // Methods checking/returning the space of a given object/address. ===========
  // ===========================================================================

  // Returns whether the object resides in new space.
917 918 919 920 921 922 923 924 925
  static inline bool InYoungGeneration(Object object);
  static inline bool InYoungGeneration(MaybeObject object);
  static inline bool InYoungGeneration(HeapObject heap_object);
  static inline bool InFromPage(Object object);
  static inline bool InFromPage(MaybeObject object);
  static inline bool InFromPage(HeapObject heap_object);
  static inline bool InToPage(Object object);
  static inline bool InToPage(MaybeObject object);
  static inline bool InToPage(HeapObject heap_object);
926 927

  // Returns whether the object resides in old space.
928
  inline bool InOldSpace(Object object);
929

930
  // Returns whether the object resides in read-only space.
931
  inline bool InReadOnlySpace(Object object);
932

933 934
  // Checks whether an address/object in the heap (including auxiliary
  // area and unused area).
935
  bool Contains(HeapObject value);
936 937 938

  // Checks whether an address/object in a space.
  // Currently used by tests, serialization and heap verification only.
939
  bool InSpace(HeapObject value, AllocationSpace space);
940

941 942 943 944
  // Slow methods that can be used for verification as they can also be used
  // with off-heap Addresses.
  bool InSpaceSlow(Address addr, AllocationSpace space);

945
  static inline Heap* FromWritableHeapObject(const HeapObject obj);
946

947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965
  // ===========================================================================
  // Object statistics tracking. ===============================================
  // ===========================================================================

  // Returns the number of buckets used by object statistics tracking during a
  // major GC. Note that the following methods fail gracefully when the bounds
  // are exceeded though.
  size_t NumberOfTrackedHeapObjectTypes();

  // Returns object statistics about count and size at the last major GC.
  // Objects are being grouped into buckets that roughly resemble existing
  // instance types.
  size_t ObjectCountAtLastGC(size_t index);
  size_t ObjectSizeAtLastGC(size_t index);

  // Retrieves names of buckets used by object statistics tracking.
  bool GetObjectTypeName(size_t index, const char** object_type,
                         const char** object_sub_type);

966 967 968 969 970 971
  // The total number of native contexts object on the heap.
  size_t NumberOfNativeContexts();
  // The total number of native contexts that were detached but were not
  // garbage collected yet.
  size_t NumberOfDetachedContexts();

972 973 974 975 976 977 978
  // ===========================================================================
  // Code statistics. ==========================================================
  // ===========================================================================

  // Collect code (Code and BytecodeArray objects) statistics.
  void CollectCodeStatistics();

979 980 981 982
  // ===========================================================================
  // GC statistics. ============================================================
  // ===========================================================================

983
  // Returns the maximum amount of memory reserved for the heap.
984
  size_t MaxReserved();
985 986 987
  size_t MaxSemiSpaceSize() { return max_semi_space_size_; }
  size_t InitialSemiSpaceSize() { return initial_semispace_size_; }
  size_t MaxOldGenerationSize() { return max_old_generation_size_; }
988

989 990
  V8_EXPORT_PRIVATE static size_t ComputeMaxOldGenerationSize(
      uint64_t physical_memory);
991 992 993

  static size_t ComputeMaxSemiSpaceSize(uint64_t physical_memory) {
    const uint64_t min_physical_memory = 512 * MB;
994
    const uint64_t max_physical_memory = 3 * static_cast<uint64_t>(GB);
995 996 997 998

    uint64_t capped_physical_memory =
        Max(Min(physical_memory, max_physical_memory), min_physical_memory);
    // linearly scale max semi-space size: (X-A)/(B-A)*(D-C)+C
999 1000 1001 1002 1003
    size_t semi_space_size_in_kb =
        static_cast<size_t>(((capped_physical_memory - min_physical_memory) *
                             (kMaxSemiSpaceSizeInKB - kMinSemiSpaceSizeInKB)) /
                                (max_physical_memory - min_physical_memory) +
                            kMinSemiSpaceSizeInKB);
1004
    return RoundUp(semi_space_size_in_kb, (1 << kPageSizeBits) / KB);
1005 1006
  }

1007 1008
  // Returns the capacity of the heap in bytes w/o growing. Heap grows when
  // more spaces are needed until it reaches the limit.
1009
  size_t Capacity();
1010

1011
  // Returns the capacity of the old generation.
1012
  size_t OldGenerationCapacity();
1013

1014 1015
  // Returns the amount of memory currently held alive by the unmapper.
  size_t CommittedMemoryOfUnmapper();
1016

1017
  // Returns the amount of memory currently committed for the heap.
1018
  size_t CommittedMemory();
1019

1020
  // Returns the amount of memory currently committed for the old space.
1021
  size_t CommittedOldGenerationMemory();
1022

1023
  // Returns the amount of executable memory currently committed for the heap.
1024
  size_t CommittedMemoryExecutable();
1025

1026 1027
  // Returns the amount of phyical memory currently committed for the heap.
  size_t CommittedPhysicalMemory();
1028

1029
  // Returns the maximum amount of memory ever committed for the heap.
1030
  size_t MaximumCommittedMemory() { return maximum_committed_; }
1031

1032 1033 1034
  // Updates the maximum committed memory for the heap. Should be called
  // whenever a space grows.
  void UpdateMaximumCommitted();
1035

1036 1037 1038
  // Returns the available bytes in space w/o growing.
  // Heap doesn't guarantee that it can allocate an object that requires
  // all available bytes. Check MaxHeapObjectSize() instead.
1039
  size_t Available();
1040

1041
  // Returns of size of all objects residing in the heap.
1042
  size_t SizeOfObjects();
1043

1044
  void UpdateSurvivalStatistics(int start_new_space_size);
1045

1046
  inline void IncrementPromotedObjectsSize(size_t object_size) {
1047
    promoted_objects_size_ += object_size;
1048
  }
1049
  inline size_t promoted_objects_size() { return promoted_objects_size_; }
1050

1051
  inline void IncrementSemiSpaceCopiedObjectSize(size_t object_size) {
1052
    semi_space_copied_object_size_ += object_size;
1053
  }
1054
  inline size_t semi_space_copied_object_size() {
1055
    return semi_space_copied_object_size_;
1056
  }
1057

1058
  inline size_t SurvivedYoungObjectSize() {
1059
    return promoted_objects_size_ + semi_space_copied_object_size_;
1060
  }
1061

1062
  inline void IncrementNodesDiedInNewSpace() { nodes_died_in_new_space_++; }
1063

1064
  inline void IncrementNodesCopiedInNewSpace() { nodes_copied_in_new_space_++; }
1065

1066
  inline void IncrementNodesPromoted() { nodes_promoted_++; }
1067

1068
  inline void IncrementYoungSurvivorsCounter(size_t survived) {
1069 1070
    survived_last_scavenge_ = survived;
    survived_since_last_expansion_ += survived;
1071
  }
1072

1073 1074
  inline uint64_t OldGenerationObjectsAndPromotedExternalMemorySize() {
    return OldGenerationSizeOfObjects() + PromotedExternalMemorySize();
1075 1076
  }

mlippautz's avatar
mlippautz committed
1077
  inline void UpdateNewSpaceAllocationCounter();
1078

mlippautz's avatar
mlippautz committed
1079
  inline size_t NewSpaceAllocationCounter();
1080

1081 1082 1083 1084
  // This should be used only for testing.
  void set_new_space_allocation_counter(size_t new_value) {
    new_space_allocation_counter_ = new_value;
  }
1085

1086
  void UpdateOldGenerationAllocationCounter() {
1087 1088
    old_generation_allocation_counter_at_last_gc_ =
        OldGenerationAllocationCounter();
1089
    old_generation_size_at_last_gc_ = 0;
1090
  }
1091

1092
  size_t OldGenerationAllocationCounter() {
1093 1094
    return old_generation_allocation_counter_at_last_gc_ +
           PromotedSinceLastGC();
1095
  }
1096

1097
  // This should be used only for testing.
1098 1099
  void set_old_generation_allocation_counter_at_last_gc(size_t new_value) {
    old_generation_allocation_counter_at_last_gc_ = new_value;
1100
  }
1101

1102
  size_t PromotedSinceLastGC() {
1103
    size_t old_generation_size = OldGenerationSizeOfObjects();
1104
    DCHECK_GE(old_generation_size, old_generation_size_at_last_gc_);
1105
    return old_generation_size - old_generation_size_at_last_gc_;
1106
  }
1107

1108
  // This is called by the sweeper when it discovers more free space
1109
  // than expected at the end of the preceding GC.
1110 1111
  void NotifyRefinedOldGenerationSize(size_t decreased_bytes) {
    if (old_generation_size_at_last_gc_ != 0) {
1112 1113 1114
      // OldGenerationSizeOfObjects() is now smaller by |decreased_bytes|.
      // Adjust old_generation_size_at_last_gc_ too, so that PromotedSinceLastGC
      // continues to increase monotonically, rather than decreasing here.
1115 1116 1117 1118 1119
      DCHECK_GE(old_generation_size_at_last_gc_, decreased_bytes);
      old_generation_size_at_last_gc_ -= decreased_bytes;
    }
  }

1120
  int gc_count() const { return gc_count_; }
1121

1122 1123
  bool is_current_gc_forced() const { return is_current_gc_forced_; }

1124 1125 1126
  // Returns the size of objects residing in non-new spaces.
  // Excludes external memory held by those objects.
  size_t OldGenerationSizeOfObjects();
1127

1128 1129 1130
  // ===========================================================================
  // Prologue/epilogue callback methods.========================================
  // ===========================================================================
1131

1132 1133 1134 1135
  void AddGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
                             GCType gc_type_filter, void* data);
  void RemoveGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
                                void* data);
1136

1137 1138 1139 1140
  void AddGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback,
                             GCType gc_type_filter, void* data);
  void RemoveGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback,
                                void* data);
1141

1142 1143
  void CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags);
  void CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags);
1144

1145 1146 1147
  // ===========================================================================
  // Allocation methods. =======================================================
  // ===========================================================================
1148

1149
  // Creates a filler object and returns a heap object immediately after it.
1150 1151
  V8_WARN_UNUSED_RESULT HeapObject PrecedeWithFiller(HeapObject object,
                                                     int filler_size);
1152

1153 1154 1155
  // Creates a filler object if needed for alignment and returns a heap object
  // immediately after it. If any space is left after the returned object,
  // another filler object is created so the over allocated memory is iterable.
1156 1157 1158
  V8_WARN_UNUSED_RESULT HeapObject
  AlignWithFiller(HeapObject object, int object_size, int allocation_size,
                  AllocationAlignment alignment);
1159

1160
  // ===========================================================================
1161
  // ArrayBuffer tracking. =====================================================
1162
  // ===========================================================================
1163

1164 1165 1166 1167
  // TODO(gc): API usability: encapsulate mutation of JSArrayBuffer::is_external
  // in the registration/unregistration APIs. Consider dropping the "New" from
  // "RegisterNewArrayBuffer" because one can re-register a previously
  // unregistered buffer, too, and the name is confusing.
1168 1169
  void RegisterNewArrayBuffer(JSArrayBuffer buffer);
  void UnregisterArrayBuffer(JSArrayBuffer buffer);
1170

1171 1172 1173 1174
  // ===========================================================================
  // Allocation site tracking. =================================================
  // ===========================================================================

1175 1176 1177
  // Updates the AllocationSite of a given {object}. The entry (including the
  // count) is cached on the local pretenuring feedback.
  inline void UpdateAllocationSite(
1178
      Map map, HeapObject object, PretenuringFeedbackMap* pretenuring_feedback);
1179 1180 1181 1182 1183

  // Merges local pretenuring feedback into the global one. Note that this
  // method needs to be called after evacuation, as allocation sites may be
  // evacuated and this method resolves forward pointers accordingly.
  void MergeAllocationSitePretenuringFeedback(
1184
      const PretenuringFeedbackMap& local_pretenuring_feedback);
1185

1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
  // ===========================================================================
  // Allocation tracking. ======================================================
  // ===========================================================================

  // Adds {new_space_observer} to new space and {observer} to any other space.
  void AddAllocationObserversToAllSpaces(
      AllocationObserver* observer, AllocationObserver* new_space_observer);

  // Removes {new_space_observer} from new space and {observer} from any other
  // space.
  void RemoveAllocationObserversFromAllSpaces(
      AllocationObserver* observer, AllocationObserver* new_space_observer);

1199 1200 1201 1202 1203
  bool allocation_step_in_progress() { return allocation_step_in_progress_; }
  void set_allocation_step_in_progress(bool val) {
    allocation_step_in_progress_ = val;
  }

1204
  // ===========================================================================
1205 1206 1207 1208 1209 1210 1211 1212 1213
  // Heap object allocation tracking. ==========================================
  // ===========================================================================

  void AddHeapObjectAllocationTracker(HeapObjectAllocationTracker* tracker);
  void RemoveHeapObjectAllocationTracker(HeapObjectAllocationTracker* tracker);
  bool has_heap_object_allocation_tracker() const {
    return !allocation_trackers_.empty();
  }

1214
  // ===========================================================================
1215 1216
  // Retaining path tracking. ==================================================
  // ===========================================================================
1217

1218 1219 1220
  // Adds the given object to the weak table of retaining path targets.
  // On each GC if the marker discovers the object, it will print the retaining
  // path. This requires --track-retaining-path flag.
1221 1222
  void AddRetainingPathTarget(Handle<HeapObject> object,
                              RetainingPathOption option);
1223

1224 1225 1226 1227
  // ===========================================================================
  // Stack frame support. ======================================================
  // ===========================================================================

1228 1229
  // Returns the Code object for a given interior pointer.
  Code GcSafeFindCodeForInnerPointer(Address inner_pointer);
1230 1231 1232

  // Returns true if {addr} is contained within {code} and false otherwise.
  // Mostly useful for debugging.
1233
  bool GcSafeCodeContains(Code code, Address addr);
1234

1235
// =============================================================================
1236 1237 1238
#ifdef VERIFY_HEAP
  // Verify the heap is in its normal state before or after a GC.
  void Verify();
1239
  void VerifyRememberedSetFor(HeapObject object);
1240
#endif
1241

1242 1243 1244 1245
#ifdef V8_ENABLE_ALLOCATION_TIMEOUT
  void set_allocation_timeout(int timeout) { allocation_timeout_ = timeout; }
#endif

1246
#ifdef DEBUG
1247 1248 1249
  void VerifyCountersAfterSweeping();
  void VerifyCountersBeforeConcurrentSweeping();

1250 1251
  void Print();
  void PrintHandles();
1252

1253
  // Report code statistics.
1254 1255
  void ReportCodeStatistics(const char* title);
#endif
1256
  void* GetRandomMmapAddr() {
1257
    void* result = v8::internal::GetRandomMmapAddr();
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
#if V8_TARGET_ARCH_X64
#if V8_OS_MACOSX
    // The Darwin kernel [as of macOS 10.12.5] does not clean up page
    // directory entries [PDE] created from mmap or mach_vm_allocate, even
    // after the region is destroyed. Using a virtual address space that is
    // too large causes a leak of about 1 wired [can never be paged out] page
    // per call to mmap(). The page is only reclaimed when the process is
    // killed. Confine the hint to a 32-bit section of the virtual address
    // space. See crbug.com/700928.
    uintptr_t offset =
1268
        reinterpret_cast<uintptr_t>(v8::internal::GetRandomMmapAddr()) &
1269 1270 1271 1272 1273 1274
        kMmapRegionMask;
    result = reinterpret_cast<void*>(mmap_region_base_ + offset);
#endif  // V8_OS_MACOSX
#endif  // V8_TARGET_ARCH_X64
    return result;
  }
ulan@chromium.org's avatar
ulan@chromium.org committed
1275

1276 1277 1278
  static const char* GarbageCollectionReasonToString(
      GarbageCollectionReason gc_reason);

1279 1280 1281
  // Calculates the nof entries for the full sized number to string cache.
  inline int MaxNumberToStringCacheSize() const;

1282
 private:
1283
  class SkipStoreBufferScope;
1284

1285
  typedef String (*ExternalStringTableUpdaterCallback)(Heap* heap,
1286
                                                       FullObjectSlot pointer);
1287

1288 1289 1290 1291 1292
  // External strings table is a place where all external strings are
  // registered.  We need to keep track of such strings to properly
  // finalize them.
  class ExternalStringTable {
   public:
1293 1294
    explicit ExternalStringTable(Heap* heap) : heap_(heap) {}

1295
    // Registers an external string.
1296 1297
    inline void AddString(String string);
    bool Contains(String string);
1298

1299
    void IterateAll(RootVisitor* v);
1300 1301
    void IterateYoung(RootVisitor* v);
    void PromoteYoung();
1302

1303 1304 1305
    // Restores internal invariant and gets rid of collected strings. Must be
    // called after each Iterate*() that modified the strings.
    void CleanUpAll();
1306
    void CleanUpYoung();
1307

1308
    // Finalize all registered external strings and clear tables.
1309 1310
    void TearDown();

1311
    void UpdateYoungReferences(
1312 1313 1314
        Heap::ExternalStringTableUpdaterCallback updater_func);
    void UpdateReferences(
        Heap::ExternalStringTableUpdaterCallback updater_func);
1315

1316
   private:
1317
    void Verify();
1318
    void VerifyYoung();
1319

1320
    Heap* const heap_;
1321

1322 1323 1324 1325
    // To speed up scavenge collections young string are kept separate from old
    // strings.
    std::vector<Object> young_strings_;
    std::vector<Object> old_strings_;
1326 1327 1328 1329

    DISALLOW_COPY_AND_ASSIGN(ExternalStringTable);
  };

1330
  struct StrongRootsList;
1331

1332 1333 1334
  struct StringTypeTable {
    InstanceType type;
    int size;
1335
    RootIndex index;
1336 1337
  };

1338
  struct ConstantStringTable {
1339
    const char* contents;
1340
    RootIndex index;
1341 1342 1343 1344 1345
  };

  struct StructTable {
    InstanceType type;
    int size;
1346
    RootIndex index;
1347 1348
  };

1349 1350 1351 1352
  struct GCCallbackTuple {
    GCCallbackTuple(v8::Isolate::GCCallbackWithData callback, GCType gc_type,
                    void* data)
        : callback(callback), gc_type(gc_type), data(data) {}
1353

1354
    bool operator==(const GCCallbackTuple& other) const;
1355
    GCCallbackTuple& operator=(const GCCallbackTuple& other) V8_NOEXCEPT;
1356

1357
    v8::Isolate::GCCallbackWithData callback;
1358
    GCType gc_type;
1359
    void* data;
1360
  };
1361

1362
  static const int kInitialStringTableSize = StringTable::kMinCapacity;
1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
  static const int kInitialEvalCacheSize = 64;
  static const int kInitialNumberStringCacheSize = 256;

  static const int kRememberedUnmappedPages = 128;

  static const StringTypeTable string_type_table[];
  static const ConstantStringTable constant_string_table[];
  static const StructTable struct_table[];

  static const int kYoungSurvivalRateHighThreshold = 90;
  static const int kYoungSurvivalRateAllowedDeviation = 15;
  static const int kOldSurvivalRateLowThreshold = 10;

  static const int kMaxMarkCompactsInIdleRound = 7;
  static const int kIdleScavengeThreshold = 5;

1379
  static const int kInitialFeedbackCapacity = 256;
1380 1381

  Heap();
1382
  ~Heap();
1383

1384 1385
  // Selects the proper allocation space based on the pretenuring decision.
  static AllocationSpace SelectSpace(PretenureFlag pretenure) {
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
    switch (pretenure) {
      case TENURED_READ_ONLY:
        return RO_SPACE;
      case TENURED:
        return OLD_SPACE;
      case NOT_TENURED:
        return NEW_SPACE;
      default:
        UNREACHABLE();
    }
1396 1397
  }

1398 1399 1400 1401
  static size_t DefaultGetExternallyAllocatedMemoryInBytesCallback() {
    return 0;
  }

1402
#define ROOT_ACCESSOR(type, name, CamelName) inline void set_##name(type value);
1403 1404 1405
  ROOT_LIST(ROOT_ACCESSOR)
#undef ROOT_ACCESSOR

1406
  StoreBuffer* store_buffer() { return store_buffer_.get(); }
1407

1408
  void set_current_gc_flags(int flags) {
1409 1410 1411 1412
    current_gc_flags_ = flags;
  }

  inline bool ShouldReduceMemory() const {
1413
    return (current_gc_flags_ & kReduceMemoryFootprintMask) != 0;
1414 1415
  }

1416 1417
  int NumberOfScavengeTasks();

1418
  // Checks whether a global GC is necessary
1419 1420
  GarbageCollector SelectGarbageCollector(AllocationSpace space,
                                          const char** reason);
1421

1422 1423 1424 1425 1426
  // Make sure there is a filler value behind the top of the new space
  // so that the GC does not confuse some unintialized/stale memory
  // with the allocation memento of the object at the top
  void EnsureFillerObjectAtTop();

1427
  // Ensure that we have swept all spaces in such a way that we can iterate
1428
  // over all objects.  May cause a GC.
1429 1430
  void MakeHeapIterable();

1431 1432 1433
  // Performs garbage collection
  // Returns whether there is a chance another major GC could
  // collect more garbage.
1434 1435 1436
  bool PerformGarbageCollection(
      GarbageCollector collector,
      const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
1437 1438 1439 1440

  inline void UpdateOldSpaceLimits();

  bool CreateInitialMaps();
1441
  void CreateInternalAccessorInfoObjects();
1442 1443 1444 1445 1446 1447
  void CreateInitialObjects();

  // Commits from space if it is uncommitted.
  void EnsureFromSpaceIsCommitted();

  // Uncommit unused semi space.
mlippautz's avatar
mlippautz committed
1448
  bool UncommitFromSpace();
1449 1450 1451 1452

  // Fill in bogus values in from space
  void ZapFromSpace();

1453 1454 1455
  // Zaps the memory of a code object.
  void ZapCodeObject(Address start_address, int size_in_bytes);

1456 1457 1458 1459 1460 1461 1462 1463 1464
  // Deopts all code that contains allocation instruction which are tenured or
  // not tenured. Moreover it clears the pretenuring allocation site statistics.
  void ResetAllAllocationSitesDependentCode(PretenureFlag flag);

  // Evaluates local pretenuring for the old space and calls
  // ResetAllTenuredAllocationSitesDependentCode if too many objects died in
  // the old space.
  void EvaluateOldSpaceLocalPretenuring(uint64_t size_of_objects_before_gc);

1465
  // Record statistics after garbage collection.
1466 1467 1468 1469 1470
  void ReportStatisticsAfterGC();

  // Flush the number to string cache.
  void FlushNumberStringCache();

1471
  void ConfigureInitialOldGenerationSize();
1472

1473 1474 1475 1476 1477 1478 1479
  bool HasLowYoungGenerationAllocationRate();
  bool HasLowOldGenerationAllocationRate();
  double YoungGenerationMutatorUtilization();
  double OldGenerationMutatorUtilization();

  void ReduceNewSpaceSize();

1480
  GCIdleTimeHeapState ComputeHeapState();
1481 1482

  bool PerformIdleTimeAction(GCIdleTimeAction action,
1483
                             GCIdleTimeHeapState heap_state,
1484 1485 1486
                             double deadline_in_ms);

  void IdleNotificationEpilogue(GCIdleTimeAction action,
1487 1488
                                GCIdleTimeHeapState heap_state, double start_ms,
                                double deadline_in_ms);
1489

1490
  int NextAllocationTimeout(int current_timeout = 0);
1491
  inline void UpdateAllocationsHash(HeapObject object);
1492
  inline void UpdateAllocationsHash(uint32_t value);
Clemens Hammacher's avatar
Clemens Hammacher committed
1493
  void PrintAllocationsHash();
1494

1495 1496 1497
  void PrintMaxMarkingLimitReached();
  void PrintMaxNewSpaceSizeReached();

1498 1499
  int NextStressMarkingLimit();

1500 1501 1502
  void AddToRingBuffer(const char* string);
  void GetFromRingBuffer(char* buffer);

1503
  void CompactRetainedMaps(WeakArrayList retained_maps);
1504

1505
  void CollectGarbageOnMemoryPressure();
1506

1507 1508
  void EagerlyFreeExternalMemory();

1509
  bool InvokeNearHeapLimitCallback();
1510

1511
  void ComputeFastPromotionMode();
1512

1513 1514 1515 1516
  // Attempt to over-approximate the weak closure by marking object groups and
  // implicit references from global handles, but don't atomically complete
  // marking. If we continue to mark incrementally, we might have marked
  // objects that die later.
1517 1518
  void FinalizeIncrementalMarkingIncrementally(
      GarbageCollectionReason gc_reason);
1519

1520 1521 1522 1523 1524 1525
  // Returns the timer used for a given GC type.
  // - GCScavenger: young generation GC
  // - GCCompactor: full GC
  // - GCFinalzeMC: finalization of incremental full GC
  // - GCFinalizeMCReduceMemory: finalization of incremental full GC with
  // memory reduction
1526 1527
  TimedHistogram* GCTypeTimer(GarbageCollector collector);
  TimedHistogram* GCTypePriorityTimer(GarbageCollector collector);
1528

1529 1530 1531 1532 1533 1534 1535 1536 1537
  // ===========================================================================
  // Pretenuring. ==============================================================
  // ===========================================================================

  // Pretenuring decisions are made based on feedback collected during new space
  // evacuation. Note that between feedback collection and calling this method
  // object in old space must not move.
  void ProcessPretenuringFeedback();

1538
  // Removes an entry from the global pretenuring storage.
1539
  void RemoveAllocationSitePretenuringFeedback(AllocationSite site);
1540

1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551
  // ===========================================================================
  // Actual GC. ================================================================
  // ===========================================================================

  // Code that should be run before and after each GC.  Includes some
  // reporting/verification activities when compiled with DEBUG set.
  void GarbageCollectionPrologue();
  void GarbageCollectionEpilogue();

  // Performs a major collection in the whole heap.
  void MarkCompact();
1552 1553
  // Performs a minor collection of just the young generation.
  void MinorMarkCompact();
1554 1555 1556 1557 1558 1559 1560

  // Code to be run before and after mark-compact.
  void MarkCompactPrologue();
  void MarkCompactEpilogue();

  // Performs a minor collection in new generation.
  void Scavenge();
1561
  void EvacuateYoungGeneration();
1562

1563
  void UpdateYoungReferencesInExternalStringTable(
1564 1565 1566 1567 1568 1569 1570 1571 1572
      ExternalStringTableUpdaterCallback updater_func);

  void UpdateReferencesInExternalStringTable(
      ExternalStringTableUpdaterCallback updater_func);

  void ProcessAllWeakReferences(WeakObjectRetainer* retainer);
  void ProcessYoungWeakReferences(WeakObjectRetainer* retainer);
  void ProcessNativeContexts(WeakObjectRetainer* retainer);
  void ProcessAllocationSites(WeakObjectRetainer* retainer);
1573
  void ProcessWeakListRoots(WeakObjectRetainer* retainer);
1574 1575 1576 1577 1578

  // ===========================================================================
  // GC statistics. ============================================================
  // ===========================================================================

1579
  inline size_t OldGenerationSpaceAvailable() {
1580 1581 1582
    if (old_generation_allocation_limit_ <=
        OldGenerationObjectsAndPromotedExternalMemorySize())
      return 0;
1583
    return old_generation_allocation_limit_ -
1584 1585
           static_cast<size_t>(
               OldGenerationObjectsAndPromotedExternalMemorySize());
1586
  }
1587

1588 1589 1590 1591
  // We allow incremental marking to overshoot the allocation limit for
  // performace reasons. If the overshoot is too large then we are more
  // eager to finalize incremental marking.
  inline bool AllocationLimitOvershotByLargeMargin() {
1592 1593 1594
    // This guards against too eager finalization in small heaps.
    // The number is chosen based on v8.browsing_mobile on Nexus 7v2.
    size_t kMarginForSmallHeaps = 32u * MB;
1595 1596 1597 1598 1599
    if (old_generation_allocation_limit_ >=
        OldGenerationObjectsAndPromotedExternalMemorySize())
      return false;
    uint64_t overshoot = OldGenerationObjectsAndPromotedExternalMemorySize() -
                         old_generation_allocation_limit_;
1600 1601
    // Overshoot margin is 50% of allocation limit or half-way to the max heap
    // with special handling of small heaps.
1602
    uint64_t margin =
1603
        Min(Max(old_generation_allocation_limit_ / 2, kMarginForSmallHeaps),
1604 1605 1606 1607
            (max_old_generation_size_ - old_generation_allocation_limit_) / 2);
    return overshoot >= margin;
  }

1608
  void UpdateTotalGCTime(double duration);
1609 1610 1611

  bool MaximumSizeScavenge() { return maximum_size_scavenges_ > 0; }

1612 1613 1614 1615 1616
  bool IsIneffectiveMarkCompact(size_t old_generation_size,
                                double mutator_utilization);
  void CheckIneffectiveMarkCompact(size_t old_generation_size,
                                   double mutator_utilization);

1617 1618 1619 1620 1621 1622
  inline void IncrementExternalBackingStoreBytes(ExternalBackingStoreType type,
                                                 size_t amount);

  inline void DecrementExternalBackingStoreBytes(ExternalBackingStoreType type,
                                                 size_t amount);

1623 1624 1625 1626
  // ===========================================================================
  // Growing strategy. =========================================================
  // ===========================================================================

1627 1628
  HeapController* heap_controller() { return heap_controller_.get(); }
  MemoryReducer* memory_reducer() { return memory_reducer_.get(); }
1629

1630 1631 1632 1633
  // For some webpages RAIL mode does not switch from PERFORMANCE_LOAD.
  // This constant limits the effect of load RAIL mode on GC.
  // The value is arbitrary and chosen as the largest load time observed in
  // v8 browsing benchmarks.
1634
  static const int kMaxLoadTimeMs = 7000;
1635 1636 1637

  bool ShouldOptimizeForLoadTime();

1638
  size_t old_generation_allocation_limit() const {
1639 1640 1641
    return old_generation_allocation_limit_;
  }

1642
  bool always_allocate() { return always_allocate_scope_count_ != 0; }
1643

1644
  bool CanExpandOldGeneration(size_t size);
1645

1646
  bool ShouldExpandOldGenerationOnSlowAllocation();
1647

1648
  enum class HeapGrowingMode { kSlow, kConservative, kMinimal, kDefault };
1649

1650 1651
  HeapGrowingMode CurrentHeapGrowingMode();

1652 1653 1654
  enum class IncrementalMarkingLimit { kNoLimit, kSoftLimit, kHardLimit };
  IncrementalMarkingLimit IncrementalMarkingLimitReached();

1655 1656 1657 1658 1659
  // ===========================================================================
  // Idle notification. ========================================================
  // ===========================================================================

  bool RecentIdleNotificationHappened();
ulan's avatar
ulan committed
1660
  void ScheduleIdleScavengeIfNeeded(int bytes_allocated);
1661

1662 1663 1664 1665 1666 1667 1668 1669 1670 1671
  // ===========================================================================
  // HeapIterator helpers. =====================================================
  // ===========================================================================

  void heap_iterator_start() { heap_iterator_depth_++; }

  void heap_iterator_end() { heap_iterator_depth_--; }

  bool in_heap_iterator() { return heap_iterator_depth_ > 0; }

1672 1673 1674 1675 1676
  // ===========================================================================
  // Allocation methods. =======================================================
  // ===========================================================================

  // Allocates a JS Map in the heap.
1677
  V8_WARN_UNUSED_RESULT AllocationResult
1678
  AllocateMap(InstanceType instance_type, int instance_size,
1679 1680
              ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND,
              int inobject_properties = 0);
1681

1682
  // Allocate an uninitialized object.  The memory is non-executable if the
1683 1684 1685
  // hardware and OS allow.  This is the single choke-point for allocations
  // performed by the runtime and should not be bypassed (to extend this to
  // inlined allocations, use the Heap::DisableInlineAllocation() support).
1686
  V8_WARN_UNUSED_RESULT inline AllocationResult AllocateRaw(
1687
      int size_in_bytes, AllocationSpace space,
1688
      AllocationAlignment aligment = kWordAligned);
1689

1690 1691 1692 1693 1694
  // This method will try to perform an allocation of a given size in a given
  // space. If the allocation fails, a regular full garbage collection is
  // triggered and the allocation is retried. This is performed multiple times.
  // If after that retry procedure the allocation still fails nullptr is
  // returned.
1695
  HeapObject AllocateRawWithLightRetry(
1696 1697 1698 1699 1700 1701 1702 1703 1704
      int size, AllocationSpace space,
      AllocationAlignment alignment = kWordAligned);

  // This method will try to perform an allocation of a given size in a given
  // space. If the allocation fails, a regular full garbage collection is
  // triggered and the allocation is retried. This is performed multiple times.
  // If after that retry procedure the allocation still fails a "hammer"
  // garbage collection is triggered which tries to significantly reduce memory.
  // If the allocation still fails after that a fatal error is thrown.
1705
  HeapObject AllocateRawWithRetryOrFail(
1706 1707
      int size, AllocationSpace space,
      AllocationAlignment alignment = kWordAligned);
1708
  HeapObject AllocateRawCodeInLargeObjectSpace(int size);
1709

1710
  // Allocates a heap object based on the map.
1711
  V8_WARN_UNUSED_RESULT AllocationResult Allocate(Map map,
1712
                                                  AllocationSpace space);
1713

1714 1715 1716
  // Takes a code object and checks if it is on memory which is not subject to
  // compaction. This method will return a new code object on an immovable
  // memory location if the original code object was movable.
1717
  HeapObject EnsureImmovableCode(HeapObject heap_object, int object_size);
1718

1719
  // Allocates a partial map for bootstrapping.
1720 1721
  V8_WARN_UNUSED_RESULT AllocationResult
  AllocatePartialMap(InstanceType instance_type, int instance_size);
1722

1723
  void FinalizePartialMap(Map map);
1724

1725
  // Allocate empty fixed typed array of given type.
1726 1727
  V8_WARN_UNUSED_RESULT AllocationResult
  AllocateEmptyFixedTypedArray(ExternalArrayType array_type);
1728

1729 1730 1731 1732
  void set_force_oom(bool value) { force_oom_ = value; }

  // ===========================================================================
  // Retaining path tracing ====================================================
1733 1734
  // ===========================================================================

1735 1736 1737
  void AddRetainer(HeapObject retainer, HeapObject object);
  void AddEphemeronRetainer(HeapObject retainer, HeapObject object);
  void AddRetainingRoot(Root root, HeapObject object);
1738 1739
  // Returns true if the given object is a target of retaining path tracking.
  // Stores the option corresponding to the object in the provided *option.
1740 1741
  bool IsRetainingPathTarget(HeapObject object, RetainingPathOption* option);
  void PrintRetainingPath(HeapObject object, RetainingPathOption option);
1742

1743 1744 1745 1746
#ifdef DEBUG
  void IncrementObjectCounters();
#endif  // DEBUG

1747
  // The amount of memory that has been freed concurrently.
1748
  std::atomic<intptr_t> external_memory_concurrently_freed_{0};
1749

1750 1751
  // This can be calculated directly from a pointer to the heap; however, it is
  // more expedient to get at the isolate directly from within Heap methods.
1752
  Isolate* isolate_ = nullptr;
1753

1754
  size_t code_range_size_ = 0;
1755
  size_t max_semi_space_size_ = 8 * (kSystemPointerSize / 4) * MB;
1756
  size_t initial_semispace_size_ = kMinSemiSpaceSizeInKB * KB;
1757
  size_t max_old_generation_size_ = 700ul * (kSystemPointerSize / 4) * MB;
1758
  size_t initial_max_old_generation_size_;
1759
  size_t initial_max_old_generation_size_threshold_;
1760
  size_t initial_old_generation_size_;
1761 1762
  bool old_generation_size_configured_ = false;
  size_t maximum_committed_ = 0;
1763
  size_t old_generation_capacity_after_bootstrap_ = 0;
1764

1765
  // Backing store bytes (array buffers and external strings).
1766
  std::atomic<size_t> backing_store_bytes_{0};
1767

1768 1769
  // For keeping track of how much data has survived
  // scavenge since last new space expansion.
1770
  size_t survived_since_last_expansion_ = 0;
1771

1772
  // ... and since the last scavenge.
1773
  size_t survived_last_scavenge_ = 0;
1774

1775 1776
  // This is not the depth of nested AlwaysAllocateScope's but rather a single
  // count, as scopes can be acquired from multiple tasks (read: threads).
1777
  std::atomic<size_t> always_allocate_scope_count_{0};
1778

1779 1780
  // Stores the memory pressure level that set by MemoryPressureNotification
  // and reset by a mark-compact garbage collection.
1781
  std::atomic<MemoryPressureLevel> memory_pressure_level_;
1782

1783 1784
  std::vector<std::pair<v8::NearHeapLimitCallback, void*> >
      near_heap_limit_callbacks_;
1785

1786
  // For keeping track of context disposals.
1787
  int contexts_disposed_ = 0;
1788

1789 1790 1791
  // The length of the retained_maps array at the time of context disposal.
  // This separates maps in the retained_maps array that were created before
  // and after context disposal.
1792 1793
  int number_of_disposed_maps_ = 0;

1794 1795
  ReadOnlyHeap* read_only_heap_ = nullptr;

1796 1797 1798 1799 1800
  NewSpace* new_space_ = nullptr;
  OldSpace* old_space_ = nullptr;
  CodeSpace* code_space_ = nullptr;
  MapSpace* map_space_ = nullptr;
  LargeObjectSpace* lo_space_ = nullptr;
1801
  CodeLargeObjectSpace* code_lo_space_ = nullptr;
1802 1803
  NewLargeObjectSpace* new_lo_space_ = nullptr;
  ReadOnlySpace* read_only_space_ = nullptr;
1804 1805
  // Map from the space id to the space.
  Space* space_[LAST_SPACE + 1];
1806

1807 1808
  // Determines whether code space is write-protected. This is essentially a
  // race-free copy of the {FLAG_write_protect_code_memory} flag.
1809
  bool write_protect_code_memory_ = false;
1810

1811
  // Holds the number of open CodeSpaceMemoryModificationScopes.
1812
  uintptr_t code_space_memory_modification_scope_depth_ = 0;
1813

1814 1815 1816
  HeapState gc_state_ = NOT_IN_GC;

  int gc_post_processing_depth_ = 0;
1817

1818
  // Returns the amount of external memory registered since last global gc.
1819
  uint64_t PromotedExternalMemorySize();
1820

1821
  // How many "runtime allocations" happened.
1822
  uint32_t allocations_count_ = 0;
1823

1824
  // Running hash over allocations performed.
1825
  uint32_t raw_allocations_hash_ = 0;
1826

1827 1828
  // Starts marking when stress_marking_percentage_% of the marking start limit
  // is reached.
1829
  int stress_marking_percentage_ = 0;
1830

1831 1832
  // Observer that causes more frequent checks for reached incremental marking
  // limit.
1833
  AllocationObserver* stress_marking_observer_ = nullptr;
1834

1835
  // Observer that can cause early scavenge start.
1836
  StressScavengeObserver* stress_scavenge_observer_ = nullptr;
1837

1838
  bool allocation_step_in_progress_ = false;
1839

1840 1841
  // The maximum percent of the marking limit reached wihout causing marking.
  // This is tracked when specyfing --fuzzer-gc-analysis.
1842
  double max_marking_limit_reached_ = 0.0;
1843

1844
  // How many mark-sweep collections happened.
1845
  unsigned int ms_count_ = 0;
1846

1847
  // How many gc happened.
1848
  unsigned int gc_count_ = 0;
1849

1850 1851
  // The number of Mark-Compact garbage collections that are considered as
  // ineffective. See IsIneffectiveMarkCompact() predicate.
1852
  int consecutive_ineffective_mark_compacts_ = 0;
1853

1854
  static const uintptr_t kMmapRegionMask = 0xFFFFFFFFu;
1855
  uintptr_t mmap_region_base_ = 0;
1856

1857
  // For post mortem debugging.
1858
  int remembered_unmapped_pages_index_ = 0;
1859
  Address remembered_unmapped_pages_[kRememberedUnmappedPages];
1860

1861 1862 1863 1864
  // Limit that triggers a global GC on the next (normally caused) GC.  This
  // is checked when we have already decided to do a GC to help determine
  // which collector to invoke, before expanding a paged space in the old
  // generation and on every allocation in large object space.
1865
  size_t old_generation_allocation_limit_;
1866

1867 1868
  // Indicates that inline bump-pointer allocation has been globally disabled
  // for all spaces. This is used to disable allocations in generated code.
1869
  bool inline_allocation_disabled_ = false;
1870 1871 1872

  // Weak list heads, threaded through the objects.
  // List heads are initialized lazily and contain the undefined_value at start.
1873 1874
  Object native_contexts_list_;
  Object allocation_sites_list_;
1875

1876 1877
  std::vector<GCCallbackTuple> gc_epilogue_callbacks_;
  std::vector<GCCallbackTuple> gc_prologue_callbacks_;
1878

1879 1880
  GetExternallyAllocatedMemoryInBytesCallback external_memory_callback_;

1881 1882
  int deferred_counters_[v8::Isolate::kUseCounterFeatureCount];

1883 1884 1885 1886 1887 1888 1889 1890 1891
  size_t promoted_objects_size_ = 0;
  double promotion_ratio_ = 0.0;
  double promotion_rate_ = 0.0;
  size_t semi_space_copied_object_size_ = 0;
  size_t previous_semi_space_copied_object_size_ = 0;
  double semi_space_copied_rate_ = 0.0;
  int nodes_died_in_new_space_ = 0;
  int nodes_copied_in_new_space_ = 0;
  int nodes_promoted_ = 0;
1892

1893 1894 1895 1896
  // This is the pretenuring trigger for allocation sites that are in maybe
  // tenure state. When we switched to the maximum new space size we deoptimize
  // the code that belongs to the allocation site and derive the lifetime
  // of the allocation site.
1897
  unsigned int maximum_size_scavenges_ = 0;
1898

1899
  // Total time spent in GC.
1900
  double total_gc_time_ms_;
1901

1902
  // Last time an idle notification happened.
1903
  double last_idle_notification_time_ = 0.0;
1904

1905
  // Last time a garbage collection happened.
1906 1907
  double last_gc_time_ = 0.0;

1908 1909
  std::unique_ptr<GCTracer> tracer_;
  std::unique_ptr<MarkCompactCollector> mark_compact_collector_;
1910
  MinorMarkCompactCollector* minor_mark_compact_collector_ = nullptr;
1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924
  std::unique_ptr<ScavengerCollector> scavenger_collector_;
  std::unique_ptr<ArrayBufferCollector> array_buffer_collector_;
  std::unique_ptr<MemoryAllocator> memory_allocator_;
  std::unique_ptr<StoreBuffer> store_buffer_;
  std::unique_ptr<HeapController> heap_controller_;
  std::unique_ptr<IncrementalMarking> incremental_marking_;
  std::unique_ptr<ConcurrentMarking> concurrent_marking_;
  std::unique_ptr<GCIdleTimeHandler> gc_idle_time_handler_;
  std::unique_ptr<MemoryReducer> memory_reducer_;
  std::unique_ptr<ObjectStats> live_object_stats_;
  std::unique_ptr<ObjectStats> dead_object_stats_;
  std::unique_ptr<ScavengeJob> scavenge_job_;
  std::unique_ptr<AllocationObserver> idle_scavenge_observer_;
  std::unique_ptr<LocalEmbedderHeapTracer> local_embedder_heap_tracer_;
1925
  StrongRootsList* strong_roots_list_ = nullptr;
1926

1927 1928 1929
  // This counter is increased before each GC and never reset.
  // To account for the bytes allocated since the last GC, use the
  // NewSpaceAllocationCounter() function.
1930
  size_t new_space_allocation_counter_ = 0;
1931

1932 1933 1934
  // This counter is increased before each GC and never reset. To
  // account for the bytes allocated since the last GC, use the
  // OldGenerationAllocationCounter() function.
1935
  size_t old_generation_allocation_counter_at_last_gc_ = 0;
1936 1937

  // The size of objects in old generation after the last MarkCompact GC.
1938
  size_t old_generation_size_at_last_gc_ = 0;
1939

1940 1941 1942 1943 1944
  // The feedback storage is used to store allocation sites (keys) and how often
  // they have been visited (values) by finding a memento behind an object. The
  // storage is only alive temporary during a GC. The invariant is that all
  // pointers in this map are already fixed, i.e., they do not point to
  // forwarding pointers.
1945
  PretenuringFeedbackMap global_pretenuring_feedback_;
1946

1947
  char trace_ring_buffer_[kTraceRingBufferSize];
1948 1949

  // Used as boolean.
1950
  uint8_t is_marking_flag_ = 0;
1951

1952 1953 1954
  // If it's not full then the data is from 0 to ring_buffer_end_.  If it's
  // full then the data is from ring_buffer_end_ to the end of the buffer and
  // from 0 to ring_buffer_end_.
1955 1956
  bool ring_buffer_full_ = false;
  size_t ring_buffer_end_ = 0;
1957

1958
  // Flag is set when the heap has been configured.  The heap can be repeatedly
1959
  // configured through the API until it is set up.
1960
  bool configured_ = false;
1961

1962
  // Currently set GC flags that are respected by all GC components.
1963
  int current_gc_flags_ = Heap::kNoGCFlags;
1964

1965 1966 1967 1968
  // Currently set GC callback flags that are used to pass information between
  // the embedder and V8's GC.
  GCCallbackFlags current_gc_callback_flags_;

1969 1970
  bool is_current_gc_forced_;

1971 1972
  ExternalStringTable external_string_table_;

1973
  base::Mutex relocation_mutex_;
1974

1975
  int gc_callbacks_depth_ = 0;
1976

1977
  bool deserialization_complete_ = false;
1978

1979
  // The depth of HeapIterator nestings.
1980
  int heap_iterator_depth_ = 0;
1981

1982
  bool fast_promotion_mode_ = false;
1983

1984
  // Used for testing purposes.
1985 1986
  bool force_oom_ = false;
  bool delay_sweeper_tasks_for_testing_ = false;
1987

1988
  HeapObject pending_layout_change_object_;
1989

1990
  base::Mutex unprotected_memory_chunks_mutex_;
1991
  std::unordered_set<MemoryChunk*> unprotected_memory_chunks_;
1992
  bool unprotected_memory_chunks_registry_enabled_ = false;
1993

1994 1995 1996 1997
#ifdef V8_ENABLE_ALLOCATION_TIMEOUT
  // If the --gc-interval flag is set to a positive value, this
  // variable holds the value indicating the number of allocations
  // remain until the next failure and garbage collection.
1998
  int allocation_timeout_ = 0;
1999 2000
#endif  // V8_ENABLE_ALLOCATION_TIMEOUT

2001 2002
  std::map<HeapObject, HeapObject, Object::Comparer> retainer_;
  std::map<HeapObject, Root, Object::Comparer> retaining_root_;
2003 2004
  // If an object is retained by an ephemeron, then the retaining key of the
  // ephemeron is stored in this map.
2005
  std::map<HeapObject, HeapObject, Object::Comparer> ephemeron_retainer_;
2006 2007 2008
  // For each index inthe retaining_path_targets_ array this map
  // stores the option of the corresponding target.
  std::map<int, RetainingPathOption> retaining_path_target_option_;
2009

2010 2011
  std::vector<HeapObjectAllocationTracker*> allocation_trackers_;

2012
  // Classes in "heap" can be friends.
2013
  friend class AlwaysAllocateScope;
2014
  friend class ArrayBufferCollector;
2015
  friend class ConcurrentMarking;
2016
  friend class GCCallbacksScope;
2017
  friend class GCTracer;
2018
  friend class MemoryController;
2019
  friend class HeapIterator;
2020
  friend class IdleScavengeObserver;
2021
  friend class IncrementalMarking;
2022 2023
  friend class IncrementalMarkingJob;
  friend class LargeObjectSpace;
2024
  template <FixedArrayVisitationMode fixed_array_mode,
2025
            TraceRetainingPathMode retaining_path_mode, typename MarkingState>
2026
  friend class MarkingVisitor;
2027
  friend class MarkCompactCollector;
2028
  friend class MarkCompactCollectorBase;
2029
  friend class MinorMarkCompactCollector;
2030
  friend class NewLargeObjectSpace;
ulan's avatar
ulan committed
2031
  friend class NewSpace;
2032
  friend class ObjectStatsCollector;
2033
  friend class Page;
2034
  friend class PagedSpace;
2035
  friend class ReadOnlyRoots;
2036
  friend class Scavenger;
2037
  friend class ScavengerCollector;
2038
  friend class Space;
2039
  friend class StoreBuffer;
2040
  friend class Sweeper;
2041
  friend class heap::TestMemoryAllocatorScope;
2042

2043 2044 2045 2046 2047 2048
  // The allocator interface.
  friend class Factory;

  // The Isolate constructs us.
  friend class Isolate;

2049
  // Used in cctest.
2050
  friend class heap::HeapTester;
2051

2052
  FRIEND_TEST(HeapControllerTest, OldGenerationAllocationLimit);
2053 2054
  FRIEND_TEST(HeapTest, ExternalLimitDefault);
  FRIEND_TEST(HeapTest, ExternalLimitStaysAboveDefaultForExplicitHandling);
2055
  DISALLOW_COPY_AND_ASSIGN(Heap);
2056 2057 2058
};


ager@chromium.org's avatar
ager@chromium.org committed
2059 2060
class HeapStats {
 public:
2061 2062 2063
  static const int kStartMarker = 0xDECADE00;
  static const int kEndMarker = 0xDECADE01;

2064
  intptr_t* start_marker;                  //  0
2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075
  size_t* ro_space_size;                   //  1
  size_t* ro_space_capacity;               //  2
  size_t* new_space_size;                  //  3
  size_t* new_space_capacity;              //  4
  size_t* old_space_size;                  //  5
  size_t* old_space_capacity;              //  6
  size_t* code_space_size;                 //  7
  size_t* code_space_capacity;             //  8
  size_t* map_space_size;                  //  9
  size_t* map_space_capacity;              // 10
  size_t* lo_space_size;                   // 11
2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091
  size_t* code_lo_space_size;              // 12
  size_t* global_handle_count;             // 13
  size_t* weak_global_handle_count;        // 14
  size_t* pending_global_handle_count;     // 15
  size_t* near_death_global_handle_count;  // 16
  size_t* free_global_handle_count;        // 17
  size_t* memory_allocator_size;           // 18
  size_t* memory_allocator_capacity;       // 19
  size_t* malloced_memory;                 // 20
  size_t* malloced_peak_memory;            // 21
  size_t* objects_per_type;                // 22
  size_t* size_per_type;                   // 23
  int* os_error;                           // 24
  char* last_few_messages;                 // 25
  char* js_stacktrace;                     // 26
  intptr_t* end_marker;                    // 27
2092 2093 2094
};


2095 2096
class AlwaysAllocateScope {
 public:
2097
  explicit inline AlwaysAllocateScope(Heap* heap);
2098
  explicit inline AlwaysAllocateScope(Isolate* isolate);
2099
  inline ~AlwaysAllocateScope();
2100 2101

 private:
2102
  Heap* heap_;
2103 2104
};

2105
// The CodeSpaceMemoryModificationScope can only be used by the main thread.
2106 2107 2108 2109
class CodeSpaceMemoryModificationScope {
 public:
  explicit inline CodeSpaceMemoryModificationScope(Heap* heap);
  inline ~CodeSpaceMemoryModificationScope();
2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121

 private:
  Heap* heap_;
};

// The CodePageCollectionMemoryModificationScope can only be used by the main
// thread. It will not be enabled if a CodeSpaceMemoryModificationScope is
// already active.
class CodePageCollectionMemoryModificationScope {
 public:
  explicit inline CodePageCollectionMemoryModificationScope(Heap* heap);
  inline ~CodePageCollectionMemoryModificationScope();
2122 2123 2124 2125 2126

 private:
  Heap* heap_;
};

2127 2128 2129
// The CodePageMemoryModificationScope does not check if tansitions to
// writeable and back to executable are actually allowed, i.e. the MemoryChunk
// was registered to be executable. It can be used by concurrent threads.
2130 2131
class CodePageMemoryModificationScope {
 public:
2132
  explicit inline CodePageMemoryModificationScope(MemoryChunk* chunk);
2133 2134 2135 2136
  inline ~CodePageMemoryModificationScope();

 private:
  MemoryChunk* chunk_;
2137
  bool scope_active_;
2138 2139 2140

  // Disallow any GCs inside this scope, as a relocation of the underlying
  // object would change the {MemoryChunk} that this scope targets.
2141
  DISALLOW_HEAP_ALLOCATION(no_heap_allocation_)
2142
};
2143

2144 2145 2146 2147 2148
// Visitor class to verify interior pointers in spaces that do not contain
// or care about intergenerational references. All heap object pointers have to
// point into the heap to a location that has a map pointer at its first word.
// Caveat: Heap::Contains is an approximation because it can return true for
// objects in a heap space but above the allocation pointer.
2149
class VerifyPointersVisitor : public ObjectVisitor, public RootVisitor {
2150
 public:
2151
  explicit VerifyPointersVisitor(Heap* heap) : heap_(heap) {}
2152
  void VisitPointers(HeapObject host, ObjectSlot start,
2153
                     ObjectSlot end) override;
2154
  void VisitPointers(HeapObject host, MaybeObjectSlot start,
2155
                     MaybeObjectSlot end) override;
2156
  void VisitCodeTarget(Code host, RelocInfo* rinfo) override;
2157
  void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) override;
2158

2159 2160
  void VisitRootPointers(Root root, const char* description,
                         FullObjectSlot start, FullObjectSlot end) override;
2161

2162
 protected:
2163
  V8_INLINE void VerifyHeapObjectImpl(HeapObject heap_object);
2164 2165 2166 2167

  template <typename TSlot>
  V8_INLINE void VerifyPointersImpl(TSlot start, TSlot end);

2168
  virtual void VerifyPointers(HeapObject host, MaybeObjectSlot start,
2169
                              MaybeObjectSlot end);
2170 2171

  Heap* heap_;
2172 2173 2174
};


2175
// Verify that all objects are Smis.
2176
class VerifySmisVisitor : public RootVisitor {
2177
 public:
2178 2179
  void VisitRootPointers(Root root, const char* description,
                         FullObjectSlot start, FullObjectSlot end) override;
2180 2181
};

2182
// Space iterator for iterating over all the paged spaces of the heap: Map
2183 2184
// space, old space, code space and optionally read only space. Returns each
// space in turn, and null when it is done.
2185
class V8_EXPORT_PRIVATE PagedSpaces {
2186
 public:
2187 2188 2189 2190 2191 2192 2193
  enum class SpacesSpecifier { kSweepablePagedSpaces, kAllPagedSpaces };

  explicit PagedSpaces(Heap* heap, SpacesSpecifier specifier =
                                       SpacesSpecifier::kSweepablePagedSpaces)
      : heap_(heap),
        counter_(specifier == SpacesSpecifier::kAllPagedSpaces ? RO_SPACE
                                                               : OLD_SPACE) {}
2194
  PagedSpace* next();
2195

2196
 private:
2197
  Heap* heap_;
2198 2199 2200 2201
  int counter_;
};


2202 2203
class SpaceIterator : public Malloced {
 public:
2204
  explicit SpaceIterator(Heap* heap);
2205 2206 2207
  virtual ~SpaceIterator();

  bool has_next();
2208
  Space* next();
2209 2210

 private:
2211
  Heap* heap_;
2212
  int current_space_;         // from enum AllocationSpace.
2213 2214 2215
};


2216 2217 2218 2219
// A HeapIterator provides iteration over the whole heap. It
// aggregates the specific iterators for the different spaces as
// these can only iterate over one space only.
//
2220 2221 2222
// HeapIterator ensures there is no allocation during its lifetime
// (using an embedded DisallowHeapAllocation instance).
//
2223 2224 2225 2226 2227
// HeapIterator can skip free list nodes (that is, de-allocated heap
// objects that still remain in the heap). As implementation of free
// nodes filtering uses GC marks, it can't be used during MS/MC GC
// phases. Also, it is forbidden to interrupt iteration in this mode,
// as this will leave heap objects marked (and thus, unusable).
2228
class HeapIterator {
2229
 public:
2230 2231 2232 2233
  enum HeapObjectsFiltering { kNoFiltering, kFilterUnreachable };

  explicit HeapIterator(Heap* heap,
                        HeapObjectsFiltering filtering = kNoFiltering);
2234
  ~HeapIterator();
2235

2236
  HeapObject next();
2237 2238

 private:
2239
  HeapObject NextObject();
2240

2241
  DISALLOW_HEAP_ALLOCATION(no_heap_allocation_)
2242

2243
  Heap* heap_;
2244 2245
  HeapObjectsFiltering filtering_;
  HeapObjectsFilter* filter_;
2246 2247 2248
  // Space iterator for iterating all the spaces.
  SpaceIterator* space_iterator_;
  // Object iterator for the space currently being iterated.
2249
  std::unique_ptr<ObjectIterator> object_iterator_;
2250 2251
};

2252 2253 2254
// Abstract base class for checking whether a weak object should be retained.
class WeakObjectRetainer {
 public:
2255
  virtual ~WeakObjectRetainer() = default;
2256

2257
  // Return whether this object should be retained. If nullptr is returned the
2258 2259
  // object has no references. Otherwise the address of the retained object
  // should be returned as in some GC situations the object has been moved.
2260
  virtual Object RetainAs(Object object) = 0;
2261 2262
};

2263
// -----------------------------------------------------------------------------
2264 2265
// Allows observation of allocations.
class AllocationObserver {
2266
 public:
2267
  explicit AllocationObserver(intptr_t step_size)
2268
      : step_size_(step_size), bytes_to_next_step_(step_size) {
2269
    DCHECK_LE(kTaggedSize, step_size);
2270
  }
2271
  virtual ~AllocationObserver() = default;
2272

2273
  // Called each time the observed space does an allocation step. This may be
2274 2275
  // more frequently than the step_size we are monitoring (e.g. when there are
  // multiple observers, or when page or space boundary is encountered.)
2276
  void AllocationStep(int bytes_allocated, Address soon_object, size_t size);
2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302

 protected:
  intptr_t step_size() const { return step_size_; }
  intptr_t bytes_to_next_step() const { return bytes_to_next_step_; }

  // Pure virtual method provided by the subclasses that gets called when at
  // least step_size bytes have been allocated. soon_object is the address just
  // allocated (but not yet initialized.) size is the size of the object as
  // requested (i.e. w/o the alignment fillers). Some complexities to be aware
  // of:
  // 1) soon_object will be nullptr in cases where we end up observing an
  //    allocation that happens to be a filler space (e.g. page boundaries.)
  // 2) size is the requested size at the time of allocation. Right-trimming
  //    may change the object size dynamically.
  // 3) soon_object may actually be the first object in an allocation-folding
  //    group. In such a case size is the size of the group rather than the
  //    first object.
  virtual void Step(int bytes_allocated, Address soon_object, size_t size) = 0;

  // Subclasses can override this method to make step size dynamic.
  virtual intptr_t GetNextStepSize() { return step_size_; }

  intptr_t step_size_;
  intptr_t bytes_to_next_step_;

 private:
2303
  friend class Space;
2304
  DISALLOW_COPY_AND_ASSIGN(AllocationObserver);
2305 2306
};

2307 2308
V8_EXPORT_PRIVATE const char* AllocationSpaceName(AllocationSpace space);

2309 2310 2311 2312 2313 2314 2315 2316 2317 2318
// -----------------------------------------------------------------------------
// Allows observation of heap object allocations.
class HeapObjectAllocationTracker {
 public:
  virtual void AllocationEvent(Address addr, int size) = 0;
  virtual void MoveEvent(Address from, Address to, int size) {}
  virtual void UpdateObjectSizeEvent(Address addr, int size) {}
  virtual ~HeapObjectAllocationTracker() = default;
};

2319 2320
}  // namespace internal
}  // namespace v8
2321

2322
#endif  // V8_HEAP_HEAP_H_