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