< prev index next >
src/hotspot/share/runtime/heapMonitoring.cpp
Print this page
rev 48551 : [mq]: heap8
rev 48552 : [mq]: heap10a
rev 48553 : [mq]: heap14_rebased
rev 48555 : [mq]: heap16
rev 48556 : [mq]: heap17
rev 48557 : [mq]: heap17
rev 48558 : [mq]: heap19
rev 48559 : [mq]: heap20
rev 48560 : [mq]: heap21
rev 48562 : [mq]: heap23
rev 48564 : [mq]: update-spec
rev 48565 : [mq]: event
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2017, Google and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Google and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -219,11 +219,12 @@
// Each object that we profile is stored as trace with the thread_id.
class StackTraceStorage : public CHeapObj<mtInternal> {
public:
// The function that gets called to add a trace to the list of
// traces we are maintaining.
- void add_trace(jvmtiAllocTraceInfo* trace, oop o);
+ // Returns if the trace got added or not.
+ bool add_trace(jvmtiAllocTraceInfo* trace, oop o);
// The function that gets called by the client to retrieve the list
// of stack traces. Passes a jvmtiAllocTraceInfo which will get mutated.
void get_live_alloc_stack_traces(JvmtiEnv* env,
jvmtiAllocTraceInfo** traces,
@@ -278,15 +279,10 @@
MutexLocker mu(HeapMonitorStorage_lock);
_stats.sample_rate_accumulation += rate;
_stats.sample_rate_count++;
}
- bool initialized() {
- return OrderAccess::load_acquire(&_initialized) != 0;
- return _initialized;
- }
-
private:
// The traces currently sampled.
GrowableArray<StackTraceDataWithOop>* _allocated_traces;
// The traces currently sampled.
@@ -303,11 +299,11 @@
// Maximum amount of storage provided by the JVMTI call initialize_profiling.
int _max_gc_storage;
static StackTraceStorage* internal_storage;
- int _initialized;
+ bool _initialized;
// Support functions and classes for copying data to the external
// world.
class StackTraceDataCopier {
public:
@@ -390,11 +386,11 @@
_allocated_traces = NULL;
_traces_on_last_full_gc = NULL;
_recent_garbage_traces = NULL;
_frequent_garbage_traces = NULL;
_max_gc_storage = 0;
- OrderAccess::release_store(&_initialized, 0);
+ _initialized = false;
}
void StackTraceStorage::free_garbage() {
StackTraceData** recent_garbage = NULL;
uint32_t recent_size = 0;
@@ -423,11 +419,11 @@
StackTraceData::unreference_and_free(frequent_garbage[i]);
}
}
void StackTraceStorage::free_storage() {
- if (!initialized()) {
+ if (!_initialized) {
return;
}
delete _allocated_traces;
delete _traces_on_last_full_gc;
@@ -438,21 +434,20 @@
reset();
}
StackTraceStorage::~StackTraceStorage() {
- MutexLocker mu(HeapMonitorStorage_lock);
free_storage();
}
void StackTraceStorage::allocate_storage(int max_gc_storage) {
assert(HeapMonitorStorage_lock->owned_by_self()
|| (SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread()),
"This should not be accessed concurrently");
// In case multiple threads got locked and then 1 by 1 got through.
- if (initialized()) {
+ if (_initialized) {
return;
}
_allocated_traces = new (ResourceObj::C_HEAP, mtInternal)
GrowableArray<StackTraceDataWithOop>(128, true);
@@ -462,30 +457,41 @@
_recent_garbage_traces = new MostRecentGarbageTraces(max_gc_storage);
_frequent_garbage_traces = new FrequentGarbageTraces(max_gc_storage);
_max_gc_storage = max_gc_storage;
memset(&_stats, 0, sizeof(_stats));
- OrderAccess::release_store(&_initialized, 1);
+ _initialized = true;
}
-void StackTraceStorage::add_trace(jvmtiAllocTraceInfo* trace, oop o) {
+bool StackTraceStorage::add_trace(jvmtiAllocTraceInfo* trace, oop o) {
MutexLocker mu(HeapMonitorStorage_lock);
- // Last minute check on initialization here in case:
- // Between the moment object_alloc_do_sample's check for initialization
- // and now, there was a stop() that deleted the data.
- if (initialized()) {
+ // Last minute check on initialization here in case the system got turned off
+ // and a few sample requests got through to here, ie:
+ // A sample point happened in TLAB, that code checks for
+ // HeapMonitoring::enabled and calls object_alloc_do_sample.
+ // The code starts getting a stacktrace and then calls the this add_trace.
+ //
+ // At the same time, another thread has turned off HeapMonitoring while the
+ // stacktraces were getting constructed and disables StackTraceStorage.
+ //
+ // Both disabling and this add_trace are protected by the same
+ // HeapMonitorStorage_lock mutex.
+ if (!_initialized) {
+ return false;
+ }
+
StackTraceDataWithOop new_data(trace, o);
_stats.sample_count++;
_stats.stack_depth_accumulation += trace->stack_info->frame_count;
_allocated_traces->append(new_data);
- }
+ return true;
}
void StackTraceStorage::weak_oops_do(BoolObjectClosure* is_alive,
OopClosure* f) {
size_t count = 0;
- if (initialized()) {
+ if (_initialized) {
int len = _allocated_traces->length();
_traces_on_last_full_gc->clear();
// Compact the oop traces. Moves the live oops to the beginning of the
@@ -847,13 +853,11 @@
StackTraceStorage::storage()->accumulate_sample_rate(rate);
}
void HeapMonitoring::object_alloc_do_sample(Thread* t, oopDesc* o, size_t byte_size) {
JavaThread* thread = static_cast<JavaThread*>(t);
- if (StackTraceStorage::storage()->initialized()) {
assert(t->is_Java_thread(), "non-Java thread passed to do_sample");
- JavaThread* thread = static_cast<JavaThread*>(t);
jvmtiAllocTraceInfo* trace = NEW_C_HEAP_OBJ(jvmtiAllocTraceInfo, mtInternal);
if (trace == NULL) {
return;
}
@@ -892,16 +896,15 @@
}
stack_info->frame_count = count;
}
if (stack_info->frame_count > 0) {
- // Success!
- StackTraceStorage::storage()->add_trace(trace, o);
+ if (StackTraceStorage::storage()->add_trace(trace, o)) {
return;
}
+ }
// Failure!
FREE_C_HEAP_ARRAY(jvmtiFrameInfo, frames);
FREE_C_HEAP_OBJ(stack_info);
FREE_C_HEAP_OBJ(trace);
- }
}
< prev index next >