8152590: C2: @Stable support doesn't always work w/ incremental inlining
authorvlivanov
Mon, 11 Apr 2016 21:42:55 +0300
changeset 38030 93f24e7b3c43
parent 38029 c645d414429f
child 38031 e0b822facc03
8152590: C2: @Stable support doesn't always work w/ incremental inlining Reviewed-by: kvn
hotspot/src/share/vm/c1/c1_Canonicalizer.cpp
hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
hotspot/src/share/vm/ci/ciConstant.hpp
hotspot/src/share/vm/ci/ciField.cpp
hotspot/src/share/vm/ci/ciField.hpp
hotspot/src/share/vm/ci/ciInstance.cpp
hotspot/src/share/vm/ci/ciInstance.hpp
hotspot/src/share/vm/ci/ciKlass.cpp
hotspot/src/share/vm/ci/ciSymbol.cpp
hotspot/src/share/vm/opto/graphKit.cpp
hotspot/src/share/vm/opto/graphKit.hpp
hotspot/src/share/vm/opto/library_call.cpp
hotspot/src/share/vm/opto/macro.cpp
hotspot/src/share/vm/opto/memnode.cpp
hotspot/src/share/vm/opto/parse3.cpp
hotspot/src/share/vm/opto/stringopts.cpp
hotspot/src/share/vm/opto/type.cpp
hotspot/src/share/vm/opto/type.hpp
hotspot/test/compiler/unsafe/UnsafeGetConstantField.java
hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -247,7 +247,7 @@
 
   } else if ((lf = x->array()->as_LoadField()) != NULL) {
     ciField* field = lf->field();
-    if (field->is_constant() && field->is_static()) {
+    if (field->is_static_constant()) {
       assert(PatchALot || ScavengeRootsInCode < 2, "Constant field loads are folded during parsing");
       ciObject* c = field->constant_value().as_object();
       if (!c->is_null_object()) {
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -1520,6 +1520,8 @@
 }
 
 Value GraphBuilder::make_constant(ciConstant field_value, ciField* field) {
+  if (!field_value.is_valid())  return NULL;
+
   BasicType field_type = field_value.basic_type();
   ValueType* value = as_ValueType(field_value);
 
@@ -1587,9 +1589,8 @@
     case Bytecodes::_getstatic: {
       // check for compile-time constants, i.e., initialized static final fields
       Value constant = NULL;
-      if (field->is_constant() && !PatchALot) {
+      if (field->is_static_constant() && !PatchALot) {
         ciConstant field_value = field->constant_value();
-        // Stable static fields are checked for non-default values in ciField::initialize_from().
         assert(!field->is_stable() || !field_value.is_null_or_zero(),
                "stable static w/ default value shouldn't be a constant");
         constant = make_constant(field_value, field);
@@ -1618,31 +1619,18 @@
       Value constant = NULL;
       obj = apop();
       ObjectType* obj_type = obj->type()->as_ObjectType();
-      if (obj_type->is_constant() && !PatchALot) {
+      if (field->is_constant() && obj_type->is_constant() && !PatchALot) {
         ciObject* const_oop = obj_type->constant_value();
         if (!const_oop->is_null_object() && const_oop->is_loaded()) {
-          if (field->is_constant()) {
-            ciConstant field_value = field->constant_value_of(const_oop);
-            if (FoldStableValues && field->is_stable() && field_value.is_null_or_zero()) {
-              // Stable field with default value can't be constant.
-              constant = NULL;
-            } else {
-              constant = make_constant(field_value, field);
-            }
-          } else {
-            // For CallSite objects treat the target field as a compile time constant.
-            if (const_oop->is_call_site()) {
+          ciConstant field_value = field->constant_value_of(const_oop);
+          if (field_value.is_valid()) {
+            constant = make_constant(field_value, field);
+            // For CallSite objects add a dependency for invalidation of the optimization.
+            if (field->is_call_site_target()) {
               ciCallSite* call_site = const_oop->as_call_site();
-              if (field->is_call_site_target()) {
-                ciMethodHandle* target = call_site->get_target();
-                if (target != NULL) {  // just in case
-                  ciConstant field_val(T_OBJECT, target);
-                  constant = new Constant(as_ValueType(field_val));
-                  // Add a dependence for invalidation of the optimization.
-                  if (!call_site->is_constant_call_site()) {
-                    dependency_recorder()->assert_call_site_target_value(call_site, target);
-                  }
-                }
+              if (!call_site->is_constant_call_site()) {
+                ciMethodHandle* target = field_value.as_object()->as_method_handle();
+                dependency_recorder()->assert_call_site_target_value(call_site, target);
               }
             }
           }
--- a/hotspot/src/share/vm/ci/ciConstant.hpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/ci/ciConstant.hpp	Mon Apr 11 21:42:55 2016 +0300
@@ -124,6 +124,9 @@
     }
   }
 
+  bool is_valid() const {
+    return basic_type() != T_ILLEGAL;
+  }
   // Debugging output
   void print();
 };
--- a/hotspot/src/share/vm/ci/ciField.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/ci/ciField.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -235,94 +235,75 @@
   _holder = CURRENT_ENV->get_instance_klass(fd->field_holder());
 
   // Check to see if the field is constant.
-  bool is_final = this->is_final();
-  bool is_stable = FoldStableValues && this->is_stable();
-  if (_holder->is_initialized() && (is_final || is_stable)) {
-    if (!this->is_static()) {
-      // A field can be constant if it's a final static field or if
+  Klass* k = _holder->get_Klass();
+  bool is_stable_field = FoldStableValues && is_stable();
+  if (is_final() || is_stable_field) {
+    if (is_static()) {
+      // This field just may be constant.  The only case where it will
+      // not be constant is when the field is a *special* static & final field
+      // whose value may change.  The three examples are java.lang.System.in,
+      // java.lang.System.out, and java.lang.System.err.
+      assert(SystemDictionary::System_klass() != NULL, "Check once per vm");
+      if (k == SystemDictionary::System_klass()) {
+        // Check offsets for case 2: System.in, System.out, or System.err
+        if( _offset == java_lang_System::in_offset_in_bytes()  ||
+            _offset == java_lang_System::out_offset_in_bytes() ||
+            _offset == java_lang_System::err_offset_in_bytes() ) {
+          _is_constant = false;
+          return;
+        }
+      }
+      _is_constant = true;
+    } else {
+      // An instance field can be constant if it's a final static field or if
       // it's a final non-static field of a trusted class (classes in
       // java.lang.invoke and sun.invoke packages and subpackages).
-      if (is_stable || trust_final_non_static_fields(_holder)) {
-        _is_constant = true;
-        return;
-      }
-      _is_constant = false;
-      return;
-    }
-
-    // This field just may be constant.  The only case where it will
-    // not be constant is when the field is a *special* static&final field
-    // whose value may change.  The three examples are java.lang.System.in,
-    // java.lang.System.out, and java.lang.System.err.
-
-    KlassHandle k = _holder->get_Klass();
-    assert( SystemDictionary::System_klass() != NULL, "Check once per vm");
-    if( k() == SystemDictionary::System_klass() ) {
-      // Check offsets for case 2: System.in, System.out, or System.err
-      if( _offset == java_lang_System::in_offset_in_bytes()  ||
-          _offset == java_lang_System::out_offset_in_bytes() ||
-          _offset == java_lang_System::err_offset_in_bytes() ) {
-        _is_constant = false;
-        return;
-      }
-    }
-
-    Handle mirror = k->java_mirror();
-
-    switch(type()->basic_type()) {
-    case T_BYTE:
-      _constant_value = ciConstant(type()->basic_type(), mirror->byte_field(_offset));
-      break;
-    case T_CHAR:
-      _constant_value = ciConstant(type()->basic_type(), mirror->char_field(_offset));
-      break;
-    case T_SHORT:
-      _constant_value = ciConstant(type()->basic_type(), mirror->short_field(_offset));
-      break;
-    case T_BOOLEAN:
-      _constant_value = ciConstant(type()->basic_type(), mirror->bool_field(_offset));
-      break;
-    case T_INT:
-      _constant_value = ciConstant(type()->basic_type(), mirror->int_field(_offset));
-      break;
-    case T_FLOAT:
-      _constant_value = ciConstant(mirror->float_field(_offset));
-      break;
-    case T_DOUBLE:
-      _constant_value = ciConstant(mirror->double_field(_offset));
-      break;
-    case T_LONG:
-      _constant_value = ciConstant(mirror->long_field(_offset));
-      break;
-    case T_OBJECT:
-    case T_ARRAY:
-      {
-        oop o = mirror->obj_field(_offset);
-
-        // A field will be "constant" if it is known always to be
-        // a non-null reference to an instance of a particular class,
-        // or to a particular array.  This can happen even if the instance
-        // or array is not perm.  In such a case, an "unloaded" ciArray
-        // or ciInstance is created.  The compiler may be able to use
-        // information about the object's class (which is exact) or length.
-
-        if (o == NULL) {
-          _constant_value = ciConstant(type()->basic_type(), ciNullObject::make());
-        } else {
-          _constant_value = ciConstant(type()->basic_type(), CURRENT_ENV->get_object(o));
-          assert(_constant_value.as_object() == CURRENT_ENV->get_object(o), "check interning");
-        }
-      }
-    }
-    if (is_stable && _constant_value.is_null_or_zero()) {
-      // It is not a constant after all; treat it as uninitialized.
-      _is_constant = false;
-    } else {
-      _is_constant = true;
+      _is_constant = is_stable_field || trust_final_non_static_fields(_holder);
     }
   } else {
-    _is_constant = false;
+    // For CallSite objects treat the target field as a compile time constant.
+    assert(SystemDictionary::CallSite_klass() != NULL, "should be already initialized");
+    if (k == SystemDictionary::CallSite_klass() &&
+        _offset == java_lang_invoke_CallSite::target_offset_in_bytes()) {
+      _is_constant = true;
+    } else {
+      // Non-final & non-stable fields are not constants.
+      _is_constant = false;
+    }
+  }
+}
+
+// ------------------------------------------------------------------
+// ciField::constant_value
+// Get the constant value of a this static field.
+ciConstant ciField::constant_value() {
+  assert(is_static() && is_constant(), "illegal call to constant_value()");
+  if (!_holder->is_initialized()) {
+    return ciConstant(); // Not initialized yet
   }
+  if (_constant_value.basic_type() == T_ILLEGAL) {
+    // Static fields are placed in mirror objects.
+    VM_ENTRY_MARK;
+    ciInstance* mirror = CURRENT_ENV->get_instance(_holder->get_Klass()->java_mirror());
+    _constant_value = mirror->field_value_impl(type()->basic_type(), offset());
+  }
+  if (FoldStableValues && is_stable() && _constant_value.is_null_or_zero()) {
+    return ciConstant();
+  }
+  return _constant_value;
+}
+
+// ------------------------------------------------------------------
+// ciField::constant_value_of
+// Get the constant value of non-static final field in the given object.
+ciConstant ciField::constant_value_of(ciObject* object) {
+  assert(!is_static() && is_constant(), "only if field is non-static constant");
+  assert(object->is_instance(), "must be instance");
+  ciConstant field_value = object->as_instance()->field_value(this);
+  if (FoldStableValues && is_stable() && field_value.is_null_or_zero()) {
+    return ciConstant();
+  }
+  return field_value;
 }
 
 // ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciField.hpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/ci/ciField.hpp	Mon Apr 11 21:42:55 2016 +0300
@@ -62,7 +62,7 @@
   void initialize_from(fieldDescriptor* fd);
 
 public:
-  ciFlags flags() { return _flags; }
+  ciFlags flags() const { return _flags; }
 
   // Of which klass is this field a member?
   //
@@ -89,13 +89,13 @@
   //
   //   In that case the declared holder of f would be B and
   //   the canonical holder of f would be A.
-  ciInstanceKlass* holder() { return _holder; }
+  ciInstanceKlass* holder() const { return _holder; }
 
   // Name of this field?
-  ciSymbol* name() { return _name; }
+  ciSymbol* name() const { return _name; }
 
   // Signature of this field?
-  ciSymbol* signature() { return _signature; }
+  ciSymbol* signature() const { return _signature; }
 
   // Of what type is this field?
   ciType* type() { return (_type == NULL) ? compute_type() : _type; }
@@ -107,13 +107,13 @@
   int size_in_bytes() { return type2aelembytes(layout_type()); }
 
   // What is the offset of this field?
-  int offset() {
+  int offset() const {
     assert(_offset >= 1, "illegal call to offset()");
     return _offset;
   }
 
   // Same question, explicit units.  (Fields are aligned to the byte level.)
-  int offset_in_bytes() {
+  int offset_in_bytes() const {
     return offset();
   }
 
@@ -127,31 +127,27 @@
   //
   // Clarification: A field is considered constant if:
   //   1. The field is both static and final
-  //   2. The canonical holder of the field has undergone
-  //      static initialization.
-  //   3. The field is not one of the special static/final
+  //   2. The field is not one of the special static/final
   //      non-constant fields.  These are java.lang.System.in
   //      and java.lang.System.out.  Abomination.
   //
   // A field is also considered constant if it is marked @Stable
   // and is non-null (or non-zero, if a primitive).
-  // For non-static fields, the null/zero check must be
-  // arranged by the user, as constant_value().is_null_or_zero().
-  bool is_constant() { return _is_constant; }
+  //
+  // A user should also check the field value (constant_value().is_valid()), since
+  // constant fields of non-initialized classes don't have values yet.
+  bool is_constant() const { return _is_constant; }
 
-  // Get the constant value of this field.
-  ciConstant constant_value() {
-    assert(is_static() && is_constant(), "illegal call to constant_value()");
-    return _constant_value;
+  // Get the constant value of the static field.
+  ciConstant constant_value();
+
+  bool is_static_constant() {
+    return is_static() && is_constant() && constant_value().is_valid();
   }
 
   // Get the constant value of non-static final field in the given
   // object.
-  ciConstant constant_value_of(ciObject* object) {
-    assert(!is_static() && is_constant(), "only if field is non-static constant");
-    assert(object->is_instance(), "must be instance");
-    return object->as_instance()->field_value(this);
-  }
+  ciConstant constant_value_of(ciObject* object);
 
   // Check for link time errors.  Accessing a field from a
   // certain class via a certain bytecode may or may not be legal.
@@ -165,14 +161,14 @@
                  Bytecodes::Code bc);
 
   // Java access flags
-  bool is_public      () { return flags().is_public(); }
-  bool is_private     () { return flags().is_private(); }
-  bool is_protected   () { return flags().is_protected(); }
-  bool is_static      () { return flags().is_static(); }
-  bool is_final       () { return flags().is_final(); }
-  bool is_stable      () { return flags().is_stable(); }
-  bool is_volatile    () { return flags().is_volatile(); }
-  bool is_transient   () { return flags().is_transient(); }
+  bool is_public      () const { return flags().is_public(); }
+  bool is_private     () const { return flags().is_private(); }
+  bool is_protected   () const { return flags().is_protected(); }
+  bool is_static      () const { return flags().is_static(); }
+  bool is_final       () const { return flags().is_final(); }
+  bool is_stable      () const { return flags().is_stable(); }
+  bool is_volatile    () const { return flags().is_volatile(); }
+  bool is_transient   () const { return flags().is_transient(); }
 
   bool is_call_site_target() {
     ciInstanceKlass* callsite_klass = CURRENT_ENV->CallSite_klass();
--- a/hotspot/src/share/vm/ci/ciInstance.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/ci/ciInstance.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -56,49 +56,21 @@
 }
 
 // ------------------------------------------------------------------
-// ciInstance::field_value
-//
-// Constant value of a field.
-ciConstant ciInstance::field_value(ciField* field) {
-  assert(is_loaded(), "invalid access - must be loaded");
-  assert(field->holder()->is_loaded(), "invalid access - holder must be loaded");
-  assert(klass()->is_subclass_of(field->holder()), "invalid access - must be subclass");
-
-  VM_ENTRY_MARK;
-  ciConstant result;
+// ciInstance::field_value_impl
+ciConstant ciInstance::field_value_impl(BasicType field_btype, int offset) {
   Handle obj = get_oop();
   assert(!obj.is_null(), "bad oop");
-  BasicType field_btype = field->type()->basic_type();
-  int offset = field->offset();
-
   switch(field_btype) {
-  case T_BYTE:
-    return ciConstant(field_btype, obj->byte_field(offset));
-    break;
-  case T_CHAR:
-    return ciConstant(field_btype, obj->char_field(offset));
-    break;
-  case T_SHORT:
-    return ciConstant(field_btype, obj->short_field(offset));
-    break;
-  case T_BOOLEAN:
-    return ciConstant(field_btype, obj->bool_field(offset));
-    break;
-  case T_INT:
-    return ciConstant(field_btype, obj->int_field(offset));
-    break;
-  case T_FLOAT:
-    return ciConstant(obj->float_field(offset));
-    break;
-  case T_DOUBLE:
-    return ciConstant(obj->double_field(offset));
-    break;
-  case T_LONG:
-    return ciConstant(obj->long_field(offset));
-    break;
-  case T_OBJECT:
-  case T_ARRAY:
-    {
+    case T_BYTE:    return ciConstant(field_btype, obj->byte_field(offset));
+    case T_CHAR:    return ciConstant(field_btype, obj->char_field(offset));
+    case T_SHORT:   return ciConstant(field_btype, obj->short_field(offset));
+    case T_BOOLEAN: return ciConstant(field_btype, obj->bool_field(offset));
+    case T_INT:     return ciConstant(field_btype, obj->int_field(offset));
+    case T_FLOAT:   return ciConstant(obj->float_field(offset));
+    case T_DOUBLE:  return ciConstant(obj->double_field(offset));
+    case T_LONG:    return ciConstant(obj->long_field(offset));
+    case T_OBJECT:  // fall through
+    case T_ARRAY: {
       oop o = obj->obj_field(offset);
 
       // A field will be "constant" if it is known always to be
@@ -115,12 +87,23 @@
       }
     }
   }
-  ShouldNotReachHere();
-  // to shut up the compiler
+  fatal("no field value: %s", type2name(field_btype));
   return ciConstant();
 }
 
 // ------------------------------------------------------------------
+// ciInstance::field_value
+//
+// Constant value of a field.
+ciConstant ciInstance::field_value(ciField* field) {
+  assert(is_loaded(), "invalid access - must be loaded");
+  assert(field->holder()->is_loaded(), "invalid access - holder must be loaded");
+  assert(field->is_static() || klass()->is_subclass_of(field->holder()), "invalid access - must be subclass");
+
+  GUARDED_VM_ENTRY(return field_value_impl(field->type()->basic_type(), field->offset());)
+}
+
+// ------------------------------------------------------------------
 // ciInstance::field_value_by_offset
 //
 // Constant value of a field at the specified offset.
--- a/hotspot/src/share/vm/ci/ciInstance.hpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/ci/ciInstance.hpp	Mon Apr 11 21:42:55 2016 +0300
@@ -36,6 +36,7 @@
 // instance of java.lang.Object.
 class ciInstance : public ciObject {
   CI_PACKAGE_ACCESS
+  friend class ciField;
 
 protected:
   ciInstance(instanceHandle h_i) : ciObject(h_i) {
@@ -50,6 +51,8 @@
 
   void print_impl(outputStream* st);
 
+  ciConstant field_value_impl(BasicType field_btype, int offset);
+
 public:
   // If this object is a java mirror, return the corresponding type.
   // Otherwise, return NULL.
--- a/hotspot/src/share/vm/ci/ciKlass.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/ci/ciKlass.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -88,12 +88,7 @@
   assert(this->is_loaded(), "must be loaded: %s", this->name()->as_quoted_ascii());
   assert(that->is_loaded(), "must be loaded: %s", that->name()->as_quoted_ascii());
 
-  VM_ENTRY_MARK;
-  Klass* this_klass = get_Klass();
-  Klass* that_klass = that->get_Klass();
-  bool result = this_klass->is_subclass_of(that_klass);
-
-  return result;
+  GUARDED_VM_ENTRY(return get_Klass()->is_subclass_of(that->get_Klass());)
 }
 
 // ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciSymbol.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/ci/ciSymbol.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -58,9 +58,7 @@
 //
 // The text of the symbol as a null-terminated C string.
 const char* ciSymbol::as_utf8() {
-  VM_QUICK_ENTRY_MARK;
-  Symbol* s = get_symbol();
-  return s->as_utf8();
+  GUARDED_VM_QUICK_ENTRY(return get_symbol()->as_utf8();)
 }
 
 // The text of the symbol as a null-terminated C string.
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -4466,6 +4466,25 @@
   set_memory(st, TypeAryPtr::BYTES);
 }
 
+Node* GraphKit::make_constant_from_field(ciField* field, Node* obj) {
+  if (!field->is_constant()) {
+    return NULL; // Field not marked as constant.
+  }
+  ciInstance* holder = NULL;
+  if (!field->is_static()) {
+    ciObject* const_oop = obj->bottom_type()->is_oopptr()->const_oop();
+    if (const_oop != NULL && const_oop->is_instance()) {
+      holder = const_oop->as_instance();
+    }
+  }
+  const Type* con_type = Type::make_constant_from_field(field, holder, field->layout_type(),
+                                                        /*is_unsigned_load=*/false);
+  if (con_type != NULL) {
+    return makecon(con_type);
+  }
+  return NULL;
+}
+
 Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) {
   // Reify the property as a CastPP node in Ideal graph to comply with monotonicity
   // assumption of CCP analysis.
--- a/hotspot/src/share/vm/opto/graphKit.hpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/opto/graphKit.hpp	Mon Apr 11 21:42:55 2016 +0300
@@ -910,6 +910,8 @@
   void add_predicate(int nargs = 0);
   void add_predicate_impl(Deoptimization::DeoptReason reason, int nargs);
 
+  Node* make_constant_from_field(ciField* field, Node* obj);
+
   // Produce new array node of stable type
   Node* cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type);
 };
--- a/hotspot/src/share/vm/opto/library_call.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -2550,13 +2550,9 @@
     Node* p = NULL;
     // Try to constant fold a load from a constant field
     ciField* field = alias_type->field();
-    if (heap_base_oop != top() &&
-        field != NULL && field->is_constant() && !mismatched) {
+    if (heap_base_oop != top() && field != NULL && field->is_constant() && !mismatched) {
       // final or stable field
-      const Type* con_type = Type::make_constant(alias_type->field(), heap_base_oop);
-      if (con_type != NULL) {
-        p = makecon(con_type);
-      }
+      p = make_constant_from_field(field, heap_base_oop);
     }
     if (p == NULL) {
       // To be valid, unsafe loads may depend on other conditions than
--- a/hotspot/src/share/vm/opto/macro.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/opto/macro.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -860,7 +860,7 @@
       if (basic_elem_type == T_OBJECT || basic_elem_type == T_ARRAY) {
         if (!elem_type->is_loaded()) {
           field_type = TypeInstPtr::BOTTOM;
-        } else if (field != NULL && field->is_constant() && field->is_static()) {
+        } else if (field != NULL && field->is_static_constant()) {
           // This can happen if the constant oop is non-perm.
           ciObject* con = field->constant_value().as_object();
           // Do not "join" in the previous type; it doesn't add value,
--- a/hotspot/src/share/vm/opto/memnode.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -796,7 +796,7 @@
 #endif
     {
       assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop");
-      load = new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo, control_dependency);
+      load = new LoadPNode(ctl, mem, adr, adr_type, rt->is_ptr(), mo, control_dependency);
     }
     break;
   }
@@ -1620,72 +1620,6 @@
   return NULL;
 }
 
-static ciConstant check_mismatched_access(ciConstant con, BasicType loadbt, bool is_unsigned) {
-  BasicType conbt = con.basic_type();
-  switch (conbt) {
-    case T_BOOLEAN: conbt = T_BYTE;   break;
-    case T_ARRAY:   conbt = T_OBJECT; break;
-  }
-  switch (loadbt) {
-    case T_BOOLEAN:   loadbt = T_BYTE;   break;
-    case T_NARROWOOP: loadbt = T_OBJECT; break;
-    case T_ARRAY:     loadbt = T_OBJECT; break;
-    case T_ADDRESS:   loadbt = T_OBJECT; break;
-  }
-  if (conbt == loadbt) {
-    if (is_unsigned && conbt == T_BYTE) {
-      // LoadB (T_BYTE) with a small mask (<=8-bit) is converted to LoadUB (T_BYTE).
-      return ciConstant(T_INT, con.as_int() & 0xFF);
-    } else {
-      return con;
-    }
-  }
-  if (conbt == T_SHORT && loadbt == T_CHAR) {
-    // LoadS (T_SHORT) with a small mask (<=16-bit) is converted to LoadUS (T_CHAR).
-    return ciConstant(T_INT, con.as_int() & 0xFFFF);
-  }
-  return ciConstant(); // T_ILLEGAL
-}
-
-// Try to constant-fold a stable array element.
-static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, bool is_unsigned_load, BasicType loadbt) {
-  assert(ary->const_oop(), "array should be constant");
-  assert(ary->is_stable(), "array should be stable");
-
-  // Decode the results of GraphKit::array_element_address.
-  ciArray* aobj = ary->const_oop()->as_array();
-  ciConstant element_value = aobj->element_value_by_offset(off);
-  if (element_value.basic_type() == T_ILLEGAL) {
-    return NULL; // wrong offset
-  }
-  ciConstant con = check_mismatched_access(element_value, loadbt, is_unsigned_load);
-  assert(con.basic_type() != T_ILLEGAL, "elembt=%s; loadbt=%s; unsigned=%d",
-         type2name(element_value.basic_type()), type2name(loadbt), is_unsigned_load);
-
-  if (con.basic_type() != T_ILLEGAL && // not a mismatched access
-      !con.is_null_or_zero()) {        // not a default value
-    const Type* con_type = Type::make_from_constant(con);
-    if (con_type != NULL) {
-      if (con_type->isa_aryptr()) {
-        // Join with the array element type, in case it is also stable.
-        int dim = ary->stable_dimension();
-        con_type = con_type->is_aryptr()->cast_to_stable(true, dim-1);
-      }
-      if (loadbt == T_NARROWOOP && con_type->isa_oopptr()) {
-        con_type = con_type->make_narrowoop();
-      }
-#ifndef PRODUCT
-      if (TraceIterativeGVN) {
-        tty->print("FoldStableValues: array element [off=%d]: con_type=", off);
-        con_type->dump(); tty->cr();
-      }
-#endif //PRODUCT
-      return con_type;
-    }
-  }
-  return NULL;
-}
-
 //------------------------------Value-----------------------------------------
 const Type* LoadNode::Value(PhaseGVN* phase) const {
   // Either input is TOP ==> the result is TOP
@@ -1714,10 +1648,14 @@
     const bool off_beyond_header = ((uint)off >= (uint)min_base_off);
 
     // Try to constant-fold a stable array element.
-    if (FoldStableValues && !is_mismatched_access() && ary->is_stable() && ary->const_oop() != NULL) {
+    if (FoldStableValues && !is_mismatched_access() && ary->is_stable()) {
       // Make sure the reference is not into the header and the offset is constant
-      if (off_beyond_header && adr->is_AddP() && off != Type::OffsetBot) {
-        const Type* con_type = fold_stable_ary_elem(ary, off, is_unsigned(), memory_type());
+      ciObject* aobj = ary->const_oop();
+      if (aobj != NULL && off_beyond_header && adr->is_AddP() && off != Type::OffsetBot) {
+        int stable_dimension = (ary->stable_dimension() > 0 ? ary->stable_dimension() - 1 : 0);
+        const Type* con_type = Type::make_constant_from_array_element(aobj->as_array(), off,
+                                                                      stable_dimension,
+                                                                      memory_type(), is_unsigned());
         if (con_type != NULL) {
           return con_type;
         }
@@ -1784,28 +1722,10 @@
     // For oop loads, we expect the _type to be precise.
     // Optimizations for constant objects
     ciObject* const_oop = tinst->const_oop();
-    if (const_oop != NULL) {
-      // For constant CallSites treat the target field as a compile time constant.
-      if (const_oop->is_call_site()) {
-        ciCallSite* call_site = const_oop->as_call_site();
-        ciField* field = call_site->klass()->as_instance_klass()->get_field_by_offset(off, /*is_static=*/ false);
-        if (field != NULL && field->is_call_site_target()) {
-          ciMethodHandle* target = call_site->get_target();
-          if (target != NULL) {  // just in case
-            ciConstant constant(T_OBJECT, target);
-            const Type* t;
-            if (adr->bottom_type()->is_ptr_to_narrowoop()) {
-              t = TypeNarrowOop::make_from_constant(constant.as_object(), true);
-            } else {
-              t = TypeOopPtr::make_from_constant(constant.as_object(), true);
-            }
-            // Add a dependence for invalidation of the optimization.
-            if (!call_site->is_constant_call_site()) {
-              C->dependencies()->assert_call_site_target_value(call_site, target);
-            }
-            return t;
-          }
-        }
+    if (const_oop != NULL && const_oop->is_instance()) {
+      const Type* con_type = Type::make_constant_from_field(const_oop->as_instance(), off, is_unsigned(), memory_type());
+      if (con_type != NULL) {
+        return con_type;
       }
     }
   } else if (tp->base() == Type::KlassPtr) {
--- a/hotspot/src/share/vm/opto/parse3.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/opto/parse3.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -149,9 +149,9 @@
   // Does this field have a constant value?  If so, just push the value.
   if (field->is_constant()) {
     // final or stable field
-    const Type* con_type = Type::make_constant(field, obj);
-    if (con_type != NULL) {
-      push_node(con_type->basic_type(), makecon(con_type));
+    Node* con = make_constant_from_field(field, obj);
+    if (con != NULL) {
+      push_node(field->layout_type(), con);
       return;
     }
   }
@@ -174,12 +174,16 @@
     if (!field->type()->is_loaded()) {
       type = TypeInstPtr::BOTTOM;
       must_assert_null = true;
-    } else if (field->is_constant() && field->is_static()) {
+    } else if (field->is_static_constant()) {
       // This can happen if the constant oop is non-perm.
       ciObject* con = field->constant_value().as_object();
       // Do not "join" in the previous type; it doesn't add value,
       // and may yield a vacuous result if the field is of interface type.
-      type = TypeOopPtr::make_from_constant(con)->isa_oopptr();
+      if (con->is_null_object()) {
+        type = TypePtr::NULL_PTR;
+      } else {
+        type = TypeOopPtr::make_from_constant(con)->isa_oopptr();
+      }
       assert(type != NULL, "field singleton type must be consistent");
     } else {
       type = TypeOopPtr::make_from_klass(field_klass->as_klass());
--- a/hotspot/src/share/vm/opto/stringopts.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/opto/stringopts.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -1112,7 +1112,7 @@
   if( bt == T_OBJECT ) {
     if (!field->type()->is_loaded()) {
       type = TypeInstPtr::BOTTOM;
-    } else if (field->is_constant()) {
+    } else if (field->is_static_constant()) {
       // This can happen if the constant oop is non-perm.
       ciObject* con = field->constant_value().as_object();
       // Do not "join" in the previous type; it doesn't add value,
--- a/hotspot/src/share/vm/opto/type.cpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/opto/type.cpp	Mon Apr 11 21:42:55 2016 +0300
@@ -225,74 +225,156 @@
 
 
 //-----------------------make_from_constant------------------------------------
-const Type* Type::make_from_constant(ciConstant constant, bool require_constant) {
+const Type* Type::make_from_constant(ciConstant constant, bool require_constant,
+                                     int stable_dimension, bool is_narrow_oop,
+                                     bool is_autobox_cache) {
   switch (constant.basic_type()) {
-  case T_BOOLEAN:  return TypeInt::make(constant.as_boolean());
-  case T_CHAR:     return TypeInt::make(constant.as_char());
-  case T_BYTE:     return TypeInt::make(constant.as_byte());
-  case T_SHORT:    return TypeInt::make(constant.as_short());
-  case T_INT:      return TypeInt::make(constant.as_int());
-  case T_LONG:     return TypeLong::make(constant.as_long());
-  case T_FLOAT:    return TypeF::make(constant.as_float());
-  case T_DOUBLE:   return TypeD::make(constant.as_double());
-  case T_ARRAY:
-  case T_OBJECT:
-    {
-      // cases:
-      //   can_be_constant    = (oop not scavengable || ScavengeRootsInCode != 0)
-      //   should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
-      // An oop is not scavengable if it is in the perm gen.
-      ciObject* oop_constant = constant.as_object();
-      if (oop_constant->is_null_object()) {
-        return Type::get_zero_type(T_OBJECT);
-      } else if (require_constant || oop_constant->should_be_constant()) {
-        return TypeOopPtr::make_from_constant(oop_constant, require_constant);
+    case T_BOOLEAN:  return TypeInt::make(constant.as_boolean());
+    case T_CHAR:     return TypeInt::make(constant.as_char());
+    case T_BYTE:     return TypeInt::make(constant.as_byte());
+    case T_SHORT:    return TypeInt::make(constant.as_short());
+    case T_INT:      return TypeInt::make(constant.as_int());
+    case T_LONG:     return TypeLong::make(constant.as_long());
+    case T_FLOAT:    return TypeF::make(constant.as_float());
+    case T_DOUBLE:   return TypeD::make(constant.as_double());
+    case T_ARRAY:
+    case T_OBJECT: {
+        // cases:
+        //   can_be_constant    = (oop not scavengable || ScavengeRootsInCode != 0)
+        //   should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
+        // An oop is not scavengable if it is in the perm gen.
+        const Type* con_type = NULL;
+        ciObject* oop_constant = constant.as_object();
+        if (oop_constant->is_null_object()) {
+          con_type = Type::get_zero_type(T_OBJECT);
+        } else if (require_constant || oop_constant->should_be_constant()) {
+          con_type = TypeOopPtr::make_from_constant(oop_constant, require_constant);
+          if (con_type != NULL) {
+            if (Compile::current()->eliminate_boxing() && is_autobox_cache) {
+              con_type = con_type->is_aryptr()->cast_to_autobox_cache(true);
+            }
+            if (stable_dimension > 0) {
+              assert(FoldStableValues, "sanity");
+              assert(!con_type->is_zero_type(), "default value for stable field");
+              con_type = con_type->is_aryptr()->cast_to_stable(true, stable_dimension);
+            }
+          }
+        }
+        if (is_narrow_oop) {
+          con_type = con_type->make_narrowoop();
+        }
+        return con_type;
       }
-    }
-  case T_ILLEGAL:
-    // Invalid ciConstant returned due to OutOfMemoryError in the CI
-    assert(Compile::current()->env()->failing(), "otherwise should not see this");
-    return NULL;
+    case T_ILLEGAL:
+      // Invalid ciConstant returned due to OutOfMemoryError in the CI
+      assert(Compile::current()->env()->failing(), "otherwise should not see this");
+      return NULL;
   }
   // Fall through to failure
   return NULL;
 }
 
-
-const Type* Type::make_constant(ciField* field, Node* obj) {
-  if (!field->is_constant())  return NULL;
-
-  const Type* con_type = NULL;
+static ciConstant check_mismatched_access(ciConstant con, BasicType loadbt, bool is_unsigned) {
+  BasicType conbt = con.basic_type();
+  switch (conbt) {
+    case T_BOOLEAN: conbt = T_BYTE;   break;
+    case T_ARRAY:   conbt = T_OBJECT; break;
+  }
+  switch (loadbt) {
+    case T_BOOLEAN:   loadbt = T_BYTE;   break;
+    case T_NARROWOOP: loadbt = T_OBJECT; break;
+    case T_ARRAY:     loadbt = T_OBJECT; break;
+    case T_ADDRESS:   loadbt = T_OBJECT; break;
+  }
+  if (conbt == loadbt) {
+    if (is_unsigned && conbt == T_BYTE) {
+      // LoadB (T_BYTE) with a small mask (<=8-bit) is converted to LoadUB (T_BYTE).
+      return ciConstant(T_INT, con.as_int() & 0xFF);
+    } else {
+      return con;
+    }
+  }
+  if (conbt == T_SHORT && loadbt == T_CHAR) {
+    // LoadS (T_SHORT) with a small mask (<=16-bit) is converted to LoadUS (T_CHAR).
+    return ciConstant(T_INT, con.as_int() & 0xFFFF);
+  }
+  return ciConstant(); // T_ILLEGAL
+}
+
+// Try to constant-fold a stable array element.
+const Type* Type::make_constant_from_array_element(ciArray* array, int off, int stable_dimension,
+                                                   BasicType loadbt, bool is_unsigned_load) {
+  // Decode the results of GraphKit::array_element_address.
+  ciConstant element_value = array->element_value_by_offset(off);
+  if (element_value.basic_type() == T_ILLEGAL) {
+    return NULL; // wrong offset
+  }
+  ciConstant con = check_mismatched_access(element_value, loadbt, is_unsigned_load);
+
+  assert(con.basic_type() != T_ILLEGAL, "elembt=%s; loadbt=%s; unsigned=%d",
+         type2name(element_value.basic_type()), type2name(loadbt), is_unsigned_load);
+
+  if (con.is_valid() &&          // not a mismatched access
+      !con.is_null_or_zero()) {  // not a default value
+    bool is_narrow_oop = (loadbt == T_NARROWOOP);
+    return Type::make_from_constant(con, /*require_constant=*/true, stable_dimension, is_narrow_oop, /*is_autobox_cache=*/false);
+  }
+  return NULL;
+}
+
+const Type* Type::make_constant_from_field(ciInstance* holder, int off, bool is_unsigned_load, BasicType loadbt) {
+  ciField* field;
+  ciType* type = holder->java_mirror_type();
+  if (type != NULL && type->is_instance_klass() && off >= InstanceMirrorKlass::offset_of_static_fields()) {
+    // Static field
+    field = type->as_instance_klass()->get_field_by_offset(off, /*is_static=*/true);
+  } else {
+    // Instance field
+    field = holder->klass()->as_instance_klass()->get_field_by_offset(off, /*is_static=*/false);
+  }
+  if (field == NULL) {
+    return NULL; // Wrong offset
+  }
+  return Type::make_constant_from_field(field, holder, loadbt, is_unsigned_load);
+}
+
+const Type* Type::make_constant_from_field(ciField* field, ciInstance* holder,
+                                           BasicType loadbt, bool is_unsigned_load) {
+  if (!field->is_constant()) {
+    return NULL; // Non-constant field
+  }
+  ciConstant field_value;
   if (field->is_static()) {
     // final static field
-    con_type = Type::make_from_constant(field->constant_value(), /*require_const=*/true);
-    if (Compile::current()->eliminate_boxing() && field->is_autobox_cache() && con_type != NULL) {
-      con_type = con_type->is_aryptr()->cast_to_autobox_cache(true);
-    }
-  } else {
+    field_value = field->constant_value();
+  } else if (holder != NULL) {
     // final or stable non-static field
     // Treat final non-static fields of trusted classes (classes in
     // java.lang.invoke and sun.invoke packages and subpackages) as
     // compile time constants.
-    if (obj->is_Con()) {
-      const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr();
-      ciObject* constant_oop = oop_ptr->const_oop();
-      ciConstant constant = field->constant_value_of(constant_oop);
-      con_type = Type::make_from_constant(constant, /*require_const=*/true);
-    }
+    field_value = field->constant_value_of(holder);
+  }
+  if (!field_value.is_valid()) {
+    return NULL; // Not a constant
   }
-  if (FoldStableValues && field->is_stable() && con_type != NULL) {
-    if (con_type->is_zero_type()) {
-      return NULL; // the field hasn't been initialized yet
-    } else if (con_type->isa_oopptr()) {
-      const Type* stable_type = Type::get_const_type(field->type());
-      if (field->type()->is_array_klass()) {
-        int stable_dimension = field->type()->as_array_klass()->dimension();
-        stable_type = stable_type->is_aryptr()->cast_to_stable(true, stable_dimension);
-      }
-      if (stable_type != NULL) {
-        con_type = con_type->join_speculative(stable_type);
-      }
+
+  ciConstant con = check_mismatched_access(field_value, loadbt, is_unsigned_load);
+
+  assert(con.is_valid(), "elembt=%s; loadbt=%s; unsigned=%d",
+         type2name(field_value.basic_type()), type2name(loadbt), is_unsigned_load);
+
+  bool is_stable_array = FoldStableValues && field->is_stable() && field->type()->is_array_klass();
+  int stable_dimension = (is_stable_array ? field->type()->as_array_klass()->dimension() : 0);
+  bool is_narrow_oop = (loadbt == T_NARROWOOP);
+
+  const Type* con_type = make_from_constant(con, /*require_constant=*/ true,
+                                            stable_dimension, is_narrow_oop,
+                                            field->is_autobox_cache());
+  if (con_type != NULL && field->is_call_site_target()) {
+    ciCallSite* call_site = holder->as_call_site();
+    if (!call_site->is_constant_call_site()) {
+      ciMethodHandle* target = call_site->get_target();
+      Compile::current()->dependencies()->assert_call_site_target_value(call_site, target);
     }
   }
   return con_type;
--- a/hotspot/src/share/vm/opto/type.hpp	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/src/share/vm/opto/type.hpp	Mon Apr 11 21:42:55 2016 +0300
@@ -417,9 +417,26 @@
   static const Type* get_typeflow_type(ciType* type);
 
   static const Type* make_from_constant(ciConstant constant,
-                                        bool require_constant = false);
+                                        bool require_constant = false,
+                                        int stable_dimension = 0,
+                                        bool is_narrow = false,
+                                        bool is_autobox_cache = false);
+
+  static const Type* make_constant_from_field(ciInstance* holder,
+                                              int off,
+                                              bool is_unsigned_load,
+                                              BasicType loadbt);
 
-  static const Type* make_constant(ciField* field, Node* obj);
+  static const Type* make_constant_from_field(ciField* field,
+                                              ciInstance* holder,
+                                              BasicType loadbt,
+                                              bool is_unsigned_load);
+
+  static const Type* make_constant_from_array_element(ciArray* array,
+                                                      int off,
+                                                      int stable_dimension,
+                                                      BasicType loadbt,
+                                                      bool is_unsigned_load);
 
   // Speculative type helper methods. See TypePtr.
   virtual const TypePtr* speculative() const                                  { return NULL; }
--- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java	Mon Apr 11 21:42:55 2016 +0300
@@ -33,6 +33,7 @@
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.vm.annotation
  *          java.base/jdk.internal.misc
+ *
  * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
  *                         -Xbatch -XX:-TieredCompilation
  *                         -XX:+FoldStableValues
@@ -63,7 +64,6 @@
 import jdk.internal.misc.Unsafe;
 
 import java.io.IOException;
-import java.lang.reflect.Field;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
--- a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java	Mon Apr 11 21:42:31 2016 +0300
+++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java	Mon Apr 11 21:42:55 2016 +0300
@@ -26,24 +26,28 @@
 /*
  * @test
  * @summary tests on constant folding of unsafe get operations from stable arrays
- * @library /testlibrary /test/lib
- * @ignore 8151137
+ * @library /testlibrary
  *
  * @requires vm.flavor != "client"
  *
+ * @modules java.base/jdk.internal.vm.annotation
+ *          java.base/jdk.internal.misc
+
  * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
  *                   -Xbatch -XX:-TieredCompilation
  *                   -XX:+FoldStableValues
  *                   -XX:CompileCommand=dontinline,*Test::test*
- *                   UnsafeGetStableArrayElement
+ *                   compiler.unsafe.UnsafeGetStableArrayElement
  */
+package compiler.unsafe;
+
 import jdk.internal.misc.Unsafe;
 import jdk.internal.vm.annotation.Stable;
 import java.util.concurrent.Callable;
+import jdk.test.lib.Platform;
 
 import static jdk.internal.misc.Unsafe.*;
 import static jdk.test.lib.Asserts.*;
-import static jdk.test.lib.Platform;
 
 public class UnsafeGetStableArrayElement {
     @Stable static final boolean[] STABLE_BOOLEAN_ARRAY = new boolean[16];
@@ -219,13 +223,7 @@
         Setter.reset();
     }
 
-    public static void main(String[] args) throws Exception {
-        if (Platform.isServer()) {
-            test();
-        }
-    }
-
-    static void test() throws Exception {
+    static void testUnsafeAccess() throws Exception {
         // boolean[], aligned accesses
         testMatched(   Test::testZ_Z, Test::changeZ);
         testMismatched(Test::testZ_B, Test::changeZ);
@@ -329,4 +327,11 @@
         run(Test::testL_I);
         run(Test::testL_F);
     }
+
+    public static void main(String[] args) throws Exception {
+        if (Platform.isServer()) {
+            testUnsafeAccess();
+        }
+        System.out.println("TEST PASSED");
+    }
 }