Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8331429: [JVMCI] Cleanup JVMCIRuntime allocation routines #19176

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
63 changes: 23 additions & 40 deletions src/hotspot/share/jvmci/jvmciRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -117,34 +117,28 @@ 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
return;
}
} else {
// make sure klass is initialized
h->initialize(CHECK);
if (!h->is_initialized()) {
// Cannot re-execute class initialization without side effects
// so return without attempting the initialization
return;
mur47x111 marked this conversation as resolved.
Show resolved Hide resolved
}
// 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.
Expand All @@ -153,27 +147,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());
}
// Drop the allocation
obj = nullptr;
} else {
deopt_caller();
}
Expand All @@ -183,42 +171,37 @@ 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
return;
}
} else {
// Make sure klass gets initialized
klass->initialize(CHECK);
if (!klass->is_initialized()) {
// Cannot re-execute class initialization without side effects
// so return without attempting the initialization
return;
}

oop obj = klass->allocate_instance(CHECK);
Expand Down
28 changes: 5 additions & 23 deletions src/hotspot/share/jvmci/jvmciRuntime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
mur47x111 marked this conversation as resolved.
Show resolved Hide resolved
// 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); }
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);
Expand Down
63 changes: 30 additions & 33 deletions src/hotspot/share/jvmci/vmStructs_jvmci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down Expand Up @@ -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) \
Expand Down Expand Up @@ -800,39 +803,33 @@
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) \
declare_function(JVMCIRuntime::dynamic_new_array_or_null) \
declare_function(JVMCIRuntime::dynamic_new_instance_or_null) \
\
declare_function(JVMCIRuntime::invoke_static_method_one_arg) \
\
declare_function(JVMCIRuntime::vm_message) \
declare_function(JVMCIRuntime::identity_hash_code) \
declare_function(JVMCIRuntime::exception_handler_for_pc) \
declare_function(JVMCIRuntime::monitorenter) \
declare_function(JVMCIRuntime::monitorexit) \
declare_function(JVMCIRuntime::object_notify) \
declare_function(JVMCIRuntime::object_notifyAll) \
declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \
declare_function(JVMCIRuntime::throw_klass_external_name_exception) \
declare_function(JVMCIRuntime::throw_class_cast_exception) \
declare_function(JVMCIRuntime::log_primitive) \
declare_function(JVMCIRuntime::log_object) \
declare_function(JVMCIRuntime::log_printf) \
declare_function(JVMCIRuntime::vm_error) \
declare_function(JVMCIRuntime::load_and_clear_exception) \
G1GC_ONLY(declare_function(JVMCIRuntime::write_barrier_pre)) \
G1GC_ONLY(declare_function(JVMCIRuntime::write_barrier_post)) \
declare_function(JVMCIRuntime::validate_object) \
\
declare_function(JVMCIRuntime::new_instance_or_null) \
declare_function(JVMCIRuntime::new_array_or_null) \
declare_function(JVMCIRuntime::new_multi_array_or_null) \
declare_function(JVMCIRuntime::dynamic_new_array_or_null) \
declare_function(JVMCIRuntime::dynamic_new_instance_or_null) \
\
declare_function(JVMCIRuntime::invoke_static_method_one_arg) \
\
declare_function(JVMCIRuntime::vm_message) \
declare_function(JVMCIRuntime::identity_hash_code) \
declare_function(JVMCIRuntime::exception_handler_for_pc) \
declare_function(JVMCIRuntime::monitorenter) \
declare_function(JVMCIRuntime::monitorexit) \
declare_function(JVMCIRuntime::object_notify) \
declare_function(JVMCIRuntime::object_notifyAll) \
declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \
declare_function(JVMCIRuntime::throw_klass_external_name_exception) \
declare_function(JVMCIRuntime::throw_class_cast_exception) \
declare_function(JVMCIRuntime::log_primitive) \
declare_function(JVMCIRuntime::log_object) \
declare_function(JVMCIRuntime::log_printf) \
declare_function(JVMCIRuntime::vm_error) \
declare_function(JVMCIRuntime::load_and_clear_exception) \
G1GC_ONLY(declare_function(JVMCIRuntime::write_barrier_pre)) \
G1GC_ONLY(declare_function(JVMCIRuntime::write_barrier_post)) \
declare_function(JVMCIRuntime::validate_object) \
\
declare_function(JVMCIRuntime::test_deoptimize_call_int)


Expand Down