< 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 >