From aaf11effb2d3125072813a0c4ef15098ea556d7f Mon Sep 17 00:00:00 2001 From: TheRealMDoerr Date: Tue, 27 Sep 2022 11:16:27 +0200 Subject: [PATCH] Backport 14c6ac457d319a2e7f9cc9e7355c81c421a065dd --- src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp | 82 ++++++++++++++++--- .../os_cpu/linux_ppc/thread_linux_ppc.cpp | 4 +- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp index f8953c00554..17136141311 100644 --- a/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp @@ -1,6 +1,7 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 SAP SE. All rights reserved. + * Copyright (c) 2022, IBM Corp. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +25,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspace.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.hpp" @@ -34,23 +36,83 @@ frame JavaThread::pd_last_frame() { address pc = _anchor.last_Java_pc(); // Last_Java_pc ist not set, if we come here from compiled code. - if (pc == NULL) - pc = (address) *(sp + 2); + // Assume spill slot for link register contains a suitable pc. + // Should have been filled by method entry code. + if (pc == NULL) { + pc = (address) *(sp + 2); + } return frame(sp, pc); } bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) { - ucontext_t* uc = (ucontext_t*) ucontext; - *fr_addr = frame((intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/], - (address)uc->uc_mcontext.jmp_context.iar); - return true; + + // If we have a last_Java_frame, then we should use it even if + // isInJava == true. It should be more reliable than ucontext info. + if (has_last_Java_frame() && frame_anchor()->walkable()) { + frame last_frame = pd_last_frame(); + if (last_frame.pc() == nullptr) return false; + *fr_addr = last_frame; + return true; + } + + // At this point, we don't have a last_Java_frame, so + // we try to glean some information out of the ucontext + // if we were running Java code when SIGPROF came in. + if (isInJava) { + ucontext_t* uc = (ucontext_t*) ucontext; + address pc = (address)uc->uc_mcontext.jmp_context.iar; + + if (pc == NULL) { + // ucontext wasn't useful + return false; + } + + frame ret_frame((intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/], pc); + + if (ret_frame.fp() == NULL) { + // The found frame does not have a valid frame pointer. + // Bail out because this will create big trouble later on, either + // - when using istate, calculated as (NULL - ijava_state_size) or + // - when using fp() directly in safe_for_sender() + // + // There is no conclusive description (yet) how this could happen, but it does. + // For more details on what was observed, see thread_linux_s390.cpp + return false; + } + + if (ret_frame.is_interpreted_frame()) { + frame::ijava_state *istate = ret_frame.get_ijava_state(); + const Method *m = (const Method*)(istate->method); + if (!Method::is_valid_method(m)) return false; + if (!Metaspace::contains(m->constMethod())) return false; + + uint64_t reg_bcp = uc->uc_mcontext.jmp_context.gpr[14/*R14_bcp*/]; + uint64_t istate_bcp = istate->bcp; + uint64_t code_start = (uint64_t)(m->code_base()); + uint64_t code_end = (uint64_t)(m->code_base() + m->code_size()); + if (istate_bcp >= code_start && istate_bcp < code_end) { + // we have a valid bcp, don't touch it, do nothing + } else if (reg_bcp >= code_start && reg_bcp < code_end) { + istate->bcp = reg_bcp; + } else { + return false; + } + } + if (!ret_frame.safe_for_sender(this)) { + // nothing else to try if the frame isn't good + return false; + } + *fr_addr = ret_frame; + return true; + } + // nothing else to try + return false; } -// Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Aix/PPC. +// Forte Analyzer AsyncGetCallTrace profiling support. bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) { - Unimplemented(); - return false; + return pd_get_top_frame_for_profiling(fr_addr, ucontext, isInJava); } void JavaThread::cache_global_variables() { } diff --git a/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp index d7546a79048..fb229b505c1 100644 --- a/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp @@ -49,7 +49,9 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than ucontext info. if (has_last_Java_frame() && frame_anchor()->walkable()) { - *fr_addr = pd_last_frame(); + frame last_frame = pd_last_frame(); + if (last_frame.pc() == nullptr) return false; + *fr_addr = last_frame; return true; }