| File: | jdk/src/hotspot/share/prims/stackwalk.cpp |
| Warning: | line 260, column 18 Value stored to 'ret' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* |
| 2 | * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 12 | * version 2 for more details (a copy is included in the LICENSE file that |
| 13 | * accompanied this code). |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License version |
| 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | * |
| 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| 20 | * or visit www.oracle.com if you need additional information or have any |
| 21 | * questions. |
| 22 | * |
| 23 | */ |
| 24 | |
| 25 | #include "precompiled.hpp" |
| 26 | #include "classfile/javaClasses.hpp" |
| 27 | #include "classfile/javaClasses.inline.hpp" |
| 28 | #include "classfile/vmClasses.hpp" |
| 29 | #include "classfile/vmSymbols.hpp" |
| 30 | #include "logging/log.hpp" |
| 31 | #include "logging/logStream.hpp" |
| 32 | #include "memory/oopFactory.hpp" |
| 33 | #include "memory/universe.hpp" |
| 34 | #include "oops/klass.inline.hpp" |
| 35 | #include "oops/oop.inline.hpp" |
| 36 | #include "oops/objArrayOop.inline.hpp" |
| 37 | #include "prims/stackwalk.hpp" |
| 38 | #include "runtime/globals.hpp" |
| 39 | #include "runtime/handles.inline.hpp" |
| 40 | #include "runtime/javaCalls.hpp" |
| 41 | #include "runtime/keepStackGCProcessed.hpp" |
| 42 | #include "runtime/stackWatermarkSet.hpp" |
| 43 | #include "runtime/thread.inline.hpp" |
| 44 | #include "runtime/vframe.inline.hpp" |
| 45 | #include "utilities/formatBuffer.hpp" |
| 46 | #include "utilities/globalDefinitions.hpp" |
| 47 | |
| 48 | // setup and cleanup actions |
| 49 | void BaseFrameStream::setup_magic_on_entry(objArrayHandle frames_array) { |
| 50 | frames_array->obj_at_put(magic_pos, _thread->threadObj()); |
| 51 | _anchor = address_value(); |
| 52 | assert(check_magic(frames_array), "invalid magic")do { if (!(check_magic(frames_array))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 52, "assert(" "check_magic(frames_array)" ") failed", "invalid magic" ); ::breakpoint(); } } while (0); |
| 53 | } |
| 54 | |
| 55 | bool BaseFrameStream::check_magic(objArrayHandle frames_array) { |
| 56 | oop m1 = frames_array->obj_at(magic_pos); |
| 57 | jlong m2 = _anchor; |
| 58 | if (m1 == _thread->threadObj() && m2 == address_value()) return true; |
| 59 | return false; |
| 60 | } |
| 61 | |
| 62 | bool BaseFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) { |
| 63 | bool ok = check_magic(frames_array); |
| 64 | frames_array->obj_at_put(magic_pos, NULL__null); |
| 65 | _anchor = 0L; |
| 66 | return ok; |
| 67 | } |
| 68 | |
| 69 | JavaFrameStream::JavaFrameStream(JavaThread* thread, int mode) |
| 70 | : BaseFrameStream(thread), _vfst(thread) { |
| 71 | _need_method_info = StackWalk::need_method_info(mode); |
| 72 | } |
| 73 | |
| 74 | void JavaFrameStream::next() { _vfst.next();} |
| 75 | |
| 76 | // Returns the BaseFrameStream for the current stack being traversed. |
| 77 | // |
| 78 | // Parameters: |
| 79 | // thread Current Java thread. |
| 80 | // magic Magic value used for each stack walking |
| 81 | // frames_array User-supplied buffers. The 0th element is reserved |
| 82 | // for this BaseFrameStream to use |
| 83 | // |
| 84 | BaseFrameStream* BaseFrameStream::from_current(JavaThread* thread, jlong magic, |
| 85 | objArrayHandle frames_array) |
| 86 | { |
| 87 | oop m1 = frames_array->obj_at(magic_pos); |
| 88 | if (m1 != thread->threadObj()) return NULL__null; |
| 89 | if (magic == 0L) return NULL__null; |
| 90 | BaseFrameStream* stream = (BaseFrameStream*) (intptr_t) magic; |
| 91 | if (!stream->is_valid_in(thread, frames_array)) return NULL__null; |
| 92 | return stream; |
| 93 | } |
| 94 | |
| 95 | // Unpacks one or more frames into user-supplied buffers. |
| 96 | // Updates the end index, and returns the number of unpacked frames. |
| 97 | // Always start with the existing vfst.method and bci. |
| 98 | // Do not call vfst.next to advance over the last returned value. |
| 99 | // In other words, do not leave any stale data in the vfst. |
| 100 | // |
| 101 | // Parameters: |
| 102 | // mode Restrict which frames to be decoded. |
| 103 | // BaseFrameStream stream of frames |
| 104 | // max_nframes Maximum number of frames to be filled. |
| 105 | // start_index Start index to the user-supplied buffers. |
| 106 | // frames_array Buffer to store Class or StackFrame in, starting at start_index. |
| 107 | // frames array is a Class<?>[] array when only getting caller |
| 108 | // reference, and a StackFrameInfo[] array (or derivative) |
| 109 | // otherwise. It should never be null. |
| 110 | // end_index End index to the user-supplied buffers with unpacked frames. |
| 111 | // |
| 112 | // Returns the number of frames whose information was transferred into the buffers. |
| 113 | // |
| 114 | int StackWalk::fill_in_frames(jlong mode, BaseFrameStream& stream, |
| 115 | int max_nframes, int start_index, |
| 116 | objArrayHandle frames_array, |
| 117 | int& end_index, TRAPSJavaThread* __the_thread__) { |
| 118 | log_debug(stackwalk)(!(LogImpl<(LogTag::_stackwalk), (LogTag::__NO_TAG), (LogTag ::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG)>::is_level(LogLevel::Debug))) ? (void)0 : LogImpl <(LogTag::_stackwalk), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::write<LogLevel::Debug>("fill_in_frames limit=%d start=%d frames length=%d", |
| 119 | max_nframes, start_index, frames_array->length()); |
| 120 | assert(max_nframes > 0, "invalid max_nframes")do { if (!(max_nframes > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 120, "assert(" "max_nframes > 0" ") failed", "invalid max_nframes" ); ::breakpoint(); } } while (0); |
| 121 | assert(start_index + max_nframes <= frames_array->length(), "oob")do { if (!(start_index + max_nframes <= frames_array->length ())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 121, "assert(" "start_index + max_nframes <= frames_array->length()" ") failed", "oob"); ::breakpoint(); } } while (0); |
| 122 | |
| 123 | int frames_decoded = 0; |
| 124 | for (; !stream.at_end(); stream.next()) { |
| 125 | Method* method = stream.method(); |
| 126 | |
| 127 | if (method == NULL__null) continue; |
| 128 | |
| 129 | // skip hidden frames for default StackWalker option (i.e. SHOW_HIDDEN_FRAMES |
| 130 | // not set) and when StackWalker::getCallerClass is called |
| 131 | if (!ShowHiddenFrames && (skip_hidden_frames(mode) || get_caller_class(mode))) { |
| 132 | if (method->is_hidden()) { |
| 133 | LogTarget(Debug, stackwalk)LogTargetImpl<LogLevel::Debug, (LogTag::_stackwalk), (LogTag ::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG), (LogTag::__NO_TAG)> lt; |
| 134 | if (lt.is_enabled()) { |
| 135 | ResourceMark rm(THREAD__the_thread__); |
| 136 | LogStream ls(lt); |
| 137 | ls.print(" hidden method: "); |
| 138 | method->print_short_name(&ls); |
| 139 | ls.cr(); |
| 140 | } |
| 141 | continue; |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | int index = end_index++; |
| 146 | LogTarget(Debug, stackwalk)LogTargetImpl<LogLevel::Debug, (LogTag::_stackwalk), (LogTag ::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG), (LogTag::__NO_TAG)> lt; |
| 147 | if (lt.is_enabled()) { |
| 148 | ResourceMark rm(THREAD__the_thread__); |
| 149 | LogStream ls(lt); |
| 150 | ls.print(" %d: frame method: ", index); |
| 151 | method->print_short_name(&ls); |
| 152 | ls.print_cr(" bci=%d", stream.bci()); |
| 153 | } |
| 154 | |
| 155 | if (!need_method_info(mode) && get_caller_class(mode) && |
| 156 | index == start_index && method->caller_sensitive()) { |
| 157 | ResourceMark rm(THREAD__the_thread__); |
| 158 | THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 160, vmSymbols::java_lang_UnsupportedOperationException(), err_msg ("StackWalker::getCallerClass called from @CallerSensitive '%s' method" , method->external_name())); return 0; } |
| 159 | err_msg("StackWalker::getCallerClass called from @CallerSensitive '%s' method",{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 160, vmSymbols::java_lang_UnsupportedOperationException(), err_msg ("StackWalker::getCallerClass called from @CallerSensitive '%s' method" , method->external_name())); return 0; } |
| 160 | method->external_name())){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 160, vmSymbols::java_lang_UnsupportedOperationException(), err_msg ("StackWalker::getCallerClass called from @CallerSensitive '%s' method" , method->external_name())); return 0; }; |
| 161 | } |
| 162 | // fill in StackFrameInfo and initialize MemberName |
| 163 | stream.fill_frame(index, frames_array, methodHandle(THREAD__the_thread__, method), CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
| 164 | if (++frames_decoded >= max_nframes) break; |
| 165 | } |
| 166 | return frames_decoded; |
| 167 | } |
| 168 | |
| 169 | // Fill in the LiveStackFrameInfo at the given index in frames_array |
| 170 | void LiveFrameStream::fill_frame(int index, objArrayHandle frames_array, |
| 171 | const methodHandle& method, TRAPSJavaThread* __the_thread__) { |
| 172 | HandleMark hm(THREAD__the_thread__); |
| 173 | Handle stackFrame(THREAD__the_thread__, frames_array->obj_at(index)); |
| 174 | fill_live_stackframe(stackFrame, method, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
| 175 | } |
| 176 | |
| 177 | // Fill in the StackFrameInfo at the given index in frames_array |
| 178 | void JavaFrameStream::fill_frame(int index, objArrayHandle frames_array, |
| 179 | const methodHandle& method, TRAPSJavaThread* __the_thread__) { |
| 180 | if (_need_method_info) { |
| 181 | HandleMark hm(THREAD__the_thread__); |
| 182 | Handle stackFrame(THREAD__the_thread__, frames_array->obj_at(index)); |
| 183 | fill_stackframe(stackFrame, method, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
| 184 | } else { |
| 185 | frames_array->obj_at_put(index, method->method_holder()->java_mirror()); |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | // Create and return a LiveStackFrame.PrimitiveSlot (if needed) for the |
| 190 | // StackValue at the given index. 'type' is expected to be T_INT, T_LONG, |
| 191 | // T_OBJECT, or T_CONFLICT. |
| 192 | oop LiveFrameStream::create_primitive_slot_instance(StackValueCollection* values, |
| 193 | int i, BasicType type, TRAPSJavaThread* __the_thread__) { |
| 194 | Klass* k = vmClasses::LiveStackFrameInfo_klass(); |
| 195 | InstanceKlass* ik = InstanceKlass::cast(k); |
| 196 | |
| 197 | JavaValue result(T_OBJECT); |
| 198 | JavaCallArguments args; |
| 199 | Symbol* signature = NULL__null; |
| 200 | |
| 201 | // ## TODO: type is only available in LocalVariable table, if present. |
| 202 | // ## StackValue type is T_INT or T_OBJECT (or converted to T_LONG on 64-bit) |
| 203 | switch (type) { |
| 204 | case T_INT: |
| 205 | args.push_int(values->int_at(i)); |
| 206 | signature = vmSymbols::asPrimitive_int_signature(); |
| 207 | break; |
| 208 | |
| 209 | case T_LONG: |
| 210 | args.push_long(values->long_at(i)); |
| 211 | signature = vmSymbols::asPrimitive_long_signature(); |
| 212 | break; |
| 213 | |
| 214 | case T_FLOAT: |
| 215 | case T_DOUBLE: |
| 216 | case T_BYTE: |
| 217 | case T_SHORT: |
| 218 | case T_CHAR: |
| 219 | case T_BOOLEAN: |
| 220 | THROW_MSG_(vmSymbols::java_lang_InternalError(), "Unexpected StackValue type", NULL){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 220, vmSymbols::java_lang_InternalError(), "Unexpected StackValue type" ); return __null; }; |
| 221 | |
| 222 | case T_OBJECT: |
| 223 | return values->obj_at(i)(); |
| 224 | |
| 225 | case T_CONFLICT: |
| 226 | // put a non-null slot |
| 227 | #ifdef _LP641 |
| 228 | args.push_long(0); |
| 229 | signature = vmSymbols::asPrimitive_long_signature(); |
| 230 | #else |
| 231 | args.push_int(0); |
| 232 | signature = vmSymbols::asPrimitive_int_signature(); |
| 233 | #endif |
| 234 | |
| 235 | break; |
| 236 | |
| 237 | default: ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 237); ::breakpoint(); } while (0); |
| 238 | } |
| 239 | JavaCalls::call_static(&result, |
| 240 | ik, |
| 241 | vmSymbols::asPrimitive_name(), |
| 242 | signature, |
| 243 | &args, |
| 244 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
| 245 | return (instanceOop) result.get_oop(); |
| 246 | } |
| 247 | |
| 248 | objArrayHandle LiveFrameStream::values_to_object_array(StackValueCollection* values, TRAPSJavaThread* __the_thread__) { |
| 249 | objArrayHandle empty; |
| 250 | int length = values->size(); |
| 251 | objArrayOop array_oop = oopFactory::new_objArray(vmClasses::Object_klass(), |
| 252 | length, CHECK_(empty)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return empty; (void)(0); |
| 253 | objArrayHandle array_h(THREAD__the_thread__, array_oop); |
| 254 | for (int i = 0; i < values->size(); i++) { |
| 255 | StackValue* st = values->at(i); |
| 256 | BasicType type = st->type(); |
| 257 | int index = i; |
| 258 | #ifdef _LP641 |
| 259 | if (type != T_OBJECT && type != T_CONFLICT) { |
| 260 | intptr_t ret = st->get_int(); // read full 64-bit slot |
Value stored to 'ret' during its initialization is never read | |
| 261 | type = T_LONG; // treat as long |
| 262 | index--; // undo +1 in StackValueCollection::long_at |
| 263 | } |
| 264 | #endif |
| 265 | oop obj = create_primitive_slot_instance(values, index, type, CHECK_(empty)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return empty; (void)(0); |
| 266 | if (obj != NULL__null) { |
| 267 | array_h->obj_at_put(i, obj); |
| 268 | } |
| 269 | } |
| 270 | return array_h; |
| 271 | } |
| 272 | |
| 273 | objArrayHandle LiveFrameStream::monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors, TRAPSJavaThread* __the_thread__) { |
| 274 | int length = monitors->length(); |
| 275 | objArrayOop array_oop = oopFactory::new_objArray(vmClasses::Object_klass(), |
| 276 | length, CHECK_(objArrayHandle())__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return objArrayHandle(); (void)(0); |
| 277 | objArrayHandle array_h(THREAD__the_thread__, array_oop); |
| 278 | for (int i = 0; i < length; i++) { |
| 279 | MonitorInfo* monitor = monitors->at(i); |
| 280 | array_h->obj_at_put(i, monitor->owner()); |
| 281 | } |
| 282 | return array_h; |
| 283 | } |
| 284 | |
| 285 | // Fill StackFrameInfo with bci and initialize memberName |
| 286 | void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method, TRAPSJavaThread* __the_thread__) { |
| 287 | java_lang_StackFrameInfo::set_method_and_bci(stackFrame, method, bci(), THREAD__the_thread__); |
| 288 | } |
| 289 | |
| 290 | // Fill LiveStackFrameInfo with locals, monitors, and expressions |
| 291 | void LiveFrameStream::fill_live_stackframe(Handle stackFrame, |
| 292 | const methodHandle& method, TRAPSJavaThread* __the_thread__) { |
| 293 | fill_stackframe(stackFrame, method, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
| 294 | if (_jvf != NULL__null) { |
| 295 | ResourceMark rm(THREAD__the_thread__); |
| 296 | HandleMark hm(THREAD__the_thread__); |
| 297 | |
| 298 | StackValueCollection* locals = _jvf->locals(); |
| 299 | StackValueCollection* expressions = _jvf->expressions(); |
| 300 | GrowableArray<MonitorInfo*>* monitors = _jvf->monitors(); |
| 301 | |
| 302 | int mode = 0; |
| 303 | if (_jvf->is_interpreted_frame()) { |
| 304 | mode = MODE_INTERPRETED; |
| 305 | } else if (_jvf->is_compiled_frame()) { |
| 306 | mode = MODE_COMPILED; |
| 307 | } |
| 308 | |
| 309 | if (!locals->is_empty()) { |
| 310 | objArrayHandle locals_h = values_to_object_array(locals, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
| 311 | java_lang_LiveStackFrameInfo::set_locals(stackFrame(), locals_h()); |
| 312 | } |
| 313 | if (!expressions->is_empty()) { |
| 314 | objArrayHandle expressions_h = values_to_object_array(expressions, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
| 315 | java_lang_LiveStackFrameInfo::set_operands(stackFrame(), expressions_h()); |
| 316 | } |
| 317 | if (monitors->length() > 0) { |
| 318 | objArrayHandle monitors_h = monitors_to_object_array(monitors, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); |
| 319 | java_lang_LiveStackFrameInfo::set_monitors(stackFrame(), monitors_h()); |
| 320 | } |
| 321 | java_lang_LiveStackFrameInfo::set_mode(stackFrame(), mode); |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | // Begins stack walking. |
| 326 | // |
| 327 | // Parameters: |
| 328 | // stackStream StackStream object |
| 329 | // mode Stack walking mode. |
| 330 | // skip_frames Number of frames to be skipped. |
| 331 | // frame_count Number of frames to be traversed. |
| 332 | // start_index Start index to the user-supplied buffers. |
| 333 | // frames_array Buffer to store StackFrame in, starting at start_index. |
| 334 | // frames array is a Class<?>[] array when only getting caller |
| 335 | // reference, and a StackFrameInfo[] array (or derivative) |
| 336 | // otherwise. It should never be null. |
| 337 | // |
| 338 | // Returns Object returned from AbstractStackWalker::doStackWalk call. |
| 339 | // |
| 340 | oop StackWalk::walk(Handle stackStream, jlong mode, |
| 341 | int skip_frames, int frame_count, int start_index, |
| 342 | objArrayHandle frames_array, |
| 343 | TRAPSJavaThread* __the_thread__) { |
| 344 | ResourceMark rm(THREAD__the_thread__); |
| 345 | JavaThread* jt = THREAD__the_thread__; |
| 346 | log_debug(stackwalk)(!(LogImpl<(LogTag::_stackwalk), (LogTag::__NO_TAG), (LogTag ::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG)>::is_level(LogLevel::Debug))) ? (void)0 : LogImpl <(LogTag::_stackwalk), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::write<LogLevel::Debug>("Start walking: mode " JLONG_FORMAT"%" "l" "d" " skip %d frames batch size %d", |
| 347 | mode, skip_frames, frame_count); |
| 348 | |
| 349 | if (frames_array.is_null()) { |
| 350 | THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 350, vmSymbols::java_lang_NullPointerException(), "frames_array is NULL" ); return __null; }; |
| 351 | } |
| 352 | |
| 353 | // Setup traversal onto my stack. |
| 354 | if (live_frame_info(mode)) { |
| 355 | assert (use_frames_array(mode), "Bad mode for get live frame")do { if (!(use_frames_array(mode))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 355, "assert(" "use_frames_array(mode)" ") failed", "Bad mode for get live frame" ); ::breakpoint(); } } while (0); |
| 356 | RegisterMap regMap(jt, true); |
| 357 | LiveFrameStream stream(jt, ®Map); |
| 358 | return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count, |
| 359 | start_index, frames_array, THREAD__the_thread__); |
| 360 | } else { |
| 361 | JavaFrameStream stream(jt, mode); |
| 362 | return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count, |
| 363 | start_index, frames_array, THREAD__the_thread__); |
| 364 | } |
| 365 | } |
| 366 | |
| 367 | oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream, |
| 368 | jlong mode, int skip_frames, int frame_count, |
| 369 | int start_index, objArrayHandle frames_array, TRAPSJavaThread* __the_thread__) { |
| 370 | methodHandle m_doStackWalk(THREAD__the_thread__, Universe::do_stack_walk_method()); |
| 371 | |
| 372 | { |
| 373 | Klass* stackWalker_klass = vmClasses::StackWalker_klass(); |
| 374 | Klass* abstractStackWalker_klass = vmClasses::AbstractStackWalker_klass(); |
| 375 | while (!stream.at_end()) { |
| 376 | InstanceKlass* ik = stream.method()->method_holder(); |
| 377 | if (ik != stackWalker_klass && |
| 378 | ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { |
| 379 | break; |
| 380 | } |
| 381 | |
| 382 | LogTarget(Debug, stackwalk)LogTargetImpl<LogLevel::Debug, (LogTag::_stackwalk), (LogTag ::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG), (LogTag::__NO_TAG)> lt; |
| 383 | if (lt.is_enabled()) { |
| 384 | ResourceMark rm(THREAD__the_thread__); |
| 385 | LogStream ls(lt); |
| 386 | ls.print(" skip "); |
| 387 | stream.method()->print_short_name(&ls); |
| 388 | ls.cr(); |
| 389 | } |
| 390 | stream.next(); |
| 391 | } |
| 392 | |
| 393 | // stack frame has been traversed individually and resume stack walk |
| 394 | // from the stack frame at depth == skip_frames. |
| 395 | for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) { |
| 396 | LogTarget(Debug, stackwalk)LogTargetImpl<LogLevel::Debug, (LogTag::_stackwalk), (LogTag ::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG), (LogTag::__NO_TAG)> lt; |
| 397 | if (lt.is_enabled()) { |
| 398 | ResourceMark rm(THREAD__the_thread__); |
| 399 | LogStream ls(lt); |
| 400 | ls.print(" skip "); |
| 401 | stream.method()->print_short_name(&ls); |
| 402 | ls.cr(); |
| 403 | } |
| 404 | } |
| 405 | } |
| 406 | |
| 407 | int end_index = start_index; |
| 408 | int numFrames = 0; |
| 409 | if (!stream.at_end()) { |
| 410 | KeepStackGCProcessedMark keep_stack(THREAD__the_thread__); |
| 411 | numFrames = fill_in_frames(mode, stream, frame_count, start_index, |
| 412 | frames_array, end_index, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
| 413 | if (numFrames < 1) { |
| 414 | THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 414, vmSymbols::java_lang_InternalError(), "stack walk: decode failed" ); return __null; }; |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | // JVM_CallStackWalk walks the stack and fills in stack frames, then calls to |
| 419 | // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk |
| 420 | // which calls the implementation to consume the stack frames. |
| 421 | // When JVM_CallStackWalk returns, it invalidates the stack stream. |
| 422 | JavaValue result(T_OBJECT); |
| 423 | JavaCallArguments args(stackStream); |
| 424 | args.push_long(stream.address_value()); |
| 425 | args.push_int(skip_frames); |
| 426 | args.push_int(frame_count); |
| 427 | args.push_int(start_index); |
| 428 | args.push_int(end_index); |
| 429 | |
| 430 | // Link the thread and vframe stream into the callee-visible object |
| 431 | stream.setup_magic_on_entry(frames_array); |
| 432 | |
| 433 | JavaCalls::call(&result, m_doStackWalk, &args, THREAD__the_thread__); |
| 434 | |
| 435 | // Do this before anything else happens, to disable any lingering stream objects |
| 436 | bool ok = stream.cleanup_magic_on_exit(frames_array); |
| 437 | |
| 438 | // Throw pending exception if we must |
| 439 | (void) (CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); |
| 440 | |
| 441 | if (!ok) { |
| 442 | THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 442, vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit" ); return __null; }; |
| 443 | } |
| 444 | |
| 445 | // Return normally |
| 446 | return result.get_oop(); |
| 447 | } |
| 448 | |
| 449 | // Walk the next batch of stack frames |
| 450 | // |
| 451 | // Parameters: |
| 452 | // stackStream StackStream object |
| 453 | // mode Stack walking mode. |
| 454 | // magic Must be valid value to continue the stack walk |
| 455 | // frame_count Number of frames to be decoded. |
| 456 | // start_index Start index to the user-supplied buffers. |
| 457 | // frames_array Buffer to store StackFrame in, starting at start_index. |
| 458 | // |
| 459 | // Returns the end index of frame filled in the buffer. |
| 460 | // |
| 461 | jint StackWalk::fetchNextBatch(Handle stackStream, jlong mode, jlong magic, |
| 462 | int frame_count, int start_index, |
| 463 | objArrayHandle frames_array, |
| 464 | TRAPSJavaThread* __the_thread__) |
| 465 | { |
| 466 | JavaThread* jt = THREAD__the_thread__; |
| 467 | BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array); |
| 468 | if (existing_stream == NULL__null) { |
| 469 | THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 469, vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers" ); return 0L; }; |
| 470 | } |
| 471 | |
| 472 | if (frames_array.is_null()) { |
| 473 | THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 473, vmSymbols::java_lang_NullPointerException(), "frames_array is NULL" ); return 0L; }; |
| 474 | } |
| 475 | |
| 476 | log_debug(stackwalk)(!(LogImpl<(LogTag::_stackwalk), (LogTag::__NO_TAG), (LogTag ::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG)>::is_level(LogLevel::Debug))) ? (void)0 : LogImpl <(LogTag::_stackwalk), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::write<LogLevel::Debug>("StackWalk::fetchNextBatch frame_count %d existing_stream " |
| 477 | PTR_FORMAT"0x%016" "l" "x" " start %d frames %d", |
| 478 | frame_count, p2i(existing_stream), start_index, frames_array->length()); |
| 479 | int end_index = start_index; |
| 480 | if (frame_count <= 0) { |
| 481 | return end_index; // No operation. |
| 482 | } |
| 483 | |
| 484 | int count = frame_count + start_index; |
| 485 | assert (frames_array->length() >= count, "not enough space in buffers")do { if (!(frames_array->length() >= count)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 485, "assert(" "frames_array->length() >= count" ") failed" , "not enough space in buffers"); ::breakpoint(); } } while ( 0); |
| 486 | |
| 487 | BaseFrameStream& stream = (*existing_stream); |
| 488 | if (!stream.at_end()) { |
| 489 | // If we have to get back here for even more frames, then 1) the user did not supply |
| 490 | // an accurate hint suggesting the depth of the stack walk, and 2) we are not just |
| 491 | // peeking at a few frames. Take the cost of flushing out any pending deferred GC |
| 492 | // processing of the stack. |
| 493 | KeepStackGCProcessedMark keep_stack(jt); |
| 494 | stream.next(); // advance past the last frame decoded in previous batch |
| 495 | if (!stream.at_end()) { |
| 496 | int n = fill_in_frames(mode, stream, frame_count, start_index, |
| 497 | frames_array, end_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); |
| 498 | if (n < 1) { |
| 499 | THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/stackwalk.cpp" , 499, vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed" ); return 0L; }; |
| 500 | } |
| 501 | return end_index; |
| 502 | } |
| 503 | } |
| 504 | return end_index; |
| 505 | } |