8331429: [JVMCI] Cleanup JVMCIRuntime allocation routines
Reviewed-by: dlong, dnsimon
This commit is contained in:
parent
2f10a316ff
commit
957eb611ce
@ -125,23 +125,17 @@ class InternalOOMEMark: public StackObj {
|
||||
|
||||
public:
|
||||
explicit InternalOOMEMark(JavaThread* thread) {
|
||||
if (thread != nullptr) {
|
||||
_outer = thread->is_in_internal_oome_mark();
|
||||
thread->set_is_in_internal_oome_mark(true);
|
||||
_thread = thread;
|
||||
} else {
|
||||
_outer = false;
|
||||
_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;
|
||||
}
|
||||
|
||||
~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);
|
||||
}
|
||||
// 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; }
|
||||
|
@ -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
|
||||
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
|
||||
current->set_vm_result(nullptr);
|
||||
return;
|
||||
}
|
||||
// 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());
|
||||
}
|
||||
// Drop the allocation
|
||||
obj = nullptr;
|
||||
} else {
|
||||
deopt_caller();
|
||||
}
|
||||
@ -183,42 +172,38 @@ 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
|
||||
current->set_vm_result(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
oop obj = klass->allocate_instance(CHECK);
|
||||
|
@ -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);
|
||||
|
@ -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,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)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user