< prev index next >
src/hotspot/share/opto/graphKit.cpp
Print this page
*** 1595,1605 ****
const TypePtr* adr_type,
Node* val,
const Type* val_type,
BasicType bt,
DecoratorSet decorators,
! bool deoptimize_on_exception) {
// 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.
if (_gvn.type(val) == TypePtr::NULL_PTR) {
val = _gvn.makecon(TypePtr::NULL_PTR);
--- 1595,1606 ----
const TypePtr* adr_type,
Node* val,
const Type* val_type,
BasicType bt,
DecoratorSet decorators,
! bool deoptimize_on_exception,
! bool safe_for_replace) {
// 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.
if (_gvn.type(val) == TypePtr::NULL_PTR) {
val = _gvn.makecon(TypePtr::NULL_PTR);
*** 1610,1620 ****
}
assert(val != NULL, "not dead path");
if (val->is_ValueType()) {
// Allocate value type and get oop
! val = val->as_ValueType()->allocate(this, deoptimize_on_exception)->get_oop();
}
C2AccessValuePtr addr(adr, adr_type);
C2AccessValue value(val, val_type);
C2ParseAccess access(this, decorators | C2_WRITE_ACCESS, bt, obj, addr);
--- 1611,1621 ----
}
assert(val != NULL, "not dead path");
if (val->is_ValueType()) {
// Allocate value type and get oop
! val = val->as_ValueType()->allocate(this, deoptimize_on_exception, safe_for_replace)->get_oop();
}
C2AccessValuePtr addr(adr, adr_type);
C2AccessValue value(val, val_type);
C2ParseAccess access(this, decorators | C2_WRITE_ACCESS, bt, obj, addr);
*** 3129,3139 ****
}
// Load the object's klass
Node* obj_klass = NULL;
if (is_value) {
! obj_klass = makecon(TypeKlassPtr::make(_gvn.type(not_null_obj)->is_valuetype()->value_klass()));
} else {
obj_klass = load_object_klass(not_null_obj);
}
// Generate the subtype check
--- 3130,3140 ----
}
// Load the object's klass
Node* obj_klass = NULL;
if (is_value) {
! obj_klass = makecon(TypeKlassPtr::make(_gvn.type(not_null_obj)->value_klass()));
} else {
obj_klass = load_object_klass(not_null_obj);
}
// Generate the subtype check
*** 3183,3193 ****
// want a residual null check left around. (Causes a slowdown,
// for example, in some objArray manipulations, such as a[i]=a[j].)
if (tk->singleton()) {
ciKlass* klass = NULL;
if (is_value) {
! klass = _gvn.type(obj)->is_valuetype()->value_klass();
} else {
const TypeOopPtr* objtp = _gvn.type(obj)->isa_oopptr();
if (objtp != NULL) {
klass = objtp->klass();
}
--- 3184,3194 ----
// want a residual null check left around. (Causes a slowdown,
// for example, in some objArray manipulations, such as a[i]=a[j].)
if (tk->singleton()) {
ciKlass* klass = NULL;
if (is_value) {
! klass = _gvn.type(obj)->value_klass();
} else {
const TypeOopPtr* objtp = _gvn.type(obj)->isa_oopptr();
if (objtp != NULL) {
klass = objtp->klass();
}
*** 3236,3245 ****
--- 3237,3249 ----
// Make the merge point
enum { _obj_path = 1, _null_path, PATH_LIMIT };
RegionNode* region = new RegionNode(PATH_LIMIT);
Node* phi = new PhiNode(region, toop);
+ _gvn.set_type(region, Type::CONTROL);
+ _gvn.set_type(phi, toop);
+
C->set_has_split_ifs(true); // Has chance for split-if optimization
// Use null-cast information if it is available
bool speculative_not_null = false;
bool never_see_null = ((failure_control == NULL) // regular case only
*** 3301,3311 ****
if (cast_obj == NULL) {
// Load the object's klass
Node* obj_klass = NULL;
if (is_value) {
! obj_klass = makecon(TypeKlassPtr::make(_gvn.type(not_null_obj)->is_valuetype()->value_klass()));
} else {
obj_klass = load_object_klass(not_null_obj);
}
// Generate the subtype check
--- 3305,3315 ----
if (cast_obj == NULL) {
// Load the object's klass
Node* obj_klass = NULL;
if (is_value) {
! obj_klass = makecon(TypeKlassPtr::make(_gvn.type(not_null_obj)->value_klass()));
} else {
obj_klass = load_object_klass(not_null_obj);
}
// Generate the subtype check
*** 3378,3426 ****
uncommon_trap(Deoptimization::Reason_class_check,
Deoptimization::Action_none);
}
}
! // Deoptimize if 'ary' is flattened or if 'obj' is null and 'ary' is a value type array
! void GraphKit::gen_value_type_array_guard(Node* ary, Node* obj, int nargs) {
assert(EnableValhalla, "should only be used if value types are enabled");
! // Load array element klass
! Node* kls = load_object_klass(ary);
! 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));
! // Check if element is a value type
! Node* flags_addr = basic_plus_adr(elem_klass, in_bytes(Klass::access_flags_offset()));
! Node* flags = make_load(NULL, flags_addr, TypeInt::INT, T_INT, MemNode::unordered);
! Node* is_value_elem = _gvn.transform(new AndINode(flags, intcon(JVM_ACC_VALUE)));
!
! const Type* objtype = _gvn.type(obj);
! if (objtype == TypePtr::NULL_PTR) {
! // Object is always null, check if array is a value type array
! Node* cmp = _gvn.transform(new CmpINode(is_value_elem, intcon(0)));
! Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
! { BuildCutout unless(this, bol, PROB_MAX);
! // TODO just deoptimize for now if we store null to a value type array
! inc_sp(nargs);
! uncommon_trap(Deoptimization::Reason_array_check,
! Deoptimization::Action_none);
}
! } else {
! // Check if (is_value_elem && obj_is_null) <=> (!is_value_elem | !obj_is_null == 0)
! // TODO what if we later figure out that obj is never null?
! Node* not_value = _gvn.transform(new XorINode(is_value_elem, intcon(JVM_ACC_VALUE)));
! not_value = _gvn.transform(new ConvI2LNode(not_value));
! Node* not_null = _gvn.transform(new CastP2XNode(NULL, obj));
! Node* both = _gvn.transform(new OrLNode(not_null, not_value));
! Node* cmp = _gvn.transform(new CmpLNode(both, longcon(0)));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::ne));
{ BuildCutout unless(this, bol, PROB_MAX);
- // TODO just deoptimize for now if we store null to a value type array
inc_sp(nargs);
! uncommon_trap(Deoptimization::Reason_array_check,
Deoptimization::Action_none);
}
}
}
Node* GraphKit::load_lh_array_tag(Node* kls) {
Node* lhp = basic_plus_adr(kls, in_bytes(Klass::layout_helper_offset()));
Node* layout_val = make_load(NULL, lhp, TypeInt::INT, T_INT, MemNode::unordered);
--- 3382,3423 ----
uncommon_trap(Deoptimization::Reason_class_check,
Deoptimization::Action_none);
}
}
! // Deoptimize if 'ary' is a null-free value type array and 'val' is null
! void GraphKit::gen_value_array_null_guard(Node* ary, Node* val, int nargs) {
assert(EnableValhalla, "should only be used if value types are enabled");
! const Type* val_t = _gvn.type(val);
! if (val->is_ValueType() || !TypePtr::NULL_PTR->higher_equal(val_t)) {
! return; // Never null
}
! RegionNode* region = new RegionNode(3);
! Node* null_ctl = top();
! null_check_oop(val, &null_ctl);
! if (null_ctl != top()) {
! PreserveJVMState pjvms(this);
! set_control(null_ctl);
! // Get array element mirror and corresponding value mirror
! Node* array_type_mirror = load_mirror_from_klass(load_object_klass(ary));
! Node* elem_mirror_adr = basic_plus_adr(array_type_mirror, java_lang_Class::component_mirror_offset_in_bytes());
! Node* elem_mirror = access_load_at(array_type_mirror, elem_mirror_adr, _gvn.type(elem_mirror_adr)->is_ptr(), TypeInstPtr::MIRROR, T_OBJECT, IN_HEAP);
! Node* value_mirror_adr = basic_plus_adr(elem_mirror, java_lang_Class::value_mirror_offset_in_bytes());
! Node* value_mirror = access_load_at(elem_mirror, value_mirror_adr, _gvn.type(value_mirror_adr)->is_ptr(), TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR), T_OBJECT, IN_HEAP);
! // Deoptimize if elem_mirror == value_mirror => null-free array
! Node* cmp = _gvn.transform(new CmpPNode(elem_mirror, value_mirror));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::ne));
{ BuildCutout unless(this, bol, PROB_MAX);
inc_sp(nargs);
! uncommon_trap(Deoptimization::Reason_null_check,
Deoptimization::Action_none);
}
+ region->init_req(1, control());
}
+ region->init_req(2, control());
+ set_control(_gvn.transform(region));
+ record_for_igvn(region);
}
Node* GraphKit::load_lh_array_tag(Node* kls) {
Node* lhp = basic_plus_adr(kls, in_bytes(Klass::layout_helper_offset()));
Node* layout_val = make_load(NULL, lhp, TypeInt::INT, T_INT, MemNode::unordered);
*** 3622,3637 ****
const TypeKlassPtr* inst_klass = _gvn.type(klass_node)->isa_klassptr();
if (!StressReflectiveCode && inst_klass != NULL) {
ciKlass* klass = inst_klass->klass();
assert(klass != NULL, "klass should not be NULL");
bool xklass = inst_klass->klass_is_exact();
! bool can_be_value_array = false;
! if (klass->is_array_klass() && EnableValhalla && ValueArrayFlatten) {
! ciKlass* elem = klass->as_array_klass()->element_klass();
! can_be_value_array = elem != NULL && (elem->is_java_lang_Object() || elem->is_interface());
}
! if (xklass || (klass->is_array_klass() && !can_be_value_array)) {
jint lhelper = klass->layout_helper();
if (lhelper != Klass::_lh_neutral_value) {
constant_value = lhelper;
return (Node*) NULL;
}
--- 3619,3634 ----
const TypeKlassPtr* inst_klass = _gvn.type(klass_node)->isa_klassptr();
if (!StressReflectiveCode && inst_klass != NULL) {
ciKlass* klass = inst_klass->klass();
assert(klass != NULL, "klass should not be NULL");
bool xklass = inst_klass->klass_is_exact();
! bool can_be_flattened = false;
! if (ValueArrayFlatten && klass->is_obj_array_klass()) {
! ciKlass* elem = klass->as_obj_array_klass()->element_klass();
! can_be_flattened = elem->is_java_lang_Object() || elem->is_interface();
}
! if (xklass || (klass->is_array_klass() && !can_be_flattened)) {
jint lhelper = klass->layout_helper();
if (lhelper != Klass::_lh_neutral_value) {
constant_value = lhelper;
return (Node*) NULL;
}
*** 4051,4061 ****
Node* null_free = MakeConX(ArrayStorageProperties::null_free.encode<NOT_LP64(jint) LP64_ONLY(jlong)>(props_shift));
Node* flat = MakeConX(ArrayStorageProperties::flattened_and_null_free.encode<NOT_LP64(jint) LP64_ONLY(jlong)>(props_shift));
// Check if element mirror is a value mirror
Node* p = basic_plus_adr(elem_mirror, java_lang_Class::value_mirror_offset_in_bytes());
! Node* value_mirror = access_load_at(elem_mirror, p, _gvn.type(p)->is_ptr(), TypeInstPtr::MIRROR, T_OBJECT, IN_HEAP);
Node* cmp = _gvn.transform(new CmpPNode(elem_mirror, value_mirror));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
IfNode* iff = create_and_map_if(control(), bol, PROB_FAIR, COUNT_UNKNOWN);
// Not a value mirror but a box mirror or not a value type array, initialize with all zero
--- 4048,4058 ----
Node* null_free = MakeConX(ArrayStorageProperties::null_free.encode<NOT_LP64(jint) LP64_ONLY(jlong)>(props_shift));
Node* flat = MakeConX(ArrayStorageProperties::flattened_and_null_free.encode<NOT_LP64(jint) LP64_ONLY(jlong)>(props_shift));
// Check if element mirror is a value mirror
Node* p = basic_plus_adr(elem_mirror, java_lang_Class::value_mirror_offset_in_bytes());
! Node* value_mirror = access_load_at(elem_mirror, p, _gvn.type(p)->is_ptr(), TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR), T_OBJECT, IN_HEAP);
Node* cmp = _gvn.transform(new CmpPNode(elem_mirror, value_mirror));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
IfNode* iff = create_and_map_if(control(), bol, PROB_FAIR, COUNT_UNKNOWN);
// Not a value mirror but a box mirror or not a value type array, initialize with all zero
< prev index next >