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:
|
public:
|
||||||
explicit InternalOOMEMark(JavaThread* thread) {
|
explicit InternalOOMEMark(JavaThread* thread) {
|
||||||
if (thread != nullptr) {
|
assert(thread != nullptr, "nullptr is not supported");
|
||||||
_outer = thread->is_in_internal_oome_mark();
|
_outer = thread->is_in_internal_oome_mark();
|
||||||
thread->set_is_in_internal_oome_mark(true);
|
thread->set_is_in_internal_oome_mark(true);
|
||||||
_thread = thread;
|
_thread = thread;
|
||||||
} else {
|
|
||||||
_outer = false;
|
|
||||||
_thread = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~InternalOOMEMark() {
|
~InternalOOMEMark() {
|
||||||
if (_thread != nullptr) {
|
// Check that only InternalOOMEMark sets
|
||||||
// Check that only InternalOOMEMark sets
|
// JavaThread::_is_in_internal_oome_mark
|
||||||
// JavaThread::_is_in_internal_oome_mark
|
assert(_thread->is_in_internal_oome_mark(), "must be");
|
||||||
assert(_thread->is_in_internal_oome_mark(), "must be");
|
_thread->set_is_in_internal_oome_mark(_outer);
|
||||||
_thread->set_is_in_internal_oome_mark(_outer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaThread* thread() const { return _thread; }
|
JavaThread* thread() const { return _thread; }
|
||||||
|
@ -102,7 +102,7 @@ class RetryableAllocationMark {
|
|||||||
private:
|
private:
|
||||||
InternalOOMEMark _iom;
|
InternalOOMEMark _iom;
|
||||||
public:
|
public:
|
||||||
RetryableAllocationMark(JavaThread* thread, bool activate) : _iom(activate ? thread : nullptr) {}
|
RetryableAllocationMark(JavaThread* thread) : _iom(thread) {}
|
||||||
~RetryableAllocationMark() {
|
~RetryableAllocationMark() {
|
||||||
JavaThread* THREAD = _iom.thread(); // For exception macros.
|
JavaThread* THREAD = _iom.thread(); // For exception macros.
|
||||||
if (THREAD != nullptr) {
|
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;
|
JRT_BLOCK;
|
||||||
assert(klass->is_klass(), "not a class");
|
assert(klass->is_klass(), "not a class");
|
||||||
Handle holder(current, klass->klass_holder()); // keep the klass alive
|
Handle holder(current, klass->klass_holder()); // keep the klass alive
|
||||||
InstanceKlass* h = InstanceKlass::cast(klass);
|
InstanceKlass* h = InstanceKlass::cast(klass);
|
||||||
{
|
{
|
||||||
RetryableAllocationMark ram(current, null_on_fail);
|
RetryableAllocationMark ram(current);
|
||||||
h->check_valid_for_instantiation(true, CHECK);
|
h->check_valid_for_instantiation(true, CHECK);
|
||||||
oop obj;
|
if (!h->is_initialized()) {
|
||||||
if (null_on_fail) {
|
// Cannot re-execute class initialization without side effects
|
||||||
if (!h->is_initialized()) {
|
// so return without attempting the initialization
|
||||||
// Cannot re-execute class initialization without side effects
|
current->set_vm_result(nullptr);
|
||||||
// so return without attempting the initialization
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// make sure klass is initialized
|
|
||||||
h->initialize(CHECK);
|
|
||||||
}
|
}
|
||||||
// allocate instance and return via TLS
|
// allocate instance and return via TLS
|
||||||
obj = h->allocate_instance(CHECK);
|
oop obj = h->allocate_instance(CHECK);
|
||||||
current->set_vm_result(obj);
|
current->set_vm_result(obj);
|
||||||
}
|
}
|
||||||
JRT_BLOCK_END;
|
JRT_BLOCK_END;
|
||||||
SharedRuntime::on_slowpath_allocation_exit(current);
|
SharedRuntime::on_slowpath_allocation_exit(current);
|
||||||
JRT_END
|
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;
|
JRT_BLOCK;
|
||||||
// Note: no handle for klass needed since they are not used
|
// Note: no handle for klass needed since they are not used
|
||||||
// anymore after new_objArray() and no GC can happen before.
|
// 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;
|
oop obj;
|
||||||
if (array_klass->is_typeArray_klass()) {
|
if (array_klass->is_typeArray_klass()) {
|
||||||
BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type();
|
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);
|
obj = oopFactory::new_typeArray(elt_type, length, CHECK);
|
||||||
} else {
|
} else {
|
||||||
Handle holder(current, array_klass->klass_holder()); // keep the klass alive
|
Handle holder(current, array_klass->klass_holder()); // keep the klass alive
|
||||||
Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass();
|
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);
|
obj = oopFactory::new_objArray(elem_klass, length, CHECK);
|
||||||
}
|
}
|
||||||
// This is pretty rare but this runtime patch is stressful to deoptimization
|
// 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 we deoptimize here so force a deopt to stress the path.
|
||||||
if (DeoptimizeALot) {
|
if (DeoptimizeALot) {
|
||||||
static int deopts = 0;
|
static int deopts = 0;
|
||||||
// Alternate between deoptimizing and raising an error (which will also cause a deopt)
|
|
||||||
if (deopts++ % 2 == 0) {
|
if (deopts++ % 2 == 0) {
|
||||||
if (null_on_fail) {
|
// Drop the allocation
|
||||||
// Drop the allocation
|
obj = nullptr;
|
||||||
obj = nullptr;
|
|
||||||
} else {
|
|
||||||
ResourceMark rm(current);
|
|
||||||
THROW(vmSymbols::java_lang_OutOfMemoryError());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
deopt_caller();
|
deopt_caller();
|
||||||
}
|
}
|
||||||
@ -183,42 +172,38 @@ JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array_common(JavaThread* current, Klass*
|
|||||||
SharedRuntime::on_slowpath_allocation_exit(current);
|
SharedRuntime::on_slowpath_allocation_exit(current);
|
||||||
JRT_END
|
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(klass->is_klass(), "not a class");
|
||||||
assert(rank >= 1, "rank must be nonzero");
|
assert(rank >= 1, "rank must be nonzero");
|
||||||
Handle holder(current, klass->klass_holder()); // keep the klass alive
|
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);
|
oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK);
|
||||||
current->set_vm_result(obj);
|
current->set_vm_result(obj);
|
||||||
JRT_END
|
JRT_END
|
||||||
|
|
||||||
JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array_common(JavaThread* current, oopDesc* element_mirror, jint length, bool null_on_fail))
|
JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array_or_null(JavaThread* current, oopDesc* element_mirror, jint length))
|
||||||
RetryableAllocationMark ram(current, null_on_fail);
|
RetryableAllocationMark ram(current);
|
||||||
oop obj = Reflection::reflect_new_array(element_mirror, length, CHECK);
|
oop obj = Reflection::reflect_new_array(element_mirror, length, CHECK);
|
||||||
current->set_vm_result(obj);
|
current->set_vm_result(obj);
|
||||||
JRT_END
|
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));
|
InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(type_mirror));
|
||||||
|
|
||||||
if (klass == nullptr) {
|
if (klass == nullptr) {
|
||||||
ResourceMark rm(current);
|
ResourceMark rm(current);
|
||||||
THROW(vmSymbols::java_lang_InstantiationException());
|
THROW(vmSymbols::java_lang_InstantiationException());
|
||||||
}
|
}
|
||||||
RetryableAllocationMark ram(current, null_on_fail);
|
RetryableAllocationMark ram(current);
|
||||||
|
|
||||||
// Create new instance (the receiver)
|
// Create new instance (the receiver)
|
||||||
klass->check_valid_for_instantiation(false, CHECK);
|
klass->check_valid_for_instantiation(false, CHECK);
|
||||||
|
|
||||||
if (null_on_fail) {
|
if (!klass->is_initialized()) {
|
||||||
if (!klass->is_initialized()) {
|
// Cannot re-execute class initialization without side effects
|
||||||
// Cannot re-execute class initialization without side effects
|
// so return without attempting the initialization
|
||||||
// so return without attempting the initialization
|
current->set_vm_result(nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Make sure klass gets initialized
|
|
||||||
klass->initialize(CHECK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
oop obj = klass->allocate_instance(CHECK);
|
oop obj = klass->allocate_instance(CHECK);
|
||||||
|
@ -504,34 +504,16 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
|
|||||||
|
|
||||||
static BasicType kindToBasicType(const Handle& kind, TRAPS);
|
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
|
// The following routines are called from compiled JVMCI code
|
||||||
|
|
||||||
// When allocation fails, these stubs:
|
// When allocation fails, these stubs return null and have no pending OutOfMemoryError exception.
|
||||||
// 1. Exercise -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError handling and also
|
// Compiled code can use these stubs if a failed allocation will be retried (e.g., by deoptimizing
|
||||||
// post a JVMTI_EVENT_RESOURCE_EXHAUSTED event if the failure is an OutOfMemroyError
|
// and re-executing in the interpreter).
|
||||||
// 2. Return null with a pending exception.
|
static void new_instance_or_null(JavaThread* thread, Klass* klass);
|
||||||
// Compiled code must ensure these stubs are not called twice for the same allocation
|
static void new_array_or_null(JavaThread* thread, Klass* klass, jint length);
|
||||||
// site due to the non-repeatable side effects in the case of OOME.
|
static void new_multi_array_or_null(JavaThread* thread, Klass* klass, int rank, jint* dims);
|
||||||
static void new_instance(JavaThread* current, Klass* klass) { new_instance_common(current, klass, false); }
|
static void dynamic_new_array_or_null(JavaThread* thread, oopDesc* element_mirror, jint length);
|
||||||
static void new_array(JavaThread* current, Klass* klass, jint length) { new_array_common(current, klass, length, false); }
|
static void dynamic_new_instance_or_null(JavaThread* thread, oopDesc* type_mirror);
|
||||||
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); }
|
|
||||||
|
|
||||||
static void vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3);
|
static void vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3);
|
||||||
static jint identity_hash_code(JavaThread* current, oopDesc* obj);
|
static jint identity_hash_code(JavaThread* current, oopDesc* obj);
|
||||||
|
@ -251,6 +251,8 @@
|
|||||||
nonstatic_field(Klass, _modifier_flags, jint) \
|
nonstatic_field(Klass, _modifier_flags, jint) \
|
||||||
nonstatic_field(Klass, _access_flags, AccessFlags) \
|
nonstatic_field(Klass, _access_flags, AccessFlags) \
|
||||||
nonstatic_field(Klass, _class_loader_data, ClassLoaderData*) \
|
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, start_bci, u2) \
|
||||||
nonstatic_field(LocalVariableTableElement, length, u2) \
|
nonstatic_field(LocalVariableTableElement, length, u2) \
|
||||||
@ -381,6 +383,7 @@
|
|||||||
static_field(StubRoutines, _bigIntegerRightShiftWorker, address) \
|
static_field(StubRoutines, _bigIntegerRightShiftWorker, address) \
|
||||||
static_field(StubRoutines, _bigIntegerLeftShiftWorker, address) \
|
static_field(StubRoutines, _bigIntegerLeftShiftWorker, address) \
|
||||||
static_field(StubRoutines, _cont_thaw, 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, _tlab, ThreadLocalAllocBuffer) \
|
||||||
nonstatic_field(Thread, _allocated_bytes, jlong) \
|
nonstatic_field(Thread, _allocated_bytes, jlong) \
|
||||||
@ -800,39 +803,33 @@
|
|||||||
declare_function(Deoptimization::uncommon_trap) \
|
declare_function(Deoptimization::uncommon_trap) \
|
||||||
declare_function(Deoptimization::unpack_frames) \
|
declare_function(Deoptimization::unpack_frames) \
|
||||||
\
|
\
|
||||||
declare_function(JVMCIRuntime::new_instance) \
|
declare_function(JVMCIRuntime::new_instance_or_null) \
|
||||||
declare_function(JVMCIRuntime::new_array) \
|
declare_function(JVMCIRuntime::new_array_or_null) \
|
||||||
declare_function(JVMCIRuntime::new_multi_array) \
|
declare_function(JVMCIRuntime::new_multi_array_or_null) \
|
||||||
declare_function(JVMCIRuntime::dynamic_new_array) \
|
declare_function(JVMCIRuntime::dynamic_new_array_or_null) \
|
||||||
declare_function(JVMCIRuntime::dynamic_new_instance) \
|
declare_function(JVMCIRuntime::dynamic_new_instance_or_null) \
|
||||||
\
|
\
|
||||||
declare_function(JVMCIRuntime::new_instance_or_null) \
|
declare_function(JVMCIRuntime::invoke_static_method_one_arg) \
|
||||||
declare_function(JVMCIRuntime::new_array_or_null) \
|
\
|
||||||
declare_function(JVMCIRuntime::new_multi_array_or_null) \
|
declare_function(JVMCIRuntime::vm_message) \
|
||||||
declare_function(JVMCIRuntime::dynamic_new_array_or_null) \
|
declare_function(JVMCIRuntime::identity_hash_code) \
|
||||||
declare_function(JVMCIRuntime::dynamic_new_instance_or_null) \
|
declare_function(JVMCIRuntime::exception_handler_for_pc) \
|
||||||
\
|
declare_function(JVMCIRuntime::monitorenter) \
|
||||||
declare_function(JVMCIRuntime::invoke_static_method_one_arg) \
|
declare_function(JVMCIRuntime::monitorexit) \
|
||||||
\
|
declare_function(JVMCIRuntime::object_notify) \
|
||||||
declare_function(JVMCIRuntime::vm_message) \
|
declare_function(JVMCIRuntime::object_notifyAll) \
|
||||||
declare_function(JVMCIRuntime::identity_hash_code) \
|
declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \
|
||||||
declare_function(JVMCIRuntime::exception_handler_for_pc) \
|
declare_function(JVMCIRuntime::throw_klass_external_name_exception) \
|
||||||
declare_function(JVMCIRuntime::monitorenter) \
|
declare_function(JVMCIRuntime::throw_class_cast_exception) \
|
||||||
declare_function(JVMCIRuntime::monitorexit) \
|
declare_function(JVMCIRuntime::log_primitive) \
|
||||||
declare_function(JVMCIRuntime::object_notify) \
|
declare_function(JVMCIRuntime::log_object) \
|
||||||
declare_function(JVMCIRuntime::object_notifyAll) \
|
declare_function(JVMCIRuntime::log_printf) \
|
||||||
declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \
|
declare_function(JVMCIRuntime::vm_error) \
|
||||||
declare_function(JVMCIRuntime::throw_klass_external_name_exception) \
|
declare_function(JVMCIRuntime::load_and_clear_exception) \
|
||||||
declare_function(JVMCIRuntime::throw_class_cast_exception) \
|
G1GC_ONLY(declare_function(JVMCIRuntime::write_barrier_pre)) \
|
||||||
declare_function(JVMCIRuntime::log_primitive) \
|
G1GC_ONLY(declare_function(JVMCIRuntime::write_barrier_post)) \
|
||||||
declare_function(JVMCIRuntime::log_object) \
|
declare_function(JVMCIRuntime::validate_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)
|
declare_function(JVMCIRuntime::test_deoptimize_call_int)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user