< 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

*** 24,53 **** #include "precompiled.hpp" #include "gc/shared/collectedHeap.hpp" #include "memory/universe.hpp" #include "runtime/heapMonitoring.hpp" #include "runtime/orderAccess.inline.hpp" #include "runtime/vframe.hpp" static const int MaxStackDepth = 1024; // Internal data structure representing traces, used when object has been GC'd. class StackTraceData : public CHeapObj<mtInternal> { private: ! jvmtiStackTrace* _trace; int _references; public: ! StackTraceData(jvmtiStackTrace* t) : _trace(t), _references(0) {} void increment_reference_count() { _references++; } ! jvmtiStackTrace* get_trace() const { return _trace; } static void unreference_and_free(StackTraceData* data) { if (!data) { --- 24,54 ---- #include "precompiled.hpp" #include "gc/shared/collectedHeap.hpp" #include "memory/universe.hpp" + #include "prims/jvmtiEnvBase.hpp" #include "runtime/heapMonitoring.hpp" #include "runtime/orderAccess.inline.hpp" #include "runtime/vframe.hpp" static const int MaxStackDepth = 1024; // Internal data structure representing traces, used when object has been GC'd. class StackTraceData : public CHeapObj<mtInternal> { private: ! jvmtiAllocTraceInfo* _trace; int _references; public: ! StackTraceData(jvmtiAllocTraceInfo* t) : _trace(t), _references(0) {} void increment_reference_count() { _references++; } ! jvmtiAllocTraceInfo* get_trace() const { return _trace; } static void unreference_and_free(StackTraceData* data) { if (!data) {
*** 55,65 **** } data->_references--; if (data->_references == 0) { if (data->_trace != NULL) { ! FREE_C_HEAP_ARRAY(jvmtiFrameInfo, data->_trace->frames); FREE_C_HEAP_OBJ(data->_trace); } delete data; } } --- 56,68 ---- } data->_references--; if (data->_references == 0) { if (data->_trace != NULL) { ! jvmtiStackInfo* stack_info = data->_trace->stack_info; ! FREE_C_HEAP_ARRAY(jvmtiFrameInfo, stack_info->frame_buffer); ! FREE_C_HEAP_OBJ(stack_info); FREE_C_HEAP_OBJ(data->_trace); } delete data; } }
*** 71,81 **** class StackTraceDataWithOop : public StackTraceData { private: oop _obj; public: ! StackTraceDataWithOop(jvmtiStackTrace* t, oop o) : StackTraceData(t) { store_oop(o); } StackTraceDataWithOop() : StackTraceData(NULL), _obj(NULL) { } --- 74,84 ---- class StackTraceDataWithOop : public StackTraceData { private: oop _obj; public: ! StackTraceDataWithOop(jvmtiAllocTraceInfo* t, oop o) : StackTraceData(t) { store_oop(o); } StackTraceDataWithOop() : StackTraceData(NULL), _obj(NULL) { }
*** 216,242 **** // 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(jvmtiStackTrace* trace, oop o); // The function that gets called by the client to retrieve the list ! // of stack traces. Passes a jvmtiStackTraces which will get mutated. ! void get_all_stack_traces(jvmtiStackTraces* traces); // The function that gets called by the client to retrieve the list ! // of stack traces. Passes a jvmtiStackTraces which will get mutated. ! void get_garbage_stack_traces(jvmtiStackTraces* traces); // The function that gets called by the client to retrieve the list ! // of stack traces. Passes a jvmtiStackTraces which will get mutated. ! void get_frequent_garbage_stack_traces(jvmtiStackTraces* traces); // The function that gets called by the client to retrieve the list ! // of stack traces. Passes a jvmtiStackTraces which will get mutated. ! void get_cached_stack_traces(jvmtiStackTraces* traces); // Executes whenever weak references are traversed. is_alive tells // you if the given oop is still reachable and live. void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f); --- 219,253 ---- // 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); // The function that gets called by the client to retrieve the list ! // of stack traces. Passes a jvmtiAllocTraceInfo which will get mutated. ! void get_all_stack_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr); // The function that gets called by the client to retrieve the list ! // of stack traces. Passes a jvmtiAllocTraceInfo which will get mutated. ! void get_garbage_stack_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr); // The function that gets called by the client to retrieve the list ! // of stack traces. Passes a jvmtiAllocTraceInfo which will get mutated. ! void get_frequent_garbage_stack_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr); // The function that gets called by the client to retrieve the list ! // of stack traces. Passes a jvmtiAllocTraceInfo which will get mutated. ! void get_cached_stack_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr); // Executes whenever weak references are traversed. is_alive tells // you if the given oop is still reachable and live. void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
*** 269,278 **** --- 280,290 ---- _stats.sample_rate_count++; } bool initialized() { return OrderAccess::load_acquire(&_initialized) != 0; + return _initialized; } private: // The traces currently sampled. GrowableArray<StackTraceDataWithOop>* _allocated_traces;
*** 324,347 **** private: StackTraceData** _data; int _size; }; - // Copies from StackTraceData to jvmtiStackTrace. - bool deep_copy(jvmtiStackTrace* to, const StackTraceData* from); - // Creates a deep copy of the list of StackTraceData. ! void copy_stack_traces(const StackTraceDataCopier &copier, ! jvmtiStackTraces* traces); void store_garbage_trace(const StackTraceDataWithOop &trace); void free_garbage(); void free_storage(); void reset(); void allocate_storage(int max_gc_storage); }; StackTraceStorage* StackTraceStorage::internal_storage; // Statics for Sampler --- 336,372 ---- private: StackTraceData** _data; int _size; }; // Creates a deep copy of the list of StackTraceData. ! void copy_stack_traces(JvmtiEnv* env, ! const StackTraceDataCopier &copier, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr); void store_garbage_trace(const StackTraceDataWithOop &trace); void free_garbage(); void free_storage(); void reset(); void allocate_storage(int max_gc_storage); + + int calculate_frame_count(const StackTraceDataCopier &copier); + int calculate_info_count(const StackTraceDataCopier &copier); + + bool copy_frame(const StackTraceData* stack_trace_data, + jvmtiAllocTraceInfo* current_alloc_traces, + jvmtiStackInfo* current_stack_info, + jvmtiFrameInfo* current_frame_info); + + // Returns frame copy success. Failure can result when there is no longer + // enough memory. + bool copy_frames(const StackTraceDataCopier& copier, int info_count, + unsigned char* start, + unsigned char* end); }; StackTraceStorage* StackTraceStorage::internal_storage; // Statics for Sampler
*** 351,364 **** --- 376,394 ---- // Cheap random number generator uint64_t HeapMonitoring::_rnd; StackTraceStorage::StackTraceStorage() { + MutexLocker mu(HeapMonitorStorage_lock); reset(); } void StackTraceStorage::reset() { + assert(HeapMonitorStorage_lock->owned_by_self() + || (SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread()), + "This should not be accessed concurrently"); + _allocated_traces = NULL; _traces_on_last_full_gc = NULL; _recent_garbage_traces = NULL; _frequent_garbage_traces = NULL; _max_gc_storage = 0;
*** 413,422 **** --- 443,456 ---- 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()) { return; }
*** 431,449 **** _max_gc_storage = max_gc_storage; memset(&_stats, 0, sizeof(_stats)); OrderAccess::release_store(&_initialized, 1); } ! void StackTraceStorage::add_trace(jvmtiStackTrace* 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()) { StackTraceDataWithOop new_data(trace, o); _stats.sample_count++; ! _stats.stack_depth_accumulation += trace->frame_count; _allocated_traces->append(new_data); } } void StackTraceStorage::weak_oops_do(BoolObjectClosure* is_alive, --- 465,483 ---- _max_gc_storage = max_gc_storage; memset(&_stats, 0, sizeof(_stats)); OrderAccess::release_store(&_initialized, 1); } ! void 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()) { StackTraceDataWithOop new_data(trace, o); _stats.sample_count++; ! _stats.stack_depth_accumulation += trace->stack_info->frame_count; _allocated_traces->append(new_data); } } void StackTraceStorage::weak_oops_do(BoolObjectClosure* is_alive,
*** 489,604 **** } log_develop_trace(gc, ref)("Clearing HeapMonitoring weak reference (" INT64_FORMAT ")", count); } - bool StackTraceStorage::deep_copy(jvmtiStackTrace* to, - const StackTraceData* from) { - const jvmtiStackTrace* src = from->get_trace(); - *to = *src; - - to->frames = - NEW_C_HEAP_ARRAY(jvmtiFrameInfo, src->frame_count, mtInternal); - - if (to->frames == NULL) { - return false; - } - - memcpy(to->frames, - src->frames, - sizeof(jvmtiFrameInfo) * src->frame_count); - return true; - } - // Called by the outside world; returns a copy of the stack traces // (because we could be replacing them as the user handles them). // The array is secretly null-terminated (to make it easier to reclaim). ! void StackTraceStorage::get_all_stack_traces(jvmtiStackTraces* traces) { MutexLocker mu(HeapMonitorStorage_lock); if (!_allocated_traces) { ! traces->stack_traces = NULL; ! traces->trace_count = 0; return; } LiveStackTraceDataCopier copier(_allocated_traces); ! copy_stack_traces(copier, traces); } // See comment on get_all_stack_traces ! void StackTraceStorage::get_garbage_stack_traces(jvmtiStackTraces* traces) { MutexLocker mu(HeapMonitorStorage_lock); if (!_recent_garbage_traces) { ! traces->stack_traces = NULL; ! traces->trace_count = 0; return; } GarbageStackTraceDataCopier copier(_recent_garbage_traces->get_traces(), _recent_garbage_traces->size()); ! copy_stack_traces(copier, traces); } // See comment on get_all_stack_traces void StackTraceStorage::get_frequent_garbage_stack_traces( ! jvmtiStackTraces* traces) { MutexLocker mu(HeapMonitorStorage_lock); if (!_frequent_garbage_traces) { ! traces->stack_traces = NULL; ! traces->trace_count = 0; return; } GarbageStackTraceDataCopier copier(_frequent_garbage_traces->get_traces(), _frequent_garbage_traces->size()); ! copy_stack_traces(copier, traces); } // See comment on get_all_stack_traces ! void StackTraceStorage::get_cached_stack_traces(jvmtiStackTraces* traces) { MutexLocker mu(HeapMonitorStorage_lock); if (!_traces_on_last_full_gc) { ! traces->stack_traces = NULL; ! traces->trace_count = 0; return; } LiveStackTraceDataCopier copier(_traces_on_last_full_gc); ! copy_stack_traces(copier, traces); } ! void StackTraceStorage::copy_stack_traces(const StackTraceDataCopier &copier, ! jvmtiStackTraces* traces) { int len = copier.size(); ! // Create a new array to store the StackTraceData objects. ! // + 1 for a NULL at the end. ! jvmtiStackTrace* t = ! NEW_C_HEAP_ARRAY(jvmtiStackTrace, len + 1, mtInternal); ! if (t == NULL) { ! traces->stack_traces = NULL; ! traces->trace_count = 0; ! return; } - // +1 to have a NULL at the end of the array. - memset(t, 0, (len + 1) * sizeof(*t)); ! // Copy the StackTraceData objects into the new array. ! int trace_count = 0; for (int i = 0; i < len; i++) { const StackTraceData* stack_trace = copier.get(i); if (stack_trace != NULL) { ! jvmtiStackTrace* to = &t[trace_count]; ! if (!deep_copy(to, stack_trace)) { ! continue; } ! trace_count++; } } ! traces->stack_traces = t; ! traces->trace_count = trace_count; } void StackTraceStorage::store_garbage_trace(const StackTraceDataWithOop &trace) { StackTraceData* new_trace = new StackTraceData(trace.get_trace()); --- 523,727 ---- } log_develop_trace(gc, ref)("Clearing HeapMonitoring weak reference (" INT64_FORMAT ")", count); } // Called by the outside world; returns a copy of the stack traces // (because we could be replacing them as the user handles them). // The array is secretly null-terminated (to make it easier to reclaim). ! void StackTraceStorage::get_all_stack_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr) { MutexLocker mu(HeapMonitorStorage_lock); if (!_allocated_traces) { ! *traces = NULL; ! *trace_counter_ptr = 0; return; } LiveStackTraceDataCopier copier(_allocated_traces); ! copy_stack_traces(env, copier, traces, trace_counter_ptr); } // See comment on get_all_stack_traces ! void StackTraceStorage::get_garbage_stack_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr) { MutexLocker mu(HeapMonitorStorage_lock); if (!_recent_garbage_traces) { ! *traces = NULL; ! *trace_counter_ptr = 0; return; } GarbageStackTraceDataCopier copier(_recent_garbage_traces->get_traces(), _recent_garbage_traces->size()); ! copy_stack_traces(env, copier, traces, trace_counter_ptr); } // See comment on get_all_stack_traces void StackTraceStorage::get_frequent_garbage_stack_traces( ! JvmtiEnv* env, jvmtiAllocTraceInfo** traces, jint* trace_counter_ptr) { MutexLocker mu(HeapMonitorStorage_lock); if (!_frequent_garbage_traces) { ! *traces = NULL; ! *trace_counter_ptr = 0; return; } GarbageStackTraceDataCopier copier(_frequent_garbage_traces->get_traces(), _frequent_garbage_traces->size()); ! copy_stack_traces(env, copier, traces, trace_counter_ptr); } // See comment on get_all_stack_traces ! void StackTraceStorage::get_cached_stack_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr) { MutexLocker mu(HeapMonitorStorage_lock); if (!_traces_on_last_full_gc) { ! *traces = NULL; ! *trace_counter_ptr = 0; return; } LiveStackTraceDataCopier copier(_traces_on_last_full_gc); ! copy_stack_traces(env, copier, traces, trace_counter_ptr); } ! int StackTraceStorage::calculate_frame_count(const StackTraceDataCopier &copier) { int len = copier.size(); ! // Walk the traces first to find the size of the frames as well. ! int frame_total = 0; ! ! for (int i = 0; i < len; i++) { ! const StackTraceData* stack_trace = copier.get(i); ! ! if (stack_trace != NULL) { ! jvmtiAllocTraceInfo* trace = stack_trace->get_trace(); ! jvmtiStackInfo* stack_info = trace->stack_info; ! frame_total += stack_info->frame_count; ! } } ! return frame_total; ! } ! ! int StackTraceStorage::calculate_info_count(const StackTraceDataCopier &copier) { ! int len = copier.size(); ! ! int info_total = 0; ! for (int i = 0; i < len; i++) { const StackTraceData* stack_trace = copier.get(i); + if (stack_trace != NULL) { ! // TODO: merge this with the method above. ! info_total++; ! } ! } ! ! return info_total; ! } ! ! // Method to test if the data structure would fit between the src address and ! // the end address. ! template<typename T, typename U> ! static bool next_ptr_less_or_equal(T src, U* end) { ! return (src + 1) <= reinterpret_cast<T>(end); ! } ! ! bool StackTraceStorage::copy_frame(const StackTraceData* stack_trace_data, ! jvmtiAllocTraceInfo* current_alloc_trace, ! jvmtiStackInfo* current_stack_info, ! jvmtiFrameInfo* current_frame_info) { ! jvmtiAllocTraceInfo* trace = stack_trace_data->get_trace(); ! jvmtiStackInfo* stack_info = trace->stack_info; ! int frame_count = stack_info->frame_count; ! ! memcpy(current_alloc_trace, trace, sizeof(*trace)); ! ! current_alloc_trace->stack_info = current_stack_info; ! memcpy(current_stack_info, stack_info, sizeof(*stack_info)); ! ! current_stack_info->frame_buffer = current_frame_info; ! memcpy(current_frame_info, stack_info->frame_buffer, ! sizeof(jvmtiFrameInfo) * frame_count); ! return true; ! } ! ! bool StackTraceStorage::copy_frames(const StackTraceDataCopier& copier, ! int info_count, ! unsigned char* start, ! unsigned char* end) { ! jvmtiAllocTraceInfo* start_alloc_trace = reinterpret_cast<jvmtiAllocTraceInfo*>(start); ! jvmtiStackInfo* start_stack_info = reinterpret_cast<jvmtiStackInfo*>(start_alloc_trace + info_count); ! jvmtiFrameInfo* start_frame_info = reinterpret_cast<jvmtiFrameInfo*>(start_stack_info + info_count); ! ! jvmtiAllocTraceInfo* current_alloc_trace = start_alloc_trace; ! jvmtiStackInfo* current_stack_info = start_stack_info; ! jvmtiFrameInfo* current_frame_info = start_frame_info; ! ! for (int i = 0; i < info_count; i++) { ! assert(next_ptr_less_or_equal(current_alloc_trace, start_stack_info), ! "jvmtiAllocTraceInfo would write over jvmtiStackInfos."); ! assert(next_ptr_less_or_equal(current_stack_info, start_frame_info), ! "jvmtiStackInfo would write over jvmtiFrameInfos."); ! ! assert(next_ptr_less_or_equal(current_frame_info, end), ! "jvmtiFrameInfo would write over the end of the buffer."); ! ! const StackTraceData* stack_trace_data = copier.get(i); ! if (stack_trace_data != NULL) { ! if (!copy_frame(stack_trace_data, current_alloc_trace, ! current_stack_info, current_frame_info)) { ! return false; } ! ! current_frame_info += current_stack_info->frame_count; ! current_stack_info++; ! current_alloc_trace++; } } ! return true; ! } ! ! void StackTraceStorage::copy_stack_traces(JvmtiEnv* env, ! const StackTraceDataCopier& copier, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr) { ! *traces = NULL; ! *trace_counter_ptr = 0; ! ! int frame_total = calculate_frame_count(copier); ! int len = calculate_info_count(copier); ! ! // Allocate the whole stacktraces in one bloc to simplify freeing. ! size_t total_size = len * sizeof(jvmtiAllocTraceInfo) ! + len * sizeof(jvmtiStackInfo) ! + frame_total * sizeof(jvmtiFrameInfo); ! ! unsigned char* buffer = NULL; ! jvmtiAllocTraceInfo* result = NULL; ! JvmtiEnvBase* env_base = reinterpret_cast<JvmtiEnvBase*>(env); ! env_base->allocate(total_size, &buffer); ! ! if (buffer == NULL) { ! return; ! } ! ! bool success = copy_frames(copier, len, buffer, buffer + total_size); ! ! if (!success) { ! env_base->deallocate(buffer); ! return; ! } ! ! *trace_counter_ptr = len; ! *traces = reinterpret_cast<jvmtiAllocTraceInfo*>(buffer); } void StackTraceStorage::store_garbage_trace(const StackTraceDataWithOop &trace) { StackTraceData* new_trace = new StackTraceData(trace.get_trace());
*** 613,656 **** } _stats.garbage_collected_samples++; } ! void HeapMonitoring::get_live_traces(jvmtiStackTraces* traces) { ! StackTraceStorage::storage()->get_all_stack_traces(traces); } void HeapMonitoring::get_sampling_statistics(jvmtiHeapSamplingStats* stats) { const jvmtiHeapSamplingStats& internal_stats = StackTraceStorage::storage()->get_heap_sampling_stats(); *stats = internal_stats; } ! void HeapMonitoring::get_frequent_garbage_traces(jvmtiStackTraces* traces) { ! StackTraceStorage::storage()->get_frequent_garbage_stack_traces(traces); ! } ! ! void HeapMonitoring::get_garbage_traces(jvmtiStackTraces* traces) { ! StackTraceStorage::storage()->get_garbage_stack_traces(traces); ! } ! ! void HeapMonitoring::get_cached_traces(jvmtiStackTraces* traces) { ! StackTraceStorage::storage()->get_cached_stack_traces(traces); ! } ! ! void HeapMonitoring::release_traces(jvmtiStackTraces* traces) { ! jint trace_count = traces->trace_count; ! jvmtiStackTrace* stack_traces = traces->stack_traces; ! ! for (jint i = 0; i < trace_count; i++) { ! jvmtiStackTrace* current_trace = stack_traces + i; ! FREE_C_HEAP_ARRAY(jvmtiFrameInfo, current_trace->frames); ! } ! ! FREE_C_HEAP_ARRAY(jvmtiStackTrace, traces->stack_traces); ! traces->trace_count = 0; ! traces->stack_traces = NULL; } // Invoked by the GC to clean up old stack traces and remove old arrays // of instrumentation that are still lying around. void HeapMonitoring::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) { --- 736,780 ---- } _stats.garbage_collected_samples++; } ! void HeapMonitoring::get_live_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr) { ! StackTraceStorage::storage()->get_all_stack_traces(env, ! traces, ! trace_counter_ptr); } void HeapMonitoring::get_sampling_statistics(jvmtiHeapSamplingStats* stats) { const jvmtiHeapSamplingStats& internal_stats = StackTraceStorage::storage()->get_heap_sampling_stats(); *stats = internal_stats; } ! void HeapMonitoring::get_frequent_garbage_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr) { ! StackTraceStorage::storage()->get_frequent_garbage_stack_traces( ! env, traces, trace_counter_ptr); ! } ! ! void HeapMonitoring::get_garbage_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr) { ! StackTraceStorage::storage()->get_garbage_stack_traces(env, ! traces, ! trace_counter_ptr); ! } ! ! void HeapMonitoring::get_cached_traces(JvmtiEnv* env, ! jvmtiAllocTraceInfo** traces, ! jint* trace_counter_ptr) { ! StackTraceStorage::storage()->get_cached_stack_traces(env, ! traces, ! trace_counter_ptr); } // Invoked by the GC to clean up old stack traces and remove old arrays // of instrumentation that are still lying around. void HeapMonitoring::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
*** 729,761 **** *ptr = rate; StackTraceStorage::storage()->accumulate_sample_rate(rate); } ! void HeapMonitoring::object_alloc_do_sample(Thread* t, oopDesc* o, intx 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); ! jvmtiStackTrace* trace = NEW_C_HEAP_OBJ(jvmtiStackTrace, mtInternal); if (trace == NULL) { return; } jvmtiFrameInfo* frames = NEW_C_HEAP_ARRAY(jvmtiFrameInfo, MaxStackDepth, mtInternal); if (frames == NULL) { FREE_C_HEAP_OBJ(trace); return; } - trace->frames = frames; trace->thread_id = SharedRuntime::get_java_tid(thread); trace->size = byte_size; - trace->frame_count = 0; if (thread->has_last_Java_frame()) { // just to be safe vframeStream vfst(thread, true); int count = 0; while (!vfst.at_end() && count < MaxStackDepth) { --- 853,893 ---- *ptr = rate; 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; ! } ! ! jvmtiStackInfo* stack_info = NEW_C_HEAP_OBJ(jvmtiStackInfo, mtInternal); if (trace == NULL) { + FREE_C_HEAP_OBJ(trace); return; } + trace->stack_info = stack_info; jvmtiFrameInfo* frames = NEW_C_HEAP_ARRAY(jvmtiFrameInfo, MaxStackDepth, mtInternal); if (frames == NULL) { + FREE_C_HEAP_OBJ(stack_info); FREE_C_HEAP_OBJ(trace); return; } + stack_info->frame_buffer = frames; + stack_info->frame_count = 0; trace->thread_id = SharedRuntime::get_java_tid(thread); trace->size = byte_size; if (thread->has_last_Java_frame()) { // just to be safe vframeStream vfst(thread, true); int count = 0; while (!vfst.at_end() && count < MaxStackDepth) {
*** 764,782 **** frames[count].method = m->jmethod_id(); count++; vfst.next(); } ! trace->frame_count = count; } ! if (trace->frame_count> 0) { // Success! StackTraceStorage::storage()->add_trace(trace, o); return; } // Failure! ! FREE_C_HEAP_ARRAY(jvmtiFrameInfo, trace->frames); FREE_C_HEAP_OBJ(trace); } } --- 896,915 ---- frames[count].method = m->jmethod_id(); count++; vfst.next(); } ! stack_info->frame_count = count; } ! if (stack_info->frame_count > 0) { // Success! 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 >