< prev index next >

src/hotspot/share/prims/jvmtiImpl.cpp

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.
--- 1,7 ---
  /*
!  * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.

*** 46,11 ***
  #include "runtime/frame.inline.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/interfaceSupport.inline.hpp"
  #include "runtime/javaCalls.hpp"
  #include "runtime/javaThread.hpp"
! #include "runtime/jniHandles.hpp"
  #include "runtime/os.hpp"
  #include "runtime/serviceThread.hpp"
  #include "runtime/signature.hpp"
  #include "runtime/threadSMR.hpp"
  #include "runtime/vframe.inline.hpp"
--- 46,11 ---
  #include "runtime/frame.inline.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/interfaceSupport.inline.hpp"
  #include "runtime/javaCalls.hpp"
  #include "runtime/javaThread.hpp"
! #include "runtime/jniHandles.inline.hpp"
  #include "runtime/os.hpp"
  #include "runtime/serviceThread.hpp"
  #include "runtime/signature.hpp"
  #include "runtime/threadSMR.hpp"
  #include "runtime/vframe.inline.hpp"

*** 325,10 ***
--- 325,11 ---
    , _type(type)
    , _value(value)
    , _jvf(nullptr)
    , _set(set)
    , _self(self)
+   , _need_clone(false)
    , _result(JVMTI_ERROR_NONE)
  {
  }
  
  // Check that the klass is assignable to a type with the given signature.

*** 474,10 ***
--- 475,38 ---
      return false;
    }
    return true;
  }
  
+ void VM_BaseGetOrSetLocal::check_and_clone_this_value_object() {
+   oop obj = JNIHandles::resolve(_value.l);
+   HandleMark hm(_calling_thread);
+   Handle obj_h(_calling_thread, obj);
+ 
+   assert(_type == T_OBJECT, "sanity check");
+   assert(obj != nullptr, "expected non-null oop");
+   assert(obj_h()->is_inline(), "expected inline oop");
+   assert(_index == 0, "expected slot 0 for THIS object");
+ 
+   InlineKlass* klass = InlineKlass::cast(obj_h()->klass());
+   inlineOop obj_copy = klass->allocate_instance(_calling_thread);
+   if (obj_copy == nullptr) {
+     _result = JVMTI_ERROR_OUT_OF_MEMORY;
+   } else {
+     inlineOop thisObj = inlineOop(obj_h());
+     // copy object payload into the object snapshot
+     BufferedValuePayload src(thisObj);
+     BufferedValuePayload dst(obj_copy, klass);
+     src.copy_to(dst);
+ 
+     // Must ensure the content of the buffered value is visible
+     // before publishing the buffered value oop
+     OrderAccess::storestore();
+   }
+   _value.l = JNIHandles::make_local(_calling_thread, obj_copy);
+ }
+ 
  static bool can_be_deoptimized(vframe* vf) {
    return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized());
  }
  
  bool VM_GetOrSetLocal::doit_prologue() {

*** 608,19 ***
--- 637,32 ---
          case T_DOUBLE: _value.d = locals->double_at(_index);   break;
          case T_OBJECT: {
            // Wrap the oop to be returned in a local JNI handle since
            // oops_do() no longer applies after doit() is finished.
            oop obj = locals->obj_at(_index)();
+ 
+           if (Arguments::is_valhalla_enabled()) {
+             bool is_ctor = _jvf->method()->is_object_constructor();
+             if (is_ctor && _index == 0 && obj != nullptr && obj->is_inline()) {
+               _need_clone = true; // need to allocate an object snapshot in doit_epilogue
+             }
+           }
            _value.l = JNIHandles::make_local(_calling_thread, obj);
            break;
          }
          default: ShouldNotReachHere();
        }
      }
    }
  }
  
+ void VM_BaseGetOrSetLocal::doit_epilogue() {
+   if (_need_clone) {
+     check_and_clone_this_value_object();
+   }
+ }
+ 
  bool VM_BaseGetOrSetLocal::allow_nested_vm_operations() const {
    return true; // May need to deoptimize
  }
  
  
< prev index next >