< prev index next >

src/hotspot/share/runtime/vframe.cpp

Print this page
*** 20,10 ***
--- 20,11 ---
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   *
   */
  
+ #include "oops/stackChunkOop.hpp"
  #include "precompiled.hpp"
  #include "classfile/javaClasses.inline.hpp"
  #include "classfile/javaThreadStatus.hpp"
  #include "classfile/vmClasses.hpp"
  #include "classfile/vmSymbols.hpp"

*** 37,10 ***
--- 38,11 ---
  #include "memory/resourceArea.hpp"
  #include "oops/instanceKlass.hpp"
  #include "oops/oop.inline.hpp"
  #include "prims/jvmtiExport.hpp"
  #include "runtime/frame.inline.hpp"
+ #include "runtime/globals.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/objectMonitor.hpp"
  #include "runtime/objectMonitor.inline.hpp"
  #include "runtime/osThread.hpp"
  #include "runtime/signature.hpp"

*** 51,19 ***
  #include "runtime/vframe.inline.hpp"
  #include "runtime/vframeArray.hpp"
  #include "runtime/vframe_hp.hpp"
  
  vframe::vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread)
! : _reg_map(reg_map), _thread(thread) {
    assert(fr != NULL, "must have frame");
    _fr = *fr;
  }
  
  vframe::vframe(const frame* fr, JavaThread* thread)
