8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering

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
This commit is contained in:
Goetz Lindenmaier 2013-11-15 11:05:32 -08:00
parent d8b9e9f681
commit 13b13f5259
17 changed files with 351 additions and 255 deletions

View File

@ -104,13 +104,12 @@ void GraphKit::gen_stub(address C_function,
//
Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset()));
Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS);
store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias);
store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias, MemNode::unordered);
// Set _thread_in_native
// The order of stores into TLS is critical! Setting _thread_in_native MUST
// be last, because a GC is allowed at any time after setting it and the GC
// will require last_Java_pc and last_Java_sp.
Node* adr_state = basic_plus_adr(top(), thread, in_bytes(JavaThread::thread_state_offset()));
//-----------------------------
// Compute signature for C call. Varies from the Java signature!
@ -225,16 +224,15 @@ void GraphKit::gen_stub(address C_function,
//-----------------------------
// Clear last_Java_sp
store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias);
store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias, MemNode::unordered);
// Clear last_Java_pc and (optionally)_flags
store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias);
store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias, MemNode::unordered);
#if defined(SPARC)
store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias);
store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias, MemNode::unordered);
#endif /* defined(SPARC) */
#if (defined(IA64) && !defined(AIX))
Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset()));
if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease);
store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias);
store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias, MemNode::unordered);
#endif
// For is-fancy-jump, the C-return value is also the branch target
@ -242,16 +240,16 @@ void GraphKit::gen_stub(address C_function,
// Runtime call returning oop in TLS? Fetch it out
if( pass_tls ) {
Node* adr = basic_plus_adr(top(), thread, in_bytes(JavaThread::vm_result_offset()));
Node* vm_result = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, false);
Node* vm_result = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, MemNode::unordered);
map()->set_req(TypeFunc::Parms, vm_result); // vm_result passed as result
// clear thread-local-storage(tls)
store_to_memory(NULL, adr, null(), T_ADDRESS, NoAlias);
store_to_memory(NULL, adr, null(), T_ADDRESS, NoAlias, MemNode::unordered);
}
//-----------------------------
// check exception
Node* adr = basic_plus_adr(top(), thread, in_bytes(Thread::pending_exception_offset()));
Node* pending = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, false);
Node* pending = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, MemNode::unordered);
Node* exit_memory = reset_memory();

View File

