diff --git a/src/arguments.cpp b/src/arguments.cpp index 2343d8f15..cabc14001 100644 --- a/src/arguments.cpp +++ b/src/arguments.cpp @@ -76,7 +76,7 @@ static const Multiplier UNIVERSAL[] = {{'n', 1}, {'u', 1000}, {'m', 1000000}, {' // interval=N - sampling interval in ns (default: 10'000'000, i.e. 10 ms) // jstackdepth=N - maximum Java stack depth (default: 2048) // signal=N - use alternative signal for cpu or wall clock profiling -// features=LIST - advanced stack trace features (vtable, comptask)" +// features=LIST - advanced stack trace features (vtable, comptask, pcaddr)" // safemode=BITS - disable stack recovery techniques (default: 0, i.e. everything enabled) // file=FILENAME - output file name for dumping // log=FILENAME - log warnings and errors to the given dedicated stream @@ -272,6 +272,7 @@ Error Arguments::parse(const char* args) { if (strstr(value, "probesp")) _features.probe_sp = 1; if (strstr(value, "vtable")) _features.vtable_target = 1; if (strstr(value, "comptask")) _features.comp_task = 1; + if (strstr(value, "pcaddr")) _features.pc_addr = 1; } CASE("safemode") { diff --git a/src/arguments.h b/src/arguments.h index 951cceab0..ead35f55d 100644 --- a/src/arguments.h +++ b/src/arguments.h @@ -108,10 +108,11 @@ struct StackWalkFeatures { unsigned short probe_sp : 1; unsigned short vtable_target : 1; unsigned short comp_task : 1; - unsigned short _reserved : 7; + unsigned short pc_addr : 1; + unsigned short _reserved : 6; StackWalkFeatures() : unknown_java(1), unwind_stub(1), unwind_comp(1), unwind_native(1), java_anchor(1), gc_traces(1), - probe_sp(0), vtable_target(0), comp_task(0), _reserved(0) { + probe_sp(0), vtable_target(0), comp_task(0), pc_addr(0), _reserved(0) { } }; diff --git a/src/flightRecorder.cpp b/src/flightRecorder.cpp index 399164739..813c7d251 100644 --- a/src/flightRecorder.cpp +++ b/src/flightRecorder.cpp @@ -255,6 +255,10 @@ class Lookup { } else if (frame.bci == BCI_NATIVE_FRAME) { const char* name = (const char*)method; fillNativeMethodInfo(mi, name, Profiler::instance()->getLibraryName(name)); + } else if (frame.bci == BCI_ADDRESS) { + char buf[32]; + snprintf(buf, sizeof(buf), "%p", method); + fillNativeMethodInfo(mi, buf, NULL); } else if (frame.bci == BCI_ERROR) { fillNativeMethodInfo(mi, (const char*)method, NULL); } else { @@ -709,7 +713,7 @@ class Recording { } const char* getFeaturesString(char* str, size_t size, StackWalkFeatures f) { - snprintf(str, size, "%s %s %s %s %s %s %s %s %s", + snprintf(str, size, "%s %s %s %s %s %s %s %s %s %s", f.unknown_java ? "unknown_java" : "-", f.unwind_stub ? "unwind_stub" : "-", f.unwind_comp ? "unwind_comp" : "-", @@ -718,7 +722,8 @@ class Recording { f.gc_traces ? "gc_traces" : "-", f.probe_sp ? "probesp" : "-", f.vtable_target ? "vtable" : "-", - f.comp_task ? "comptask" : "-"); + f.comp_task ? "comptask" : "-", + f.pc_addr ? "pcaddr" : "-"); return str; } diff --git a/src/frameName.cpp b/src/frameName.cpp index ac217db7d..cae3c6137 100644 --- a/src/frameName.cpp +++ b/src/frameName.cpp @@ -292,6 +292,12 @@ const char* FrameName::name(ASGCT_CallFrame& frame, bool for_matching) { } } + case BCI_ADDRESS: { + char buf[32]; + snprintf(buf, sizeof(buf), "%p", frame.method_id); + return _str.assign(buf).c_str(); + } + case BCI_ERROR: return _str.assign("[").append((const char*)frame.method_id).append("]").c_str(); @@ -345,6 +351,7 @@ FrameTypeId FrameName::type(ASGCT_CallFrame& frame) { return FRAME_KERNEL; case BCI_THREAD_ID: + case BCI_ADDRESS: case BCI_ERROR: return FRAME_NATIVE; diff --git a/src/main/main.cpp b/src/main/main.cpp index 94c95f8e8..0896ff431 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -57,7 +57,7 @@ static const char USAGE_STRING[] = " -I include output only stack traces containing the specified pattern\n" " -X exclude exclude stack traces with the specified pattern\n" " -L level log level: debug|info|warn|error|none\n" - " -F features advanced stack trace features: vtable, comptask\n" + " -F features advanced stack trace features: vtable, comptask, pcaddr\n" " -v, --version display version string\n" "\n" " --title string FlameGraph title\n" diff --git a/src/profiler.cpp b/src/profiler.cpp index fb1db10da..c3fa6ccd2 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -84,8 +84,8 @@ static bool sortByCounter(const NamedMethodSample& a, const NamedMethodSample& b } -static inline int noNativeStack(EventType event_type) { - return (1 << event_type) & ((1 << INSTRUMENTED_METHOD) | (1 << LOCK_SAMPLE) | (1 << PARK_SAMPLE)); +static inline int hasNativeStack(EventType event_type) { + return (1 << event_type) & ~((1 << INSTRUMENTED_METHOD) | (1 << LOCK_SAMPLE) | (1 << PARK_SAMPLE)); } static inline bool isVTableStub(const char* name) { @@ -320,10 +320,6 @@ int Profiler::getNativeTrace(void* ucontext, ASGCT_CallFrame* frames, EventType const void* callchain[MAX_NATIVE_FRAMES]; int native_frames; - if (_cstack == CSTACK_NO || noNativeStack(event_type)) { - return 0; - } - // Use PerfEvents stack walker for execution samples, or basic stack walker for other events if (event_type == PERF_SAMPLE) { native_frames = PerfEvents::walk(tid, ucontext, callchain, MAX_NATIVE_FRAMES, java_ctx); @@ -655,7 +651,14 @@ u64 Profiler::recordSample(void* ucontext, u64 counter, EventType event_type, Ev } StackContext java_ctx = {0}; - num_frames += getNativeTrace(ucontext, frames + num_frames, event_type, tid, &java_ctx); + if (hasNativeStack(event_type)) { + if (_features.pc_addr && event_type <= EXECUTION_SAMPLE) { + num_frames += makeFrame(frames + num_frames, BCI_ADDRESS, StackFrame(ucontext).pc()); + } + if (_cstack != CSTACK_NO) { + num_frames += getNativeTrace(ucontext, frames + num_frames, event_type, tid, &java_ctx); + } + } if (_cstack == CSTACK_VM) { num_frames += StackWalker::walkVM(ucontext, frames + num_frames, _max_stack_depth); diff --git a/src/vmEntry.h b/src/vmEntry.h index 31adda348..40cfbfc4b 100644 --- a/src/vmEntry.h +++ b/src/vmEntry.h @@ -40,7 +40,8 @@ enum ASGCT_CallFrameType { BCI_LOCK = -14, // class name of the locked object BCI_PARK = -15, // class name of the park() blocker BCI_THREAD_ID = -16, // method_id designates a thread - BCI_ERROR = -17, // method_id is an error string + BCI_ADDRESS = -17, // method_id is a PC address + BCI_ERROR = -18, // method_id is an error string }; // See hotspot/src/share/vm/prims/forte.cpp