< prev index next >

src/hotspot/share/runtime/vframe.cpp

Print this page

        

@@ -87,10 +87,11 @@
 }
 
 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;
   return vframe::new_vframe(&s, &temp_map, thread());
 }

@@ -255,52 +256,65 @@
 }
 
 // ------------- interpretedVFrame --------------
 
 u_char* interpretedVFrame::bcp() const {
-  return fr().interpreter_frame_bcp();
+    return (!register_map()->in_cont())  ? fr().interpreter_frame_bcp() : Continuation::interpreter_frame_bcp(fr(), register_map());
 }
 
 void interpretedVFrame::set_bcp(u_char* bcp) {
+  assert (!register_map()->in_cont(), ""); // unsupported for now because seems to be unused
   fr().interpreter_frame_set_bcp(bcp);
 }
 
 intptr_t* interpretedVFrame::locals_addr_at(int offset) const {
+  assert (!register_map()->in_cont(), ""); // 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 (!register_map()->in_cont()) { // 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();
+  return (!register_map()->in_cont()) ? fr().interpreter_frame_method() : Continuation::interpreter_frame_method(fr(), register_map());
 }
 
-static StackValue* create_stack_value_from_oop_map(const InterpreterOopMap& oop_mask,
+static StackValue* create_stack_value_from_oop_map(const RegisterMap* reg_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)) {
+    oop obj = NULL;
+    if (addr != NULL) {
+      // obj = (UseCompressedOops && reg_map->in_cont()) ? HeapAccess<IS_ARRAY>::oop_load((narrowOop*)addr) : *(oop*)addr;
+      if (UseCompressedOops && reg_map->in_cont())
+        obj = HeapAccess<IS_ARRAY>::oop_load((narrowOop*)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);
 }

@@ -319,43 +333,56 @@
 }
 
 static void stack_locals(StackValueCollection* result,
                          int length,
                          const InterpreterOopMap& oop_mask,
-                         const frame& fr) {
+                         const frame& fr,
+                         const RegisterMap* reg_map) {
 
   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 (!reg_map->in_cont()) {
+      addr = fr.interpreter_frame_local_at(i);
+      assert(addr >= fr.sp(), "must be inside the frame");
+    } else {
+      addr = (intptr_t*)Continuation::interpreter_frame_local_at(fr, reg_map, oop_mask, 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(reg_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) {
+                              const frame& fr,
+                              const RegisterMap* reg_map) {
 
   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 (!reg_map->in_cont()) {
+      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 = (intptr_t*)Continuation::interpreter_frame_expression_stack_at(fr, reg_map, oop_mask, i);
     }
 
-    StackValue* const sv = create_stack_value_from_oop_map(oop_mask,
+    StackValue* const sv = create_stack_value_from_oop_map(reg_map,
+                                                           oop_mask,
                                                            i + max_locals,
                                                            addr);
     assert(sv != NULL, "sanity check");
 
     result->add(sv);

@@ -402,13 +429,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(), register_map());
   } else {
-    stack_locals(result, length, oop_mask, fr());
+    stack_locals(result, length, oop_mask, fr(), register_map());
   }
 
   assert(length == result->size(), "invariant");
 
   return result;

@@ -455,11 +482,11 @@
 }
 #endif
 
 // top-frame will be skipped
 vframeStream::vframeStream(JavaThread* thread, frame top_frame,
-  bool stop_at_java_call_stub) : vframeStreamCommon(thread) {
+  bool stop_at_java_call_stub) : vframeStreamCommon(RegisterMap(thread, false, 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);

@@ -467,10 +494,58 @@
     _prev_frame = _frame;
     _frame = _frame.sender(&_reg_map);
   }
 }
 
+vframeStream::vframeStream(JavaThread* thread, Handle continuation_scope, bool stop_at_java_call_stub) 
+ : vframeStreamCommon(RegisterMap(thread, false, 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();
+  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);
+    }
+    _frame = _frame.sender(&_reg_map);
+  }
+  _cont = Handle(Thread::current(), 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()));
+}
+
+vframeStream::vframeStream(Handle continuation) 
+ : vframeStreamCommon(RegisterMap(NULL, false, true)) {
+
+  _stop_at_java_call_stub = false;
+  _continuation_scope = Handle();
+  
+  if (!Continuation::has_last_Java_frame(continuation)) {
+    _mode = at_end_mode;
+    return;
+  }
+
+  _frame = Continuation::last_frame(continuation, &_reg_map);
+  _cont = continuation;
+  while (!fill_from_frame()) {
+    _frame = _frame.sender(&_reg_map);
+  }
+
+  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()));
+}
+
 
 // Step back n frames, skip any pseudo frames in between.
 // This function is used in Class.forName, Class.newInstance, Method.Invoke,
 // AccessController.doPrivileged.
 void vframeStreamCommon::security_get_caller_frame(int depth) {

@@ -666,11 +741,13 @@
     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 = (map.in_cont() || Continuation::is_cont_barrier_frame(fr()))
+      ? Continuation::frame_size(fr(), &map)
+      : 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
< prev index next >