< prev index next >

src/share/vm/runtime/deoptimization.cpp

Print this page

        

@@ -211,41 +211,63 @@
       // It is not guaranteed that we can get such information here only
       // by analyzing bytecode in deoptimized frames. This is why this flag
       // is set during method compilation (see Compile::Process_OopMap_Node()).
       // If the previous frame was popped or if we are dispatching an exception,
       // we don't have an oop result.
-      bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution() && (exec_mode == Unpack_deopt);
-      Handle return_value;
+      ScopeDesc* scope = chunk->at(0)->scope();
+      bool save_oop_result = scope->return_oop() && !thread->popframe_forcing_deopt_reexecution() && (exec_mode == Unpack_deopt);
+      // In case of the return of multiple values, we must take care
+      // of all oop return values.
+      GrowableArray<Handle> return_oops;
+      ValueKlass* vk = NULL;
+      if (save_oop_result) {
+        if (scope->return_vt()) {
+          vk = ValueKlass::returned_value_type(map);
+          if (vk != NULL) {
+            bool success = vk->save_oop_results(map, return_oops);
+            assert(success, "found klass ptr being returned: saving oops can't fail");
+            save_oop_result = false;
+          } else {
+            vk = NULL;
+          }
+        }
+      }      
       if (save_oop_result) {
         // Reallocation may trigger GC. If deoptimization happened on return from
         // call which returns oop we need to save it since it is not in oopmap.
         oop result = deoptee.saved_oop_result(&map);
         assert(result == NULL || result->is_oop(), "must be oop");
-        return_value = Handle(thread, result);
+        return_oops.push(Handle(thread, result));
         assert(Universe::heap()->is_in_or_null(result), "must be heap pointer");
         if (TraceDeoptimization) {
           ttyLocker ttyl;
           tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, p2i(result), p2i(thread));
         }
       }
-      if (objects != NULL) {
+      if (objects != NULL || vk != NULL) {
         bool skip_internal = (cm != NULL) && !cm->is_compiled_by_jvmci();
         JRT_BLOCK
-          realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD);
+          if (vk != NULL) {
+            realloc_failures = realloc_value_type_result(vk, map, return_oops, THREAD);
+          }
+          if (objects != NULL) {
+            realloc_failures = realloc_failures || realloc_objects(thread, &deoptee, objects, THREAD);
           reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal, THREAD);
+          }
         JRT_END
 #ifndef PRODUCT
         if (TraceDeoptimization) {
           ttyLocker ttyl;
           tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, p2i(thread));
           print_objects(objects, realloc_failures);
         }
 #endif
       }
-      if (save_oop_result) {
+      if (save_oop_result || vk != NULL) {
         // Restore result.
-        deoptee.set_saved_oop_result(&map, return_value());
+        assert(return_oops.length() == 1, "no value type");
+        deoptee.set_saved_oop_result(&map, return_oops.pop()());
       }
 #ifndef INCLUDE_JVMCI
     }
     if (EliminateLocks) {
 #endif // INCLUDE_JVMCI

@@ -850,10 +872,30 @@
   }
 
   return failures;
 }
 
+// We're deoptimizing at the return of a call, value type fields are
+// in registers. When we go back to the interpreter, it will expect a
+// reference to a value type instance. Allocate and initialize it from
+// the register values here.
+bool Deoptimization::realloc_value_type_result(ValueKlass* vk, const RegisterMap& map, GrowableArray<Handle>& return_oops, TRAPS) {
+  VMRegPair* regs;
+  int nb_fields;
+  const GrowableArray<SigEntry>& sig_vk = vk->return_convention(regs, nb_fields);
+  regs++;
+  nb_fields--;
+  oop new_vt = vk->realloc_result(sig_vk, map, regs, return_oops, nb_fields, THREAD);
+  if (new_vt == NULL) {
+    CLEAR_PENDING_EXCEPTION;
+    THROW_OOP_(Universe::out_of_memory_error_realloc_objects(), true);
+  }
+  return_oops.clear();
+  return_oops.push(Handle(THREAD, new_vt));
+  return false;
+}
+
 // restore elements of an eliminated type array
 void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type) {
   int index = 0;
   intptr_t val;
 
< prev index next >