1 /*
  2  * Copyright (c) 2022, 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_VM_RUNTIME_FRAME_HELPERS_INLINE_HPP
 26 #define SHARE_VM_RUNTIME_FRAME_HELPERS_INLINE_HPP
 27 
 28 #include "code/scopeDesc.hpp"
 29 #include "compiler/oopMap.hpp"
 30 #include "compiler/oopMap.inline.hpp"
 31 #include "runtime/frame.hpp"
 32 #include "runtime/frame.inline.hpp"
 33 #include "runtime/stackValue.hpp"
 34 #include "utilities/macros.hpp"
 35 
 36 class Frame {
 37 public:
 38   static inline intptr_t** callee_link_address(const frame& f);
 39   static inline Method* frame_method(const frame& f);
 40   static inline address real_pc(const frame& f);
 41   static inline void patch_pc(const frame& f, address pc);
 42   static address* return_pc_address(const frame& f);
 43   static address return_pc(const frame& f);
 44   static bool is_stub(CodeBlob* cb);
 45 
 46 #ifdef ASSERT
 47   static inline intptr_t* frame_top(const frame &f);
 48   static inline bool is_deopt_return(address pc, const frame& sender);
 49   static bool assert_frame_laid_out(frame f);
 50 
 51   static char* method_name(Method* m);
 52   static Method* top_java_frame_method(const frame& f);
 53   static Method* bottom_java_frame_method(const frame& f)  { return Frame::frame_method(f); }
 54   static char* top_java_frame_name(const frame& f) { return method_name(top_java_frame_method(f)); }
 55   static char* bottom_java_frame_name(const frame& f) { return method_name(bottom_java_frame_method(f)); }
 56   static bool assert_bottom_java_frame_name(const frame& f, const char* name);
 57 #endif
 58 };
 59 
 60 template<typename Self>
 61 class FrameCommon : public Frame {
 62 public:
 63   template <typename FrameT> static bool is_instance(const FrameT& f);
 64 };
 65 
 66 class Interpreted : public FrameCommon<Interpreted> {
 67 public:
 68   DEBUG_ONLY(static const char* name;)
 69   static const bool interpreted = true;
 70   static const bool stub = false;
 71   static const int extra_oops = 0;
 72   static const char type = 'i';
 73 
 74 public:
 75 
 76   static inline intptr_t* frame_top(const frame& f, InterpreterOopMap* mask);
 77   static inline intptr_t* frame_top(const frame& f);
 78   static inline intptr_t* frame_top(const frame& f, int callee_argsize, bool callee_interpreted);
 79   template <bool relative = false>
 80   static inline intptr_t* frame_bottom(const frame& f);
 81   template <bool relative = false>
 82   static inline intptr_t* sender_unextended_sp(const frame& f);
 83   template <bool relative = false>
 84   static inline int stack_argsize(const frame& f);
 85 
 86   static inline address* return_pc_address(const frame& f);
 87   static inline address return_pc(const frame& f);
 88   template <bool relative>
 89   static void patch_sender_sp(frame& f, intptr_t* sp);
 90 
 91   static int size(const frame& f, InterpreterOopMap* mask);
 92   static int size(const frame& f);
 93   static inline int expression_stack_size(const frame &f, InterpreterOopMap* mask);
 94   static bool is_owning_locks(const frame& f);
 95 
 96   typedef InterpreterOopMap* ExtraT;
 97 };
 98 
 99 DEBUG_ONLY(const char* Interpreted::name = "Interpreted";)
100 
101 template<typename Self>
102 class NonInterpreted : public FrameCommon<Self>  {
103 public:
104   static inline intptr_t* frame_top(const frame& f, int callee_argsize, bool callee_interpreted);
105   static inline intptr_t* frame_top(const frame& f);
106   static inline intptr_t* frame_bottom(const frame& f);
107 
108   static inline int size(const frame& f);
109   static inline int stack_argsize(const frame& f);
110   static inline int num_oops(const frame& f);
111 };
112 
113 class NonInterpretedUnknown : public NonInterpreted<NonInterpretedUnknown>  {
114 public:
115   DEBUG_ONLY(static const char* name;)
116   static const bool interpreted = false;
117 
118   template <typename FrameT> static bool is_instance(const FrameT& f);
119 };
120 
121 DEBUG_ONLY(const char* NonInterpretedUnknown::name = "NonInterpretedUnknown";)
122 
123 class Compiled : public NonInterpreted<Compiled>  {
124 public:
125   DEBUG_ONLY(static const char* name;)
126   static const bool interpreted = false;
127   static const bool stub = false;
128   static const int extra_oops = 1;
129   static const char type = 'c';
130 
131   template <typename RegisterMapT>
132   static bool is_owning_locks(JavaThread* thread, RegisterMapT* map, const frame& f);
133   static address deopt_original_pc(intptr_t* sp, address pc, CodeBlob* cb);
134 };
135 
136 DEBUG_ONLY(const char* Compiled::name = "Compiled";)
137 
138 class StubF : public NonInterpreted<StubF> {
139 public:
140   DEBUG_ONLY(static const char* name;)
141   static const bool interpreted = false;
142   static const bool stub = true;
143   static const int extra_oops = 0;
144   static const char type = 's';
145 };
146 
147 DEBUG_ONLY(const char* StubF::name = "Stub";)
148 
149 template<typename Self>
150 template <typename FrameT>
151 bool FrameCommon<Self>::is_instance(const FrameT& f) {
152   return (Self::interpreted == f.is_interpreted_frame()) && (Self::stub == (!Self::interpreted && is_stub(f.cb())));
153 }
154 
155 template <typename FrameT>
156 bool NonInterpretedUnknown::is_instance(const FrameT& f) {
157   return (interpreted == f.is_interpreted_frame());
158 }
159 
160 bool Frame::is_stub(CodeBlob* cb) {
161   return cb != nullptr && (cb->is_safepoint_stub() || cb->is_runtime_stub());
162 }
163 
164 inline Method* Frame::frame_method(const frame& f) {
165   return f.is_interpreted_frame() ? f.interpreter_frame_method() : f.cb()->as_compiled_method()->method();
166 }
167 
168 address Frame::return_pc(const frame& f) {
169   return *return_pc_address(f);
170 }
171 
172 #ifdef ASSERT
173 intptr_t* Frame::frame_top(const frame &f) {
174   if (f.is_interpreted_frame()) {
175     ResourceMark rm;
176     InterpreterOopMap mask;
177     f.interpreted_frame_oop_map(&mask);
178     return Interpreted::frame_top(f, &mask);
179   } else {
180     return Compiled::frame_top(f);
181   }
182 }
183 
184 char* Frame::method_name(Method* m) {
185   return m != nullptr ? m->name_and_sig_as_C_string() : nullptr;
186 }
187 
188 Method* Frame::top_java_frame_method(const frame& f) {
189   Method* m = nullptr;
190   if (f.is_interpreted_frame()) {
191     m = f.interpreter_frame_method();
192   } else if (f.is_compiled_frame()) {
193     CompiledMethod* cm = f.cb()->as_compiled_method();
194     ScopeDesc* scope = cm->scope_desc_at(f.pc());
195     m = scope->method();
196   } else if (f.is_native_frame()) {
197     m = f.cb()->as_nmethod()->method();
198   }
199 
200   return m;
201 }
202 
203 bool Frame::assert_bottom_java_frame_name(const frame& f, const char* name) {
204   ResourceMark rm;
205   bool res = (strcmp(bottom_java_frame_name(f), name) == 0);
206   assert (res, "name: %s", bottom_java_frame_name(f));
207   return res;
208 }
209 
210 bool Frame::is_deopt_return(address pc, const frame& sender) {
211   if (sender.is_interpreted_frame()) return false;
212 
213   CompiledMethod* cm = sender.cb()->as_compiled_method();
214   return cm->is_deopt_pc(pc);
215 }
216 
217 #endif
218 
219 address Interpreted::return_pc(const frame& f) {
220   return *return_pc_address(f);
221 }
222 
223 int Interpreted::size(const frame&f) {
224   return Interpreted::frame_bottom<true>(f) - Interpreted::frame_top(f);
225 }
226 
227 template <bool relative>
228 inline int Interpreted::stack_argsize(const frame& f) {
229   return f.interpreter_frame_method()->size_of_parameters();
230 }
231 
232 inline int Interpreted::expression_stack_size(const frame &f, InterpreterOopMap* mask) {
233   int size = mask->expression_stack_size();
234   assert (size <= f.interpreter_frame_expression_stack_size(), "size1: %d size2: %d", size, f.interpreter_frame_expression_stack_size());
235   return size;
236 }
237 
238 bool Interpreted::is_owning_locks(const frame& f) {
239   assert (f.interpreter_frame_monitor_end() <= f.interpreter_frame_monitor_begin(), "must be");
240   if (f.interpreter_frame_monitor_end() == f.interpreter_frame_monitor_begin())
241     return false;
242 
243   for (BasicObjectLock* current = f.previous_monitor_in_interpreter_frame(f.interpreter_frame_monitor_begin());
244         current >= f.interpreter_frame_monitor_end();
245         current = f.previous_monitor_in_interpreter_frame(current)) {
246 
247       oop obj = current->obj();
248       if (obj != nullptr) {
249         return true;
250       }
251   }
252   return false;
253 }
254 
255 inline intptr_t* Interpreted::frame_top(const frame& f) { // inclusive; this will be copied with the frame
256   return f.unextended_sp();
257 }
258 
259 int Interpreted::size(const frame&f, InterpreterOopMap* mask) {
260   return Interpreted::frame_bottom(f) - Interpreted::frame_top(f, mask);
261 }
262 
263 template<typename Self>
264 inline intptr_t* NonInterpreted<Self>::frame_top(const frame& f, int callee_argsize, bool callee_interpreted) {
265   return f.unextended_sp() + (callee_interpreted ? 0 : callee_argsize);
266 }
267 
268 template<typename Self>
269 inline intptr_t* NonInterpreted<Self>::frame_top(const frame& f) { // inclusive; this will be copied with the frame
270   return f.unextended_sp();
271 }
272 
273 template<typename Self>
274 inline intptr_t* NonInterpreted<Self>::frame_bottom(const frame& f) { // exclusive; this will not be copied with the frame
275   return f.unextended_sp() + f.cb()->frame_size();
276 }
277 
278 template<typename Self>
279 inline int NonInterpreted<Self>::size(const frame& f) {
280   assert (!f.is_interpreted_frame() && Self::is_instance(f), "");
281   return f.cb()->frame_size();
282 }
283 
284 template<typename Self>
285 inline int NonInterpreted<Self>::stack_argsize(const frame& f) {
286   return f.compiled_frame_stack_argsize();
287 }
288 
289 template<typename Self>
290 inline int NonInterpreted<Self>::num_oops(const frame& f) {
291   assert (!f.is_interpreted_frame() && Self::is_instance(f), "");
292   return f.num_oops() + Self::extra_oops;
293 }
294 
295 
296 address Compiled::deopt_original_pc(intptr_t* sp, address pc, CodeBlob* cb) {
297   // TODO DEOPT: unnecessary in the long term solution of unroll on freeze
298 
299   assert (cb != nullptr && cb->is_compiled(), "");
300   CompiledMethod* cm = cb->as_compiled_method();
301   if (cm->is_deopt_pc(pc)) {
302     pc = *(address*)((address)sp + cm->orig_pc_offset());
303     assert(pc != nullptr, "");
304     assert(cm->insts_contains_inclusive(pc), "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
305     assert(!cm->is_deopt_pc(pc), "");
306   }
307 
308   return pc;
309 }
310 
311 template<typename RegisterMapT>
312 bool Compiled::is_owning_locks(JavaThread* thread, RegisterMapT* map, const frame& f) {
313   assert (!f.is_interpreted_frame() && Compiled::is_instance(f), "");
314 
315   CompiledMethod* cm = f.cb()->as_compiled_method();
316   assert (!cm->is_compiled() || !cm->as_compiled_method()->is_native_method(), ""); // See compiledVFrame::compiledVFrame(...) in vframe_hp.cpp
317 
318   if (!cm->has_monitors()) return false;
319 
320   frame::update_map_with_saved_link(map, Frame::callee_link_address(f)); // the monitor object could be stored in the link register
321   ResourceMark rm;
322   for (ScopeDesc* scope = cm->scope_desc_at(f.pc()); scope != nullptr; scope = scope->sender()) {
323     GrowableArray<MonitorValue*>* mons = scope->monitors();
324     if (mons == nullptr || mons->is_empty())
325       continue;
326 
327     for (int index = (mons->length()-1); index >= 0; index--) { // see compiledVFrame::monitors()
328       MonitorValue* mon = mons->at(index);
329       if (mon->eliminated())
330         continue; // we ignore scalar-replaced monitors
331       ScopeValue* ov = mon->owner();
332       StackValue* owner_sv = StackValue::create_stack_value(&f, map, ov); // it is an oop
333       oop owner = owner_sv->get_obj()();
334       if (owner != nullptr) {
335         //assert(cm->has_monitors(), "");
336         return true;
337       }
338     }
339   }
340   return false;
341 }
342 
343 #include CPU_HEADER_INLINE(frame_helpers)
344 
345 #endif // SHARE_VM_RUNTIME_FRAME_HELPERS_INLINE_HPP