< prev index next >
src/hotspot/share/opto/graphKit.cpp
Print this page
@@ -1392,10 +1392,41 @@
}
return value;
}
+Node* GraphKit::filter_null(Node* value, bool null2default, ciValueKlass* vk, int trap_bci) {
+ Node* null_ctl = top();
+ value = null_check_oop(value, &null_ctl);
+ if (!null_ctl->is_top()) {
+ if (null2default) {
+ // Return default value if oop is null
+ Node* region = new RegionNode(3);
+ region->init_req(1, control());
+ region->init_req(2, null_ctl);
+ value = PhiNode::make(region, value, TypeInstPtr::make(TypePtr::BotPTR, vk));
+ value->set_req(2, ValueTypeNode::default_oop(gvn(), vk));
+ set_control(gvn().transform(region));
+ value = gvn().transform(value);
+ } else {
+ // Deoptimize if oop is null
+ PreserveJVMState pjvms(this);
+ set_control(null_ctl);
+ int cur_bci = bci();
+ if (trap_bci != -1) {
+ // Put trap at different bytecode
+ push(null());
+ set_bci(trap_bci);
+ }
+ uncommon_trap(Deoptimization::Reason_null_check, Deoptimization::Action_none);
+ if (trap_bci != -1) {
+ set_bci(cur_bci);
+ }
+ }
+ }
+ return value;
+}
//------------------------------cast_not_null----------------------------------
// Cast obj to not-null on this path
Node* GraphKit::cast_not_null(Node* obj, bool do_replace_in_map) {
assert(!obj->is_ValueType(), "should not cast value type");
@@ -1788,27 +1819,19 @@
continue;
} else {
// Pass value type argument via oop to callee
arg = vt->allocate(this)->get_oop();
}
- } else if (t->is_valuetypeptr()) {
- ciMethod* declared_method = method()->get_method_at_bci(bci());
- if (arg->is_ValueTypePtr()) {
- // We are calling an Object method with a value type receiver
- ValueTypePtrNode* vt = arg->isa_ValueTypePtr();
- assert(i == TypeFunc::Parms && !declared_method->is_static(), "argument must be receiver");
- assert(vt->is_allocated(&gvn()), "argument must be allocated");
- arg = vt->get_oop();
- } else {
+ } else if (t->is_valuetypeptr() && !arg->is_ValueTypePtr() && gvn().type(arg)->maybe_null()) {
// Constant null passed for a value type argument
assert(arg->bottom_type()->remove_speculative() == TypePtr::NULL_PTR, "Anything other than null?");
+ ciMethod* declared_method = method()->get_method_at_bci(bci());
int arg_size = declared_method->signature()->arg_size_for_bc(java_bc());
inc_sp(arg_size); // restore arguments
uncommon_trap(Deoptimization::Reason_null_check, Deoptimization::Action_none);
return;
}
- }
call->init_req(idx, arg);
idx++;
}
}
@@ -2861,13 +2884,15 @@
// Subsume downstream occurrences of receiver with a cast to
// recv_xtype, since now we know what the type will be.
Node* cast = new CheckCastPPNode(control(), receiver, recv_xtype);
Node* res = _gvn.transform(cast);
if (recv_xtype->is_valuetypeptr()) {
- assert(!gvn().type(res)->is_ptr()->maybe_null(), "should never be null");
+ assert(!gvn().type(res)->maybe_null(), "should never be null");
+ if (recv_xtype->value_klass()->is_scalarizable()) {
res = ValueTypeNode::make_from_oop(this, res, recv_xtype->value_klass());
}
+ }
(*casted_receiver) = res;
// (User must make the replace_in_map call.)
return fail;
@@ -3166,18 +3191,22 @@
// the profiling data at this bytecode. Don't lose it, feed it
// to the type system as a speculative type.
if (!is_value) {
obj = record_profiled_receiver_for_speculation(obj);
if (toop->is_valuetypeptr()) {
+ if (toop->value_klass()->is_scalarizable()) {
obj = ValueTypeNode::make_from_oop(this, obj, toop->value_klass(), /* buffer_check */ false, /* null2default */ false);
+ } else {
+ obj = filter_null(obj);
+ }
}
}
return obj;
case Compile::SSC_always_false:
// It needs a null check because a null will *pass* the cast check.
- // A non-null value will always produce an exception.
- if (is_value) {
+ if (is_value || toop->is_valuetypeptr()) {
+ // Value types are never null - always throw an exception
builtin_throw(Deoptimization::Reason_class_check, makecon(TypeKlassPtr::make(klass)));
return top();
} else {
return null_assert(obj);
}
@@ -3206,11 +3235,18 @@
bool never_see_null = ((failure_control == NULL) // regular case only
&& seems_never_null(obj, data, speculative_not_null));
// Null check; get casted pointer; set region slot 3
Node* null_ctl = top();
- Node* not_null_obj = is_value ? obj : null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace, speculative_not_null);
+ Node* not_null_obj = NULL;
+ if (is_value) {
+ not_null_obj = obj;
+ } else if (toop->is_valuetypeptr()) {
+ not_null_obj = filter_null(obj);
+ } else {
+ not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace, speculative_not_null);
+ }
// If not_null_obj is dead, only null-path is taken
if (stopped()) { // Doing instance-of on a NULL?
set_control(null_ctl);
return null();
@@ -3263,16 +3299,12 @@
}
// Generate the subtype check
Node* not_subtype_ctrl = gen_subtype_check( obj_klass, superklass );
- if (is_value) {
- not_null_obj = ValueTypePtrNode::make_from_value_type(this, not_null_obj->as_ValueType(), true);
- }
-
// Plug in success path into the merge
- cast_obj = _gvn.transform(new CheckCastPPNode(control(), not_null_obj, toop));
+ cast_obj = is_value ? not_null_obj : _gvn.transform(new CheckCastPPNode(control(), not_null_obj, toop));
// Failure path ends in uncommon trap (or may be dead - failure impossible)
if (failure_control == NULL) {
if (not_subtype_ctrl != top()) { // If failure is possible
PreserveJVMState pjvms(this);
set_control(not_subtype_ctrl);
@@ -3304,11 +3336,14 @@
record_for_igvn(region);
if (!is_value) {
res = record_profiled_receiver_for_speculation(res);
if (toop->is_valuetypeptr()) {
- res = ValueTypeNode::make_from_oop(this, res, toop->value_klass(), /* buffer_check */ false, /* null2default */ false);
+ assert(!gvn().type(res)->maybe_null(), "should never be null");
+ if (toop->value_klass()->is_scalarizable()) {
+ res = ValueTypeNode::make_from_oop(this, res, toop->value_klass());
+ }
}
}
return res;
}
@@ -4351,12 +4386,15 @@
/*is_unsigned_load=*/false);
if (con_type != NULL) {
Node* con = makecon(con_type);
if (field->layout_type() == T_VALUETYPE) {
// Load value type from constant oop
+ assert(!con_type->maybe_null(), "should never be null");
+ if (field->type()->as_value_klass()->is_scalarizable()) {
con = ValueTypeNode::make_from_oop(this, con, field->type()->as_value_klass());
}
+ }
return con;
}
return NULL;
}
< prev index next >