7090904: JSR 292: JRuby junit test crashes in PSScavengeRootsClosure::do_oop
authortwisti
Mon, 24 Oct 2011 07:53:17 -0700
changeset 10966 0c9ed2dfc6a2
parent 10965 0d123ed671cc
child 10967 e13ea25b2f0b
7090904: JSR 292: JRuby junit test crashes in PSScavengeRootsClosure::do_oop Reviewed-by: kvn, never, jrose
hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
hotspot/src/share/vm/interpreter/bytecodeTracer.cpp
hotspot/src/share/vm/runtime/deoptimization.cpp
hotspot/src/share/vm/runtime/frame.cpp
hotspot/src/share/vm/runtime/frame.hpp
hotspot/src/share/vm/runtime/thread.cpp
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Sun Oct 23 23:57:39 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Mon Oct 24 07:53:17 2011 -0700
@@ -1609,6 +1609,12 @@
     // and sender_sp is fp+8
     intptr_t* locals = interpreter_frame->sender_sp() + max_locals - 1;
 
+#ifdef ASSERT
+    if (caller->is_interpreted_frame()) {
+      assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement");
+    }
+#endif
+
     interpreter_frame->interpreter_frame_set_locals(locals);
     BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin();
     BasicObjectLock* monbot = montop - moncount;
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Sun Oct 23 23:57:39 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Mon Oct 24 07:53:17 2011 -0700
@@ -1622,6 +1622,12 @@
     // sender_sp is fp+16 XXX
     intptr_t* locals = interpreter_frame->sender_sp() + max_locals - 1;
 
+#ifdef ASSERT
+    if (caller->is_interpreted_frame()) {
+      assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement");
+    }
+#endif
+
     interpreter_frame->interpreter_frame_set_locals(locals);
     BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin();
     BasicObjectLock* monbot = montop - moncount;
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Sun Oct 23 23:57:39 2011 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Mon Oct 24 07:53:17 2011 -0700
@@ -241,7 +241,7 @@
         st->print_cr(" not secondary entry?", i);
         return false;
       }
