1/*
2 * Copyright (c) 2015, 2017, 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_VM_PRIMS_STACKWALK_HPP
27#define SHARE_VM_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()      { _vfst.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_VM_PRIMS_STACKWALK_HPP
161