! : _reg_map(thread), _thread(thread) {
    assert(fr != NULL, "must have frame");
    _fr = *fr;
  }
  
  vframe* vframe::new_vframe(StackFrameStream& fst, JavaThread* thread) {
    if (fst.current()->is_runtime_frame()) {
      fst.next();
--- 53,21 ---
  #include "runtime/vframe.inline.hpp"
  #include "runtime/vframeArray.hpp"
  #include "runtime/vframe_hp.hpp"
  
  vframe::vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread)
! : _reg_map(reg_map), _thread(thread), 
+   _chunk(Thread::current(), reg_map->stack_chunk()(), reg_map->stack_chunk().not_null()) {
    assert(fr != NULL, "must have frame");
    _fr = *fr;
  }
  
  vframe::vframe(const frame* fr, JavaThread* thread)
! : _reg_map(thread), _thread(thread), _chunk() {
    assert(fr != NULL, "must have frame");
    _fr = *fr;
+   assert (!_reg_map.in_cont(), "");
  }
  
  vframe* vframe::new_vframe(StackFrameStream& fst, JavaThread* thread) {
    if (fst.current()->is_runtime_frame()) {
      fst.next();

*** 104,13 ***
--- 108,18 ---
  }
  
  vframe* vframe::sender() const {
    RegisterMap temp_map = *register_map();
    assert(is_top(), "just checking");
+   if (_fr.is_empty()) return NULL;
    if (_fr.is_entry_frame() && _fr.is_first_frame()) return NULL;
    frame s = _fr.real_sender(&temp_map);
    if (s.is_first_frame()) return NULL;
+   if (Continuation::is_continuation_enterSpecial(s)) {
+     if (Continuation::continuation_scope(Continuation::get_continuation_for_frame(temp_map.thread(), _fr)) == java_lang_VirtualThread::vthread_scope())
+       return NULL;
+   }
    return vframe::new_vframe(&s, &temp_map, thread());
  }
  
  vframe* vframe::top() const {
    vframe* vf = (vframe*) this;

*** 120,16 ***
  
  
  javaVFrame* vframe::java_sender() const {
    vframe* f = sender();
    while (f != NULL) {
!     if (f->is_java_frame()) return javaVFrame::cast(f);
      f = f->sender();
    }
    return NULL;
  }
  
  // ------------- javaVFrame --------------
  
  GrowableArray<MonitorInfo*>* javaVFrame::locked_monitors() {
    assert(SafepointSynchronize::is_at_safepoint() || JavaThread::current() == thread(),
           "must be at safepoint or it's a java frame of the current thread");
--- 129,29 ---
  
  
  javaVFrame* vframe::java_sender() const {
    vframe* f = sender();
    while (f != NULL) {
!     if (f->is_java_frame() && !javaVFrame::cast(f)->method()->is_continuation_enter_intrinsic()) return javaVFrame::cast(f);
      f = f->sender();
    }
    return NULL;
  }
  
+ extern "C" bool dbg_is_safe(const void* p, intptr_t errvalue);
+ 
+ void vframe::restore_register_map() const {
+   assert (this != NULL, "");
+   assert (dbg_is_safe(this, -1), "");
+   assert (register_map() != NULL, "");
+   assert (dbg_is_safe(register_map(), -1), "");
+ 
+   if (_reg_map.stack_chunk()() != stack_chunk()) {
+     const_cast<vframe*>(this)->_reg_map.set_stack_chunk(stack_chunk());
+   }
+ }
+ 
  // ------------- javaVFrame --------------
  
  GrowableArray<MonitorInfo*>* javaVFrame::locked_monitors() {
    assert(SafepointSynchronize::is_at_safepoint() || JavaThread::current() == thread(),
           "must be at safepoint or it's a java frame of the current thread");

*** 275,52 ***
  }
  
  // ------------- interpretedVFrame --------------
  
  u_char* interpretedVFrame::bcp() const {
!   return fr().interpreter_frame_bcp();
  }
  
  void interpretedVFrame::set_bcp(u_char* bcp) {
    fr().interpreter_frame_set_bcp(bcp);
  }
  
  intptr_t* interpretedVFrame::locals_addr_at(int offset) const {
    assert(fr().is_interpreted_frame(), "frame should be an interpreted frame");
    return fr().interpreter_frame_local_at(offset);
  }
  
  
  GrowableArray<MonitorInfo*>* interpretedVFrame::monitors() const {
    GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(5);
!   for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin()));
!        current >= fr().interpreter_frame_monitor_end();
!        current = fr().previous_monitor_in_interpreter_frame(current)) {
!     result->push(new MonitorInfo(current->obj(), current->lock(), false, false));
    }
    return result;
  }
  
  int interpretedVFrame::bci() const {
    return method()->bci_from(bcp());
  }
  
  Method* interpretedVFrame::method() const {
!   return fr().interpreter_frame_method();
  }
  
  static StackValue* create_stack_value_from_oop_map(const InterpreterOopMap& oop_mask,
                                                     int index,
!                                                    const intptr_t* const addr) {
  
    assert(index >= 0 &&
           index < oop_mask.number_of_entries(), "invariant");
  
    // categorize using oop_mask
    if (oop_mask.is_oop(index)) {
      // reference (oop) "r"
!     Handle h(Thread::current(), addr != NULL ? (*(oop*)addr) : (oop)NULL);
      return new StackValue(h);
    }
    // value (integer) "v"
    return new StackValue(addr != NULL ? *addr : 0);
  }
--- 297,66 ---
  }
  
  // ------------- interpretedVFrame --------------
  
  u_char* interpretedVFrame::bcp() const {
!   return stack_chunk() == NULL ? fr().interpreter_frame_bcp() : stack_chunk()->interpreter_frame_bcp(fr());
  }
  
  void interpretedVFrame::set_bcp(u_char* bcp) {
+   assert (stack_chunk() == NULL, ""); // unsupported for now because seems to be unused
    fr().interpreter_frame_set_bcp(bcp);
  }
  
  intptr_t* interpretedVFrame::locals_addr_at(int offset) const {
+   assert (stack_chunk() == NULL, ""); // unsupported for now because seems to be unused
    assert(fr().is_interpreted_frame(), "frame should be an interpreted frame");
    return fr().interpreter_frame_local_at(offset);
  }
  
  
  GrowableArray<MonitorInfo*>* interpretedVFrame::monitors() const {
    GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(5);
!   if (stack_chunk() == NULL) { // no monitors in continuations
!     for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin()));
!         current >= fr().interpreter_frame_monitor_end();
!         current = fr().previous_monitor_in_interpreter_frame(current)) {
+       result->push(new MonitorInfo(current->obj(), current->lock(), false, false));
+     }
    }
    return result;
  }
  
  int interpretedVFrame::bci() const {
    return method()->bci_from(bcp());
  }
  
  Method* interpretedVFrame::method() const {
!   // assert ((stack_chunk() != NULL) == register_map()->in_cont(), "_in_cont: %d register_map()->in_cont(): %d", stack_chunk() != NULL, register_map()->in_cont());
+   return stack_chunk() == NULL ? fr().interpreter_frame_method() : stack_chunk()->interpreter_frame_method(fr());
  }
  
  static StackValue* create_stack_value_from_oop_map(const InterpreterOopMap& oop_mask,
                                                     int index,
!                                                    const intptr_t* const addr,
+                                                    stackChunkOop chunk) {
  
    assert(index >= 0 &&
           index < oop_mask.number_of_entries(), "invariant");
  
    // categorize using oop_mask
    if (oop_mask.is_oop(index)) {
+     oop obj = NULL;
+     if (addr != NULL) {
+       if (chunk != NULL) {
+         obj = (chunk->has_bitmap() && UseCompressedOops) ? (oop)HeapAccess<>::oop_load((narrowOop*)addr) : HeapAccess<>::oop_load((oop*)addr);
+       } else {
+         obj = *(oop*)addr;
+       }
+     }
      // reference (oop) "r"
!     Handle h(Thread::current(), obj);
      return new StackValue(h);
    }
    // value (integer) "v"
    return new StackValue(addr != NULL ? *addr : 0);
  }

