changeset 3153:5ca1332171c8

Fixed an issue in the HotSpot code for rethrowing an exception at deopt (wrong values on the expression stack caused a crash when GC and deopt happened at the same time).
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Tue, 05 Jul 2011 18:55:22 +0200
parents 3e89c4c5f37f
children a08723c368c2
files src/share/vm/interpreter/interpreterRuntime.cpp src/share/vm/runtime/deoptimization.cpp src/share/vm/runtime/vframeArray.cpp
diffstat 3 files changed, 37 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Tue Jul 05 16:41:53 2011 +0200
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Tue Jul 05 18:55:22 2011 +0200
@@ -459,6 +459,7 @@
   } while (should_repeat == true);
 
   if (h_method->method_data() != NULL) {
+    ResourceMark rm(thread);
     ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci);
     if (pdata != NULL) {
       int tstate0 = pdata->trap_state();
--- a/src/share/vm/runtime/deoptimization.cpp	Tue Jul 05 16:41:53 2011 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Tue Jul 05 18:55:22 2011 +0200
@@ -1244,7 +1244,7 @@
 
     if (trap_scope->rethrow_exception()) {
       if (TraceDeoptimization) {
-        tty->print_cr("Exception to be rethrown in the interpreter");
+        tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", instanceKlass::cast(trap_method->method_holder())->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci);
       }
       GrowableArray<ScopeValue*>* expressions = trap_scope->expressions();
       ScopeValue* topOfStack = expressions->top();
--- a/src/share/vm/runtime/vframeArray.cpp	Tue Jul 05 16:41:53 2011 +0200
+++ b/src/share/vm/runtime/vframeArray.cpp	Tue Jul 05 18:55:22 2011 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "code/scopeDesc.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
@@ -62,7 +63,7 @@
   _method = vf->method();
   _bci    = vf->raw_bci();
   _reexecute = vf->should_reexecute();
-
+  
   int index;
 
   // Get the monitors off-stack
@@ -126,28 +127,37 @@
 
   // Now the expressions off-stack
   // Same silliness as above
-
-  StackValueCollection *exprs = vf->expressions();
-  _expressions = new StackValueCollection(exprs->size());
-  for(index = 0; index < exprs->size(); index++) {
-    StackValue* value = exprs->at(index);
-    switch(value->type()) {
-      case T_OBJECT:
-        assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
-        // preserve object type
-        _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT ));
-        break;
-      case T_CONFLICT:
-        // A dead stack element.  Will be initialized to null/zero.
-        // This can occur when the compiler emits a state in which stack
-        // elements are known to be dead (because of an imminent exception).
-        _expressions->add( new StackValue());
-        break;
-      case T_INT:
-        _expressions->add( new StackValue(value->get_int()));
-        break;
-      default:
-        ShouldNotReachHere();
+  bool rethrow_exception = vf->scope()->rethrow_exception();
+  if (rethrow_exception) {
+    // (tw) Make sure there are only null pointers on the stack, because the stack values do not correspond to the GC map at the bytecode at which the exception is rethrown.
+    _expressions = new StackValueCollection(vf->method()->max_stack());
+    assert(Thread::current()->has_pending_exception(), "just checking");
+    for (int i=0; i<vf->method()->max_stack(); ++i) {
+      _expressions->add( new StackValue());
+    }
+  } else {
+    StackValueCollection *exprs = vf->expressions();
+    _expressions = new StackValueCollection(exprs->size());
+    for(index = 0; index < exprs->size(); index++) {
+      StackValue* value = exprs->at(index);
+      switch(value->type()) {
+        case T_OBJECT:
+          assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
+          // preserve object type
+          _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT ));
+          break;
+        case T_CONFLICT:
+          // A dead stack element.  Will be initialized to null/zero.
+          // This can occur when the compiler emits a state in which stack
+          // elements are known to be dead (because of an imminent exception).
+          _expressions->add( new StackValue());
+          break;
+        case T_INT:
+          _expressions->add( new StackValue(value->get_int()));
+          break;
+        default:
+          ShouldNotReachHere();
+      }
     }
   }
 }
@@ -314,8 +324,7 @@
   // only unpacks the part of the expression stack not used by callee
   // as parameters. The callee parameters are unpacked as part of the
   // callee locals.
-  int i;
-  for(i = 0; i < expressions()->size(); i++) {
+  for(int i = 0; i < expressions()->size(); i++) {
     StackValue *value = expressions()->at(i);
     intptr_t*   addr  = iframe()->interpreter_frame_expression_stack_at(i);
     switch(value->type()) {
@@ -352,7 +361,7 @@
 
 
   // Unpack the locals
-  for(i = 0; i < locals()->size(); i++) {
+  for(int i = 0; i < locals()->size(); i++) {
     StackValue *value = locals()->at(i);
     intptr_t* addr  = iframe()->interpreter_frame_local_at(i);
     switch(value->type()) {