< prev index next >

src/hotspot/share/runtime/stackChunkFrameStream.inline.hpp

Print this page

 89   }
 90   DEBUG_ONLY(else _unextended_sp = nullptr;)
 91   assert(_sp >= chunk->start_address(), "");
 92   assert(_sp <= chunk->end_address() + frame::metadata_words, "");
 93 
 94   if (f.cb() != nullptr) {
 95     _oopmap = nullptr;
 96     _cb = f.cb();
 97   } else {
 98     get_cb();
 99   }
100 
101   if (is_stub()) {
102     get_oopmap(pc(), 0);
103     DEBUG_ONLY(_has_stub = true);
104   } DEBUG_ONLY(else _has_stub = false;)
105 }
106 
107 template <ChunkFrames frame_kind>
108 inline bool StackChunkFrameStream<frame_kind>::is_stub() const {
109   return cb() != nullptr && (_cb->is_safepoint_stub() || _cb->is_runtime_stub());
110 }
111 
112 template <ChunkFrames frame_kind>
113 inline bool StackChunkFrameStream<frame_kind>::is_compiled() const {
114   return cb() != nullptr && _cb->is_nmethod();
115 }
116 
117 template <>
118 inline bool StackChunkFrameStream<ChunkFrames::Mixed>::is_interpreted() const {
119   return !is_done() && Interpreter::contains(pc());
120 }
121 
122 template <>
123 inline bool StackChunkFrameStream<ChunkFrames::CompiledOnly>::is_interpreted() const {
124   return false;
125 }
126 
127 // StackChunkFrameStream<frame_kind>::frame_size() returns the words required to
128 // store the given frame as the only frame in a StackChunk. This is the size of the
129 // frame itself plus its stack arguments plus metadata at the caller's frame top (1)

