src/share/vm/opto/library_call.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/vm/opto/library_call.cpp	Thu Feb 11 15:30:00 2016
--- new/src/share/vm/opto/library_call.cpp	Thu Feb 11 15:30:00 2016

*** 269,280 **** --- 269,284 ---- // Helper functions for inlining arraycopy bool inline_arraycopy(); AllocateArrayNode* tightly_coupled_allocation(Node* ptr, RegionNode* slow_region); - JVMState* arraycopy_restore_alloc_state(AllocateArrayNode* alloc, int& saved_reexecute_sp); ! void arraycopy_move_allocation_here(AllocateArrayNode* alloc, Node* dest, JVMState* saved_jvms, int saved_reexecute_sp); ! int& saved_reexecute_sp); + void arraycopy_move_allocation_here(AllocateArrayNode* alloc, + Node* dest, + JVMState* saved_jvms, + int saved_reexecute_sp); typedef enum { LS_xadd, LS_xchg, LS_cmpxchg } LoadStoreKind; bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind); bool inline_unsafe_ordered_store(BasicType type); bool inline_unsafe_fence(vmIntrinsics::ID id);
*** 4549,4565 **** --- 4553,4564 ---- // unitialized array will escape the compiled method. To prevent that // we set the JVM state for uncommon traps between the allocation and // the arraycopy to the state before the allocation so, in case of // deoptimization, we'll reexecute the allocation and the // initialization. - JVMState* LibraryCallKit::arraycopy_restore_alloc_state(AllocateArrayNode* alloc, int& saved_reexecute_sp) { ! if (alloc != NULL) { ciMethod* trap_method = alloc->jvms()->method(); int trap_bci = alloc->jvms()->bci(); if (!C->too_many_traps(trap_method, trap_bci, Deoptimization::Reason_intrinsic) & !C->too_many_traps(trap_method, trap_bci, Deoptimization::Reason_null_check)) { ! int& saved_reexecute_sp) { // Make sure there's no store between the allocation and the // arraycopy otherwise visible side effects could be rexecuted // in case of deoptimization and cause incorrect execution. bool no_interfering_store = true; Node* mem = alloc->in(TypeFunc::Memory);
*** 4609,4631 **** --- 4608,4631 ---- set_jvms(sfpt->jvms()); _reexecute_sp = jvms()->sp(); return saved_jvms; } } } return NULL; } // In case of a deoptimization, we restart execution at the // allocation, allocating a new array. We would leave an uninitialized // array in the heap that GCs wouldn't expect. Move the allocation // after the traps so we don't allocate the array if we // deoptimize. This is possible because tightly_coupled_allocation() // guarantees there's no observer of the allocated array at this point // and the control flow is simple enough. - void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, Node* dest, JVMState* saved_jvms, int saved_reexecute_sp) { + Node* dest, + JVMState* saved_jvms, + int saved_reexecute_sp) { if (saved_jvms != NULL && !stopped()) { assert(alloc != NULL, "only with a tightly coupled allocation"); // restore JVM state to the state at the arraycopy saved_jvms->map()->set_control(map()->control()); assert(saved_jvms->map()->memory() == map()->memory(), "memory state changed?");
*** 4692,4709 **** --- 4692,4713 ---- // Check for allocation before we add nodes that would confuse // tightly_coupled_allocation() AllocateArrayNode* alloc = tightly_coupled_allocation(dest, NULL); + ciMethod* alloc_method = NULL; + int alloc_bci = -1; + if (alloc != NULL) { + alloc_method = alloc->jvms()->method(); + alloc_bci = alloc->jvms()->bci(); + } int saved_reexecute_sp = -1; ! JVMState* saved_jvms = arraycopy_restore_alloc_state(alloc, saved_reexecute_sp); // See arraycopy_restore_alloc_state() comment // if alloc == NULL we don't have to worry about a tightly coupled allocation so we can emit all needed guards // if saved_jvms != NULL (then alloc != NULL) then we can handle guards and a tightly coupled allocation // if saved_jvms == NULL and alloc != NULL, we can’t emit any guards bool can_emit_guards = (alloc == NULL || saved_jvms != NULL); ! JVMState* saved_jvms = NULL; + if (alloc != NULL && !C->too_many_traps(alloc_method, alloc_bci, Deoptimization::Reason_null_check)) { + saved_jvms = arraycopy_restore_alloc_state(alloc, saved_reexecute_sp); + } // The following tests must be performed // (1) src and dest are arrays. // (2) src and dest arrays must have elements of the same BasicType // (3) src and dest must not be null.
*** 4719,4739 **** --- 4723,4746 ---- Node* null_ctl = top(); src = saved_jvms != NULL ? null_check_oop(src, &null_ctl, true, true) : null_check(src, T_ARRAY); assert(null_ctl->is_top(), "no null control here"); dest = null_check(dest, T_ARRAY); ! if (!can_emit_guards) { // if saved_jvms == NULL and alloc != NULL, we don't emit any // guards but the arraycopy node could still take advantage of a // tightly allocated allocation. tightly_coupled_allocation() is // called again to make sure it takes the null check above into // account: the null check is mandatory and if it caused an // uncommon trap to be emitted then the allocation can't be // considered tightly coupled in this context. ! if (saved_jvms == NULL) { + // See if the null check above was optimized out (alloc not null) alloc = tightly_coupled_allocation(dest, NULL); + if (alloc != NULL && !C->too_many_traps(alloc_method, alloc_bci, Deoptimization::Reason_intrinsic)) { + saved_jvms = arraycopy_restore_alloc_state(alloc, saved_reexecute_sp); + } } + // See arraycopy_restore_alloc_state() comment + // if alloc == NULL we don't have to worry about a tightly coupled allocation so we can emit all needed guards + // if saved_jvms != NULL (then alloc != NULL) then we can handle guards and a tightly coupled allocation + // if saved_jvms == NULL and alloc != NULL, we can’t emit any guards + bool can_emit_guards = (alloc == NULL || (saved_jvms != NULL && !C->too_many_traps(alloc_method, alloc_bci, Deoptimization::Reason_intrinsic))); + bool validated = false; const Type* src_type = _gvn.type(src); const Type* dest_type = _gvn.type(dest); const TypeAryPtr* top_src = src_type->isa_aryptr();
*** 4832,4849 **** --- 4839,4849 ---- } } } } ciMethod* trap_method = method(); int trap_bci = bci(); if (saved_jvms != NULL) { trap_method = alloc->jvms()->method(); trap_bci = alloc->jvms()->bci(); } if (!C->too_many_traps(trap_method, trap_bci, Deoptimization::Reason_intrinsic) && + if ((alloc != NULL || !C->too_many_traps(method(), bci(), Deoptimization::Reason_intrinsic)) && can_emit_guards && !src->is_top() && !dest->is_top()) { // validate arguments: enables transformation the ArrayCopyNode validated = true;

src/share/vm/opto/library_call.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File