--- old/src/share/vm/prims/forte.cpp 2015-05-29 13:57:38.401083197 +0200 +++ new/src/share/vm/prims/forte.cpp 2015-05-29 13:57:38.337083200 +0200 @@ -172,8 +172,27 @@ // Now do we have a useful PcDesc? if (pc_desc == NULL || pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) { - // No debug information available for this pc - // vframeStream would explode if we try and walk the frames. + // No debug information is available for this PC. + // + // vframeStreamCommon::fill_from_frame() will decode the frame depending + // on the state of the thread. + // + // Case #1: If the thread is in Java (state == _thread_in_Java), then + // the vframeStreamCommon object will be filled as if the frame were a native + // compiled frame. Therefore, no debug information is needed. + // + // Case #2: If the thread is in any other state, then two steps will be performed: + // - if asserts are enabled, found_bad_method_frame() will be called and + // the assert in found_bad_method_frame() will be triggered; + // - if asserts are disabled, the vframeStreamCommon object will be filled + // as if it were a native compiled frame. + // + // Case (2) is similar to the way interpreter frames are processed in + // vframeStreamCommon::fill_from_interpreter_frame in case no valid BCI + // was found for an interpreted frame. If asserts are enabled, the assert + // in found_bad_method_frame() will be triggered. If asserts are disabled, + // the vframeStreamCommon object will be filled afterwards as if the + // interpreter were at the point of entering into the method. return false; } @@ -230,9 +249,10 @@ // 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; + *method_p = method; // If the Method* found is invalid, it is + // ignored by forte_fill_call_trace_given_top(). + // So set method_p only if the Method is valid. intptr_t bcx = fr->interpreter_frame_bcx(); @@ -247,18 +267,33 @@ } -// Determine if 'fr' can be used to find an initial Java frame. -// Return false if it can not find a fully decipherable Java frame -// (in other words a frame that isn't safe to use in a vframe stream). -// Obviously if it can't even find a Java frame false will also be returned. +// Determine if a Java frame can be found starting with the frame 'fr'. +// +// Check the return value of find_initial_Java_frame and the value of +// 'method_p' to decide on how use the results returned by this method. +// +// If 'method_p' is not NULL, an initial Java frame has been found and +// the stack can be walked starting from that initial frame. In this case, +// 'method_p' points to the Method that the initial frame belongs to and +// the initial Java frame is returned in initial_frame_p. +// +// find_initial_Java_frame() returns true if a Method has been found (i.e., +// 'method_p' is not NULL) and the initial frame that belongs to that Method +// is decipherable. // -// If we find a Java frame decipherable or not then by definition we have -// identified a method and that will be returned to the caller via method_p. -// If we can determine a bci that is returned also. (Hmm is it possible -// to return a method and bci and still return false? ) +// A frame is considered to be decipherable: // -// The initial Java frame we find (if any) is return via initial_frame_p. +// - if the frame is a compiled frame and a PCDesc is available; // +// - if the frame is an interpreter frame that is valid or the thread is +// state (_thread_in_native || state == _thread_in_vm || state == _thread_blocked). +// +// Note that find_initial_Java_frame() can return false even if an initial +// Java method was found (e.g., there is no PCDesc available for the method). +// +// If 'method_p' is NULL, it was not possible to find a Java frame when +// walking the stack starting from 'fr'. In this case find_initial_Java_frame +// returns false. static bool find_initial_Java_frame(JavaThread* thread, frame* fr, @@ -278,8 +313,6 @@ // recognizable to us. This should only happen if we are in a JRT_LEAF // or something called by a JRT_LEAF method. - - frame candidate = *fr; // If the starting frame we were given has no codeBlob associated with @@ -334,9 +367,11 @@ nmethod* nm = (nmethod*) candidate.cb(); *method_p = nm->method(); - // If the frame isn't fully decipherable then the default - // value for the bci is a signal that we don't have a bci. - // If we have a decipherable frame this bci value will + // If the frame is not decipherable, then the value of -1 + // for the BCI is used to signal that no BCI is available. + // Furthermore, the method returns false in this case. + // + // If a decipherable frame is available, the BCI value will // not be used. *bci_p = -1; @@ -347,9 +382,9 @@ if (nm->is_native_method()) return true; - // If it isn't decipherable then we have found a pc that doesn't - // have a PCDesc that can get us a bci however we did find - // a method + // If the frame is not decipherable, then a PC was found + // that does not have a PCDesc from which a BCI can be obtained. + // Nevertheless, a Method was found. if (!is_decipherable_compiled_frame(thread, &candidate, nm)) { return false; @@ -358,7 +393,7 @@ // is_decipherable_compiled_frame may modify candidate's pc *initial_frame_p = candidate; - assert(nm->pc_desc_at(candidate.pc()) != NULL, "if it's decipherable then pc must be valid"); + assert(nm->pc_desc_at(candidate.pc()) != NULL, "debug information must be available if the frame is decipherable"); return true; } @@ -388,17 +423,17 @@ frame initial_Java_frame; Method* method; - int bci; + int bci = -1; // assume BCI is not available for method + // update with correct information if available 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) + // Walk the stack starting from 'top_frame' and search for an initial Java frame. + find_initial_Java_frame(thd, &top_frame, &initial_Java_frame, &method, &bci); + // Check if a Java Method has been found. if (method == NULL) return; if (!method->is_valid_method()) { @@ -406,29 +441,6 @@ 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++) {