Thanks for re-reviewing. -Doug
> On 5 Oct 2018, at 18:05, Vladimir Kozlov <vladimir.koz...@oracle.com> wrote: > > Looks good. > > Thanks, > Vladimir > > On 10/5/18 8:22 AM, Doug Simon wrote: >> Hi, >> Testing found a bug in the original webrev. Namely, when clearing out a >> pending exception and returning null in the JVMCI ..._or_null stubs, the >> JavaThread::_vm_result field was not being set to NULL. I've addressed this >> in v2 of the webrev: >> Relative diff for bug fix: >> ----------------------------------------------------------------------------------------------- >> -// Manages a scope in which a failed heap allocation will throw an >> exception. >> -// The pending exception is cleared when leaving the scope. >> +// Manages a scope for a JVMCI runtime call that attempts a heap allocation. >> +// If there is a pending exception upon closing the scope and the runtime >> +// call is of the variety where allocation failure returns NULL without an >> +// exception, the following action is taken: >> +// 1. The pending exception is cleared >> +// 2. NULL is written to JavaThread::_vm_result >> +// 3. Checks that an OutOfMemoryError is >> Universe::out_of_memory_error_retry(). >> class RetryableAllocationMark: public StackObj { >> private: >> JavaThread* _thread; >> public: >> RetryableAllocationMark(JavaThread* thread, bool activate) { >> if (activate) { >> - assert(thread->in_retryable_allocation(), "retryable allocation scope >> is non-reentrant"); >> + assert(!thread->in_retryable_allocation(), "retryable allocation >> scope is non-reentrant"); >> _thread = thread; >> _thread->set_in_retryable_allocation(true); >> } else { >> @@ -136,6 +141,7 @@ >> ResourceMark rm; >> fatal("Unexpected exception in scope of retryable allocation: " >> INTPTR_FORMAT " of type %s", p2i(ex), ex->klass()->external_name()); >> } >> + _thread->set_vm_result(NULL); >> } >> } >> } >> ----------------------------------------------------------------------------------------------- >> I also took the opportunity to factor out negative array length checking: >> ----------------------------------------------------------------------------------------------- >> diff -r 4d36f5998a8b src/hotspot/share/oops/arrayKlass.cpp >> --- a/src/hotspot/share/oops/arrayKlass.cpp Fri Oct 05 17:04:06 2018 +0200 >> +++ b/src/hotspot/share/oops/arrayKlass.cpp Fri Oct 05 17:17:17 2018 +0200 >> @@ -130,9 +130,6 @@ >> } >> objArrayOop ArrayKlass::allocate_arrayArray(int n, int length, TRAPS) { >> - if (length < 0) { >> - THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), >> err_msg("%d", length)); >> - } >> check_array_allocation_length(length, >> arrayOopDesc::max_array_length(T_ARRAY), CHECK_0); >> int size = objArrayOopDesc::object_size(length); >> Klass* k = array_klass(n+dimension(), CHECK_0); >> diff -r 4d36f5998a8b src/hotspot/share/oops/instanceKlass.cpp >> --- a/src/hotspot/share/oops/instanceKlass.cpp Fri Oct 05 17:04:06 >> 2018 +0200 >> +++ b/src/hotspot/share/oops/instanceKlass.cpp Fri Oct 05 17:17:17 >> 2018 +0200 >> @@ -1201,9 +1201,6 @@ >> } >> objArrayOop InstanceKlass::allocate_objArray(int n, int length, TRAPS) { >> - if (length < 0) { >> - THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), >> err_msg("%d", length)); >> - } >> check_array_allocation_length(length, >> arrayOopDesc::max_array_length(T_OBJECT), CHECK_NULL); >> int size = objArrayOopDesc::object_size(length); >> Klass* ak = array_klass(n, CHECK_NULL); >> diff -r 4d36f5998a8b src/hotspot/share/oops/klass.cpp >> --- a/src/hotspot/share/oops/klass.cpp Fri Oct 05 17:04:06 2018 +0200 >> +++ b/src/hotspot/share/oops/klass.cpp Fri Oct 05 17:17:17 2018 +0200 >> @@ -620,6 +620,8 @@ >> } else { >> THROW_OOP(Universe::out_of_memory_error_retry()); >> } >> + } else if (length < 0) { >> + THROW_MSG(vmSymbols::java_lang_NegativeArraySizeException(), >> err_msg("%d", length)); >> } >> } >> diff -r 4d36f5998a8b src/hotspot/share/oops/klass.hpp >> --- a/src/hotspot/share/oops/klass.hpp Fri Oct 05 17:04:06 2018 +0200 >> +++ b/src/hotspot/share/oops/klass.hpp Fri Oct 05 17:17:17 2018 +0200 >> @@ -514,7 +514,7 @@ >> virtual Klass* array_klass_impl(bool or_null, int rank, TRAPS); >> virtual Klass* array_klass_impl(bool or_null, TRAPS); >> - // Error handling when length > max_length >> + // Error handling when length > max_length or length < 0 >> static void check_array_allocation_length(int length, int max_length, >> TRAPS); >> void set_vtable_length(int len) { _vtable_len= len; } >> diff -r 4d36f5998a8b src/hotspot/share/oops/objArrayKlass.cpp >> --- a/src/hotspot/share/oops/objArrayKlass.cpp Fri Oct 05 17:04:06 >> 2018 +0200 >> +++ b/src/hotspot/share/oops/objArrayKlass.cpp Fri Oct 05 17:17:17 >> 2018 +0200 >> @@ -170,14 +170,10 @@ >> } >> objArrayOop ObjArrayKlass::allocate(int length, TRAPS) { >> - if (length >= 0) { >> - check_array_allocation_length(length, >> arrayOopDesc::max_array_length(T_OBJECT), CHECK_0); >> - int size = objArrayOopDesc::object_size(length); >> - return (objArrayOop)Universe::heap()->array_allocate(this, size, length, >> - /* do_zero */ >> true, THREAD); >> - } else { >> - THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), >> err_msg("%d", length)); >> - } >> + check_array_allocation_length(length, >> arrayOopDesc::max_array_length(T_OBJECT), CHECK_0); >> + int size = objArrayOopDesc::object_size(length); >> + return (objArrayOop)Universe::heap()->array_allocate(this, size, length, >> + /* do_zero */ true, >> THREAD); >> } >> static int multi_alloc_counter = 0; >> diff -r 4d36f5998a8b src/hotspot/share/oops/typeArrayKlass.cpp >> --- a/src/hotspot/share/oops/typeArrayKlass.cpp Fri Oct 05 17:04:06 >> 2018 +0200 >> +++ b/src/hotspot/share/oops/typeArrayKlass.cpp Fri Oct 05 17:17:17 >> 2018 +0200 >> @@ -99,14 +99,10 @@ >> typeArrayOop TypeArrayKlass::allocate_common(int length, bool do_zero, >> TRAPS) { >> assert(log2_element_size() >= 0, "bad scale"); >> - if (length >= 0) { >> - check_array_allocation_length(length, max_length(), CHECK_NULL); >> - size_t size = typeArrayOopDesc::object_size(layout_helper(), length); >> - return (typeArrayOop)Universe::heap()->array_allocate(this, (int)size, >> length, >> - do_zero, >> CHECK_NULL); >> - } else { >> - THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), >> err_msg("%d", length)); >> - } >> + check_array_allocation_length(length, max_length(), CHECK_NULL); >> + size_t size = typeArrayOopDesc::object_size(layout_helper(), length); >> + return (typeArrayOop)Universe::heap()->array_allocate(this, (int)size, >> length, >> + do_zero, >> CHECK_NULL); >> } >> oop TypeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) { >> ----------------------------------------------------------------------------------------------- >> Please confirm review these new changes: >> http://cr.openjdk.java.net/~dnsimon/8208686v2 >> -Doug >>> On 4 Oct 2018, at 00:20, Doug Simon <doug.si...@oracle.com> wrote: >>> >>> Thanks for the reviews Serguei and Vladimir. >>> >>> Unless I hear objections in the next 24 hours, I'll push this webrev. >>> >>> -Doug >>> >>>> On 3 Oct 2018, at 03:14, serguei.spit...@oracle.com wrote: >>>> >>>> Hi Doug, >>>> >>>> The JVMTI related part looks good to me. >>>> Thank you for fixing it! >>>> >>>> Thanks, >>>> Serguei >>>> >>>> On 10/2/18 1:11 AM, Doug Simon wrote: >>>>> It would be great to get some input from the non-compilers teams on this >>>>> RFR. >>>>> >>>>> -Doug >>>>> >>>>>> On 28 Sep 2018, at 19:51, Vladimir Kozlov <vladimir.koz...@oracle.com> >>>>>> wrote: >>>>>> >>>>>> To let you know, me and Tom R. did review these changes and agreed that >>>>>> it is the least intrusive changes for Hotspot shared code. >>>>>> >>>>>> Thanks, >>>>>> Vladimir >>>>>> >>>>>> On 9/25/18 8:11 AM, Daniel D. Daugherty wrote: >>>>>>> Adding serviceability-dev@... since this is JVM/TI... >>>>>>> Dan >>>>>>> On 9/25/18 10:48 AM, Doug Simon wrote: >>>>>>>> A major design point of Graal is to treat allocations as non-side >>>>>>>> effecting to give more freedom to the optimizer by reducing the number >>>>>>>> of distinct FrameStates that need to be managed. When failing an >>>>>>>> allocation, Graal will deoptimize to the last side effecting >>>>>>>> instruction before the allocation. This mean the VM code for heap >>>>>>>> allocation will potentially be executed twice, once from Graal >>>>>>>> compiled code and then again in the interpreter. While this is >>>>>>>> perfectly fine according to the JVM specification, it can cause >>>>>>>> confusing behavior for JVMTI based tools. They will receive 2 >>>>>>>> ResourceExhausted events for a single allocation. Furthermore, the >>>>>>>> first ResourceExhausted event (on the Graal allocation slow path) >>>>>>>> might denote a bytecode instruction that performs no allocation, >>>>>>>> making it hard to debug the memory failure. >>>>>>>> >>>>>>>> The proposed solution is to add an extra set of JVMCI VM runtime calls >>>>>>>> for allocation. These entry points will attempt the allocation and >>>>>>>> upon failure, >>>>>>>> skip side-effects such as posting JVMTI events or handling >>>>>>>> -XX:OnOutOfMemoryError. The compiled code using these entry points is >>>>>>>> expected deoptmize on null. >>>>>>>> >>>>>>>> The path from these new entry points to where allocation can fail goes >>>>>>>> through quite a bit of VM code. One could modify all these paths by: >>>>>>>> * Returning null instead of throwing an exception on failure. >>>>>>>> * Adding a `bool null_on_fail` argument to all relevant methods. >>>>>>>> * Adding extra null checking where necessary after each call to these >>>>>>>> methods when `null_on_fail == true`. >>>>>>>> This represents a significant number of changes. >>>>>>>> >>>>>>>> Instead, the proposed solution introduces a new >>>>>>>> _in_retryable_allocation thread-local. This way, only the entry points >>>>>>>> and allocation routines that raise an exception need to be modified. >>>>>>>> Failure is communicated back to the new entry points by throwing a >>>>>>>> special pre-allocated OOME object (i.e., >>>>>>>> Universe::out_of_memory_error_retry()) which must not propagate back >>>>>>>> to Java code. Use of this object is not strictly necessary; it is >>>>>>>> introduced to highlight/document the special allocation mode. >>>>>>>> >>>>>>>> The proposed solution is at >>>>>>>> http://cr.openjdk.java.net/~dnsimon/8208686. >>>>>>>> THE JBS bug is: https://bugs.openjdk.java.net/browse/JDK-8208686 >>>>>>>> >>>>>>>> -Doug >>>> >>>