From 1e0bf05aafbbbc595df83068439eb11debf3eeca Mon Sep 17 00:00:00 2001 From: Ben Konyi Date: Thu, 26 Jan 2017 15:24:03 -0800 Subject: [PATCH] Added tracking of memory usage within ApiNativeScopes. Usage to be displayed within Observatory. BUG= R=asiva@google.com Review-Url: https://codereview.chromium.org/2650583014 . --- runtime/vm/dart_api_state.cc | 2 ++ runtime/vm/dart_api_state.h | 20 ++++++++++++++++++++ runtime/vm/zone.cc | 21 +++++++++++++-------- runtime/vm/zone_test.cc | 16 ++++++++++++++++ 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/runtime/vm/dart_api_state.cc b/runtime/vm/dart_api_state.cc index 2d1d82717e8..d5d0d3b7b08 100644 --- a/runtime/vm/dart_api_state.cc +++ b/runtime/vm/dart_api_state.cc @@ -14,6 +14,8 @@ namespace dart { +intptr_t ApiNativeScope::current_memory_usage_ = 0; + BackgroundFinalizer::BackgroundFinalizer(Isolate* isolate, FinalizationQueue* queue) : isolate_(isolate), queue_(queue) { diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h index 3ca4f728b0d..7946ef8ea5b 100644 --- a/runtime/vm/dart_api_state.h +++ b/runtime/vm/dart_api_state.h @@ -674,11 +674,18 @@ class ApiNativeScope { ASSERT(Current() == NULL); OSThread::SetThreadLocal(Api::api_native_key_, reinterpret_cast(this)); + // We manually increment the memory usage counter since there is memory + // initially allocated within the zone on creation. + IncrementNativeScopeMemoryUsage(zone_.GetZone()->CapacityInBytes()); } ~ApiNativeScope() { ASSERT(Current() == this); OSThread::SetThreadLocal(Api::api_native_key_, 0); + // We must also manually decrement the memory usage counter since the native + // is still holding it's initial memory and ~Zone() won't be able to + // determine which memory usage counter to decrement. + DecrementNativeScopeMemoryUsage(zone_.GetZone()->CapacityInBytes()); } static inline ApiNativeScope* Current() { @@ -686,6 +693,16 @@ class ApiNativeScope { OSThread::GetThreadLocal(Api::api_native_key_)); } + static intptr_t current_memory_usage() { return current_memory_usage_; } + + static void IncrementNativeScopeMemoryUsage(intptr_t size) { + AtomicOperations::IncrementBy(¤t_memory_usage_, size); + } + + static void DecrementNativeScopeMemoryUsage(intptr_t size) { + AtomicOperations::DecrementBy(¤t_memory_usage_, size); + } + Zone* zone() { Zone* result = zone_.GetZone(); ASSERT(result->handles()->CountScopedHandles() == 0); @@ -694,6 +711,9 @@ class ApiNativeScope { } private: + // The current total memory usage within ApiNativeScopes. + static intptr_t current_memory_usage_; + ApiZone zone_; }; diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc index 05e7eb75806..b4c8e312cd1 100644 --- a/runtime/vm/zone.cc +++ b/runtime/vm/zone.cc @@ -6,6 +6,7 @@ #include "platform/assert.h" #include "platform/utils.h" +#include "vm/dart_api_state.h" #include "vm/flags.h" #include "vm/handles_impl.h" #include "vm/heap.h" @@ -46,9 +47,10 @@ void Zone::Segment::DeleteSegmentList(Segment* head) { Thread* current_thread = Thread::Current(); while (current != NULL) { if (current_thread != NULL) { - // TODO(bkonyi) Handle special case of segment deletion within native - // isolate. current_thread->DecrementMemoryUsage(current->size()); + } else if (ApiNativeScope::Current() != NULL) { + // If there is no current thread, we might be inside of a native scope. + ApiNativeScope::DecrementNativeScopeMemoryUsage(current->size()); } Segment* next = current->next(); #ifdef DEBUG @@ -74,15 +76,19 @@ Zone::Segment* Zone::Segment::New(intptr_t size, Zone::Segment* next) { #endif result->next_ = next; result->size_ = size; - if (Thread::Current() != NULL) { - // TODO(bkonyi) Handle special case of segment creation within native - // isolate. - Thread::Current()->IncrementMemoryUsage(size); + Thread* current = Thread::Current(); + if (current != NULL) { + current->IncrementMemoryUsage(size); + } else if (ApiNativeScope::Current() != NULL) { + // If there is no current thread, we might be inside of a native scope. + ApiNativeScope::IncrementNativeScopeMemoryUsage(size); } return result; } - +// TODO(bkonyi): We need to account for the initial chunk size when a new zone +// is created within a new thread or ApiNativeScope when calculating high +// watermarks or memory consumption. Zone::Zone() : initial_buffer_(buffer_, kInitialChunkSize), position_(initial_buffer_.start()), @@ -117,7 +123,6 @@ void Zone::DeleteAll() { if (large_segments_ != NULL) { Segment::DeleteSegmentList(large_segments_); } - // Reset zone state. #ifdef DEBUG memset(initial_buffer_.pointer(), kZapDeletedByte, initial_buffer_.size()); diff --git a/runtime/vm/zone_test.cc b/runtime/vm/zone_test.cc index ba0a25b188c..21b50c0076c 100644 --- a/runtime/vm/zone_test.cc +++ b/runtime/vm/zone_test.cc @@ -228,4 +228,20 @@ UNIT_TEST_CASE(PrintZoneMemoryInfoToJSON) { } #endif + +UNIT_TEST_CASE(NativeScopeZoneAllocation) { + ASSERT(ApiNativeScope::Current() == NULL); + ASSERT(Thread::Current() == NULL); + EXPECT_EQ(0, ApiNativeScope::current_memory_usage()); + { + ApiNativeScope scope; + EXPECT_EQ(scope.zone()->CapacityInBytes(), + ApiNativeScope::current_memory_usage()); + (void)Dart_ScopeAllocate(2048); + EXPECT_EQ(scope.zone()->CapacityInBytes(), + ApiNativeScope::current_memory_usage()); + } + EXPECT_EQ(0, ApiNativeScope::current_memory_usage()); +} + } // namespace dart