Skip to content

Commit 040d29c

Browse files
allow VM to skip native frames fully
1 parent d1fa57e commit 040d29c

File tree

5 files changed

+50
-25
lines changed

5 files changed

+50
-25
lines changed

src/arguments.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ Error Arguments::parse(const char* args) {
254254
if (strstr(value, "comptask")) _features.comp_task = 1;
255255
if (strstr(value, "pcaddr")) _features.pc_addr = 1;
256256
if (strstr(value, "agct")) _features.agct = 1;
257+
if (strstr(value, "nonative")) _features.no_native = 1;
257258
}
258259

259260
CASE("file")

src/arguments.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ struct StackWalkFeatures {
112112
unsigned short vtable_target : 1; // show receiver classes of vtable/itable stubs
113113
unsigned short comp_task : 1; // display current compilation task for JIT threads
114114
unsigned short pc_addr : 1; // record exact PC address for each sample
115-
unsigned short _padding : 9; // pad structure to 16 bits
115+
unsigned short no_native : 1; // do not collect native stacks
116+
unsigned short _padding : 8; // pad structure to 16 bits
116117
};
117118

118119

src/profiler.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ u64 Profiler::recordSample(void* ucontext, u64 counter, EventType event_type, Ev
426426
if (_features.pc_addr && event_type <= WALL_CLOCK_SAMPLE) {
427427
num_frames += makeFrame(frames + num_frames, BCI_ADDRESS, StackFrame(ucontext).pc());
428428
}
429-
if (_cstack != CSTACK_NO) {
429+
if (!_features.no_native || _cstack != CSTACK_NO) {
430430
num_frames += getNativeTrace(ucontext, frames + num_frames, event_type, tid, &cpu);
431431
}
432432
}
@@ -869,6 +869,18 @@ Error Profiler::start(Arguments& args, bool reset) {
869869
// Save the arguments for shutdown or restart
870870
args.save();
871871

872+
_features = args._features;
873+
if (!VMStructs::hasClassNames()) {
874+
_features.vtable_target = 0;
875+
}
876+
if (!VMStructs::hasCompilerStructs()) {
877+
_features.comp_task = 0;
878+
}
879+
880+
if (args._cstack == CSTACK_NO) {
881+
_features.no_native = 1;
882+
}
883+
872884
if (reset || _start_time == 0) {
873885
// Reset counters
874886
_total_samples = 0;
@@ -884,7 +896,7 @@ Error Profiler::start(Arguments& args, bool reset) {
884896
_add_event_frame = args._output != OUTPUT_JFR;
885897
_add_thread_frame = args._threads && args._output != OUTPUT_JFR;
886898
_add_sched_frame = args._sched;
887-
_add_cpu_frame = args._record_cpu;
899+
_add_cpu_frame = args._record_cpu && !_features.no_native;
888900
unlockAll();
889901

890902
// Reset thread names and IDs
@@ -908,14 +920,6 @@ Error Profiler::start(Arguments& args, bool reset) {
908920
}
909921
}
910922

911-
_features = args._features;
912-
if (!VMStructs::hasClassNames()) {
913-
_features.vtable_target = 0;
914-
}
915-
if (!VMStructs::hasCompilerStructs()) {
916-
_features.comp_task = 0;
917-
}
918-
919923
_update_thread_names = args._threads || args._output == OUTPUT_JFR;
920924
_thread_filter.init(args._filter);
921925

src/stackWalker.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ int StackWalker::walkVM(void* ucontext, ASGCT_CallFrame* frames, int max_depth,
235235

236236
// Show extended frame types and stub frames for execution-type events
237237
bool details = event_type <= MALLOC_SAMPLE || features.mixed;
238+
bool no_native = features.no_native;
238239

239240
JavaFrameAnchor* anchor = NULL;
240241
VMThread* vm_thread = VMThread::current();
@@ -248,6 +249,12 @@ int StackWalker::walkVM(void* ucontext, ASGCT_CallFrame* frames, int max_depth,
248249
}
249250
}
250251

252+
// Jump directly to java frame if possible in case native frames are not desired
253+
if (no_native && anchor != NULL) {
254+
anchor->restoreFrame(pc, sp, fp);
255+
anchor = NULL;
256+
}
257+
251258
unwind_loop:
252259
uintptr_t prev_sp = sp;
253260
while (depth < max_depth) {
@@ -388,7 +395,7 @@ int StackWalker::walkVM(void* ucontext, ASGCT_CallFrame* frames, int max_depth,
388395
const void* start = stub != NULL ? stub->_start : nm->code();
389396
const char* name = stub != NULL ? stub->_name : nm->name();
390397

391-
if (details) {
398+
if (!no_native && details) {
392399
fillFrame(frames[depth++], BCI_NATIVE_FRAME, name);
393400
}
394401

@@ -405,22 +412,24 @@ int StackWalker::walkVM(void* ucontext, ASGCT_CallFrame* frames, int max_depth,
405412
}
406413
} else {
407414
native_lib = profiler->findLibraryByAddress(pc);
408-
const char* method_name = native_lib != NULL ? native_lib->binarySearch(pc) : NULL;
409-
char mark;
410-
if (method_name != NULL && (mark = NativeFunc::mark(method_name)) != 0) {
411-
if (mark == MARK_ASYNC_PROFILER && (event_type == MALLOC_SAMPLE || event_type == NATIVE_LOCK_SAMPLE)) {
412-
// Skip all internal frames above hook functions, leave the hook itself
413-
depth = 0;
414-
} else if (mark == MARK_COMPILER_ENTRY && features.comp_task && vm_thread != NULL) {
415-
// Insert current compile task as a pseudo Java frame
416-
VMMethod* method = vm_thread->compiledMethod();
417-
jmethodID method_id = method != NULL ? method->id() : NULL;
418-
if (method_id != NULL) {
419-
fillFrame(frames[depth++], FRAME_JIT_COMPILED, 0, method_id);
415+
if (!no_native) {
416+
const char* method_name = native_lib != NULL ? native_lib->binarySearch(pc) : NULL;
417+
char mark;
418+
if (method_name != NULL && (mark = NativeFunc::mark(method_name)) != 0) {
419+
if (mark == MARK_ASYNC_PROFILER && (event_type == MALLOC_SAMPLE || event_type == NATIVE_LOCK_SAMPLE)) {
420+
// Skip all internal frames above hook functions, leave the hook itself
421+
depth = 0;
422+
} else if (mark == MARK_COMPILER_ENTRY && features.comp_task && vm_thread != NULL) {
423+
// Insert current compile task as a pseudo Java frame
424+
VMMethod* method = vm_thread->compiledMethod();
425+
jmethodID method_id = method != NULL ? method->id() : NULL;
426+
if (method_id != NULL) {
427+
fillFrame(frames[depth++], FRAME_JIT_COMPILED, 0, method_id);
428+
}
420429
}
421430
}
431+
fillFrame(frames[depth++], BCI_NATIVE_FRAME, method_name);
422432
}
423-
fillFrame(frames[depth++], BCI_NATIVE_FRAME, method_name);
424433
}
425434

426435
FrameDesc* f = native_lib != NULL ? native_lib->findFrameDesc(pc) : &FrameDesc::default_frame;

test/test/cstack/CstackTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ public void asyncGetCallTrace(TestProcess p) throws Exception {
2626
assert out.contains("LongInitializer.main_\\[j]");
2727
}
2828

29+
@Test(mainClass = LongInitializer.class, jvm = Jvm.HOTSPOT)
30+
public void noNative(TestProcess p) throws Exception {
31+
Output out = p.profile(PROFILE_COMMAND + "--cstack no");
32+
assert !out.contains(";readBytes");
33+
assert out.contains("LongInitializer.main_\\[0]");
34+
assert !out.contains("InstanceKlass::initialize");
35+
assert !out.contains("call_stub");
36+
assert !out.contains("JavaMain");
37+
}
38+
2939
@Test(mainClass = LongInitializer.class, jvm = Jvm.HOTSPOT, os = Os.LINUX)
3040
public void vmStructs(TestProcess p) throws Exception {
3141
Output out = p.profile(PROFILE_COMMAND + "--cstack vm");

0 commit comments

Comments
 (0)