179   return is_interpreted() ? interpreter_frame_size()
180                           : cb()->frame_size() + stack_argsize() + frame::metadata_words_at_top;
181 }
182 
183 template <ChunkFrames frame_kind>
184 inline int StackChunkFrameStream<frame_kind>::stack_argsize() const {
185   if (is_interpreted()) {
186     return interpreter_frame_stack_argsize();
187   }
188   if (is_stub()) {
189     return 0;
190   }
191   assert(cb() != nullptr, "");
192   assert(cb()->is_nmethod(), "");
193   assert(cb()->as_nmethod()->method() != nullptr, "");
194   return (cb()->as_nmethod()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord;
195 }
196 
197 template <ChunkFrames frame_kind>
198 inline int StackChunkFrameStream<frame_kind>::num_oops() const {
199   return is_interpreted() ? interpreter_frame_num_oops() : oopmap()->num_oops();







200 }
201 
202 template <ChunkFrames frame_kind>
203 inline void StackChunkFrameStream<frame_kind>::initialize_register_map(RegisterMap* map) {
204   update_reg_map_pd(map);
205 }
206 
207 template <ChunkFrames frame_kind>
208 template <typename RegisterMapT>
209 inline void StackChunkFrameStream<frame_kind>::next(RegisterMapT* map, bool stop) {
210   update_reg_map(map);
211   bool safepoint = is_stub();
212   if (frame_kind == ChunkFrames::Mixed) {
213     if (is_interpreted()) {
214       next_for_interpreter_frame();
215     } else {
216       _sp = _unextended_sp + cb()->frame_size();
217       if (_sp >= _end - frame::metadata_words) {
218         _sp = _end;
219       }
220       _unextended_sp = is_interpreted() ? unextended_sp_for_interpreter_frame() : _sp;
221     }
222     assert(_unextended_sp >= _sp - frame::metadata_words, "");
223   } else {
224     _sp += cb()->frame_size();
225   }
226   assert(!is_interpreted() || _unextended_sp == unextended_sp_for_interpreter_frame(), "");
227 
228   DEBUG_ONLY(_index++;)
229   if (stop) {
230     return;
231   }
232 
233   get_cb();
234   update_reg_map_pd(map);
235   if (safepoint && cb() != nullptr) { // there's no post-call nop and no fast oopmap lookup
236     _oopmap = cb()->oop_map_for_return_address(pc());
237   }
238 }
239 
240 template <ChunkFrames frame_kind>
241 inline void StackChunkFrameStream<frame_kind>::get_cb() {
242   _oopmap = nullptr;
243   if (is_done() || is_interpreted()) {
244     _cb = nullptr;
245     return;
246   }
247 
248   assert(pc() != nullptr, "");
249   assert(dbg_is_safe(pc(), -1), "");
250 
251   _cb = CodeCache::find_blob_fast(pc());
252 
253   assert(_cb != nullptr, "");
254   assert(is_interpreted() || ((is_stub() || is_compiled()) && _cb->frame_size() > 0), "");
255 }
256 

283 template <typename RegisterMapT>
284 inline void* StackChunkFrameStream<frame_kind>::reg_to_loc(VMReg reg, const RegisterMapT* map) const {
285   assert(!is_done(), "");
286   return reg->is_reg() ? (void*)map->location(reg, sp()) // see frame::update_map_with_saved_link(&map, link_addr);
287                        : (void*)((address)unextended_sp() + (reg->reg2stack() * VMRegImpl::stack_slot_size));
288 }
289 
290 template<>
291 template<>
292 inline void StackChunkFrameStream<ChunkFrames::Mixed>::update_reg_map(RegisterMap* map) {
293   assert(!map->in_cont() || map->stack_chunk() == _chunk, "");
294   if (map->update_map() && is_stub()) {
295     frame f = to_frame();
296     oopmap()->update_register_map(&f, map); // we have callee-save registers in this case
297   }
298 }
299 
300 template<>
301 template<>
302 inline void StackChunkFrameStream<ChunkFrames::CompiledOnly>::update_reg_map(RegisterMap* map) {
303   assert(map->in_cont(), "");
304   assert(map->stack_chunk()() == _chunk, "");
305   if (map->update_map()) {
306     frame f = to_frame();
307     oopmap()->update_register_map(&f, map); // we have callee-save registers in this case
308   }
309 }
310 
311 template <ChunkFrames frame_kind>
312 template <typename RegisterMapT>
313 inline void StackChunkFrameStream<frame_kind>::update_reg_map(RegisterMapT* map) {}
314 
315 template <ChunkFrames frame_kind>
316 inline address StackChunkFrameStream<frame_kind>::orig_pc() const {
317   address pc1 = pc();
318   if (is_interpreted() || is_stub()) {
319     return pc1;
320   }
321   nmethod* nm = cb()->as_nmethod();
322   if (nm->is_deopt_pc(pc1)) {
323     pc1 = *(address*)((address)unextended_sp() + nm->orig_pc_offset());
324   }
325 

 89   }
 90   DEBUG_ONLY(else _unextended_sp = nullptr;)
 91   assert(_sp >= chunk->start_address(), "");
 92   assert(_sp <= chunk->end_address() + frame::metadata_words, "");
 93 
 94   if (f.cb() != nullptr) {
 95     _oopmap = nullptr;
 96     _cb = f.cb();
 97   } else {
 98     get_cb();
 99   }
100 
101   if (is_stub()) {
102     get_oopmap(pc(), 0);
103     DEBUG_ONLY(_has_stub = true);
104   } DEBUG_ONLY(else _has_stub = false;)
105 }
106 
107 template <ChunkFrames frame_kind>
108 inline bool StackChunkFrameStream<frame_kind>::is_stub() const {
109   return cb() != nullptr && _cb->is_runtime_stub();
110 }
111 
112 template <ChunkFrames frame_kind>
113 inline bool StackChunkFrameStream<frame_kind>::is_compiled() const {
114   return cb() != nullptr && _cb->is_nmethod();
115 }
116 
117 template <>
118 inline bool StackChunkFrameStream<ChunkFrames::Mixed>::is_interpreted() const {
119   return !is_done() && Interpreter::contains(pc());
120 }
121 
122 template <>
123 inline bool StackChunkFrameStream<ChunkFrames::CompiledOnly>::is_interpreted() const {
124   return false;
125 }
126 
127 // StackChunkFrameStream<frame_kind>::frame_size() returns the words required to
128 // store the given frame as the only frame in a StackChunk. This is the size of the
129 // frame itself plus its stack arguments plus metadata at the caller's frame top (1)

