< 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 +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) {
+ : _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) {
+ : _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 +129,29 @@
  
  
  javaVFrame* vframe::java_sender() const {
    vframe* f = sender();
    while (f != NULL) {
-     if (f->is_java_frame()) return javaVFrame::cast(f);
+     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 +297,66 @@
  }
  
  // ------------- interpretedVFrame --------------
  
  u_char* interpretedVFrame::bcp() const {
-   return fr().interpreter_frame_bcp();
+   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);
-   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));
+   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 {
-   return fr().interpreter_frame_method();
+   // 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) {
+                                                    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(), addr != NULL ? (*(oop*)addr) : (oop)NULL);
+     Handle h(Thread::current(), obj);
      return new StackValue(h);
    }
    // value (integer) "v"
    return new StackValue(addr != NULL ? *addr : 0);
  }

@@ -339,45 +375,58 @@
  }
  
  static void stack_locals(StackValueCollection* result,
                           int length,
                           const InterpreterOopMap& oop_mask,
-                          const frame& fr) {
+                          const frame& fr,
+                          const stackChunkOop chunk) {
  
    assert(result != NULL, "invariant");
  
    for (int i = 0; i < length; ++i) {
-     const intptr_t* const addr = fr.interpreter_frame_local_at(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");
-     assert(addr >= fr.sp(), "must be inside the frame");
  
-     StackValue* const sv = create_stack_value_from_oop_map(oop_mask, i, addr);
+     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 frame& fr,
+                               const stackChunkOop chunk) {
  
    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;
+     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);
+                                                            addr,
+                                                            chunk);
      assert(sv != NULL, "sanity check");
  
      result->add(sv);
    }
  }

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

@@ -490,19 +539,57 @@
  }
  #endif
  
  // top-frame will be skipped
  vframeStream::vframeStream(JavaThread* thread, frame top_frame,
-                            bool stop_at_java_call_stub) :
-     vframeStreamCommon(thread, true /* process_frames */) {
+                           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
-   _prev_frame = top_frame;
    _frame  = top_frame.sender(&_reg_map);
    while (!fill_from_frame()) {
-     _prev_frame = _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 +658,24 @@
    }
  }
  
  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);
+   // 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(), "");
  
-       assert(f.is_compiled_frame(), "expected compiled Java frame");
+     compiledVFrame* cvf = compiledVFrame::cast(vframe::new_vframe(&_frame, &_reg_map, _thread));
  
-       cvf = compiledVFrame::cast(vframe::new_vframe(&f, &map, _thread));
+     guarantee(cvf->cb() == cb(), "wrong code blob");
  
-       assert(cvf->cb() == cb(), "wrong code blob");
+     cvf = cvf->at_scope(_decode_offset, _vframe_id); // get the same scope as this stream
  
-       // 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");
+     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 +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(&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 >