@ -494,7 +494,7 @@ void GraphKit::uncommon_trap_if_should_post_on_exceptions(Deoptimization::DeoptR
// first must access the should_post_on_exceptions_flag in this thread's JavaThread
Node* jthread = _gvn.transform(new (C) ThreadLocalNode());
Node* adr = basic_plus_adr(top(), jthread, in_bytes(JavaThread::should_post_on_exceptions_flag_offset()));
Node* should_post_flag = make_load(control(), adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, false);
Node* should_post_flag = make_load(control(), adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, MemNode::unordered);
// Test the should_post_on_exceptions_flag vs. 0
Node* chk = _gvn.transform( new (C) CmpINode(should_post_flag, intcon(0)) );
@ -596,7 +596,8 @@ void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) {
Node *adr = basic_plus_adr(ex_node, ex_node, offset);
const TypeOopPtr* val_type = TypeOopPtr::make_from_klass(env()->String_klass());
Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), val_type, T_OBJECT);
// Conservatively release stores of object references.
Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), val_type, T_OBJECT, MemNode::release);
add_exception_state(make_exception_state(ex_node));
return;
@ -1483,16 +1484,16 @@ void GraphKit::set_all_memory_call(Node* call, bool separate_io_proj) {
// factory methods in "int adr_idx"
Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
int adr_idx,
bool require_atomic_access) {
MemNode::MemOrd mo, bool require_atomic_access) {
assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" );
const TypePtr* adr_type = NULL; // debug-mode-only argument
debug_only(adr_type = C->get_adr_type(adr_idx));
Node* mem = memory(adr_idx);
Node* ld;
if (require_atomic_access && bt == T_LONG) {
ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t);
ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, mo);
} else {
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt);
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo);
}
ld = _gvn.transform(ld);
if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) {
@ -1504,6 +1505,7 @@ Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt,
int adr_idx,
MemNode::MemOrd mo,
bool require_atomic_access) {
assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" );
const TypePtr* adr_type = NULL;
@ -1511,9 +1513,9 @@ Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt,
Node *mem = memory(adr_idx);
Node* st;
if (require_atomic_access && bt == T_LONG) {
st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val);
st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo);
} else {
st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt);
st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo);
}
st = _gvn.transform(st);
set_memory(st, adr_idx);
@ -1613,7 +1615,8 @@ Node* GraphKit::store_oop(Node* ctl,
Node* val,
const TypeOopPtr* val_type,
BasicType bt,
bool use_precise) {
bool use_precise,
MemNode::MemOrd mo) {
// Transformation of a value which could be NULL pointer (CastPP #NULL)
// could be delayed during Parse (for example, in adjust_map_after_if()).
// Execute transformation here to avoid barrier generation in such case.
@ -1633,7 +1636,7 @@ Node* GraphKit::store_oop(Node* ctl,
NULL /* pre_val */,
bt);
Node* store = store_to_memory(control(), adr, val, bt, adr_idx);
Node* store = store_to_memory(control(), adr, val, bt, adr_idx, mo);
post_barrier(control(), store, obj, adr, adr_idx, val, bt, use_precise);
return store;
}
@ -1644,7 +1647,8 @@ Node* GraphKit::store_oop_to_unknown(Node* ctl,
Node* adr, // actual adress to store val at
const TypePtr* adr_type,
Node* val,
BasicType bt) {
BasicType bt,
MemNode::MemOrd mo) {
Compile::AliasType* at = C->alias_type(adr_type);
const TypeOopPtr* val_type = NULL;
if (adr_type->isa_instptr()) {
@ -1663,7 +1667,7 @@ Node* GraphKit::store_oop_to_unknown(Node* ctl,
if (val_type == NULL) {
val_type = TypeInstPtr::BOTTOM;
}
return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true);
return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true, mo);
}
@ -1707,7 +1711,7 @@ Node* GraphKit::load_array_element(Node* ctl, Node* ary, Node* idx, const TypeAr
const Type* elemtype = arytype->elem();
BasicType elembt = elemtype->array_element_basic_type();
Node* adr = array_element_address(ary, idx, elembt, arytype->size());
Node* ld = make_load(ctl, adr, elemtype, elembt, arytype);
Node* ld = make_load(ctl, adr, elemtype, elembt, arytype, MemNode::unordered);
return ld;
}
@ -1942,9 +1946,9 @@ void GraphKit::increment_counter(address counter_addr) {
void GraphKit::increment_counter(Node* counter_addr) {
int adr_type = Compile::AliasIdxRaw;
Node* ctrl = control();
Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type);
Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1)));
store_to_memory( ctrl, counter_addr, incr, T_INT, adr_type );
store_to_memory(ctrl, counter_addr, incr, T_INT, adr_type, MemNode::unordered);
}
@ -2525,7 +2529,8 @@ Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) {
// First load the super-klass's check-offset
Node *p1 = basic_plus_adr( superklass, superklass, in_bytes(Klass::super_check_offset_offset()) );
Node *chk_off = _gvn.transform( new (C) LoadINode( NULL, memory(p1), p1, _gvn.type(p1)->is_ptr() ) );
Node *chk_off = _gvn.transform(new (C) LoadINode(NULL, memory(p1), p1, _gvn.type(p1)->is_ptr(),
TypeInt::INT, MemNode::unordered));
int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset());
bool might_be_cache = (find_int_con(chk_off, cacheoff_con) == cacheoff_con);
@ -3238,7 +3243,7 @@ Node* GraphKit::get_layout_helper(Node* klass_node, jint& constant_value) {
}
constant_value = Klass::_lh_neutral_value; // put in a known value
Node* lhp = basic_plus_adr(klass_node, klass_node, in_bytes(Klass::layout_helper_offset()));
return make_load(NULL, lhp, TypeInt::INT, T_INT);
return make_load(NULL, lhp, TypeInt::INT, T_INT, MemNode::unordered);
}
// We just put in an allocate/initialize with a big raw-memory effect.
@ -3773,7 +3778,7 @@ void GraphKit::write_barrier_post(Node* oop_store,
// Smash zero into card
if( !UseConcMarkSweepGC ) {
__ store(__ ctrl(), card_adr, zero, bt, adr_type);
__ store(__ ctrl(), card_adr, zero, bt, adr_type, MemNode::release);
} else {
// Specialized path for CM store barrier
__ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, bt, adr_type);
@ -3870,9 +3875,9 @@ void GraphKit::g1_write_barrier_pre(bool do_load,
// Now get the buffer location we will log the previous value into and store it
Node *log_addr = __ AddP(no_base, buffer, next_index);
__ store(__ ctrl(), log_addr, pre_val, T_OBJECT, Compile::AliasIdxRaw);
__ store(__ ctrl(), log_addr, pre_val, T_OBJECT, Compile::AliasIdxRaw, MemNode::unordered);
// update the index
__ store(__ ctrl(), index_adr, next_index, index_bt, Compile::AliasIdxRaw);
__ store(__ ctrl(), index_adr, next_index, index_bt, Compile::AliasIdxRaw, MemNode::unordered);
} __ else_(); {
@ -3912,8 +3917,9 @@ void GraphKit::g1_mark_card(IdealKit& ideal,
Node* next_index = _gvn.transform(new (C) SubXNode(index, __ ConX(sizeof(intptr_t))));
Node* log_addr = __ AddP(no_base, buffer, next_index);
__ store(__ ctrl(), log_addr, card_adr, T_ADDRESS, Compile::AliasIdxRaw);
__ store(__ ctrl(), index_adr, next_index, TypeX_X->basic_type(), Compile::AliasIdxRaw);
// Order, see storeCM.
__ store(__ ctrl(), log_addr, card_adr, T_ADDRESS, Compile::AliasIdxRaw, MemNode::unordered);
__ store(__ ctrl(), index_adr, next_index, TypeX_X->basic_type(), Compile::AliasIdxRaw, MemNode::unordered);
} __ else_(); {
__ make_leaf_call(tf, CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), "g1_wb_post", card_adr, __ thread());
@ -4043,7 +4049,7 @@ Node* GraphKit::load_String_offset(Node* ctrl, Node* str) {
int offset_field_idx = C->get_alias_index(offset_field_type);
return make_load(ctrl,
basic_plus_adr(str, str, offset_offset),
TypeInt::INT, T_INT, offset_field_idx);
TypeInt::INT, T_INT, offset_field_idx, MemNode::unordered);
} else {
return intcon(0);
}
@ -4058,7 +4064,7 @@ Node* GraphKit::load_String_length(Node* ctrl, Node* str) {
int count_field_idx = C->get_alias_index(count_field_type);
return make_load(ctrl,
basic_plus_adr(str, str, count_offset),
TypeInt::INT, T_INT, count_field_idx);
TypeInt::INT, T_INT, count_field_idx, MemNode::unordered);
} else {
return load_array_length(load_String_value(ctrl, str));
}
@ -4074,7 +4080,7 @@ Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
ciTypeArrayKlass::make(T_CHAR), true, 0);
int value_field_idx = C->get_alias_index(value_field_type);
Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset),
value_type, T_OBJECT, value_field_idx);
value_type, T_OBJECT, value_field_idx, MemNode::unordered);
// String.value field is known to be @Stable.
if (UseImplicitStableValues) {
load = cast_array_to_stable(load, value_type);
@ -4089,7 +4095,7 @@ void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) {
const TypePtr* offset_field_type = string_type->add_offset(offset_offset);
int offset_field_idx = C->get_alias_index(offset_field_type);
store_to_memory(ctrl, basic_plus_adr(str, offset_offset),
value, T_INT, offset_field_idx);
value, T_INT, offset_field_idx, MemNode::unordered);
}
void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
@ -4099,7 +4105,7 @@ void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
const TypePtr* value_field_type = string_type->add_offset(value_offset);
store_oop_to_object(ctrl, str, basic_plus_adr(str, value_offset), value_field_type,
value, TypeAryPtr::CHARS, T_OBJECT);
value, TypeAryPtr::CHARS, T_OBJECT, MemNode::unordered);
}
void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) {
@ -4109,7 +4115,7 @@ void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) {
const TypePtr* count_field_type = string_type->add_offset(count_offset);
int count_field_idx = C->get_alias_index(count_field_type);
store_to_memory(ctrl, basic_plus_adr(str, count_offset),
value, T_INT, count_field_idx);
value, T_INT, count_field_idx, MemNode::unordered);
}
Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) {

View File

@ -510,36 +510,50 @@ class GraphKit : public Phase {
// Create a LoadNode, reading from the parser's memory state.
// (Note: require_atomic_access is useful only with T_LONG.)
//
// We choose the unordered semantics by default because we have
// adapted the `do_put_xxx' and `do_get_xxx' procedures for the case
// of volatile fields.
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
bool require_atomic_access = false) {
MemNode::MemOrd mo, bool require_atomic_access = false) {
// This version computes alias_index from bottom_type
return make_load(ctl, adr, t, bt, adr->bottom_type()->is_ptr(),
require_atomic_access);
mo, require_atomic_access);
}
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type, bool require_atomic_access = false) {
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type,
MemNode::MemOrd mo, bool require_atomic_access = false) {
// This version computes alias_index from an address type
assert(adr_type != NULL, "use other make_load factory");
return make_load(ctl, adr, t, bt, C->get_alias_index(adr_type),
require_atomic_access);
mo, require_atomic_access);
}
// This is the base version which is given an alias index.
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, bool require_atomic_access = false);
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx,
MemNode::MemOrd mo, bool require_atomic_access = false);
// Create & transform a StoreNode and store the effect into the
// parser's memory state.
//
// We must ensure that stores of object references will be visible
// only after the object's initialization. So the clients of this
// procedure must indicate that the store requires `release'
// semantics, if the stored value is an object reference that might
// point to a new object and may become externally visible.
Node* store_to_memory(Node* ctl, Node* adr, Node* val, BasicType bt,
const TypePtr* adr_type,
MemNode::MemOrd mo,
bool require_atomic_access = false) {
// This version computes alias_index from an address type
assert(adr_type != NULL, "use other store_to_memory factory");
return store_to_memory(ctl, adr, val, bt,
C->get_alias_index(adr_type),
require_atomic_access);
mo, require_atomic_access);
}
// This is the base version which is given alias index
// Return the new StoreXNode
Node* store_to_memory(Node* ctl, Node* adr, Node* val, BasicType bt,
int adr_idx,
MemNode::MemOrd,
bool require_atomic_access = false);
@ -557,40 +571,44 @@ class GraphKit : public Phase {
Node* store_oop(Node* ctl,
Node* obj, // containing obj
Node* adr, // actual adress to store val at
Node* adr, // actual adress to store val at
const TypePtr* adr_type,
Node* val,
const TypeOopPtr* val_type,
BasicType bt,
bool use_precise);
bool use_precise,
MemNode::MemOrd mo);
Node* store_oop_to_object(Node* ctl,
Node* obj, // containing obj
Node* adr, // actual adress to store val at
Node* adr, // actual adress to store val at
const TypePtr* adr_type,
Node* val,
const TypeOopPtr* val_type,
BasicType bt) {
return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, false);
BasicType bt,
MemNode::MemOrd mo) {
return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, false, mo);
}
Node* store_oop_to_array(Node* ctl,
Node* obj, // containing obj
Node* adr, // actual adress to store val at
Node* adr, // actual adress to store val at
const TypePtr* adr_type,
Node* val,
const TypeOopPtr* val_type,
BasicType bt) {
return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true);
BasicType bt,
MemNode::MemOrd mo) {
return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true, mo);
}
// Could be an array or object we don't know at compile time (unsafe ref.)
Node* store_oop_to_unknown(Node* ctl,
Node* obj, // containing obj
Node* adr, // actual adress to store val at
Node* adr, // actual adress to store val at
const TypePtr* adr_type,
Node* val,
BasicType bt);
BasicType bt,
MemNode::MemOrd mo);
// For the few case where the barriers need special help
void pre_barrier(bool do_load, Node* ctl,

View File

@ -359,25 +359,25 @@ Node* IdealKit::load(Node* ctl,
Node* mem = memory(adr_idx);
Node* ld;
if (require_atomic_access && bt == T_LONG) {
ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t);
ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, MemNode::unordered);
} else {
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt);
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, MemNode::unordered);
}
return transform(ld);
}
Node* IdealKit::store(Node* ctl, Node* adr, Node *val, BasicType bt,
int adr_idx,
bool require_atomic_access) {
assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" );
int adr_idx,
MemNode::MemOrd mo, bool require_atomic_access) {
assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory");
const TypePtr* adr_type = NULL;
debug_only(adr_type = C->get_adr_type(adr_idx));
Node *mem = memory(adr_idx);
Node* st;
if (require_atomic_access && bt == T_LONG) {
st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val);
st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo);
} else {
st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt);
st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo);
}
st = transform(st);
set_memory(st, adr_idx);

View File

@ -226,6 +226,7 @@ class IdealKit: public StackObj {
Node* val,
BasicType bt,
int adr_idx,
MemNode::MemOrd mo,
bool require_atomic_access = false);
// Store a card mark ordered after store_oop

View File

