< prev index next >

src/hotspot/share/runtime/safepoint.cpp

Print this page
@@ -40,10 +40,11 @@
  #include "logging/logStream.hpp"
  #include "memory/resourceArea.hpp"
  #include "memory/universe.hpp"
  #include "oops/oop.inline.hpp"
  #include "oops/symbol.hpp"
+ #include "oops/inlineKlass.hpp"
  #include "runtime/atomic.hpp"
  #include "runtime/deoptimization.hpp"
  #include "runtime/frame.inline.hpp"
  #include "runtime/globals.hpp"
  #include "runtime/handles.inline.hpp"

@@ -779,21 +780,38 @@
    // 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();
+     Method* method = nm->method();
+     bool return_oop = method->is_returning_oop();
      HandleMark hm(self);
-     Handle return_value;
+     GrowableArray<Handle> return_values;
+     InlineKlass* vk = nullptr;
+     if (return_oop && InlineTypeReturnedAsFields &&
+         (method->result_type() == T_OBJECT)) {
+       // Check if an inline type is returned as fields
+       vk = InlineKlass::returned_inline_klass(map);
+       if (vk != nullptr) {
+         // 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.
+         assert(vk == method->returns_inline_type(thread()), "bad inline klass");
+         vk->save_oop_fields(map, return_values);
+         return_oop = false;
+       }
+     }
+ 
      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(oopDesc::is_oop_or_null(result), "must be oop");
-       return_value = Handle(self, result);
+       return_values.push(Handle(self, result));
        assert(Universe::heap()->is_in_or_null(result), "must be heap pointer");
      }
  
      // We get here if compiled return polls found a reason to call into the VM.
      // One condition for that is that the top frame is not yet safe to use.

@@ -803,11 +821,14 @@
      // Process pending operation
      SafepointMechanism::process_if_requested_with_exit_check(self, true /* check asyncs */);
  
      // 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 != nullptr) {
+       vk->restore_oop_results(map, return_values);
      }
    }
  
    // This is a safepoint poll. Verify the return address and block.
    else {
< prev index next >