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