< prev index next >

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

Print this page
@@ -25,15 +25,23 @@
  #ifndef SHARE_RUNTIME_VFRAME_INLINE_HPP
  #define SHARE_RUNTIME_VFRAME_INLINE_HPP
  
  #include "runtime/vframe.hpp"
  
+ #include "oops/instanceStackChunkKlass.inline.hpp"
+ #include "runtime/handles.inline.hpp"
  #include "runtime/frame.inline.hpp"
  #include "runtime/thread.inline.hpp"
  
- inline vframeStreamCommon::vframeStreamCommon(JavaThread* thread, bool process_frames) : _reg_map(thread, false, process_frames) {
-   _thread = thread;
+ inline vframeStreamCommon::vframeStreamCommon(RegisterMap reg_map) : _reg_map(reg_map), _cont(NULL) {
+   _thread = _reg_map.thread();
+ }
+ 
+ inline oop vframeStreamCommon::continuation() const { 
+   if (_reg_map.cont() != NULL) return _reg_map.cont();
+   if (_cont != NULL)           return _cont->continuation();
+   return NULL;
  }
  
  inline intptr_t* vframeStreamCommon::frame_id() const        { return _frame.id(); }
  
  inline int vframeStreamCommon::vframe_id() const {

@@ -48,35 +56,65 @@
  
  inline bool vframeStreamCommon::is_interpreted_frame() const { return _frame.is_interpreted_frame(); }
  
  inline bool vframeStreamCommon::is_entry_frame() const       { return _frame.is_entry_frame(); }
  
+ extern "C" void pfl();
+ 
  inline void vframeStreamCommon::next() {
    // handle frames with inlining
    if (_mode == compiled_mode    && fill_in_compiled_inlined_sender()) return;
  
    // handle general case
    do {
-     _prev_frame = _frame;
+     bool cont_entry = false;
+     if (Continuation::is_continuation_enterSpecial(_frame)) {
+       assert (!_reg_map.in_cont(), "");
+       assert (_cont != NULL, "");
+       assert (_cont->cont_oop() != NULL, "_cont: " INTPTR_FORMAT, p2i(_cont));
+       cont_entry = true;
+       
+       oop scope = jdk_internal_vm_Continuation::scope(_cont->cont_oop());
+       if ((_continuation_scope.not_null() && scope == _continuation_scope()) || scope == java_lang_VirtualThread::vthread_scope()) {
+         _mode = at_end_mode;
+         break;
+       }
+     } else if (_reg_map.in_cont() && Continuation::is_continuation_entry_frame(_frame, &_reg_map)) {
+       assert (_reg_map.cont() != NULL, "");
+       oop scope = jdk_internal_vm_Continuation::scope(_reg_map.cont());
+       if ((_continuation_scope.not_null() && scope == _continuation_scope()) || scope == java_lang_VirtualThread::vthread_scope()) {
+         _mode = at_end_mode;
+         break;
+       }      
+     }
+ 
      _frame = _frame.sender(&_reg_map);
+     
+     if (cont_entry) {
+       _cont = _cont->parent();
+     }
    } while (!fill_from_frame());
  }
  
- inline vframeStream::vframeStream(JavaThread* thread, bool stop_at_java_call_stub, bool process_frame)
-   : vframeStreamCommon(thread, process_frame /* process_frames */) {
+ inline vframeStream::vframeStream(JavaThread* thread, bool stop_at_java_call_stub, bool process_frame, bool vthread_carrier)
+   : vframeStreamCommon(RegisterMap(thread, true, process_frame, true)) {
    _stop_at_java_call_stub = stop_at_java_call_stub;
  
    if (!thread->has_last_Java_frame()) {
      _mode = at_end_mode;
      return;
    }
  
-   _frame = _thread->last_frame();
+   _frame = vthread_carrier ? _thread->vthread_carrier_last_frame(&_reg_map) : _thread->last_frame();
+   _cont = _thread->last_continuation();
    while (!fill_from_frame()) {
-     _prev_frame = _frame;
+     if (_cont != NULL && Continuation::is_continuation_enterSpecial(_frame)) {
+       _cont = _cont->parent();
+     }
      _frame = _frame.sender(&_reg_map);
    }
+   // assert (_reg_map.stack_chunk()() == (stackChunkOop)NULL, "map.chunk: " INTPTR_FORMAT, p2i((stackChunkOopDesc*)_reg_map.stack_chunk()()));
  }
  
  inline bool vframeStreamCommon::fill_in_compiled_inlined_sender() {
    if (_sender_decode_offset == DebugInformationRecorder::serialized_null) {
      return false;

@@ -139,19 +177,25 @@
    _method = nm()->method();
    _bci = 0;
  }
  
  inline bool vframeStreamCommon::fill_from_frame() {
+   if (_frame.is_empty()) {
+     _mode = at_end_mode;
+     return true;
+   }
+ 
    // Interpreted frame
    if (_frame.is_interpreted_frame()) {
      fill_from_interpreter_frame();
      return true;
    }
  
    // Compiled frame
  
    if (cb() != NULL && cb()->is_compiled()) {
+     assert (nm()->method() != NULL, "must be");
      if (nm()->is_native_method()) {
        // Do not rely on scopeDesc since the pc might be unprecise due to the _last_native_pc trick.
        fill_from_compiled_native_frame();
      } else {
        PcDesc* pc_desc = nm()->pc_desc_at(_frame.pc());

@@ -171,11 +215,11 @@
          // asserting. If however the thread is safepoint safe this
          // is the sign of a compiler bug  and we'll let
          // fill_from_compiled_frame handle it.
  
  
-         JavaThreadState state = _thread->thread_state();
+         JavaThreadState state = _thread != NULL ? _thread->thread_state() : _thread_in_Java;
  
          // in_Java should be good enough to test safepoint safety
          // if state were say in_Java_trans then we'd expect that
          // the pc would have already been slightly adjusted to
          // one that would produce a pcDesc since the trans state

@@ -203,10 +247,11 @@
          decode_offset = DebugInformationRecorder::serialized_null;
        } else {
          decode_offset = pc_desc->scope_decode_offset();
        }
        fill_from_compiled_frame(decode_offset);
+ 
        _vframe_id = 0;
      }
      return true;
    }
  

@@ -219,13 +264,20 @@
    return false;
  }
  
  
  inline void vframeStreamCommon::fill_from_interpreter_frame() {
-   Method* method = _frame.interpreter_frame_method();
-   address   bcp    = _frame.interpreter_frame_bcp();
-   int       bci    = method->validate_bci_from_bcp(bcp);
+   Method* method;
+   address bcp;
+   if (!_reg_map.in_cont()) {
+     method = _frame.interpreter_frame_method();
+     bcp    = _frame.interpreter_frame_bcp();
+   } else {
+     method = _reg_map.stack_chunk()->interpreter_frame_method(_frame);
+     bcp    = _reg_map.stack_chunk()->interpreter_frame_bcp(_frame);
+   }
+   int bci  = method->validate_bci_from_bcp(bcp);
    // 6379830 AsyncGetCallTrace sometimes feeds us wild frames.
    // AsyncGetCallTrace interrupts the VM asynchronously. As a result
    // it is possible to access an interpreter frame for which
    // no Java-level information is yet available (e.g., becasue
    // the frame was being created when the VM interrupted it).
< prev index next >