void frame::describe_pd(FrameValues& values, int frame_no) { for (int w = 0; w < frame::register_save_words; w++) { values.describe(frame_no, sp() + w, err_msg("register save area word %d", w), 1); } if (is_ricochet_frame()) { MethodHandles::RicochetFrame::describe(this, values, frame_no); } else if (is_interpreted_frame()) { DESCRIBE_FP_OFFSET(interpreter_frame_d_scratch_fp); DESCRIBE_FP_OFFSET(interpreter_frame_l_scratch_fp); DESCRIBE_FP_OFFSET(interpreter_frame_padding); DESCRIBE_FP_OFFSET(interpreter_frame_oop_temp); // esp, according to Lesp (e.g. not depending on bci), if seems valid intptr_t* esp = *interpreter_frame_esp_addr(); if ((esp >= sp()) && (esp < fp())) { values.describe(-1, esp, "*Lesp"); } } if (!is_compiled_frame()) { if (frame::callee_aggregate_return_pointer_words != 0) { values.describe(frame_no, sp() + frame::callee_aggregate_return_pointer_sp_offset, "callee_aggregate_return_pointer_word"); } for (int w = 0; w < frame::callee_register_argument_save_area_words; w++) { values.describe(frame_no, sp() + frame::callee_register_argument_save_area_sp_offset + w, err_msg("callee_register_argument_save_area_words %d", w)); } } }
void frame::describe_pd(FrameValues& values, int frame_no) { if (is_interpreted_frame()) { DESCRIBE_FP_OFFSET(interpreter_frame_sender_sp); DESCRIBE_FP_OFFSET(interpreter_frame_last_sp); DESCRIBE_FP_OFFSET(interpreter_frame_method); DESCRIBE_FP_OFFSET(interpreter_frame_mdx); DESCRIBE_FP_OFFSET(interpreter_frame_cache); DESCRIBE_FP_OFFSET(interpreter_frame_locals); DESCRIBE_FP_OFFSET(interpreter_frame_bcx); DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp); } else if (is_entry_frame()) { // This could be more descriptive if we use the enum in // stubGenerator to map to real names but it's most important to // claim these frame slots so the error checking works. for (int i = 0; i < entry_frame_after_call_words; i++) { values.describe(frame_no, fp() - i, err_msg("call_stub word fp - %d", i)); } } }
void trace_method_handle_stub(const char* adaptername, oopDesc* mh, intptr_t* entry_sp, intptr_t* saved_regs) { bool has_mh = (strstr(adaptername, "/static") == NULL && strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH const char* mh_reg_name = has_mh ? "R23_method_handle" : "G23"; tty->print_cr("MH %s %s="INTPTR_FORMAT " sp=" INTPTR_FORMAT, adaptername, mh_reg_name, p2i(mh), p2i(entry_sp)); if (Verbose) { tty->print_cr("Registers:"); const int abi_offset = frame::abi_reg_args_size / 8; for (int i = R3->encoding(); i <= R12->encoding(); i++) { Register r = as_Register(i); int count = i - R3->encoding(); // The registers are stored in reverse order on the stack (by save_volatile_gprs(R1_SP, abi_reg_args_size)). tty->print("%3s=" PTR_FORMAT, r->name(), saved_regs[abi_offset + count]); if ((count + 1) % 4 == 0) { tty->cr(); } else { tty->print(", "); } } tty->cr(); { // dumping last frame with frame::describe JavaThread* p = JavaThread::active(); ResourceMark rm; PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here FrameValues values; // Note: We want to allow trace_method_handle from any call site. // While trace_method_handle creates a frame, it may be entered // without a PC on the stack top (e.g. not just after a call). // Walking that frame could lead to failures due to that invalid PC. // => carefully detect that frame when doing the stack walking // Current C frame frame cur_frame = os::current_frame(); // Robust search of trace_calling_frame (independant of inlining). // Assumes saved_regs comes from a pusha in the trace_calling_frame. assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?"); frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame); while (trace_calling_frame.fp() < saved_regs) { trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame); } // Safely create a frame and call frame::describe. intptr_t *dump_sp = trace_calling_frame.sender_sp(); frame dump_frame = frame(dump_sp); dump_frame.describe(values, 1); values.describe(-1, saved_regs, "raw top of stack"); tty->print_cr("Stack layout:"); values.print(p); } if (has_mh && mh->is_oop()) { mh->print(); if (java_lang_invoke_MethodHandle::is_instance(mh)) { if (java_lang_invoke_MethodHandle::form_offset_in_bytes() != 0) java_lang_invoke_MethodHandle::form(mh)->print(); } } } }
void trace_method_handle_stub(const char* adaptername, oop mh, intptr_t* saved_regs, intptr_t* entry_sp) { // called as a leaf from native code: do not block the JVM! bool has_mh = (strstr(adaptername, "/static") == NULL && strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH const char* mh_reg_name = has_mh ? "rcx_mh" : "rcx"; tty->print_cr("MH %s %s="PTR_FORMAT" sp="PTR_FORMAT, adaptername, mh_reg_name, mh, entry_sp); if (Verbose) { tty->print_cr("Registers:"); const int saved_regs_count = RegisterImpl::number_of_registers; for (int i = 0; i < saved_regs_count; i++) { Register r = as_Register(i); // The registers are stored in reverse order on the stack (by pusha). tty->print("%3s=" PTR_FORMAT, r->name(), saved_regs[((saved_regs_count - 1) - i)]); if ((i + 1) % 4 == 0) { tty->cr(); } else { tty->print(", "); } } tty->cr(); { // dumping last frame with frame::describe JavaThread* p = JavaThread::active(); ResourceMark rm; PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here FrameValues values; // Note: We want to allow trace_method_handle from any call site. // While trace_method_handle creates a frame, it may be entered // without a PC on the stack top (e.g. not just after a call). // Walking that frame could lead to failures due to that invalid PC. // => carefully detect that frame when doing the stack walking // Current C frame frame cur_frame = os::current_frame(); // Robust search of trace_calling_frame (independant of inlining). // Assumes saved_regs comes from a pusha in the trace_calling_frame. assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?"); frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame); while (trace_calling_frame.fp() < saved_regs) { trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame); } // safely create a frame and call frame::describe intptr_t *dump_sp = trace_calling_frame.sender_sp(); intptr_t *dump_fp = trace_calling_frame.link(); bool walkable = has_mh; // whether the traced frame shoud be walkable if (walkable) { // The previous definition of walkable may have to be refined // if new call sites cause the next frame constructor to start // failing. Alternatively, frame constructors could be // modified to support the current or future non walkable // frames (but this is more intrusive and is not considered as // part of this RFE, which will instead use a simpler output). frame dump_frame = frame(dump_sp, dump_fp); dump_frame.describe(values, 1); } else { // Stack may not be walkable (invalid PC above FP): // Add descriptions without building a Java frame to avoid issues values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>"); values.describe(-1, dump_sp, "sp for #1"); } values.describe(-1, entry_sp, "raw top of stack"); tty->print_cr("Stack layout:"); values.print(p); } if (has_mh && mh->is_oop()) { mh->print(); if (java_lang_invoke_MethodHandle::is_instance(mh)) { if (java_lang_invoke_MethodHandle::form_offset_in_bytes() != 0) java_lang_invoke_MethodHandle::form(mh)->print(); } } } }
void frame::describe_pd(FrameValues& values, int frame_no) { if (is_interpreted_frame()) { #ifdef CC_INTERP interpreterState istate = get_interpreterState(); values.describe(frame_no, (intptr_t*)istate, "istate"); values.describe(frame_no, (intptr_t*)&(istate->_thread), " thread"); values.describe(frame_no, (intptr_t*)&(istate->_bcp), " bcp"); values.describe(frame_no, (intptr_t*)&(istate->_locals), " locals"); values.describe(frame_no, (intptr_t*)&(istate->_constants), " constants"); values.describe(frame_no, (intptr_t*)&(istate->_method), err_msg(" method = %s", istate->_method->name_and_sig_as_C_string())); values.describe(frame_no, (intptr_t*)&(istate->_mdx), " mdx"); values.describe(frame_no, (intptr_t*)&(istate->_stack), " stack"); values.describe(frame_no, (intptr_t*)&(istate->_msg), err_msg(" msg = %s", BytecodeInterpreter::C_msg(istate->_msg))); values.describe(frame_no, (intptr_t*)&(istate->_result), " result"); values.describe(frame_no, (intptr_t*)&(istate->_prev_link), " prev_link"); values.describe(frame_no, (intptr_t*)&(istate->_oop_temp), " oop_temp"); values.describe(frame_no, (intptr_t*)&(istate->_stack_base), " stack_base"); values.describe(frame_no, (intptr_t*)&(istate->_stack_limit), " stack_limit"); values.describe(frame_no, (intptr_t*)&(istate->_monitor_base), " monitor_base"); values.describe(frame_no, (intptr_t*)&(istate->_frame_bottom), " frame_bottom"); values.describe(frame_no, (intptr_t*)&(istate->_last_Java_pc), " last_Java_pc"); values.describe(frame_no, (intptr_t*)&(istate->_last_Java_fp), " last_Java_fp"); values.describe(frame_no, (intptr_t*)&(istate->_last_Java_sp), " last_Java_sp"); values.describe(frame_no, (intptr_t*)&(istate->_self_link), " self_link"); values.describe(frame_no, (intptr_t*)&(istate->_native_fresult), " native_fresult"); values.describe(frame_no, (intptr_t*)&(istate->_native_lresult), " native_lresult"); #else #define DESCRIBE_ADDRESS(name) \ values.describe(frame_no, (intptr_t*)&(get_ijava_state()->name), #name); DESCRIBE_ADDRESS(method); DESCRIBE_ADDRESS(locals); DESCRIBE_ADDRESS(monitors); DESCRIBE_ADDRESS(cpoolCache); DESCRIBE_ADDRESS(bcp); DESCRIBE_ADDRESS(esp); DESCRIBE_ADDRESS(mdx); DESCRIBE_ADDRESS(top_frame_sp); DESCRIBE_ADDRESS(sender_sp); DESCRIBE_ADDRESS(oop_tmp); DESCRIBE_ADDRESS(lresult); DESCRIBE_ADDRESS(fresult); #endif } }