Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 72 additions & 10 deletions src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -24,6 +25,7 @@
*/

#include "precompiled.hpp"
#include "memory/metaspace.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/thread.hpp"

Expand All @@ -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() == NULL) 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() { }
4 changes: 3 additions & 1 deletion src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() == NULL) return false;
*fr_addr = last_frame;
return true;
}

Expand Down