@ -1057,7 +1057,7 @@ Node* LibraryCallKit::generate_current_thread(Node* &tls_output) {
const Type* thread_type = TypeOopPtr::make_from_klass(thread_klass)->cast_to_ptr_type(TypePtr::NotNull);
Node* thread = _gvn.transform(new (C) ThreadLocalNode());
Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::threadObj_offset()));
Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT);
Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT, MemNode::unordered);
tls_output = thread;
return threadObj;
}
@ -2640,7 +2640,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder);
if (!is_store) {
Node* p = make_load(control(), adr, value_type, type, adr_type, is_volatile);
Node* p = make_load(control(), adr, value_type, type, adr_type, MemNode::unordered, is_volatile);
// load value
switch (type) {
case T_BOOLEAN:
@ -2684,13 +2684,14 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
break;
}
MemNode::MemOrd mo = is_volatile ? MemNode::release : MemNode::unordered;
if (type != T_OBJECT ) {
(void) store_to_memory(control(), adr, val, type, adr_type, is_volatile);
(void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile);
} else {
// Possibly an oop being stored to Java heap or native memory
if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) {
// oop to Java heap.
(void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type);
(void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo);
} else {
// We can't tell at compile time if we are storing in the Java heap or outside
// of it. So we need to emit code to conditionally do the proper type of
@ -2702,11 +2703,11 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
__ if_then(heap_base_oop, BoolTest::ne, null(), PROB_UNLIKELY(0.999)); {
// Sync IdealKit and graphKit.
sync_kit(ideal);
Node* st = store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type);
Node* st = store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo);
// Update IdealKit memory.
__ sync_kit(this);
} __ else_(); {
__ store(__ ctrl(), adr, val, type, alias_type->index(), is_volatile);
__ store(__ ctrl(), adr, val, type, alias_type->index(), mo, is_volatile);
} __ end_if();
// Final sync IdealKit and GraphKit.
final_sync(ideal);
@ -2979,12 +2980,12 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
Node *newval_enc = _gvn.transform(new (C) EncodePNode(newval, newval->bottom_type()->make_narrowoop()));
if (kind == LS_xchg) {
load_store = _gvn.transform(new (C) GetAndSetNNode(control(), mem, adr,
newval_enc, adr_type, value_type->make_narrowoop()));
newval_enc, adr_type, value_type->make_narrowoop()));
} else {
assert(kind == LS_cmpxchg, "wrong LoadStore operation");
Node *oldval_enc = _gvn.transform(new (C) EncodePNode(oldval, oldval->bottom_type()->make_narrowoop()));
load_store = _gvn.transform(new (C) CompareAndSwapNNode(control(), mem, adr,
newval_enc, oldval_enc));
newval_enc, oldval_enc));
}
} else
#endif
@ -3090,9 +3091,9 @@ bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) {
const bool require_atomic_access = true;
Node* store;
if (type == T_OBJECT) // reference stores need a store barrier.
store = store_oop_to_unknown(control(), base, adr, adr_type, val, type);
store = store_oop_to_unknown(control(), base, adr, adr_type, val, type, MemNode::release);
else {
store = store_to_memory(control(), adr, val, type, adr_type, require_atomic_access);
store = store_to_memory(control(), adr, val, type, adr_type, MemNode::release, require_atomic_access);
}
insert_mem_bar(Op_MemBarCPUOrder);
return true;
@ -3152,7 +3153,7 @@ bool LibraryCallKit::inline_unsafe_allocate() {
Node* insp = basic_plus_adr(kls, in_bytes(InstanceKlass::init_state_offset()));
// Use T_BOOLEAN for InstanceKlass::_init_state so the compiler
// can generate code to load it as unsigned byte.
Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN);
Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN, MemNode::unordered);
Node* bits = intcon(InstanceKlass::fully_initialized);
test = _gvn.transform(new (C) SubINode(inst, bits));
// The 'test' is non-zero if we need to take a slow path.
@ -3176,14 +3177,14 @@ bool LibraryCallKit::inline_native_classID() {
kls = null_check(kls, T_OBJECT);
ByteSize offset = TRACE_ID_OFFSET;
Node* insp = basic_plus_adr(kls, in_bytes(offset));
Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG);
Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG, MemNode::unordered);
Node* bits = longcon(~0x03l); // ignore bit 0 & 1
Node* andl = _gvn.transform(new (C) AndLNode(tvalue, bits));
Node* clsused = longcon(0x01l); // set the class bit
Node* orl = _gvn.transform(new (C) OrLNode(tvalue, clsused));
const TypePtr *adr_type = _gvn.type(insp)->isa_ptr();
store_to_memory(control(), insp, orl, T_LONG, adr_type);
store_to_memory(control(), insp, orl, T_LONG, adr_type, MemNode::unordered);
set_result(andl);
return true;
}
@ -3192,15 +3193,15 @@ bool LibraryCallKit::inline_native_threadID() {
Node* tls_ptr = NULL;
Node* cur_thr = generate_current_thread(tls_ptr);
Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset()));
Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS);
Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered);
p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::thread_id_offset()));
Node* threadid = NULL;
size_t thread_id_size = OSThread::thread_id_size();
if (thread_id_size == (size_t) BytesPerLong) {
threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG));
threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG, MemNode::unordered));
} else if (thread_id_size == (size_t) BytesPerInt) {
threadid = make_load(control(), p, TypeInt::INT, T_INT);
threadid = make_load(control(), p, TypeInt::INT, T_INT, MemNode::unordered);
} else {
ShouldNotReachHere();
}
@ -3275,11 +3276,11 @@ bool LibraryCallKit::inline_native_isInterrupted() {
// (b) Interrupt bit on TLS must be false.
Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset()));
Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS);
Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered);
p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset()));
// Set the control input on the field _interrupted read to prevent it floating up.
Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT);
Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT, MemNode::unordered);
Node* cmp_bit = _gvn.transform(new (C) CmpINode(int_bit, intcon(0)));
Node* bol_bit = _gvn.transform(new (C) BoolNode(cmp_bit, BoolTest::ne));
@ -3347,7 +3348,7 @@ bool LibraryCallKit::inline_native_isInterrupted() {
// Given a klass oop, load its java mirror (a java.lang.Class oop).
Node* LibraryCallKit::load_mirror_from_klass(Node* klass) {
Node* p = basic_plus_adr(klass, in_bytes(Klass::java_mirror_offset()));
return make_load(NULL, p, TypeInstPtr::MIRROR, T_OBJECT);
return make_load(NULL, p, TypeInstPtr::MIRROR, T_OBJECT, MemNode::unordered);
}
//-----------------------load_klass_from_mirror_common-------------------------
@ -3384,7 +3385,7 @@ Node* LibraryCallKit::generate_access_flags_guard(Node* kls, int modifier_mask,
// Branch around if the given klass has the given modifier bit set.
// Like generate_guard, adds a new path onto the region.
Node* modp = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset()));
Node* mods = make_load(NULL, modp, TypeInt::INT, T_INT);
Node* mods = make_load(NULL, modp, TypeInt::INT, T_INT, MemNode::unordered);
Node* mask = intcon(modifier_mask);
Node* bits = intcon(modifier_bits);
Node* mbit = _gvn.transform(new (C) AndINode(mods, mask));
@ -3501,7 +3502,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) {
case vmIntrinsics::_getModifiers:
p = basic_plus_adr(kls, in_bytes(Klass::modifier_flags_offset()));
query_value = make_load(NULL, p, TypeInt::INT, T_INT);
query_value = make_load(NULL, p, TypeInt::INT, T_INT, MemNode::unordered);
break;
case vmIntrinsics::_isInterface:
@ -3559,7 +3560,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) {
// Be sure to pin the oop load to the guard edge just created:
Node* is_array_ctrl = region->in(region->req()-1);
Node* cma = basic_plus_adr(kls, in_bytes(ArrayKlass::component_mirror_offset()));
Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT);
Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT, MemNode::unordered);
phi->add_req(cmo);
}
query_value = null(); // non-array case is null
@ -3567,7 +3568,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) {
case vmIntrinsics::_getClassAccessFlags:
p = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset()));
query_value = make_load(NULL, p, TypeInt::INT, T_INT);
query_value = make_load(NULL, p, TypeInt::INT, T_INT, MemNode::unordered);
break;
default:
@ -3933,7 +3934,7 @@ Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass,
vtable_index*vtableEntry::size()) * wordSize +
vtableEntry::method_offset_in_bytes();
Node* entry_addr = basic_plus_adr(obj_klass, entry_offset);
Node* target_call = make_load(NULL, entry_addr, TypePtr::NOTNULL, T_ADDRESS);
Node* target_call = make_load(NULL, entry_addr, TypePtr::NOTNULL, T_ADDRESS, MemNode::unordered);
// Compare the target method with the expected method (e.g., Object.hashCode).
const TypePtr* native_call_addr = TypeMetadataPtr::make(method);
@ -4059,7 +4060,7 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
// Get the header out of the object, use LoadMarkNode when available
Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes());
Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type());
Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type(), MemNode::unordered);
// Test the header to see if it is unlocked.
Node *lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place);
@ -5480,7 +5481,7 @@ LibraryCallKit::generate_clear_array(const TypePtr* adr_type,
// Store a zero to the immediately preceding jint:
Node* x1 = _gvn.transform(new(C) AddXNode(start, MakeConX(-bump_bit)));
Node* p1 = basic_plus_adr(dest, x1);
mem = StoreNode::make(_gvn, control(), mem, p1, adr_type, intcon(0), T_INT);
mem = StoreNode::make(_gvn, control(), mem, p1, adr_type, intcon(0), T_INT, MemNode::unordered);
mem = _gvn.transform(mem);
}
}
@ -5530,8 +5531,8 @@ LibraryCallKit::generate_block_arraycopy(const TypePtr* adr_type,
((src_off ^ dest_off) & (BytesPerLong-1)) == 0) {
Node* sptr = basic_plus_adr(src, src_off);
Node* dptr = basic_plus_adr(dest, dest_off);
Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, adr_type);
store_to_memory(control(), dptr, sval, T_INT, adr_type);
Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
store_to_memory(control(), dptr, sval, T_INT, adr_type, MemNode::unordered);
src_off += BytesPerInt;
dest_off += BytesPerInt;
} else {
@ -5596,7 +5597,7 @@ LibraryCallKit::generate_checkcast_arraycopy(const TypePtr* adr_type,
// super_check_offset, for the desired klass.
int sco_offset = in_bytes(Klass::super_check_offset_offset());
Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset);
Node* n3 = new(C) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr());
Node* n3 = new(C) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr(), TypeInt::INT, MemNode::unordered);
Node* check_offset = ConvI2X(_gvn.transform(n3));
Node* check_value = dest_elem_klass;
@ -5737,7 +5738,7 @@ bool LibraryCallKit::inline_updateCRC32() {
Node* base = makecon(TypeRawPtr::make(StubRoutines::crc_table_addr()));
Node* offset = _gvn.transform(new (C) LShiftINode(result, intcon(0x2)));
Node* adr = basic_plus_adr(top(), base, ConvI2X(offset));
result = make_load(control(), adr, TypeInt::INT, T_INT);
result = make_load(control(), adr, TypeInt::INT, T_INT, MemNode::unordered);
crc = _gvn.transform(new (C) URShiftINode(crc, intcon(8)));
result = _gvn.transform(new (C) XorINode(crc, result));
@ -5838,7 +5839,7 @@ bool LibraryCallKit::inline_reference_get() {
const TypeOopPtr* object_type = TypeOopPtr::make_from_klass(klass);
Node* no_ctrl = NULL;
Node* result = make_load(no_ctrl, adr, object_type, T_OBJECT);
Node* result = make_load(no_ctrl, adr, object_type, T_OBJECT, MemNode::unordered);
// Use the pre-barrier to record the value in the referent field
pre_barrier(false /* do_load */,
@ -5885,7 +5886,7 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * field
const Type *type = TypeOopPtr::make_from_klass(field_klass->as_klass());
// Build the load.
Node* loadedField = make_load(NULL, adr, type, bt, adr_type, is_vol);
Node* loadedField = make_load(NULL, adr, type, bt, adr_type, MemNode::unordered, is_vol);
return loadedField;
}

View File

@ -1084,7 +1084,7 @@ void PhaseMacroExpand::set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_ad
Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) {
Node* adr = basic_plus_adr(base, offset);
const TypePtr* adr_type = adr->bottom_type()->is_ptr();
Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt);
Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt, MemNode::unordered);
transform_later(value);
return value;
}
@ -1092,7 +1092,7 @@ Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset,
Node* PhaseMacroExpand::make_store(Node* ctl, Node* mem, Node* base, int offset, Node* value, BasicType bt) {
Node* adr = basic_plus_adr(base, offset);
mem = StoreNode::make(_igvn, ctl, mem, adr, NULL, value, bt);
mem = StoreNode::make(_igvn, ctl, mem, adr, NULL, value, bt, MemNode::unordered);
transform_later(mem);
return mem;
}
@ -1272,8 +1272,8 @@ void PhaseMacroExpand::expand_allocate_common(
// Load(-locked) the heap top.
// See note above concerning the control input when using a TLAB
Node *old_eden_top = UseTLAB
? new (C) LoadPNode (ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM)
: new (C) LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr);
? new (C) LoadPNode (ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered)
: new (C) LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr, MemNode::acquire);
transform_later(old_eden_top);
// Add to heap top to get a new heap top
@ -1320,7 +1320,7 @@ void PhaseMacroExpand::expand_allocate_common(
if (UseTLAB) {
Node* store_eden_top =
new (C) StorePNode(needgc_false, contended_phi_rawmem, eden_top_adr,
TypeRawPtr::BOTTOM, new_eden_top);
TypeRawPtr::BOTTOM, new_eden_top, MemNode::unordered);
transform_later(store_eden_top);
fast_oop_ctrl = needgc_false; // No contention, so this is the fast path
fast_oop_rawmem = store_eden_top;
@ -1700,9 +1700,10 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false,
_igvn.MakeConX(in_bytes(JavaThread::tlab_pf_top_offset())) );
transform_later(eden_pf_adr);
Node *old_pf_wm = new (C) LoadPNode( needgc_false,
Node *old_pf_wm = new (C) LoadPNode(needgc_false,
contended_phi_rawmem, eden_pf_adr,
TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM );
TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM,
MemNode::unordered);
transform_later(old_pf_wm);
// check against new_eden_top
@ -1726,9 +1727,10 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false,
transform_later(new_pf_wmt );
new_pf_wmt->set_req(0, need_pf_true);
Node *store_new_wmt = new (C) StorePNode( need_pf_true,
Node *store_new_wmt = new (C) StorePNode(need_pf_true,
contended_phi_rawmem, eden_pf_adr,
TypeRawPtr::BOTTOM, new_pf_wmt );
TypeRawPtr::BOTTOM, new_pf_wmt,
MemNode::unordered);
transform_later(store_new_wmt);
// adding prefetches

