bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // QQQ #ifdef CC_INTERP #else 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; } if (fp() + interpreter_frame_initial_sp_offset < sp()) { 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 (!m->is_valid_method()) return false; // stack frames shouldn't be much larger than max_stack elements if (fp() - sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) { return false; } // validate bci/bcx intptr_t bcx = interpreter_frame_bcx(); if (m->validate_bci_from_bcx(bcx) < 0) { return false; } // validate ConstantPoolCache* ConstantPoolCache* cp = *interpreter_frame_cache_addr(); if (cp == NULL || !cp->is_metaspace_object()) return false; // validate locals address locals = (address) *interpreter_frame_locals_addr(); if (locals > thread->stack_base() || locals < (address) fp()) return false; // We'd have to be pretty unlucky to be mislead at this point #endif // CC_INTERP return true; }
static bool is_decipherable_interpreted_frame(JavaThread* thread, frame* fr, Method** method_p, int* bci_p) { assert(fr->is_interpreted_frame(), "just checking"); // top frame is an interpreted frame // check if it is walkable (i.e. valid Method* and valid bci) // Because we may be racing a gc thread the method and/or bci // of a valid interpreter frame may look bad causing us to // fail the is_interpreted_frame_valid test. If the thread // is in any of the following states we are assured that the // frame is in fact valid and we must have hit the race. JavaThreadState state = thread->thread_state(); bool known_valid = (state == _thread_in_native || state == _thread_in_vm || state == _thread_blocked ); if (known_valid || fr->is_interpreted_frame_valid(thread)) { // The frame code should completely validate the frame so that // references to Method* and bci are completely safe to access // If they aren't the frame code should be fixed not this // code. However since gc isn't locked out the values could be // stale. This is a race we can never completely win since we can't // lock out gc so do one last check after retrieving their values // from the frame for additional safety Method* method = fr->interpreter_frame_method(); // We've at least found a method. // NOTE: there is something to be said for the approach that // if we don't find a valid bci then the method is not likely // a valid method. Then again we may have caught an interpreter // frame in the middle of construction and the bci field is // not yet valid. *method_p = method; if (!method->is_valid_method()) return false; intptr_t bcx = fr->interpreter_frame_bcx(); int bci = method->validate_bci_from_bcx(bcx); // note: bci is set to -1 if not a valid bci *bci_p = bci; return true; } return false; }
static void forte_fill_call_trace_given_top(JavaThread* thd, ASGCT_CallTrace* trace, int depth, frame top_frame) { NoHandleMark nhm; frame initial_Java_frame; Method* method; int bci; int count; count = 0; assert(trace->frames != NULL, "trace->frames must be non-NULL"); bool fully_decipherable = find_initial_Java_frame(thd, &top_frame, &initial_Java_frame, &method, &bci); // The frame might not be walkable but still recovered a method // (e.g. an nmethod with no scope info for the pc) if (method == NULL) return; if (!method->is_valid_method()) { trace->num_frames = ticks_GC_active; // -2 return; } // We got a Java frame however it isn't fully decipherable // so it won't necessarily be safe to use it for the // initial frame in the vframe stream. if (!fully_decipherable) { // Take whatever method the top-frame decoder managed to scrape up. // We look further at the top frame only if non-safepoint // debugging information is available. count++; trace->num_frames = count; trace->frames[0].method_id = method->find_jmethod_id_or_null(); if (!method->is_native()) { trace->frames[0].lineno = bci; } else { trace->frames[0].lineno = -3; } if (!initial_Java_frame.safe_for_sender(thd)) return; RegisterMap map(thd, false); initial_Java_frame = initial_Java_frame.sender(&map); } vframeStreamForte st(thd, initial_Java_frame, false); for (; !st.at_end() && count < depth; st.forte_next(), count++) { bci = st.bci(); method = st.method(); if (!method->is_valid_method()) { // we throw away everything we've gathered in this sample since // none of it is safe trace->num_frames = ticks_GC_active; // -2 return; } trace->frames[count].method_id = method->find_jmethod_id_or_null(); if (!method->is_native()) { trace->frames[count].lineno = bci; } else { trace->frames[count].lineno = -3; } } trace->num_frames = count; return; }