< prev index next >
src/hotspot/share/opto/parse2.cpp
Print this page
*** 64,100 ****
// Handle value type arrays
const TypeOopPtr* elemptr = elemtype->make_oopptr();
const TypeAryPtr* ary_t = _gvn.type(ary)->is_aryptr();
if (elemtype->isa_valuetype() != NULL) {
// Load from flattened value type array
! ciValueKlass* vk = elemtype->is_valuetype()->value_klass();
! Node* vt = ValueTypeNode::make_from_flattened(this, vk, ary, adr);
push(vt);
return;
} else if (elemptr != NULL && elemptr->is_valuetypeptr() && !elemptr->maybe_null()) {
! // Load from non-flattened 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()) {
// Cannot statically determine if array is flattened, emit runtime check
- assert(!elemptr->is_valuetypeptr(), "we know the exact type");
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);
! elemtype = ary_t->elem()->make_oopptr();
! Node* ld = access_load_at(ary, adr, adr_type, elemtype, bt,
IN_HEAP | IS_ARRAY | C2_CONTROL_DEPENDENT_LOAD);
ideal.sync_kit(this);
ideal.set(res, ld);
} ideal.else_(); {
// flattened
sync_kit(ideal);
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));
Node* obj_size = NULL;
kill_dead_locals();
inc_sp(2);
--- 64,112 ----
// Handle value type arrays
const TypeOopPtr* elemptr = elemtype->make_oopptr();
const TypeAryPtr* ary_t = _gvn.type(ary)->is_aryptr();
if (elemtype->isa_valuetype() != NULL) {
// 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
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);
ideal.sync_kit(this);
ideal.set(res, ld);
} ideal.else_(); {
// flattened
sync_kit(ideal);
+ if (elemptr->is_valuetypeptr()) {
+ // Element type is known, cast and load from flattened representation
+ assert(elemptr->maybe_null(), "must be nullable");
+ ciValueKlass* vk = elemptr->value_klass();
+ assert(vk->flatten_array(), "must be flattenable");
+ ciArrayKlass* array_klass = ciArrayKlass::make(vk, /* never_null */ true);
+ 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);
+ } 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));
Node* obj_size = NULL;
kill_dead_locals();
inc_sp(2);
*** 103,113 ****
AllocateNode* alloc = AllocateNode::Ideal_allocation(alloc_obj, &_gvn);
assert(alloc->maybe_set_complete(&_gvn), "");
alloc->initialization()->set_complete_with_arraycopy();
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
! // Unknown value type so might have 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);
Node* countx = obj_size;
countx = _gvn.transform(new SubXNode(countx, MakeConX(base_off)));
--- 115,125 ----
AllocateNode* alloc = AllocateNode::Ideal_allocation(alloc_obj, &_gvn);
assert(alloc->maybe_set_complete(&_gvn), "");
alloc->initialization()->set_complete_with_arraycopy();
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);
Node* countx = obj_size;
countx = _gvn.transform(new SubXNode(countx, MakeConX(base_off)));
*** 132,146 ****
sync_kit(ideal);
}
insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out_or_null(AllocateNode::RawAddress));
- ideal.sync_kit(this);
ideal.set(res, alloc_obj);
} ideal.end_if();
sync_kit(ideal);
! push_node(bt, ideal.value(res));
return;
}
if (elemtype == TypeInt::BOOL) {
bt = T_BOOLEAN;
--- 144,159 ----
sync_kit(ideal);
}
insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out_or_null(AllocateNode::RawAddress));
ideal.set(res, alloc_obj);
+ }
+ ideal.sync_kit(this);
} ideal.end_if();
sync_kit(ideal);
! push_node(bt, _gvn.transform(ideal.value(res)));
return;
}
if (elemtype == TypeInt::BOOL) {
bt = T_BOOLEAN;
*** 186,240 ****
if (!cast_val->is_ValueType()) {
inc_sp(3);
cast_val = null_check(cast_val);
if (stopped()) return;
dec_sp(3);
! cast_val = ValueTypeNode::make_from_oop(this, cast_val, elemtype->is_valuetype()->value_klass());
}
cast_val->as_ValueType()->store_flattened(this, ary, adr);
return;
} else if (elemptr->is_valuetypeptr() && !elemptr->maybe_null()) {
! // Store to non-flattened value type array
if (!cast_val->is_ValueType()) {
- // Can not store null into a value type array
inc_sp(3);
cast_val = null_check(cast_val);
if (stopped()) return;
dec_sp(3);
}
! } else if (elemptr->can_be_value_type() && !ary_t->klass_is_exact() &&
(val->is_ValueType() || val_t == TypePtr::NULL_PTR || val_t->is_oopptr()->can_be_value_type())) {
! if (ValueArrayFlatten) {
IdealKit ideal(this);
Node* kls = load_object_klass(ary);
Node* layout_val = load_lh_array_tag(kls);
ideal.if_then(layout_val, BoolTest::ne, intcon(Klass::_lh_array_tag_vt_value)); {
! // non flattened
sync_kit(ideal);
!
! if (!val->is_ValueType() && TypePtr::NULL_PTR->higher_equal(val_t)) {
! gen_value_type_array_guard(ary, val, 3);
! }
!
const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(bt);
elemtype = ary_t->elem()->make_oopptr();
! access_store_at(ary, adr, adr_type, val, elemtype, bt, MO_UNORDERED | IN_HEAP | IS_ARRAY);
ideal.sync_kit(this);
} ideal.else_(); {
// flattened
! // Object/interface array must be flattened, cast it
! if (val->is_ValueType()) {
! sync_kit(ideal);
! const TypeValueType* vt = _gvn.type(val)->is_valuetype();
! ciArrayKlass* array_klass = ciArrayKlass::make(vt->value_klass(), true);
! const TypeAryPtr* arytype = TypeOopPtr::make_from_klass(array_klass)->isa_aryptr();
! ary = _gvn.transform(new CheckCastPPNode(control(), ary, arytype));
! adr = array_element_address(ary, idx, T_OBJECT, arytype->size(), control());
! val->as_ValueType()->store_flattened(this, ary, adr);
! ideal.sync_kit(this);
! } else {
! if (TypePtr::NULL_PTR->higher_equal(val_t)) {
sync_kit(ideal);
Node* null_ctl = top();
val = null_check_oop(val, &null_ctl);
if (null_ctl != top()) {
PreserveJVMState pjvms(this);
--- 199,246 ----
if (!cast_val->is_ValueType()) {
inc_sp(3);
cast_val = null_check(cast_val);
if (stopped()) return;
dec_sp(3);
! cast_val = ValueTypeNode::make_from_oop(this, cast_val, elemtype->value_klass());
}
cast_val->as_ValueType()->store_flattened(this, ary, adr);
return;
} else if (elemptr->is_valuetypeptr() && !elemptr->maybe_null()) {
! // Store to non-flattened but flattenable value type array (elements can never be null)
if (!cast_val->is_ValueType()) {
inc_sp(3);
cast_val = null_check(cast_val);
if (stopped()) return;
dec_sp(3);
}
! } else if (elemptr->can_be_value_type() && (!ary_t->klass_is_exact() || elemptr->is_valuetypeptr()) &&
(val->is_ValueType() || val_t == TypePtr::NULL_PTR || val_t->is_oopptr()->can_be_value_type())) {
! // Cannot statically determine if array is flattened, emit runtime check
! ciValueKlass* vk = NULL;
! // Try to determine the value klass
! if (val->is_ValueType()) {
! vk = val_t->value_klass();
! } else if (elemptr->is_valuetypeptr()) {
! vk = elemptr->value_klass();
! }
! if (ValueArrayFlatten && (vk == NULL || vk->flatten_array())) {
IdealKit ideal(this);
Node* kls = load_object_klass(ary);
Node* layout_val = load_lh_array_tag(kls);
ideal.if_then(layout_val, BoolTest::ne, intcon(Klass::_lh_array_tag_vt_value)); {
! // non-flattened
sync_kit(ideal);
! gen_value_array_null_guard(ary, val, 3);
const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(bt);
elemtype = ary_t->elem()->make_oopptr();
! access_store_at(ary, adr, adr_type, val, elemtype, bt, MO_UNORDERED | IN_HEAP | IS_ARRAY, false, false);
ideal.sync_kit(this);
} ideal.else_(); {
// flattened
! if (!val->is_ValueType() && TypePtr::NULL_PTR->higher_equal(val_t)) {
! // Add null check
sync_kit(ideal);
Node* null_ctl = top();
val = null_check_oop(val, &null_ctl);
if (null_ctl != top()) {
PreserveJVMState pjvms(this);
*** 243,266 ****
uncommon_trap(Deoptimization::Reason_null_check, Deoptimization::Action_none);
dec_sp(3);
}
ideal.sync_kit(this);
}
! if (!ideal.ctrl()->is_top()) {
ideal.make_leaf_call(OptoRuntime::store_unknown_value_Type(),
CAST_FROM_FN_PTR(address, OptoRuntime::store_unknown_value),
"store_unknown_value",
val, ary, idx);
}
- }
} ideal.end_if();
sync_kit(ideal);
return;
} else {
! if (!val->is_ValueType() && TypePtr::NULL_PTR->higher_equal(val_t)) {
! gen_value_type_array_guard(ary, val, 3);
! }
}
}
}
if (elemtype == TypeInt::BOOL) {
--- 249,286 ----
uncommon_trap(Deoptimization::Reason_null_check, Deoptimization::Action_none);
dec_sp(3);
}
ideal.sync_kit(this);
}
! if (vk != NULL && !stopped()) {
! // Element type is known, cast and store to flattened representation
! sync_kit(ideal);
! assert(vk->flatten_array(), "must be flattenable");
! assert(elemptr->maybe_null(), "must be nullable");
! ciArrayKlass* array_klass = ciArrayKlass::make(vk, /* never_null */ true);
! const TypeAryPtr* arytype = TypeOopPtr::make_from_klass(array_klass)->isa_aryptr();
! ary = _gvn.transform(new CheckCastPPNode(control(), ary, arytype));
! adr = array_element_address(ary, idx, T_OBJECT, arytype->size(), control());
! if (!val->is_ValueType()) {
! assert(!gvn().type(val)->maybe_null(), "value type array elements should never be null");
! val = ValueTypeNode::make_from_oop(this, val, vk);
! }
! 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");
ideal.make_leaf_call(OptoRuntime::store_unknown_value_Type(),
CAST_FROM_FN_PTR(address, OptoRuntime::store_unknown_value),
"store_unknown_value",
val, ary, idx);
}
} ideal.end_if();
sync_kit(ideal);
return;
} else {
! gen_value_array_null_guard(ary, val, 3);
}
}
}
if (elemtype == TypeInt::BOOL) {
< prev index next >