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
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
4348bool 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.
51114bool 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
56118void JavaThread::cache_global_variables () { }
0 commit comments