Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_HEAP_HEAP_H_
6 : #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 : // Clients of this interface shouldn't depend on lots of heap internals.
15 : // 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 : #include "src/allocation.h"
20 : #include "src/assert-scope.h"
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"
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 : namespace debug {
36 : typedef void (*OutOfMemoryCallback)(void* data);
37 : } // namespace debug
38 :
39 : namespace internal {
40 :
41 : namespace heap {
42 : class HeapTester;
43 : class TestMemoryAllocatorScope;
44 : } // namespace heap
45 :
46 : class ObjectBoilerplateDescription;
47 : class BytecodeArray;
48 : class CodeDataContainer;
49 : class DeoptimizationData;
50 : class HandlerTable;
51 : class IncrementalMarking;
52 : class JSArrayBuffer;
53 : class ExternalString;
54 : using v8::MemoryPressureLevel;
55 :
56 : class AllocationObserver;
57 : class ArrayBufferCollector;
58 : class ArrayBufferTracker;
59 : class CodeLargeObjectSpace;
60 : class ConcurrentMarking;
61 : class GCIdleTimeAction;
62 : class GCIdleTimeHandler;
63 : class GCIdleTimeHeapState;
64 : class GCTracer;
65 : class HeapController;
66 : class HeapObjectAllocationTracker;
67 : class HeapObjectsFilter;
68 : class HeapStats;
69 : class HistogramTimer;
70 : class Isolate;
71 : class JSWeakFactory;
72 : class LocalEmbedderHeapTracer;
73 : class MemoryAllocator;
74 : class MemoryReducer;
75 : class MinorMarkCompactCollector;
76 : class ObjectIterator;
77 : class ObjectStats;
78 : class Page;
79 : class PagedSpace;
80 : class RootVisitor;
81 : class ScavengeJob;
82 : class Scavenger;
83 : class ScavengerCollector;
84 : class Space;
85 : class StoreBuffer;
86 : class StressScavengeObserver;
87 : class TimedHistogram;
88 : class TracePossibleWrapperReporter;
89 : class WeakObjectRetainer;
90 :
91 : enum ArrayStorageAllocationMode {
92 : DONT_INITIALIZE_ARRAY_ELEMENTS,
93 : INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE
94 : };
95 :
96 : enum class ClearRecordedSlots { kYes, kNo };
97 :
98 : enum class ClearFreedMemoryMode { kClearFreedMemory, kDontClearFreedMemory };
99 :
100 : enum ExternalBackingStoreType { kArrayBuffer, kExternalString, kNumTypes };
101 :
102 : enum class FixedArrayVisitationMode { kRegular, kIncremental };
103 :
104 : enum class TraceRetainingPathMode { kEnabled, kDisabled };
105 :
106 : enum class RetainingPathOption { kDefault, kTrackEphemeronPath };
107 :
108 : enum class GarbageCollectionReason {
109 : kUnknown = 0,
110 : kAllocationFailure = 1,
111 : kAllocationLimit = 2,
112 : kContextDisposal = 3,
113 : kCountersExtension = 4,
114 : kDebugger = 5,
115 : kDeserializer = 6,
116 : kExternalMemoryPressure = 7,
117 : kFinalizeMarkingViaStackGuard = 8,
118 : kFinalizeMarkingViaTask = 9,
119 : kFullHashtable = 10,
120 : kHeapProfiler = 11,
121 : kIdleTask = 12,
122 : kLastResort = 13,
123 : kLowMemoryNotification = 14,
124 : kMakeHeapIterable = 15,
125 : kMemoryPressure = 16,
126 : kMemoryReducer = 17,
127 : kRuntime = 18,
128 : kSamplingProfiler = 19,
129 : kSnapshotCreator = 20,
130 : kTesting = 21,
131 : kExternalFinalize = 22
132 : // If you add new items here, then update the incremental_marking_reason,
133 : // mark_compact_reason, and scavenge_reason counters in counters.h.
134 : // Also update src/tools/metrics/histograms/histograms.xml in chromium.
135 : };
136 :
137 : enum class YoungGenerationHandling {
138 : kRegularScavenge = 0,
139 : kFastPromotionDuringScavenge = 1,
140 : // Histogram::InspectConstructionArguments in chromium requires us to have at
141 : // least three buckets.
142 : kUnusedBucket = 2,
143 : // If you add new items here, then update the young_generation_handling in
144 : // counters.h.
145 : // Also update src/tools/metrics/histograms/histograms.xml in chromium.
146 : };
147 :
148 : class AllocationResult {
149 : public:
150 20217 : static inline AllocationResult Retry(AllocationSpace space = NEW_SPACE) {
151 20217 : return AllocationResult(space);
152 : }
153 :
154 : // Implicit constructor from Object.
155 529849584 : AllocationResult(Object object) // NOLINT
156 529849584 : : object_(object) {
157 : // AllocationResults can't return Smis, which are used to represent
158 : // failure and the space to retry in.
159 529640721 : CHECK(!object->IsSmi());
160 529640721 : }
161 :
162 724573476 : AllocationResult() : object_(Smi::FromInt(NEW_SPACE)) {}
163 :
164 1067032383 : inline bool IsRetry() { return object_->IsSmi(); }
165 : inline HeapObject ToObjectChecked();
166 : inline AllocationSpace RetrySpace();
167 :
168 : template <typename T>
169 1067032125 : bool To(T* obj) {
170 1066842396 : if (IsRetry()) return false;
171 1066233876 : *obj = T::cast(object_);
172 1066233876 : return true;
173 : }
174 :
175 : private:
176 : explicit AllocationResult(AllocationSpace space)
177 20627 : : object_(Smi::FromInt(static_cast<int>(space))) {}
178 :
179 : Object object_;
180 : };
181 :
182 : STATIC_ASSERT(sizeof(AllocationResult) == kSystemPointerSize);
183 :
184 : #ifdef DEBUG
185 : struct CommentStatistic {
186 : const char* comment;
187 : int size;
188 : int count;
189 : void Clear() {
190 : comment = nullptr;
191 : size = 0;
192 : count = 0;
193 : }
194 : // Must be small, since an iteration is used for lookup.
195 : static const int kMaxComments = 64;
196 : };
197 : #endif
198 :
199 188604 : class Heap {
200 : public:
201 : enum FindMementoMode { kForRuntime, kForGC };
202 :
203 : enum HeapState {
204 : NOT_IN_GC,
205 : SCAVENGE,
206 : MARK_COMPACT,
207 : MINOR_MARK_COMPACT,
208 : TEAR_DOWN
209 : };
210 :
211 : using PretenuringFeedbackMap =
212 : std::unordered_map<AllocationSite, size_t, Object::Hasher>;
213 :
214 : // Taking this mutex prevents the GC from entering a phase that relocates
215 : // object references.
216 : base::Mutex* relocation_mutex() { return &relocation_mutex_; }
217 :
218 : // Support for partial snapshots. After calling this we have a linear
219 : // space to write objects in each space.
220 : struct Chunk {
221 : uint32_t size;
222 : Address start;
223 : Address end;
224 : };
225 : typedef std::vector<Chunk> Reservation;
226 :
227 : static const int kInitalOldGenerationLimitFactor = 2;
228 :
229 : #if V8_OS_ANDROID
230 : // Don't apply pointer multiplier on Android since it has no swap space and
231 : // should instead adapt it's heap size based on available physical memory.
232 : static const int kPointerMultiplier = 1;
233 : #else
234 : // TODO(ishell): kSystePointerMultiplier?
235 : static const int kPointerMultiplier = i::kSystemPointerSize / 4;
236 : #endif
237 :
238 : // Semi-space size needs to be a multiple of page size.
239 : static const size_t kMinSemiSpaceSizeInKB =
240 : 1 * kPointerMultiplier * ((1 << kPageSizeBits) / KB);
241 : static const size_t kMaxSemiSpaceSizeInKB =
242 : 16 * kPointerMultiplier * ((1 << kPageSizeBits) / KB);
243 :
244 : static const int kTraceRingBufferSize = 512;
245 : static const int kStacktraceBufferSize = 512;
246 :
247 : static const int kNoGCFlags = 0;
248 : static const int kReduceMemoryFootprintMask = 1;
249 :
250 : // The minimum size of a HeapObject on the heap.
251 : static const int kMinObjectSizeInTaggedWords = 2;
252 :
253 : static const int kMinPromotedPercentForFastPromotionMode = 90;
254 :
255 : STATIC_ASSERT(static_cast<int>(RootIndex::kUndefinedValue) ==
256 : Internals::kUndefinedValueRootIndex);
257 : STATIC_ASSERT(static_cast<int>(RootIndex::kTheHoleValue) ==
258 : Internals::kTheHoleValueRootIndex);
259 : STATIC_ASSERT(static_cast<int>(RootIndex::kNullValue) ==
260 : Internals::kNullValueRootIndex);
261 : STATIC_ASSERT(static_cast<int>(RootIndex::kTrueValue) ==
262 : Internals::kTrueValueRootIndex);
263 : STATIC_ASSERT(static_cast<int>(RootIndex::kFalseValue) ==
264 : Internals::kFalseValueRootIndex);
265 : STATIC_ASSERT(static_cast<int>(RootIndex::kempty_string) ==
266 : Internals::kEmptyStringRootIndex);
267 :
268 : // Calculates the maximum amount of filler that could be required by the
269 : // given alignment.
270 : static int GetMaximumFillToAlign(AllocationAlignment alignment);
271 : // Calculates the actual amount of filler required for a given address at the
272 : // given alignment.
273 : static int GetFillToAlign(Address address, AllocationAlignment alignment);
274 :
275 : void FatalProcessOutOfMemory(const char* location);
276 :
277 : // Checks whether the space is valid.
278 : static bool IsValidAllocationSpace(AllocationSpace space);
279 :
280 : // Zapping is needed for verify heap, and always done in debug builds.
281 : static inline bool ShouldZapGarbage() {
282 : #ifdef DEBUG
283 : return true;
284 : #else
285 : #ifdef VERIFY_HEAP
286 : return FLAG_verify_heap;
287 : #else
288 : return false;
289 : #endif
290 : #endif
291 : }
292 :
293 : static uintptr_t ZapValue() {
294 0 : return FLAG_clear_free_memory ? kClearedFreeMemoryValue : kZapValue;
295 : }
296 :
297 : static inline bool IsYoungGenerationCollector(GarbageCollector collector) {
298 642496 : return collector == SCAVENGER || collector == MINOR_MARK_COMPACTOR;
299 : }
300 :
301 : static inline GarbageCollector YoungGenerationCollector() {
302 : #if ENABLE_MINOR_MC
303 23594 : return (FLAG_minor_mc) ? MINOR_MARK_COMPACTOR : SCAVENGER;
304 : #else
305 : return SCAVENGER;
306 : #endif // ENABLE_MINOR_MC
307 : }
308 :
309 : static inline const char* CollectorName(GarbageCollector collector) {
310 0 : switch (collector) {
311 : case SCAVENGER:
312 : return "Scavenger";
313 : case MARK_COMPACTOR:
314 : return "Mark-Compact";
315 : case MINOR_MARK_COMPACTOR:
316 : return "Minor Mark-Compact";
317 : }
318 : return "Unknown collector";
319 : }
320 :
321 : // Copy block of memory from src to dst. Size of block should be aligned
322 : // by pointer size.
323 : static inline void CopyBlock(Address dst, Address src, int byte_size);
324 :
325 : V8_EXPORT_PRIVATE static void WriteBarrierForCodeSlow(Code host);
326 : V8_EXPORT_PRIVATE static void GenerationalBarrierSlow(HeapObject object,
327 : Address slot,
328 : HeapObject value);
329 : V8_EXPORT_PRIVATE static void GenerationalBarrierForElementsSlow(
330 : Heap* heap, FixedArray array, int offset, int length);
331 : V8_EXPORT_PRIVATE static void GenerationalBarrierForCodeSlow(
332 : Code host, RelocInfo* rinfo, HeapObject value);
333 : V8_EXPORT_PRIVATE static void MarkingBarrierSlow(HeapObject object,
334 : Address slot,
335 : HeapObject value);
336 : V8_EXPORT_PRIVATE static void MarkingBarrierForElementsSlow(
337 : Heap* heap, HeapObject object);
338 : V8_EXPORT_PRIVATE static void MarkingBarrierForCodeSlow(Code host,
339 : RelocInfo* rinfo,
340 : HeapObject value);
341 : V8_EXPORT_PRIVATE static void MarkingBarrierForDescriptorArraySlow(
342 : Heap* heap, HeapObject host, HeapObject descriptor_array,
343 : int number_of_own_descriptors);
344 : V8_EXPORT_PRIVATE static bool PageFlagsAreConsistent(HeapObject object);
345 :
346 : // Notifies the heap that is ok to start marking or other activities that
347 : // should not happen during deserialization.
348 : void NotifyDeserializationComplete();
349 :
350 : inline Address* NewSpaceAllocationTopAddress();
351 : inline Address* NewSpaceAllocationLimitAddress();
352 : inline Address* OldSpaceAllocationTopAddress();
353 : inline Address* OldSpaceAllocationLimitAddress();
354 :
355 : // Move len elements within a given array from src_index index to dst_index
356 : // index.
357 : void MoveElements(FixedArray array, int dst_index, int src_index, int len,
358 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
359 :
360 : // Initialize a filler object to keep the ability to iterate over the heap
361 : // when introducing gaps within pages. If slots could have been recorded in
362 : // the freed area, then pass ClearRecordedSlots::kYes as the mode. Otherwise,
363 : // pass ClearRecordedSlots::kNo. If the memory after the object header of
364 : // the filler should be cleared, pass in kClearFreedMemory. The default is
365 : // kDontClearFreedMemory.
366 : V8_EXPORT_PRIVATE HeapObject CreateFillerObjectAt(
367 : Address addr, int size, ClearRecordedSlots clear_slots_mode,
368 : ClearFreedMemoryMode clear_memory_mode =
369 : ClearFreedMemoryMode::kDontClearFreedMemory);
370 :
371 : template <typename T>
372 2940327 : void CreateFillerForArray(T object, int elements_to_trim, int bytes_to_trim);
373 :
374 : bool CanMoveObjectStart(HeapObject object);
375 :
376 : bool IsImmovable(HeapObject object);
377 :
378 : bool IsLargeObject(HeapObject object);
379 : bool IsLargeMemoryChunk(MemoryChunk* chunk);
380 :
381 : bool IsInYoungGeneration(HeapObject object);
382 :
383 : // Trim the given array from the left. Note that this relocates the object
384 : // start and hence is only valid if there is only a single reference to it.
385 : FixedArrayBase LeftTrimFixedArray(FixedArrayBase obj, int elements_to_trim);
386 :
387 : // Trim the given array from the right.
388 : void RightTrimFixedArray(FixedArrayBase obj, int elements_to_trim);
389 : void RightTrimWeakFixedArray(WeakFixedArray obj, int elements_to_trim);
390 :
391 : // Converts the given boolean condition to JavaScript boolean value.
392 : inline Oddball ToBoolean(bool condition);
393 :
394 : // Notify the heap that a context has been disposed.
395 : int NotifyContextDisposed(bool dependant_context);
396 :
397 : void set_native_contexts_list(Object object) {
398 408239 : native_contexts_list_ = object;
399 : }
400 : Object native_contexts_list() const { return native_contexts_list_; }
401 :
402 : void set_allocation_sites_list(Object object) {
403 388579 : allocation_sites_list_ = object;
404 : }
405 : Object allocation_sites_list() { return allocation_sites_list_; }
406 :
407 : // Used in CreateAllocationSiteStub and the (de)serializer.
408 : Address allocation_sites_list_address() {
409 63275 : return reinterpret_cast<Address>(&allocation_sites_list_);
410 : }
411 :
412 : // Traverse all the allocaions_sites [nested_site and weak_next] in the list
413 : // and foreach call the visitor
414 : void ForeachAllocationSite(
415 : Object list, const std::function<void(AllocationSite)>& visitor);
416 :
417 : // Number of mark-sweeps.
418 20 : int ms_count() const { return ms_count_; }
419 :
420 : // Checks whether the given object is allowed to be migrated from it's
421 : // current space into the given destination space. Used for debugging.
422 : bool AllowedToBeMigrated(HeapObject object, AllocationSpace dest);
423 :
424 : void CheckHandleCount();
425 :
426 : // Number of "runtime allocations" done so far.
427 : uint32_t allocations_count() { return allocations_count_; }
428 :
429 : // Print short heap statistics.
430 : void PrintShortHeapStatistics();
431 :
432 : bool write_protect_code_memory() const { return write_protect_code_memory_; }
433 :
434 : uintptr_t code_space_memory_modification_scope_depth() {
435 : return code_space_memory_modification_scope_depth_;
436 : }
437 :
438 : void increment_code_space_memory_modification_scope_depth() {
439 465724 : code_space_memory_modification_scope_depth_++;
440 : }
441 :
442 : void decrement_code_space_memory_modification_scope_depth() {
443 465725 : code_space_memory_modification_scope_depth_--;
444 : }
445 :
446 : void UnprotectAndRegisterMemoryChunk(MemoryChunk* chunk);
447 : void UnprotectAndRegisterMemoryChunk(HeapObject object);
448 : void UnregisterUnprotectedMemoryChunk(MemoryChunk* chunk);
449 : V8_EXPORT_PRIVATE void ProtectUnprotectedMemoryChunks();
450 :
451 : void EnableUnprotectedMemoryChunksRegistry() {
452 2048526 : unprotected_memory_chunks_registry_enabled_ = true;
453 : }
454 :
455 : void DisableUnprotectedMemoryChunksRegistry() {
456 2048530 : unprotected_memory_chunks_registry_enabled_ = false;
457 : }
458 :
459 : bool unprotected_memory_chunks_registry_enabled() {
460 : return unprotected_memory_chunks_registry_enabled_;
461 : }
462 :
463 : inline HeapState gc_state() { return gc_state_; }
464 : void SetGCState(HeapState state);
465 : bool IsTearingDown() const { return gc_state_ == TEAR_DOWN; }
466 :
467 : inline bool IsInGCPostProcessing() { return gc_post_processing_depth_ > 0; }
468 :
469 : // If an object has an AllocationMemento trailing it, return it, otherwise
470 : // return a null AllocationMemento.
471 : template <FindMementoMode mode>
472 : inline AllocationMemento FindAllocationMemento(Map map, HeapObject object);
473 :
474 : // Returns false if not able to reserve.
475 : bool ReserveSpace(Reservation* reservations, std::vector<Address>* maps);
476 :
477 : //
478 : // Support for the API.
479 : //
480 :
481 : void CreateApiObjects();
482 :
483 : // Implements the corresponding V8 API function.
484 : bool IdleNotification(double deadline_in_seconds);
485 : bool IdleNotification(int idle_time_in_ms);
486 :
487 : void MemoryPressureNotification(MemoryPressureLevel level,
488 : bool is_isolate_locked);
489 : void CheckMemoryPressure();
490 :
491 : void AddNearHeapLimitCallback(v8::NearHeapLimitCallback, void* data);
492 : void RemoveNearHeapLimitCallback(v8::NearHeapLimitCallback callback,
493 : size_t heap_limit);
494 : void AutomaticallyRestoreInitialHeapLimit(double threshold_percent);
495 :
496 : double MonotonicallyIncreasingTimeInMs();
497 :
498 : void RecordStats(HeapStats* stats, bool take_snapshot = false);
499 :
500 : // Check new space expansion criteria and expand semispaces if it was hit.
501 : void CheckNewSpaceExpansionCriteria();
502 :
503 : void VisitExternalResources(v8::ExternalResourceVisitor* visitor);
504 :
505 : // An object should be promoted if the object has survived a
506 : // scavenge operation.
507 : inline bool ShouldBePromoted(Address old_address);
508 :
509 : void IncrementDeferredCount(v8::Isolate::UseCounterFeature feature);
510 :
511 : inline uint64_t HashSeed();
512 :
513 : inline int NextScriptId();
514 : inline int NextDebuggingId();
515 : inline int GetNextTemplateSerialNumber();
516 :
517 : void SetSerializedObjects(FixedArray objects);
518 : void SetSerializedGlobalProxySizes(FixedArray sizes);
519 :
520 : // For post mortem debugging.
521 : void RememberUnmappedPage(Address page, bool compacted);
522 :
523 1200546 : int64_t external_memory_hard_limit() { return MaxOldGenerationSize() / 2; }
524 :
525 : V8_INLINE int64_t external_memory();
526 : V8_INLINE void update_external_memory(int64_t delta);
527 : V8_INLINE void update_external_memory_concurrently_freed(intptr_t freed);
528 : V8_INLINE void account_external_memory_concurrently_freed();
529 :
530 : size_t backing_store_bytes() const { return backing_store_bytes_; }
531 :
532 : void CompactWeakArrayLists(PretenureFlag pretenure);
533 :
534 : void AddRetainedMap(Handle<Map> map);
535 :
536 : // This event is triggered after successful allocation of a new object made
537 : // by runtime. Allocations of target space for object evacuation do not
538 : // trigger the event. In order to track ALL allocations one must turn off
539 : // FLAG_inline_new.
540 : inline void OnAllocationEvent(HeapObject object, int size_in_bytes);
541 :
542 : // This event is triggered after object is moved to a new place.
543 : inline void OnMoveEvent(HeapObject target, HeapObject source,
544 : int size_in_bytes);
545 :
546 : inline bool CanAllocateInReadOnlySpace();
547 : bool deserialization_complete() const { return deserialization_complete_; }
548 :
549 : bool HasLowAllocationRate();
550 : bool HasHighFragmentation();
551 : bool HasHighFragmentation(size_t used, size_t committed);
552 :
553 : void ActivateMemoryReducerIfNeeded();
554 :
555 : bool ShouldOptimizeForMemoryUsage();
556 :
557 : bool HighMemoryPressure() {
558 : return memory_pressure_level_ != MemoryPressureLevel::kNone;
559 : }
560 :
561 5 : void RestoreHeapLimit(size_t heap_limit) {
562 : // Do not set the limit lower than the live size + some slack.
563 5 : size_t min_limit = SizeOfObjects() + SizeOfObjects() / 4;
564 : max_old_generation_size_ =
565 10 : Min(max_old_generation_size_, Max(heap_limit, min_limit));
566 5 : }
567 :
568 : // ===========================================================================
569 : // Initialization. ===========================================================
570 : // ===========================================================================
571 :
572 : // Configure heap sizes
573 : // max_semi_space_size_in_kb: maximum semi-space size in KB
574 : // max_old_generation_size_in_mb: maximum old generation size in MB
575 : // code_range_size_in_mb: code range size in MB
576 : void ConfigureHeap(size_t max_semi_space_size_in_kb,
577 : size_t max_old_generation_size_in_mb,
578 : size_t code_range_size_in_mb);
579 : void ConfigureHeapDefault();
580 :
581 : // Prepares the heap, setting up memory areas that are needed in the isolate
582 : // without actually creating any objects.
583 : void SetUp();
584 :
585 : // (Re-)Initialize hash seed from flag or RNG.
586 : void InitializeHashSeed();
587 :
588 : // Bootstraps the object heap with the core set of objects required to run.
589 : // Returns whether it succeeded.
590 : bool CreateHeapObjects();
591 :
592 : // Create ObjectStats if live_object_stats_ or dead_object_stats_ are nullptr.
593 : void CreateObjectStats();
594 :
595 : // Sets the TearDown state, so no new GC tasks get posted.
596 : void StartTearDown();
597 :
598 : // Destroys all memory allocated by the heap.
599 : void TearDown();
600 :
601 : // Returns whether SetUp has been called.
602 : bool HasBeenSetUp();
603 :
604 : // ===========================================================================
605 : // Getters for spaces. =======================================================
606 : // ===========================================================================
607 :
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 : MapSpace* map_space() { return map_space_; }
614 : 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 :
619 : inline PagedSpace* paged_space(int idx);
620 : inline Space* space(int idx);
621 :
622 : // Returns name of the space.
623 : const char* GetSpaceName(int idx);
624 :
625 : // ===========================================================================
626 : // Getters to other components. ==============================================
627 : // ===========================================================================
628 :
629 : GCTracer* tracer() { return tracer_; }
630 :
631 : MemoryAllocator* memory_allocator() { return memory_allocator_; }
632 :
633 : inline Isolate* isolate();
634 :
635 60936996 : MarkCompactCollector* mark_compact_collector() {
636 60936996 : return mark_compact_collector_;
637 : }
638 :
639 : MinorMarkCompactCollector* minor_mark_compact_collector() {
640 : return minor_mark_compact_collector_;
641 : }
642 :
643 : ArrayBufferCollector* array_buffer_collector() {
644 : return array_buffer_collector_;
645 : }
646 :
647 : // ===========================================================================
648 : // Root set access. ==========================================================
649 : // ===========================================================================
650 :
651 : // Shortcut to the roots table stored in the Isolate.
652 : V8_INLINE RootsTable& roots_table();
653 :
654 : // Heap root getters.
655 : #define ROOT_ACCESSOR(type, name, CamelName) inline type name();
656 : MUTABLE_ROOT_LIST(ROOT_ACCESSOR)
657 : #undef ROOT_ACCESSOR
658 :
659 : V8_INLINE void SetRootMaterializedObjects(FixedArray objects);
660 : V8_INLINE void SetRootScriptList(Object value);
661 : V8_INLINE void SetRootStringTable(StringTable value);
662 : V8_INLINE void SetRootNoScriptSharedFunctionInfos(Object value);
663 : V8_INLINE void SetMessageListeners(TemplateList value);
664 :
665 : // Set the stack limit in the roots table. Some architectures generate
666 : // code that looks here, because it is faster than loading from the static
667 : // jslimit_/real_jslimit_ variable in the StackGuard.
668 : void SetStackLimits();
669 :
670 : // The stack limit is thread-dependent. To be able to reproduce the same
671 : // snapshot blob, we need to reset it before serializing.
672 : void ClearStackLimits();
673 :
674 : void RegisterStrongRoots(FullObjectSlot start, FullObjectSlot end);
675 : void UnregisterStrongRoots(FullObjectSlot start);
676 :
677 : void SetBuiltinsConstantsTable(FixedArray cache);
678 :
679 : // A full copy of the interpreter entry trampoline, used as a template to
680 : // create copies of the builtin at runtime. The copies are used to create
681 : // better profiling information for ticks in bytecode execution. Note that
682 : // this is always a copy of the full builtin, i.e. not the off-heap
683 : // trampoline.
684 : // See also: FLAG_interpreted_frames_native_stack.
685 : void SetInterpreterEntryTrampolineForProfiling(Code code);
686 :
687 : // Add weak_factory into the dirty_js_weak_factories list.
688 : void AddDirtyJSWeakFactory(
689 : JSWeakFactory weak_factory,
690 : std::function<void(HeapObject object, ObjectSlot slot, Object target)>
691 : gc_notify_updated_slot);
692 :
693 : void AddKeepDuringJobTarget(Handle<JSReceiver> target);
694 : void ClearKeepDuringJobSet();
695 :
696 : // ===========================================================================
697 : // Inline allocation. ========================================================
698 : // ===========================================================================
699 :
700 : // Indicates whether inline bump-pointer allocation has been disabled.
701 : bool inline_allocation_disabled() { return inline_allocation_disabled_; }
702 :
703 : // Switch whether inline bump-pointer allocation should be used.
704 : void EnableInlineAllocation();
705 : void DisableInlineAllocation();
706 :
707 : // ===========================================================================
708 : // Methods triggering GCs. ===================================================
709 : // ===========================================================================
710 :
711 : // Performs garbage collection operation.
712 : // Returns whether there is a chance that another major GC could
713 : // collect more garbage.
714 : V8_EXPORT_PRIVATE bool CollectGarbage(
715 : AllocationSpace space, GarbageCollectionReason gc_reason,
716 : const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
717 :
718 : // Performs a full garbage collection.
719 : V8_EXPORT_PRIVATE void CollectAllGarbage(
720 : int flags, GarbageCollectionReason gc_reason,
721 : const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
722 :
723 : // Last hope GC, should try to squeeze as much as possible.
724 : void CollectAllAvailableGarbage(GarbageCollectionReason gc_reason);
725 :
726 : // Precise garbage collection that potentially finalizes already running
727 : // incremental marking before performing an atomic garbage collection.
728 : // Only use if absolutely necessary or in tests to avoid floating garbage!
729 : void PreciseCollectAllGarbage(
730 : int flags, GarbageCollectionReason gc_reason,
731 : const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
732 :
733 : // Reports and external memory pressure event, either performs a major GC or
734 : // completes incremental marking in order to free external resources.
735 : void ReportExternalMemoryPressure();
736 :
737 : typedef v8::Isolate::GetExternallyAllocatedMemoryInBytesCallback
738 : GetExternallyAllocatedMemoryInBytesCallback;
739 :
740 : void SetGetExternallyAllocatedMemoryInBytesCallback(
741 : GetExternallyAllocatedMemoryInBytesCallback callback) {
742 62883 : external_memory_callback_ = callback;
743 : }
744 :
745 : // Invoked when GC was requested via the stack guard.
746 : void HandleGCRequest();
747 :
748 : // ===========================================================================
749 : // Builtins. =================================================================
750 : // ===========================================================================
751 :
752 : Code builtin(int index);
753 : Address builtin_address(int index);
754 : void set_builtin(int index, Code builtin);
755 :
756 : // ===========================================================================
757 : // Iterators. ================================================================
758 : // ===========================================================================
759 :
760 : // None of these methods iterate over the read-only roots. To do this use
761 : // ReadOnlyRoots::Iterate. Read-only root iteration is not necessary for
762 : // garbage collection and is usually only performed as part of
763 : // (de)serialization or heap verification.
764 :
765 : // Iterates over the strong roots and the weak roots.
766 : void IterateRoots(RootVisitor* v, VisitMode mode);
767 : // Iterates over the strong roots.
768 : void IterateStrongRoots(RootVisitor* v, VisitMode mode);
769 : // Iterates over entries in the smi roots list. Only interesting to the
770 : // serializer/deserializer, since GC does not care about smis.
771 : void IterateSmiRoots(RootVisitor* v);
772 : // Iterates over weak string tables.
773 : void IterateWeakRoots(RootVisitor* v, VisitMode mode);
774 : // Iterates over weak global handles.
775 : void IterateWeakGlobalHandles(RootVisitor* v);
776 : // Iterates over builtins.
777 : void IterateBuiltins(RootVisitor* v);
778 :
779 : // ===========================================================================
780 : // Store buffer API. =========================================================
781 : // ===========================================================================
782 :
783 : // Used for query incremental marking status in generated code.
784 : Address* IsMarkingFlagAddress() {
785 : return reinterpret_cast<Address*>(&is_marking_flag_);
786 : }
787 :
788 176245 : void SetIsMarkingFlag(uint8_t flag) { is_marking_flag_ = flag; }
789 :
790 : Address* store_buffer_top_address();
791 : static intptr_t store_buffer_mask_constant();
792 : static Address store_buffer_overflow_function_address();
793 :
794 : void ClearRecordedSlot(HeapObject object, ObjectSlot slot);
795 : void ClearRecordedSlotRange(Address start, Address end);
796 :
797 : #ifdef DEBUG
798 : void VerifyClearedSlot(HeapObject object, ObjectSlot slot);
799 : #endif
800 :
801 : // ===========================================================================
802 : // Incremental marking API. ==================================================
803 : // ===========================================================================
804 :
805 : int GCFlagsForIncrementalMarking() {
806 1702066 : return ShouldOptimizeForMemoryUsage() ? kReduceMemoryFootprintMask
807 1702067 : : kNoGCFlags;
808 : }
809 :
810 : // Start incremental marking and ensure that idle time handler can perform
811 : // incremental steps.
812 : void StartIdleIncrementalMarking(
813 : GarbageCollectionReason gc_reason,
814 : GCCallbackFlags gc_callback_flags = GCCallbackFlags::kNoGCCallbackFlags);
815 :
816 : // Starts incremental marking assuming incremental marking is currently
817 : // stopped.
818 : void StartIncrementalMarking(
819 : int gc_flags, GarbageCollectionReason gc_reason,
820 : GCCallbackFlags gc_callback_flags = GCCallbackFlags::kNoGCCallbackFlags);
821 :
822 : void StartIncrementalMarkingIfAllocationLimitIsReached(
823 : int gc_flags,
824 : GCCallbackFlags gc_callback_flags = GCCallbackFlags::kNoGCCallbackFlags);
825 :
826 : void FinalizeIncrementalMarkingIfComplete(GarbageCollectionReason gc_reason);
827 : // Synchronously finalizes incremental marking.
828 : void FinalizeIncrementalMarkingAtomically(GarbageCollectionReason gc_reason);
829 :
830 : void RegisterDeserializedObjectsForBlackAllocation(
831 : Reservation* reservations, const std::vector<HeapObject>& large_objects,
832 : const std::vector<Address>& maps);
833 :
834 49237 : IncrementalMarking* incremental_marking() { return incremental_marking_; }
835 :
836 : // ===========================================================================
837 : // Concurrent marking API. ===================================================
838 : // ===========================================================================
839 :
840 : ConcurrentMarking* concurrent_marking() { return concurrent_marking_; }
841 :
842 : // The runtime uses this function to notify potentially unsafe object layout
843 : // changes that require special synchronization with the concurrent marker.
844 : // The old size is the size of the object before layout change.
845 : void NotifyObjectLayoutChange(HeapObject object, int old_size,
846 : const DisallowHeapAllocation&);
847 :
848 : #ifdef VERIFY_HEAP
849 : // This function checks that either
850 : // - the map transition is safe,
851 : // - or it was communicated to GC using NotifyObjectLayoutChange.
852 : void VerifyObjectLayoutChange(HeapObject object, Map new_map);
853 : #endif
854 :
855 : // ===========================================================================
856 : // Deoptimization support API. ===============================================
857 : // ===========================================================================
858 :
859 : // Setters for code offsets of well-known deoptimization targets.
860 : void SetArgumentsAdaptorDeoptPCOffset(int pc_offset);
861 : void SetConstructStubCreateDeoptPCOffset(int pc_offset);
862 : void SetConstructStubInvokeDeoptPCOffset(int pc_offset);
863 : void SetInterpreterEntryReturnPCOffset(int pc_offset);
864 :
865 : // Invalidates references in the given {code} object that are referenced
866 : // transitively from the deoptimization data. Mutates write-protected code.
867 : void InvalidateCodeDeoptimizationData(Code code);
868 :
869 : void DeoptMarkedAllocationSites();
870 :
871 : bool DeoptMaybeTenuredAllocationSites();
872 :
873 : // ===========================================================================
874 : // Embedder heap tracer support. =============================================
875 : // ===========================================================================
876 :
877 223634 : LocalEmbedderHeapTracer* local_embedder_heap_tracer() const {
878 223634 : return local_embedder_heap_tracer_;
879 : }
880 :
881 : void SetEmbedderHeapTracer(EmbedderHeapTracer* tracer);
882 : EmbedderHeapTracer* GetEmbedderHeapTracer() const;
883 :
884 : void RegisterExternallyReferencedObject(Address* location);
885 : void SetEmbedderStackStateForNextFinalizaton(
886 : EmbedderHeapTracer::EmbedderStackState stack_state);
887 :
888 : // ===========================================================================
889 : // External string table API. ================================================
890 : // ===========================================================================
891 :
892 : // Registers an external string.
893 : inline void RegisterExternalString(String string);
894 :
895 : // Called when a string's resource is changed. The size of the payload is sent
896 : // as argument of the method.
897 : inline void UpdateExternalString(String string, size_t old_payload,
898 : size_t new_payload);
899 :
900 : // Finalizes an external string by deleting the associated external
901 : // data and clearing the resource pointer.
902 : inline void FinalizeExternalString(String string);
903 :
904 : static String UpdateNewSpaceReferenceInExternalStringTableEntry(
905 : Heap* heap, FullObjectSlot pointer);
906 :
907 : // ===========================================================================
908 : // Methods checking/returning the space of a given object/address. ===========
909 : // ===========================================================================
910 :
911 : // Returns whether the object resides in new space.
912 : static inline bool InNewSpace(Object object);
913 : static inline bool InNewSpace(MaybeObject object);
914 : static inline bool InNewSpace(HeapObject heap_object);
915 : static inline bool InFromSpace(Object object);
916 : static inline bool InFromSpace(MaybeObject object);
917 : static inline bool InFromSpace(HeapObject heap_object);
918 : static inline bool InToSpace(Object object);
919 : static inline bool InToSpace(MaybeObject object);
920 : static inline bool InToSpace(HeapObject heap_object);
921 :
922 : // Returns whether the object resides in old space.
923 : inline bool InOldSpace(Object object);
924 :
925 : // Returns whether the object resides in read-only space.
926 : inline bool InReadOnlySpace(Object object);
927 :
928 : // Checks whether an address/object in the heap (including auxiliary
929 : // area and unused area).
930 : bool Contains(HeapObject value);
931 :
932 : // Checks whether an address/object in a space.
933 : // Currently used by tests, serialization and heap verification only.
934 : bool InSpace(HeapObject value, AllocationSpace space);
935 :
936 : // Slow methods that can be used for verification as they can also be used
937 : // with off-heap Addresses.
938 : bool InSpaceSlow(Address addr, AllocationSpace space);
939 :
940 : static inline Heap* FromWritableHeapObject(const HeapObject obj);
941 :
942 : // ===========================================================================
943 : // Object statistics tracking. ===============================================
944 : // ===========================================================================
945 :
946 : // Returns the number of buckets used by object statistics tracking during a
947 : // major GC. Note that the following methods fail gracefully when the bounds
948 : // are exceeded though.
949 : size_t NumberOfTrackedHeapObjectTypes();
950 :
951 : // Returns object statistics about count and size at the last major GC.
952 : // Objects are being grouped into buckets that roughly resemble existing
953 : // instance types.
954 : size_t ObjectCountAtLastGC(size_t index);
955 : size_t ObjectSizeAtLastGC(size_t index);
956 :
957 : // Retrieves names of buckets used by object statistics tracking.
958 : bool GetObjectTypeName(size_t index, const char** object_type,
959 : const char** object_sub_type);
960 :
961 : // The total number of native contexts object on the heap.
962 : size_t NumberOfNativeContexts();
963 : // The total number of native contexts that were detached but were not
964 : // garbage collected yet.
965 : size_t NumberOfDetachedContexts();
966 :
967 : // ===========================================================================
968 : // Code statistics. ==========================================================
969 : // ===========================================================================
970 :
971 : // Collect code (Code and BytecodeArray objects) statistics.
972 : void CollectCodeStatistics();
973 :
974 : // ===========================================================================
975 : // GC statistics. ============================================================
976 : // ===========================================================================
977 :
978 : // Returns the maximum amount of memory reserved for the heap.
979 : size_t MaxReserved();
980 : size_t MaxSemiSpaceSize() { return max_semi_space_size_; }
981 : size_t InitialSemiSpaceSize() { return initial_semispace_size_; }
982 : size_t MaxOldGenerationSize() { return max_old_generation_size_; }
983 :
984 : V8_EXPORT_PRIVATE static size_t ComputeMaxOldGenerationSize(
985 : uint64_t physical_memory);
986 :
987 : static size_t ComputeMaxSemiSpaceSize(uint64_t physical_memory) {
988 : const uint64_t min_physical_memory = 512 * MB;
989 : const uint64_t max_physical_memory = 3 * static_cast<uint64_t>(GB);
990 :
991 : uint64_t capped_physical_memory =
992 : Max(Min(physical_memory, max_physical_memory), min_physical_memory);
993 : // linearly scale max semi-space size: (X-A)/(B-A)*(D-C)+C
994 : size_t semi_space_size_in_kb =
995 28773 : static_cast<size_t>(((capped_physical_memory - min_physical_memory) *
996 28773 : (kMaxSemiSpaceSizeInKB - kMinSemiSpaceSizeInKB)) /
997 : (max_physical_memory - min_physical_memory) +
998 : kMinSemiSpaceSizeInKB);
999 : return RoundUp(semi_space_size_in_kb, (1 << kPageSizeBits) / KB);
1000 : }
1001 :
1002 : // Returns the capacity of the heap in bytes w/o growing. Heap grows when
1003 : // more spaces are needed until it reaches the limit.
1004 : size_t Capacity();
1005 :
1006 : // Returns the capacity of the old generation.
1007 : size_t OldGenerationCapacity();
1008 :
1009 : // Returns the amount of memory currently held alive by the unmapper.
1010 : size_t CommittedMemoryOfUnmapper();
1011 :
1012 : // Returns the amount of memory currently committed for the heap.
1013 : size_t CommittedMemory();
1014 :
1015 : // Returns the amount of memory currently committed for the old space.
1016 : size_t CommittedOldGenerationMemory();
1017 :
1018 : // Returns the amount of executable memory currently committed for the heap.
1019 : size_t CommittedMemoryExecutable();
1020 :
1021 : // Returns the amount of phyical memory currently committed for the heap.
1022 : size_t CommittedPhysicalMemory();
1023 :
1024 : // Returns the maximum amount of memory ever committed for the heap.
1025 : size_t MaximumCommittedMemory() { return maximum_committed_; }
1026 :
1027 : // Updates the maximum committed memory for the heap. Should be called
1028 : // whenever a space grows.
1029 : void UpdateMaximumCommitted();
1030 :
1031 : // Returns the available bytes in space w/o growing.
1032 : // Heap doesn't guarantee that it can allocate an object that requires
1033 : // all available bytes. Check MaxHeapObjectSize() instead.
1034 : size_t Available();
1035 :
1036 : // Returns of size of all objects residing in the heap.
1037 : size_t SizeOfObjects();
1038 :
1039 : void UpdateSurvivalStatistics(int start_new_space_size);
1040 :
1041 : inline void IncrementPromotedObjectsSize(size_t object_size) {
1042 123179 : promoted_objects_size_ += object_size;
1043 : }
1044 : inline size_t promoted_objects_size() { return promoted_objects_size_; }
1045 :
1046 : inline void IncrementSemiSpaceCopiedObjectSize(size_t object_size) {
1047 123179 : semi_space_copied_object_size_ += object_size;
1048 : }
1049 : inline size_t semi_space_copied_object_size() {
1050 : return semi_space_copied_object_size_;
1051 : }
1052 :
1053 : inline size_t SurvivedNewSpaceObjectSize() {
1054 154254 : return promoted_objects_size_ + semi_space_copied_object_size_;
1055 : }
1056 :
1057 3170661 : inline void IncrementNodesDiedInNewSpace() { nodes_died_in_new_space_++; }
1058 :
1059 1790598 : inline void IncrementNodesCopiedInNewSpace() { nodes_copied_in_new_space_++; }
1060 :
1061 324718 : inline void IncrementNodesPromoted() { nodes_promoted_++; }
1062 :
1063 : inline void IncrementYoungSurvivorsCounter(size_t survived) {
1064 109144 : survived_last_scavenge_ = survived;
1065 109144 : survived_since_last_expansion_ += survived;
1066 : }
1067 :
1068 487242 : inline uint64_t OldGenerationObjectsAndPromotedExternalMemorySize() {
1069 974314 : return OldGenerationSizeOfObjects() + PromotedExternalMemorySize();
1070 : }
1071 :
1072 : inline void UpdateNewSpaceAllocationCounter();
1073 :
1074 : inline size_t NewSpaceAllocationCounter();
1075 :
1076 : // This should be used only for testing.
1077 : void set_new_space_allocation_counter(size_t new_value) {
1078 5 : new_space_allocation_counter_ = new_value;
1079 : }
1080 :
1081 : void UpdateOldGenerationAllocationCounter() {
1082 : old_generation_allocation_counter_at_last_gc_ =
1083 83492 : OldGenerationAllocationCounter();
1084 83492 : old_generation_size_at_last_gc_ = 0;
1085 : }
1086 :
1087 : size_t OldGenerationAllocationCounter() {
1088 286608 : return old_generation_allocation_counter_at_last_gc_ +
1089 286613 : PromotedSinceLastGC();
1090 : }
1091 :
1092 : // This should be used only for testing.
1093 : void set_old_generation_allocation_counter_at_last_gc(size_t new_value) {
1094 5 : old_generation_allocation_counter_at_last_gc_ = new_value;
1095 : }
1096 :
1097 : size_t PromotedSinceLastGC() {
1098 286613 : size_t old_generation_size = OldGenerationSizeOfObjects();
1099 : DCHECK_GE(old_generation_size, old_generation_size_at_last_gc_);
1100 286613 : return old_generation_size - old_generation_size_at_last_gc_;
1101 : }
1102 :
1103 : // This is called by the sweeper when it discovers more free space
1104 : // than expected at the end of the preceding GC.
1105 : void NotifyRefinedOldGenerationSize(size_t decreased_bytes) {
1106 12438 : if (old_generation_size_at_last_gc_ != 0) {
1107 : // OldGenerationSizeOfObjects() is now smaller by |decreased_bytes|.
1108 : // Adjust old_generation_size_at_last_gc_ too, so that PromotedSinceLastGC
1109 : // continues to increase monotonically, rather than decreasing here.
1110 : DCHECK_GE(old_generation_size_at_last_gc_, decreased_bytes);
1111 6835 : old_generation_size_at_last_gc_ -= decreased_bytes;
1112 : }
1113 : }
1114 :
1115 69176419 : int gc_count() const { return gc_count_; }
1116 :
1117 1789328 : bool is_current_gc_forced() const { return is_current_gc_forced_; }
1118 :
1119 : // Returns the size of objects residing in non-new spaces.
1120 : // Excludes external memory held by those objects.
1121 : size_t OldGenerationSizeOfObjects();
1122 :
1123 : // ===========================================================================
1124 : // Prologue/epilogue callback methods.========================================
1125 : // ===========================================================================
1126 :
1127 : void AddGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
1128 : GCType gc_type_filter, void* data);
1129 : void RemoveGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
1130 : void* data);
1131 :
1132 : void AddGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback,
1133 : GCType gc_type_filter, void* data);
1134 : void RemoveGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback,
1135 : void* data);
1136 :
1137 : void CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags);
1138 : void CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags);
1139 :
1140 : // ===========================================================================
1141 : // Allocation methods. =======================================================
1142 : // ===========================================================================
1143 :
1144 : // Creates a filler object and returns a heap object immediately after it.
1145 : V8_WARN_UNUSED_RESULT HeapObject PrecedeWithFiller(HeapObject object,
1146 : int filler_size);
1147 :
1148 : // Creates a filler object if needed for alignment and returns a heap object
1149 : // immediately after it. If any space is left after the returned object,
1150 : // another filler object is created so the over allocated memory is iterable.
1151 : V8_WARN_UNUSED_RESULT HeapObject
1152 : AlignWithFiller(HeapObject object, int object_size, int allocation_size,
1153 : AllocationAlignment alignment);
1154 :
1155 : // ===========================================================================
1156 : // ArrayBuffer tracking. =====================================================
1157 : // ===========================================================================
1158 :
1159 : // TODO(gc): API usability: encapsulate mutation of JSArrayBuffer::is_external
1160 : // in the registration/unregistration APIs. Consider dropping the "New" from
1161 : // "RegisterNewArrayBuffer" because one can re-register a previously
1162 : // unregistered buffer, too, and the name is confusing.
1163 : void RegisterNewArrayBuffer(JSArrayBuffer buffer);
1164 : void UnregisterArrayBuffer(JSArrayBuffer buffer);
1165 :
1166 : // ===========================================================================
1167 : // Allocation site tracking. =================================================
1168 : // ===========================================================================
1169 :
1170 : // Updates the AllocationSite of a given {object}. The entry (including the
1171 : // count) is cached on the local pretenuring feedback.
1172 : inline void UpdateAllocationSite(
1173 : Map map, HeapObject object, PretenuringFeedbackMap* pretenuring_feedback);
1174 :
1175 : // Merges local pretenuring feedback into the global one. Note that this
1176 : // method needs to be called after evacuation, as allocation sites may be
1177 : // evacuated and this method resolves forward pointers accordingly.
1178 : void MergeAllocationSitePretenuringFeedback(
1179 : const PretenuringFeedbackMap& local_pretenuring_feedback);
1180 :
1181 : // ===========================================================================
1182 : // Allocation tracking. ======================================================
1183 : // ===========================================================================
1184 :
1185 : // Adds {new_space_observer} to new space and {observer} to any other space.
1186 : void AddAllocationObserversToAllSpaces(
1187 : AllocationObserver* observer, AllocationObserver* new_space_observer);
1188 :
1189 : // Removes {new_space_observer} from new space and {observer} from any other
1190 : // space.
1191 : void RemoveAllocationObserversFromAllSpaces(
1192 : AllocationObserver* observer, AllocationObserver* new_space_observer);
1193 :
1194 : bool allocation_step_in_progress() { return allocation_step_in_progress_; }
1195 : void set_allocation_step_in_progress(bool val) {
1196 44846478 : allocation_step_in_progress_ = val;
1197 : }
1198 :
1199 : // ===========================================================================
1200 : // Heap object allocation tracking. ==========================================
1201 : // ===========================================================================
1202 :
1203 : void AddHeapObjectAllocationTracker(HeapObjectAllocationTracker* tracker);
1204 : void RemoveHeapObjectAllocationTracker(HeapObjectAllocationTracker* tracker);
1205 : bool has_heap_object_allocation_tracker() const {
1206 : return !allocation_trackers_.empty();
1207 : }
1208 :
1209 : // ===========================================================================
1210 : // Retaining path tracking. ==================================================
1211 : // ===========================================================================
1212 :
1213 : // Adds the given object to the weak table of retaining path targets.
1214 : // On each GC if the marker discovers the object, it will print the retaining
1215 : // path. This requires --track-retaining-path flag.
1216 : void AddRetainingPathTarget(Handle<HeapObject> object,
1217 : RetainingPathOption option);
1218 :
1219 : // ===========================================================================
1220 : // Stack frame support. ======================================================
1221 : // ===========================================================================
1222 :
1223 : // Returns the Code object for a given interior pointer.
1224 : Code GcSafeFindCodeForInnerPointer(Address inner_pointer);
1225 :
1226 : // Returns true if {addr} is contained within {code} and false otherwise.
1227 : // Mostly useful for debugging.
1228 : bool GcSafeCodeContains(Code code, Address addr);
1229 :
1230 : // =============================================================================
1231 : #ifdef VERIFY_HEAP
1232 : // Verify the heap is in its normal state before or after a GC.
1233 : void Verify();
1234 : void VerifyRememberedSetFor(HeapObject object);
1235 : #endif
1236 :
1237 : #ifdef V8_ENABLE_ALLOCATION_TIMEOUT
1238 : void set_allocation_timeout(int timeout) { allocation_timeout_ = timeout; }
1239 : #endif
1240 :
1241 : #ifdef DEBUG
1242 : void VerifyCountersAfterSweeping();
1243 : void VerifyCountersBeforeConcurrentSweeping();
1244 :
1245 : void Print();
1246 : void PrintHandles();
1247 :
1248 : // Report code statistics.
1249 : void ReportCodeStatistics(const char* title);
1250 : #endif
1251 : void* GetRandomMmapAddr() {
1252 763186 : void* result = v8::internal::GetRandomMmapAddr();
1253 : #if V8_TARGET_ARCH_X64
1254 : #if V8_OS_MACOSX
1255 : // The Darwin kernel [as of macOS 10.12.5] does not clean up page
1256 : // directory entries [PDE] created from mmap or mach_vm_allocate, even
1257 : // after the region is destroyed. Using a virtual address space that is
1258 : // too large causes a leak of about 1 wired [can never be paged out] page
1259 : // per call to mmap(). The page is only reclaimed when the process is
1260 : // killed. Confine the hint to a 32-bit section of the virtual address
1261 : // space. See crbug.com/700928.
1262 : uintptr_t offset =
1263 : reinterpret_cast<uintptr_t>(v8::internal::GetRandomMmapAddr()) &
1264 : kMmapRegionMask;
1265 : result = reinterpret_cast<void*>(mmap_region_base_ + offset);
1266 : #endif // V8_OS_MACOSX
1267 : #endif // V8_TARGET_ARCH_X64
1268 : return result;
1269 : }
1270 :
1271 : static const char* GarbageCollectionReasonToString(
1272 : GarbageCollectionReason gc_reason);
1273 :
1274 : // Calculates the nof entries for the full sized number to string cache.
1275 : inline int MaxNumberToStringCacheSize() const;
1276 :
1277 : private:
1278 : class SkipStoreBufferScope;
1279 :
1280 : typedef String (*ExternalStringTableUpdaterCallback)(Heap* heap,
1281 : FullObjectSlot pointer);
1282 :
1283 : // External strings table is a place where all external strings are
1284 : // registered. We need to keep track of such strings to properly
1285 : // finalize them.
1286 125736 : class ExternalStringTable {
1287 : public:
1288 62883 : explicit ExternalStringTable(Heap* heap) : heap_(heap) {}
1289 :
1290 : // Registers an external string.
1291 : inline void AddString(String string);
1292 : bool Contains(String string);
1293 :
1294 : void IterateAll(RootVisitor* v);
1295 : void IterateNewSpaceStrings(RootVisitor* v);
1296 : void PromoteAllNewSpaceStrings();
1297 :
1298 : // Restores internal invariant and gets rid of collected strings. Must be
1299 : // called after each Iterate*() that modified the strings.
1300 : void CleanUpAll();
1301 : void CleanUpNewSpaceStrings();
1302 :
1303 : // Finalize all registered external strings and clear tables.
1304 : void TearDown();
1305 :
1306 : void UpdateNewSpaceReferences(
1307 : Heap::ExternalStringTableUpdaterCallback updater_func);
1308 : void UpdateReferences(
1309 : Heap::ExternalStringTableUpdaterCallback updater_func);
1310 :
1311 : private:
1312 : void Verify();
1313 : void VerifyNewSpace();
1314 :
1315 : Heap* const heap_;
1316 :
1317 : // To speed up scavenge collections new space string are kept
1318 : // separate from old space strings.
1319 : std::vector<Object> new_space_strings_;
1320 : std::vector<Object> old_space_strings_;
1321 :
1322 : DISALLOW_COPY_AND_ASSIGN(ExternalStringTable);
1323 : };
1324 :
1325 : struct StrongRootsList;
1326 :
1327 : struct StringTypeTable {
1328 : InstanceType type;
1329 : int size;
1330 : RootIndex index;
1331 : };
1332 :
1333 : struct ConstantStringTable {
1334 : const char* contents;
1335 : RootIndex index;
1336 : };
1337 :
1338 : struct StructTable {
1339 : InstanceType type;
1340 : int size;
1341 : RootIndex index;
1342 : };
1343 :
1344 8260 : struct GCCallbackTuple {
1345 : GCCallbackTuple(v8::Isolate::GCCallbackWithData callback, GCType gc_type,
1346 : void* data)
1347 71148 : : callback(callback), gc_type(gc_type), data(data) {}
1348 :
1349 : bool operator==(const GCCallbackTuple& other) const;
1350 : GCCallbackTuple& operator=(const GCCallbackTuple& other) V8_NOEXCEPT;
1351 :
1352 : v8::Isolate::GCCallbackWithData callback;
1353 : GCType gc_type;
1354 : void* data;
1355 : };
1356 :
1357 : static const int kInitialStringTableSize = StringTable::kMinCapacity;
1358 : static const int kInitialEvalCacheSize = 64;
1359 : static const int kInitialNumberStringCacheSize = 256;
1360 :
1361 : static const int kRememberedUnmappedPages = 128;
1362 :
1363 : static const StringTypeTable string_type_table[];
1364 : static const ConstantStringTable constant_string_table[];
1365 : static const StructTable struct_table[];
1366 :
1367 : static const int kYoungSurvivalRateHighThreshold = 90;
1368 : static const int kYoungSurvivalRateAllowedDeviation = 15;
1369 : static const int kOldSurvivalRateLowThreshold = 10;
1370 :
1371 : static const int kMaxMarkCompactsInIdleRound = 7;
1372 : static const int kIdleScavengeThreshold = 5;
1373 :
1374 : static const int kInitialFeedbackCapacity = 256;
1375 :
1376 : Heap();
1377 :
1378 : // Selects the proper allocation space based on the pretenuring decision.
1379 282580562 : static AllocationSpace SelectSpace(PretenureFlag pretenure) {
1380 282580562 : switch (pretenure) {
1381 : case TENURED_READ_ONLY:
1382 : return RO_SPACE;
1383 : case TENURED:
1384 124962810 : return OLD_SPACE;
1385 : case NOT_TENURED:
1386 157361470 : return NEW_SPACE;
1387 : default:
1388 0 : UNREACHABLE();
1389 : }
1390 : }
1391 :
1392 0 : static size_t DefaultGetExternallyAllocatedMemoryInBytesCallback() {
1393 0 : return 0;
1394 : }
1395 :
1396 : #define ROOT_ACCESSOR(type, name, CamelName) inline void set_##name(type value);
1397 : ROOT_LIST(ROOT_ACCESSOR)
1398 : #undef ROOT_ACCESSOR
1399 :
1400 : StoreBuffer* store_buffer() { return store_buffer_; }
1401 :
1402 : void set_current_gc_flags(int flags) {
1403 131460 : current_gc_flags_ = flags;
1404 : }
1405 :
1406 : inline bool ShouldReduceMemory() const {
1407 1204425 : return (current_gc_flags_ & kReduceMemoryFootprintMask) != 0;
1408 : }
1409 :
1410 : int NumberOfScavengeTasks();
1411 :
1412 : // Checks whether a global GC is necessary
1413 : GarbageCollector SelectGarbageCollector(AllocationSpace space,
1414 : const char** reason);
1415 :
1416 : // Make sure there is a filler value behind the top of the new space
1417 : // so that the GC does not confuse some unintialized/stale memory
1418 : // with the allocation memento of the object at the top
1419 : void EnsureFillerObjectAtTop();
1420 :
1421 : // Ensure that we have swept all spaces in such a way that we can iterate
1422 : // over all objects. May cause a GC.
1423 : void MakeHeapIterable();
1424 :
1425 : // Performs garbage collection
1426 : // Returns whether there is a chance another major GC could
1427 : // collect more garbage.
1428 : bool PerformGarbageCollection(
1429 : GarbageCollector collector,
1430 : const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
1431 :
1432 : inline void UpdateOldSpaceLimits();
1433 :
1434 : bool CreateInitialMaps();
1435 : void CreateInternalAccessorInfoObjects();
1436 : void CreateInitialObjects();
1437 :
1438 : // Commits from space if it is uncommitted.
1439 : void EnsureFromSpaceIsCommitted();
1440 :
1441 : // Uncommit unused semi space.
1442 : bool UncommitFromSpace();
1443 :
1444 : // Fill in bogus values in from space
1445 : void ZapFromSpace();
1446 :
1447 : // Zaps the memory of a code object.
1448 : void ZapCodeObject(Address start_address, int size_in_bytes);
1449 :
1450 : // Deopts all code that contains allocation instruction which are tenured or
1451 : // not tenured. Moreover it clears the pretenuring allocation site statistics.
1452 : void ResetAllAllocationSitesDependentCode(PretenureFlag flag);
1453 :
1454 : // Evaluates local pretenuring for the old space and calls
1455 : // ResetAllTenuredAllocationSitesDependentCode if too many objects died in
1456 : // the old space.
1457 : void EvaluateOldSpaceLocalPretenuring(uint64_t size_of_objects_before_gc);
1458 :
1459 : // Record statistics after garbage collection.
1460 : void ReportStatisticsAfterGC();
1461 :
1462 : // Flush the number to string cache.
1463 : void FlushNumberStringCache();
1464 :
1465 : void ConfigureInitialOldGenerationSize();
1466 :
1467 : bool HasLowYoungGenerationAllocationRate();
1468 : bool HasLowOldGenerationAllocationRate();
1469 : double YoungGenerationMutatorUtilization();
1470 : double OldGenerationMutatorUtilization();
1471 :
1472 : void ReduceNewSpaceSize();
1473 :
1474 : GCIdleTimeHeapState ComputeHeapState();
1475 :
1476 : bool PerformIdleTimeAction(GCIdleTimeAction action,
1477 : GCIdleTimeHeapState heap_state,
1478 : double deadline_in_ms);
1479 :
1480 : void IdleNotificationEpilogue(GCIdleTimeAction action,
1481 : GCIdleTimeHeapState heap_state, double start_ms,
1482 : double deadline_in_ms);
1483 :
1484 : int NextAllocationTimeout(int current_timeout = 0);
1485 : inline void UpdateAllocationsHash(HeapObject object);
1486 : inline void UpdateAllocationsHash(uint32_t value);
1487 : void PrintAllocationsHash();
1488 :
1489 : void PrintMaxMarkingLimitReached();
1490 : void PrintMaxNewSpaceSizeReached();
1491 :
1492 : int NextStressMarkingLimit();
1493 :
1494 : void AddToRingBuffer(const char* string);
1495 : void GetFromRingBuffer(char* buffer);
1496 :
1497 : void CompactRetainedMaps(WeakArrayList retained_maps);
1498 :
1499 : void CollectGarbageOnMemoryPressure();
1500 :
1501 : void EagerlyFreeExternalMemory();
1502 :
1503 : bool InvokeNearHeapLimitCallback();
1504 :
1505 : void ComputeFastPromotionMode();
1506 :
1507 : // Attempt to over-approximate the weak closure by marking object groups and
1508 : // implicit references from global handles, but don't atomically complete
1509 : // marking. If we continue to mark incrementally, we might have marked
1510 : // objects that die later.
1511 : void FinalizeIncrementalMarkingIncrementally(
1512 : GarbageCollectionReason gc_reason);
1513 :
1514 : // Returns the timer used for a given GC type.
1515 : // - GCScavenger: young generation GC
1516 : // - GCCompactor: full GC
1517 : // - GCFinalzeMC: finalization of incremental full GC
1518 : // - GCFinalizeMCReduceMemory: finalization of incremental full GC with
1519 : // memory reduction
1520 : TimedHistogram* GCTypeTimer(GarbageCollector collector);
1521 : TimedHistogram* GCTypePriorityTimer(GarbageCollector collector);
1522 :
1523 : // ===========================================================================
1524 : // Pretenuring. ==============================================================
1525 : // ===========================================================================
1526 :
1527 : // Pretenuring decisions are made based on feedback collected during new space
1528 : // evacuation. Note that between feedback collection and calling this method
1529 : // object in old space must not move.
1530 : void ProcessPretenuringFeedback();
1531 :
1532 : // Removes an entry from the global pretenuring storage.
1533 : void RemoveAllocationSitePretenuringFeedback(AllocationSite site);
1534 :
1535 : // ===========================================================================
1536 : // Actual GC. ================================================================
1537 : // ===========================================================================
1538 :
1539 : // Code that should be run before and after each GC. Includes some
1540 : // reporting/verification activities when compiled with DEBUG set.
1541 : void GarbageCollectionPrologue();
1542 : void GarbageCollectionEpilogue();
1543 :
1544 : // Performs a major collection in the whole heap.
1545 : void MarkCompact();
1546 : // Performs a minor collection of just the young generation.
1547 : void MinorMarkCompact();
1548 :
1549 : // Code to be run before and after mark-compact.
1550 : void MarkCompactPrologue();
1551 : void MarkCompactEpilogue();
1552 :
1553 : // Performs a minor collection in new generation.
1554 : void Scavenge();
1555 : void EvacuateYoungGeneration();
1556 :
1557 : void UpdateNewSpaceReferencesInExternalStringTable(
1558 : ExternalStringTableUpdaterCallback updater_func);
1559 :
1560 : void UpdateReferencesInExternalStringTable(
1561 : ExternalStringTableUpdaterCallback updater_func);
1562 :
1563 : void ProcessAllWeakReferences(WeakObjectRetainer* retainer);
1564 : void ProcessYoungWeakReferences(WeakObjectRetainer* retainer);
1565 : void ProcessNativeContexts(WeakObjectRetainer* retainer);
1566 : void ProcessAllocationSites(WeakObjectRetainer* retainer);
1567 : void ProcessWeakListRoots(WeakObjectRetainer* retainer);
1568 :
1569 : // ===========================================================================
1570 : // GC statistics. ============================================================
1571 : // ===========================================================================
1572 :
1573 243023 : inline size_t OldGenerationSpaceAvailable() {
1574 486046 : if (old_generation_allocation_limit_ <=
1575 243023 : OldGenerationObjectsAndPromotedExternalMemorySize())
1576 : return 0;
1577 240631 : return old_generation_allocation_limit_ -
1578 : static_cast<size_t>(
1579 240631 : OldGenerationObjectsAndPromotedExternalMemorySize());
1580 : }
1581 :
1582 : // We allow incremental marking to overshoot the allocation limit for
1583 : // performace reasons. If the overshoot is too large then we are more
1584 : // eager to finalize incremental marking.
1585 1912 : inline bool AllocationLimitOvershotByLargeMargin() {
1586 : // This guards against too eager finalization in small heaps.
1587 : // The number is chosen based on v8.browsing_mobile on Nexus 7v2.
1588 : size_t kMarginForSmallHeaps = 32u * MB;
1589 3824 : if (old_generation_allocation_limit_ >=
1590 1912 : OldGenerationObjectsAndPromotedExternalMemorySize())
1591 : return false;
1592 1676 : uint64_t overshoot = OldGenerationObjectsAndPromotedExternalMemorySize() -
1593 1676 : old_generation_allocation_limit_;
1594 : // Overshoot margin is 50% of allocation limit or half-way to the max heap
1595 : // with special handling of small heaps.
1596 : uint64_t margin =
1597 : Min(Max(old_generation_allocation_limit_ / 2, kMarginForSmallHeaps),
1598 1676 : (max_old_generation_size_ - old_generation_allocation_limit_) / 2);
1599 1676 : return overshoot >= margin;
1600 : }
1601 :
1602 : void UpdateTotalGCTime(double duration);
1603 :
1604 107086 : bool MaximumSizeScavenge() { return maximum_size_scavenges_ > 0; }
1605 :
1606 : bool IsIneffectiveMarkCompact(size_t old_generation_size,
1607 : double mutator_utilization);
1608 : void CheckIneffectiveMarkCompact(size_t old_generation_size,
1609 : double mutator_utilization);
1610 :
1611 : inline void IncrementExternalBackingStoreBytes(ExternalBackingStoreType type,
1612 : size_t amount);
1613 :
1614 : inline void DecrementExternalBackingStoreBytes(ExternalBackingStoreType type,
1615 : size_t amount);
1616 :
1617 : // ===========================================================================
1618 : // Growing strategy. =========================================================
1619 : // ===========================================================================
1620 :
1621 : HeapController* heap_controller() { return heap_controller_; }
1622 : MemoryReducer* memory_reducer() { return memory_reducer_; }
1623 :
1624 : // For some webpages RAIL mode does not switch from PERFORMANCE_LOAD.
1625 : // This constant limits the effect of load RAIL mode on GC.
1626 : // The value is arbitrary and chosen as the largest load time observed in
1627 : // v8 browsing benchmarks.
1628 : static const int kMaxLoadTimeMs = 7000;
1629 :
1630 : bool ShouldOptimizeForLoadTime();
1631 :
1632 : size_t old_generation_allocation_limit() const {
1633 : return old_generation_allocation_limit_;
1634 : }
1635 :
1636 : bool always_allocate() { return always_allocate_scope_count_ != 0; }
1637 :
1638 : bool CanExpandOldGeneration(size_t size);
1639 :
1640 : bool ShouldExpandOldGenerationOnSlowAllocation();
1641 :
1642 : enum class HeapGrowingMode { kSlow, kConservative, kMinimal, kDefault };
1643 :
1644 : HeapGrowingMode CurrentHeapGrowingMode();
1645 :
1646 : enum class IncrementalMarkingLimit { kNoLimit, kSoftLimit, kHardLimit };
1647 : IncrementalMarkingLimit IncrementalMarkingLimitReached();
1648 :
1649 : // ===========================================================================
1650 : // Idle notification. ========================================================
1651 : // ===========================================================================
1652 :
1653 : bool RecentIdleNotificationHappened();
1654 : void ScheduleIdleScavengeIfNeeded(int bytes_allocated);
1655 :
1656 : // ===========================================================================
1657 : // HeapIterator helpers. =====================================================
1658 : // ===========================================================================
1659 :
1660 7853 : void heap_iterator_start() { heap_iterator_depth_++; }
1661 :
1662 7853 : void heap_iterator_end() { heap_iterator_depth_--; }
1663 :
1664 : bool in_heap_iterator() { return heap_iterator_depth_ > 0; }
1665 :
1666 : // ===========================================================================
1667 : // Allocation methods. =======================================================
1668 : // ===========================================================================
1669 :
1670 : // Allocates a JS Map in the heap.
1671 : V8_WARN_UNUSED_RESULT AllocationResult
1672 : AllocateMap(InstanceType instance_type, int instance_size,
1673 : ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND,
1674 : int inobject_properties = 0);
1675 :
1676 : // Allocate an uninitialized object. The memory is non-executable if the
1677 : // hardware and OS allow. This is the single choke-point for allocations
1678 : // performed by the runtime and should not be bypassed (to extend this to
1679 : // inlined allocations, use the Heap::DisableInlineAllocation() support).
1680 : V8_WARN_UNUSED_RESULT inline AllocationResult AllocateRaw(
1681 : int size_in_bytes, AllocationSpace space,
1682 : AllocationAlignment aligment = kWordAligned);
1683 :
1684 : // This method will try to perform an allocation of a given size in a given
1685 : // space. If the allocation fails, a regular full garbage collection is
1686 : // triggered and the allocation is retried. This is performed multiple times.
1687 : // If after that retry procedure the allocation still fails nullptr is
1688 : // returned.
1689 : HeapObject AllocateRawWithLightRetry(
1690 : int size, AllocationSpace space,
1691 : AllocationAlignment alignment = kWordAligned);
1692 :
1693 : // This method will try to perform an allocation of a given size in a given
1694 : // space. If the allocation fails, a regular full garbage collection is
1695 : // triggered and the allocation is retried. This is performed multiple times.
1696 : // If after that retry procedure the allocation still fails a "hammer"
1697 : // garbage collection is triggered which tries to significantly reduce memory.
1698 : // If the allocation still fails after that a fatal error is thrown.
1699 : HeapObject AllocateRawWithRetryOrFail(
1700 : int size, AllocationSpace space,
1701 : AllocationAlignment alignment = kWordAligned);
1702 : HeapObject AllocateRawCodeInLargeObjectSpace(int size);
1703 :
1704 : // Allocates a heap object based on the map.
1705 : V8_WARN_UNUSED_RESULT AllocationResult Allocate(Map map,
1706 : AllocationSpace space);
1707 :
1708 : // Takes a code object and checks if it is on memory which is not subject to
1709 : // compaction. This method will return a new code object on an immovable
1710 : // memory location if the original code object was movable.
1711 : HeapObject EnsureImmovableCode(HeapObject heap_object, int object_size);
1712 :
1713 : // Allocates a partial map for bootstrapping.
1714 : V8_WARN_UNUSED_RESULT AllocationResult
1715 : AllocatePartialMap(InstanceType instance_type, int instance_size);
1716 :
1717 : void FinalizePartialMap(Map map);
1718 :
1719 : // Allocate empty fixed typed array of given type.
1720 : V8_WARN_UNUSED_RESULT AllocationResult
1721 : AllocateEmptyFixedTypedArray(ExternalArrayType array_type);
1722 :
1723 75 : void set_force_oom(bool value) { force_oom_ = value; }
1724 :
1725 : // ===========================================================================
1726 : // Retaining path tracing ====================================================
1727 : // ===========================================================================
1728 :
1729 : void AddRetainer(HeapObject retainer, HeapObject object);
1730 : void AddEphemeronRetainer(HeapObject retainer, HeapObject object);
1731 : void AddRetainingRoot(Root root, HeapObject object);
1732 : // Returns true if the given object is a target of retaining path tracking.
1733 : // Stores the option corresponding to the object in the provided *option.
1734 : bool IsRetainingPathTarget(HeapObject object, RetainingPathOption* option);
1735 : void PrintRetainingPath(HeapObject object, RetainingPathOption option);
1736 :
1737 : #ifdef DEBUG
1738 : void IncrementObjectCounters();
1739 : #endif // DEBUG
1740 :
1741 : // The amount of memory that has been freed concurrently.
1742 : std::atomic<intptr_t> external_memory_concurrently_freed_{0};
1743 :
1744 : // This can be calculated directly from a pointer to the heap; however, it is
1745 : // more expedient to get at the isolate directly from within Heap methods.
1746 : Isolate* isolate_ = nullptr;
1747 :
1748 : size_t code_range_size_ = 0;
1749 : size_t max_semi_space_size_ = 8 * (kSystemPointerSize / 4) * MB;
1750 : size_t initial_semispace_size_ = kMinSemiSpaceSizeInKB * KB;
1751 : size_t max_old_generation_size_ = 700ul * (kSystemPointerSize / 4) * MB;
1752 : size_t initial_max_old_generation_size_;
1753 : size_t initial_max_old_generation_size_threshold_;
1754 : size_t initial_old_generation_size_;
1755 : bool old_generation_size_configured_ = false;
1756 : size_t maximum_committed_ = 0;
1757 :
1758 : // Backing store bytes (array buffers and external strings).
1759 : std::atomic<size_t> backing_store_bytes_{0};
1760 :
1761 : // For keeping track of how much data has survived
1762 : // scavenge since last new space expansion.
1763 : size_t survived_since_last_expansion_ = 0;
1764 :
1765 : // ... and since the last scavenge.
1766 : size_t survived_last_scavenge_ = 0;
1767 :
1768 : // This is not the depth of nested AlwaysAllocateScope's but rather a single
1769 : // count, as scopes can be acquired from multiple tasks (read: threads).
1770 : std::atomic<size_t> always_allocate_scope_count_{0};
1771 :
1772 : // Stores the memory pressure level that set by MemoryPressureNotification
1773 : // and reset by a mark-compact garbage collection.
1774 : std::atomic<MemoryPressureLevel> memory_pressure_level_;
1775 :
1776 : std::vector<std::pair<v8::NearHeapLimitCallback, void*> >
1777 : near_heap_limit_callbacks_;
1778 :
1779 : // For keeping track of context disposals.
1780 : int contexts_disposed_ = 0;
1781 :
1782 : // The length of the retained_maps array at the time of context disposal.
1783 : // This separates maps in the retained_maps array that were created before
1784 : // and after context disposal.
1785 : int number_of_disposed_maps_ = 0;
1786 :
1787 : NewSpace* new_space_ = nullptr;
1788 : OldSpace* old_space_ = nullptr;
1789 : CodeSpace* code_space_ = nullptr;
1790 : MapSpace* map_space_ = nullptr;
1791 : LargeObjectSpace* lo_space_ = nullptr;
1792 : CodeLargeObjectSpace* code_lo_space_ = nullptr;
1793 : NewLargeObjectSpace* new_lo_space_ = nullptr;
1794 : ReadOnlySpace* read_only_space_ = nullptr;
1795 : // Map from the space id to the space.
1796 : Space* space_[LAST_SPACE + 1];
1797 :
1798 : // Determines whether code space is write-protected. This is essentially a
1799 : // race-free copy of the {FLAG_write_protect_code_memory} flag.
1800 : bool write_protect_code_memory_ = false;
1801 :
1802 : // Holds the number of open CodeSpaceMemoryModificationScopes.
1803 : uintptr_t code_space_memory_modification_scope_depth_ = 0;
1804 :
1805 : HeapState gc_state_ = NOT_IN_GC;
1806 :
1807 : int gc_post_processing_depth_ = 0;
1808 :
1809 : // Returns the amount of external memory registered since last global gc.
1810 : uint64_t PromotedExternalMemorySize();
1811 :
1812 : // How many "runtime allocations" happened.
1813 : uint32_t allocations_count_ = 0;
1814 :
1815 : // Running hash over allocations performed.
1816 : uint32_t raw_allocations_hash_ = 0;
1817 :
1818 : // Starts marking when stress_marking_percentage_% of the marking start limit
1819 : // is reached.
1820 : int stress_marking_percentage_ = 0;
1821 :
1822 : // Observer that causes more frequent checks for reached incremental marking
1823 : // limit.
1824 : AllocationObserver* stress_marking_observer_ = nullptr;
1825 :
1826 : // Observer that can cause early scavenge start.
1827 : StressScavengeObserver* stress_scavenge_observer_ = nullptr;
1828 :
1829 : bool allocation_step_in_progress_ = false;
1830 :
1831 : // The maximum percent of the marking limit reached wihout causing marking.
1832 : // This is tracked when specyfing --fuzzer-gc-analysis.
1833 : double max_marking_limit_reached_ = 0.0;
1834 :
1835 : // How many mark-sweep collections happened.
1836 : unsigned int ms_count_ = 0;
1837 :
1838 : // How many gc happened.
1839 : unsigned int gc_count_ = 0;
1840 :
1841 : // The number of Mark-Compact garbage collections that are considered as
1842 : // ineffective. See IsIneffectiveMarkCompact() predicate.
1843 : int consecutive_ineffective_mark_compacts_ = 0;
1844 :
1845 : static const uintptr_t kMmapRegionMask = 0xFFFFFFFFu;
1846 : uintptr_t mmap_region_base_ = 0;
1847 :
1848 : // For post mortem debugging.
1849 : int remembered_unmapped_pages_index_ = 0;
1850 : Address remembered_unmapped_pages_[kRememberedUnmappedPages];
1851 :
1852 : // Limit that triggers a global GC on the next (normally caused) GC. This
1853 : // is checked when we have already decided to do a GC to help determine
1854 : // which collector to invoke, before expanding a paged space in the old
1855 : // generation and on every allocation in large object space.
1856 : size_t old_generation_allocation_limit_;
1857 :
1858 : // Indicates that inline bump-pointer allocation has been globally disabled
1859 : // for all spaces. This is used to disable allocations in generated code.
1860 : bool inline_allocation_disabled_ = false;
1861 :
1862 : // Weak list heads, threaded through the objects.
1863 : // List heads are initialized lazily and contain the undefined_value at start.
1864 : Object native_contexts_list_;
1865 : Object allocation_sites_list_;
1866 :
1867 : std::vector<GCCallbackTuple> gc_epilogue_callbacks_;
1868 : std::vector<GCCallbackTuple> gc_prologue_callbacks_;
1869 :
1870 : GetExternallyAllocatedMemoryInBytesCallback external_memory_callback_;
1871 :
1872 : int deferred_counters_[v8::Isolate::kUseCounterFeatureCount];
1873 :
1874 : size_t promoted_objects_size_ = 0;
1875 : double promotion_ratio_ = 0.0;
1876 : double promotion_rate_ = 0.0;
1877 : size_t semi_space_copied_object_size_ = 0;
1878 : size_t previous_semi_space_copied_object_size_ = 0;
1879 : double semi_space_copied_rate_ = 0.0;
1880 : int nodes_died_in_new_space_ = 0;
1881 : int nodes_copied_in_new_space_ = 0;
1882 : int nodes_promoted_ = 0;
1883 :
1884 : // This is the pretenuring trigger for allocation sites that are in maybe
1885 : // tenure state. When we switched to the maximum new space size we deoptimize
1886 : // the code that belongs to the allocation site and derive the lifetime
1887 : // of the allocation site.
1888 : unsigned int maximum_size_scavenges_ = 0;
1889 :
1890 : // Total time spent in GC.
1891 : double total_gc_time_ms_;
1892 :
1893 : // Last time an idle notification happened.
1894 : double last_idle_notification_time_ = 0.0;
1895 :
1896 : // Last time a garbage collection happened.
1897 : double last_gc_time_ = 0.0;
1898 :
1899 : GCTracer* tracer_ = nullptr;
1900 : MarkCompactCollector* mark_compact_collector_ = nullptr;
1901 : MinorMarkCompactCollector* minor_mark_compact_collector_ = nullptr;
1902 : ScavengerCollector* scavenger_collector_ = nullptr;
1903 : ArrayBufferCollector* array_buffer_collector_ = nullptr;
1904 : MemoryAllocator* memory_allocator_ = nullptr;
1905 : StoreBuffer* store_buffer_ = nullptr;
1906 : HeapController* heap_controller_ = nullptr;
1907 : IncrementalMarking* incremental_marking_ = nullptr;
1908 : ConcurrentMarking* concurrent_marking_ = nullptr;
1909 : GCIdleTimeHandler* gc_idle_time_handler_ = nullptr;
1910 : MemoryReducer* memory_reducer_ = nullptr;
1911 : ObjectStats* live_object_stats_ = nullptr;
1912 : ObjectStats* dead_object_stats_ = nullptr;
1913 : ScavengeJob* scavenge_job_ = nullptr;
1914 : AllocationObserver* idle_scavenge_observer_ = nullptr;
1915 : LocalEmbedderHeapTracer* local_embedder_heap_tracer_ = nullptr;
1916 : StrongRootsList* strong_roots_list_ = nullptr;
1917 :
1918 : // This counter is increased before each GC and never reset.
1919 : // To account for the bytes allocated since the last GC, use the
1920 : // NewSpaceAllocationCounter() function.
1921 : size_t new_space_allocation_counter_ = 0;
1922 :
1923 : // This counter is increased before each GC and never reset. To
1924 : // account for the bytes allocated since the last GC, use the
1925 : // OldGenerationAllocationCounter() function.
1926 : size_t old_generation_allocation_counter_at_last_gc_ = 0;
1927 :
1928 : // The size of objects in old generation after the last MarkCompact GC.
1929 : size_t old_generation_size_at_last_gc_ = 0;
1930 :
1931 : // The feedback storage is used to store allocation sites (keys) and how often
1932 : // they have been visited (values) by finding a memento behind an object. The
1933 : // storage is only alive temporary during a GC. The invariant is that all
1934 : // pointers in this map are already fixed, i.e., they do not point to
1935 : // forwarding pointers.
1936 : PretenuringFeedbackMap global_pretenuring_feedback_;
1937 :
1938 : char trace_ring_buffer_[kTraceRingBufferSize];
1939 :
1940 : // Used as boolean.
1941 : uint8_t is_marking_flag_ = 0;
1942 :
1943 : // If it's not full then the data is from 0 to ring_buffer_end_. If it's
1944 : // full then the data is from ring_buffer_end_ to the end of the buffer and
1945 : // from 0 to ring_buffer_end_.
1946 : bool ring_buffer_full_ = false;
1947 : size_t ring_buffer_end_ = 0;
1948 :
1949 : // Flag is set when the heap has been configured. The heap can be repeatedly
1950 : // configured through the API until it is set up.
1951 : bool configured_ = false;
1952 :
1953 : // Currently set GC flags that are respected by all GC components.
1954 : int current_gc_flags_ = Heap::kNoGCFlags;
1955 :
1956 : // Currently set GC callback flags that are used to pass information between
1957 : // the embedder and V8's GC.
1958 : GCCallbackFlags current_gc_callback_flags_;
1959 :
1960 : bool is_current_gc_forced_;
1961 :
1962 : ExternalStringTable external_string_table_;
1963 :
1964 : base::Mutex relocation_mutex_;
1965 :
1966 : int gc_callbacks_depth_ = 0;
1967 :
1968 : bool deserialization_complete_ = false;
1969 :
1970 : // The depth of HeapIterator nestings.
1971 : int heap_iterator_depth_ = 0;
1972 :
1973 : bool fast_promotion_mode_ = false;
1974 :
1975 : // Used for testing purposes.
1976 : bool force_oom_ = false;
1977 : bool delay_sweeper_tasks_for_testing_ = false;
1978 :
1979 : HeapObject pending_layout_change_object_;
1980 :
1981 : base::Mutex unprotected_memory_chunks_mutex_;
1982 : std::unordered_set<MemoryChunk*> unprotected_memory_chunks_;
1983 : bool unprotected_memory_chunks_registry_enabled_ = false;
1984 :
1985 : #ifdef V8_ENABLE_ALLOCATION_TIMEOUT
1986 : // If the --gc-interval flag is set to a positive value, this
1987 : // variable holds the value indicating the number of allocations
1988 : // remain until the next failure and garbage collection.
1989 : int allocation_timeout_ = 0;
1990 : #endif // V8_ENABLE_ALLOCATION_TIMEOUT
1991 :
1992 : std::map<HeapObject, HeapObject, Object::Comparer> retainer_;
1993 : std::map<HeapObject, Root, Object::Comparer> retaining_root_;
1994 : // If an object is retained by an ephemeron, then the retaining key of the
1995 : // ephemeron is stored in this map.
1996 : std::map<HeapObject, HeapObject, Object::Comparer> ephemeron_retainer_;
1997 : // For each index inthe retaining_path_targets_ array this map
1998 : // stores the option of the corresponding target.
1999 : std::map<int, RetainingPathOption> retaining_path_target_option_;
2000 :
2001 : std::vector<HeapObjectAllocationTracker*> allocation_trackers_;
2002 :
2003 : // Classes in "heap" can be friends.
2004 : friend class AlwaysAllocateScope;
2005 : friend class ArrayBufferCollector;
2006 : friend class ConcurrentMarking;
2007 : friend class EphemeronHashTableMarkingTask;
2008 : friend class GCCallbacksScope;
2009 : friend class GCTracer;
2010 : friend class MemoryController;
2011 : friend class HeapIterator;
2012 : friend class IdleScavengeObserver;
2013 : friend class IncrementalMarking;
2014 : friend class IncrementalMarkingJob;
2015 : friend class LargeObjectSpace;
2016 : template <FixedArrayVisitationMode fixed_array_mode,
2017 : TraceRetainingPathMode retaining_path_mode, typename MarkingState>
2018 : friend class MarkingVisitor;
2019 : friend class MarkCompactCollector;
2020 : friend class MarkCompactCollectorBase;
2021 : friend class MinorMarkCompactCollector;
2022 : friend class NewSpace;
2023 : friend class ObjectStatsCollector;
2024 : friend class Page;
2025 : friend class PagedSpace;
2026 : friend class ReadOnlyRoots;
2027 : friend class Scavenger;
2028 : friend class ScavengerCollector;
2029 : friend class Space;
2030 : friend class StoreBuffer;
2031 : friend class Sweeper;
2032 : friend class heap::TestMemoryAllocatorScope;
2033 :
2034 : // The allocator interface.
2035 : friend class Factory;
2036 :
2037 : // The Isolate constructs us.
2038 : friend class Isolate;
2039 :
2040 : // Used in cctest.
2041 : friend class heap::HeapTester;
2042 :
2043 : FRIEND_TEST(HeapControllerTest, OldGenerationAllocationLimit);
2044 : FRIEND_TEST(HeapTest, ExternalLimitDefault);
2045 : FRIEND_TEST(HeapTest, ExternalLimitStaysAboveDefaultForExplicitHandling);
2046 : DISALLOW_COPY_AND_ASSIGN(Heap);
2047 : };
2048 :
2049 :
2050 : class HeapStats {
2051 : public:
2052 : static const int kStartMarker = 0xDECADE00;
2053 : static const int kEndMarker = 0xDECADE01;
2054 :
2055 : intptr_t* start_marker; // 0
2056 : size_t* ro_space_size; // 1
2057 : size_t* ro_space_capacity; // 2
2058 : size_t* new_space_size; // 3
2059 : size_t* new_space_capacity; // 4
2060 : size_t* old_space_size; // 5
2061 : size_t* old_space_capacity; // 6
2062 : size_t* code_space_size; // 7
2063 : size_t* code_space_capacity; // 8
2064 : size_t* map_space_size; // 9
2065 : size_t* map_space_capacity; // 10
2066 : size_t* lo_space_size; // 11
2067 : size_t* code_lo_space_size; // 12
2068 : size_t* global_handle_count; // 13
2069 : size_t* weak_global_handle_count; // 14
2070 : size_t* pending_global_handle_count; // 15
2071 : size_t* near_death_global_handle_count; // 16
2072 : size_t* free_global_handle_count; // 17
2073 : size_t* memory_allocator_size; // 18
2074 : size_t* memory_allocator_capacity; // 19
2075 : size_t* malloced_memory; // 20
2076 : size_t* malloced_peak_memory; // 21
2077 : size_t* objects_per_type; // 22
2078 : size_t* size_per_type; // 23
2079 : int* os_error; // 24
2080 : char* last_few_messages; // 25
2081 : char* js_stacktrace; // 26
2082 : intptr_t* end_marker; // 27
2083 : };
2084 :
2085 :
2086 : class AlwaysAllocateScope {
2087 : public:
2088 : explicit inline AlwaysAllocateScope(Isolate* isolate);
2089 : inline ~AlwaysAllocateScope();
2090 :
2091 : private:
2092 : Heap* heap_;
2093 : };
2094 :
2095 : // The CodeSpaceMemoryModificationScope can only be used by the main thread.
2096 : class CodeSpaceMemoryModificationScope {
2097 : public:
2098 : explicit inline CodeSpaceMemoryModificationScope(Heap* heap);
2099 : inline ~CodeSpaceMemoryModificationScope();
2100 :
2101 : private:
2102 : Heap* heap_;
2103 : };
2104 :
2105 : // The CodePageCollectionMemoryModificationScope can only be used by the main
2106 : // thread. It will not be enabled if a CodeSpaceMemoryModificationScope is
2107 : // already active.
2108 : class CodePageCollectionMemoryModificationScope {
2109 : public:
2110 : explicit inline CodePageCollectionMemoryModificationScope(Heap* heap);
2111 : inline ~CodePageCollectionMemoryModificationScope();
2112 :
2113 : private:
2114 : Heap* heap_;
2115 : };
2116 :
2117 : // The CodePageMemoryModificationScope does not check if tansitions to
2118 : // writeable and back to executable are actually allowed, i.e. the MemoryChunk
2119 : // was registered to be executable. It can be used by concurrent threads.
2120 : class CodePageMemoryModificationScope {
2121 : public:
2122 : explicit inline CodePageMemoryModificationScope(MemoryChunk* chunk);
2123 : inline ~CodePageMemoryModificationScope();
2124 :
2125 : private:
2126 : MemoryChunk* chunk_;
2127 : bool scope_active_;
2128 :
2129 : // Disallow any GCs inside this scope, as a relocation of the underlying
2130 : // object would change the {MemoryChunk} that this scope targets.
2131 : DISALLOW_HEAP_ALLOCATION(no_heap_allocation_);
2132 : };
2133 :
2134 : // Visitor class to verify interior pointers in spaces that do not contain
2135 : // or care about intergenerational references. All heap object pointers have to
2136 : // point into the heap to a location that has a map pointer at its first word.
2137 : // Caveat: Heap::Contains is an approximation because it can return true for
2138 : // objects in a heap space but above the allocation pointer.
2139 0 : class VerifyPointersVisitor : public ObjectVisitor, public RootVisitor {
2140 : public:
2141 : explicit VerifyPointersVisitor(Heap* heap) : heap_(heap) {}
2142 : void VisitPointers(HeapObject host, ObjectSlot start,
2143 : ObjectSlot end) override;
2144 : void VisitPointers(HeapObject host, MaybeObjectSlot start,
2145 : MaybeObjectSlot end) override;
2146 : void VisitCodeTarget(Code host, RelocInfo* rinfo) override;
2147 : void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) override;
2148 :
2149 : void VisitRootPointers(Root root, const char* description,
2150 : FullObjectSlot start, FullObjectSlot end) override;
2151 :
2152 : protected:
2153 : V8_INLINE void VerifyHeapObjectImpl(HeapObject heap_object);
2154 :
2155 : template <typename TSlot>
2156 : V8_INLINE void VerifyPointersImpl(TSlot start, TSlot end);
2157 :
2158 : virtual void VerifyPointers(HeapObject host, MaybeObjectSlot start,
2159 : MaybeObjectSlot end);
2160 :
2161 : Heap* heap_;
2162 : };
2163 :
2164 :
2165 : // Verify that all objects are Smis.
2166 0 : class VerifySmisVisitor : public RootVisitor {
2167 : public:
2168 : void VisitRootPointers(Root root, const char* description,
2169 : FullObjectSlot start, FullObjectSlot end) override;
2170 : };
2171 :
2172 : // Space iterator for iterating over all the paged spaces of the heap: Map
2173 : // space, old space, code space and optionally read only space. Returns each
2174 : // space in turn, and null when it is done.
2175 : class V8_EXPORT_PRIVATE PagedSpaces {
2176 : public:
2177 : enum class SpacesSpecifier { kSweepablePagedSpaces, kAllPagedSpaces };
2178 :
2179 : explicit PagedSpaces(Heap* heap, SpacesSpecifier specifier =
2180 : SpacesSpecifier::kSweepablePagedSpaces)
2181 : : heap_(heap),
2182 : counter_(specifier == SpacesSpecifier::kAllPagedSpaces ? RO_SPACE
2183 5823189 : : OLD_SPACE) {}
2184 : PagedSpace* next();
2185 :
2186 : private:
2187 : Heap* heap_;
2188 : int counter_;
2189 : };
2190 :
2191 :
2192 263075 : class SpaceIterator : public Malloced {
2193 : public:
2194 : explicit SpaceIterator(Heap* heap);
2195 : virtual ~SpaceIterator();
2196 :
2197 : bool has_next();
2198 : Space* next();
2199 :
2200 : private:
2201 : Heap* heap_;
2202 : int current_space_; // from enum AllocationSpace.
2203 : };
2204 :
2205 :
2206 : // A HeapIterator provides iteration over the whole heap. It
2207 : // aggregates the specific iterators for the different spaces as
2208 : // these can only iterate over one space only.
2209 : //
2210 : // HeapIterator ensures there is no allocation during its lifetime
2211 : // (using an embedded DisallowHeapAllocation instance).
2212 : //
2213 : // HeapIterator can skip free list nodes (that is, de-allocated heap
2214 : // objects that still remain in the heap). As implementation of free
2215 : // nodes filtering uses GC marks, it can't be used during MS/MC GC
2216 : // phases. Also, it is forbidden to interrupt iteration in this mode,
2217 : // as this will leave heap objects marked (and thus, unusable).
2218 : class HeapIterator {
2219 : public:
2220 : enum HeapObjectsFiltering { kNoFiltering, kFilterUnreachable };
2221 :
2222 : explicit HeapIterator(Heap* heap,
2223 : HeapObjectsFiltering filtering = kNoFiltering);
2224 : ~HeapIterator();
2225 :
2226 : HeapObject next();
2227 :
2228 : private:
2229 : HeapObject NextObject();
2230 :
2231 : DISALLOW_HEAP_ALLOCATION(no_heap_allocation_);
2232 :
2233 : Heap* heap_;
2234 : HeapObjectsFiltering filtering_;
2235 : HeapObjectsFilter* filter_;
2236 : // Space iterator for iterating all the spaces.
2237 : SpaceIterator* space_iterator_;
2238 : // Object iterator for the space currently being iterated.
2239 : std::unique_ptr<ObjectIterator> object_iterator_;
2240 : };
2241 :
2242 : // Abstract base class for checking whether a weak object should be retained.
2243 83492 : class WeakObjectRetainer {
2244 : public:
2245 190578 : virtual ~WeakObjectRetainer() = default;
2246 :
2247 : // Return whether this object should be retained. If nullptr is returned the
2248 : // object has no references. Otherwise the address of the retained object
2249 : // should be returned as in some GC situations the object has been moved.
2250 : virtual Object RetainAs(Object object) = 0;
2251 : };
2252 :
2253 : // -----------------------------------------------------------------------------
2254 : // Allows observation of allocations.
2255 : class AllocationObserver {
2256 : public:
2257 : explicit AllocationObserver(intptr_t step_size)
2258 188814 : : step_size_(step_size), bytes_to_next_step_(step_size) {
2259 : DCHECK_LE(kTaggedSize, step_size);
2260 : }
2261 188739 : virtual ~AllocationObserver() = default;
2262 :
2263 : // Called each time the observed space does an allocation step. This may be
2264 : // more frequently than the step_size we are monitoring (e.g. when there are
2265 : // multiple observers, or when page or space boundary is encountered.)
2266 : void AllocationStep(int bytes_allocated, Address soon_object, size_t size);
2267 :
2268 : protected:
2269 : intptr_t step_size() const { return step_size_; }
2270 : intptr_t bytes_to_next_step() const { return bytes_to_next_step_; }
2271 :
2272 : // Pure virtual method provided by the subclasses that gets called when at
2273 : // least step_size bytes have been allocated. soon_object is the address just
2274 : // allocated (but not yet initialized.) size is the size of the object as
2275 : // requested (i.e. w/o the alignment fillers). Some complexities to be aware
2276 : // of:
2277 : // 1) soon_object will be nullptr in cases where we end up observing an
2278 : // allocation that happens to be a filler space (e.g. page boundaries.)
2279 : // 2) size is the requested size at the time of allocation. Right-trimming
2280 : // may change the object size dynamically.
2281 : // 3) soon_object may actually be the first object in an allocation-folding
2282 : // group. In such a case size is the size of the group rather than the
2283 : // first object.
2284 : virtual void Step(int bytes_allocated, Address soon_object, size_t size) = 0;
2285 :
2286 : // Subclasses can override this method to make step size dynamic.
2287 97224 : virtual intptr_t GetNextStepSize() { return step_size_; }
2288 :
2289 : intptr_t step_size_;
2290 : intptr_t bytes_to_next_step_;
2291 :
2292 : private:
2293 : friend class Space;
2294 : DISALLOW_COPY_AND_ASSIGN(AllocationObserver);
2295 : };
2296 :
2297 : V8_EXPORT_PRIVATE const char* AllocationSpaceName(AllocationSpace space);
2298 :
2299 : // -----------------------------------------------------------------------------
2300 : // Allows observation of heap object allocations.
2301 70981 : class HeapObjectAllocationTracker {
2302 : public:
2303 : virtual void AllocationEvent(Address addr, int size) = 0;
2304 31254 : virtual void MoveEvent(Address from, Address to, int size) {}
2305 2807 : virtual void UpdateObjectSizeEvent(Address addr, int size) {}
2306 70965 : virtual ~HeapObjectAllocationTracker() = default;
2307 : };
2308 :
2309 : } // namespace internal
2310 : } // namespace v8
2311 :
2312 : #endif // V8_HEAP_HEAP_H_
|