1 /*
2  * Copyright (c) 1997, 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 #ifndef SHARE_RUNTIME_VFRAME_HPP
26 #define SHARE_RUNTIME_VFRAME_HPP
27 
28 #include "code/debugInfo.hpp"
29 #include "code/debugInfoRec.hpp"
30 #include "code/location.hpp"
31 #include "oops/oop.hpp"
32 #include "runtime/frame.hpp"
33 #include "runtime/handles.hpp"
34 #include "runtime/registerMap.hpp"
35 #include "runtime/stackValue.hpp"
36 #include "runtime/stackValueCollection.hpp"
37 #include "utilities/growableArray.hpp"
38 
39 // vframes are virtual stack frames representing source level activations.
40 // A single frame may hold several source level activations in the case of
41 // optimized code. The debugging stored with the optimized code enables
42 // us to unfold a frame as a stack of vframes.
43 // A cVFrame represents an activation of a non-java method.
44 
45 // The vframe inheritance hierarchy:
46 // - vframe
47 //   - javaVFrame
48 //     - interpretedVFrame
49 //     - compiledVFrame     ; (used for both compiled Java methods and native stubs)
50 //   - externalVFrame
51 //     - entryVFrame        ; special frame created when calling Java from C
52 
53 // - BasicLock
54 
55 class StackFrameStream;
56 
57 class vframe: public ResourceObj {
58  protected:
59   frame        _fr;      // Raw frame behind the virtual frame.
60   RegisterMap  _reg_map; // Register map for the raw frame (used to handle callee-saved registers).
61   JavaThread*  _thread;  // The thread owning the raw frame.
62 
63   vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread);
64   vframe(const frame* fr, JavaThread* thread);
65  public:
66   // Factory methods for creating vframes
67   static vframe* new_vframe(const frame* f, const RegisterMap *reg_map, JavaThread* thread);
68   static vframe* new_vframe(StackFrameStream& fst, JavaThread* thread);
69 
70   // Accessors
fr() const71   frame              fr()           const { return _fr;       }
cb() const72   CodeBlob*          cb()         const { return _fr.cb();  }
nm() const73   CompiledMethod*   nm()         const {
74       assert( cb() != NULL && cb()->is_compiled(), "usage");
75       return (CompiledMethod*) cb();
76   }
77 
78 // ???? Does this need to be a copy?
frame_pointer()79   frame*             frame_pointer() { return &_fr;       }
register_map() const80   const RegisterMap* register_map() const { return &_reg_map; }
thread() const81   JavaThread*        thread()       const { return _thread;   }
82 
83   // Returns the sender vframe
84   virtual vframe* sender() const;
85 
86   // Returns the next javaVFrame on the stack (skipping all other kinds of frame)
87   javaVFrame *java_sender() const;
88 
89   // Answers if the this is the top vframe in the frame, i.e., if the sender vframe
90   // is in the caller frame
is_top() const91   virtual bool is_top() const { return true; }
92 
93   // Returns top vframe within same frame (see is_top())
94   virtual vframe* top() const;
95 
96   // Type testing operations
is_entry_frame() const97   virtual bool is_entry_frame()       const { return false; }
is_java_frame() const98   virtual bool is_java_frame()        const { return false; }
is_interpreted_frame() const99   virtual bool is_interpreted_frame() const { return false; }
is_compiled_frame() const100   virtual bool is_compiled_frame()    const { return false; }
101 
102 #ifndef PRODUCT
103   // printing operations
104   virtual void print_value() const;
105   virtual void print();
106 #endif
107 };
108 
109 
110 class javaVFrame: public vframe {
111  public:
112   // JVM state
113   virtual Method*                      method()         const = 0;
114   virtual int                          bci()            const = 0;
115   virtual StackValueCollection*        locals()         const = 0;
116   virtual StackValueCollection*        expressions()    const = 0;
117   // the order returned by monitors() is from oldest -> youngest#4418568
118   virtual GrowableArray<MonitorInfo*>* monitors()       const = 0;
119 
120   // Debugging support via JVMTI.
121   // NOTE that this is not guaranteed to give correct results for compiled vframes.
122   // Deoptimize first if necessary.
123   virtual void set_locals(StackValueCollection* values) const = 0;
124 
125   // Test operation
is_java_frame() const126   bool is_java_frame() const { return true; }
127 
128  protected:
javaVFrame(const frame * fr,const RegisterMap * reg_map,JavaThread * thread)129   javaVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {}
javaVFrame(const frame * fr,JavaThread * thread)130   javaVFrame(const frame* fr, JavaThread* thread) : vframe(fr, thread) {}
131 
132  public:
133   // casting
cast(vframe * vf)134   static javaVFrame* cast(vframe* vf) {
135     assert(vf == NULL || vf->is_java_frame(), "must be java frame");
136     return (javaVFrame*) vf;
137   }
138 
139   // Return an array of monitors locked by this frame in the youngest to oldest order
140   GrowableArray<MonitorInfo*>* locked_monitors();
141 
142   // printing used during stack dumps and diagnostics
143   static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state);
144   void print_lock_info_on(outputStream* st, int frame_count);
print_lock_info(int frame_count)145   void print_lock_info(int frame_count) { print_lock_info_on(tty, frame_count); }
146 
147 #ifndef PRODUCT
148  public:
149   // printing operations
150   void print();
151   void print_value() const;
152   void print_activation(int index) const;
153 
154   // verify operations
155   virtual void verify() const;
156 
157   // Structural compare
158   bool structural_compare(javaVFrame* other);
159 #endif
160   friend class vframe;
161 };
162 
163 class interpretedVFrame: public javaVFrame {
164  public:
165   // JVM state
166   Method*                      method()         const;
167   int                          bci()            const;
168   StackValueCollection*        locals()         const;
169   StackValueCollection*        expressions()    const;
170   GrowableArray<MonitorInfo*>* monitors()       const;
171 
172   void set_locals(StackValueCollection* values) const;
173 
174   // Test operation
is_interpreted_frame() const175   bool is_interpreted_frame() const { return true; }
176 
177  protected:
interpretedVFrame(const frame * fr,const RegisterMap * reg_map,JavaThread * thread)178   interpretedVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : javaVFrame(fr, reg_map, thread) {};
179 
180  public:
181   // Accessors for Byte Code Pointer
182   u_char* bcp() const;
183   void set_bcp(u_char* bcp);
184 
185   // casting
cast(vframe * vf)186   static interpretedVFrame* cast(vframe* vf) {
187     assert(vf == NULL || vf->is_interpreted_frame(), "must be interpreted frame");
188     return (interpretedVFrame*) vf;
189   }
190 
191  private:
192   static const int bcp_offset;
193   intptr_t* locals_addr_at(int offset) const;
194   StackValueCollection* stack_data(bool expressions) const;
195   // returns where the parameters starts relative to the frame pointer
196   int start_of_parameters() const;
197 
198 #ifndef PRODUCT
199  public:
200   // verify operations
201   void verify() const;
202 #endif
203   friend class vframe;
204 };
205 
206 
207 class externalVFrame: public vframe {
208  protected:
externalVFrame(const frame * fr,const RegisterMap * reg_map,JavaThread * thread)209   externalVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {}
210 
211 #ifndef PRODUCT
212  public:
213   // printing operations
214   void print_value() const;
215   void print();
216 #endif
217   friend class vframe;
218 };
219 
220 class entryVFrame: public externalVFrame {
221  public:
is_entry_frame() const222   bool is_entry_frame() const { return true; }
223 
224  protected:
225   entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread);
226 
227  public:
228   // casting
cast(vframe * vf)229   static entryVFrame* cast(vframe* vf) {
230     assert(vf == NULL || vf->is_entry_frame(), "must be entry frame");
231     return (entryVFrame*) vf;
232   }
233 
234 #ifndef PRODUCT
235  public:
236   // printing
237   void print_value() const;
238   void print();
239 #endif
240   friend class vframe;
241 };
242 
243 
244 // A MonitorInfo is a ResourceObject that describes a the pair:
245 // 1) the owner of the monitor
246 // 2) the monitor lock
247 class MonitorInfo : public ResourceObj {
248  private:
249   Handle     _owner; // the object owning the monitor
250   BasicLock* _lock;
251   Handle     _owner_klass; // klass (mirror) if owner was scalar replaced
252   bool       _eliminated;
253   bool       _owner_is_scalar_replaced;
254  public:
255   // Constructor
256   MonitorInfo(oop owner, BasicLock* lock, bool eliminated, bool owner_is_scalar_replaced);
257   // Accessors
owner() const258   oop owner() const {
259     assert(!_owner_is_scalar_replaced, "should not be called for scalar replaced object");
260     return _owner();
261   }
owner_klass() const262   oop owner_klass() const {
263     assert(_owner_is_scalar_replaced, "should not be called for not scalar replaced object");
264     return _owner_klass();
265   }
lock() const266   BasicLock* lock()  const { return _lock;  }
eliminated() const267   bool eliminated()  const { return _eliminated; }
owner_is_scalar_replaced() const268   bool owner_is_scalar_replaced()  const { return _owner_is_scalar_replaced; }
269 };
270 
271 class vframeStreamCommon : StackObj {
272  protected:
273   // common
274   frame        _prev_frame;
275   frame        _frame;
276   JavaThread*  _thread;
277   RegisterMap  _reg_map;
278   enum { interpreted_mode, compiled_mode, at_end_mode } _mode;
279 
280   // For compiled_mode
281   int _decode_offset;
282   int _sender_decode_offset;
283   int _vframe_id;
284 
285   // Cached information
286   Method* _method;
287   int       _bci;
288 
289   // Should VM activations be ignored or not
290   bool _stop_at_java_call_stub;
291 
292   bool fill_in_compiled_inlined_sender();
293   void fill_from_compiled_frame(int decode_offset);
294   void fill_from_compiled_native_frame();
295 
296   void fill_from_interpreter_frame();
297   bool fill_from_frame();
298 
299   // Helper routine for security_get_caller_frame
300   void skip_prefixed_method_and_wrappers();
301 
302   DEBUG_ONLY(void found_bad_method_frame() const;)
303 
304  public:
305   // Constructor
306   inline vframeStreamCommon(JavaThread* thread, bool process_frames);
307 
308   // Accessors
method() const309   Method* method() const { return _method; }
bci() const310   int bci() const { return _bci; }
311   inline intptr_t* frame_id() const;
frame_pc() const312   address frame_pc() const { return _frame.pc(); }
313 
cb() const314   CodeBlob*          cb()         const { return _frame.cb();  }
nm() const315   CompiledMethod*   nm()         const {
316       assert( cb() != NULL && cb()->is_compiled(), "usage");
317       return (CompiledMethod*) cb();
318   }
319 
320   javaVFrame* asJavaVFrame();
321 
322   // Frame type
323   inline bool is_interpreted_frame() const;
324   inline bool is_entry_frame() const;
325 
326   // Iteration
327   inline void next();
328   void security_next();
329 
at_end() const330   bool at_end() const { return _mode == at_end_mode; }
331 
332   // Implements security traversal. Skips depth no. of frame including
333   // special security frames and prefixed native methods
334   void security_get_caller_frame(int depth);
335 };
336 
337 class vframeStream : public vframeStreamCommon {
338  public:
339   // Constructors
340   vframeStream(JavaThread* thread, bool stop_at_java_call_stub = false, bool process_frames = true);
341 
342   // top_frame may not be at safepoint, start with sender
343   vframeStream(JavaThread* thread, frame top_frame, bool stop_at_java_call_stub = false);
344 };
345 
346 #endif // SHARE_RUNTIME_VFRAME_HPP
347