View File

@ -825,16 +825,15 @@ void Matcher::init_spill_mask( Node *ret ) {
// Compute generic short-offset Loads
#ifdef _LP64
MachNode *spillCP = match_tree(new (C) LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM));
MachNode *spillCP = match_tree(new (C) LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
#endif
MachNode *spillI = match_tree(new (C) LoadINode(NULL,mem,fp,atp));
MachNode *spillL = match_tree(new (C) LoadLNode(NULL,mem,fp,atp));
MachNode *spillF = match_tree(new (C) LoadFNode(NULL,mem,fp,atp));
MachNode *spillD = match_tree(new (C) LoadDNode(NULL,mem,fp,atp));
MachNode *spillP = match_tree(new (C) LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM));
MachNode *spillI = match_tree(new (C) LoadINode(NULL,mem,fp,atp,TypeInt::INT,MemNode::unordered));
MachNode *spillL = match_tree(new (C) LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered,false));
MachNode *spillF = match_tree(new (C) LoadFNode(NULL,mem,fp,atp,Type::FLOAT,MemNode::unordered));
MachNode *spillD = match_tree(new (C) LoadDNode(NULL,mem,fp,atp,Type::DOUBLE,MemNode::unordered));
MachNode *spillP = match_tree(new (C) LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
assert(spillI != NULL && spillL != NULL && spillF != NULL &&
spillD != NULL && spillP != NULL, "");
// Get the ADLC notion of the right regmask, for each basic type.
#ifdef _LP64
idealreg2regmask[Op_RegN] = &spillCP->out_RegMask();

View File

@ -907,7 +907,7 @@ bool LoadNode::is_immutable_value(Node* adr) {
//----------------------------LoadNode::make-----------------------------------
// Polymorphic factory method:
Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt ) {
Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo) {
Compile* C = gvn.C;
// sanity check the alias category against the created node type
@ -923,34 +923,34 @@ Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const Type
rt->isa_oopptr() || is_immutable_value(adr),
"raw memory operations should have control edge");
switch (bt) {
case T_BOOLEAN: return new (C) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int() );
case T_BYTE: return new (C) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() );
case T_INT: return new (C) LoadINode (ctl, mem, adr, adr_type, rt->is_int() );
case T_CHAR: return new (C) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int() );
case T_SHORT: return new (C) LoadSNode (ctl, mem, adr, adr_type, rt->is_int() );
case T_LONG: return new (C) LoadLNode (ctl, mem, adr, adr_type, rt->is_long() );
case T_FLOAT: return new (C) LoadFNode (ctl, mem, adr, adr_type, rt );
case T_DOUBLE: return new (C) LoadDNode (ctl, mem, adr, adr_type, rt );
case T_ADDRESS: return new (C) LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr() );
case T_BOOLEAN: return new (C) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo);
case T_BYTE: return new (C) LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo);
case T_INT: return new (C) LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo);
case T_CHAR: return new (C) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo);
case T_SHORT: return new (C) LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo);
case T_LONG: return new (C) LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo);
case T_FLOAT: return new (C) LoadFNode (ctl, mem, adr, adr_type, rt, mo);
case T_DOUBLE: return new (C) LoadDNode (ctl, mem, adr, adr_type, rt, mo);
case T_ADDRESS: return new (C) LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo);
case T_OBJECT:
#ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
Node* load = gvn.transform(new (C) LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop()));
Node* load = gvn.transform(new (C) LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo));
return new (C) DecodeNNode(load, load->bottom_type()->make_ptr());
} else
#endif
{
assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop");
return new (C) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr());
return new (C) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo);
}
}
ShouldNotReachHere();
return (LoadNode*)NULL;
}
LoadLNode* LoadLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt) {
LoadLNode* LoadLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) {
bool require_atomic = true;
return new (C) LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), require_atomic);
return new (C) LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, require_atomic);
}
@ -2032,12 +2032,12 @@ Node *LoadKlassNode::make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* a
#ifdef _LP64
if (adr_type->is_ptr_to_narrowklass()) {
assert(UseCompressedClassPointers, "no compressed klasses");
Node* load_klass = gvn.transform(new (C) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowklass()));
Node* load_klass = gvn.transform(new (C) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowklass(), MemNode::unordered));
return new (C) DecodeNKlassNode(load_klass, load_klass->bottom_type()->make_ptr());
}
#endif
assert(!adr_type->is_ptr_to_narrowklass() && !adr_type->is_ptr_to_narrowoop(), "should have got back a narrow oop");
return new (C) LoadKlassNode(ctl, mem, adr, at, tk);
return new (C) LoadKlassNode(ctl, mem, adr, at, tk, MemNode::unordered);
}
//------------------------------Value------------------------------------------
@ -2347,45 +2347,46 @@ Node* LoadRangeNode::Identity( PhaseTransform *phase ) {
//=============================================================================
//---------------------------StoreNode::make-----------------------------------
// Polymorphic factory method:
StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt ) {
StoreNode* StoreNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt, MemOrd mo) {
assert((mo == unordered || mo == release), "unexpected");
Compile* C = gvn.C;
assert( C->get_alias_index(adr_type) != Compile::AliasIdxRaw ||
ctl != NULL, "raw memory operations should have control edge");
assert(C->get_alias_index(adr_type) != Compile::AliasIdxRaw ||
ctl != NULL, "raw memory operations should have control edge");
switch (bt) {
case T_BOOLEAN:
case T_BYTE: return new (C) StoreBNode(ctl, mem, adr, adr_type, val);
case T_INT: return new (C) StoreINode(ctl, mem, adr, adr_type, val);
case T_BYTE: return new (C) StoreBNode(ctl, mem, adr, adr_type, val, mo);
case T_INT: return new (C) StoreINode(ctl, mem, adr, adr_type, val, mo);
case T_CHAR:
case T_SHORT: return new (C) StoreCNode(ctl, mem, adr, adr_type, val);
case T_LONG: return new (C) StoreLNode(ctl, mem, adr, adr_type, val);
case T_FLOAT: return new (C) StoreFNode(ctl, mem, adr, adr_type, val);
case T_DOUBLE: return new (C) StoreDNode(ctl, mem, adr, adr_type, val);
case T_SHORT: return new (C) StoreCNode(ctl, mem, adr, adr_type, val, mo);
case T_LONG: return new (C) StoreLNode(ctl, mem, adr, adr_type, val, mo);
case T_FLOAT: return new (C) StoreFNode(ctl, mem, adr, adr_type, val, mo);
case T_DOUBLE: return new (C) StoreDNode(ctl, mem, adr, adr_type, val, mo);
case T_METADATA:
case T_ADDRESS:
case T_OBJECT:
#ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
val = gvn.transform(new (C) EncodePNode(val, val->bottom_type()->make_narrowoop()));
return new (C) StoreNNode(ctl, mem, adr, adr_type, val);
return new (C) StoreNNode(ctl, mem, adr, adr_type, val, mo);
} else if (adr->bottom_type()->is_ptr_to_narrowklass() ||
(UseCompressedClassPointers && val->bottom_type()->isa_klassptr() &&
adr->bottom_type()->isa_rawptr())) {
val = gvn.transform(new (C) EncodePKlassNode(val, val->bottom_type()->make_narrowklass()));
return new (C) StoreNKlassNode(ctl, mem, adr, adr_type, val);
return new (C) StoreNKlassNode(ctl, mem, adr, adr_type, val, mo);
}
#endif
{
return new (C) StorePNode(ctl, mem, adr, adr_type, val);
return new (C) StorePNode(ctl, mem, adr, adr_type, val, mo);
}
}
ShouldNotReachHere();
return (StoreNode*)NULL;
}
StoreLNode* StoreLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val) {
StoreLNode* StoreLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) {
bool require_atomic = true;
return new (C) StoreLNode(ctl, mem, adr, adr_type, val, require_atomic);
return new (C) StoreLNode(ctl, mem, adr, adr_type, val, mo, require_atomic);
}
@ -2778,12 +2779,12 @@ Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape){
Node *zero = phase->makecon(TypeLong::ZERO);
Node *off = phase->MakeConX(BytesPerLong);
mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero);
mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero,MemNode::unordered,false);
count--;
while( count-- ) {
mem = phase->transform(mem);
adr = phase->transform(new (phase->C) AddPNode(base,adr,off));
mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero);
mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero,MemNode::unordered,false);
}
return mem;
}
@ -2827,7 +2828,7 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest,
Node* adr = new (C) AddPNode(dest, dest, phase->MakeConX(offset));
adr = phase->transform(adr);
const TypePtr* atp = TypeRawPtr::BOTTOM;
mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT);
mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT, MemNode::unordered);
mem = phase->transform(mem);
offset += BytesPerInt;
}
@ -2888,7 +2889,7 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest,
Node* adr = new (C) AddPNode(dest, dest, phase->MakeConX(done_offset));
adr = phase->transform(adr);
const TypePtr* atp = TypeRawPtr::BOTTOM;
mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT);
mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT, MemNode::unordered);
mem = phase->transform(mem);
done_offset += BytesPerInt;
}
@ -3762,14 +3763,14 @@ InitializeNode::coalesce_subword_stores(intptr_t header_size,
++new_long;
off[nst] = offset;
st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp,
phase->longcon(con), T_LONG);
phase->longcon(con), T_LONG, MemNode::unordered);
} else {
// Omit either if it is a zero.
if (con0 != 0) {
++new_int;
off[nst] = offset;
st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp,
phase->intcon(con0), T_INT);
phase->intcon(con0), T_INT, MemNode::unordered);
}
if (con1 != 0) {
++new_int;
@ -3777,7 +3778,7 @@ InitializeNode::coalesce_subword_stores(intptr_t header_size,
adr = make_raw_address(offset, phase);
off[nst] = offset;
st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp,
phase->intcon(con1), T_INT);
phase->intcon(con1), T_INT, MemNode::unordered);
}
}

