8274903: Zero: Support AsyncGetCallTrace

Reviewed-by: sspitsyn, aph
This commit is contained in:
Aleksey Shipilev 2021-12-08 17:52:03 +00:00
parent 83454530ea
commit 92aa75b721
4 changed files with 143 additions and 18 deletions

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
* Copyright (c) 2007, 2021, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -116,13 +116,67 @@ void frame::patch_pc(Thread* thread, address pc) {
}
bool frame::safe_for_sender(JavaThread *thread) {
ShouldNotCallThis();
return false;
address sp = (address)_sp;
// consider stack guards when trying to determine "safe" stack pointers
// sp must be within the usable part of the stack (not in guards)
if (!thread->is_in_usable_stack(sp)) {
return false;
}
// an fp must be within the stack and above (but not equal) sp
if (!thread->is_in_stack_range_excl((address)fp(), sp)) {
return false;
}
// All good.
return true;
}
bool frame::is_interpreted_frame_valid(JavaThread *thread) const {
ShouldNotCallThis();
return false;
assert(is_interpreted_frame(), "Not an interpreted frame");
// These are reasonable sanity checks
if (fp() == 0 || (intptr_t(fp()) & (wordSize-1)) != 0) {
return false;
}
if (sp() == 0 || (intptr_t(sp()) & (wordSize-1)) != 0) {
return false;
}
// These are hacks to keep us out of trouble.
// The problem with these is that they mask other problems
if (fp() <= sp()) { // this attempts to deal with unsigned comparison above
return false;
}
// do some validation of frame elements
// first the method
Method* m = *interpreter_frame_method_addr();
// validate the method we'd find in this potential sender
if (!Method::is_valid_method(m)) {
return false;
}
// validate bci/bcp
address bcp = interpreter_frame_bcp();
if (m->validate_bci_from_bcp(bcp) < 0) {
return false;
}
// validate ConstantPoolCache*
ConstantPoolCache* cp = *interpreter_frame_cache_addr();
if (MetaspaceObj::is_valid(cp) == false) {
return false;
}
// validate locals
address locals = (address) *interpreter_frame_locals_addr();
if (!thread->is_in_stack_range_incl(locals, (address)fp())) {
return false;
}
return true;
}
BasicType frame::interpreter_frame_result(oop* oop_result,

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright 2009, 2010 Red Hat, Inc.
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2021, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,3 +35,40 @@ frame JavaThread::pd_last_frame() {
void JavaThread::cache_global_variables() {
// nothing to do
}
bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr,
void* ucontext,
bool isInJava) {
if (has_last_Java_frame()) {
*fr_addr = pd_last_frame();
return true;
}
if (isInJava) {
// We know we are in Java, but there is no frame?
// Try to find the top-most Java frame on Zero stack then.
intptr_t* sp = zero_stack()->sp();
ZeroFrame* zf = top_zero_frame();
while (zf != NULL) {
if (zf->is_interpreter_frame()) {
interpreterState istate = zf->as_interpreter_frame()->interpreter_state();
if (istate->self_link() == istate) {
// Valid interpreter state found, this is our frame.
*fr_addr = frame(zf, sp);
return true;
}
}
sp = ((intptr_t *) zf) + 1;
zf = zf->next();
}
}
// No dice.
return false;
}
bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr,
void* ucontext,
bool isInJava) {
return pd_get_top_frame_for_signal_handler(fr_addr, ucontext, isInJava);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2021, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -96,16 +96,10 @@
public:
bool pd_get_top_frame_for_signal_handler(frame* fr_addr,
void* ucontext,
bool isInJava) {
ShouldNotCallThis();
return false; // silence compile warning
}
bool isInJava);
bool pd_get_top_frame_for_profiling(frame* fr_addr,
void* ucontext,
bool isInJava) {
ShouldNotCallThis();
return false; // silence compile warning
}
bool isInJava);
#endif // OS_CPU_LINUX_ZERO_THREAD_LINUX_ZERO_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -314,6 +314,46 @@ static bool find_initial_Java_frame(JavaThread* thread,
frame candidate = *fr;
#ifdef ZERO
// Zero has no frames with code blobs, so the generic code fails.
// Instead, try to do Zero-specific search for Java frame.
{
RegisterMap map(thread, false, false);
while (true) {
// Cannot walk this frame? Cannot do anything anymore.
if (!candidate.safe_for_sender(thread)) {
return false;
}
if (candidate.is_entry_frame()) {
// jcw is NULL if the java call wrapper could not be found
JavaCallWrapper* jcw = candidate.entry_frame_call_wrapper_if_safe(thread);
// If initial frame is frame from StubGenerator and there is no
// previous anchor, there are no java frames associated with a method
if (jcw == NULL || jcw->is_first_frame()) {
return false;
}
}
// If we find a decipherable interpreted frame, this is our initial frame.
if (candidate.is_interpreted_frame()) {
if (is_decipherable_interpreted_frame(thread, &candidate, method_p, bci_p)) {
*initial_frame_p = candidate;
return true;
}
}
// Walk some more.
candidate = candidate.sender(&map);
}
// No dice, report no initial frames.
return false;
}
#endif
// If the starting frame we were given has no codeBlob associated with
// it see if we can find such a frame because only frames with codeBlobs
// are possible Java frames.