< prev index next >

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

Print this page

        

@@ -23,18 +23,25 @@
  */
 
 #ifndef SHARE_RUNTIME_VFRAME_INLINE_HPP
 #define SHARE_RUNTIME_VFRAME_INLINE_HPP
 
+#include "classfile/javaClasses.inline.hpp"
+#include "runtime/handles.inline.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/handles.inline.hpp"
 #include "runtime/vframe.hpp"
 
 inline vframeStreamCommon::vframeStreamCommon(JavaThread* thread) : _reg_map(thread, false) {
   _thread = thread;
 }
 
+inline vframeStreamCommon::vframeStreamCommon(RegisterMap reg_map) : _reg_map(reg_map) {
+  _thread = _reg_map.thread();
+}
+
 inline intptr_t* vframeStreamCommon::frame_id() const        { return _frame.id(); }
 
 inline bool vframeStreamCommon::is_interpreted_frame() const { return _frame.is_interpreted_frame(); }
 
 inline bool vframeStreamCommon::is_entry_frame() const       { return _frame.is_entry_frame(); }

@@ -43,29 +50,58 @@
   // handle frames with inlining
   if (_mode == compiled_mode    && fill_in_compiled_inlined_sender()) return;
 
   // handle general case
   do {
+    assert (_continuation_scope.is_null() || _cont.not_null(), "must be");
+    bool cont_entry = false;
+    oop cont = (oop)NULL;
+    if (_cont.not_null() && Continuation::is_continuation_entry_frame(_frame, &_reg_map)) {
+      cont_entry = true;
+      cont = _cont();
+      oop scope = java_lang_Continuation::scope(cont);
+
+      // *(_cont.raw_value()) = java_lang_Continuation::parent(_cont());
+
+      if (_continuation_scope.not_null() && oopDesc::equals(scope, _continuation_scope())) {
+        assert (Continuation::is_frame_in_continuation(_frame, cont), "");
+        _mode = at_end_mode;
+        break;
+      }
+    }
+
     _prev_frame = _frame;
     _frame = _frame.sender(&_reg_map);
+    
+    if (cont_entry) {
+      *(_cont.raw_value()) = java_lang_Continuation::parent(cont);
+      assert (_reg_map.cont() == (oop)NULL || oopDesc::equals(_cont(), _reg_map.cont()), 
+        "map.cont: " INTPTR_FORMAT " vframeStream: " INTPTR_FORMAT, 
+        p2i((oopDesc*)_reg_map.cont()), p2i((oopDesc*)_cont()));
+    }
   } while (!fill_from_frame());
 }
 
 inline vframeStream::vframeStream(JavaThread* thread, bool stop_at_java_call_stub)
-  : vframeStreamCommon(thread) {
+  : vframeStreamCommon(RegisterMap(thread, false, 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();
+  oop cont = _thread->last_continuation();
   while (!fill_from_frame()) {
+    if (cont != (oop)NULL && Continuation::is_continuation_entry_frame(_frame, &_reg_map)) {
+      cont = java_lang_Continuation::parent(cont);
+    }
     _prev_frame = _frame;
     _frame = _frame.sender(&_reg_map);
   }
+  _cont = cont != (oop)NULL ? Handle(Thread::current(), cont) : Handle();
 }
 
 inline bool vframeStreamCommon::fill_in_compiled_inlined_sender() {
   if (_sender_decode_offset == DebugInformationRecorder::serialized_null) {
     return false;

@@ -128,19 +164,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());

@@ -160,11 +202,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

@@ -192,10 +234,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;
   }
 

@@ -208,12 +251,19 @@
   return false;
 }
 
 
 inline void vframeStreamCommon::fill_from_interpreter_frame() {
-  Method* method = _frame.interpreter_frame_method();
-  address   bcp    = _frame.interpreter_frame_bcp();
+  Method* method;
+  address bcp;
+  if (!_reg_map.in_cont()) {
+    method = _frame.interpreter_frame_method();
+    bcp    = _frame.interpreter_frame_bcp();
+  } else {
+    method = Continuation::interpreter_frame_method(_frame, &_reg_map);
+    bcp    = Continuation::interpreter_frame_bcp(_frame, &_reg_map);
+  }
   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
< prev index next >