changeset 53564:ca37a22640e7 lworld

8216465: [lworld][c1] null check is needed when reading non-nullable static fields Reviewed-by: thartmann
author iklam
date Wed, 09 Jan 2019 17:22:02 -0800
parents 5e2f5c15f970
children 8bdb4443d68b
files src/hotspot/share/c1/c1_GraphBuilder.cpp src/hotspot/share/c1/c1_Instruction.hpp src/hotspot/share/c1/c1_LIRGenerator.cpp
diffstat 3 files changed, 56 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp	Wed Jan 09 17:03:58 2019 -0800
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp	Wed Jan 09 17:22:02 2019 -0800
@@ -1678,9 +1678,35 @@
   ciInstanceKlass* holder = field->holder();
   BasicType field_type = field->type()->basic_type();
   ValueType* type = as_ValueType(field_type);
+
+  // Null check and deopt for getting static value field
+  ciValueKlass* value_klass = NULL;
+  Value default_value = NULL;
+  bool needs_deopt = false;
+  if (code == Bytecodes::_getstatic && !field->is_static_constant() &&
+      field->layout_type() == T_VALUETYPE) {
+    value_klass = field->type()->as_value_klass();
+    if (holder->is_loaded()) {
+      ciInstance* mirror = field->holder()->java_mirror();
+      ciObject* val = mirror->field_value(field).as_object();
+      if (!val->is_null_object()) {
+        // No need to perform null check on this static field
+        value_klass = NULL;
+      }
+    }
+    if (value_klass != NULL) {
+      if (value_klass->is_loaded()) {
+        default_value = new Constant(new InstanceConstant(value_klass->default_value_instance()));
+      } else {
+        needs_deopt = true;
+      }
+    }
+  }
+
   // call will_link again to determine if the field is valid.
   const bool needs_patching = !holder->is_loaded() ||
                               !field->will_link(method(), code) ||
+                              needs_deopt ||
                               PatchALot;
 
   ValueStack* state_before = NULL;
@@ -1729,7 +1755,8 @@
           state_before = copy_state_for_exception();
         }
         push(type, append(new LoadField(append(obj), offset, field, true,
-                                        state_before, needs_patching)));
+                                        state_before, needs_patching,
+                                        value_klass, default_value)));
       }
       break;
     }
--- a/src/hotspot/share/c1/c1_Instruction.hpp	Wed Jan 09 17:03:58 2019 -0800
+++ b/src/hotspot/share/c1/c1_Instruction.hpp	Wed Jan 09 17:22:02 2019 -0800
@@ -840,17 +840,24 @@
 
 
 LEAF(LoadField, AccessField)
+  ciValueKlass* _value_klass;
+  Value _default_value;
  public:
   // creation
   LoadField(Value obj, int offset, ciField* field, bool is_static,
-            ValueStack* state_before, bool needs_patching)
+            ValueStack* state_before, bool needs_patching,
+            ciValueKlass* value_klass = NULL, Value default_value = NULL )
   : AccessField(obj, offset, field, is_static, state_before, needs_patching)
+  , _value_klass(value_klass), _default_value(default_value)
   {}
 
   ciType* declared_type() const;
 
   // generic
   HASHING2(LoadField, !needs_patching() && !field()->is_volatile(), obj()->subst(), offset())  // cannot be eliminated if needs patching or if volatile
+
+  ciValueKlass* value_klass() const { return _value_klass;}
+  Value default_value() const { return _default_value; }
 };
 
 
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp	Wed Jan 09 17:03:58 2019 -0800
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp	Wed Jan 09 17:22:02 2019 -0800
@@ -1876,6 +1876,14 @@
       // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code.
       __ null_check(obj, new CodeEmitInfo(info), /* deoptimize */ needs_patching);
     }
+  } else if (x->value_klass() != NULL && x->default_value() == NULL) {
+    assert(x->is_static() && !x->value_klass()->is_loaded(), "must be");
+    assert(needs_patching, "must be");
+    // The value klass was not loaded so we don't know what its default value should be
+    CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info),
+                                        Deoptimization::Reason_unloaded,
+                                        Deoptimization::Action_make_not_entrant);
+    __ branch(lir_cond_always, T_ILLEGAL, stub);
   }
 
   DecoratorSet decorators = IN_HEAP;
@@ -1890,6 +1898,18 @@
   access_load_at(decorators, field_type,
                  object, LIR_OprFact::intConst(x->offset()), result,
                  info ? new CodeEmitInfo(info) : NULL, info);
+
+  if (x->value_klass() != NULL && x->default_value() != NULL) {
+    LabelObj* L_end = new LabelObj();
+    __ cmp(lir_cond_notEqual, result, LIR_OprFact::oopConst(NULL));
+    __ branch(lir_cond_notEqual, T_OBJECT, L_end->label());
+
+    LIRItem default_value(x->default_value(), this);
+    default_value.load_item();
+    __ move(default_value.result(), result);
+
+    __ branch_destination(L_end->label());
+  }
 }