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)); } } }
GrowableArray<MonitorInfo*>* javaVFrame::locked_monitors() { assert(SafepointSynchronize::is_at_safepoint() || JavaThread::current() == thread(), "must be at safepoint or it's a java frame of the current thread"); GrowableArray<MonitorInfo*>* mons = monitors(); GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(mons->length()); if (mons->is_empty()) return result; bool found_first_monitor = false; ObjectMonitor *pending_monitor = thread()->current_pending_monitor(); ObjectMonitor *waiting_monitor = thread()->current_waiting_monitor(); oop pending_obj = (pending_monitor != NULL ? (oop) pending_monitor->object() : (oop) NULL); oop waiting_obj = (waiting_monitor != NULL ? (oop) waiting_monitor->object() : (oop) NULL); for (int index = (mons->length()-1); index >= 0; index--) { MonitorInfo* monitor = mons->at(index); if (monitor->eliminated() && is_compiled_frame()) continue; // skip eliminated monitor oop obj = monitor->owner(); if (obj == NULL) continue; // skip unowned monitor // // Skip the monitor that the thread is blocked to enter or waiting on // if (!found_first_monitor && (obj == pending_obj || obj == waiting_obj)) { continue; } found_first_monitor = true; result->append(monitor); } return result; }
void javaVFrame::print() { ResourceMark rm; vframe::print(); tty->print("\t"); method()->print_value(); tty->cr(); tty->print_cr("\tbci: %d", bci()); print_stack_values("locals", locals()); print_stack_values("expressions", expressions()); GrowableArray<MonitorInfo*>* list = monitors(); if (list->is_empty()) return; tty->print_cr("\tmonitor list:"); for (int index = (list->length()-1); index >= 0; index--) { MonitorInfo* monitor = list->at(index); tty->print("\t obj\t"); if (monitor->owner_is_scalar_replaced()) { Klass* k = java_lang_Class::as_Klass(monitor->owner_klass()); tty->print("( is scalar replaced %s)", k->external_name()); } else if (monitor->owner() == NULL) { tty->print("( null )"); } else { monitor->owner()->print_value(); tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner()); } if (monitor->eliminated() && is_compiled_frame()) tty->print(" ( lock is eliminated )"); tty->cr(); tty->print("\t "); monitor->lock()->print_on(tty); tty->cr(); } }
bool javaVFrame::structural_compare(javaVFrame* other) { // Check static part if (method() != other->method()) return false; if (bci() != other->bci()) return false; // Check locals StackValueCollection *locs = locals(); StackValueCollection *other_locs = other->locals(); assert(locs->size() == other_locs->size(), "sanity check"); int i; for(i = 0; i < locs->size(); i++) { // it might happen the compiler reports a conflict and // the interpreter reports a bogus int. if ( is_compiled_frame() && locs->at(i)->type() == T_CONFLICT) continue; if (other->is_compiled_frame() && other_locs->at(i)->type() == T_CONFLICT) continue; if (!locs->at(i)->equal(other_locs->at(i))) return false; } // Check expressions StackValueCollection* exprs = expressions(); StackValueCollection* other_exprs = other->expressions(); assert(exprs->size() == other_exprs->size(), "sanity check"); for(i = 0; i < exprs->size(); i++) { if (!exprs->at(i)->equal(other_exprs->at(i))) return false; } return true; }
void frame::follow_roots() { if (is_interpreted_frame()) { if (has_interpreted_float_marker() && follow_roots_interpreted_float_frame()) return; // Follow the roots of the frame for (oop* p = sp(); p <= temp_addr(0); p++) { MarkSweep::follow_root(p); } MarkSweep::follow_root((oop*)hp_addr()); MarkSweep::follow_root(receiver_addr()); return; } if (is_compiled_frame()) { if (has_compiled_float_marker() && follow_roots_compiled_float_frame()) return; for (oop* p = sp(); p < (oop*)fp(); p++) MarkSweep::follow_root(p); return; } if (is_entry_frame()) { for (oop* p = sp(); p < (oop*)fp(); p++) MarkSweep::follow_root(p); return; } if (is_deoptimized_frame()) { // Expression stack oop* end = (oop*)fp() + frame_real_sender_sp_offset; for (oop* p = sp(); p < end; p++) MarkSweep::follow_root(p); MarkSweep::follow_root((oop*)frame_array_addr()); return; } }
void frame::adjust_unextended_sp() { // If we are returning to a compiled MethodHandle call site, the // saved_fp will in fact be a saved value of the unextended SP. The // simplest way to tell whether we are returning to such a call site // is as follows: if (is_compiled_frame() && false /*is_at_mh_callsite()*/) { // TODO PPC port // If the sender PC is a deoptimization point, get the original // PC. For MethodHandle call site the unextended_sp is stored in // saved_fp. _unextended_sp = _fp - _cb->frame_size(); #ifdef ASSERT nmethod *sender_nm = _cb->as_nmethod_or_null(); assert(sender_nm && *_sp == *_unextended_sp, "backlink changed"); intptr_t* sp = _unextended_sp; // check if stack can be walked from here for (int x = 0; x < 5; ++x) { // check up to a couple of backlinks intptr_t* prev_sp = *(intptr_t**)sp; if (prev_sp == 0) break; // end of stack assert(prev_sp>sp, "broken stack"); sp = prev_sp; } if (sender_nm->is_deopt_mh_entry(_pc)) { // checks for deoptimization address original_pc = sender_nm->get_original_pc(this); assert(sender_nm->insts_contains(original_pc), "original PC must be in nmethod"); assert(sender_nm->is_method_handle_return(original_pc), "must be"); } #endif } }
bool frame::should_be_deoptimized() const { if (!is_compiled_frame()) return false; nmethod* nm = code(); if (TraceApplyChange) { std->print("checking (%s) ", nm->is_marked_for_deoptimization() ? "true" : "false"); nm->print_value_on(std); std->cr(); } return nm->is_marked_for_deoptimization(); }
intptr_t* frame::real_fp() const { if (_cb != NULL) { // use the frame size if valid int size = _cb->frame_size(); if (size > 0) { return unextended_sp() + size; } } // else rely on fp() assert(! is_compiled_frame(), "unknown compiled frame size"); return fp(); }
void frame::print() const { std->print("[%s frame: fp = %#lx, sp = %#lx, pc = %#lx", print_name(), fp(), sp(), pc()); if (is_compiled_frame()) { std->print(", nm = %#x", findNMethod(pc())); } else if (is_interpreted_frame()) { std->print(", hp = %#x, method = %#x", hp(), method()); } std->print_cr("]"); if (PrintLongFrames) { for (oop* p = sp(); p < (oop*)fp(); p++) std->print_cr(" - 0x%lx: 0x%lx", p, *p); } }
void frame::oop_iterate(OopClosure* blk) { if (is_interpreted_frame()) { if (has_interpreted_float_marker() && oop_iterate_interpreted_float_frame(blk)) return; // lprintf("Frame: fp = %#lx, sp = %#lx]\n", fp(), sp()); for (oop* p = sp(); p <= temp_addr(0); p++) { // lprintf("\t[%#lx]: ", p); // (*p)->short_print(); // lprintf("\n"); blk->do_oop(p); } // lprintf("\t{%#lx}: ", receiver_addr()); // (*receiver_addr())->short_print(); // lprintf("\n"); blk->do_oop(receiver_addr()); return; } if (is_compiled_frame()) { if (has_compiled_float_marker() && oop_iterate_compiled_float_frame(blk)) return; // All oops are [sp..fp[ for (oop* p = sp(); p < (oop*)fp(); p++) { blk->do_oop(p); } return; } if (is_entry_frame()) { // All oops are [sp..fp[ for (oop* p = sp(); p < (oop*)fp(); p++) { blk->do_oop(p); } return; } if (is_deoptimized_frame()) { // Expression stack oop* end = (oop*)fp() + frame_real_sender_sp_offset; // All oops are [sp..end[ for (oop* p = sp(); p < end; p++) { blk->do_oop(p); } blk->do_oop((oop*)frame_array_addr()); return; } }
IC_Iterator* frame::current_ic_iterator() const { if (is_interpreted_frame()) { InterpretedIC* ic = current_interpretedIC(); if (ic && !Bytecodes::is_send_code(ic->send_code())) return NULL; return ic ? new InterpretedIC_Iterator(ic) : NULL; } if (is_compiled_frame()) { CompiledIC* ic = current_compiledIC(); return ic->inlineCache() ? new CompiledIC_Iterator(ic) : NULL; // a perform, not a send } // entry or deoptimized frame return NULL; }
nmethod* frame::code() const { assert(is_compiled_frame(), "no code"); return findNMethod(pc()); }
CompiledIC* frame::current_compiledIC() const { return is_compiled_frame() ? CompiledIC_from_return_addr(pc()) // may fail if current frame isn't at a send -- caller must know : NULL; }
char* frame::print_name() const { if (is_interpreted_frame()) return "interpreted"; if (is_compiled_frame()) return "compiled"; if (is_deoptimized_frame()) return "deoptimized"; return "C"; }
void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { ResourceMark rm; // If this is the first frame, and java.lang.Object.wait(...) then print out the receiver. if (frame_count == 0) { if (method()->name() == vmSymbols::wait_name() && method()->method_holder()->name() == vmSymbols::java_lang_Object()) { StackValueCollection* locs = locals(); if (!locs->is_empty()) { StackValue* sv = locs->at(0); if (sv->type() == T_OBJECT) { Handle o = locs->at(0)->get_obj(); print_locked_object_class_name(st, o, "waiting on"); } } } else if (thread()->current_park_blocker() != NULL) { oop obj = thread()->current_park_blocker(); Klass* k = obj->klass(); st->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", "parking to wait for ", (address)obj, k->external_name()); } } // Print out all monitors that we have locked or are trying to lock GrowableArray<MonitorInfo*>* mons = monitors(); if (!mons->is_empty()) { bool found_first_monitor = false; for (int index = (mons->length()-1); index >= 0; index--) { MonitorInfo* monitor = mons->at(index); if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code if (monitor->owner_is_scalar_replaced()) { Klass* k = java_lang_Class::as_Klass(monitor->owner_klass()); st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name()); } else { oop obj = monitor->owner(); if (obj != NULL) { print_locked_object_class_name(st, obj, "eliminated"); } } continue; } if (monitor->owner() != NULL) { // First, assume we have the monitor locked. If we haven't found an // owned monitor before and this is the first frame, then we need to // see if we have completed the lock or we are blocked trying to // acquire it - we can only be blocked if the monitor is inflated const char *lock_state = "locked"; // assume we have the monitor locked if (!found_first_monitor && frame_count == 0) { markOop mark = monitor->owner()->mark(); if (mark->has_monitor() && mark->monitor() == thread()->current_pending_monitor()) { lock_state = "waiting to lock"; } } found_first_monitor = true; print_locked_object_class_name(st, monitor->owner(), lock_state); } } } }
void frame::print_for_deoptimization(outputStream* st) { ResourceMark rm; st->print(" - "); if (is_interpreted_frame()) { st->print("I "); interpretedVFrame* vf = (interpretedVFrame*) vframe::new_vframe(this); vf->method()->print_value_on(st); if (ActivationShowBCI) { st->print(" bci=%d ", vf->bci()); } std->print_cr(" @ 0x%lx", fp()); print_context_chain(vf->interpreter_context(), st); if (ActivationShowExpressionStack) { GrowableArray<oop>* stack = vf->expression_stack(); for (int index = 0; index < stack->length(); index++) { st->print(" %3d: ", index); stack->at(index)->print_value_on(st); st->cr(); } } return; } if (is_compiled_frame()) { st->print("C "); compiledVFrame* vf = (compiledVFrame*) vframe::new_vframe(this); assert(vf->is_compiled_frame(), "should be compiled vframe"); vf->code()->print_value_on(st); std->print_cr(" @ 0x%lx", fp()); while (true) { st->print(" "); vf->method()->print_value_on(st); std->print_cr(" @ %d", vf->scope()->offset()); print_context_chain(vf->compiled_context(), st); if (vf->is_top()) break; vf = (compiledVFrame*) vf->sender(); assert(vf->is_compiled_frame(), "should be compiled vframe"); } return; } if (is_deoptimized_frame()) { st->print("D "); frame_array()->print_value(); std->print_cr(" @ 0x%lx", fp()); deoptimizedVFrame* vf = (deoptimizedVFrame*) vframe::new_vframe(this); assert(vf->is_deoptimized_frame(), "should be deoptimized vframe"); while (true) { st->print(" "); vf->method()->print_value_on(st); std->cr(); print_context_chain(vf->deoptimized_context(), st); if (vf->is_top()) break; vf = (deoptimizedVFrame*) vf->sender(); assert(vf->is_deoptimized_frame(), "should be deoptimized vframe"); } return; } st->print("E foreign frame @ 0x%lx", fp()); }
inline bool frame::is_known_frame() const { return is_interpreted_frame() || is_native_frame() || is_compiled_frame(); }
inline bool frame::is_java_frame() const { return is_interpreted_frame() || is_compiled_frame(); }
bool is_delta_frame() const { return is_interpreted_frame() || is_compiled_frame(); }