*** 339,45 ***
  }
  
  static void stack_locals(StackValueCollection* result,
                           int length,
                           const InterpreterOopMap& oop_mask,
!                          const frame& fr) {
  
    assert(result != NULL, "invariant");
  
    for (int i = 0; i < length; ++i) {
!     const intptr_t* const addr = fr.interpreter_frame_local_at(i);
      assert(addr != NULL, "invariant");
-     assert(addr >= fr.sp(), "must be inside the frame");
  
!     StackValue* const sv = create_stack_value_from_oop_map(oop_mask, i, addr);
      assert(sv != NULL, "sanity check");
  
      result->add(sv);
    }
  }
  
  static void stack_expressions(StackValueCollection* result,
                                int length,
                                int max_locals,
                                const InterpreterOopMap& oop_mask,
!                               const frame& fr) {
  
    assert(result != NULL, "invariant");
  
    for (int i = 0; i < length; ++i) {
!     const intptr_t* addr = fr.interpreter_frame_expression_stack_at(i);
!     assert(addr != NULL, "invariant");
!     if (!is_in_expression_stack(fr, addr)) {
!       // Need to ensure no bogus escapes.
!       addr = NULL;
      }
  
      StackValue* const sv = create_stack_value_from_oop_map(oop_mask,
                                                             i + max_locals,
!                                                            addr);
      assert(sv != NULL, "sanity check");
  
      result->add(sv);
    }
  }
