1 // Copyright 2020 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_ALLOCATION_OBSERVER_H_ 6 #define V8_HEAP_ALLOCATION_OBSERVER_H_ 7 8 #include <cstdint> 9 #include <unordered_set> 10 #include <vector> 11 12 #include "src/common/globals.h" 13 14 namespace v8 { 15 namespace internal { 16 17 class AllocationObserver; 18 19 class AllocationCounter { 20 public: AllocationCounter()21 AllocationCounter() 22 : paused_(false), 23 current_counter_(0), 24 next_counter_(0), 25 step_in_progress_(false) {} 26 V8_EXPORT_PRIVATE void AddAllocationObserver(AllocationObserver* observer); 27 V8_EXPORT_PRIVATE void RemoveAllocationObserver(AllocationObserver* observer); 28 IsActive()29 bool IsActive() { return !IsPaused() && observers_.size() > 0; } 30 Pause()31 void Pause() { 32 DCHECK(!paused_); 33 DCHECK(!step_in_progress_); 34 paused_ = true; 35 } 36 Resume()37 void Resume() { 38 DCHECK(paused_); 39 DCHECK(!step_in_progress_); 40 paused_ = false; 41 } 42 43 V8_EXPORT_PRIVATE void AdvanceAllocationObservers(size_t allocated); 44 V8_EXPORT_PRIVATE void InvokeAllocationObservers(Address soon_object, 45 size_t object_size, 46 size_t aligned_object_size); 47 NextBytes()48 size_t NextBytes() { 49 DCHECK(IsActive()); 50 return next_counter_ - current_counter_; 51 } 52 IsStepInProgress()53 bool IsStepInProgress() { return step_in_progress_; } 54 55 private: IsPaused()56 bool IsPaused() { return paused_; } 57 58 struct AllocationObserverCounter { AllocationObserverCounterAllocationObserverCounter59 AllocationObserverCounter(AllocationObserver* observer, size_t prev_counter, 60 size_t next_counter) 61 : observer_(observer), 62 prev_counter_(prev_counter), 63 next_counter_(next_counter) {} 64 65 AllocationObserver* observer_; 66 size_t prev_counter_; 67 size_t next_counter_; 68 }; 69 70 std::vector<AllocationObserverCounter> observers_; 71 std::vector<AllocationObserverCounter> pending_added_; 72 std::unordered_set<AllocationObserver*> pending_removed_; 73 74 bool paused_; 75 76 size_t current_counter_; 77 size_t next_counter_; 78 79 bool step_in_progress_; 80 }; 81 82 // ----------------------------------------------------------------------------- 83 // Allows observation of allocations. 84 class AllocationObserver { 85 public: AllocationObserver(intptr_t step_size)86 explicit AllocationObserver(intptr_t step_size) : step_size_(step_size) { 87 DCHECK_LE(kTaggedSize, step_size); 88 } 89 virtual ~AllocationObserver() = default; 90 91 protected: 92 // Pure virtual method provided by the subclasses that gets called when at 93 // least step_size bytes have been allocated. soon_object is the address just 94 // allocated (but not yet initialized.) size is the size of the object as 95 // requested (i.e. w/o the alignment fillers). Some complexities to be aware 96 // of: 97 // 1) soon_object will be nullptr in cases where we end up observing an 98 // allocation that happens to be a filler space (e.g. page boundaries.) 99 // 2) size is the requested size at the time of allocation. Right-trimming 100 // may change the object size dynamically. 101 // 3) soon_object may actually be the first object in an allocation-folding 102 // group. In such a case size is the size of the group rather than the 103 // first object. 104 virtual void Step(int bytes_allocated, Address soon_object, size_t size) = 0; 105 106 // Subclasses can override this method to make step size dynamic. GetNextStepSize()107 virtual intptr_t GetNextStepSize() { return step_size_; } 108 109 private: 110 intptr_t step_size_; 111 112 friend class AllocationCounter; 113 DISALLOW_COPY_AND_ASSIGN(AllocationObserver); 114 }; 115 116 class V8_EXPORT_PRIVATE PauseAllocationObserversScope { 117 public: 118 explicit PauseAllocationObserversScope(Heap* heap); 119 ~PauseAllocationObserversScope(); 120 121 private: 122 Heap* heap_; 123 DISALLOW_COPY_AND_ASSIGN(PauseAllocationObserversScope); 124 }; 125 126 } // namespace internal 127 } // namespace v8 128 129 #endif // V8_HEAP_ALLOCATION_OBSERVER_H_ 130