1.1 --- a/src/share/vm/opto/memnode.cpp Mon Sep 09 19:53:28 2013 +0200 1.2 +++ b/src/share/vm/opto/memnode.cpp Tue Sep 10 14:51:48 2013 -0700 1.3 @@ -962,6 +962,19 @@ 1.4 return (uintptr_t)in(Control) + (uintptr_t)in(Memory) + (uintptr_t)in(Address); 1.5 } 1.6 1.7 +static bool skip_through_membars(Compile::AliasType* atp, const TypeInstPtr* tp, bool eliminate_boxing) { 1.8 + if ((atp != NULL) && (atp->index() >= Compile::AliasIdxRaw)) { 1.9 + bool non_volatile = (atp->field() != NULL) && !atp->field()->is_volatile(); 1.10 + bool is_stable_ary = FoldStableValues && 1.11 + (tp != NULL) && (tp->isa_aryptr() != NULL) && 1.12 + tp->isa_aryptr()->is_stable(); 1.13 + 1.14 + return (eliminate_boxing && non_volatile) || is_stable_ary; 1.15 + } 1.16 + 1.17 + return false; 1.18 +} 1.19 + 1.20 //---------------------------can_see_stored_value------------------------------ 1.21 // This routine exists to make sure this set of tests is done the same 1.22 // everywhere. We need to make a coordinated change: first LoadNode::Ideal 1.23 @@ -976,11 +989,9 @@ 1.24 const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr(); 1.25 Compile::AliasType* atp = (tp != NULL) ? phase->C->alias_type(tp) : NULL; 1.26 // This is more general than load from boxing objects. 1.27 - if (phase->C->eliminate_boxing() && (atp != NULL) && 1.28 - (atp->index() >= Compile::AliasIdxRaw) && 1.29 - (atp->field() != NULL) && !atp->field()->is_volatile()) { 1.30 + if (skip_through_membars(atp, tp, phase->C->eliminate_boxing())) { 1.31 uint alias_idx = atp->index(); 1.32 - bool final = atp->field()->is_final(); 1.33 + bool final = !atp->is_rewritable(); 1.34 Node* result = NULL; 1.35 Node* current = st; 1.36 // Skip through chains of MemBarNodes checking the MergeMems for 1.37 @@ -1015,7 +1026,6 @@ 1.38 } 1.39 } 1.40 1.41 - 1.42 // Loop around twice in the case Load -> Initialize -> Store. 1.43 // (See PhaseIterGVN::add_users_to_worklist, which knows about this case.) 1.44 for (int trip = 0; trip <= 1; trip++) { 1.45 @@ -1577,6 +1587,40 @@ 1.46 return NULL; 1.47 } 1.48 1.49 +// Try to constant-fold a stable array element. 1.50 +static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) { 1.51 + assert(ary->is_stable(), "array should be stable"); 1.52 + 1.53 + if (ary->const_oop() != NULL) { 1.54 + // Decode the results of GraphKit::array_element_address. 1.55 + ciArray* aobj = ary->const_oop()->as_array(); 1.56 + ciConstant con = aobj->element_value_by_offset(off); 1.57 + 1.58 + if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) { 1.59 + const Type* con_type = Type::make_from_constant(con); 1.60 + if (con_type != NULL) { 1.61 + if (con_type->isa_aryptr()) { 1.62 + // Join with the array element type, in case it is also stable. 1.63 + int dim = ary->stable_dimension(); 1.64 + con_type = con_type->is_aryptr()->cast_to_stable(true, dim-1); 1.65 + } 1.66 + if (loadbt == T_NARROWOOP && con_type->isa_oopptr()) { 1.67 + con_type = con_type->make_narrowoop(); 1.68 + } 1.69 +#ifndef PRODUCT 1.70 + if (TraceIterativeGVN) { 1.71 + tty->print("FoldStableValues: array element [off=%d]: con_type=", off); 1.72 + con_type->dump(); tty->cr(); 1.73 + } 1.74 +#endif //PRODUCT 1.75 + return con_type; 1.76 + } 1.77 + } 1.78 + } 1.79 + 1.80 + return NULL; 1.81 +} 1.82 + 1.83 //------------------------------Value----------------------------------------- 1.84 const Type *LoadNode::Value( PhaseTransform *phase ) const { 1.85 // Either input is TOP ==> the result is TOP 1.86 @@ -1591,8 +1635,31 @@ 1.87 Compile* C = phase->C; 1.88 1.89 // Try to guess loaded type from pointer type 1.90 - if (tp->base() == Type::AryPtr) { 1.91 - const Type *t = tp->is_aryptr()->elem(); 1.92 + if (tp->isa_aryptr()) { 1.93 + const TypeAryPtr* ary = tp->is_aryptr(); 1.94 + const Type *t = ary->elem(); 1.95 + 1.96 + // Determine whether the reference is beyond the header or not, by comparing 1.97 + // the offset against the offset of the start of the array's data. 1.98 + // Different array types begin at slightly different offsets (12 vs. 16). 1.99 + // We choose T_BYTE as an example base type that is least restrictive 1.100 + // as to alignment, which will therefore produce the smallest 1.101 + // possible base offset. 1.102 + const int min_base_off = arrayOopDesc::base_offset_in_bytes(T_BYTE); 1.103 + const bool off_beyond_header = ((uint)off >= (uint)min_base_off); 1.104 + 1.105 + // Try to constant-fold a stable array element. 1.106 + if (FoldStableValues && ary->is_stable()) { 1.107 + // Make sure the reference is not into the header 1.108 + if (off_beyond_header && off != Type::OffsetBot) { 1.109 + assert(adr->is_AddP() && adr->in(AddPNode::Offset)->is_Con(), "offset is a constant"); 1.110 + const Type* con_type = fold_stable_ary_elem(ary, off, memory_type()); 1.111 + if (con_type != NULL) { 1.112 + return con_type; 1.113 + } 1.114 + } 1.115 + } 1.116 + 1.117 // Don't do this for integer types. There is only potential profit if 1.118 // the element type t is lower than _type; that is, for int types, if _type is 1.119 // more restrictive than t. This only happens here if one is short and the other 1.120 @@ -1613,14 +1680,7 @@ 1.121 && Opcode() != Op_LoadKlass && Opcode() != Op_LoadNKlass) { 1.122 // t might actually be lower than _type, if _type is a unique 1.123 // concrete subclass of abstract class t. 1.124 - // Make sure the reference is not into the header, by comparing 1.125 - // the offset against the offset of the start of the array's data. 1.126 - // Different array types begin at slightly different offsets (12 vs. 16). 1.127 - // We choose T_BYTE as an example base type that is least restrictive 1.128 - // as to alignment, which will therefore produce the smallest 1.129 - // possible base offset. 1.130 - const int min_base_off = arrayOopDesc::base_offset_in_bytes(T_BYTE); 1.131 - if ((uint)off >= (uint)min_base_off) { // is the offset beyond the header? 1.132 + if (off_beyond_header) { // is the offset beyond the header? 1.133 const Type* jt = t->join(_type); 1.134 // In any case, do not allow the join, per se, to empty out the type. 1.135 if (jt->empty() && !t->empty()) {