View File

@ -51,6 +51,10 @@ public:
ValueIn, // Value to store
OopStore // Preceeding oop store, only in StoreCM
};
typedef enum { unordered = 0,
acquire, // Load has to acquire or be succeeded by MemBarAcquire.
release // Store has to release or be preceded by MemBarRelease.
} MemOrd;
protected:
MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at )
: Node(c0,c1,c2 ) {
@ -134,20 +138,32 @@ public:
//------------------------------LoadNode---------------------------------------
// Load value; requires Memory and Address
class LoadNode : public MemNode {
private:
// On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish
// loads that can be reordered, and such requiring acquire semantics to
// adhere to the Java specification. The required behaviour is stored in
// this field.
const MemOrd _mo;
protected:
virtual uint cmp( const Node &n ) const;
virtual uint cmp(const Node &n) const;
virtual uint size_of() const; // Size is bigger
const Type* const _type; // What kind of value is loaded?
public:
LoadNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt )
: MemNode(c,mem,adr,at), _type(rt) {
LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo)
: MemNode(c,mem,adr,at), _type(rt), _mo(mo) {
init_class_id(Class_Load);
}
inline bool is_unordered() const { return !is_acquire(); }
inline bool is_acquire() const {
assert(_mo == unordered || _mo == acquire, "unexpected");
return _mo == acquire;
}
// Polymorphic factory method:
static Node* make( PhaseGVN& gvn, Node *c, Node *mem, Node *adr,
const TypePtr* at, const Type *rt, BasicType bt );
static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr,
const TypePtr* at, const Type *rt, BasicType bt, MemOrd mo);
virtual uint hash() const; // Check the type
@ -210,8 +226,8 @@ protected:
// Load a byte (8bits signed) from memory
class LoadBNode : public LoadNode {
public:
LoadBNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::BYTE )
: LoadNode(c,mem,adr,at,ti) {}
LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
: LoadNode(c, mem, adr, at, ti, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
@ -224,8 +240,8 @@ public:
// Load a unsigned byte (8bits unsigned) from memory
class LoadUBNode : public LoadNode {
public:
LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti = TypeInt::UBYTE )
: LoadNode(c, mem, adr, at, ti) {}
LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo)
: LoadNode(c, mem, adr, at, ti, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node* Ideal(PhaseGVN *phase, bool can_reshape);
@ -238,8 +254,8 @@ public:
// Load an unsigned short/char (16bits unsigned) from memory
class LoadUSNode : public LoadNode {
public:
LoadUSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::CHAR )
: LoadNode(c,mem,adr,at,ti) {}
LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
: LoadNode(c, mem, adr, at, ti, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
@ -252,8 +268,8 @@ public:
// Load a short (16bits signed) from memory
class LoadSNode : public LoadNode {
public:
LoadSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::SHORT )
: LoadNode(c,mem,adr,at,ti) {}
LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
: LoadNode(c, mem, adr, at, ti, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
@ -266,8 +282,8 @@ public:
// Load an integer from memory
class LoadINode : public LoadNode {
public:
LoadINode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::INT )
: LoadNode(c,mem,adr,at,ti) {}
LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
: LoadNode(c, mem, adr, at, ti, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual int store_Opcode() const { return Op_StoreI; }
@ -278,8 +294,8 @@ public:
// Load an array length from the array
class LoadRangeNode : public LoadINode {
public:
LoadRangeNode( Node *c, Node *mem, Node *adr, const TypeInt *ti = TypeInt::POS )
: LoadINode(c,mem,adr,TypeAryPtr::RANGE,ti) {}
LoadRangeNode(Node *c, Node *mem, Node *adr, const TypeInt *ti = TypeInt::POS)
: LoadINode(c, mem, adr, TypeAryPtr::RANGE, ti, MemNode::unordered) {}
virtual int Opcode() const;
virtual const Type *Value( PhaseTransform *phase ) const;
virtual Node *Identity( PhaseTransform *phase );
@ -298,18 +314,16 @@ class LoadLNode : public LoadNode {
const bool _require_atomic_access; // is piecewise load forbidden?
public:
LoadLNode( Node *c, Node *mem, Node *adr, const TypePtr* at,
const TypeLong *tl = TypeLong::LONG,
bool require_atomic_access = false )
: LoadNode(c,mem,adr,at,tl)
, _require_atomic_access(require_atomic_access)
{}
LoadLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeLong *tl,
MemOrd mo, bool require_atomic_access = false)
: LoadNode(c, mem, adr, at, tl, mo), _require_atomic_access(require_atomic_access) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegL; }
virtual int store_Opcode() const { return Op_StoreL; }
virtual BasicType memory_type() const { return T_LONG; }
bool require_atomic_access() { return _require_atomic_access; }
static LoadLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt);
static LoadLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
const Type* rt, MemOrd mo);
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const {
LoadNode::dump_spec(st);
@ -322,8 +336,8 @@ public:
// Load a long from unaligned memory
class LoadL_unalignedNode : public LoadLNode {
public:
LoadL_unalignedNode( Node *c, Node *mem, Node *adr, const TypePtr* at )
: LoadLNode(c,mem,adr,at) {}
LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo)
: LoadLNode(c, mem, adr, at, TypeLong::LONG, mo) {}
virtual int Opcode() const;
};
@ -331,8 +345,8 @@ public:
// Load a float (64 bits) from memory
class LoadFNode : public LoadNode {
public:
LoadFNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t = Type::FLOAT )
: LoadNode(c,mem,adr,at,t) {}
LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo)
: LoadNode(c, mem, adr, at, t, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegF; }
virtual int store_Opcode() const { return Op_StoreF; }
@ -343,8 +357,8 @@ public:
// Load a double (64 bits) from memory
class LoadDNode : public LoadNode {
public:
LoadDNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t = Type::DOUBLE )
: LoadNode(c,mem,adr,at,t) {}
LoadDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo)
: LoadNode(c, mem, adr, at, t, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegD; }
virtual int store_Opcode() const { return Op_StoreD; }
@ -355,8 +369,8 @@ public:
// Load a double from unaligned memory
class LoadD_unalignedNode : public LoadDNode {
public:
LoadD_unalignedNode( Node *c, Node *mem, Node *adr, const TypePtr* at )
: LoadDNode(c,mem,adr,at) {}
LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo)
: LoadDNode(c, mem, adr, at, Type::DOUBLE, mo) {}
virtual int Opcode() const;
};
@ -364,8 +378,8 @@ public:
// Load a pointer from memory (either object or array)
class LoadPNode : public LoadNode {
public:
LoadPNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t )
: LoadNode(c,mem,adr,at,t) {}
LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo)
: LoadNode(c, mem, adr, at, t, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegP; }
virtual int store_Opcode() const { return Op_StoreP; }
@ -387,8 +401,8 @@ public:
// Load a narrow oop from memory (either object or array)
class LoadNNode : public LoadNode {
public:
LoadNNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t )
: LoadNode(c,mem,adr,at,t) {}
LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo)
: LoadNode(c, mem, adr, at, t, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegN; }
virtual int store_Opcode() const { return Op_StoreN; }
@ -409,8 +423,8 @@ public:
// Load a Klass from an object
class LoadKlassNode : public LoadPNode {
public:
LoadKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeKlassPtr *tk )
: LoadPNode(c,mem,adr,at,tk) {}
LoadKlassNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeKlassPtr *tk, MemOrd mo)
: LoadPNode(c, mem, adr, at, tk, mo) {}
virtual int Opcode() const;
virtual const Type *Value( PhaseTransform *phase ) const;
virtual Node *Identity( PhaseTransform *phase );
@ -425,8 +439,8 @@ public:
// Load a narrow Klass from an object.
class LoadNKlassNode : public LoadNNode {
public:
LoadNKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowKlass *tk )
: LoadNNode(c,mem,adr,at,tk) {}
LoadNKlassNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowKlass *tk, MemOrd mo)
: LoadNNode(c, mem, adr, at, tk, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegN; }
virtual int store_Opcode() const { return Op_StoreNKlass; }
@ -441,6 +455,14 @@ public:
//------------------------------StoreNode--------------------------------------
// Store value; requires Store, Address and Value
class StoreNode : public MemNode {
private:
// On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish
// stores that can be reordered, and such requiring release semantics to
// adhere to the Java specification. The required behaviour is stored in
// this field.
const MemOrd _mo;
// Needed for proper cloning.
virtual uint size_of() const { return sizeof(*this); }
protected:
virtual uint cmp( const Node &n ) const;
virtual bool depends_only_on_test() const { return false; }
@ -449,18 +471,44 @@ protected:
Node *Ideal_sign_extended_input(PhaseGVN *phase, int num_bits);
public:
StoreNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val )
: MemNode(c,mem,adr,at,val) {
// We must ensure that stores of object references will be visible
// only after the object's initialization. So the callers of this
// procedure must indicate that the store requires `release'
// semantics, if the stored value is an object reference that might
// point to a new object and may become externally visible.
StoreNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo)
: MemNode(c, mem, adr, at, val), _mo(mo) {
init_class_id(Class_Store);
}
StoreNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store )
: MemNode(c,mem,adr,at,val,oop_store) {
StoreNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store, MemOrd mo)
: MemNode(c, mem, adr, at, val, oop_store), _mo(mo) {
init_class_id(Class_Store);
}
// Polymorphic factory method:
static StoreNode* make( PhaseGVN& gvn, Node *c, Node *mem, Node *adr,
const TypePtr* at, Node *val, BasicType bt );
inline bool is_unordered() const { return !is_release(); }
inline bool is_release() const {
assert((_mo == unordered || _mo == release), "unexpected");
return _mo == release;
}
// Conservatively release stores of object references in order to
// ensure visibility of object initialization.
static inline MemOrd release_if_reference(const BasicType t) {
const MemOrd mo = (t == T_ARRAY ||
t == T_ADDRESS || // Might be the address of an object reference (`boxing').
t == T_OBJECT) ? release : unordered;
return mo;
}
// Polymorphic factory method
//
// We must ensure that stores of object references will be visible
// only after the object's initialization. So the callers of this
// procedure must indicate that the store requires `release'
// semantics, if the stored value is an object reference that might
// point to a new object and may become externally visible.
static StoreNode* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr,
const TypePtr* at, Node *val, BasicType bt, MemOrd mo);
virtual uint hash() const; // Check the type
@ -491,7 +539,8 @@ public:
// Store byte to memory
class StoreBNode : public StoreNode {
public:
StoreBNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {}
StoreBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo)
: StoreNode(c, mem, adr, at, val, mo) {}
virtual int Opcode() const;
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual BasicType memory_type() const { return T_BYTE; }
@ -501,7 +550,8 @@ public:
// Store char/short to memory
class StoreCNode : public StoreNode {
public:
StoreCNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {}
StoreCNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo)
: StoreNode(c, mem, adr, at, val, mo) {}
virtual int Opcode() const;
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual BasicType memory_type() const { return T_CHAR; }
@ -511,7 +561,8 @@ public:
// Store int to memory
class StoreINode : public StoreNode {
public:
StoreINode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {}
StoreINode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo)
: StoreNode(c, mem, adr, at, val, mo) {}
virtual int Opcode() const;
virtual BasicType memory_type() const { return T_INT; }
};
@ -528,15 +579,12 @@ class StoreLNode : public StoreNode {
const bool _require_atomic_access; // is piecewise store forbidden?
public:
StoreLNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val,
bool require_atomic_access = false )
: StoreNode(c,mem,adr,at,val)
, _require_atomic_access(require_atomic_access)
{}
StoreLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo, bool require_atomic_access = false)
: StoreNode(c, mem, adr, at, val, mo), _require_atomic_access(require_atomic_access) {}
virtual int Opcode() const;
virtual BasicType memory_type() const { return T_LONG; }
bool require_atomic_access() { return _require_atomic_access; }
static StoreLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val);
static StoreLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo);
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const {
StoreNode::dump_spec(st);
@ -549,7 +597,8 @@ public:
// Store float to memory
class StoreFNode : public StoreNode {
public:
StoreFNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {}
StoreFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo)
: StoreNode(c, mem, adr, at, val, mo) {}
virtual int Opcode() const;
virtual BasicType memory_type() const { return T_FLOAT; }
};
@ -558,7 +607,8 @@ public:
// Store double to memory
class StoreDNode : public StoreNode {
public:
StoreDNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {}
StoreDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo)
: StoreNode(c, mem, adr, at, val, mo) {}
virtual int Opcode() const;
virtual BasicType memory_type() const { return T_DOUBLE; }
};
@ -567,7 +617,8 @@ public:
// Store pointer to memory
class StorePNode : public StoreNode {
public:
StorePNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {}
StorePNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo)
: StoreNode(c, mem, adr, at, val, mo) {}
virtual int Opcode() const;
virtual BasicType memory_type() const { return T_ADDRESS; }
};
@ -576,7 +627,8 @@ public:
// Store narrow oop to memory
class StoreNNode : public StoreNode {
public:
StoreNNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {}
StoreNNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo)
: StoreNode(c, mem, adr, at, val, mo) {}
virtual int Opcode() const;
virtual BasicType memory_type() const { return T_NARROWOOP; }
};
@ -585,7 +637,8 @@ public:
// Store narrow klass to memory
class StoreNKlassNode : public StoreNNode {
public:
StoreNKlassNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNNode(c,mem,adr,at,val) {}
StoreNKlassNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo)
: StoreNNode(c, mem, adr, at, val, mo) {}
virtual int Opcode() const;
virtual BasicType memory_type() const { return T_NARROWKLASS; }
};
@ -606,7 +659,7 @@ class StoreCMNode : public StoreNode {
public:
StoreCMNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store, int oop_alias_idx ) :
StoreNode(c,mem,adr,at,val,oop_store),
StoreNode(c, mem, adr, at, val, oop_store, MemNode::release),
_oop_alias_idx(oop_alias_idx) {
assert(_oop_alias_idx >= Compile::AliasIdxRaw ||
_oop_alias_idx == Compile::AliasIdxBot && Compile::current()->AliasLevel() == 0,
@ -626,8 +679,8 @@ public:
// On PowerPC and friends it's a real load-locked.
class LoadPLockedNode : public LoadPNode {
public:
LoadPLockedNode( Node *c, Node *mem, Node *adr )
: LoadPNode(c,mem,adr,TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM) {}
LoadPLockedNode(Node *c, Node *mem, Node *adr, MemOrd mo)
: LoadPNode(c, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, mo) {}
virtual int Opcode() const;
virtual int store_Opcode() const { return Op_StorePConditional; }
virtual bool depends_only_on_test() const { return true; }

View File

@ -485,7 +485,8 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node *ldus = new (phase->C) LoadUSNode(load->in(MemNode::Control),
load->in(MemNode::Memory),
load->in(MemNode::Address),
load->adr_type());
load->adr_type(),
TypeInt::CHAR, MemNode::unordered);
ldus = phase->transform(ldus);
return new (phase->C) AndINode(ldus, phase->intcon(mask & 0xFFFF));
}
@ -496,7 +497,8 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* ldub = new (phase->C) LoadUBNode(load->in(MemNode::Control),
load->in(MemNode::Memory),
load->in(MemNode::Address),
load->adr_type());
load->adr_type(),
TypeInt::UBYTE, MemNode::unordered);
ldub = phase->transform(ldub);
return new (phase->C) AndINode(ldub, phase->intcon(mask));
}
@ -931,9 +933,10 @@ Node *RShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) {
ld->outcnt() == 1 && ld->unique_out() == shl)
// Replace zero-extension-load with sign-extension-load
return new (phase->C) LoadSNode( ld->in(MemNode::Control),
ld->in(MemNode::Memory),
ld->in(MemNode::Address),
ld->adr_type());
ld->in(MemNode::Memory),
ld->in(MemNode::Address),
ld->adr_type(), TypeInt::SHORT,
MemNode::unordered);
}
// Check for "(byte[i] <<24)>>24" which simply sign-extends

