< prev index next > src/hotspot/share/prims/jvmtiImpl.cpp
Print this page
/*
! * 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.
/*
! * 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.
#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"
#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"
, _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.
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() {
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 >