Skip to content

Commit 9014a18

Browse files
committed
8293998: [PPC64] JfrGetCallTrace: assert(_pc != nullptr) failed: must have PC
Reviewed-by: phh Backport-of: 90cc8ac9398ff300f6d74383ea84fd82552f1c5d
1 parent 0013d84 commit 9014a18

File tree

2 files changed

+75
-11
lines changed

2 files changed

+75
-11
lines changed

src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
2-
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2012, 2014 SAP SE. All rights reserved.
4+
* Copyright (c) 2022, IBM Corp.
45
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
56
*
67
* This code is free software; you can redistribute it and/or modify it
@@ -24,6 +25,7 @@
2425
*/
2526

2627
#include "precompiled.hpp"
28+
#include "memory/metaspace.hpp"
2729
#include "runtime/frame.inline.hpp"
2830
#include "runtime/thread.hpp"
2931

@@ -34,23 +36,83 @@ frame JavaThread::pd_last_frame() {
3436
address pc = _anchor.last_Java_pc();
3537

3638
// Last_Java_pc ist not set, if we come here from compiled code.
37-
if (pc == NULL)
38-
pc = (address) *(sp + 2);
39+
// Assume spill slot for link register contains a suitable pc.
40+
// Should have been filled by method entry code.
41+
if (pc == NULL) {
42+
pc = (address) *(sp + 2);
43+
}
3944

4045
return frame(sp, pc);
4146
}
4247

4348
bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) {
44-
ucontext_t* uc = (ucontext_t*) ucontext;
45-
*fr_addr = frame((intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/],
46-
(address)uc->uc_mcontext.jmp_context.iar);
47-
return true;
49+
50+
// If we have a last_Java_frame, then we should use it even if
51+
// isInJava == true. It should be more reliable than ucontext info.
52+
if (has_last_Java_frame() && frame_anchor()->walkable()) {
53+
frame last_frame = pd_last_frame();
54+
if (last_frame.pc() == NULL) return false;
55+
*fr_addr = last_frame;
56+
return true;
57+
}
58+
59+
// At this point, we don't have a last_Java_frame, so
60+
// we try to glean some information out of the ucontext
61+
// if we were running Java code when SIGPROF came in.
62+
if (isInJava) {
63+
ucontext_t* uc = (ucontext_t*) ucontext;
64+
address pc = (address)uc->uc_mcontext.jmp_context.iar;
65+
66+
if (pc == NULL) {
67+
// ucontext wasn't useful
68+
return false;
69+
}
70+
71+
frame ret_frame((intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/], pc);
72+
73+
if (ret_frame.fp() == NULL) {
74+
// The found frame does not have a valid frame pointer.
75+
// Bail out because this will create big trouble later on, either
76+
// - when using istate, calculated as (NULL - ijava_state_size) or
77+
// - when using fp() directly in safe_for_sender()
78+
//
79+
// There is no conclusive description (yet) how this could happen, but it does.
80+
// For more details on what was observed, see thread_linux_s390.cpp
81+
return false;
82+
}
83+
84+
if (ret_frame.is_interpreted_frame()) {
85+
frame::ijava_state *istate = ret_frame.get_ijava_state();
86+
const Method *m = (const Method*)(istate->method);
87+
if (!Method::is_valid_method(m)) return false;
88+
if (!Metaspace::contains(m->constMethod())) return false;
89+
90+
uint64_t reg_bcp = uc->uc_mcontext.jmp_context.gpr[14/*R14_bcp*/];
91+
uint64_t istate_bcp = istate->bcp;
92+
uint64_t code_start = (uint64_t)(m->code_base());
93+
uint64_t code_end = (uint64_t)(m->code_base() + m->code_size());
94+
if (istate_bcp >= code_start && istate_bcp < code_end) {
95+
// we have a valid bcp, don't touch it, do nothing
96+
} else if (reg_bcp >= code_start && reg_bcp < code_end) {
97+
istate->bcp = reg_bcp;
98+
} else {
99+
return false;
100+
}
101+
}
102+
if (!ret_frame.safe_for_sender(this)) {
103+
// nothing else to try if the frame isn't good
104+
return false;
105+
}
106+
*fr_addr = ret_frame;
107+
return true;
108+
}
109+
// nothing else to try
110+
return false;
48111
}
49112

50-
// Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Aix/PPC.
113+
// Forte Analyzer AsyncGetCallTrace profiling support.
51114
bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) {
52-
Unimplemented();
53-
return false;
115+
return pd_get_top_frame_for_profiling(fr_addr, ucontext, isInJava);
54116
}
55117

56118
void JavaThread::cache_global_variables() { }

src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext,
4949
// If we have a last_Java_frame, then we should use it even if
5050
// isInJava == true. It should be more reliable than ucontext info.
5151
if (has_last_Java_frame() && frame_anchor()->walkable()) {
52-
*fr_addr = pd_last_frame();
52+
frame last_frame = pd_last_frame();
53+
if (last_frame.pc() == NULL) return false;
54+
*fr_addr = last_frame;
5355
return true;
5456
}
5557

0 commit comments

Comments
 (0)