< prev index next >
src/hotspot/share/opto/parse2.cpp
Print this page
@@ -63,31 +63,33 @@
// Handle value type arrays
const TypeOopPtr* elemptr = elemtype->make_oopptr();
const TypeAryPtr* ary_t = _gvn.type(ary)->is_aryptr();
if (elemtype->isa_valuetype() != NULL) {
+ C->set_flattened_accesses();
// Load from flattened value type array
Node* vt = ValueTypeNode::make_from_flattened(this, elemtype->value_klass(), ary, adr);
push(vt);
return;
} else if (elemptr != NULL && elemptr->is_valuetypeptr() && !elemptr->maybe_null()) {
// Load from non-flattened but flattenable value type array (elements can never be null)
bt = T_VALUETYPE;
} else if (ValueArrayFlatten && elemptr != NULL && elemptr->can_be_value_type() &&
!ary_t->klass_is_exact() && (!elemptr->is_valuetypeptr() || elemptr->value_klass()->flatten_array())) {
// Cannot statically determine if array is flattened, emit runtime check
+ Node* ctl = control();
IdealKit ideal(this);
IdealVariable res(ideal);
ideal.declarations_done();
Node* kls = load_object_klass(ary);
Node* tag = load_lh_array_tag(kls);
ideal.if_then(tag, BoolTest::ne, intcon(Klass::_lh_array_tag_vt_value)); {
// non-flattened
sync_kit(ideal);
const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(bt);
Node* ld = access_load_at(ary, adr, adr_type, elemptr, bt,
- IN_HEAP | IS_ARRAY | C2_CONTROL_DEPENDENT_LOAD);
+ IN_HEAP | IS_ARRAY | C2_CONTROL_DEPENDENT_LOAD, ctl);
ideal.sync_kit(this);
ideal.set(res, ld);
} ideal.else_(); {
// flattened
sync_kit(ideal);
@@ -100,10 +102,11 @@
const TypeAryPtr* arytype = TypeOopPtr::make_from_klass(array_klass)->isa_aryptr();
Node* cast = _gvn.transform(new CheckCastPPNode(control(), ary, arytype));
adr = array_element_address(cast, idx, T_VALUETYPE, ary_t->size(), control());
Node* vt = ValueTypeNode::make_from_flattened(this, vk, cast, adr)->allocate(this, false, false)->get_oop();
ideal.set(res, vt);
+ ideal.sync_kit(this);
} else {
// Element type is unknown, emit runtime call
assert(!ary_t->klass_is_exact(), "should not have exact type here");
Node* k_adr = basic_plus_adr(kls, in_bytes(ArrayKlass::element_klass_offset()));
Node* elem_klass = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), k_adr, TypeInstPtr::KLASS));
@@ -114,10 +117,16 @@
dec_sp(2);
AllocateNode* alloc = AllocateNode::Ideal_allocation(alloc_obj, &_gvn);
assert(alloc->maybe_set_complete(&_gvn), "");
alloc->initialization()->set_complete_with_arraycopy();
+
+ // This membar keeps this access to an unknown flattened array
+ // correctly ordered with other unknown and known flattened
+ // array accesses.
+ insert_mem_bar_volatile(Op_MemBarCPUOrder, C->get_alias_index(TypeAryPtr::VALUES));
+
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
// Unknown value type might contain reference fields
if (!bs->array_copy_requires_gc_barriers(false, T_OBJECT, false, BarrierSetC2::Parsing)) {
int base_off = sizeof(instanceOopDesc);
Node* dst_base = basic_plus_adr(alloc_obj, base_off);
@@ -142,15 +151,28 @@
"load_unknown_value",
ary, idx, alloc_obj);
sync_kit(ideal);
}
- insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out_or_null(AllocateNode::RawAddress));
+ // This makes sure no other thread sees a partially initialized buffered value
+ insert_mem_bar_volatile(Op_MemBarStoreStore, Compile::AliasIdxRaw, alloc->proj_out_or_null(AllocateNode::RawAddress));
+
+ // Same as MemBarCPUOrder above: keep this unknown flattened
+ // array access correctly ordered with other flattened array
+ // access
+ insert_mem_bar_volatile(Op_MemBarCPUOrder, C->get_alias_index(TypeAryPtr::VALUES));
+
+ // Prevent any use of the newly allocated value before it is
+ // fully initialized
+ alloc_obj = new CastPPNode(alloc_obj, _gvn.type(alloc_obj), true);
+ alloc_obj->set_req(0, control());
+ alloc_obj = _gvn.transform(alloc_obj);
+
+ ideal.sync_kit(this);
ideal.set(res, alloc_obj);
}
- ideal.sync_kit(this);
} ideal.end_if();
sync_kit(ideal);
push_node(bt, _gvn.transform(ideal.value(res)));
return;
}
@@ -193,10 +215,11 @@
const TypeAryPtr* ary_t = _gvn.type(ary)->is_aryptr();
if (bt == T_OBJECT) {
const TypeOopPtr* elemptr = elemtype->make_oopptr();
const Type* val_t = _gvn.type(val);
if (elemtype->isa_valuetype() != NULL) {
+ C->set_flattened_accesses();
// Store to flattened value type array
if (!cast_val->is_ValueType()) {
inc_sp(3);
cast_val = null_check(cast_val);
if (stopped()) return;
@@ -267,14 +290,30 @@
val->as_ValueType()->store_flattened(this, ary, adr);
ideal.sync_kit(this);
} else if (!ideal.ctrl()->is_top()) {
// Element type is unknown, emit runtime call
assert(!ary_t->klass_is_exact(), "should not have exact type here");
+ sync_kit(ideal);
+
+ // This membar keeps this access to an unknown flattened
+ // array correctly ordered with other unknown and known
+ // flattened array accesses.
+ insert_mem_bar_volatile(Op_MemBarCPUOrder, C->get_alias_index(TypeAryPtr::VALUES));
+ ideal.sync_kit(this);
+
ideal.make_leaf_call(OptoRuntime::store_unknown_value_Type(),
CAST_FROM_FN_PTR(address, OptoRuntime::store_unknown_value),
"store_unknown_value",
val, ary, idx);
+
+ sync_kit(ideal);
+ // Same as MemBarCPUOrder above: keep this unknown
+ // flattened array access correctly ordered with other
+ // flattened array access
+ insert_mem_bar_volatile(Op_MemBarCPUOrder, C->get_alias_index(TypeAryPtr::VALUES));
+ ideal.sync_kit(this);
+
}
} ideal.end_if();
sync_kit(ideal);
return;
} else {
< prev index next >