View File

@ -106,24 +106,24 @@ Node *Parse::fetch_interpreter_state(int index,
// Very similar to LoadNode::make, except we handle un-aligned longs and
// doubles on Sparc. Intel can handle them just fine directly.
Node *l;
switch( bt ) { // Signature is flattened
case T_INT: l = new (C) LoadINode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break;
case T_FLOAT: l = new (C) LoadFNode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break;
case T_ADDRESS: l = new (C) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ); break;
case T_OBJECT: l = new (C) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break;
switch (bt) { // Signature is flattened
case T_INT: l = new (C) LoadINode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInt::INT, MemNode::unordered); break;
case T_FLOAT: l = new (C) LoadFNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::FLOAT, MemNode::unordered); break;
case T_ADDRESS: l = new (C) LoadPNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered); break;
case T_OBJECT: l = new (C) LoadPNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM, MemNode::unordered); break;
case T_LONG:
case T_DOUBLE: {
// Since arguments are in reverse order, the argument address 'adr'
// refers to the back half of the long/double. Recompute adr.
adr = basic_plus_adr( local_addrs_base, local_addrs, -(index+1)*wordSize );
if( Matcher::misaligned_doubles_ok ) {
adr = basic_plus_adr(local_addrs_base, local_addrs, -(index+1)*wordSize);
if (Matcher::misaligned_doubles_ok) {
l = (bt == T_DOUBLE)
? (Node*)new (C) LoadDNode( ctl, mem, adr, TypeRawPtr::BOTTOM )
: (Node*)new (C) LoadLNode( ctl, mem, adr, TypeRawPtr::BOTTOM );
? (Node*)new (C) LoadDNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::DOUBLE, MemNode::unordered)
: (Node*)new (C) LoadLNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeLong::LONG, MemNode::unordered);
} else {
l = (bt == T_DOUBLE)
? (Node*)new (C) LoadD_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM )
: (Node*)new (C) LoadL_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM );
? (Node*)new (C) LoadD_unalignedNode(ctl, mem, adr, TypeRawPtr::BOTTOM, MemNode::unordered)
: (Node*)new (C) LoadL_unalignedNode(ctl, mem, adr, TypeRawPtr::BOTTOM, MemNode::unordered);
}
break;
}
@ -229,7 +229,7 @@ void Parse::load_interpreter_state(Node* osr_buf) {
Node *displaced_hdr = fetch_interpreter_state((index*2) + 1, T_ADDRESS, monitors_addr, osr_buf);
store_to_memory(control(), box, displaced_hdr, T_ADDRESS, Compile::AliasIdxRaw);
store_to_memory(control(), box, displaced_hdr, T_ADDRESS, Compile::AliasIdxRaw, MemNode::unordered);
// Build a bogus FastLockNode (no code will be generated) and push the
// monitor into our debug info.
@ -1931,7 +1931,7 @@ void Parse::call_register_finalizer() {
Node* klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), klass_addr, TypeInstPtr::KLASS) );
Node* access_flags_addr = basic_plus_adr(klass, klass, in_bytes(Klass::access_flags_offset()));
Node* access_flags = make_load(NULL, access_flags_addr, TypeInt::INT, T_INT);
Node* access_flags = make_load(NULL, access_flags_addr, TypeInt::INT, T_INT, MemNode::unordered);
Node* mask = _gvn.transform(new (C) AndINode(access_flags, intcon(JVM_ACC_HAS_FINALIZER)));
Node* check = _gvn.transform(new (C) CmpINode(mask, intcon(0)));

