Repository navigation
jcmd java_stack
ceragon edited this page Jun 1, 2022
·
3 revisions
javaVFrame* JavaThread::last_java_vframe(RegisterMap *reg_map) {
// 栈顶
frame f = last_frame();
// 下面的作用是从栈顶开始,找到一个java的栈帧,并转换为 javaVFrame
for (vframe* vf = vframe::new_vframe(&f, reg_map, this); vf; vf = vf->sender()) {
if (vf->is_java_frame()) return javaVFrame::cast(vf);
}
return NULL;
}class JavaThread: public Thread {
JavaFrameAnchor _anchor;
// 获取最后一帧
frame last_frame() {
_anchor.make_walkable(this);
return pd_last_frame();
}
};void JavaFrameAnchor::make_walkable(JavaThread* thread) {
if (walkable()) return;
capture_last_Java_pc();
}
void JavaFrameAnchor::capture_last_Java_pc() {
_last_Java_pc = (address)_last_Java_sp[-1];
}class JavaFrameAnchor {
intptr_t* volatile _last_Java_sp;
volatile address _last_Java_pc;
// x86 架构相关
// FP value associated with _last_Java_sp:
intptr_t* volatile _last_Java_fp;
bool walkable(void) {
return _last_Java_sp != NULL && _last_Java_pc != NULL;
}
};frame JavaThread::pd_last_frame() {
return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc());
}class frame {
intptr_t* _sp; // stack pointer (from Thread::last_Java_sp)
address _pc; // program counter (the next instruction after the call)
CodeBlob* _cb; // CodeBlob that "owns" pc
enum deopt_state {
not_deoptimized,
is_deoptimized,
unknown
};
deopt_state _deopt_state;
};
inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
init(sp, fp, pc);
}
inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
_sp = sp;
_unextended_sp = sp;
_fp = fp;
_pc = pc;
_cb = CodeCache::find_blob(pc);
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
// 说明这一帧对应的方法已经被 jit 优化过了
_pc = original_pc;
_deopt_state = is_deoptimized;
} else {
// 还处于解释执行阶段
_deopt_state = not_deoptimized;
}
}class vframe: public ResourceObj {
frame _fr;
};
vframe* vframe::sender() const {
RegisterMap temp_map = *register_map();
if (_fr.is_entry_frame() && _fr.is_first_frame()) return NULL;
frame s = _fr.real_sender(&temp_map);
if (s.is_first_frame()) return NULL;
return vframe::new_vframe(&s, &temp_map, thread());
}frame frame::real_sender(RegisterMap* map) const {
frame result = sender(map);
while (result.is_runtime_frame() || result.is_ignored_frame()) {
result = result.sender(map);
}
return result;
}
frame frame::sender(RegisterMap* map) const {
if (is_entry_frame()) return sender_for_entry_frame(map);
if (is_interpreted_frame()) return sender_for_interpreter_frame(map);
if (_cb != NULL) {
return sender_for_compiled_frame(map);
}
return frame(sender_sp(), link(), sender_pc());
}vframe* vframe::new_vframe(const frame* f, const RegisterMap* reg_map, JavaThread* thread) {
if (f->is_interpreted_frame()) {
// java 解释执行的栈帧
return new interpretedVFrame(f, reg_map, thread);
}
CodeBlob* cb = f->cb();
if (cb != NULL) {
// 代码块不为空
if (cb->is_compiled()) {
// 只要是被编译后的方法,或者执行过 AOT 的方法,都被视为编译后的代码
CompiledMethod* nm = (CompiledMethod*)cb;
// java 编译后的栈帧
return new compiledVFrame(f, reg_map, thread, nm);
}
if (f->is_runtime_frame()) {
RegisterMap temp_map = *reg_map;
frame s = f->sender(&temp_map);
// 非java栈帧
return new_vframe(&s, &temp_map, thread);
}
}
// 非 java栈帧
return new externalVFrame(f, reg_map, thread);
}
bool frame::is_interpreted_frame() const {
// 由于 pc 指向的是当前栈帧执行的下一条指令地址,
// 只要指令的地址范围在解释器产生的代码范围内,就说明是解释执行产生的栈帧
return Interpreter::contains(pc());
}Method* interpretedVFrame::method() const {
return fr().interpreter_frame_method();
}
Method* frame::interpreter_frame_method() const {
Method* m = *interpreter_frame_method_addr();
return m;
}
enum {
pc_return_offset = 0,
interpreter_frame_sender_sp_offset = -1,
interpreter_frame_last_sp_offset = interpreter_frame_sender_sp_offset - 1,
interpreter_frame_method_offset = interpreter_frame_last_sp_offset - 1,
};
inline Method** frame::interpreter_frame_method_addr() const {
return (Method**)addr_at(interpreter_frame_method_offset);
}
class frame {
intptr_t* _fp; // frame pointer
intptr_t* addr_at(int index) const { return &fp()[index]; }
intptr_t* fp() const { return _fp; }
};