179   return is_interpreted() ? interpreter_frame_size()
180                           : cb()->frame_size() + stack_argsize() + frame::metadata_words_at_top;
181 }
182 
183 template <ChunkFrames frame_kind>
184 inline int StackChunkFrameStream<frame_kind>::stack_argsize() const {
185   if (is_interpreted()) {
186     return interpreter_frame_stack_argsize();
187   }
188   if (is_stub()) {
189     return 0;
190   }
191   assert(cb() != nullptr, "");
192   assert(cb()->is_nmethod(), "");
193   assert(cb()->as_nmethod()->method() != nullptr, "");
194   return (cb()->as_nmethod()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord;
195 }
196 
197 template <ChunkFrames frame_kind>
198 inline int StackChunkFrameStream<frame_kind>::num_oops() const {
199   if (is_interpreted()) {
200     return interpreter_frame_num_oops();
201   } else if (is_compiled()) {
202     return oopmap()->num_oops();
203   } else {
204     assert(is_stub(), "invariant");
205     return 0;
206   }
207 }
208 
209 template <ChunkFrames frame_kind>
210 inline void StackChunkFrameStream<frame_kind>::initialize_register_map(RegisterMap* map) {
211   update_reg_map_pd(map);
212 }
213 
214 template <ChunkFrames frame_kind>
215 template <typename RegisterMapT>
216 inline void StackChunkFrameStream<frame_kind>::next(RegisterMapT* map, bool stop) {
217   update_reg_map(map);
218   bool safepoint = is_stub();
219   if (frame_kind == ChunkFrames::Mixed) {
220     if (is_interpreted()) {
221       next_for_interpreter_frame();
222     } else {
223       _sp = _unextended_sp + cb()->frame_size();
224       if (_sp >= _end - frame::metadata_words) {
225         _sp = _end;
226       }
227       _unextended_sp = is_interpreted() ? unextended_sp_for_interpreter_frame() : _sp;
228     }
229     assert(_unextended_sp >= _sp - frame::metadata_words, "");
230   } else {
231     _sp += cb()->frame_size();
232   }
233   assert(!is_interpreted() || _unextended_sp == unextended_sp_for_interpreter_frame(), "");
234 
235   DEBUG_ONLY(_index++;)
236   if (stop) {
237     return;
238   }
239 
240   get_cb();
241   update_reg_map_pd(map);
242   if (safepoint && cb() != nullptr) { // there's no post-call nop and no fast oopmap lookup
243     _oopmap = cb()->oop_map_for_return_address(orig_pc());
244   }
245 }
246 
247 template <ChunkFrames frame_kind>
248 inline void StackChunkFrameStream<frame_kind>::get_cb() {
249   _oopmap = nullptr;
250   if (is_done() || is_interpreted()) {
251     _cb = nullptr;
252     return;
253   }
254 
255   assert(pc() != nullptr, "");
256   assert(dbg_is_safe(pc(), -1), "");
257 
258   _cb = CodeCache::find_blob_fast(pc());
259 
260   assert(_cb != nullptr, "");
261   assert(is_interpreted() || ((is_stub() || is_compiled()) && _cb->frame_size() > 0), "");
262 }
263 

290 template <typename RegisterMapT>
291 inline void* StackChunkFrameStream<frame_kind>::reg_to_loc(VMReg reg, const RegisterMapT* map) const {
292   assert(!is_done(), "");
293   return reg->is_reg() ? (void*)map->location(reg, sp()) // see frame::update_map_with_saved_link(&map, link_addr);
294                        : (void*)((address)unextended_sp() + (reg->reg2stack() * VMRegImpl::stack_slot_size));
295 }
296 
297 template<>
298 template<>
299 inline void StackChunkFrameStream<ChunkFrames::Mixed>::update_reg_map(RegisterMap* map) {
300   assert(!map->in_cont() || map->stack_chunk() == _chunk, "");
301   if (map->update_map() && is_stub()) {
302     frame f = to_frame();
303     oopmap()->update_register_map(&f, map); // we have callee-save registers in this case
304   }
305 }
306 
307 template<>
308 template<>
309 inline void StackChunkFrameStream<ChunkFrames::CompiledOnly>::update_reg_map(RegisterMap* map) {
310   assert(!map->in_cont() || map->stack_chunk() == _chunk, "");
311   if (map->update_map() && is_stub()) {

312     frame f = to_frame();
313     oopmap()->update_register_map(&f, map); // we have callee-save registers in this case
314   }
315 }
316 
317 template <ChunkFrames frame_kind>
318 template <typename RegisterMapT>
319 inline void StackChunkFrameStream<frame_kind>::update_reg_map(RegisterMapT* map) {}
320 
321 template <ChunkFrames frame_kind>
322 inline address StackChunkFrameStream<frame_kind>::orig_pc() const {
323   address pc1 = pc();
324   if (is_interpreted() || is_stub()) {
325     return pc1;
326   }
327   nmethod* nm = cb()->as_nmethod();
328   if (nm->is_deopt_pc(pc1)) {
329     pc1 = *(address*)((address)unextended_sp() + nm->orig_pc_offset());
330   }
331 
< prev index next >