-      i = cache->entry_at(i)->main_entry_index();
+      i = cache->entry_at(i)->main_entry_index() + constantPoolOopDesc::CPCACHE_INDEX_TAG;
       goto check_cache_index;
     } else {
       st->print_cr(" not in cache[*]?", i);
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp	Sun Oct 23 23:57:39 2011 -0700
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp	Mon Oct 24 07:53:17 2011 -0700
@@ -362,8 +362,6 @@
   intptr_t* frame_sizes = NEW_C_HEAP_ARRAY(intptr_t, number_of_frames);
   // +1 because we always have an interpreter return address for the final slot.
   address* frame_pcs = NEW_C_HEAP_ARRAY(address, number_of_frames + 1);
-  int callee_parameters = 0;
-  int callee_locals = 0;
   int popframe_extra_args = 0;
   // Create an interpreter return address for the stub to use as its return
   // address so the skeletal frames are perfectly walkable
@@ -387,14 +385,20 @@
   // handles are used.  If the caller is interpreted get the real
   // value so that the proper amount of space can be added to it's
   // frame.
-  int caller_actual_parameters = callee_parameters;
+  bool caller_was_method_handle = false;
   if (deopt_sender.is_interpreted_frame()) {
     methodHandle method = deopt_sender.interpreter_frame_method();
     Bytecode_invoke cur = Bytecode_invoke_check(method,
                                                 deopt_sender.interpreter_frame_bci());
-    Symbol* signature = method->constants()->signature_ref_at(cur.index());
-    ArgumentSizeComputer asc(signature);
-    caller_actual_parameters = asc.size() + (cur.has_receiver() ? 1 : 0);
+    if (cur.code() == Bytecodes::_invokedynamic ||
+        (cur.code() == Bytecodes::_invokevirtual &&
+         method->constants()->klass_ref_at_noresolve(cur.index()) == vmSymbols::java_lang_invoke_MethodHandle() &&
+         methodOopDesc::is_method_handle_invoke_name(cur.name()))) {
+      // Method handle invokes may involve fairly arbitrary chains of
+      // calls so it's impossible to know how much actual space the
+      // caller has for locals.
+      caller_was_method_handle = true;
+    }
   }
 
   //
@@ -411,14 +415,15 @@
   // in the frame_sizes/frame_pcs so the assembly code can do a trivial walk.
   // so things look a little strange in this loop.
   //
+  int callee_parameters = 0;
+  int callee_locals = 0;
   for (int index = 0; index < array->frames(); index++ ) {
     // frame[number_of_frames - 1 ] = on_stack_size(youngest)
     // frame[number_of_frames - 2 ] = on_stack_size(sender(youngest))
     // frame[number_of_frames - 3 ] = on_stack_size(sender(sender(youngest)))
     int caller_parms = callee_parameters;
-    if (index == array->frames() - 1) {
-      // Use the value from the interpreted caller
-      caller_parms = caller_actual_parameters;
+    if ((index == array->frames() - 1) && caller_was_method_handle) {
+      caller_parms = 0;
     }
     frame_sizes[number_of_frames - 1 - index] = BytesPerWord * array->element(index)->on_stack_size(caller_parms,
                                                                                                     callee_parameters,
@@ -460,13 +465,13 @@
   // QQQ I'd rather see this pushed down into last_frame_adjust
   // and have it take the sender (aka caller).
 
-  if (deopt_sender.is_compiled_frame()) {
+  if (deopt_sender.is_compiled_frame() || caller_was_method_handle) {
     caller_adjustment = last_frame_adjust(0, callee_locals);
-  } else if (callee_locals > caller_actual_parameters) {
+  } else if (callee_locals > callee_parameters) {
     // The caller frame may need extending to accommodate
     // non-parameter locals of the first unpacked interpreted frame.
     // Compute that adjustment.
-    caller_adjustment = last_frame_adjust(caller_actual_parameters, callee_locals);
+    caller_adjustment = last_frame_adjust(callee_parameters, callee_locals);
   }
 
   // If the sender is deoptimized the we must retrieve the address of the handler
@@ -481,7 +486,7 @@
 
   UnrollBlock* info = new UnrollBlock(array->frame_size() * BytesPerWord,
                                       caller_adjustment * BytesPerWord,
-                                      caller_actual_parameters,
+                                      caller_was_method_handle ? 0 : callee_parameters,
                                       number_of_frames,
                                       frame_sizes,
                                       frame_pcs,
--- a/hotspot/src/share/vm/runtime/frame.cpp	Sun Oct 23 23:57:39 2011 -0700
+++ b/hotspot/src/share/vm/runtime/frame.cpp	Mon Oct 24 07:53:17 2011 -0700
@@ -1338,7 +1338,11 @@
     // Label values common to most frames
     values.describe(-1, unextended_sp(), err_msg("unextended_sp for #%d", frame_no));
     values.describe(-1, sp(), err_msg("sp for #%d", frame_no));
-    values.describe(-1, fp(), err_msg("fp for #%d", frame_no));
+    if (is_compiled_frame()) {
+      values.describe(-1, sp() + _cb->frame_size(), err_msg("computed fp for #%d", frame_no));
+    } else {
+      values.describe(-1, fp(), err_msg("fp for #%d", frame_no));
+    }
   }
   if (is_interpreted_frame()) {
     methodOop m = interpreter_frame_method();
@@ -1450,9 +1454,8 @@
 }
 
 
-void FrameValues::print() {
+void FrameValues::print(JavaThread* thread) {
   _values.sort(compare);
-  JavaThread* thread = JavaThread::current();
 
   // Sometimes values like the fp can be invalid values if the
   // register map wasn't updated during the walk.  Trim out values
@@ -1460,12 +1463,22 @@
   int min_index = 0;
   int max_index = _values.length() - 1;
   intptr_t* v0 = _values.at(min_index).location;
-  while (!thread->is_in_stack((address)v0)) {
-    v0 = _values.at(++min_index).location;
-  }
   intptr_t* v1 = _values.at(max_index).location;
-  while (!thread->is_in_stack((address)v1)) {
-    v1 = _values.at(--max_index).location;
+
+  if (thread == Thread::current()) {
+    while (!thread->is_in_stack((address)v0)) {
+      v0 = _values.at(++min_index).location;
+    }
+    while (!thread->is_in_stack((address)v1)) {
+      v1 = _values.at(--max_index).location;
+    }
+  } else {
+    while (!thread->on_local_stack((address)v0)) {
+      v0 = _values.at(++min_index).location;
+    }
+    while (!thread->on_local_stack((address)v1)) {
+      v1 = _values.at(--max_index).location;
+    }
   }
   intptr_t* min = MIN2(v0, v1);
   intptr_t* max = MAX2(v0, v1);
--- a/hotspot/src/share/vm/runtime/frame.hpp	Sun Oct 23 23:57:39 2011 -0700
+++ b/hotspot/src/share/vm/runtime/frame.hpp	Mon Oct 24 07:53:17 2011 -0700
@@ -516,7 +516,7 @@
   void describe(int owner, intptr_t* location, const char* description, int priority = 0);
 
   void validate();
-  void print();
+  void print(JavaThread* thread);
 };
 
 #endif
--- a/hotspot/src/share/vm/runtime/thread.cpp	Sun Oct 23 23:57:39 2011 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Mon Oct 24 07:53:17 2011 -0700
@@ -2947,7 +2947,7 @@
     values.validate();
   } else {
     tty->print_cr("[Describe stack layout]");
-    values.print();
+    values.print(this);
   }
 }
 #endif