< prev index next >

src/share/vm/runtime/safepoint.cpp

Print this page

        

@@ -37,10 +37,11 @@
 #include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
+#include "oops/valueKlass.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/interfaceSupport.hpp"

@@ -1027,29 +1028,49 @@
   // has already had the effect of causing the return to occur, so the execution
   // will continue immediately after the call. In addition, the oopmap at the
   // return point does not mark the return value as an oop (if it is), so
   // it needs a handle here to be updated.
   if( nm->is_at_poll_return(real_return_addr) ) {
+    ResourceMark rm;
     // See if return type is an oop.
-    bool return_oop = nm->method()->is_returning_oop();
-    Handle return_value;
+    Method* method = nm->method();
+    bool return_oop = method->is_returning_oop();
+    
+    GrowableArray<Handle> return_values;
+    ValueKlass* vk = NULL;
+    if (!return_oop && method->is_returning_vt()) {
+      // We're at a safepoint at the return of a method that returns
+      // multiple values. We must make sure we preserve the oop values
+      // across the safepoint.
+      vk = ValueKlass::returned_value_type(map);
+      assert(vk == NULL || vk == method->returned_value_type(thread()) ||
+             method->returned_value_type(thread()) == SystemDictionary::___Value_klass(), "Bad value klass");
+      if (vk != NULL && !vk->save_oop_results(map, return_values)) {
+        return_oop = true;
+        vk = NULL;
+      }
+    }
+
     if (return_oop) {
       // The oop result has been saved on the stack together with all
       // the other registers. In order to preserve it over GCs we need
       // to keep it in a handle.
       oop result = caller_fr.saved_oop_result(&map);
       assert(result == NULL || result->is_oop(), "must be oop");
-      return_value = Handle(thread(), result);
+      return_values.push(Handle(thread(), result));
       assert(Universe::heap()->is_in_or_null(result), "must be heap pointer");
     }
 
     // Block the thread
     SafepointSynchronize::block(thread());
 
     // restore oop result, if any
     if (return_oop) {
-      caller_fr.set_saved_oop_result(&map, return_value());
+      assert(return_values.length() == 1, "only one return value");
+      caller_fr.set_saved_oop_result(&map, return_values.pop()());
+    } else if (vk != NULL) {
+      vk->restore_oop_results(map, return_values);
     }
   }
 
   // This is a safepoint poll. Verify the return address and block.
   else {
< prev index next >