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