--- 375,58 ---
  }
  
  static void stack_locals(StackValueCollection* result,
                           int length,
                           const InterpreterOopMap& oop_mask,
!                          const frame& fr,
+                          const stackChunkOop chunk) {
  
    assert(result != NULL, "invariant");
  
    for (int i = 0; i < length; ++i) {
!     const intptr_t* addr;
+     if (chunk == NULL) {
+       addr = fr.interpreter_frame_local_at(i);
+       assert(addr >= fr.sp(), "must be inside the frame");
+     } else {
+       addr = chunk->interpreter_frame_local_at(fr, i);
+     }
      assert(addr != NULL, "invariant");
  
!     StackValue* const sv = create_stack_value_from_oop_map(oop_mask, i, addr, chunk);
      assert(sv != NULL, "sanity check");
  
      result->add(sv);
    }
  }
  
  static void stack_expressions(StackValueCollection* result,
                                int length,
                                int max_locals,
                                const InterpreterOopMap& oop_mask,
!                               const frame& fr,
+                               const stackChunkOop chunk) {
  
    assert(result != NULL, "invariant");
  
    for (int i = 0; i < length; ++i) {
!     const intptr_t* addr;
!     if (chunk == NULL) {
!       addr = fr.interpreter_frame_expression_stack_at(i);
!       assert(addr != NULL, "invariant");
!       if (!is_in_expression_stack(fr, addr)) {
+         // Need to ensure no bogus escapes.
+         addr = NULL;
+       }
+     } else {
+       addr = chunk->interpreter_frame_expression_stack_at(fr, i);
      }
  
      StackValue* const sv = create_stack_value_from_oop_map(oop_mask,
                                                             i + max_locals,
!                                                            addr,
+                                                            chunk);
      assert(sv != NULL, "sanity check");
  
      result->add(sv);
    }
  }

*** 422,13 ***
    if (0 == length) {
      return result;
    }
  
    if (expressions) {
!     stack_expressions(result, length, max_locals, oop_mask, fr());
    } else {
!     stack_locals(result, length, oop_mask, fr());
    }
  
    assert(length == result->size(), "invariant");
  
    return result;
--- 471,13 ---
    if (0 == length) {
      return result;
    }
  
    if (expressions) {
!     stack_expressions(result, length, max_locals, oop_mask, fr(), stack_chunk());
    } else {
!     stack_locals(result, length, oop_mask, fr(), stack_chunk());
    }
  
    assert(length == result->size(), "invariant");
  
    return result;

*** 490,19 ***
  }
  #endif
  
  // top-frame will be skipped
  vframeStream::vframeStream(JavaThread* thread, frame top_frame,
!                            bool stop_at_java_call_stub) :
!     vframeStreamCommon(thread, true /* process_frames */) {
    _stop_at_java_call_stub = stop_at_java_call_stub;
  
    // skip top frame, as it may not be at safepoint
-   _prev_frame = top_frame;
    _frame  = top_frame.sender(&_reg_map);
    while (!fill_from_frame()) {
!     _prev_frame = _frame;
      _frame = _frame.sender(&_reg_map);
    }
  }
  
  
--- 539,57 ---
  }
  #endif
  
  // top-frame will be skipped
  vframeStream::vframeStream(JavaThread* thread, frame top_frame,
!                           bool stop_at_java_call_stub) : 
!     vframeStreamCommon(RegisterMap(thread, true, true, true)) {
    _stop_at_java_call_stub = stop_at_java_call_stub;
  
    // skip top frame, as it may not be at safepoint
    _frame  = top_frame.sender(&_reg_map);
    while (!fill_from_frame()) {
!     _frame = _frame.sender(&_reg_map);
+   }
+ }
+ 
+ vframeStream::vframeStream(JavaThread* thread, Handle continuation_scope, bool stop_at_java_call_stub) 
+  : vframeStreamCommon(RegisterMap(thread, true, true, true)) {
+ 
+   _stop_at_java_call_stub = stop_at_java_call_stub;
+   _continuation_scope = continuation_scope;
+   
+   if (!thread->has_last_Java_frame()) {
+     _mode = at_end_mode;
+     return;
+   }
+ 
+   _frame = _thread->last_frame();
+   _cont = _thread->last_continuation();
+   while (!fill_from_frame()) {
+     if (Continuation::is_continuation_enterSpecial(_frame)) {
+       assert (_cont != NULL, "");
+       _cont = _cont->parent();
+     }
+     _frame = _frame.sender(&_reg_map);
+   }
+ }
+ 
+ vframeStream::vframeStream(oop continuation, Handle continuation_scope) 
+  : vframeStreamCommon(RegisterMap(continuation, true)) {
+ 
+   _stop_at_java_call_stub = false;
+   _continuation_scope = continuation_scope;
+   
+   if (!Continuation::has_last_Java_frame(continuation)) {
+     _mode = at_end_mode;
+     return;
+   }
+ 
+   _frame = Continuation::last_frame(continuation, &_reg_map);
+   // _chunk = _reg_map.stack_chunk();
+   while (!fill_from_frame()) {
      _frame = _frame.sender(&_reg_map);
    }
  }
  
  