View File

@ -50,7 +50,7 @@ void Parse::array_load(BasicType elem_type) {
if (stopped()) return; // guaranteed null or range check
dec_sp(2); // Pop array and index
const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type);
Node* ld = make_load(control(), adr, elem, elem_type, adr_type);
Node* ld = make_load(control(), adr, elem, elem_type, adr_type, MemNode::unordered);
push(ld);
}
@ -62,7 +62,7 @@ void Parse::array_store(BasicType elem_type) {
Node* val = pop();
dec_sp(2); // Pop array and index
const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type);
store_to_memory(control(), adr, val, elem_type, adr_type);
store_to_memory(control(), adr, val, elem_type, adr_type, StoreNode::release_if_reference(elem_type));
}
@ -1720,14 +1720,14 @@ void Parse::do_one_bytecode() {
a = array_addressing(T_LONG, 0);
if (stopped()) return; // guaranteed null or range check
dec_sp(2); // Pop array and index
push_pair(make_load(control(), a, TypeLong::LONG, T_LONG, TypeAryPtr::LONGS));
push_pair(make_load(control(), a, TypeLong::LONG, T_LONG, TypeAryPtr::LONGS, MemNode::unordered));
break;
}
case Bytecodes::_daload: {
a = array_addressing(T_DOUBLE, 0);
if (stopped()) return; // guaranteed null or range check
dec_sp(2); // Pop array and index
push_pair(make_load(control(), a, Type::DOUBLE, T_DOUBLE, TypeAryPtr::DOUBLES));
push_pair(make_load(control(), a, Type::DOUBLE, T_DOUBLE, TypeAryPtr::DOUBLES, MemNode::unordered));
break;
}
case Bytecodes::_bastore: array_store(T_BYTE); break;
@ -1744,7 +1744,7 @@ void Parse::do_one_bytecode() {
a = pop(); // the array itself
const TypeOopPtr* elemtype = _gvn.type(a)->is_aryptr()->elem()->make_oopptr();
const TypeAryPtr* adr_type = TypeAryPtr::OOPS;
Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT);
Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT, MemNode::release);
break;
}
case Bytecodes::_lastore: {
@ -1752,7 +1752,7 @@ void Parse::do_one_bytecode() {
if (stopped()) return; // guaranteed null or range check
c = pop_pair();
dec_sp(2); // Pop array and index
store_to_memory(control(), a, c, T_LONG, TypeAryPtr::LONGS);
store_to_memory(control(), a, c, T_LONG, TypeAryPtr::LONGS, MemNode::unordered);
break;
}
case Bytecodes::_dastore: {
@ -1761,7 +1761,7 @@ void Parse::do_one_bytecode() {
c = pop_pair();
dec_sp(2); // Pop array and index
c = dstore_rounding(c);
store_to_memory(control(), a, c, T_DOUBLE, TypeAryPtr::DOUBLES);
store_to_memory(control(), a, c, T_DOUBLE, TypeAryPtr::DOUBLES, MemNode::unordered);
break;
}
case Bytecodes::_getfield:

View File

@ -228,7 +228,9 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
type = Type::get_const_basic_type(bt);
}
// Build the load.
Node* ld = make_load(NULL, adr, type, bt, adr_type, is_vol);
//
MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, is_vol);
// Adjust Java stack
if (type2size[bt] == 1)
@ -288,6 +290,16 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
// Round doubles before storing
if (bt == T_DOUBLE) val = dstore_rounding(val);
// Conservatively release stores of object references.
const MemNode::MemOrd mo =
is_vol ?
// Volatile fields need releasing stores.
MemNode::release :
// Non-volatile fields also need releasing stores if they hold an
// object reference, because the object reference might point to
// a freshly created object.
StoreNode::release_if_reference(bt);
// Store the value.
Node* store;
if (bt == T_OBJECT) {
@ -297,9 +309,9 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
} else {
field_type = TypeOopPtr::make_from_klass(field->type()->as_klass());
}
store = store_oop_to_object( control(), obj, adr, adr_type, val, field_type, bt);
store = store_oop_to_object(control(), obj, adr, adr_type, val, field_type, bt, mo);
} else {
store = store_to_memory( control(), adr, val, bt, adr_type, is_vol );
store = store_to_memory(control(), adr, val, bt, adr_type, mo, is_vol);
}
// If reference is volatile, prevent following volatiles ops from
@ -414,7 +426,7 @@ Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, in
Node* elem = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1, nargs);
intptr_t offset = header + ((intptr_t)i << LogBytesPerHeapOop);
Node* eaddr = basic_plus_adr(array, offset);
store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT);
store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT, MemNode::unordered);
}
}
return array;
@ -503,7 +515,7 @@ void Parse::do_multianewarray() {
// Fill-in it with values
for (j = 0; j < ndimensions; j++) {
Node *dims_elem = array_element_address(dims, intcon(j), T_INT);
store_to_memory(control(), dims_elem, length[j], T_INT, TypeAryPtr::INTS);
store_to_memory(control(), dims_elem, length[j], T_INT, TypeAryPtr::INTS, MemNode::unordered);
}
}

