8331429: [JVMCI] Cleanup JVMCIRuntime allocation routines

Reviewed-by: dlong, dnsimon
This commit is contained in:
Yudi Zheng 2024-05-15 09:35:11 +00:00 committed by Doug Simon
parent 2f10a316ff
commit 957eb611ce
4 changed files with 71 additions and 113 deletions

View File

@ -125,24 +125,18 @@ class InternalOOMEMark: public StackObj {
public:
explicit InternalOOMEMark(JavaThread* thread) {
if (thread != nullptr) {
assert(thread != nullptr, "nullptr is not supported");
_outer = thread->is_in_internal_oome_mark();
thread->set_is_in_internal_oome_mark(true);
_thread = thread;
} else {
_outer = false;
_thread = nullptr;
}
}
~InternalOOMEMark() {
if (_thread != nullptr) {
// Check that only InternalOOMEMark sets
// JavaThread::_is_in_internal_oome_mark
assert(_thread->is_in_internal_oome_mark(), "must be");
_thread->set_is_in_internal_oome_mark(_outer);
}
}
JavaThread* thread() const { return _thread; }
};

View File

@ -102,7 +102,7 @@ class RetryableAllocationMark {
private:
InternalOOMEMark _iom;
public:
RetryableAllocationMark(JavaThread* thread, bool activate) : _iom(activate ? thread : nullptr) {}
RetryableAllocationMark(JavaThread* thread) : _iom(thread) {}
~RetryableAllocationMark() {
JavaThread* THREAD = _iom.thread(); // For exception macros.
if (THREAD != nullptr) {
@ -117,34 +117,29 @@ class RetryableAllocationMark {
}
};
JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance_common(JavaThread* current, Klass* klass, bool null_on_fail))
JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance_or_null(JavaThread* current, Klass* klass))
JRT_BLOCK;
assert(klass->is_klass(), "not a class");
Handle holder(current, klass->klass_holder()); // keep the klass alive
InstanceKlass* h = InstanceKlass::cast(klass);
{
RetryableAllocationMark ram(current, null_on_fail);
RetryableAllocationMark ram(current);
h->check_valid_for_instantiation(true, CHECK);
oop obj;
if (null_on_fail) {
if (!h->is_initialized()) {
// Cannot re-execute class initialization without side effects
// so return without attempting the initialization
current->set_vm_result(nullptr);
return;
}
} else {
// make sure klass is initialized
h->initialize(CHECK);
}
// allocate instance and return via TLS
obj = h->allocate_instance(CHECK);
oop obj = h->allocate_instance(CHECK);
current->set_vm_result(obj);
}
JRT_BLOCK_END;
SharedRuntime::on_slowpath_allocation_exit(current);
JRT_END
JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array_common(JavaThread* current, Klass* array_klass, jint length, bool null_on_fail))
JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array_or_null(JavaThread* current, Klass* array_klass, jint length))
JRT_BLOCK;
// Note: no handle for klass needed since they are not used
// anymore after new_objArray() and no GC can happen before.
@ -153,27 +148,21 @@ JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array_common(JavaThread* current, Klass*
oop obj;
if (array_klass->is_typeArray_klass()) {
BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type();
RetryableAllocationMark ram(current, null_on_fail);
RetryableAllocationMark ram(current);
obj = oopFactory::new_typeArray(elt_type, length, CHECK);
} else {
Handle holder(current, array_klass->klass_holder()); // keep the klass alive
Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass();
RetryableAllocationMark ram(current, null_on_fail);
RetryableAllocationMark ram(current);
obj = oopFactory::new_objArray(elem_klass, length, CHECK);
}
// This is pretty rare but this runtime patch is stressful to deoptimization
// if we deoptimize here so force a deopt to stress the path.
if (DeoptimizeALot) {
static int deopts = 0;
// Alternate between deoptimizing and raising an error (which will also cause a deopt)
if (deopts++ % 2 == 0) {
if (null_on_fail) {
// Drop the allocation
obj = nullptr;
} else {
ResourceMark rm(current);
THROW(vmSymbols::java_lang_OutOfMemoryError());
}
} else {
deopt_caller();
}
@ -183,43 +172,39 @@ JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array_common(JavaThread* current, Klass*
SharedRuntime::on_slowpath_allocation_exit(current);
JRT_END
JRT_ENTRY(void, JVMCIRuntime::new_multi_array_common(JavaThread* current, Klass* klass, int rank, jint* dims, bool null_on_fail))
JRT_ENTRY(void, JVMCIRuntime::new_multi_array_or_null(JavaThread* current, Klass* klass, int rank, jint* dims))
assert(klass->is_klass(), "not a class");
assert(rank >= 1, "rank must be nonzero");
Handle holder(current, klass->klass_holder()); // keep the klass alive
RetryableAllocationMark ram(current, null_on_fail);
RetryableAllocationMark ram(current);
oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK);
current->set_vm_result(obj);
JRT_END
JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array_common(JavaThread* current, oopDesc* element_mirror, jint length, bool null_on_fail))
RetryableAllocationMark ram(current, null_on_fail);
JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array_or_null(JavaThread* current, oopDesc* element_mirror, jint length))
RetryableAllocationMark ram(current);
oop obj = Reflection::reflect_new_array(element_mirror, length, CHECK);
current->set_vm_result(obj);
JRT_END
JRT_ENTRY(void, JVMCIRuntime::dynamic_new_instance_common(JavaThread* current, oopDesc* type_mirror, bool null_on_fail))
JRT_ENTRY(void, JVMCIRuntime::dynamic_new_instance_or_null(JavaThread* current, oopDesc* type_mirror))
InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(type_mirror));
if (klass == nullptr) {
ResourceMark rm(current);
THROW(vmSymbols::java_lang_InstantiationException());
}
RetryableAllocationMark ram(current, null_on_fail);
RetryableAllocationMark ram(current);
// Create new instance (the receiver)
klass->check_valid_for_instantiation(false, CHECK);
if (null_on_fail) {
if (!klass->is_initialized()) {
// Cannot re-execute class initialization without side effects
// so return without attempting the initialization
current->set_vm_result(nullptr);
return;
}
} else {
// Make sure klass gets initialized
klass->initialize(CHECK);
}
oop obj = klass->allocate_instance(CHECK);
current->set_vm_result(obj);

