Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8274903: Zero: Support AsyncGetCallTrace #885

Closed
wants to merge 1 commit into from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
64 changes: 59 additions & 5 deletions src/hotspot/cpu/zero/frame_zero.cpp
@@ -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
Expand Down Expand Up @@ -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,
Expand Down
41 changes: 39 additions & 2 deletions src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp
@@ -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
Expand Down Expand Up @@ -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);
}
14 changes: 4 additions & 10 deletions src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp
@@ -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
Expand Down Expand Up @@ -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
42 changes: 41 additions & 1 deletion src/hotspot/share/prims/forte.cpp
@@ -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
Expand Down Expand Up @@ -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.
Expand Down