View File

@ -222,7 +222,7 @@ void Parse::emit_guard_for_new(ciInstanceKlass* klass) {
Node* init_thread_offset = _gvn.MakeConX(in_bytes(InstanceKlass::init_thread_offset()));
Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset);
Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS);
Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS, MemNode::unordered);
Node *tst = Bool( CmpP( init_thread, cur_thread), BoolTest::eq);
IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
set_control(IfTrue(iff));
@ -232,7 +232,7 @@ void Parse::emit_guard_for_new(ciInstanceKlass* klass) {
adr_node = basic_plus_adr(kls, kls, init_state_offset);
// Use T_BOOLEAN for InstanceKlass::_init_state so the compiler
// can generate code to load it as unsigned byte.
Node* init_state = make_load(NULL, adr_node, TypeInt::UBYTE, T_BOOLEAN);
Node* init_state = make_load(NULL, adr_node, TypeInt::UBYTE, T_BOOLEAN, MemNode::unordered);
Node* being_init = _gvn.intcon(InstanceKlass::being_initialized);
tst = Bool( CmpI( init_state, being_init), BoolTest::eq);
iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
@ -354,13 +354,13 @@ void Parse::increment_and_test_invocation_counter(int limit) {
Node *counters_node = makecon(adr_type);
Node* adr_iic_node = basic_plus_adr(counters_node, counters_node,
MethodCounters::interpreter_invocation_counter_offset_in_bytes());
Node* cnt = make_load(ctrl, adr_iic_node, TypeInt::INT, T_INT, adr_type);
Node* cnt = make_load(ctrl, adr_iic_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
test_counter_against_threshold(cnt, limit);
// Add one to the counter and store
Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1)));
store_to_memory( ctrl, adr_iic_node, incr, T_INT, adr_type );
store_to_memory(ctrl, adr_iic_node, incr, T_INT, adr_type, MemNode::unordered);
}
//----------------------------method_data_addressing---------------------------
@ -392,9 +392,9 @@ void Parse::increment_md_counter_at(ciMethodData* md, ciProfileData* data, ByteS
Node* adr_node = method_data_addressing(md, data, counter_offset, idx, stride);
const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr();
Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type);
Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(DataLayout::counter_increment)));
store_to_memory(NULL, adr_node, incr, T_INT, adr_type );
store_to_memory(NULL, adr_node, incr, T_INT, adr_type, MemNode::unordered);
}
//--------------------------test_for_osr_md_counter_at-------------------------
@ -402,7 +402,7 @@ void Parse::test_for_osr_md_counter_at(ciMethodData* md, ciProfileData* data, By
Node* adr_node = method_data_addressing(md, data, counter_offset);
const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr();
Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type);
Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
test_counter_against_threshold(cnt, limit);
}
@ -412,9 +412,9 @@ void Parse::set_md_flag_at(ciMethodData* md, ciProfileData* data, int flag_const
Node* adr_node = method_data_addressing(md, data, DataLayout::flags_offset());
const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr();
Node* flags = make_load(NULL, adr_node, TypeInt::BYTE, T_BYTE, adr_type);
Node* flags = make_load(NULL, adr_node, TypeInt::BYTE, T_BYTE, adr_type, MemNode::unordered);
Node* incr = _gvn.transform(new (C) OrINode(flags, _gvn.intcon(flag_constant)));
store_to_memory(NULL, adr_node, incr, T_BYTE, adr_type);
store_to_memory(NULL, adr_node, incr, T_BYTE, adr_type, MemNode::unordered);
}
//----------------------------profile_taken_branch-----------------------------

View File

@ -1122,7 +1122,8 @@ Node* PhaseStringOpts::fetch_static_field(GraphKit& kit, ciField* field) {
return kit.make_load(NULL, kit.basic_plus_adr(klass_node, field->offset_in_bytes()),
type, T_OBJECT,
C->get_alias_index(mirror_type->add_offset(field->offset_in_bytes())));
C->get_alias_index(mirror_type->add_offset(field->offset_in_bytes())),
MemNode::unordered);
}
Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) {
@ -1314,7 +1315,7 @@ void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, N
Node* ch = __ AddI(r, __ intcon('0'));
Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR),
ch, T_CHAR, char_adr_idx);
ch, T_CHAR, char_adr_idx, MemNode::unordered);
IfNode* iff = kit.create_and_map_if(head, __ Bool(__ CmpI(q, __ intcon(0)), BoolTest::ne),
@ -1356,7 +1357,7 @@ void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, N
} else {
Node* m1 = __ SubI(charPos, __ intcon(1));
Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR),
sign, T_CHAR, char_adr_idx);
sign, T_CHAR, char_adr_idx, MemNode::unordered);
final_merge->init_req(1, kit.control());
final_mem->init_req(1, st);
@ -1387,7 +1388,8 @@ Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, N
ciTypeArray* value_array = t->const_oop()->as_type_array();
for (int e = 0; e < c; e++) {
__ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
__ intcon(value_array->char_at(o + e)), T_CHAR, char_adr_idx);
__ intcon(value_array->char_at(o + e)), T_CHAR, char_adr_idx,
MemNode::unordered);
start = __ AddI(start, __ intcon(1));
}
} else {
@ -1607,7 +1609,7 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
}
case StringConcat::CharMode: {
__ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
arg, T_CHAR, char_adr_idx);
arg, T_CHAR, char_adr_idx, MemNode::unordered);
start = __ AddI(start, __ intcon(1));
break;
}

View File

@ -356,7 +356,7 @@ class XorVNode : public VectorNode {
class LoadVectorNode : public LoadNode {
public:
LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt)
: LoadNode(c, mem, adr, at, vt) {
: LoadNode(c, mem, adr, at, vt, MemNode::unordered) {
init_class_id(Class_LoadVector);
}
@ -380,7 +380,7 @@ class LoadVectorNode : public LoadNode {
class StoreVectorNode : public StoreNode {
public:
StoreVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, Node* val)
: StoreNode(c, mem, adr, at, val) {
: StoreNode(c, mem, adr, at, val, MemNode::unordered) {
assert(val->is_Vector() || val->is_LoadVector(), "sanity");
init_class_id(Class_StoreVector);
}