< prev index next >

src/hotspot/share/runtime/frame.cpp

Print this page
rev 50307 : [mq]: cont

@@ -36,10 +36,11 @@
 #include "oops/method.hpp"
 #include "oops/methodData.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/verifyOopClosure.hpp"
 #include "prims/methodHandles.hpp"
+#include "runtime/continuation.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/monitorChunk.hpp"
 #include "runtime/os.hpp"

@@ -50,15 +51,16 @@
 #include "runtime/thread.inline.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/decoder.hpp"
 #include "utilities/formatBuffer.hpp"
 
-RegisterMap::RegisterMap(JavaThread *thread, bool update_map) {
+RegisterMap::RegisterMap(JavaThread *thread, bool update_map, bool validate_oops) {
   _thread         = thread;
   _update_map     = update_map;
   clear();
   debug_only(_update_for_id = NULL;)
+  _validate_oops = validate_oops;
 #ifndef PRODUCT
   for (int i = 0; i < reg_count ; i++ ) _location[i] = NULL;
 #endif /* PRODUCT */
 }
 

@@ -67,10 +69,11 @@
   assert(map != NULL, "RegisterMap must be present");
   _thread                = map->thread();
   _update_map            = map->update_map();
   _include_argument_oops = map->include_argument_oops();
   debug_only(_update_for_id = map->_update_for_id;)
+  _validate_oops = map->_validate_oops;
   pd_initialize_from(map);
   if (update_map()) {
     for(int i = 0; i < location_valid_size; i++) {
       LocationValidType bits = !update_map() ? 0 : map->_location_valid[i];
       _location_valid[i] = bits;

@@ -131,10 +134,13 @@
 // that happens for deoptimized frames. In addition it makes the value the
 // hardware would want to see in the native frame. The only user (at this point)
 // is deoptimization. It likely no one else should ever use it.
 
 address frame::raw_pc() const {
+  // if (Continuation::is_continuation_entry_frame(*this)) {
+  //   return StubRoutines::cont_returnBarrier();
+  // }
   if (is_deoptimized_frame()) {
     CompiledMethod* cm = cb()->as_compiled_method_or_null();
     if (cm->is_method_handle_return(pc()))
       return cm->deopt_mh_handler_begin() - pc_return_offset;
     else

@@ -159,10 +165,21 @@
   _pc = newpc;
   _cb = CodeCache::find_blob_unsafe(_pc);
 
 }
 
+void frame::set_pc_preserve_deopt(address   newpc) {
+#ifdef ASSERT
+  if (_cb != NULL && _cb->is_nmethod()) {
+    assert(!((nmethod*)_cb)->is_deopt_pc(_pc), "invariant violation");
+  }
+#endif // ASSERT
+
+  _pc = newpc;
+  _cb = CodeCache::find_blob_unsafe(_pc);
+}
+
 // type testers
 bool frame::is_ignored_frame() const {
   return false;  // FIXME: some LambdaForm frames should be ignored
 }
 bool frame::is_deoptimized_frame() const {

@@ -264,10 +281,19 @@
   CompiledMethod* nm = (CompiledMethod*)_cb;
 
   if( !nm->can_be_deoptimized() )
     return false;
 
+  address* pc_addr = &(((address*) sp())[-1]); // TODO: PLATFORM
+  if (Continuation::is_return_barrier_entry(*pc_addr)) {
+    log_trace(jvmcont)("Can't deopt entry:");
+    if (log_is_enabled(Trace, jvmcont)) {
+      print_value_on(tty, NULL);
+    }
+    return false;
+  }
+
   return !nm->is_at_poll_return(pc());
 }
 
 void frame::deoptimize(JavaThread* thread) {
   // Schedule deoptimization of an nmethod activation with this frame.

@@ -334,22 +360,39 @@
   address deopt = cm->is_method_handle_return(pc()) ?
                         cm->deopt_mh_handler_begin() :
                         cm->deopt_handler_begin();
 
   // Save the original pc before we patch in the new one
+  // address xpc = pc();
   cm->set_original_pc(this, pc());
   patch_pc(thread, deopt);
 
 #ifdef ASSERT
   {
-    RegisterMap map(thread, false);
     frame check = thread->last_frame();
+    if (is_older(check.id())) {
+      RegisterMap map(thread, false);
     while (id() != check.id()) {
       check = check.sender(&map);
     }
+      // if (!check.is_deoptimized_frame()) {
+      //   tty->print_cr("Deopt failure:");
+      //   tty->print_cr("deopt: %p pc: %p", deopt, xpc);
+      //   tty->print_cr("me:");
+      //   print_on(tty);
+      //   tty->print_cr("---- %d", is_younger(check.id()));
+      //   check = thread->last_frame();
+      //   check.print_on(tty);
+      //   while (id() != check.id()) {
+      //     check = check.sender(&map);
+      //     tty->print_cr("---- %d", is_younger(check.id()));
+      //     check.print_on(tty);
+      //   }      
+      // }
     assert(check.is_deoptimized_frame(), "missed deopt");
   }
+  }
 #endif // ASSERT
 }
 
 frame frame::java_sender() const {
   RegisterMap map(JavaThread::current(), false);

@@ -951,23 +994,24 @@
   if (query_oop_map_cache) {
     m->mask_for(bci, &mask);
   } else {
     OopMapCache::compute_one_oop_map(m, bci, &mask);
   }
+  // mask.print();
   mask.iterate_oop(&blk);
 }
 
 
 void frame::oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f) {
   InterpretedArgumentOopFinder finder(signature, has_receiver, this, f);
   finder.oops_do();
 }
 
-void frame::oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* reg_map) {
+void frame::oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, DerivedOopClosure* df, const RegisterMap* reg_map) {
   assert(_cb != NULL, "sanity check");
   if (_cb->oop_maps() != NULL) {
-    OopMapSet::oops_do(this, reg_map, f);
+    OopMapSet::oops_do(this, reg_map, f, df);
 
     // Preserve potential arguments for a callee. We handle this by dispatching
     // on the codeblob. For c2i, we do
     if (reg_map->include_argument_oops()) {
       _cb->preserve_callee_argument_oops(*this, reg_map, f);

@@ -1001,10 +1045,17 @@
   virtual void handle_oop_offset() {
     // Extract low order register number from register array.
     // In LP64-land, the high-order bits are valid but unhelpful.
     VMReg reg = _regs[_offset].first();
     oop *loc = _fr.oopmapreg_to_location(reg, _reg_map);
+  #ifdef ASSERT
+    if (loc == NULL) {
+      tty->print_cr("Error walking frame oops:");
+      _fr.print_on(tty);
+      assert (loc != NULL, "reg: %ld %s loc: %p", reg->value(), reg->name(), loc);
+    }
+  #endif
     _f->do_oop(loc);
   }
 
  public:
   CompiledArgumentOopFinder(Symbol* signature, bool has_receiver, bool has_appendix, OopClosure* f, frame fr,  const RegisterMap* reg_map)

@@ -1099,11 +1150,11 @@
   // Traverse the Handle Block saved in the entry frame
   entry_frame_call_wrapper()->oops_do(f);
 }
 
 
-void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) {
+void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, DerivedOopClosure* df, RegisterMap* map, bool use_interpreter_oop_map_cache) {
 #ifndef PRODUCT
 #if defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140
 #pragma error_messages(off, SEC_NULL_PTR_DEREF)
 #endif
   // simulate GC crash here to dump java thread in error report

@@ -1115,11 +1166,11 @@
   if (is_interpreted_frame()) {
     oops_interpreted_do(f, map, use_interpreter_oop_map_cache);
   } else if (is_entry_frame()) {
     oops_entry_do(f, map);
   } else if (CodeCache::contains(pc())) {
-    oops_code_blob_do(f, cf, map);
+    oops_code_blob_do(f, cf, df, map);
   } else {
     ShouldNotReachHere();
   }
 }
 

@@ -1139,10 +1190,17 @@
     f(m);
   }
 }
 
 void frame::verify(const RegisterMap* map) {
+#ifndef PRODUCT
+  if (TraceCodeBlobStacks) {
+    tty->print_cr("*** verify");
+    print_on(tty);
+  }
+#endif
+
   // for now make sure receiver type is correct
   if (is_interpreted_frame()) {
     Method* method = interpreter_frame_method();
     guarantee(method->is_method(), "method is wrong in frame::verify");
     if (!method->is_static()) {

@@ -1152,11 +1210,11 @@
     }
   }
 #if COMPILER2_OR_JVMCI
   assert(DerivedPointerTable::is_empty(), "must be empty before verify");
 #endif
-  oops_do_internal(&VerifyOopClosure::verify_oop, NULL, (RegisterMap*)map, false);
+  oops_do_internal(&VerifyOopClosure::verify_oop, NULL, NULL, (RegisterMap*)map, false);
 }
 
 
 #ifdef ASSERT
 bool frame::verify_return_pc(address x) {
< prev index next >