Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 3 additions & 1 deletion ddprof-lib/src/main/cpp/profiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ void Profiler::addRuntimeStub(const void *address, int length,
_runtime_stubs.add(address, length, name, true);
_stubs_lock.unlock();

if (strcmp(name, "call_stub") == 0) {
if (name[0] == 'I' && strcmp(name, "Interpreter") == 0) {
CodeHeap::setInterpreterStart(address);
} else if (strcmp(name, "call_stub") == 0) {
_call_stub_begin = address;
_call_stub_end = (const char *)address + length;
}
Expand Down
94 changes: 47 additions & 47 deletions ddprof-lib/src/main/cpp/stackWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,53 @@ __attribute__((no_sanitize("address"))) int StackWalker::walkVM(void* ucontext,
anchor = NULL;
}

if (nm->isNMethod()) {
if (nm->isInterpreter()) {
if (vm_thread != NULL && vm_thread->inDeopt()) {
fillFrame(frames[depth++], BCI_ERROR, "break_deopt");
break;
}

bool is_plausible_interpreter_frame = StackWalkValidation::isPlausibleInterpreterFrame(fp, sp, bcp_offset);
if (is_plausible_interpreter_frame) {
VMMethod* method = ((VMMethod**)fp)[InterpreterFrame::method_offset];
jmethodID method_id = getMethodId(method);
if (method_id != NULL) {
Counters::increment(WALKVM_JAVA_FRAME_OK);
const char* bytecode_start = method->bytecode();
const char* bcp = ((const char**)fp)[bcp_offset];
int bci = bytecode_start == NULL || bcp < bytecode_start ? 0 : bcp - bytecode_start;
fillFrame(frames[depth++], FRAME_INTERPRETED, bci, method_id);

sp = ((uintptr_t*)fp)[InterpreterFrame::sender_sp_offset];
pc = stripPointer(((void**)fp)[FRAME_PC_SLOT]);
fp = *(uintptr_t*)fp;
continue;
}
}

if (depth == 0) {
VMMethod* method = (VMMethod*)frame.method();
jmethodID method_id = getMethodId(method);
if (method_id != NULL) {
Counters::increment(WALKVM_JAVA_FRAME_OK);
fillFrame(frames[depth++], FRAME_INTERPRETED, 0, method_id);

if (is_plausible_interpreter_frame) {
pc = stripPointer(((void**)fp)[FRAME_PC_SLOT]);
sp = frame.senderSP();
fp = *(uintptr_t*)fp;
} else {
pc = stripPointer(SafeAccess::load((void**)sp));
sp = frame.senderSP();
}
continue;
}
}

Counters::increment(WALKVM_BREAK_INTERPRETED);
fillFrame(frames[depth++], BCI_ERROR, "break_interpreted");
break;
} else if (nm->isNMethod()) {
// Check if deoptimization is in progress before walking compiled frames
if (vm_thread != NULL && vm_thread->inDeopt()) {
fillFrame(frames[depth++], BCI_ERROR, "break_deopt_compiled");
Expand Down Expand Up @@ -453,52 +499,6 @@ __attribute__((no_sanitize("address"))) int StackWalker::walkVM(void* ucontext,
Counters::increment(WALKVM_BREAK_COMPILED);
fillFrame(frames[depth++], BCI_ERROR, "break_compiled");
break;
} else if (nm->isInterpreter()) {
if (vm_thread != NULL && vm_thread->inDeopt()) {
fillFrame(frames[depth++], BCI_ERROR, "break_deopt");
break;
}

bool is_plausible_interpreter_frame = StackWalkValidation::isPlausibleInterpreterFrame(fp, sp, bcp_offset);
if (is_plausible_interpreter_frame) {
VMMethod* method = ((VMMethod**)fp)[InterpreterFrame::method_offset];
jmethodID method_id = getMethodId(method);
if (method_id != NULL) {
Counters::increment(WALKVM_JAVA_FRAME_OK);
const char* bytecode_start = method->bytecode();
const char* bcp = ((const char**)fp)[bcp_offset];
int bci = bytecode_start == NULL || bcp < bytecode_start ? 0 : bcp - bytecode_start;
fillFrame(frames[depth++], FRAME_INTERPRETED, bci, method_id);

sp = ((uintptr_t*)fp)[InterpreterFrame::sender_sp_offset];
pc = stripPointer(((void**)fp)[FRAME_PC_SLOT]);
fp = *(uintptr_t*)fp;
continue;
}
}

if (depth == 0) {
VMMethod* method = (VMMethod*)frame.method();
jmethodID method_id = getMethodId(method);
if (method_id != NULL) {
Counters::increment(WALKVM_JAVA_FRAME_OK);
fillFrame(frames[depth++], FRAME_INTERPRETED, 0, method_id);

if (is_plausible_interpreter_frame) {
pc = stripPointer(((void**)fp)[FRAME_PC_SLOT]);
sp = frame.senderSP();
fp = *(uintptr_t*)fp;
} else {
pc = stripPointer(SafeAccess::load((void**)sp));
sp = frame.senderSP();
}
continue;
}
}

Counters::increment(WALKVM_BREAK_INTERPRETED);
fillFrame(frames[depth++], BCI_ERROR, "break_interpreted");
break;
} else if (nm->isEntryFrame(pc) && !features.mixed) {
VMJavaFrameAnchor* next_anchor = VMJavaFrameAnchor::fromEntryFrame(fp);
if (next_anchor == NULL) {
Expand Down
6 changes: 6 additions & 0 deletions ddprof-lib/src/main/cpp/vmStructs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include "vmStructs.h"
Expand Down Expand Up @@ -33,6 +34,8 @@ int VMStructs::_narrow_klass_shift = -1;
int VMStructs::_interpreter_frame_bcp_offset = 0;
unsigned char VMStructs::_unsigned5_base = 0;
const void* VMStructs::_call_stub_return = nullptr;
const void* VMStructs::_interpreter_start = nullptr;
VMNMethod* VMStructs::_interpreter_nm = nullptr;
const void* VMStructs::_interpreted_frame_valid_start = nullptr;
const void* VMStructs::_interpreted_frame_valid_end = nullptr;

Expand Down Expand Up @@ -437,6 +440,9 @@ void VMStructs::resolveOffsets() {
_heap_block_used_offset < 0) {
memset(_code_heap, 0, sizeof(_code_heap));
}
if (_interpreter_nm == NULL && _interpreter_start != NULL) {
_interpreter_nm = CodeHeap::findNMethod(_interpreter_start);
}
}

void VMStructs::initJvmFunctions() {
Expand Down
32 changes: 24 additions & 8 deletions ddprof-lib/src/main/cpp/vmStructs.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <initializer_list>
#include <jvmti.h>
#include <stdint.h>
#include <string.h>
#include <type_traits>
#include "codeCache.h"
#include "counters.h"
Expand All @@ -21,6 +20,7 @@

class GCHeapSummary;
class HeapUsage;
class VMNMethod;


// During stack walking in the profiler's signal handler, GC or class unloading
Expand Down Expand Up @@ -310,6 +310,8 @@ class VMStructs {
static int _interpreter_frame_bcp_offset;
static unsigned char _unsigned5_base;
static const void* _call_stub_return;
static const void* _interpreter_start;
static VMNMethod* _interpreter_nm;
static const void* _interpreted_frame_valid_start;
static const void* _interpreted_frame_valid_end;

Expand Down Expand Up @@ -829,6 +831,16 @@ DECLARE(VMMethod)
DECLARE_END

DECLARE(VMNMethod)
private:
// Inline string comparison to avoid indirect call to strncmp
template<size_t N>
static bool startsWith(const char* s, const char (&pattern)[N]) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make it an inline utility function.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved startsWith to a file-scope static inline utility function just before DECLARE(VMNMethod).

for (size_t i = 0; i < N - 1; i++) {
if (s[i] != pattern[i]) return false;
}
return true;
}

public:
int size() {
assert(_blob_size_offset >= 0);
Expand Down Expand Up @@ -902,24 +914,23 @@ DECLARE(VMNMethod)
return *(const char**) at(_nmethod_name_offset);
}

bool isNMethod() {
const char* n = name();
return n != NULL && (strcmp(n, "nmethod") == 0 || strcmp(n, "native nmethod") == 0);
bool isInterpreter() {
return this == _interpreter_nm;
}

bool isInterpreter() {
bool isNMethod() {
const char* n = name();
return n != NULL && strcmp(n, "Interpreter") == 0;
return n != NULL && (startsWith(n, "nmethod\0") || startsWith(n, "native nmethod\0"));
}

bool isStub() {
const char* n = name();
return n != NULL && strncmp(n, "StubRoutines", 12) == 0;
return n != NULL && startsWith(n, "StubRoutines");
}

bool isVTableStub() {
const char* n = name();
return n != NULL && strcmp(n, "vtable chunks") == 0;
return n != NULL && startsWith(n, "vtable chunks");
}

VMMethod* method() {
Expand Down Expand Up @@ -985,6 +996,11 @@ class CodeHeap : VMStructs {
high = _code_heap_high);
}

static void setInterpreterStart(const void* start) {
_interpreter_start = start;
_interpreter_nm = findNMethod(start);
}

static VMNMethod* findNMethod(const void* pc) {
if (contains(_code_heap[0], pc)) return findNMethod(_code_heap[0], pc);
if (contains(_code_heap[1], pc)) return findNMethod(_code_heap[1], pc);
Expand Down
Loading