6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
Summary: Removed second CheckCastPP and use MembarCPUOrder after arraycopy to cloned object.
Reviewed-by: never
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Sep 10 10:36:24 2009 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp Thu Sep 10 18:18:06 2009 -0700
@@ -3894,7 +3894,6 @@
assert(obj_size != NULL, "");
Node* raw_obj = alloc_obj->in(1);
assert(alloc_obj->is_CheckCastPP() && raw_obj->is_Proj() && raw_obj->in(0)->is_Allocate(), "");
- assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL, "should be more precise than Object");
if (ReduceBulkZeroing) {
// We will be completely responsible for initializing this object -
@@ -3904,19 +3903,10 @@
guarantee(alloc != NULL && alloc->maybe_set_complete(&_gvn), "");
}
- // Cast to Object for arraycopy.
- // We can't use the original CheckCastPP since it should be moved
- // after the arraycopy to prevent stores flowing above it.
- Node* new_obj = new(C, 2) CheckCastPPNode(alloc_obj->in(0), raw_obj,
- TypeInstPtr::NOTNULL);
- new_obj = _gvn.transform(new_obj);
- // Substitute in the locally valid dest_oop.
- replace_in_map(alloc_obj, new_obj);
-
// Copy the fastest available way.
// TODO: generate fields copies for small objects instead.
Node* src = obj;
- Node* dest = new_obj;
+ Node* dest = alloc_obj;
Node* size = _gvn.transform(obj_size);
// Exclude the header but include array length to copy by 8 bytes words.
@@ -3962,7 +3952,7 @@
int raw_adr_idx = Compile::AliasIdxRaw;
post_barrier(control(),
memory(raw_adr_type),
- new_obj,
+ alloc_obj,
no_particular_field,
raw_adr_idx,
no_particular_value,
@@ -3970,16 +3960,8 @@
false);
}
- // Move the original CheckCastPP after arraycopy.
- _gvn.hash_delete(alloc_obj);
- alloc_obj->set_req(0, control());
- // Replace raw memory edge with new CheckCastPP to have a live oop
- // at safepoints instead of raw value.
- assert(new_obj->is_CheckCastPP() && new_obj->in(1) == alloc_obj->in(1), "sanity");
- alloc_obj->set_req(1, new_obj); // cast to the original type
- _gvn.hash_find_insert(alloc_obj); // put back into GVN table
- // Restore in the locally valid dest_oop.
- replace_in_map(new_obj, alloc_obj);
+ // Do not let reads from the cloned object float above the arraycopy.
+ insert_mem_bar(Op_MemBarCPUOrder);
}
//------------------------inline_native_clone----------------------------
@@ -4448,17 +4430,7 @@
InitializeNode* init = alloc->initialization();
assert(init->is_complete(), "we just did this");
assert(dest->is_CheckCastPP(), "sanity");
- assert(dest->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL, "type should be more precise than Object");
assert(dest->in(0)->in(0) == init, "dest pinned");
-
- // Cast to Object for arraycopy.
- // We can't use the original CheckCastPP since it should be moved
- // after the arraycopy to prevent stores flowing above it.
- Node* new_obj = new(C, 2) CheckCastPPNode(dest->in(0), dest->in(1),
- TypeInstPtr::NOTNULL);
- dest = _gvn.transform(new_obj);
- // Substitute in the locally valid dest_oop.
- replace_in_map(original_dest, dest);
adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory
// From this point on, every exit path is responsible for
// initializing any non-copied parts of the object to zero.
@@ -4788,18 +4760,6 @@
set_i_o( _gvn.transform(result_i_o) );
set_memory( _gvn.transform(result_memory), adr_type );
- if (dest != original_dest) {
- // Pin the "finished" array node after the arraycopy/zeroing operations.
- _gvn.hash_delete(original_dest);
- original_dest->set_req(0, control());
- // Replace raw memory edge with new CheckCastPP to have a live oop
- // at safepoints instead of raw value.
- assert(dest->is_CheckCastPP() && dest->in(1) == original_dest->in(1), "sanity");
- original_dest->set_req(1, dest); // cast to the original type
- _gvn.hash_find_insert(original_dest); // put back into GVN table
- // Restore in the locally valid dest_oop.
- replace_in_map(dest, original_dest);
- }
// The memory edges above are precise in order to model effects around
// array copies accurately to allow value numbering of field loads around
// arraycopy. Such field loads, both before and after, are common in Java
@@ -4810,7 +4770,9 @@
// The next memory barrier is added to avoid it. If the arraycopy can be
// optimized away (which it can, sometimes) then we can manually remove
// the membar also.
- if (InsertMemBarAfterArraycopy)
+ //
+ // Do not let reads from the cloned object float above the arraycopy.
+ if (InsertMemBarAfterArraycopy || alloc != NULL)
insert_mem_bar(Op_MemBarCPUOrder);
}
--- a/hotspot/src/share/vm/opto/type.cpp Thu Sep 10 10:36:24 2009 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp Thu Sep 10 18:18:06 2009 -0700
@@ -2236,12 +2236,12 @@
//------------------------------make-------------------------------------------
const TypeOopPtr *TypeOopPtr::make(PTR ptr,
- int offset) {
+ int offset, int instance_id) {
assert(ptr != Constant, "no constant generic pointers");
ciKlass* k = ciKlassKlass::make();
bool xk = false;
ciObject* o = NULL;
- return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, InstanceBot))->hashcons();
+ return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id))->hashcons();
}
@@ -2330,7 +2330,8 @@
case OopPtr: { // Meeting to other OopPtrs
const TypeOopPtr *tp = t->is_oopptr();
- return make( meet_ptr(tp->ptr()), meet_offset(tp->offset()) );
+ int instance_id = meet_instance_id(tp->instance_id());
+ return make( meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id );
}
case InstPtr: // For these, flip the call around to cut down
@@ -2801,7 +2802,7 @@
case OopPtr: { // Meeting to OopPtrs
// Found a OopPtr type vs self-InstPtr type
- const TypePtr *tp = t->is_oopptr();
+ const TypeOopPtr *tp = t->is_oopptr();
int offset = meet_offset(tp->offset());
PTR ptr = meet_ptr(tp->ptr());
switch (tp->ptr()) {
@@ -2812,8 +2813,10 @@
(ptr == Constant ? const_oop() : NULL), offset, instance_id);
}
case NotNull:
- case BotPTR:
- return TypeOopPtr::make(ptr, offset);
+ case BotPTR: {
+ int instance_id = meet_instance_id(tp->instance_id());
+ return TypeOopPtr::make(ptr, offset, instance_id);
+ }
default: typerr(t);
}
}
@@ -3259,7 +3262,7 @@
case OopPtr: { // Meeting to OopPtrs
// Found a OopPtr type vs self-AryPtr type
- const TypePtr *tp = t->is_oopptr();
+ const TypeOopPtr *tp = t->is_oopptr();
int offset = meet_offset(tp->offset());
PTR ptr = meet_ptr(tp->ptr());
switch (tp->ptr()) {
@@ -3270,8 +3273,10 @@
_ary, _klass, _klass_is_exact, offset, instance_id);
}
case BotPTR:
- case NotNull:
- return TypeOopPtr::make(ptr, offset);
+ case NotNull: {
+ int instance_id = meet_instance_id(tp->instance_id());
+ return TypeOopPtr::make(ptr, offset, instance_id);
+ }
default: ShouldNotReachHere();
}
}
--- a/hotspot/src/share/vm/opto/type.hpp Thu Sep 10 10:36:24 2009 -0700
+++ b/hotspot/src/share/vm/opto/type.hpp Thu Sep 10 18:18:06 2009 -0700
@@ -714,7 +714,7 @@
static const TypeOopPtr* make_from_constant(ciObject* o);
// Make a generic (unclassed) pointer to an oop.
- static const TypeOopPtr* make(PTR ptr, int offset);
+ static const TypeOopPtr* make(PTR ptr, int offset, int instance_id = InstanceBot);
ciObject* const_oop() const { return _const_oop; }
virtual ciKlass* klass() const { return _klass; }