changeset 13032:963eefaa54a1 mvt

8182585: [MVT] Reading an uninitialized static value type field should not throw a NPE Summary: Trap to interpreter if uninitialized static value type field is read. Reviewed-by: roland
author thartmann
date Fri, 23 Jun 2017 11:14:16 +0200
parents 2552e5001a5d
children c0febf8d6eee
files src/share/vm/opto/graphKit.cpp src/share/vm/opto/parse3.cpp
diffstat 2 files changed, 31 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/opto/graphKit.cpp	Thu Jun 22 21:32:03 2017 +0200
+++ b/src/share/vm/opto/graphKit.cpp	Fri Jun 23 11:14:16 2017 +0200
@@ -1077,6 +1077,7 @@
   switch(type) {
     case T_LONG   : chk = new CmpLNode(value, _gvn.zerocon(T_LONG)); break;
     case T_INT    : chk = new CmpINode(value, _gvn.intcon(0)); break;
+    case T_VALUETYPE : // fall through
     case T_ARRAY  : // fall through
       type = T_OBJECT;  // simplify further tests
     case T_OBJECT : {
@@ -1357,7 +1358,17 @@
   ld = _gvn.transform(ld);
 
   if (bt == T_VALUETYPE) {
-    // Load value type from oop
+    // Load non-flattened value type from memory. Add a null check and let the
+    // interpreter take care of initializing the field to the default value type.
+    Node* null_ctl = top();
+    ld = null_check_common(ld, bt, false, &null_ctl, false);
+    if (null_ctl != top()) {
+      assert(!adr_type->isa_aryptr(), "value type array must be initialized");
+      PreserveJVMState pjvms(this);
+      set_control(null_ctl);
+      uncommon_trap(Deoptimization::reason_null_check(false), Deoptimization::Action_maybe_recompile,
+                    t->is_valuetypeptr()->value_type()->value_klass(), "uninitialized non-flattened value type");
+    }
     ld = ValueTypeNode::make(gvn(), map()->memory(), ld);
   } else if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) {
     // Improve graph before escape analysis and boxing elimination.
--- a/src/share/vm/opto/parse3.cpp	Thu Jun 22 21:32:03 2017 +0200
+++ b/src/share/vm/opto/parse3.cpp	Fri Jun 23 11:14:16 2017 +0200
@@ -177,6 +177,8 @@
 
   ciType* field_klass = field->type();
   bool is_vol = field->is_volatile();
+  // TODO change this when we support non-flattened value type fields that are non-static
+  bool flattened = (bt == T_VALUETYPE) && !field->is_static();
 
   // Compute address and memory type.
   int offset = field->offset_in_bytes();
@@ -204,6 +206,21 @@
       assert(type != NULL, "field singleton type must be consistent");
     } else {
       type = TypeOopPtr::make_from_klass(field_klass->as_klass());
+      if (bt == T_VALUETYPE && !flattened) {
+        // A non-flattened value type field may be NULL
+        bool maybe_null = true;
+        if (field->is_static()) {
+          // Check if static field is already initialized
+          ciInstance* mirror = field->holder()->java_mirror();
+          ciObject* val = mirror->field_value(field).as_object();
+          if (!val->is_null_object()) {
+            maybe_null = false;
+          }
+        }
+        if (maybe_null) {
+          type = type->is_valuetypeptr()->cast_to_ptr_type(TypePtr::BotPTR);
+        }
+      }
     }
   } else {
     type = Type::get_const_basic_type(bt);
@@ -217,8 +234,8 @@
   MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
   bool needs_atomic_access = is_vol || AlwaysAtomicAccesses;
   Node* ld = NULL;
-   if (bt == T_VALUETYPE && !field->is_static()) {
-    // Load flattened value type from non-static field
+   if (flattened) {
+    // Load flattened value type
     ld = ValueTypeNode::make(_gvn, field_klass->as_value_klass(), map()->memory(), obj, obj, field->holder(), offset);
   } else {
     ld = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, needs_atomic_access);