View File

@ -504,34 +504,16 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
static BasicType kindToBasicType(const Handle& kind, TRAPS);
static void new_instance_common(JavaThread* current, Klass* klass, bool null_on_fail);
static void new_array_common(JavaThread* current, Klass* klass, jint length, bool null_on_fail);
static void new_multi_array_common(JavaThread* current, Klass* klass, int rank, jint* dims, bool null_on_fail);
static void dynamic_new_array_common(JavaThread* current, oopDesc* element_mirror, jint length, bool null_on_fail);
static void dynamic_new_instance_common(JavaThread* current, oopDesc* type_mirror, bool null_on_fail);
// The following routines are called from compiled JVMCI code
// When allocation fails, these stubs:
// 1. Exercise -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError handling and also
// post a JVMTI_EVENT_RESOURCE_EXHAUSTED event if the failure is an OutOfMemroyError
// 2. Return null with a pending exception.
// Compiled code must ensure these stubs are not called twice for the same allocation
// site due to the non-repeatable side effects in the case of OOME.
static void new_instance(JavaThread* current, Klass* klass) { new_instance_common(current, klass, false); }
static void new_array(JavaThread* current, Klass* klass, jint length) { new_array_common(current, klass, length, false); }
static void new_multi_array(JavaThread* current, Klass* klass, int rank, jint* dims) { new_multi_array_common(current, klass, rank, dims, false); }
static void dynamic_new_array(JavaThread* current, oopDesc* element_mirror, jint length) { dynamic_new_array_common(current, element_mirror, length, false); }
static void dynamic_new_instance(JavaThread* current, oopDesc* type_mirror) { dynamic_new_instance_common(current, type_mirror, false); }
// When allocation fails, these stubs return null and have no pending exception. Compiled code
// can use these stubs if a failed allocation will be retried (e.g., by deoptimizing and
// re-executing in the interpreter).
static void new_instance_or_null(JavaThread* thread, Klass* klass) { new_instance_common(thread, klass, true); }
static void new_array_or_null(JavaThread* thread, Klass* klass, jint length) { new_array_common(thread, klass, length, true); }
static void new_multi_array_or_null(JavaThread* thread, Klass* klass, int rank, jint* dims) { new_multi_array_common(thread, klass, rank, dims, true); }
static void dynamic_new_array_or_null(JavaThread* thread, oopDesc* element_mirror, jint length) { dynamic_new_array_common(thread, element_mirror, length, true); }
static void dynamic_new_instance_or_null(JavaThread* thread, oopDesc* type_mirror) { dynamic_new_instance_common(thread, type_mirror, true); }
// When allocation fails, these stubs return null and have no pending OutOfMemoryError exception.
// Compiled code can use these stubs if a failed allocation will be retried (e.g., by deoptimizing
// and re-executing in the interpreter).
static void new_instance_or_null(JavaThread* thread, Klass* klass);
static void new_array_or_null(JavaThread* thread, Klass* klass, jint length);
static void new_multi_array_or_null(JavaThread* thread, Klass* klass, int rank, jint* dims);
static void dynamic_new_array_or_null(JavaThread* thread, oopDesc* element_mirror, jint length);
static void dynamic_new_instance_or_null(JavaThread* thread, oopDesc* type_mirror);
static void vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3);
static jint identity_hash_code(JavaThread* current, oopDesc* obj);

View File

@ -251,6 +251,8 @@
nonstatic_field(Klass, _modifier_flags, jint) \
nonstatic_field(Klass, _access_flags, AccessFlags) \
nonstatic_field(Klass, _class_loader_data, ClassLoaderData*) \
nonstatic_field(Klass, _bitmap, uintx) \
nonstatic_field(Klass, _hash_slot, uint8_t) \
\
nonstatic_field(LocalVariableTableElement, start_bci, u2) \
nonstatic_field(LocalVariableTableElement, length, u2) \
@ -381,6 +383,7 @@
static_field(StubRoutines, _bigIntegerRightShiftWorker, address) \
static_field(StubRoutines, _bigIntegerLeftShiftWorker, address) \
static_field(StubRoutines, _cont_thaw, address) \
static_field(StubRoutines, _lookup_secondary_supers_table_slow_path_stub, address) \
\
nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \
nonstatic_field(Thread, _allocated_bytes, jlong) \
@ -800,12 +803,6 @@
declare_function(Deoptimization::uncommon_trap) \
declare_function(Deoptimization::unpack_frames) \
\
declare_function(JVMCIRuntime::new_instance) \
declare_function(JVMCIRuntime::new_array) \
declare_function(JVMCIRuntime::new_multi_array) \
declare_function(JVMCIRuntime::dynamic_new_array) \
declare_function(JVMCIRuntime::dynamic_new_instance) \
\
declare_function(JVMCIRuntime::new_instance_or_null) \
declare_function(JVMCIRuntime::new_array_or_null) \
declare_function(JVMCIRuntime::new_multi_array_or_null) \