1 // Copyright 2019 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_MEMORY_MEASUREMENT_H_ 6 #define V8_HEAP_MEMORY_MEASUREMENT_H_ 7 8 #include <list> 9 #include <unordered_map> 10 11 #include "include/v8-statistics.h" 12 #include "src/base/platform/elapsed-timer.h" 13 #include "src/base/utils/random-number-generator.h" 14 #include "src/common/globals.h" 15 #include "src/objects/contexts.h" 16 #include "src/objects/map.h" 17 #include "src/objects/objects.h" 18 19 namespace v8 { 20 namespace internal { 21 22 class Heap; 23 class NativeContextStats; 24 25 class MemoryMeasurement { 26 public: 27 explicit MemoryMeasurement(Isolate* isolate); 28 29 bool EnqueueRequest(std::unique_ptr<v8::MeasureMemoryDelegate> delegate, 30 v8::MeasureMemoryExecution execution, 31 const std::vector<Handle<NativeContext>> contexts); 32 std::vector<Address> StartProcessing(); 33 void FinishProcessing(const NativeContextStats& stats); 34 35 static std::unique_ptr<v8::MeasureMemoryDelegate> DefaultDelegate( 36 Isolate* isolate, Handle<NativeContext> context, 37 Handle<JSPromise> promise, v8::MeasureMemoryMode mode); 38 39 private: 40 static const int kGCTaskDelayInSeconds = 10; 41 struct Request { 42 std::unique_ptr<v8::MeasureMemoryDelegate> delegate; 43 Handle<WeakFixedArray> contexts; 44 std::vector<size_t> sizes; 45 size_t shared; 46 base::ElapsedTimer timer; 47 }; 48 void ScheduleReportingTask(); 49 void ReportResults(); 50 void ScheduleGCTask(v8::MeasureMemoryExecution execution); 51 bool IsGCTaskPending(v8::MeasureMemoryExecution execution); 52 void SetGCTaskPending(v8::MeasureMemoryExecution execution); 53 void SetGCTaskDone(v8::MeasureMemoryExecution execution); 54 int NextGCTaskDelayInSeconds(); 55 56 std::list<Request> received_; 57 std::list<Request> processing_; 58 std::list<Request> done_; 59 Isolate* isolate_; 60 bool reporting_task_pending_ = false; 61 bool delayed_gc_task_pending_ = false; 62 bool eager_gc_task_pending_ = false; 63 base::RandomNumberGenerator random_number_generator_; 64 }; 65 66 // Infers the native context for some of the heap objects. 67 class V8_EXPORT_PRIVATE NativeContextInferrer { 68 public: 69 // The native_context parameter is both the input and output parameter. 70 // It should be initialized to the context that will be used for the object 71 // if the inference is not successful. The function performs more work if the 72 // context is the shared context. 73 V8_INLINE bool Infer(Isolate* isolate, Map map, HeapObject object, 74 Address* native_context); 75 76 private: 77 bool InferForContext(Isolate* isolate, Context context, 78 Address* native_context); 79 bool InferForJSFunction(Isolate* isolate, JSFunction function, 80 Address* native_context); 81 bool InferForJSObject(Isolate* isolate, Map map, JSObject object, 82 Address* native_context); 83 }; 84 85 // Maintains mapping from native contexts to their sizes. 86 class V8_EXPORT_PRIVATE NativeContextStats { 87 public: 88 V8_INLINE void IncrementSize(Address context, Map map, HeapObject object, 89 size_t size); 90 Get(Address context)91 size_t Get(Address context) const { 92 const auto it = size_by_context_.find(context); 93 if (it == size_by_context_.end()) return 0; 94 return it->second; 95 } 96 void Clear(); 97 void Merge(const NativeContextStats& other); 98 99 private: 100 V8_INLINE bool HasExternalBytes(Map map); 101 void IncrementExternalSize(Address context, Map map, HeapObject object); 102 std::unordered_map<Address, size_t> size_by_context_; 103 }; 104 105 } // namespace internal 106 } // namespace v8 107 108 #endif // V8_HEAP_MEMORY_MEASUREMENT_H_ 109