Thu, 10 Sep 2009 18:18:06 -0700
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
Summary: Removed second CheckCastPP and use MembarCPUOrder after arraycopy to cloned object.
Reviewed-by: never
1.1 --- a/src/share/vm/opto/library_call.cpp Thu Sep 10 10:36:24 2009 -0700 1.2 +++ b/src/share/vm/opto/library_call.cpp Thu Sep 10 18:18:06 2009 -0700 1.3 @@ -3894,7 +3894,6 @@ 1.4 assert(obj_size != NULL, ""); 1.5 Node* raw_obj = alloc_obj->in(1); 1.6 assert(alloc_obj->is_CheckCastPP() && raw_obj->is_Proj() && raw_obj->in(0)->is_Allocate(), ""); 1.7 - assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL, "should be more precise than Object"); 1.8 1.9 if (ReduceBulkZeroing) { 1.10 // We will be completely responsible for initializing this object - 1.11 @@ -3904,19 +3903,10 @@ 1.12 guarantee(alloc != NULL && alloc->maybe_set_complete(&_gvn), ""); 1.13 } 1.14 1.15 - // Cast to Object for arraycopy. 1.16 - // We can't use the original CheckCastPP since it should be moved 1.17 - // after the arraycopy to prevent stores flowing above it. 1.18 - Node* new_obj = new(C, 2) CheckCastPPNode(alloc_obj->in(0), raw_obj, 1.19 - TypeInstPtr::NOTNULL); 1.20 - new_obj = _gvn.transform(new_obj); 1.21 - // Substitute in the locally valid dest_oop. 1.22 - replace_in_map(alloc_obj, new_obj); 1.23 - 1.24 // Copy the fastest available way. 1.25 // TODO: generate fields copies for small objects instead. 1.26 Node* src = obj; 1.27 - Node* dest = new_obj; 1.28 + Node* dest = alloc_obj; 1.29 Node* size = _gvn.transform(obj_size); 1.30 1.31 // Exclude the header but include array length to copy by 8 bytes words. 1.32 @@ -3962,7 +3952,7 @@ 1.33 int raw_adr_idx = Compile::AliasIdxRaw; 1.34 post_barrier(control(), 1.35 memory(raw_adr_type), 1.36 - new_obj, 1.37 + alloc_obj, 1.38 no_particular_field, 1.39 raw_adr_idx, 1.40 no_particular_value, 1.41 @@ -3970,16 +3960,8 @@ 1.42 false); 1.43 } 1.44 1.45 - // Move the original CheckCastPP after arraycopy. 1.46 - _gvn.hash_delete(alloc_obj); 1.47 - alloc_obj->set_req(0, control()); 1.48 - // Replace raw memory edge with new CheckCastPP to have a live oop 1.49 - // at safepoints instead of raw value. 1.50 - assert(new_obj->is_CheckCastPP() && new_obj->in(1) == alloc_obj->in(1), "sanity"); 1.51 - alloc_obj->set_req(1, new_obj); // cast to the original type 1.52 - _gvn.hash_find_insert(alloc_obj); // put back into GVN table 1.53 - // Restore in the locally valid dest_oop. 1.54 - replace_in_map(new_obj, alloc_obj); 1.55 + // Do not let reads from the cloned object float above the arraycopy. 1.56 + insert_mem_bar(Op_MemBarCPUOrder); 1.57 } 1.58 1.59 //------------------------inline_native_clone---------------------------- 1.60 @@ -4448,17 +4430,7 @@ 1.61 InitializeNode* init = alloc->initialization(); 1.62 assert(init->is_complete(), "we just did this"); 1.63 assert(dest->is_CheckCastPP(), "sanity"); 1.64 - assert(dest->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL, "type should be more precise than Object"); 1.65 assert(dest->in(0)->in(0) == init, "dest pinned"); 1.66 - 1.67 - // Cast to Object for arraycopy. 1.68 - // We can't use the original CheckCastPP since it should be moved 1.69 - // after the arraycopy to prevent stores flowing above it. 1.70 - Node* new_obj = new(C, 2) CheckCastPPNode(dest->in(0), dest->in(1), 1.71 - TypeInstPtr::NOTNULL); 1.72 - dest = _gvn.transform(new_obj); 1.73 - // Substitute in the locally valid dest_oop. 1.74 - replace_in_map(original_dest, dest); 1.75 adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory 1.76 // From this point on, every exit path is responsible for 1.77 // initializing any non-copied parts of the object to zero. 1.78 @@ -4788,18 +4760,6 @@ 1.79 set_i_o( _gvn.transform(result_i_o) ); 1.80 set_memory( _gvn.transform(result_memory), adr_type ); 1.81 1.82 - if (dest != original_dest) { 1.83 - // Pin the "finished" array node after the arraycopy/zeroing operations. 1.84 - _gvn.hash_delete(original_dest); 1.85 - original_dest->set_req(0, control()); 1.86 - // Replace raw memory edge with new CheckCastPP to have a live oop 1.87 - // at safepoints instead of raw value. 1.88 - assert(dest->is_CheckCastPP() && dest->in(1) == original_dest->in(1), "sanity"); 1.89 - original_dest->set_req(1, dest); // cast to the original type 1.90 - _gvn.hash_find_insert(original_dest); // put back into GVN table 1.91 - // Restore in the locally valid dest_oop. 1.92 - replace_in_map(dest, original_dest); 1.93 - } 1.94 // The memory edges above are precise in order to model effects around 1.95 // array copies accurately to allow value numbering of field loads around 1.96 // arraycopy. Such field loads, both before and after, are common in Java 1.97 @@ -4810,7 +4770,9 @@ 1.98 // The next memory barrier is added to avoid it. If the arraycopy can be 1.99 // optimized away (which it can, sometimes) then we can manually remove 1.100 // the membar also. 1.101 - if (InsertMemBarAfterArraycopy) 1.102 + // 1.103 + // Do not let reads from the cloned object float above the arraycopy. 1.104 + if (InsertMemBarAfterArraycopy || alloc != NULL) 1.105 insert_mem_bar(Op_MemBarCPUOrder); 1.106 } 1.107
2.1 --- a/src/share/vm/opto/type.cpp Thu Sep 10 10:36:24 2009 -0700 2.2 +++ b/src/share/vm/opto/type.cpp Thu Sep 10 18:18:06 2009 -0700 2.3 @@ -2236,12 +2236,12 @@ 2.4 2.5 //------------------------------make------------------------------------------- 2.6 const TypeOopPtr *TypeOopPtr::make(PTR ptr, 2.7 - int offset) { 2.8 + int offset, int instance_id) { 2.9 assert(ptr != Constant, "no constant generic pointers"); 2.10 ciKlass* k = ciKlassKlass::make(); 2.11 bool xk = false; 2.12 ciObject* o = NULL; 2.13 - return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, InstanceBot))->hashcons(); 2.14 + return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id))->hashcons(); 2.15 } 2.16 2.17 2.18 @@ -2330,7 +2330,8 @@ 2.19 2.20 case OopPtr: { // Meeting to other OopPtrs 2.21 const TypeOopPtr *tp = t->is_oopptr(); 2.22 - return make( meet_ptr(tp->ptr()), meet_offset(tp->offset()) ); 2.23 + int instance_id = meet_instance_id(tp->instance_id()); 2.24 + return make( meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id ); 2.25 } 2.26 2.27 case InstPtr: // For these, flip the call around to cut down 2.28 @@ -2801,7 +2802,7 @@ 2.29 2.30 case OopPtr: { // Meeting to OopPtrs 2.31 // Found a OopPtr type vs self-InstPtr type 2.32 - const TypePtr *tp = t->is_oopptr(); 2.33 + const TypeOopPtr *tp = t->is_oopptr(); 2.34 int offset = meet_offset(tp->offset()); 2.35 PTR ptr = meet_ptr(tp->ptr()); 2.36 switch (tp->ptr()) { 2.37 @@ -2812,8 +2813,10 @@ 2.38 (ptr == Constant ? const_oop() : NULL), offset, instance_id); 2.39 } 2.40 case NotNull: 2.41 - case BotPTR: 2.42 - return TypeOopPtr::make(ptr, offset); 2.43 + case BotPTR: { 2.44 + int instance_id = meet_instance_id(tp->instance_id()); 2.45 + return TypeOopPtr::make(ptr, offset, instance_id); 2.46 + } 2.47 default: typerr(t); 2.48 } 2.49 } 2.50 @@ -3259,7 +3262,7 @@ 2.51 2.52 case OopPtr: { // Meeting to OopPtrs 2.53 // Found a OopPtr type vs self-AryPtr type 2.54 - const TypePtr *tp = t->is_oopptr(); 2.55 + const TypeOopPtr *tp = t->is_oopptr(); 2.56 int offset = meet_offset(tp->offset()); 2.57 PTR ptr = meet_ptr(tp->ptr()); 2.58 switch (tp->ptr()) { 2.59 @@ -3270,8 +3273,10 @@ 2.60 _ary, _klass, _klass_is_exact, offset, instance_id); 2.61 } 2.62 case BotPTR: 2.63 - case NotNull: 2.64 - return TypeOopPtr::make(ptr, offset); 2.65 + case NotNull: { 2.66 + int instance_id = meet_instance_id(tp->instance_id()); 2.67 + return TypeOopPtr::make(ptr, offset, instance_id); 2.68 + } 2.69 default: ShouldNotReachHere(); 2.70 } 2.71 }
3.1 --- a/src/share/vm/opto/type.hpp Thu Sep 10 10:36:24 2009 -0700 3.2 +++ b/src/share/vm/opto/type.hpp Thu Sep 10 18:18:06 2009 -0700 3.3 @@ -714,7 +714,7 @@ 3.4 static const TypeOopPtr* make_from_constant(ciObject* o); 3.5 3.6 // Make a generic (unclassed) pointer to an oop. 3.7 - static const TypeOopPtr* make(PTR ptr, int offset); 3.8 + static const TypeOopPtr* make(PTR ptr, int offset, int instance_id = InstanceBot); 3.9 3.10 ciObject* const_oop() const { return _const_oop; } 3.11 virtual ciKlass* klass() const { return _klass; }