*** 571,36 ***
    }
  }
  
  javaVFrame* vframeStreamCommon::asJavaVFrame() {
    javaVFrame* result = NULL;
!   if (_mode == compiled_mode) {
!     compiledVFrame* cvf;
!     if (_frame.is_native_frame()) {
!       cvf = compiledVFrame::cast(vframe::new_vframe(&_frame, &_reg_map, _thread));
-       assert(cvf->cb() == cb(), "wrong code blob");
-     } else {
-       assert(_frame.is_compiled_frame(), "expected compiled Java frame");
- 
-       // lazy update to register map
-       bool update_map = true;
-       RegisterMap map(_thread, update_map);
-       frame f = _prev_frame.sender(&map);
  
!       assert(f.is_compiled_frame(), "expected compiled Java frame");
  
!       cvf = compiledVFrame::cast(vframe::new_vframe(&f, &map, _thread));
  
!       assert(cvf->cb() == cb(), "wrong code blob");
  
!       // get the same scope as this stream
!       cvf = cvf->at_scope(_decode_offset, _vframe_id);
! 
-       assert(cvf->scope()->decode_offset() == _decode_offset, "wrong scope");
-       assert(cvf->scope()->sender_decode_offset() == _sender_decode_offset, "wrong scope");
-     }
-     assert(cvf->vframe_id() == _vframe_id, "wrong vframe");
  
      result = cvf;
    } else {
      result = javaVFrame::cast(vframe::new_vframe(&_frame, &_reg_map, _thread));
    }
--- 658,24 ---
    }
  }
  
  javaVFrame* vframeStreamCommon::asJavaVFrame() {
    javaVFrame* result = NULL;
!   // FIXME, need to re-do JDK-8271140 and check is_native_frame?
!   if (_mode == compiled_mode && _frame.is_compiled_frame()) {
!     assert(_frame.is_compiled_frame() || _frame.is_native_frame(), "expected compiled Java frame");
!     guarantee(_reg_map.update_map(), "");
  
!     compiledVFrame* cvf = compiledVFrame::cast(vframe::new_vframe(&_frame, &_reg_map, _thread));
  
!     guarantee(cvf->cb() == cb(), "wrong code blob");
  
!     cvf = cvf->at_scope(_decode_offset, _vframe_id); // get the same scope as this stream
  
!     guarantee(cvf->scope()->decode_offset() == _decode_offset, "wrong scope");
!     guarantee(cvf->scope()->sender_decode_offset() == _sender_decode_offset, "wrong scope");
!     guarantee(cvf->vframe_id() == _vframe_id, "wrong vframe");
  
      result = cvf;
    } else {
      result = javaVFrame::cast(vframe::new_vframe(&_frame, &_reg_map, _thread));
    }

*** 701,11 ***
      tty->print("(Native Method)");
    }
    // Check frame size and print warning if it looks suspiciously large
    if (fr().sp() != NULL) {
      RegisterMap map = *register_map();
!     uint size = fr().frame_size(&map);
  #ifdef _LP64
      if (size > 8*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size);
  #else
      if (size > 4*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size);
  #endif
--- 776,11 ---
      tty->print("(Native Method)");
    }
    // Check frame size and print warning if it looks suspiciously large
    if (fr().sp() != NULL) {
      RegisterMap map = *register_map();
!     uint size = fr().frame_size();
  #ifdef _LP64
      if (size > 8*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size);
  #else
      if (size > 4*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size);
  #endif
< prev index next >