| // Copyright 2019 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_HEAP_MEMORY_MEASUREMENT_H_ |
| #define V8_HEAP_MEMORY_MEASUREMENT_H_ |
| |
| #include <list> |
| #include <unordered_map> |
| |
| #include "include/v8-statistics.h" |
| #include "src/base/platform/elapsed-timer.h" |
| #include "src/base/utils/random-number-generator.h" |
| #include "src/common/globals.h" |
| #include "src/objects/contexts.h" |
| #include "src/objects/map.h" |
| #include "src/objects/objects.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| class Heap; |
| class NativeContextStats; |
| |
| class MemoryMeasurement { |
| public: |
| explicit MemoryMeasurement(Isolate* isolate); |
| |
| bool EnqueueRequest(std::unique_ptr<v8::MeasureMemoryDelegate> delegate, |
| v8::MeasureMemoryExecution execution, |
| const std::vector<Handle<NativeContext>> contexts); |
| std::vector<Address> StartProcessing(); |
| void FinishProcessing(const NativeContextStats& stats); |
| |
| static std::unique_ptr<v8::MeasureMemoryDelegate> DefaultDelegate( |
| Isolate* isolate, Handle<NativeContext> context, |
| Handle<JSPromise> promise, v8::MeasureMemoryMode mode); |
| |
| private: |
| static const int kGCTaskDelayInSeconds = 10; |
| struct Request { |
| std::unique_ptr<v8::MeasureMemoryDelegate> delegate; |
| Handle<WeakFixedArray> contexts; |
| std::vector<size_t> sizes; |
| size_t shared; |
| base::ElapsedTimer timer; |
| }; |
| void ScheduleReportingTask(); |
| void ReportResults(); |
| void ScheduleGCTask(v8::MeasureMemoryExecution execution); |
| bool IsGCTaskPending(v8::MeasureMemoryExecution execution); |
| void SetGCTaskPending(v8::MeasureMemoryExecution execution); |
| void SetGCTaskDone(v8::MeasureMemoryExecution execution); |
| int NextGCTaskDelayInSeconds(); |
| |
| std::list<Request> received_; |
| std::list<Request> processing_; |
| std::list<Request> done_; |
| Isolate* isolate_; |
| bool reporting_task_pending_ = false; |
| bool delayed_gc_task_pending_ = false; |
| bool eager_gc_task_pending_ = false; |
| base::RandomNumberGenerator random_number_generator_; |
| }; |
| |
| // Infers the native context for some of the heap objects. |
| class V8_EXPORT_PRIVATE NativeContextInferrer { |
| public: |
| // The native_context parameter is both the input and output parameter. |
| // It should be initialized to the context that will be used for the object |
| // if the inference is not successful. The function performs more work if the |
| // context is the shared context. |
| V8_INLINE bool Infer(Isolate* isolate, Map map, HeapObject object, |
| Address* native_context); |
| |
| private: |
| bool InferForContext(Isolate* isolate, Context context, |
| Address* native_context); |
| bool InferForJSFunction(Isolate* isolate, JSFunction function, |
| Address* native_context); |
| bool InferForJSObject(Isolate* isolate, Map map, JSObject object, |
| Address* native_context); |
| }; |
| |
| // Maintains mapping from native contexts to their sizes. |
| class V8_EXPORT_PRIVATE NativeContextStats { |
| public: |
| V8_INLINE void IncrementSize(Address context, Map map, HeapObject object, |
| size_t size); |
| |
| size_t Get(Address context) const { |
| const auto it = size_by_context_.find(context); |
| if (it == size_by_context_.end()) return 0; |
| return it->second; |
| } |
| void Clear(); |
| void Merge(const NativeContextStats& other); |
| |
| private: |
| V8_INLINE bool HasExternalBytes(Map map); |
| void IncrementExternalSize(Address context, Map map, HeapObject object); |
| std::unordered_map<Address, size_t> size_by_context_; |
| }; |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_HEAP_MEMORY_MEASUREMENT_H_ |