< prev index next >

src/hotspot/share/compiler/methodLiveness.cpp

Print this page
*** 622,19 ***
      case Bytecodes::_multianewarray:
      case Bytecodes::_lookupswitch:
        // These bytecodes have no effect on the method's locals.
        break;
  
!     case Bytecodes::_return:
!       if (instruction->method()->intrinsic_id() == vmIntrinsics::_Object_init) {
!         // return from Object.init implicitly registers a finalizer
!         // for the receiver if needed, so keep it alive.
          load_one(0);
        }
        break;
! 
- 
      case Bytecodes::_lload:
      case Bytecodes::_dload:
        load_two(instruction->get_index());
        break;
  
--- 622,26 ---
      case Bytecodes::_multianewarray:
      case Bytecodes::_lookupswitch:
        // These bytecodes have no effect on the method's locals.
        break;
  
!     case Bytecodes::_return: {
!       ciMethod* method = instruction->method();
!       ciInstanceKlass* holder = method->holder();
!       const bool abstract_klass = holder->is_abstract();
+       const bool concrete_value_klass = !abstract_klass && holder->is_inlinetype();
+       if (method->intrinsic_id() == vmIntrinsics::_Object_init ||
+           (method->is_object_constructor() && (concrete_value_klass || abstract_klass))) {
+         // Returning from Object.<init> implicitly registers a finalizer for the receiver if needed, to keep it alive.
+         // Value class constructors update the scalarized receiver. We need to keep it live so that we can find it after
+         // (chained) constructor calls and propagate updates to the caller. If the holder of the constructor is abstract,
+         // we do not know if the constructor was called on a value class or not. We therefore keep the receiver of all
+         // abstract constructors live.
          load_one(0);
        }
        break;
!     }
      case Bytecodes::_lload:
      case Bytecodes::_dload:
        load_two(instruction->get_index());
        break;
  
< prev index next >