1/*
2 * Copyright (c) 2015, 2019, 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
26#ifndef SHARE_PRIMS_STACKWALK_HPP
27#define SHARE_PRIMS_STACKWALK_HPP
28
29#include "oops/oop.hpp"
30#include "runtime/vframe.hpp"
31
32// BaseFrameStream is an abstract base class for encapsulating the VM-side
33// implementation of the StackWalker API. There are two concrete subclasses:
34// - JavaFrameStream:
35// -based on vframeStream; used in most instances
36// - LiveFrameStream:
37// -based on javaVFrame; used for retrieving locals/monitors/operands for
38// LiveStackFrame
39class BaseFrameStream : public StackObj {
40private:
41 enum {
42 magic_pos = 0
43 };
44
45 JavaThread* _thread;
46 jlong _anchor;
47protected:
48 void fill_stackframe(Handle stackFrame, const methodHandle& method, TRAPS);
49public:
50 BaseFrameStream(JavaThread* thread) : _thread(thread), _anchor(0L) {}
51
52 virtual void next()=0;
53 virtual bool at_end()=0;
54
55 virtual Method* method()=0;
56 virtual int bci()=0;
57
58 virtual void fill_frame(int index, objArrayHandle frames_array,
59 const methodHandle& method, TRAPS)=0;
60
61 void setup_magic_on_entry(objArrayHandle frames_array);
62 bool check_magic(objArrayHandle frames_array);
63 bool cleanup_magic_on_exit(objArrayHandle frames_array);
64
65 bool is_valid_in(Thread* thread, objArrayHandle frames_array) {
66 return (_thread == thread && check_magic(frames_array));
67 }
68
69 jlong address_value() {
70 return (jlong) castable_address(this);
71 }
72
73 static BaseFrameStream* from_current(JavaThread* thread, jlong magic, objArrayHandle frames_array);
74};
75
76class JavaFrameStream : public BaseFrameStream {
77private:
78 vframeStream _vfst;
79 bool _need_method_info;
80public:
81 JavaFrameStream(JavaThread* thread, int mode);
82
83 void next();
84 bool at_end() { return _vfst.at_end(); }
85
86 Method* method() { return _vfst.method(); }
87 int bci() { return _vfst.bci(); }
88
89 void fill_frame(int index, objArrayHandle frames_array,
90 const methodHandle& method, TRAPS);
91};
92
93class LiveFrameStream : public BaseFrameStream {
94private:
95 enum {
96 MODE_INTERPRETED = 0x01,
97 MODE_COMPILED = 0x02
98 };
99
100 javaVFrame* _jvf;
101
102 void fill_live_stackframe(Handle stackFrame, const methodHandle& method, TRAPS);
103 static oop create_primitive_slot_instance(StackValueCollection* values,
104 int i, BasicType type, TRAPS);
105 static objArrayHandle monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors,
106 TRAPS);
107 static objArrayHandle values_to_object_array(StackValueCollection* values, TRAPS);
108public:
109 LiveFrameStream(JavaThread* thread, RegisterMap* rm) : BaseFrameStream(thread) {
110 _jvf = thread->last_java_vframe(rm);
111 }
112
113 void next() { _jvf = _jvf->java_sender(); }
114 bool at_end() { return _jvf == NULL; }
115
116 Method* method() { return _jvf->method(); }
117 int bci() { return _jvf->bci(); }
118
119 void fill_frame(int index, objArrayHandle frames_array,
120 const methodHandle& method, TRAPS);
121};
122
123class StackWalk : public AllStatic {
124private:
125 static int fill_in_frames(jlong mode, BaseFrameStream& stream,
126 int max_nframes, int start_index,
127 objArrayHandle frames_array,
128 int& end_index, TRAPS);
129
130 static inline bool get_caller_class(int mode) {
131 return (mode & JVM_STACKWALK_GET_CALLER_CLASS) != 0;
132 }
133 static inline bool skip_hidden_frames(int mode) {
134 return (mode & JVM_STACKWALK_SHOW_HIDDEN_FRAMES) == 0;
135 }
136 static inline bool live_frame_info(int mode) {
137 return (mode & JVM_STACKWALK_FILL_LIVE_STACK_FRAMES) != 0;
138 }
139
140public:
141 static inline bool need_method_info(int mode) {
142 return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0;
143 }
144 static inline bool use_frames_array(int mode) {
145 return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0;
146 }
147 static oop walk(Handle stackStream, jlong mode,
148 int skip_frames, int frame_count, int start_index,
149 objArrayHandle frames_array,
150 TRAPS);
151
152 static oop fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
153 jlong mode, int skip_frames, int frame_count,
154 int start_index, objArrayHandle frames_array, TRAPS);
155
156 static jint fetchNextBatch(Handle stackStream, jlong mode, jlong magic,
157 int frame_count, int start_index,
158 objArrayHandle frames_array, TRAPS);
159};
160#endif // SHARE_PRIMS_STACKWALK_HPP
161