Fri, 15 Nov 2013 11:05:32 -0800
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
Summary: Add a field to C2 LoadNode and StoreNode classes which indicates whether the load/store should do an acquire/release on platforms which support it.
Reviewed-by: kvn
1.1 --- a/src/share/vm/opto/generateOptoStub.cpp Thu Nov 07 11:47:11 2013 +0100 1.2 +++ b/src/share/vm/opto/generateOptoStub.cpp Fri Nov 15 11:05:32 2013 -0800 1.3 @@ -104,13 +104,12 @@ 1.4 // 1.5 Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset())); 1.6 Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS); 1.7 - store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias); 1.8 + store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias, MemNode::unordered); 1.9 1.10 // Set _thread_in_native 1.11 // The order of stores into TLS is critical! Setting _thread_in_native MUST 1.12 // be last, because a GC is allowed at any time after setting it and the GC 1.13 // will require last_Java_pc and last_Java_sp. 1.14 - Node* adr_state = basic_plus_adr(top(), thread, in_bytes(JavaThread::thread_state_offset())); 1.15 1.16 //----------------------------- 1.17 // Compute signature for C call. Varies from the Java signature! 1.18 @@ -225,16 +224,15 @@ 1.19 //----------------------------- 1.20 1.21 // Clear last_Java_sp 1.22 - store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias); 1.23 + store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias, MemNode::unordered); 1.24 // Clear last_Java_pc and (optionally)_flags 1.25 - store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias); 1.26 + store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias, MemNode::unordered); 1.27 #if defined(SPARC) 1.28 - store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias); 1.29 + store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias, MemNode::unordered); 1.30 #endif /* defined(SPARC) */ 1.31 #if (defined(IA64) && !defined(AIX)) 1.32 Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset())); 1.33 - if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); 1.34 - store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias); 1.35 + store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias, MemNode::unordered); 1.36 #endif 1.37 1.38 // For is-fancy-jump, the C-return value is also the branch target 1.39 @@ -242,16 +240,16 @@ 1.40 // Runtime call returning oop in TLS? Fetch it out 1.41 if( pass_tls ) { 1.42 Node* adr = basic_plus_adr(top(), thread, in_bytes(JavaThread::vm_result_offset())); 1.43 - Node* vm_result = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, false); 1.44 + Node* vm_result = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, MemNode::unordered); 1.45 map()->set_req(TypeFunc::Parms, vm_result); // vm_result passed as result 1.46 // clear thread-local-storage(tls) 1.47 - store_to_memory(NULL, adr, null(), T_ADDRESS, NoAlias); 1.48 + store_to_memory(NULL, adr, null(), T_ADDRESS, NoAlias, MemNode::unordered); 1.49 } 1.50 1.51 //----------------------------- 1.52 // check exception 1.53 Node* adr = basic_plus_adr(top(), thread, in_bytes(Thread::pending_exception_offset())); 1.54 - Node* pending = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, false); 1.55 + Node* pending = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, MemNode::unordered); 1.56 1.57 Node* exit_memory = reset_memory(); 1.58
2.1 --- a/src/share/vm/opto/graphKit.cpp Thu Nov 07 11:47:11 2013 +0100 2.2 +++ b/src/share/vm/opto/graphKit.cpp Fri Nov 15 11:05:32 2013 -0800 2.3 @@ -494,7 +494,7 @@ 2.4 // first must access the should_post_on_exceptions_flag in this thread's JavaThread 2.5 Node* jthread = _gvn.transform(new (C) ThreadLocalNode()); 2.6 Node* adr = basic_plus_adr(top(), jthread, in_bytes(JavaThread::should_post_on_exceptions_flag_offset())); 2.7 - Node* should_post_flag = make_load(control(), adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, false); 2.8 + Node* should_post_flag = make_load(control(), adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, MemNode::unordered); 2.9 2.10 // Test the should_post_on_exceptions_flag vs. 0 2.11 Node* chk = _gvn.transform( new (C) CmpINode(should_post_flag, intcon(0)) ); 2.12 @@ -596,7 +596,8 @@ 2.13 2.14 Node *adr = basic_plus_adr(ex_node, ex_node, offset); 2.15 const TypeOopPtr* val_type = TypeOopPtr::make_from_klass(env()->String_klass()); 2.16 - Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), val_type, T_OBJECT); 2.17 + // Conservatively release stores of object references. 2.18 + Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), val_type, T_OBJECT, MemNode::release); 2.19 2.20 add_exception_state(make_exception_state(ex_node)); 2.21 return; 2.22 @@ -1483,16 +1484,16 @@ 2.23 // factory methods in "int adr_idx" 2.24 Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, 2.25 int adr_idx, 2.26 - bool require_atomic_access) { 2.27 + MemNode::MemOrd mo, bool require_atomic_access) { 2.28 assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" ); 2.29 const TypePtr* adr_type = NULL; // debug-mode-only argument 2.30 debug_only(adr_type = C->get_adr_type(adr_idx)); 2.31 Node* mem = memory(adr_idx); 2.32 Node* ld; 2.33 if (require_atomic_access && bt == T_LONG) { 2.34 - ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t); 2.35 + ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, mo); 2.36 } else { 2.37 - ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt); 2.38 + ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo); 2.39 } 2.40 ld = _gvn.transform(ld); 2.41 if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) { 2.42 @@ -1504,6 +1505,7 @@ 2.43 2.44 Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt, 2.45 int adr_idx, 2.46 + MemNode::MemOrd mo, 2.47 bool require_atomic_access) { 2.48 assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); 2.49 const TypePtr* adr_type = NULL; 2.50 @@ -1511,9 +1513,9 @@ 2.51 Node *mem = memory(adr_idx); 2.52 Node* st; 2.53 if (require_atomic_access && bt == T_LONG) { 2.54 - st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val); 2.55 + st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); 2.56 } else { 2.57 - st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt); 2.58 + st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); 2.59 } 2.60 st = _gvn.transform(st); 2.61 set_memory(st, adr_idx); 2.62 @@ -1613,7 +1615,8 @@ 2.63 Node* val, 2.64 const TypeOopPtr* val_type, 2.65 BasicType bt, 2.66 - bool use_precise) { 2.67 + bool use_precise, 2.68 + MemNode::MemOrd mo) { 2.69 // Transformation of a value which could be NULL pointer (CastPP #NULL) 2.70 // could be delayed during Parse (for example, in adjust_map_after_if()). 2.71 // Execute transformation here to avoid barrier generation in such case. 2.72 @@ -1633,7 +1636,7 @@ 2.73 NULL /* pre_val */, 2.74 bt); 2.75 2.76 - Node* store = store_to_memory(control(), adr, val, bt, adr_idx); 2.77 + Node* store = store_to_memory(control(), adr, val, bt, adr_idx, mo); 2.78 post_barrier(control(), store, obj, adr, adr_idx, val, bt, use_precise); 2.79 return store; 2.80 } 2.81 @@ -1644,7 +1647,8 @@ 2.82 Node* adr, // actual adress to store val at 2.83 const TypePtr* adr_type, 2.84 Node* val, 2.85 - BasicType bt) { 2.86 + BasicType bt, 2.87 + MemNode::MemOrd mo) { 2.88 Compile::AliasType* at = C->alias_type(adr_type); 2.89 const TypeOopPtr* val_type = NULL; 2.90 if (adr_type->isa_instptr()) { 2.91 @@ -1663,7 +1667,7 @@ 2.92 if (val_type == NULL) { 2.93 val_type = TypeInstPtr::BOTTOM; 2.94 } 2.95 - return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true); 2.96 + return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true, mo); 2.97 } 2.98 2.99 2.100 @@ -1707,7 +1711,7 @@ 2.101 const Type* elemtype = arytype->elem(); 2.102 BasicType elembt = elemtype->array_element_basic_type(); 2.103 Node* adr = array_element_address(ary, idx, elembt, arytype->size()); 2.104 - Node* ld = make_load(ctl, adr, elemtype, elembt, arytype); 2.105 + Node* ld = make_load(ctl, adr, elemtype, elembt, arytype, MemNode::unordered); 2.106 return ld; 2.107 } 2.108 2.109 @@ -1942,9 +1946,9 @@ 2.110 void GraphKit::increment_counter(Node* counter_addr) { 2.111 int adr_type = Compile::AliasIdxRaw; 2.112 Node* ctrl = control(); 2.113 - Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type); 2.114 + Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type, MemNode::unordered); 2.115 Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1))); 2.116 - store_to_memory( ctrl, counter_addr, incr, T_INT, adr_type ); 2.117 + store_to_memory(ctrl, counter_addr, incr, T_INT, adr_type, MemNode::unordered); 2.118 } 2.119 2.120 2.121 @@ -2525,7 +2529,8 @@ 2.122 2.123 // First load the super-klass's check-offset 2.124 Node *p1 = basic_plus_adr( superklass, superklass, in_bytes(Klass::super_check_offset_offset()) ); 2.125 - Node *chk_off = _gvn.transform( new (C) LoadINode( NULL, memory(p1), p1, _gvn.type(p1)->is_ptr() ) ); 2.126 + Node *chk_off = _gvn.transform(new (C) LoadINode(NULL, memory(p1), p1, _gvn.type(p1)->is_ptr(), 2.127 + TypeInt::INT, MemNode::unordered)); 2.128 int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset()); 2.129 bool might_be_cache = (find_int_con(chk_off, cacheoff_con) == cacheoff_con); 2.130 2.131 @@ -3238,7 +3243,7 @@ 2.132 } 2.133 constant_value = Klass::_lh_neutral_value; // put in a known value 2.134 Node* lhp = basic_plus_adr(klass_node, klass_node, in_bytes(Klass::layout_helper_offset())); 2.135 - return make_load(NULL, lhp, TypeInt::INT, T_INT); 2.136 + return make_load(NULL, lhp, TypeInt::INT, T_INT, MemNode::unordered); 2.137 } 2.138 2.139 // We just put in an allocate/initialize with a big raw-memory effect. 2.140 @@ -3773,7 +3778,7 @@ 2.141 2.142 // Smash zero into card 2.143 if( !UseConcMarkSweepGC ) { 2.144 - __ store(__ ctrl(), card_adr, zero, bt, adr_type); 2.145 + __ store(__ ctrl(), card_adr, zero, bt, adr_type, MemNode::release); 2.146 } else { 2.147 // Specialized path for CM store barrier 2.148 __ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, bt, adr_type); 2.149 @@ -3870,9 +3875,9 @@ 2.150 2.151 // Now get the buffer location we will log the previous value into and store it 2.152 Node *log_addr = __ AddP(no_base, buffer, next_index); 2.153 - __ store(__ ctrl(), log_addr, pre_val, T_OBJECT, Compile::AliasIdxRaw); 2.154 + __ store(__ ctrl(), log_addr, pre_val, T_OBJECT, Compile::AliasIdxRaw, MemNode::unordered); 2.155 // update the index 2.156 - __ store(__ ctrl(), index_adr, next_index, index_bt, Compile::AliasIdxRaw); 2.157 + __ store(__ ctrl(), index_adr, next_index, index_bt, Compile::AliasIdxRaw, MemNode::unordered); 2.158 2.159 } __ else_(); { 2.160 2.161 @@ -3912,8 +3917,9 @@ 2.162 Node* next_index = _gvn.transform(new (C) SubXNode(index, __ ConX(sizeof(intptr_t)))); 2.163 Node* log_addr = __ AddP(no_base, buffer, next_index); 2.164 2.165 - __ store(__ ctrl(), log_addr, card_adr, T_ADDRESS, Compile::AliasIdxRaw); 2.166 - __ store(__ ctrl(), index_adr, next_index, TypeX_X->basic_type(), Compile::AliasIdxRaw); 2.167 + // Order, see storeCM. 2.168 + __ store(__ ctrl(), log_addr, card_adr, T_ADDRESS, Compile::AliasIdxRaw, MemNode::unordered); 2.169 + __ store(__ ctrl(), index_adr, next_index, TypeX_X->basic_type(), Compile::AliasIdxRaw, MemNode::unordered); 2.170 2.171 } __ else_(); { 2.172 __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), "g1_wb_post", card_adr, __ thread()); 2.173 @@ -4043,7 +4049,7 @@ 2.174 int offset_field_idx = C->get_alias_index(offset_field_type); 2.175 return make_load(ctrl, 2.176 basic_plus_adr(str, str, offset_offset), 2.177 - TypeInt::INT, T_INT, offset_field_idx); 2.178 + TypeInt::INT, T_INT, offset_field_idx, MemNode::unordered); 2.179 } else { 2.180 return intcon(0); 2.181 } 2.182 @@ -4058,7 +4064,7 @@ 2.183 int count_field_idx = C->get_alias_index(count_field_type); 2.184 return make_load(ctrl, 2.185 basic_plus_adr(str, str, count_offset), 2.186 - TypeInt::INT, T_INT, count_field_idx); 2.187 + TypeInt::INT, T_INT, count_field_idx, MemNode::unordered); 2.188 } else { 2.189 return load_array_length(load_String_value(ctrl, str)); 2.190 } 2.191 @@ -4074,7 +4080,7 @@ 2.192 ciTypeArrayKlass::make(T_CHAR), true, 0); 2.193 int value_field_idx = C->get_alias_index(value_field_type); 2.194 Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset), 2.195 - value_type, T_OBJECT, value_field_idx); 2.196 + value_type, T_OBJECT, value_field_idx, MemNode::unordered); 2.197 // String.value field is known to be @Stable. 2.198 if (UseImplicitStableValues) { 2.199 load = cast_array_to_stable(load, value_type); 2.200 @@ -4089,7 +4095,7 @@ 2.201 const TypePtr* offset_field_type = string_type->add_offset(offset_offset); 2.202 int offset_field_idx = C->get_alias_index(offset_field_type); 2.203 store_to_memory(ctrl, basic_plus_adr(str, offset_offset), 2.204 - value, T_INT, offset_field_idx); 2.205 + value, T_INT, offset_field_idx, MemNode::unordered); 2.206 } 2.207 2.208 void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) { 2.209 @@ -4099,7 +4105,7 @@ 2.210 const TypePtr* value_field_type = string_type->add_offset(value_offset); 2.211 2.212 store_oop_to_object(ctrl, str, basic_plus_adr(str, value_offset), value_field_type, 2.213 - value, TypeAryPtr::CHARS, T_OBJECT); 2.214 + value, TypeAryPtr::CHARS, T_OBJECT, MemNode::unordered); 2.215 } 2.216 2.217 void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) { 2.218 @@ -4109,7 +4115,7 @@ 2.219 const TypePtr* count_field_type = string_type->add_offset(count_offset); 2.220 int count_field_idx = C->get_alias_index(count_field_type); 2.221 store_to_memory(ctrl, basic_plus_adr(str, count_offset), 2.222 - value, T_INT, count_field_idx); 2.223 + value, T_INT, count_field_idx, MemNode::unordered); 2.224 } 2.225 2.226 Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) {
3.1 --- a/src/share/vm/opto/graphKit.hpp Thu Nov 07 11:47:11 2013 +0100 3.2 +++ b/src/share/vm/opto/graphKit.hpp Fri Nov 15 11:05:32 2013 -0800 3.3 @@ -510,36 +510,50 @@ 3.4 3.5 // Create a LoadNode, reading from the parser's memory state. 3.6 // (Note: require_atomic_access is useful only with T_LONG.) 3.7 + // 3.8 + // We choose the unordered semantics by default because we have 3.9 + // adapted the `do_put_xxx' and `do_get_xxx' procedures for the case 3.10 + // of volatile fields. 3.11 Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, 3.12 - bool require_atomic_access = false) { 3.13 + MemNode::MemOrd mo, bool require_atomic_access = false) { 3.14 // This version computes alias_index from bottom_type 3.15 return make_load(ctl, adr, t, bt, adr->bottom_type()->is_ptr(), 3.16 - require_atomic_access); 3.17 + mo, require_atomic_access); 3.18 } 3.19 - Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type, bool require_atomic_access = false) { 3.20 + Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type, 3.21 + MemNode::MemOrd mo, bool require_atomic_access = false) { 3.22 // This version computes alias_index from an address type 3.23 assert(adr_type != NULL, "use other make_load factory"); 3.24 return make_load(ctl, adr, t, bt, C->get_alias_index(adr_type), 3.25 - require_atomic_access); 3.26 + mo, require_atomic_access); 3.27 } 3.28 // This is the base version which is given an alias index. 3.29 - Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, bool require_atomic_access = false); 3.30 + Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, 3.31 + MemNode::MemOrd mo, bool require_atomic_access = false); 3.32 3.33 // Create & transform a StoreNode and store the effect into the 3.34 // parser's memory state. 3.35 + // 3.36 + // We must ensure that stores of object references will be visible 3.37 + // only after the object's initialization. So the clients of this 3.38 + // procedure must indicate that the store requires `release' 3.39 + // semantics, if the stored value is an object reference that might 3.40 + // point to a new object and may become externally visible. 3.41 Node* store_to_memory(Node* ctl, Node* adr, Node* val, BasicType bt, 3.42 const TypePtr* adr_type, 3.43 + MemNode::MemOrd mo, 3.44 bool require_atomic_access = false) { 3.45 // This version computes alias_index from an address type 3.46 assert(adr_type != NULL, "use other store_to_memory factory"); 3.47 return store_to_memory(ctl, adr, val, bt, 3.48 C->get_alias_index(adr_type), 3.49 - require_atomic_access); 3.50 + mo, require_atomic_access); 3.51 } 3.52 // This is the base version which is given alias index 3.53 // Return the new StoreXNode 3.54 Node* store_to_memory(Node* ctl, Node* adr, Node* val, BasicType bt, 3.55 int adr_idx, 3.56 + MemNode::MemOrd, 3.57 bool require_atomic_access = false); 3.58 3.59 3.60 @@ -557,40 +571,44 @@ 3.61 3.62 Node* store_oop(Node* ctl, 3.63 Node* obj, // containing obj 3.64 - Node* adr, // actual adress to store val at 3.65 + Node* adr, // actual adress to store val at 3.66 const TypePtr* adr_type, 3.67 Node* val, 3.68 const TypeOopPtr* val_type, 3.69 BasicType bt, 3.70 - bool use_precise); 3.71 + bool use_precise, 3.72 + MemNode::MemOrd mo); 3.73 3.74 Node* store_oop_to_object(Node* ctl, 3.75 Node* obj, // containing obj 3.76 - Node* adr, // actual adress to store val at 3.77 + Node* adr, // actual adress to store val at 3.78 const TypePtr* adr_type, 3.79 Node* val, 3.80 const TypeOopPtr* val_type, 3.81 - BasicType bt) { 3.82 - return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, false); 3.83 + BasicType bt, 3.84 + MemNode::MemOrd mo) { 3.85 + return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, false, mo); 3.86 } 3.87 3.88 Node* store_oop_to_array(Node* ctl, 3.89 Node* obj, // containing obj 3.90 - Node* adr, // actual adress to store val at 3.91 + Node* adr, // actual adress to store val at 3.92 const TypePtr* adr_type, 3.93 Node* val, 3.94 const TypeOopPtr* val_type, 3.95 - BasicType bt) { 3.96 - return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true); 3.97 + BasicType bt, 3.98 + MemNode::MemOrd mo) { 3.99 + return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true, mo); 3.100 } 3.101 3.102 // Could be an array or object we don't know at compile time (unsafe ref.) 3.103 Node* store_oop_to_unknown(Node* ctl, 3.104 Node* obj, // containing obj 3.105 - Node* adr, // actual adress to store val at 3.106 + Node* adr, // actual adress to store val at 3.107 const TypePtr* adr_type, 3.108 Node* val, 3.109 - BasicType bt); 3.110 + BasicType bt, 3.111 + MemNode::MemOrd mo); 3.112 3.113 // For the few case where the barriers need special help 3.114 void pre_barrier(bool do_load, Node* ctl,
4.1 --- a/src/share/vm/opto/idealKit.cpp Thu Nov 07 11:47:11 2013 +0100 4.2 +++ b/src/share/vm/opto/idealKit.cpp Fri Nov 15 11:05:32 2013 -0800 4.3 @@ -359,25 +359,25 @@ 4.4 Node* mem = memory(adr_idx); 4.5 Node* ld; 4.6 if (require_atomic_access && bt == T_LONG) { 4.7 - ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t); 4.8 + ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, MemNode::unordered); 4.9 } else { 4.10 - ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt); 4.11 + ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, MemNode::unordered); 4.12 } 4.13 return transform(ld); 4.14 } 4.15 4.16 Node* IdealKit::store(Node* ctl, Node* adr, Node *val, BasicType bt, 4.17 - int adr_idx, 4.18 - bool require_atomic_access) { 4.19 - assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); 4.20 + int adr_idx, 4.21 + MemNode::MemOrd mo, bool require_atomic_access) { 4.22 + assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory"); 4.23 const TypePtr* adr_type = NULL; 4.24 debug_only(adr_type = C->get_adr_type(adr_idx)); 4.25 Node *mem = memory(adr_idx); 4.26 Node* st; 4.27 if (require_atomic_access && bt == T_LONG) { 4.28 - st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val); 4.29 + st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); 4.30 } else { 4.31 - st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt); 4.32 + st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); 4.33 } 4.34 st = transform(st); 4.35 set_memory(st, adr_idx);
5.1 --- a/src/share/vm/opto/idealKit.hpp Thu Nov 07 11:47:11 2013 +0100 5.2 +++ b/src/share/vm/opto/idealKit.hpp Fri Nov 15 11:05:32 2013 -0800 5.3 @@ -226,6 +226,7 @@ 5.4 Node* val, 5.5 BasicType bt, 5.6 int adr_idx, 5.7 + MemNode::MemOrd mo, 5.8 bool require_atomic_access = false); 5.9 5.10 // Store a card mark ordered after store_oop
6.1 --- a/src/share/vm/opto/library_call.cpp Thu Nov 07 11:47:11 2013 +0100 6.2 +++ b/src/share/vm/opto/library_call.cpp Fri Nov 15 11:05:32 2013 -0800 6.3 @@ -1057,7 +1057,7 @@ 6.4 const Type* thread_type = TypeOopPtr::make_from_klass(thread_klass)->cast_to_ptr_type(TypePtr::NotNull); 6.5 Node* thread = _gvn.transform(new (C) ThreadLocalNode()); 6.6 Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::threadObj_offset())); 6.7 - Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT); 6.8 + Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT, MemNode::unordered); 6.9 tls_output = thread; 6.10 return threadObj; 6.11 } 6.12 @@ -2640,7 +2640,7 @@ 6.13 if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); 6.14 6.15 if (!is_store) { 6.16 - Node* p = make_load(control(), adr, value_type, type, adr_type, is_volatile); 6.17 + Node* p = make_load(control(), adr, value_type, type, adr_type, MemNode::unordered, is_volatile); 6.18 // load value 6.19 switch (type) { 6.20 case T_BOOLEAN: 6.21 @@ -2684,13 +2684,14 @@ 6.22 break; 6.23 } 6.24 6.25 + MemNode::MemOrd mo = is_volatile ? MemNode::release : MemNode::unordered; 6.26 if (type != T_OBJECT ) { 6.27 - (void) store_to_memory(control(), adr, val, type, adr_type, is_volatile); 6.28 + (void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile); 6.29 } else { 6.30 // Possibly an oop being stored to Java heap or native memory 6.31 if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { 6.32 // oop to Java heap. 6.33 - (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type); 6.34 + (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo); 6.35 } else { 6.36 // We can't tell at compile time if we are storing in the Java heap or outside 6.37 // of it. So we need to emit code to conditionally do the proper type of 6.38 @@ -2702,11 +2703,11 @@ 6.39 __ if_then(heap_base_oop, BoolTest::ne, null(), PROB_UNLIKELY(0.999)); { 6.40 // Sync IdealKit and graphKit. 6.41 sync_kit(ideal); 6.42 - Node* st = store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type); 6.43 + Node* st = store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo); 6.44 // Update IdealKit memory. 6.45 __ sync_kit(this); 6.46 } __ else_(); { 6.47 - __ store(__ ctrl(), adr, val, type, alias_type->index(), is_volatile); 6.48 + __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, is_volatile); 6.49 } __ end_if(); 6.50 // Final sync IdealKit and GraphKit. 6.51 final_sync(ideal); 6.52 @@ -2979,12 +2980,12 @@ 6.53 Node *newval_enc = _gvn.transform(new (C) EncodePNode(newval, newval->bottom_type()->make_narrowoop())); 6.54 if (kind == LS_xchg) { 6.55 load_store = _gvn.transform(new (C) GetAndSetNNode(control(), mem, adr, 6.56 - newval_enc, adr_type, value_type->make_narrowoop())); 6.57 + newval_enc, adr_type, value_type->make_narrowoop())); 6.58 } else { 6.59 assert(kind == LS_cmpxchg, "wrong LoadStore operation"); 6.60 Node *oldval_enc = _gvn.transform(new (C) EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); 6.61 load_store = _gvn.transform(new (C) CompareAndSwapNNode(control(), mem, adr, 6.62 - newval_enc, oldval_enc)); 6.63 + newval_enc, oldval_enc)); 6.64 } 6.65 } else 6.66 #endif 6.67 @@ -3090,9 +3091,9 @@ 6.68 const bool require_atomic_access = true; 6.69 Node* store; 6.70 if (type == T_OBJECT) // reference stores need a store barrier. 6.71 - store = store_oop_to_unknown(control(), base, adr, adr_type, val, type); 6.72 + store = store_oop_to_unknown(control(), base, adr, adr_type, val, type, MemNode::release); 6.73 else { 6.74 - store = store_to_memory(control(), adr, val, type, adr_type, require_atomic_access); 6.75 + store = store_to_memory(control(), adr, val, type, adr_type, MemNode::release, require_atomic_access); 6.76 } 6.77 insert_mem_bar(Op_MemBarCPUOrder); 6.78 return true; 6.79 @@ -3152,7 +3153,7 @@ 6.80 Node* insp = basic_plus_adr(kls, in_bytes(InstanceKlass::init_state_offset())); 6.81 // Use T_BOOLEAN for InstanceKlass::_init_state so the compiler 6.82 // can generate code to load it as unsigned byte. 6.83 - Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN); 6.84 + Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN, MemNode::unordered); 6.85 Node* bits = intcon(InstanceKlass::fully_initialized); 6.86 test = _gvn.transform(new (C) SubINode(inst, bits)); 6.87 // The 'test' is non-zero if we need to take a slow path. 6.88 @@ -3176,14 +3177,14 @@ 6.89 kls = null_check(kls, T_OBJECT); 6.90 ByteSize offset = TRACE_ID_OFFSET; 6.91 Node* insp = basic_plus_adr(kls, in_bytes(offset)); 6.92 - Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG); 6.93 + Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG, MemNode::unordered); 6.94 Node* bits = longcon(~0x03l); // ignore bit 0 & 1 6.95 Node* andl = _gvn.transform(new (C) AndLNode(tvalue, bits)); 6.96 Node* clsused = longcon(0x01l); // set the class bit 6.97 Node* orl = _gvn.transform(new (C) OrLNode(tvalue, clsused)); 6.98 6.99 const TypePtr *adr_type = _gvn.type(insp)->isa_ptr(); 6.100 - store_to_memory(control(), insp, orl, T_LONG, adr_type); 6.101 + store_to_memory(control(), insp, orl, T_LONG, adr_type, MemNode::unordered); 6.102 set_result(andl); 6.103 return true; 6.104 } 6.105 @@ -3192,15 +3193,15 @@ 6.106 Node* tls_ptr = NULL; 6.107 Node* cur_thr = generate_current_thread(tls_ptr); 6.108 Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); 6.109 - Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); 6.110 + Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered); 6.111 p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::thread_id_offset())); 6.112 6.113 Node* threadid = NULL; 6.114 size_t thread_id_size = OSThread::thread_id_size(); 6.115 if (thread_id_size == (size_t) BytesPerLong) { 6.116 - threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG)); 6.117 + threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG, MemNode::unordered)); 6.118 } else if (thread_id_size == (size_t) BytesPerInt) { 6.119 - threadid = make_load(control(), p, TypeInt::INT, T_INT); 6.120 + threadid = make_load(control(), p, TypeInt::INT, T_INT, MemNode::unordered); 6.121 } else { 6.122 ShouldNotReachHere(); 6.123 } 6.124 @@ -3275,11 +3276,11 @@ 6.125 6.126 // (b) Interrupt bit on TLS must be false. 6.127 Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); 6.128 - Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); 6.129 + Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered); 6.130 p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset())); 6.131 6.132 // Set the control input on the field _interrupted read to prevent it floating up. 6.133 - Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT); 6.134 + Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT, MemNode::unordered); 6.135 Node* cmp_bit = _gvn.transform(new (C) CmpINode(int_bit, intcon(0))); 6.136 Node* bol_bit = _gvn.transform(new (C) BoolNode(cmp_bit, BoolTest::ne)); 6.137 6.138 @@ -3347,7 +3348,7 @@ 6.139 // Given a klass oop, load its java mirror (a java.lang.Class oop). 6.140 Node* LibraryCallKit::load_mirror_from_klass(Node* klass) { 6.141 Node* p = basic_plus_adr(klass, in_bytes(Klass::java_mirror_offset())); 6.142 - return make_load(NULL, p, TypeInstPtr::MIRROR, T_OBJECT); 6.143 + return make_load(NULL, p, TypeInstPtr::MIRROR, T_OBJECT, MemNode::unordered); 6.144 } 6.145 6.146 //-----------------------load_klass_from_mirror_common------------------------- 6.147 @@ -3384,7 +3385,7 @@ 6.148 // Branch around if the given klass has the given modifier bit set. 6.149 // Like generate_guard, adds a new path onto the region. 6.150 Node* modp = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset())); 6.151 - Node* mods = make_load(NULL, modp, TypeInt::INT, T_INT); 6.152 + Node* mods = make_load(NULL, modp, TypeInt::INT, T_INT, MemNode::unordered); 6.153 Node* mask = intcon(modifier_mask); 6.154 Node* bits = intcon(modifier_bits); 6.155 Node* mbit = _gvn.transform(new (C) AndINode(mods, mask)); 6.156 @@ -3501,7 +3502,7 @@ 6.157 6.158 case vmIntrinsics::_getModifiers: 6.159 p = basic_plus_adr(kls, in_bytes(Klass::modifier_flags_offset())); 6.160 - query_value = make_load(NULL, p, TypeInt::INT, T_INT); 6.161 + query_value = make_load(NULL, p, TypeInt::INT, T_INT, MemNode::unordered); 6.162 break; 6.163 6.164 case vmIntrinsics::_isInterface: 6.165 @@ -3559,7 +3560,7 @@ 6.166 // Be sure to pin the oop load to the guard edge just created: 6.167 Node* is_array_ctrl = region->in(region->req()-1); 6.168 Node* cma = basic_plus_adr(kls, in_bytes(ArrayKlass::component_mirror_offset())); 6.169 - Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT); 6.170 + Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT, MemNode::unordered); 6.171 phi->add_req(cmo); 6.172 } 6.173 query_value = null(); // non-array case is null 6.174 @@ -3567,7 +3568,7 @@ 6.175 6.176 case vmIntrinsics::_getClassAccessFlags: 6.177 p = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset())); 6.178 - query_value = make_load(NULL, p, TypeInt::INT, T_INT); 6.179 + query_value = make_load(NULL, p, TypeInt::INT, T_INT, MemNode::unordered); 6.180 break; 6.181 6.182 default: 6.183 @@ -3933,7 +3934,7 @@ 6.184 vtable_index*vtableEntry::size()) * wordSize + 6.185 vtableEntry::method_offset_in_bytes(); 6.186 Node* entry_addr = basic_plus_adr(obj_klass, entry_offset); 6.187 - Node* target_call = make_load(NULL, entry_addr, TypePtr::NOTNULL, T_ADDRESS); 6.188 + Node* target_call = make_load(NULL, entry_addr, TypePtr::NOTNULL, T_ADDRESS, MemNode::unordered); 6.189 6.190 // Compare the target method with the expected method (e.g., Object.hashCode). 6.191 const TypePtr* native_call_addr = TypeMetadataPtr::make(method); 6.192 @@ -4059,7 +4060,7 @@ 6.193 6.194 // Get the header out of the object, use LoadMarkNode when available 6.195 Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes()); 6.196 - Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type()); 6.197 + Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type(), MemNode::unordered); 6.198 6.199 // Test the header to see if it is unlocked. 6.200 Node *lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place); 6.201 @@ -5480,7 +5481,7 @@ 6.202 // Store a zero to the immediately preceding jint: 6.203 Node* x1 = _gvn.transform(new(C) AddXNode(start, MakeConX(-bump_bit))); 6.204 Node* p1 = basic_plus_adr(dest, x1); 6.205 - mem = StoreNode::make(_gvn, control(), mem, p1, adr_type, intcon(0), T_INT); 6.206 + mem = StoreNode::make(_gvn, control(), mem, p1, adr_type, intcon(0), T_INT, MemNode::unordered); 6.207 mem = _gvn.transform(mem); 6.208 } 6.209 } 6.210 @@ -5530,8 +5531,8 @@ 6.211 ((src_off ^ dest_off) & (BytesPerLong-1)) == 0) { 6.212 Node* sptr = basic_plus_adr(src, src_off); 6.213 Node* dptr = basic_plus_adr(dest, dest_off); 6.214 - Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, adr_type); 6.215 - store_to_memory(control(), dptr, sval, T_INT, adr_type); 6.216 + Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, adr_type, MemNode::unordered); 6.217 + store_to_memory(control(), dptr, sval, T_INT, adr_type, MemNode::unordered); 6.218 src_off += BytesPerInt; 6.219 dest_off += BytesPerInt; 6.220 } else { 6.221 @@ -5596,7 +5597,7 @@ 6.222 // super_check_offset, for the desired klass. 6.223 int sco_offset = in_bytes(Klass::super_check_offset_offset()); 6.224 Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset); 6.225 - Node* n3 = new(C) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr()); 6.226 + Node* n3 = new(C) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr(), TypeInt::INT, MemNode::unordered); 6.227 Node* check_offset = ConvI2X(_gvn.transform(n3)); 6.228 Node* check_value = dest_elem_klass; 6.229 6.230 @@ -5737,7 +5738,7 @@ 6.231 Node* base = makecon(TypeRawPtr::make(StubRoutines::crc_table_addr())); 6.232 Node* offset = _gvn.transform(new (C) LShiftINode(result, intcon(0x2))); 6.233 Node* adr = basic_plus_adr(top(), base, ConvI2X(offset)); 6.234 - result = make_load(control(), adr, TypeInt::INT, T_INT); 6.235 + result = make_load(control(), adr, TypeInt::INT, T_INT, MemNode::unordered); 6.236 6.237 crc = _gvn.transform(new (C) URShiftINode(crc, intcon(8))); 6.238 result = _gvn.transform(new (C) XorINode(crc, result)); 6.239 @@ -5838,7 +5839,7 @@ 6.240 const TypeOopPtr* object_type = TypeOopPtr::make_from_klass(klass); 6.241 6.242 Node* no_ctrl = NULL; 6.243 - Node* result = make_load(no_ctrl, adr, object_type, T_OBJECT); 6.244 + Node* result = make_load(no_ctrl, adr, object_type, T_OBJECT, MemNode::unordered); 6.245 6.246 // Use the pre-barrier to record the value in the referent field 6.247 pre_barrier(false /* do_load */, 6.248 @@ -5885,7 +5886,7 @@ 6.249 const Type *type = TypeOopPtr::make_from_klass(field_klass->as_klass()); 6.250 6.251 // Build the load. 6.252 - Node* loadedField = make_load(NULL, adr, type, bt, adr_type, is_vol); 6.253 + Node* loadedField = make_load(NULL, adr, type, bt, adr_type, MemNode::unordered, is_vol); 6.254 return loadedField; 6.255 } 6.256
7.1 --- a/src/share/vm/opto/macro.cpp Thu Nov 07 11:47:11 2013 +0100 7.2 +++ b/src/share/vm/opto/macro.cpp Fri Nov 15 11:05:32 2013 -0800 7.3 @@ -1084,7 +1084,7 @@ 7.4 Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) { 7.5 Node* adr = basic_plus_adr(base, offset); 7.6 const TypePtr* adr_type = adr->bottom_type()->is_ptr(); 7.7 - Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt); 7.8 + Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt, MemNode::unordered); 7.9 transform_later(value); 7.10 return value; 7.11 } 7.12 @@ -1092,7 +1092,7 @@ 7.13 7.14 Node* PhaseMacroExpand::make_store(Node* ctl, Node* mem, Node* base, int offset, Node* value, BasicType bt) { 7.15 Node* adr = basic_plus_adr(base, offset); 7.16 - mem = StoreNode::make(_igvn, ctl, mem, adr, NULL, value, bt); 7.17 + mem = StoreNode::make(_igvn, ctl, mem, adr, NULL, value, bt, MemNode::unordered); 7.18 transform_later(mem); 7.19 return mem; 7.20 } 7.21 @@ -1272,8 +1272,8 @@ 7.22 // Load(-locked) the heap top. 7.23 // See note above concerning the control input when using a TLAB 7.24 Node *old_eden_top = UseTLAB 7.25 - ? new (C) LoadPNode (ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM) 7.26 - : new (C) LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr); 7.27 + ? new (C) LoadPNode (ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered) 7.28 + : new (C) LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr, MemNode::acquire); 7.29 7.30 transform_later(old_eden_top); 7.31 // Add to heap top to get a new heap top 7.32 @@ -1320,7 +1320,7 @@ 7.33 if (UseTLAB) { 7.34 Node* store_eden_top = 7.35 new (C) StorePNode(needgc_false, contended_phi_rawmem, eden_top_adr, 7.36 - TypeRawPtr::BOTTOM, new_eden_top); 7.37 + TypeRawPtr::BOTTOM, new_eden_top, MemNode::unordered); 7.38 transform_later(store_eden_top); 7.39 fast_oop_ctrl = needgc_false; // No contention, so this is the fast path 7.40 fast_oop_rawmem = store_eden_top; 7.41 @@ -1700,9 +1700,10 @@ 7.42 _igvn.MakeConX(in_bytes(JavaThread::tlab_pf_top_offset())) ); 7.43 transform_later(eden_pf_adr); 7.44 7.45 - Node *old_pf_wm = new (C) LoadPNode( needgc_false, 7.46 + Node *old_pf_wm = new (C) LoadPNode(needgc_false, 7.47 contended_phi_rawmem, eden_pf_adr, 7.48 - TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ); 7.49 + TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, 7.50 + MemNode::unordered); 7.51 transform_later(old_pf_wm); 7.52 7.53 // check against new_eden_top 7.54 @@ -1726,9 +1727,10 @@ 7.55 transform_later(new_pf_wmt ); 7.56 new_pf_wmt->set_req(0, need_pf_true); 7.57 7.58 - Node *store_new_wmt = new (C) StorePNode( need_pf_true, 7.59 + Node *store_new_wmt = new (C) StorePNode(need_pf_true, 7.60 contended_phi_rawmem, eden_pf_adr, 7.61 - TypeRawPtr::BOTTOM, new_pf_wmt ); 7.62 + TypeRawPtr::BOTTOM, new_pf_wmt, 7.63 + MemNode::unordered); 7.64 transform_later(store_new_wmt); 7.65 7.66 // adding prefetches
8.1 --- a/src/share/vm/opto/matcher.cpp Thu Nov 07 11:47:11 2013 +0100 8.2 +++ b/src/share/vm/opto/matcher.cpp Fri Nov 15 11:05:32 2013 -0800 8.3 @@ -825,16 +825,15 @@ 8.4 8.5 // Compute generic short-offset Loads 8.6 #ifdef _LP64 8.7 - MachNode *spillCP = match_tree(new (C) LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM)); 8.8 + MachNode *spillCP = match_tree(new (C) LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered)); 8.9 #endif 8.10 - MachNode *spillI = match_tree(new (C) LoadINode(NULL,mem,fp,atp)); 8.11 - MachNode *spillL = match_tree(new (C) LoadLNode(NULL,mem,fp,atp)); 8.12 - MachNode *spillF = match_tree(new (C) LoadFNode(NULL,mem,fp,atp)); 8.13 - MachNode *spillD = match_tree(new (C) LoadDNode(NULL,mem,fp,atp)); 8.14 - MachNode *spillP = match_tree(new (C) LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM)); 8.15 + MachNode *spillI = match_tree(new (C) LoadINode(NULL,mem,fp,atp,TypeInt::INT,MemNode::unordered)); 8.16 + MachNode *spillL = match_tree(new (C) LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered,false)); 8.17 + MachNode *spillF = match_tree(new (C) LoadFNode(NULL,mem,fp,atp,Type::FLOAT,MemNode::unordered)); 8.18 + MachNode *spillD = match_tree(new (C) LoadDNode(NULL,mem,fp,atp,Type::DOUBLE,MemNode::unordered)); 8.19 + MachNode *spillP = match_tree(new (C) LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered)); 8.20 assert(spillI != NULL && spillL != NULL && spillF != NULL && 8.21 spillD != NULL && spillP != NULL, ""); 8.22 - 8.23 // Get the ADLC notion of the right regmask, for each basic type. 8.24 #ifdef _LP64 8.25 idealreg2regmask[Op_RegN] = &spillCP->out_RegMask();
9.1 --- a/src/share/vm/opto/memnode.cpp Thu Nov 07 11:47:11 2013 +0100 9.2 +++ b/src/share/vm/opto/memnode.cpp Fri Nov 15 11:05:32 2013 -0800 9.3 @@ -907,7 +907,7 @@ 9.4 9.5 //----------------------------LoadNode::make----------------------------------- 9.6 // Polymorphic factory method: 9.7 -Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt ) { 9.8 +Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo) { 9.9 Compile* C = gvn.C; 9.10 9.11 // sanity check the alias category against the created node type 9.12 @@ -923,34 +923,34 @@ 9.13 rt->isa_oopptr() || is_immutable_value(adr), 9.14 "raw memory operations should have control edge"); 9.15 switch (bt) { 9.16 - case T_BOOLEAN: return new (C) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int() ); 9.17 - case T_BYTE: return new (C) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() ); 9.18 - case T_INT: return new (C) LoadINode (ctl, mem, adr, adr_type, rt->is_int() ); 9.19 - case T_CHAR: return new (C) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int() ); 9.20 - case T_SHORT: return new (C) LoadSNode (ctl, mem, adr, adr_type, rt->is_int() ); 9.21 - case T_LONG: return new (C) LoadLNode (ctl, mem, adr, adr_type, rt->is_long() ); 9.22 - case T_FLOAT: return new (C) LoadFNode (ctl, mem, adr, adr_type, rt ); 9.23 - case T_DOUBLE: return new (C) LoadDNode (ctl, mem, adr, adr_type, rt ); 9.24 - case T_ADDRESS: return new (C) LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr() ); 9.25 + case T_BOOLEAN: return new (C) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo); 9.26 + case T_BYTE: return new (C) LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo); 9.27 + case T_INT: return new (C) LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo); 9.28 + case T_CHAR: return new (C) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo); 9.29 + case T_SHORT: return new (C) LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo); 9.30 + case T_LONG: return new (C) LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo); 9.31 + case T_FLOAT: return new (C) LoadFNode (ctl, mem, adr, adr_type, rt, mo); 9.32 + case T_DOUBLE: return new (C) LoadDNode (ctl, mem, adr, adr_type, rt, mo); 9.33 + case T_ADDRESS: return new (C) LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo); 9.34 case T_OBJECT: 9.35 #ifdef _LP64 9.36 if (adr->bottom_type()->is_ptr_to_narrowoop()) { 9.37 - Node* load = gvn.transform(new (C) LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop())); 9.38 + Node* load = gvn.transform(new (C) LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo)); 9.39 return new (C) DecodeNNode(load, load->bottom_type()->make_ptr()); 9.40 } else 9.41 #endif 9.42 { 9.43 assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop"); 9.44 - return new (C) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr()); 9.45 + return new (C) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo); 9.46 } 9.47 } 9.48 ShouldNotReachHere(); 9.49 return (LoadNode*)NULL; 9.50 } 9.51 9.52 -LoadLNode* LoadLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt) { 9.53 +LoadLNode* LoadLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { 9.54 bool require_atomic = true; 9.55 - return new (C) LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), require_atomic); 9.56 + return new (C) LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, require_atomic); 9.57 } 9.58 9.59 9.60 @@ -2032,12 +2032,12 @@ 9.61 #ifdef _LP64 9.62 if (adr_type->is_ptr_to_narrowklass()) { 9.63 assert(UseCompressedClassPointers, "no compressed klasses"); 9.64 - Node* load_klass = gvn.transform(new (C) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowklass())); 9.65 + Node* load_klass = gvn.transform(new (C) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowklass(), MemNode::unordered)); 9.66 return new (C) DecodeNKlassNode(load_klass, load_klass->bottom_type()->make_ptr()); 9.67 } 9.68 #endif 9.69 assert(!adr_type->is_ptr_to_narrowklass() && !adr_type->is_ptr_to_narrowoop(), "should have got back a narrow oop"); 9.70 - return new (C) LoadKlassNode(ctl, mem, adr, at, tk); 9.71 + return new (C) LoadKlassNode(ctl, mem, adr, at, tk, MemNode::unordered); 9.72 } 9.73 9.74 //------------------------------Value------------------------------------------ 9.75 @@ -2347,45 +2347,46 @@ 9.76 //============================================================================= 9.77 //---------------------------StoreNode::make----------------------------------- 9.78 // Polymorphic factory method: 9.79 -StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt ) { 9.80 +StoreNode* StoreNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt, MemOrd mo) { 9.81 + assert((mo == unordered || mo == release), "unexpected"); 9.82 Compile* C = gvn.C; 9.83 - assert( C->get_alias_index(adr_type) != Compile::AliasIdxRaw || 9.84 - ctl != NULL, "raw memory operations should have control edge"); 9.85 + assert(C->get_alias_index(adr_type) != Compile::AliasIdxRaw || 9.86 + ctl != NULL, "raw memory operations should have control edge"); 9.87 9.88 switch (bt) { 9.89 case T_BOOLEAN: 9.90 - case T_BYTE: return new (C) StoreBNode(ctl, mem, adr, adr_type, val); 9.91 - case T_INT: return new (C) StoreINode(ctl, mem, adr, adr_type, val); 9.92 + case T_BYTE: return new (C) StoreBNode(ctl, mem, adr, adr_type, val, mo); 9.93 + case T_INT: return new (C) StoreINode(ctl, mem, adr, adr_type, val, mo); 9.94 case T_CHAR: 9.95 - case T_SHORT: return new (C) StoreCNode(ctl, mem, adr, adr_type, val); 9.96 - case T_LONG: return new (C) StoreLNode(ctl, mem, adr, adr_type, val); 9.97 - case T_FLOAT: return new (C) StoreFNode(ctl, mem, adr, adr_type, val); 9.98 - case T_DOUBLE: return new (C) StoreDNode(ctl, mem, adr, adr_type, val); 9.99 + case T_SHORT: return new (C) StoreCNode(ctl, mem, adr, adr_type, val, mo); 9.100 + case T_LONG: return new (C) StoreLNode(ctl, mem, adr, adr_type, val, mo); 9.101 + case T_FLOAT: return new (C) StoreFNode(ctl, mem, adr, adr_type, val, mo); 9.102 + case T_DOUBLE: return new (C) StoreDNode(ctl, mem, adr, adr_type, val, mo); 9.103 case T_METADATA: 9.104 case T_ADDRESS: 9.105 case T_OBJECT: 9.106 #ifdef _LP64 9.107 if (adr->bottom_type()->is_ptr_to_narrowoop()) { 9.108 val = gvn.transform(new (C) EncodePNode(val, val->bottom_type()->make_narrowoop())); 9.109 - return new (C) StoreNNode(ctl, mem, adr, adr_type, val); 9.110 + return new (C) StoreNNode(ctl, mem, adr, adr_type, val, mo); 9.111 } else if (adr->bottom_type()->is_ptr_to_narrowklass() || 9.112 (UseCompressedClassPointers && val->bottom_type()->isa_klassptr() && 9.113 adr->bottom_type()->isa_rawptr())) { 9.114 val = gvn.transform(new (C) EncodePKlassNode(val, val->bottom_type()->make_narrowklass())); 9.115 - return new (C) StoreNKlassNode(ctl, mem, adr, adr_type, val); 9.116 + return new (C) StoreNKlassNode(ctl, mem, adr, adr_type, val, mo); 9.117 } 9.118 #endif 9.119 { 9.120 - return new (C) StorePNode(ctl, mem, adr, adr_type, val); 9.121 + return new (C) StorePNode(ctl, mem, adr, adr_type, val, mo); 9.122 } 9.123 } 9.124 ShouldNotReachHere(); 9.125 return (StoreNode*)NULL; 9.126 } 9.127 9.128 -StoreLNode* StoreLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val) { 9.129 +StoreLNode* StoreLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { 9.130 bool require_atomic = true; 9.131 - return new (C) StoreLNode(ctl, mem, adr, adr_type, val, require_atomic); 9.132 + return new (C) StoreLNode(ctl, mem, adr, adr_type, val, mo, require_atomic); 9.133 } 9.134 9.135 9.136 @@ -2778,12 +2779,12 @@ 9.137 9.138 Node *zero = phase->makecon(TypeLong::ZERO); 9.139 Node *off = phase->MakeConX(BytesPerLong); 9.140 - mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero); 9.141 + mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero,MemNode::unordered,false); 9.142 count--; 9.143 while( count-- ) { 9.144 mem = phase->transform(mem); 9.145 adr = phase->transform(new (phase->C) AddPNode(base,adr,off)); 9.146 - mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero); 9.147 + mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero,MemNode::unordered,false); 9.148 } 9.149 return mem; 9.150 } 9.151 @@ -2827,7 +2828,7 @@ 9.152 Node* adr = new (C) AddPNode(dest, dest, phase->MakeConX(offset)); 9.153 adr = phase->transform(adr); 9.154 const TypePtr* atp = TypeRawPtr::BOTTOM; 9.155 - mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT); 9.156 + mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT, MemNode::unordered); 9.157 mem = phase->transform(mem); 9.158 offset += BytesPerInt; 9.159 } 9.160 @@ -2888,7 +2889,7 @@ 9.161 Node* adr = new (C) AddPNode(dest, dest, phase->MakeConX(done_offset)); 9.162 adr = phase->transform(adr); 9.163 const TypePtr* atp = TypeRawPtr::BOTTOM; 9.164 - mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT); 9.165 + mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT, MemNode::unordered); 9.166 mem = phase->transform(mem); 9.167 done_offset += BytesPerInt; 9.168 } 9.169 @@ -3762,14 +3763,14 @@ 9.170 ++new_long; 9.171 off[nst] = offset; 9.172 st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, 9.173 - phase->longcon(con), T_LONG); 9.174 + phase->longcon(con), T_LONG, MemNode::unordered); 9.175 } else { 9.176 // Omit either if it is a zero. 9.177 if (con0 != 0) { 9.178 ++new_int; 9.179 off[nst] = offset; 9.180 st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, 9.181 - phase->intcon(con0), T_INT); 9.182 + phase->intcon(con0), T_INT, MemNode::unordered); 9.183 } 9.184 if (con1 != 0) { 9.185 ++new_int; 9.186 @@ -3777,7 +3778,7 @@ 9.187 adr = make_raw_address(offset, phase); 9.188 off[nst] = offset; 9.189 st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, 9.190 - phase->intcon(con1), T_INT); 9.191 + phase->intcon(con1), T_INT, MemNode::unordered); 9.192 } 9.193 } 9.194
10.1 --- a/src/share/vm/opto/memnode.hpp Thu Nov 07 11:47:11 2013 +0100 10.2 +++ b/src/share/vm/opto/memnode.hpp Fri Nov 15 11:05:32 2013 -0800 10.3 @@ -51,6 +51,10 @@ 10.4 ValueIn, // Value to store 10.5 OopStore // Preceeding oop store, only in StoreCM 10.6 }; 10.7 + typedef enum { unordered = 0, 10.8 + acquire, // Load has to acquire or be succeeded by MemBarAcquire. 10.9 + release // Store has to release or be preceded by MemBarRelease. 10.10 + } MemOrd; 10.11 protected: 10.12 MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at ) 10.13 : Node(c0,c1,c2 ) { 10.14 @@ -134,20 +138,32 @@ 10.15 //------------------------------LoadNode--------------------------------------- 10.16 // Load value; requires Memory and Address 10.17 class LoadNode : public MemNode { 10.18 +private: 10.19 + // On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish 10.20 + // loads that can be reordered, and such requiring acquire semantics to 10.21 + // adhere to the Java specification. The required behaviour is stored in 10.22 + // this field. 10.23 + const MemOrd _mo; 10.24 + 10.25 protected: 10.26 - virtual uint cmp( const Node &n ) const; 10.27 + virtual uint cmp(const Node &n) const; 10.28 virtual uint size_of() const; // Size is bigger 10.29 const Type* const _type; // What kind of value is loaded? 10.30 public: 10.31 10.32 - LoadNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt ) 10.33 - : MemNode(c,mem,adr,at), _type(rt) { 10.34 + LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo) 10.35 + : MemNode(c,mem,adr,at), _type(rt), _mo(mo) { 10.36 init_class_id(Class_Load); 10.37 } 10.38 + inline bool is_unordered() const { return !is_acquire(); } 10.39 + inline bool is_acquire() const { 10.40 + assert(_mo == unordered || _mo == acquire, "unexpected"); 10.41 + return _mo == acquire; 10.42 + } 10.43 10.44 // Polymorphic factory method: 10.45 - static Node* make( PhaseGVN& gvn, Node *c, Node *mem, Node *adr, 10.46 - const TypePtr* at, const Type *rt, BasicType bt ); 10.47 + static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr, 10.48 + const TypePtr* at, const Type *rt, BasicType bt, MemOrd mo); 10.49 10.50 virtual uint hash() const; // Check the type 10.51 10.52 @@ -210,8 +226,8 @@ 10.53 // Load a byte (8bits signed) from memory 10.54 class LoadBNode : public LoadNode { 10.55 public: 10.56 - LoadBNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::BYTE ) 10.57 - : LoadNode(c,mem,adr,at,ti) {} 10.58 + LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) 10.59 + : LoadNode(c, mem, adr, at, ti, mo) {} 10.60 virtual int Opcode() const; 10.61 virtual uint ideal_reg() const { return Op_RegI; } 10.62 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 10.63 @@ -224,8 +240,8 @@ 10.64 // Load a unsigned byte (8bits unsigned) from memory 10.65 class LoadUBNode : public LoadNode { 10.66 public: 10.67 - LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti = TypeInt::UBYTE ) 10.68 - : LoadNode(c, mem, adr, at, ti) {} 10.69 + LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo) 10.70 + : LoadNode(c, mem, adr, at, ti, mo) {} 10.71 virtual int Opcode() const; 10.72 virtual uint ideal_reg() const { return Op_RegI; } 10.73 virtual Node* Ideal(PhaseGVN *phase, bool can_reshape); 10.74 @@ -238,8 +254,8 @@ 10.75 // Load an unsigned short/char (16bits unsigned) from memory 10.76 class LoadUSNode : public LoadNode { 10.77 public: 10.78 - LoadUSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::CHAR ) 10.79 - : LoadNode(c,mem,adr,at,ti) {} 10.80 + LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) 10.81 + : LoadNode(c, mem, adr, at, ti, mo) {} 10.82 virtual int Opcode() const; 10.83 virtual uint ideal_reg() const { return Op_RegI; } 10.84 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 10.85 @@ -252,8 +268,8 @@ 10.86 // Load a short (16bits signed) from memory 10.87 class LoadSNode : public LoadNode { 10.88 public: 10.89 - LoadSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::SHORT ) 10.90 - : LoadNode(c,mem,adr,at,ti) {} 10.91 + LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) 10.92 + : LoadNode(c, mem, adr, at, ti, mo) {} 10.93 virtual int Opcode() const; 10.94 virtual uint ideal_reg() const { return Op_RegI; } 10.95 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 10.96 @@ -266,8 +282,8 @@ 10.97 // Load an integer from memory 10.98 class LoadINode : public LoadNode { 10.99 public: 10.100 - LoadINode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::INT ) 10.101 - : LoadNode(c,mem,adr,at,ti) {} 10.102 + LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) 10.103 + : LoadNode(c, mem, adr, at, ti, mo) {} 10.104 virtual int Opcode() const; 10.105 virtual uint ideal_reg() const { return Op_RegI; } 10.106 virtual int store_Opcode() const { return Op_StoreI; } 10.107 @@ -278,8 +294,8 @@ 10.108 // Load an array length from the array 10.109 class LoadRangeNode : public LoadINode { 10.110 public: 10.111 - LoadRangeNode( Node *c, Node *mem, Node *adr, const TypeInt *ti = TypeInt::POS ) 10.112 - : LoadINode(c,mem,adr,TypeAryPtr::RANGE,ti) {} 10.113 + LoadRangeNode(Node *c, Node *mem, Node *adr, const TypeInt *ti = TypeInt::POS) 10.114 + : LoadINode(c, mem, adr, TypeAryPtr::RANGE, ti, MemNode::unordered) {} 10.115 virtual int Opcode() const; 10.116 virtual const Type *Value( PhaseTransform *phase ) const; 10.117 virtual Node *Identity( PhaseTransform *phase ); 10.118 @@ -298,18 +314,16 @@ 10.119 const bool _require_atomic_access; // is piecewise load forbidden? 10.120 10.121 public: 10.122 - LoadLNode( Node *c, Node *mem, Node *adr, const TypePtr* at, 10.123 - const TypeLong *tl = TypeLong::LONG, 10.124 - bool require_atomic_access = false ) 10.125 - : LoadNode(c,mem,adr,at,tl) 10.126 - , _require_atomic_access(require_atomic_access) 10.127 - {} 10.128 + LoadLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeLong *tl, 10.129 + MemOrd mo, bool require_atomic_access = false) 10.130 + : LoadNode(c, mem, adr, at, tl, mo), _require_atomic_access(require_atomic_access) {} 10.131 virtual int Opcode() const; 10.132 virtual uint ideal_reg() const { return Op_RegL; } 10.133 virtual int store_Opcode() const { return Op_StoreL; } 10.134 virtual BasicType memory_type() const { return T_LONG; } 10.135 bool require_atomic_access() { return _require_atomic_access; } 10.136 - static LoadLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt); 10.137 + static LoadLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, 10.138 + const Type* rt, MemOrd mo); 10.139 #ifndef PRODUCT 10.140 virtual void dump_spec(outputStream *st) const { 10.141 LoadNode::dump_spec(st); 10.142 @@ -322,8 +336,8 @@ 10.143 // Load a long from unaligned memory 10.144 class LoadL_unalignedNode : public LoadLNode { 10.145 public: 10.146 - LoadL_unalignedNode( Node *c, Node *mem, Node *adr, const TypePtr* at ) 10.147 - : LoadLNode(c,mem,adr,at) {} 10.148 + LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo) 10.149 + : LoadLNode(c, mem, adr, at, TypeLong::LONG, mo) {} 10.150 virtual int Opcode() const; 10.151 }; 10.152 10.153 @@ -331,8 +345,8 @@ 10.154 // Load a float (64 bits) from memory 10.155 class LoadFNode : public LoadNode { 10.156 public: 10.157 - LoadFNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t = Type::FLOAT ) 10.158 - : LoadNode(c,mem,adr,at,t) {} 10.159 + LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo) 10.160 + : LoadNode(c, mem, adr, at, t, mo) {} 10.161 virtual int Opcode() const; 10.162 virtual uint ideal_reg() const { return Op_RegF; } 10.163 virtual int store_Opcode() const { return Op_StoreF; } 10.164 @@ -343,8 +357,8 @@ 10.165 // Load a double (64 bits) from memory 10.166 class LoadDNode : public LoadNode { 10.167 public: 10.168 - LoadDNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t = Type::DOUBLE ) 10.169 - : LoadNode(c,mem,adr,at,t) {} 10.170 + LoadDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo) 10.171 + : LoadNode(c, mem, adr, at, t, mo) {} 10.172 virtual int Opcode() const; 10.173 virtual uint ideal_reg() const { return Op_RegD; } 10.174 virtual int store_Opcode() const { return Op_StoreD; } 10.175 @@ -355,8 +369,8 @@ 10.176 // Load a double from unaligned memory 10.177 class LoadD_unalignedNode : public LoadDNode { 10.178 public: 10.179 - LoadD_unalignedNode( Node *c, Node *mem, Node *adr, const TypePtr* at ) 10.180 - : LoadDNode(c,mem,adr,at) {} 10.181 + LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo) 10.182 + : LoadDNode(c, mem, adr, at, Type::DOUBLE, mo) {} 10.183 virtual int Opcode() const; 10.184 }; 10.185 10.186 @@ -364,8 +378,8 @@ 10.187 // Load a pointer from memory (either object or array) 10.188 class LoadPNode : public LoadNode { 10.189 public: 10.190 - LoadPNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t ) 10.191 - : LoadNode(c,mem,adr,at,t) {} 10.192 + LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo) 10.193 + : LoadNode(c, mem, adr, at, t, mo) {} 10.194 virtual int Opcode() const; 10.195 virtual uint ideal_reg() const { return Op_RegP; } 10.196 virtual int store_Opcode() const { return Op_StoreP; } 10.197 @@ -387,8 +401,8 @@ 10.198 // Load a narrow oop from memory (either object or array) 10.199 class LoadNNode : public LoadNode { 10.200 public: 10.201 - LoadNNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t ) 10.202 - : LoadNode(c,mem,adr,at,t) {} 10.203 + LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo) 10.204 + : LoadNode(c, mem, adr, at, t, mo) {} 10.205 virtual int Opcode() const; 10.206 virtual uint ideal_reg() const { return Op_RegN; } 10.207 virtual int store_Opcode() const { return Op_StoreN; } 10.208 @@ -409,8 +423,8 @@ 10.209 // Load a Klass from an object 10.210 class LoadKlassNode : public LoadPNode { 10.211 public: 10.212 - LoadKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeKlassPtr *tk ) 10.213 - : LoadPNode(c,mem,adr,at,tk) {} 10.214 + LoadKlassNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeKlassPtr *tk, MemOrd mo) 10.215 + : LoadPNode(c, mem, adr, at, tk, mo) {} 10.216 virtual int Opcode() const; 10.217 virtual const Type *Value( PhaseTransform *phase ) const; 10.218 virtual Node *Identity( PhaseTransform *phase ); 10.219 @@ -425,8 +439,8 @@ 10.220 // Load a narrow Klass from an object. 10.221 class LoadNKlassNode : public LoadNNode { 10.222 public: 10.223 - LoadNKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowKlass *tk ) 10.224 - : LoadNNode(c,mem,adr,at,tk) {} 10.225 + LoadNKlassNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowKlass *tk, MemOrd mo) 10.226 + : LoadNNode(c, mem, adr, at, tk, mo) {} 10.227 virtual int Opcode() const; 10.228 virtual uint ideal_reg() const { return Op_RegN; } 10.229 virtual int store_Opcode() const { return Op_StoreNKlass; } 10.230 @@ -441,6 +455,14 @@ 10.231 //------------------------------StoreNode-------------------------------------- 10.232 // Store value; requires Store, Address and Value 10.233 class StoreNode : public MemNode { 10.234 +private: 10.235 + // On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish 10.236 + // stores that can be reordered, and such requiring release semantics to 10.237 + // adhere to the Java specification. The required behaviour is stored in 10.238 + // this field. 10.239 + const MemOrd _mo; 10.240 + // Needed for proper cloning. 10.241 + virtual uint size_of() const { return sizeof(*this); } 10.242 protected: 10.243 virtual uint cmp( const Node &n ) const; 10.244 virtual bool depends_only_on_test() const { return false; } 10.245 @@ -449,18 +471,44 @@ 10.246 Node *Ideal_sign_extended_input(PhaseGVN *phase, int num_bits); 10.247 10.248 public: 10.249 - StoreNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) 10.250 - : MemNode(c,mem,adr,at,val) { 10.251 + // We must ensure that stores of object references will be visible 10.252 + // only after the object's initialization. So the callers of this 10.253 + // procedure must indicate that the store requires `release' 10.254 + // semantics, if the stored value is an object reference that might 10.255 + // point to a new object and may become externally visible. 10.256 + StoreNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) 10.257 + : MemNode(c, mem, adr, at, val), _mo(mo) { 10.258 init_class_id(Class_Store); 10.259 } 10.260 - StoreNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store ) 10.261 - : MemNode(c,mem,adr,at,val,oop_store) { 10.262 + StoreNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store, MemOrd mo) 10.263 + : MemNode(c, mem, adr, at, val, oop_store), _mo(mo) { 10.264 init_class_id(Class_Store); 10.265 } 10.266 10.267 - // Polymorphic factory method: 10.268 - static StoreNode* make( PhaseGVN& gvn, Node *c, Node *mem, Node *adr, 10.269 - const TypePtr* at, Node *val, BasicType bt ); 10.270 + inline bool is_unordered() const { return !is_release(); } 10.271 + inline bool is_release() const { 10.272 + assert((_mo == unordered || _mo == release), "unexpected"); 10.273 + return _mo == release; 10.274 + } 10.275 + 10.276 + // Conservatively release stores of object references in order to 10.277 + // ensure visibility of object initialization. 10.278 + static inline MemOrd release_if_reference(const BasicType t) { 10.279 + const MemOrd mo = (t == T_ARRAY || 10.280 + t == T_ADDRESS || // Might be the address of an object reference (`boxing'). 10.281 + t == T_OBJECT) ? release : unordered; 10.282 + return mo; 10.283 + } 10.284 + 10.285 + // Polymorphic factory method 10.286 + // 10.287 + // We must ensure that stores of object references will be visible 10.288 + // only after the object's initialization. So the callers of this 10.289 + // procedure must indicate that the store requires `release' 10.290 + // semantics, if the stored value is an object reference that might 10.291 + // point to a new object and may become externally visible. 10.292 + static StoreNode* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr, 10.293 + const TypePtr* at, Node *val, BasicType bt, MemOrd mo); 10.294 10.295 virtual uint hash() const; // Check the type 10.296 10.297 @@ -491,7 +539,8 @@ 10.298 // Store byte to memory 10.299 class StoreBNode : public StoreNode { 10.300 public: 10.301 - StoreBNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} 10.302 + StoreBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) 10.303 + : StoreNode(c, mem, adr, at, val, mo) {} 10.304 virtual int Opcode() const; 10.305 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 10.306 virtual BasicType memory_type() const { return T_BYTE; } 10.307 @@ -501,7 +550,8 @@ 10.308 // Store char/short to memory 10.309 class StoreCNode : public StoreNode { 10.310 public: 10.311 - StoreCNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} 10.312 + StoreCNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) 10.313 + : StoreNode(c, mem, adr, at, val, mo) {} 10.314 virtual int Opcode() const; 10.315 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 10.316 virtual BasicType memory_type() const { return T_CHAR; } 10.317 @@ -511,7 +561,8 @@ 10.318 // Store int to memory 10.319 class StoreINode : public StoreNode { 10.320 public: 10.321 - StoreINode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} 10.322 + StoreINode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) 10.323 + : StoreNode(c, mem, adr, at, val, mo) {} 10.324 virtual int Opcode() const; 10.325 virtual BasicType memory_type() const { return T_INT; } 10.326 }; 10.327 @@ -528,15 +579,12 @@ 10.328 const bool _require_atomic_access; // is piecewise store forbidden? 10.329 10.330 public: 10.331 - StoreLNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, 10.332 - bool require_atomic_access = false ) 10.333 - : StoreNode(c,mem,adr,at,val) 10.334 - , _require_atomic_access(require_atomic_access) 10.335 - {} 10.336 + StoreLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo, bool require_atomic_access = false) 10.337 + : StoreNode(c, mem, adr, at, val, mo), _require_atomic_access(require_atomic_access) {} 10.338 virtual int Opcode() const; 10.339 virtual BasicType memory_type() const { return T_LONG; } 10.340 bool require_atomic_access() { return _require_atomic_access; } 10.341 - static StoreLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val); 10.342 + static StoreLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); 10.343 #ifndef PRODUCT 10.344 virtual void dump_spec(outputStream *st) const { 10.345 StoreNode::dump_spec(st); 10.346 @@ -549,7 +597,8 @@ 10.347 // Store float to memory 10.348 class StoreFNode : public StoreNode { 10.349 public: 10.350 - StoreFNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} 10.351 + StoreFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) 10.352 + : StoreNode(c, mem, adr, at, val, mo) {} 10.353 virtual int Opcode() const; 10.354 virtual BasicType memory_type() const { return T_FLOAT; } 10.355 }; 10.356 @@ -558,7 +607,8 @@ 10.357 // Store double to memory 10.358 class StoreDNode : public StoreNode { 10.359 public: 10.360 - StoreDNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} 10.361 + StoreDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) 10.362 + : StoreNode(c, mem, adr, at, val, mo) {} 10.363 virtual int Opcode() const; 10.364 virtual BasicType memory_type() const { return T_DOUBLE; } 10.365 }; 10.366 @@ -567,7 +617,8 @@ 10.367 // Store pointer to memory 10.368 class StorePNode : public StoreNode { 10.369 public: 10.370 - StorePNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} 10.371 + StorePNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) 10.372 + : StoreNode(c, mem, adr, at, val, mo) {} 10.373 virtual int Opcode() const; 10.374 virtual BasicType memory_type() const { return T_ADDRESS; } 10.375 }; 10.376 @@ -576,7 +627,8 @@ 10.377 // Store narrow oop to memory 10.378 class StoreNNode : public StoreNode { 10.379 public: 10.380 - StoreNNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} 10.381 + StoreNNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) 10.382 + : StoreNode(c, mem, adr, at, val, mo) {} 10.383 virtual int Opcode() const; 10.384 virtual BasicType memory_type() const { return T_NARROWOOP; } 10.385 }; 10.386 @@ -585,7 +637,8 @@ 10.387 // Store narrow klass to memory 10.388 class StoreNKlassNode : public StoreNNode { 10.389 public: 10.390 - StoreNKlassNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNNode(c,mem,adr,at,val) {} 10.391 + StoreNKlassNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) 10.392 + : StoreNNode(c, mem, adr, at, val, mo) {} 10.393 virtual int Opcode() const; 10.394 virtual BasicType memory_type() const { return T_NARROWKLASS; } 10.395 }; 10.396 @@ -606,7 +659,7 @@ 10.397 10.398 public: 10.399 StoreCMNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store, int oop_alias_idx ) : 10.400 - StoreNode(c,mem,adr,at,val,oop_store), 10.401 + StoreNode(c, mem, adr, at, val, oop_store, MemNode::release), 10.402 _oop_alias_idx(oop_alias_idx) { 10.403 assert(_oop_alias_idx >= Compile::AliasIdxRaw || 10.404 _oop_alias_idx == Compile::AliasIdxBot && Compile::current()->AliasLevel() == 0, 10.405 @@ -626,8 +679,8 @@ 10.406 // On PowerPC and friends it's a real load-locked. 10.407 class LoadPLockedNode : public LoadPNode { 10.408 public: 10.409 - LoadPLockedNode( Node *c, Node *mem, Node *adr ) 10.410 - : LoadPNode(c,mem,adr,TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM) {} 10.411 + LoadPLockedNode(Node *c, Node *mem, Node *adr, MemOrd mo) 10.412 + : LoadPNode(c, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, mo) {} 10.413 virtual int Opcode() const; 10.414 virtual int store_Opcode() const { return Op_StorePConditional; } 10.415 virtual bool depends_only_on_test() const { return true; }
11.1 --- a/src/share/vm/opto/mulnode.cpp Thu Nov 07 11:47:11 2013 +0100 11.2 +++ b/src/share/vm/opto/mulnode.cpp Fri Nov 15 11:05:32 2013 -0800 11.3 @@ -485,7 +485,8 @@ 11.4 Node *ldus = new (phase->C) LoadUSNode(load->in(MemNode::Control), 11.5 load->in(MemNode::Memory), 11.6 load->in(MemNode::Address), 11.7 - load->adr_type()); 11.8 + load->adr_type(), 11.9 + TypeInt::CHAR, MemNode::unordered); 11.10 ldus = phase->transform(ldus); 11.11 return new (phase->C) AndINode(ldus, phase->intcon(mask & 0xFFFF)); 11.12 } 11.13 @@ -496,7 +497,8 @@ 11.14 Node* ldub = new (phase->C) LoadUBNode(load->in(MemNode::Control), 11.15 load->in(MemNode::Memory), 11.16 load->in(MemNode::Address), 11.17 - load->adr_type()); 11.18 + load->adr_type(), 11.19 + TypeInt::UBYTE, MemNode::unordered); 11.20 ldub = phase->transform(ldub); 11.21 return new (phase->C) AndINode(ldub, phase->intcon(mask)); 11.22 } 11.23 @@ -931,9 +933,10 @@ 11.24 ld->outcnt() == 1 && ld->unique_out() == shl) 11.25 // Replace zero-extension-load with sign-extension-load 11.26 return new (phase->C) LoadSNode( ld->in(MemNode::Control), 11.27 - ld->in(MemNode::Memory), 11.28 - ld->in(MemNode::Address), 11.29 - ld->adr_type()); 11.30 + ld->in(MemNode::Memory), 11.31 + ld->in(MemNode::Address), 11.32 + ld->adr_type(), TypeInt::SHORT, 11.33 + MemNode::unordered); 11.34 } 11.35 11.36 // Check for "(byte[i] <<24)>>24" which simply sign-extends
12.1 --- a/src/share/vm/opto/parse1.cpp Thu Nov 07 11:47:11 2013 +0100 12.2 +++ b/src/share/vm/opto/parse1.cpp Fri Nov 15 11:05:32 2013 -0800 12.3 @@ -106,24 +106,24 @@ 12.4 // Very similar to LoadNode::make, except we handle un-aligned longs and 12.5 // doubles on Sparc. Intel can handle them just fine directly. 12.6 Node *l; 12.7 - switch( bt ) { // Signature is flattened 12.8 - case T_INT: l = new (C) LoadINode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break; 12.9 - case T_FLOAT: l = new (C) LoadFNode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break; 12.10 - case T_ADDRESS: l = new (C) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ); break; 12.11 - case T_OBJECT: l = new (C) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break; 12.12 + switch (bt) { // Signature is flattened 12.13 + case T_INT: l = new (C) LoadINode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInt::INT, MemNode::unordered); break; 12.14 + case T_FLOAT: l = new (C) LoadFNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::FLOAT, MemNode::unordered); break; 12.15 + case T_ADDRESS: l = new (C) LoadPNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered); break; 12.16 + case T_OBJECT: l = new (C) LoadPNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM, MemNode::unordered); break; 12.17 case T_LONG: 12.18 case T_DOUBLE: { 12.19 // Since arguments are in reverse order, the argument address 'adr' 12.20 // refers to the back half of the long/double. Recompute adr. 12.21 - adr = basic_plus_adr( local_addrs_base, local_addrs, -(index+1)*wordSize ); 12.22 - if( Matcher::misaligned_doubles_ok ) { 12.23 + adr = basic_plus_adr(local_addrs_base, local_addrs, -(index+1)*wordSize); 12.24 + if (Matcher::misaligned_doubles_ok) { 12.25 l = (bt == T_DOUBLE) 12.26 - ? (Node*)new (C) LoadDNode( ctl, mem, adr, TypeRawPtr::BOTTOM ) 12.27 - : (Node*)new (C) LoadLNode( ctl, mem, adr, TypeRawPtr::BOTTOM ); 12.28 + ? (Node*)new (C) LoadDNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::DOUBLE, MemNode::unordered) 12.29 + : (Node*)new (C) LoadLNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeLong::LONG, MemNode::unordered); 12.30 } else { 12.31 l = (bt == T_DOUBLE) 12.32 - ? (Node*)new (C) LoadD_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM ) 12.33 - : (Node*)new (C) LoadL_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM ); 12.34 + ? (Node*)new (C) LoadD_unalignedNode(ctl, mem, adr, TypeRawPtr::BOTTOM, MemNode::unordered) 12.35 + : (Node*)new (C) LoadL_unalignedNode(ctl, mem, adr, TypeRawPtr::BOTTOM, MemNode::unordered); 12.36 } 12.37 break; 12.38 } 12.39 @@ -229,7 +229,7 @@ 12.40 Node *displaced_hdr = fetch_interpreter_state((index*2) + 1, T_ADDRESS, monitors_addr, osr_buf); 12.41 12.42 12.43 - store_to_memory(control(), box, displaced_hdr, T_ADDRESS, Compile::AliasIdxRaw); 12.44 + store_to_memory(control(), box, displaced_hdr, T_ADDRESS, Compile::AliasIdxRaw, MemNode::unordered); 12.45 12.46 // Build a bogus FastLockNode (no code will be generated) and push the 12.47 // monitor into our debug info. 12.48 @@ -1931,7 +1931,7 @@ 12.49 Node* klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), klass_addr, TypeInstPtr::KLASS) ); 12.50 12.51 Node* access_flags_addr = basic_plus_adr(klass, klass, in_bytes(Klass::access_flags_offset())); 12.52 - Node* access_flags = make_load(NULL, access_flags_addr, TypeInt::INT, T_INT); 12.53 + Node* access_flags = make_load(NULL, access_flags_addr, TypeInt::INT, T_INT, MemNode::unordered); 12.54 12.55 Node* mask = _gvn.transform(new (C) AndINode(access_flags, intcon(JVM_ACC_HAS_FINALIZER))); 12.56 Node* check = _gvn.transform(new (C) CmpINode(mask, intcon(0)));
13.1 --- a/src/share/vm/opto/parse2.cpp Thu Nov 07 11:47:11 2013 +0100 13.2 +++ b/src/share/vm/opto/parse2.cpp Fri Nov 15 11:05:32 2013 -0800 13.3 @@ -50,7 +50,7 @@ 13.4 if (stopped()) return; // guaranteed null or range check 13.5 dec_sp(2); // Pop array and index 13.6 const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type); 13.7 - Node* ld = make_load(control(), adr, elem, elem_type, adr_type); 13.8 + Node* ld = make_load(control(), adr, elem, elem_type, adr_type, MemNode::unordered); 13.9 push(ld); 13.10 } 13.11 13.12 @@ -62,7 +62,7 @@ 13.13 Node* val = pop(); 13.14 dec_sp(2); // Pop array and index 13.15 const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type); 13.16 - store_to_memory(control(), adr, val, elem_type, adr_type); 13.17 + store_to_memory(control(), adr, val, elem_type, adr_type, StoreNode::release_if_reference(elem_type)); 13.18 } 13.19 13.20 13.21 @@ -1720,14 +1720,14 @@ 13.22 a = array_addressing(T_LONG, 0); 13.23 if (stopped()) return; // guaranteed null or range check 13.24 dec_sp(2); // Pop array and index 13.25 - push_pair(make_load(control(), a, TypeLong::LONG, T_LONG, TypeAryPtr::LONGS)); 13.26 + push_pair(make_load(control(), a, TypeLong::LONG, T_LONG, TypeAryPtr::LONGS, MemNode::unordered)); 13.27 break; 13.28 } 13.29 case Bytecodes::_daload: { 13.30 a = array_addressing(T_DOUBLE, 0); 13.31 if (stopped()) return; // guaranteed null or range check 13.32 dec_sp(2); // Pop array and index 13.33 - push_pair(make_load(control(), a, Type::DOUBLE, T_DOUBLE, TypeAryPtr::DOUBLES)); 13.34 + push_pair(make_load(control(), a, Type::DOUBLE, T_DOUBLE, TypeAryPtr::DOUBLES, MemNode::unordered)); 13.35 break; 13.36 } 13.37 case Bytecodes::_bastore: array_store(T_BYTE); break; 13.38 @@ -1744,7 +1744,7 @@ 13.39 a = pop(); // the array itself 13.40 const TypeOopPtr* elemtype = _gvn.type(a)->is_aryptr()->elem()->make_oopptr(); 13.41 const TypeAryPtr* adr_type = TypeAryPtr::OOPS; 13.42 - Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT); 13.43 + Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT, MemNode::release); 13.44 break; 13.45 } 13.46 case Bytecodes::_lastore: { 13.47 @@ -1752,7 +1752,7 @@ 13.48 if (stopped()) return; // guaranteed null or range check 13.49 c = pop_pair(); 13.50 dec_sp(2); // Pop array and index 13.51 - store_to_memory(control(), a, c, T_LONG, TypeAryPtr::LONGS); 13.52 + store_to_memory(control(), a, c, T_LONG, TypeAryPtr::LONGS, MemNode::unordered); 13.53 break; 13.54 } 13.55 case Bytecodes::_dastore: { 13.56 @@ -1761,7 +1761,7 @@ 13.57 c = pop_pair(); 13.58 dec_sp(2); // Pop array and index 13.59 c = dstore_rounding(c); 13.60 - store_to_memory(control(), a, c, T_DOUBLE, TypeAryPtr::DOUBLES); 13.61 + store_to_memory(control(), a, c, T_DOUBLE, TypeAryPtr::DOUBLES, MemNode::unordered); 13.62 break; 13.63 } 13.64 case Bytecodes::_getfield:
14.1 --- a/src/share/vm/opto/parse3.cpp Thu Nov 07 11:47:11 2013 +0100 14.2 +++ b/src/share/vm/opto/parse3.cpp Fri Nov 15 11:05:32 2013 -0800 14.3 @@ -228,7 +228,9 @@ 14.4 type = Type::get_const_basic_type(bt); 14.5 } 14.6 // Build the load. 14.7 - Node* ld = make_load(NULL, adr, type, bt, adr_type, is_vol); 14.8 + // 14.9 + MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered; 14.10 + Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, is_vol); 14.11 14.12 // Adjust Java stack 14.13 if (type2size[bt] == 1) 14.14 @@ -288,6 +290,16 @@ 14.15 // Round doubles before storing 14.16 if (bt == T_DOUBLE) val = dstore_rounding(val); 14.17 14.18 + // Conservatively release stores of object references. 14.19 + const MemNode::MemOrd mo = 14.20 + is_vol ? 14.21 + // Volatile fields need releasing stores. 14.22 + MemNode::release : 14.23 + // Non-volatile fields also need releasing stores if they hold an 14.24 + // object reference, because the object reference might point to 14.25 + // a freshly created object. 14.26 + StoreNode::release_if_reference(bt); 14.27 + 14.28 // Store the value. 14.29 Node* store; 14.30 if (bt == T_OBJECT) { 14.31 @@ -297,9 +309,9 @@ 14.32 } else { 14.33 field_type = TypeOopPtr::make_from_klass(field->type()->as_klass()); 14.34 } 14.35 - store = store_oop_to_object( control(), obj, adr, adr_type, val, field_type, bt); 14.36 + store = store_oop_to_object(control(), obj, adr, adr_type, val, field_type, bt, mo); 14.37 } else { 14.38 - store = store_to_memory( control(), adr, val, bt, adr_type, is_vol ); 14.39 + store = store_to_memory(control(), adr, val, bt, adr_type, mo, is_vol); 14.40 } 14.41 14.42 // If reference is volatile, prevent following volatiles ops from 14.43 @@ -414,7 +426,7 @@ 14.44 Node* elem = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1, nargs); 14.45 intptr_t offset = header + ((intptr_t)i << LogBytesPerHeapOop); 14.46 Node* eaddr = basic_plus_adr(array, offset); 14.47 - store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT); 14.48 + store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT, MemNode::unordered); 14.49 } 14.50 } 14.51 return array; 14.52 @@ -503,7 +515,7 @@ 14.53 // Fill-in it with values 14.54 for (j = 0; j < ndimensions; j++) { 14.55 Node *dims_elem = array_element_address(dims, intcon(j), T_INT); 14.56 - store_to_memory(control(), dims_elem, length[j], T_INT, TypeAryPtr::INTS); 14.57 + store_to_memory(control(), dims_elem, length[j], T_INT, TypeAryPtr::INTS, MemNode::unordered); 14.58 } 14.59 } 14.60
15.1 --- a/src/share/vm/opto/parseHelper.cpp Thu Nov 07 11:47:11 2013 +0100 15.2 +++ b/src/share/vm/opto/parseHelper.cpp Fri Nov 15 11:05:32 2013 -0800 15.3 @@ -222,7 +222,7 @@ 15.4 15.5 Node* init_thread_offset = _gvn.MakeConX(in_bytes(InstanceKlass::init_thread_offset())); 15.6 Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset); 15.7 - Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS); 15.8 + Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS, MemNode::unordered); 15.9 Node *tst = Bool( CmpP( init_thread, cur_thread), BoolTest::eq); 15.10 IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); 15.11 set_control(IfTrue(iff)); 15.12 @@ -232,7 +232,7 @@ 15.13 adr_node = basic_plus_adr(kls, kls, init_state_offset); 15.14 // Use T_BOOLEAN for InstanceKlass::_init_state so the compiler 15.15 // can generate code to load it as unsigned byte. 15.16 - Node* init_state = make_load(NULL, adr_node, TypeInt::UBYTE, T_BOOLEAN); 15.17 + Node* init_state = make_load(NULL, adr_node, TypeInt::UBYTE, T_BOOLEAN, MemNode::unordered); 15.18 Node* being_init = _gvn.intcon(InstanceKlass::being_initialized); 15.19 tst = Bool( CmpI( init_state, being_init), BoolTest::eq); 15.20 iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); 15.21 @@ -354,13 +354,13 @@ 15.22 Node *counters_node = makecon(adr_type); 15.23 Node* adr_iic_node = basic_plus_adr(counters_node, counters_node, 15.24 MethodCounters::interpreter_invocation_counter_offset_in_bytes()); 15.25 - Node* cnt = make_load(ctrl, adr_iic_node, TypeInt::INT, T_INT, adr_type); 15.26 + Node* cnt = make_load(ctrl, adr_iic_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); 15.27 15.28 test_counter_against_threshold(cnt, limit); 15.29 15.30 // Add one to the counter and store 15.31 Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1))); 15.32 - store_to_memory( ctrl, adr_iic_node, incr, T_INT, adr_type ); 15.33 + store_to_memory(ctrl, adr_iic_node, incr, T_INT, adr_type, MemNode::unordered); 15.34 } 15.35 15.36 //----------------------------method_data_addressing--------------------------- 15.37 @@ -392,9 +392,9 @@ 15.38 Node* adr_node = method_data_addressing(md, data, counter_offset, idx, stride); 15.39 15.40 const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); 15.41 - Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); 15.42 + Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); 15.43 Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(DataLayout::counter_increment))); 15.44 - store_to_memory(NULL, adr_node, incr, T_INT, adr_type ); 15.45 + store_to_memory(NULL, adr_node, incr, T_INT, adr_type, MemNode::unordered); 15.46 } 15.47 15.48 //--------------------------test_for_osr_md_counter_at------------------------- 15.49 @@ -402,7 +402,7 @@ 15.50 Node* adr_node = method_data_addressing(md, data, counter_offset); 15.51 15.52 const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); 15.53 - Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); 15.54 + Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); 15.55 15.56 test_counter_against_threshold(cnt, limit); 15.57 } 15.58 @@ -412,9 +412,9 @@ 15.59 Node* adr_node = method_data_addressing(md, data, DataLayout::flags_offset()); 15.60 15.61 const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); 15.62 - Node* flags = make_load(NULL, adr_node, TypeInt::BYTE, T_BYTE, adr_type); 15.63 + Node* flags = make_load(NULL, adr_node, TypeInt::BYTE, T_BYTE, adr_type, MemNode::unordered); 15.64 Node* incr = _gvn.transform(new (C) OrINode(flags, _gvn.intcon(flag_constant))); 15.65 - store_to_memory(NULL, adr_node, incr, T_BYTE, adr_type); 15.66 + store_to_memory(NULL, adr_node, incr, T_BYTE, adr_type, MemNode::unordered); 15.67 } 15.68 15.69 //----------------------------profile_taken_branch-----------------------------
16.1 --- a/src/share/vm/opto/stringopts.cpp Thu Nov 07 11:47:11 2013 +0100 16.2 +++ b/src/share/vm/opto/stringopts.cpp Fri Nov 15 11:05:32 2013 -0800 16.3 @@ -1122,7 +1122,8 @@ 16.4 16.5 return kit.make_load(NULL, kit.basic_plus_adr(klass_node, field->offset_in_bytes()), 16.6 type, T_OBJECT, 16.7 - C->get_alias_index(mirror_type->add_offset(field->offset_in_bytes()))); 16.8 + C->get_alias_index(mirror_type->add_offset(field->offset_in_bytes())), 16.9 + MemNode::unordered); 16.10 } 16.11 16.12 Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) { 16.13 @@ -1314,7 +1315,7 @@ 16.14 Node* ch = __ AddI(r, __ intcon('0')); 16.15 16.16 Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR), 16.17 - ch, T_CHAR, char_adr_idx); 16.18 + ch, T_CHAR, char_adr_idx, MemNode::unordered); 16.19 16.20 16.21 IfNode* iff = kit.create_and_map_if(head, __ Bool(__ CmpI(q, __ intcon(0)), BoolTest::ne), 16.22 @@ -1356,7 +1357,7 @@ 16.23 } else { 16.24 Node* m1 = __ SubI(charPos, __ intcon(1)); 16.25 Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR), 16.26 - sign, T_CHAR, char_adr_idx); 16.27 + sign, T_CHAR, char_adr_idx, MemNode::unordered); 16.28 16.29 final_merge->init_req(1, kit.control()); 16.30 final_mem->init_req(1, st); 16.31 @@ -1387,7 +1388,8 @@ 16.32 ciTypeArray* value_array = t->const_oop()->as_type_array(); 16.33 for (int e = 0; e < c; e++) { 16.34 __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR), 16.35 - __ intcon(value_array->char_at(o + e)), T_CHAR, char_adr_idx); 16.36 + __ intcon(value_array->char_at(o + e)), T_CHAR, char_adr_idx, 16.37 + MemNode::unordered); 16.38 start = __ AddI(start, __ intcon(1)); 16.39 } 16.40 } else { 16.41 @@ -1607,7 +1609,7 @@ 16.42 } 16.43 case StringConcat::CharMode: { 16.44 __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR), 16.45 - arg, T_CHAR, char_adr_idx); 16.46 + arg, T_CHAR, char_adr_idx, MemNode::unordered); 16.47 start = __ AddI(start, __ intcon(1)); 16.48 break; 16.49 }
17.1 --- a/src/share/vm/opto/vectornode.hpp Thu Nov 07 11:47:11 2013 +0100 17.2 +++ b/src/share/vm/opto/vectornode.hpp Fri Nov 15 11:05:32 2013 -0800 17.3 @@ -356,7 +356,7 @@ 17.4 class LoadVectorNode : public LoadNode { 17.5 public: 17.6 LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt) 17.7 - : LoadNode(c, mem, adr, at, vt) { 17.8 + : LoadNode(c, mem, adr, at, vt, MemNode::unordered) { 17.9 init_class_id(Class_LoadVector); 17.10 } 17.11 17.12 @@ -380,7 +380,7 @@ 17.13 class StoreVectorNode : public StoreNode { 17.14 public: 17.15 StoreVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, Node* val) 17.16 - : StoreNode(c, mem, adr, at, val) { 17.17 + : StoreNode(c, mem, adr, at, val, MemNode::unordered) { 17.18 assert(val->is_Vector() || val->is_LoadVector(), "sanity"); 17.19 init_class_id(Class_StoreVector); 17.20 }