8001107: @Stable annotation for constant folding of lazily evaluated variables

Tue, 10 Sep 2013 14:51:48 -0700

author
vlivanov
date
Tue, 10 Sep 2013 14:51:48 -0700
changeset 5658
edb5ab0f3fe5
parent 5656
cd16d587b0fa
child 5659
e0d33d2ce5aa

8001107: @Stable annotation for constant folding of lazily evaluated variables
Reviewed-by: rbackman, twisti, kvn
Contributed-by: john.r.rose@oracle.com, vladimir.x.ivanov@oracle.com

src/share/vm/ci/ciArray.cpp file | annotate | diff | comparison | revisions
src/share/vm/ci/ciArray.hpp file | annotate | diff | comparison | revisions
src/share/vm/ci/ciConstant.hpp file | annotate | diff | comparison | revisions
src/share/vm/ci/ciField.cpp file | annotate | diff | comparison | revisions
src/share/vm/ci/ciField.hpp file | annotate | diff | comparison | revisions
src/share/vm/ci/ciFlags.hpp file | annotate | diff | comparison | revisions
src/share/vm/ci/ciInstance.cpp file | annotate | diff | comparison | revisions
src/share/vm/ci/ciTypeArray.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/classFileParser.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/classFileParser.hpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/vmSymbols.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/fieldInfo.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/c2_globals.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/compile.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/compile.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/graphKit.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/graphKit.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/library_call.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/memnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/parse.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/parse3.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/type.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/type.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/globals.hpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/accessFlags.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/ci/ciArray.cpp	Mon Sep 09 19:53:28 2013 +0200
     1.2 +++ b/src/share/vm/ci/ciArray.cpp	Tue Sep 10 14:51:48 2013 -0700
     1.3 @@ -24,13 +24,92 @@
     1.4  
     1.5  #include "precompiled.hpp"
     1.6  #include "ci/ciArray.hpp"
     1.7 +#include "ci/ciArrayKlass.hpp"
     1.8 +#include "ci/ciConstant.hpp"
     1.9  #include "ci/ciKlass.hpp"
    1.10  #include "ci/ciUtilities.hpp"
    1.11 +#include "oops/objArrayOop.hpp"
    1.12 +#include "oops/typeArrayOop.hpp"
    1.13  
    1.14  // ciArray
    1.15  //
    1.16  // This class represents an arrayOop in the HotSpot virtual
    1.17  // machine.
    1.18 +static BasicType fixup_element_type(BasicType bt) {
    1.19 +  if (bt == T_ARRAY)    return T_OBJECT;
    1.20 +  if (bt == T_BOOLEAN)  return T_BYTE;
    1.21 +  return bt;
    1.22 +}
    1.23 +
    1.24 +ciConstant ciArray::element_value_impl(BasicType elembt,
    1.25 +                                       arrayOop ary,
    1.26 +                                       int index) {
    1.27 +  if (ary == NULL)
    1.28 +    return ciConstant();
    1.29 +  assert(ary->is_array(), "");
    1.30 +  if (index < 0 || index >= ary->length())
    1.31 +    return ciConstant();
    1.32 +  ArrayKlass* ak = (ArrayKlass*) ary->klass();
    1.33 +  BasicType abt = ak->element_type();
    1.34 +  if (fixup_element_type(elembt) !=
    1.35 +      fixup_element_type(abt))
    1.36 +    return ciConstant();
    1.37 +  switch (elembt) {
    1.38 +  case T_ARRAY:
    1.39 +  case T_OBJECT:
    1.40 +    {
    1.41 +      assert(ary->is_objArray(), "");
    1.42 +      objArrayOop objary = (objArrayOop) ary;
    1.43 +      oop elem = objary->obj_at(index);
    1.44 +      ciEnv* env = CURRENT_ENV;
    1.45 +      ciObject* box = env->get_object(elem);
    1.46 +      return ciConstant(T_OBJECT, box);
    1.47 +    }
    1.48 +  }
    1.49 +  assert(ary->is_typeArray(), "");
    1.50 +  typeArrayOop tary = (typeArrayOop) ary;
    1.51 +  jint value = 0;
    1.52 +  switch (elembt) {
    1.53 +  case T_LONG:          return ciConstant(tary->long_at(index));
    1.54 +  case T_FLOAT:         return ciConstant(tary->float_at(index));
    1.55 +  case T_DOUBLE:        return ciConstant(tary->double_at(index));
    1.56 +  default:              return ciConstant();
    1.57 +  case T_BYTE:          value = tary->byte_at(index);           break;
    1.58 +  case T_BOOLEAN:       value = tary->byte_at(index) & 1;       break;
    1.59 +  case T_SHORT:         value = tary->short_at(index);          break;
    1.60 +  case T_CHAR:          value = tary->char_at(index);           break;
    1.61 +  case T_INT:           value = tary->int_at(index);            break;
    1.62 +  }
    1.63 +  return ciConstant(elembt, value);
    1.64 +}
    1.65 +
    1.66 +// ------------------------------------------------------------------
    1.67 +// ciArray::element_value
    1.68 +//
    1.69 +// Current value of an element.
    1.70 +// Returns T_ILLEGAL if there is no element at the given index.
    1.71 +ciConstant ciArray::element_value(int index) {
    1.72 +  BasicType elembt = element_basic_type();
    1.73 +  GUARDED_VM_ENTRY(
    1.74 +    return element_value_impl(elembt, get_arrayOop(), index);
    1.75 +  )
    1.76 +}
    1.77 +
    1.78 +// ------------------------------------------------------------------
    1.79 +// ciArray::element_value_by_offset
    1.80 +//
    1.81 +// Current value of an element at the specified offset.
    1.82 +// Returns T_ILLEGAL if there is no element at the given offset.
    1.83 +ciConstant ciArray::element_value_by_offset(intptr_t element_offset) {
    1.84 +  BasicType elembt = element_basic_type();
    1.85 +  intptr_t shift  = exact_log2(type2aelembytes(elembt));
    1.86 +  intptr_t header = arrayOopDesc::base_offset_in_bytes(elembt);
    1.87 +  intptr_t index = (element_offset - header) >> shift;
    1.88 +  intptr_t offset = header + ((intptr_t)index << shift);
    1.89 +  if (offset != element_offset || index != (jint)index)
    1.90 +    return ciConstant();
    1.91 +  return element_value((jint) index);
    1.92 +}
    1.93  
    1.94  // ------------------------------------------------------------------
    1.95  // ciArray::print_impl
     2.1 --- a/src/share/vm/ci/ciArray.hpp	Mon Sep 09 19:53:28 2013 +0200
     2.2 +++ b/src/share/vm/ci/ciArray.hpp	Tue Sep 10 14:51:48 2013 -0700
     2.3 @@ -25,6 +25,8 @@
     2.4  #ifndef SHARE_VM_CI_CIARRAY_HPP
     2.5  #define SHARE_VM_CI_CIARRAY_HPP
     2.6  
     2.7 +#include "ci/ciArrayKlass.hpp"
     2.8 +#include "ci/ciConstant.hpp"
     2.9  #include "ci/ciObject.hpp"
    2.10  #include "oops/arrayOop.hpp"
    2.11  #include "oops/objArrayOop.hpp"
    2.12 @@ -45,15 +47,30 @@
    2.13  
    2.14    ciArray(ciKlass* klass, int len) : ciObject(klass), _length(len) {}
    2.15  
    2.16 -  arrayOop get_arrayOop() { return (arrayOop)get_oop(); }
    2.17 +  arrayOop get_arrayOop() const { return (arrayOop)get_oop(); }
    2.18  
    2.19    const char* type_string() { return "ciArray"; }
    2.20  
    2.21    void print_impl(outputStream* st);
    2.22  
    2.23 +  ciConstant element_value_impl(BasicType elembt, arrayOop ary, int index);
    2.24 +
    2.25  public:
    2.26    int length() { return _length; }
    2.27  
    2.28 +  // Convenience routines.
    2.29 +  ciArrayKlass* array_type()         { return klass()->as_array_klass(); }
    2.30 +  ciType*       element_type()       { return array_type()->element_type(); }
    2.31 +  BasicType     element_basic_type() { return element_type()->basic_type(); }
    2.32 +
    2.33 +  // Current value of an element.
    2.34 +  // Returns T_ILLEGAL if there is no element at the given index.
    2.35 +  ciConstant element_value(int index);
    2.36 +
    2.37 +  // Current value of an element at the specified offset.
    2.38 +  // Returns T_ILLEGAL if there is no element at the given offset.
    2.39 +  ciConstant element_value_by_offset(intptr_t element_offset);
    2.40 +
    2.41    // What kind of ciObject is this?
    2.42    bool is_array()        { return true; }
    2.43    bool is_java_object()  { return true; }
     3.1 --- a/src/share/vm/ci/ciConstant.hpp	Mon Sep 09 19:53:28 2013 +0200
     3.2 +++ b/src/share/vm/ci/ciConstant.hpp	Tue Sep 10 14:51:48 2013 -0700
     3.3 @@ -41,7 +41,6 @@
     3.4    union {
     3.5      jint      _int;
     3.6      jlong     _long;
     3.7 -    jint      _long_half[2];
     3.8      jfloat    _float;
     3.9      jdouble   _double;
    3.10      ciObject* _object;
    3.11 @@ -111,6 +110,20 @@
    3.12      return _value._object;
    3.13    }
    3.14  
    3.15 +  bool      is_null_or_zero() const {
    3.16 +    if (!is_java_primitive(basic_type())) {
    3.17 +      return as_object()->is_null_object();
    3.18 +    } else if (type2size[basic_type()] == 1) {
    3.19 +      // treat float bits as int, to avoid comparison with -0 and NaN
    3.20 +      return (_value._int == 0);
    3.21 +    } else if (type2size[basic_type()] == 2) {
    3.22 +      // treat double bits as long, to avoid comparison with -0 and NaN
    3.23 +      return (_value._long == 0);
    3.24 +    } else {
    3.25 +      return false;
    3.26 +    }
    3.27 +  }
    3.28 +
    3.29    // Debugging output
    3.30    void print();
    3.31  };
     4.1 --- a/src/share/vm/ci/ciField.cpp	Mon Sep 09 19:53:28 2013 +0200
     4.2 +++ b/src/share/vm/ci/ciField.cpp	Tue Sep 10 14:51:48 2013 -0700
     4.3 @@ -189,12 +189,14 @@
     4.4    _holder = CURRENT_ENV->get_instance_klass(fd->field_holder());
     4.5  
     4.6    // Check to see if the field is constant.
     4.7 -  if (_holder->is_initialized() && this->is_final()) {
     4.8 +  bool is_final = this->is_final();
     4.9 +  bool is_stable = FoldStableValues && this->is_stable();
    4.10 +  if (_holder->is_initialized() && (is_final || is_stable)) {
    4.11      if (!this->is_static()) {
    4.12        // A field can be constant if it's a final static field or if
    4.13        // it's a final non-static field of a trusted class (classes in
    4.14        // java.lang.invoke and sun.invoke packages and subpackages).
    4.15 -      if (trust_final_non_static_fields(_holder)) {
    4.16 +      if (is_stable || trust_final_non_static_fields(_holder)) {
    4.17          _is_constant = true;
    4.18          return;
    4.19        }
    4.20 @@ -227,7 +229,6 @@
    4.21  
    4.22      Handle mirror = k->java_mirror();
    4.23  
    4.24 -    _is_constant = true;
    4.25      switch(type()->basic_type()) {
    4.26      case T_BYTE:
    4.27        _constant_value = ciConstant(type()->basic_type(), mirror->byte_field(_offset));
    4.28 @@ -273,6 +274,12 @@
    4.29          }
    4.30        }
    4.31      }
    4.32 +    if (is_stable && _constant_value.is_null_or_zero()) {
    4.33 +      // It is not a constant after all; treat it as uninitialized.
    4.34 +      _is_constant = false;
    4.35 +    } else {
    4.36 +      _is_constant = true;
    4.37 +    }
    4.38    } else {
    4.39      _is_constant = false;
    4.40    }
    4.41 @@ -373,8 +380,11 @@
    4.42    tty->print(" signature=");
    4.43    _signature->print_symbol();
    4.44    tty->print(" offset=%d type=", _offset);
    4.45 -  if (_type != NULL) _type->print_name();
    4.46 -  else               tty->print("(reference)");
    4.47 +  if (_type != NULL)
    4.48 +    _type->print_name();
    4.49 +  else
    4.50 +    tty->print("(reference)");
    4.51 +  tty->print(" flags=%04x", flags().as_int());
    4.52    tty->print(" is_constant=%s", bool_to_str(_is_constant));
    4.53    if (_is_constant && is_static()) {
    4.54      tty->print(" constant_value=");
     5.1 --- a/src/share/vm/ci/ciField.hpp	Mon Sep 09 19:53:28 2013 +0200
     5.2 +++ b/src/share/vm/ci/ciField.hpp	Tue Sep 10 14:51:48 2013 -0700
     5.3 @@ -139,7 +139,10 @@
     5.4    //      non-constant fields.  These are java.lang.System.in
     5.5    //      and java.lang.System.out.  Abomination.
     5.6    //
     5.7 -  // Note: the check for case 4 is not yet implemented.
     5.8 +  // A field is also considered constant if it is marked @Stable
     5.9 +  // and is non-null (or non-zero, if a primitive).
    5.10 +  // For non-static fields, the null/zero check must be
    5.11 +  // arranged by the user, as constant_value().is_null_or_zero().
    5.12    bool is_constant() { return _is_constant; }
    5.13  
    5.14    // Get the constant value of this field.
    5.15 @@ -173,6 +176,7 @@
    5.16    bool is_protected   () { return flags().is_protected(); }
    5.17    bool is_static      () { return flags().is_static(); }
    5.18    bool is_final       () { return flags().is_final(); }
    5.19 +  bool is_stable      () { return flags().is_stable(); }
    5.20    bool is_volatile    () { return flags().is_volatile(); }
    5.21    bool is_transient   () { return flags().is_transient(); }
    5.22  
     6.1 --- a/src/share/vm/ci/ciFlags.hpp	Mon Sep 09 19:53:28 2013 +0200
     6.2 +++ b/src/share/vm/ci/ciFlags.hpp	Tue Sep 10 14:51:48 2013 -0700
     6.3 @@ -59,6 +59,7 @@
     6.4    bool is_interface   () const         { return (_flags & JVM_ACC_INTERFACE   ) != 0; }
     6.5    bool is_abstract    () const         { return (_flags & JVM_ACC_ABSTRACT    ) != 0; }
     6.6    bool is_strict      () const         { return (_flags & JVM_ACC_STRICT      ) != 0; }
     6.7 +  bool is_stable      () const         { return (_flags & JVM_ACC_FIELD_STABLE) != 0; }
     6.8  
     6.9    // Conversion
    6.10    jint   as_int()                      { return _flags; }
     7.1 --- a/src/share/vm/ci/ciInstance.cpp	Mon Sep 09 19:53:28 2013 +0200
     7.2 +++ b/src/share/vm/ci/ciInstance.cpp	Tue Sep 10 14:51:48 2013 -0700
     7.3 @@ -127,6 +127,8 @@
     7.4  ciConstant ciInstance::field_value_by_offset(int field_offset) {
     7.5    ciInstanceKlass* ik = klass()->as_instance_klass();
     7.6    ciField* field = ik->get_field_by_offset(field_offset, false);
     7.7 +  if (field == NULL)
     7.8 +    return ciConstant();  // T_ILLEGAL
     7.9    return field_value(field);
    7.10  }
    7.11  
     8.1 --- a/src/share/vm/ci/ciTypeArray.cpp	Mon Sep 09 19:53:28 2013 +0200
     8.2 +++ b/src/share/vm/ci/ciTypeArray.cpp	Tue Sep 10 14:51:48 2013 -0700
     8.3 @@ -39,5 +39,10 @@
     8.4  jchar ciTypeArray::char_at(int index) {
     8.5    VM_ENTRY_MARK;
     8.6    assert(index >= 0 && index < length(), "out of range");
     8.7 -  return get_typeArrayOop()->char_at(index);
     8.8 +  jchar c = get_typeArrayOop()->char_at(index);
     8.9 +#ifdef ASSERT
    8.10 +  jchar d = element_value(index).as_char();
    8.11 +  assert(c == d, "");
    8.12 +#endif //ASSERT
    8.13 +  return c;
    8.14  }
     9.1 --- a/src/share/vm/classfile/classFileParser.cpp	Mon Sep 09 19:53:28 2013 +0200
     9.2 +++ b/src/share/vm/classfile/classFileParser.cpp	Tue Sep 10 14:51:48 2013 -0700
     9.3 @@ -1774,6 +1774,10 @@
     9.4      if (_location != _in_method)  break;  // only allow for methods
     9.5      if (!privileged)              break;  // only allow in privileged code
     9.6      return _method_LambdaForm_Hidden;
     9.7 +  case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_invoke_Stable_signature):
     9.8 +    if (_location != _in_field)   break;  // only allow for fields
     9.9 +    if (!privileged)              break;  // only allow in privileged code
    9.10 +    return _field_Stable;
    9.11    case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Contended_signature):
    9.12      if (_location != _in_field && _location != _in_class)          break;  // only allow for fields and classes
    9.13      if (!EnableContended || (RestrictContended && !privileged))    break;  // honor privileges
    9.14 @@ -1786,6 +1790,8 @@
    9.15  void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
    9.16    if (is_contended())
    9.17      f->set_contended_group(contended_group());
    9.18 +  if (is_stable())
    9.19 +    f->set_stable(true);
    9.20  }
    9.21  
    9.22  ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
    10.1 --- a/src/share/vm/classfile/classFileParser.hpp	Mon Sep 09 19:53:28 2013 +0200
    10.2 +++ b/src/share/vm/classfile/classFileParser.hpp	Tue Sep 10 14:51:48 2013 -0700
    10.3 @@ -125,6 +125,7 @@
    10.4        _method_LambdaForm_Compiled,
    10.5        _method_LambdaForm_Hidden,
    10.6        _sun_misc_Contended,
    10.7 +      _field_Stable,
    10.8        _annotation_LIMIT
    10.9      };
   10.10      const Location _location;
   10.11 @@ -143,14 +144,23 @@
   10.12        assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
   10.13        _annotations_present |= nth_bit((int)id);
   10.14      }
   10.15 +
   10.16 +    void remove_annotation(ID id) {
   10.17 +      assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
   10.18 +      _annotations_present &= ~nth_bit((int)id);
   10.19 +    }
   10.20 +
   10.21      // Report if the annotation is present.
   10.22 -    bool has_any_annotations() { return _annotations_present != 0; }
   10.23 -    bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; }
   10.24 +    bool has_any_annotations() const { return _annotations_present != 0; }
   10.25 +    bool has_annotation(ID id) const { return (nth_bit((int)id) & _annotations_present) != 0; }
   10.26  
   10.27      void set_contended_group(u2 group) { _contended_group = group; }
   10.28 -    u2 contended_group() { return _contended_group; }
   10.29 +    u2 contended_group() const { return _contended_group; }
   10.30  
   10.31 -    bool is_contended() { return has_annotation(_sun_misc_Contended); }
   10.32 +    bool is_contended() const { return has_annotation(_sun_misc_Contended); }
   10.33 +
   10.34 +    void set_stable(bool stable) { set_annotation(_field_Stable); }
   10.35 +    bool is_stable() const { return has_annotation(_field_Stable); }
   10.36    };
   10.37  
   10.38    // This class also doubles as a holder for metadata cleanup.
    11.1 --- a/src/share/vm/classfile/vmSymbols.hpp	Mon Sep 09 19:53:28 2013 +0200
    11.2 +++ b/src/share/vm/classfile/vmSymbols.hpp	Tue Sep 10 14:51:48 2013 -0700
    11.3 @@ -270,6 +270,7 @@
    11.4    template(java_lang_invoke_LambdaForm,               "java/lang/invoke/LambdaForm")              \
    11.5    template(java_lang_invoke_ForceInline_signature,    "Ljava/lang/invoke/ForceInline;")           \
    11.6    template(java_lang_invoke_DontInline_signature,     "Ljava/lang/invoke/DontInline;")            \
    11.7 +  template(sun_invoke_Stable_signature,               "Lsun/invoke/Stable;")                      \
    11.8    template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
    11.9    template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;")  \
   11.10    template(java_lang_invoke_MagicLambdaImpl,          "java/lang/invoke/MagicLambdaImpl")         \
    12.1 --- a/src/share/vm/oops/fieldInfo.hpp	Mon Sep 09 19:53:28 2013 +0200
    12.2 +++ b/src/share/vm/oops/fieldInfo.hpp	Tue Sep 10 14:51:48 2013 -0700
    12.3 @@ -240,6 +240,14 @@
    12.4      return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0;
    12.5    }
    12.6  
    12.7 +  bool is_stable() const {
    12.8 +    return (access_flags() & JVM_ACC_FIELD_STABLE) != 0;
    12.9 +  }
   12.10 +  void set_stable(bool z) {
   12.11 +    if (z) _shorts[access_flags_offset] |=  JVM_ACC_FIELD_STABLE;
   12.12 +    else   _shorts[access_flags_offset] &= ~JVM_ACC_FIELD_STABLE;
   12.13 +  }
   12.14 +
   12.15    Symbol* lookup_symbol(int symbol_index) const {
   12.16      assert(is_internal(), "only internal fields");
   12.17      return vmSymbols::symbol_at((vmSymbols::SID)symbol_index);
    13.1 --- a/src/share/vm/opto/c2_globals.hpp	Mon Sep 09 19:53:28 2013 +0200
    13.2 +++ b/src/share/vm/opto/c2_globals.hpp	Tue Sep 10 14:51:48 2013 -0700
    13.3 @@ -448,6 +448,9 @@
    13.4    product(bool, EliminateAutoBox, true,                                     \
    13.5            "Control optimizations for autobox elimination")                  \
    13.6                                                                              \
    13.7 +  experimental(bool, UseImplicitStableValues, false,                        \
    13.8 +          "Mark well-known stable fields as such (e.g. String.value)")      \
    13.9 +                                                                            \
   13.10    product(intx, AutoBoxCacheMax, 128,                                       \
   13.11            "Sets max value cached by the java.lang.Integer autobox cache")   \
   13.12                                                                              \
    14.1 --- a/src/share/vm/opto/compile.cpp	Mon Sep 09 19:53:28 2013 +0200
    14.2 +++ b/src/share/vm/opto/compile.cpp	Tue Sep 10 14:51:48 2013 -0700
    14.3 @@ -1297,6 +1297,10 @@
    14.4  
    14.5    // Array pointers need some flattening
    14.6    const TypeAryPtr *ta = tj->isa_aryptr();
    14.7 +  if (ta && ta->is_stable()) {
    14.8 +    // Erase stability property for alias analysis.
    14.9 +    tj = ta = ta->cast_to_stable(false);
   14.10 +  }
   14.11    if( ta && is_known_inst ) {
   14.12      if ( offset != Type::OffsetBot &&
   14.13           offset > arrayOopDesc::length_offset_in_bytes() ) {
   14.14 @@ -1497,6 +1501,7 @@
   14.15    _index = i;
   14.16    _adr_type = at;
   14.17    _field = NULL;
   14.18 +  _element = NULL;
   14.19    _is_rewritable = true; // default
   14.20    const TypeOopPtr *atoop = (at != NULL) ? at->isa_oopptr() : NULL;
   14.21    if (atoop != NULL && atoop->is_known_instance()) {
   14.22 @@ -1615,6 +1620,16 @@
   14.23            && flat->is_instptr()->klass() == env()->Class_klass())
   14.24          alias_type(idx)->set_rewritable(false);
   14.25      }
   14.26 +    if (flat->isa_aryptr()) {
   14.27 +#ifdef ASSERT
   14.28 +      const int header_size_min  = arrayOopDesc::base_offset_in_bytes(T_BYTE);
   14.29 +      // (T_BYTE has the weakest alignment and size restrictions...)
   14.30 +      assert(flat->offset() < header_size_min, "array body reference must be OffsetBot");
   14.31 +#endif
   14.32 +      if (flat->offset() == TypePtr::OffsetBot) {
   14.33 +        alias_type(idx)->set_element(flat->is_aryptr()->elem());
   14.34 +      }
   14.35 +    }
   14.36      if (flat->isa_klassptr()) {
   14.37        if (flat->offset() == in_bytes(Klass::super_check_offset_offset()))
   14.38          alias_type(idx)->set_rewritable(false);
   14.39 @@ -1677,7 +1692,7 @@
   14.40    else
   14.41      t = TypeOopPtr::make_from_klass_raw(field->holder());
   14.42    AliasType* atp = alias_type(t->add_offset(field->offset_in_bytes()), field);
   14.43 -  assert(field->is_final() == !atp->is_rewritable(), "must get the rewritable bits correct");
   14.44 +  assert((field->is_final() || field->is_stable()) == !atp->is_rewritable(), "must get the rewritable bits correct");
   14.45    return atp;
   14.46  }
   14.47  
    15.1 --- a/src/share/vm/opto/compile.hpp	Mon Sep 09 19:53:28 2013 +0200
    15.2 +++ b/src/share/vm/opto/compile.hpp	Tue Sep 10 14:51:48 2013 -0700
    15.3 @@ -72,6 +72,7 @@
    15.4  class StartNode;
    15.5  class SafePointNode;
    15.6  class JVMState;
    15.7 +class Type;
    15.8  class TypeData;
    15.9  class TypePtr;
   15.10  class TypeOopPtr;
   15.11 @@ -119,6 +120,7 @@
   15.12      int             _index;         // unique index, used with MergeMemNode
   15.13      const TypePtr*  _adr_type;      // normalized address type
   15.14      ciField*        _field;         // relevant instance field, or null if none
   15.15 +    const Type*     _element;       // relevant array element type, or null if none
   15.16      bool            _is_rewritable; // false if the memory is write-once only
   15.17      int             _general_index; // if this is type is an instance, the general
   15.18                                      // type that this is an instance of
   15.19 @@ -129,6 +131,7 @@
   15.20      int             index()         const { return _index; }
   15.21      const TypePtr*  adr_type()      const { return _adr_type; }
   15.22      ciField*        field()         const { return _field; }
   15.23 +    const Type*     element()       const { return _element; }
   15.24      bool            is_rewritable() const { return _is_rewritable; }
   15.25      bool            is_volatile()   const { return (_field ? _field->is_volatile() : false); }
   15.26      int             general_index() const { return (_general_index != 0) ? _general_index : _index; }
   15.27 @@ -137,7 +140,14 @@
   15.28      void set_field(ciField* f) {
   15.29        assert(!_field,"");
   15.30        _field = f;
   15.31 -      if (f->is_final())  _is_rewritable = false;
   15.32 +      if (f->is_final() || f->is_stable()) {
   15.33 +        // In the case of @Stable, multiple writes are possible but may be assumed to be no-ops.
   15.34 +        _is_rewritable = false;
   15.35 +      }
   15.36 +    }
   15.37 +    void set_element(const Type* e) {
   15.38 +      assert(_element == NULL, "");
   15.39 +      _element = e;
   15.40      }
   15.41  
   15.42      void print_on(outputStream* st) PRODUCT_RETURN;
    16.1 --- a/src/share/vm/opto/graphKit.cpp	Mon Sep 09 19:53:28 2013 +0200
    16.2 +++ b/src/share/vm/opto/graphKit.cpp	Tue Sep 10 14:51:48 2013 -0700
    16.3 @@ -3825,8 +3825,13 @@
    16.4                                                     TypeAry::make(TypeInt::CHAR,TypeInt::POS),
    16.5                                                     ciTypeArrayKlass::make(T_CHAR), true, 0);
    16.6    int value_field_idx = C->get_alias_index(value_field_type);
    16.7 -  return make_load(ctrl, basic_plus_adr(str, str, value_offset),
    16.8 -                   value_type, T_OBJECT, value_field_idx);
    16.9 +  Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset),
   16.10 +                         value_type, T_OBJECT, value_field_idx);
   16.11 +  // String.value field is known to be @Stable.
   16.12 +  if (UseImplicitStableValues) {
   16.13 +    load = cast_array_to_stable(load, value_type);
   16.14 +  }
   16.15 +  return load;
   16.16  }
   16.17  
   16.18  void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) {
   16.19 @@ -3844,9 +3849,6 @@
   16.20    const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
   16.21                                                       false, NULL, 0);
   16.22    const TypePtr* value_field_type = string_type->add_offset(value_offset);
   16.23 -  const TypeAryPtr*  value_type = TypeAryPtr::make(TypePtr::NotNull,
   16.24 -                                                   TypeAry::make(TypeInt::CHAR,TypeInt::POS),
   16.25 -                                                   ciTypeArrayKlass::make(T_CHAR), true, 0);
   16.26    int value_field_idx = C->get_alias_index(value_field_type);
   16.27    store_to_memory(ctrl, basic_plus_adr(str, value_offset),
   16.28                    value, T_OBJECT, value_field_idx);
   16.29 @@ -3861,3 +3863,9 @@
   16.30    store_to_memory(ctrl, basic_plus_adr(str, count_offset),
   16.31                    value, T_INT, count_field_idx);
   16.32  }
   16.33 +
   16.34 +Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) {
   16.35 +  // Reify the property as a CastPP node in Ideal graph to comply with monotonicity
   16.36 +  // assumption of CCP analysis.
   16.37 +  return _gvn.transform(new(C) CastPPNode(ary, ary_type->cast_to_stable(true)));
   16.38 +}
    17.1 --- a/src/share/vm/opto/graphKit.hpp	Mon Sep 09 19:53:28 2013 +0200
    17.2 +++ b/src/share/vm/opto/graphKit.hpp	Tue Sep 10 14:51:48 2013 -0700
    17.3 @@ -836,6 +836,9 @@
    17.4    // Insert a loop predicate into the graph
    17.5    void add_predicate(int nargs = 0);
    17.6    void add_predicate_impl(Deoptimization::DeoptReason reason, int nargs);
    17.7 +
    17.8 +  // Produce new array node of stable type
    17.9 +  Node* cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type);
   17.10  };
   17.11  
   17.12  // Helper class to support building of control flow branches. Upon
    18.1 --- a/src/share/vm/opto/library_call.cpp	Mon Sep 09 19:53:28 2013 +0200
    18.2 +++ b/src/share/vm/opto/library_call.cpp	Tue Sep 10 14:51:48 2013 -0700
    18.3 @@ -1280,6 +1280,11 @@
    18.4    const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin));
    18.5    const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot);
    18.6  
    18.7 +  // String.value field is known to be @Stable.
    18.8 +  if (UseImplicitStableValues) {
    18.9 +    target = cast_array_to_stable(target, target_type);
   18.10 +  }
   18.11 +
   18.12    IdealKit kit(this, false, true);
   18.13  #define __ kit.
   18.14    Node* zero             = __ ConI(0);
    19.1 --- a/src/share/vm/opto/memnode.cpp	Mon Sep 09 19:53:28 2013 +0200
    19.2 +++ b/src/share/vm/opto/memnode.cpp	Tue Sep 10 14:51:48 2013 -0700
    19.3 @@ -962,6 +962,19 @@
    19.4    return (uintptr_t)in(Control) + (uintptr_t)in(Memory) + (uintptr_t)in(Address);
    19.5  }
    19.6  
    19.7 +static bool skip_through_membars(Compile::AliasType* atp, const TypeInstPtr* tp, bool eliminate_boxing) {
    19.8 +  if ((atp != NULL) && (atp->index() >= Compile::AliasIdxRaw)) {
    19.9 +    bool non_volatile = (atp->field() != NULL) && !atp->field()->is_volatile();
   19.10 +    bool is_stable_ary = FoldStableValues &&
   19.11 +                         (tp != NULL) && (tp->isa_aryptr() != NULL) &&
   19.12 +                         tp->isa_aryptr()->is_stable();
   19.13 +
   19.14 +    return (eliminate_boxing && non_volatile) || is_stable_ary;
   19.15 +  }
   19.16 +
   19.17 +  return false;
   19.18 +}
   19.19 +
   19.20  //---------------------------can_see_stored_value------------------------------
   19.21  // This routine exists to make sure this set of tests is done the same
   19.22  // everywhere.  We need to make a coordinated change: first LoadNode::Ideal
   19.23 @@ -976,11 +989,9 @@
   19.24    const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr();
   19.25    Compile::AliasType* atp = (tp != NULL) ? phase->C->alias_type(tp) : NULL;
   19.26    // This is more general than load from boxing objects.
   19.27 -  if (phase->C->eliminate_boxing() && (atp != NULL) &&
   19.28 -      (atp->index() >= Compile::AliasIdxRaw) &&
   19.29 -      (atp->field() != NULL) && !atp->field()->is_volatile()) {
   19.30 +  if (skip_through_membars(atp, tp, phase->C->eliminate_boxing())) {
   19.31      uint alias_idx = atp->index();
   19.32 -    bool final = atp->field()->is_final();
   19.33 +    bool final = !atp->is_rewritable();
   19.34      Node* result = NULL;
   19.35      Node* current = st;
   19.36      // Skip through chains of MemBarNodes checking the MergeMems for
   19.37 @@ -1015,7 +1026,6 @@
   19.38      }
   19.39    }
   19.40  
   19.41 -
   19.42    // Loop around twice in the case Load -> Initialize -> Store.
   19.43    // (See PhaseIterGVN::add_users_to_worklist, which knows about this case.)
   19.44    for (int trip = 0; trip <= 1; trip++) {
   19.45 @@ -1577,6 +1587,40 @@
   19.46    return NULL;
   19.47  }
   19.48  
   19.49 +// Try to constant-fold a stable array element.
   19.50 +static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) {
   19.51 +  assert(ary->is_stable(), "array should be stable");
   19.52 +
   19.53 +  if (ary->const_oop() != NULL) {
   19.54 +    // Decode the results of GraphKit::array_element_address.
   19.55 +    ciArray* aobj = ary->const_oop()->as_array();
   19.56 +    ciConstant con = aobj->element_value_by_offset(off);
   19.57 +
   19.58 +    if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) {
   19.59 +      const Type* con_type = Type::make_from_constant(con);
   19.60 +      if (con_type != NULL) {
   19.61 +        if (con_type->isa_aryptr()) {
   19.62 +          // Join with the array element type, in case it is also stable.
   19.63 +          int dim = ary->stable_dimension();
   19.64 +          con_type = con_type->is_aryptr()->cast_to_stable(true, dim-1);
   19.65 +        }
   19.66 +        if (loadbt == T_NARROWOOP && con_type->isa_oopptr()) {
   19.67 +          con_type = con_type->make_narrowoop();
   19.68 +        }
   19.69 +#ifndef PRODUCT
   19.70 +        if (TraceIterativeGVN) {
   19.71 +          tty->print("FoldStableValues: array element [off=%d]: con_type=", off);
   19.72 +          con_type->dump(); tty->cr();
   19.73 +        }
   19.74 +#endif //PRODUCT
   19.75 +        return con_type;
   19.76 +      }
   19.77 +    }
   19.78 +  }
   19.79 +
   19.80 +  return NULL;
   19.81 +}
   19.82 +
   19.83  //------------------------------Value-----------------------------------------
   19.84  const Type *LoadNode::Value( PhaseTransform *phase ) const {
   19.85    // Either input is TOP ==> the result is TOP
   19.86 @@ -1591,8 +1635,31 @@
   19.87    Compile* C = phase->C;
   19.88  
   19.89    // Try to guess loaded type from pointer type
   19.90 -  if (tp->base() == Type::AryPtr) {
   19.91 -    const Type *t = tp->is_aryptr()->elem();
   19.92 +  if (tp->isa_aryptr()) {
   19.93 +    const TypeAryPtr* ary = tp->is_aryptr();
   19.94 +    const Type *t = ary->elem();
   19.95 +
   19.96 +    // Determine whether the reference is beyond the header or not, by comparing
   19.97 +    // the offset against the offset of the start of the array's data.
   19.98 +    // Different array types begin at slightly different offsets (12 vs. 16).
   19.99 +    // We choose T_BYTE as an example base type that is least restrictive
  19.100 +    // as to alignment, which will therefore produce the smallest
  19.101 +    // possible base offset.
  19.102 +    const int min_base_off = arrayOopDesc::base_offset_in_bytes(T_BYTE);
  19.103 +    const bool off_beyond_header = ((uint)off >= (uint)min_base_off);
  19.104 +
  19.105 +    // Try to constant-fold a stable array element.
  19.106 +    if (FoldStableValues && ary->is_stable()) {
  19.107 +      // Make sure the reference is not into the header
  19.108 +      if (off_beyond_header && off != Type::OffsetBot) {
  19.109 +        assert(adr->is_AddP() && adr->in(AddPNode::Offset)->is_Con(), "offset is a constant");
  19.110 +        const Type* con_type = fold_stable_ary_elem(ary, off, memory_type());
  19.111 +        if (con_type != NULL) {
  19.112 +          return con_type;
  19.113 +        }
  19.114 +      }
  19.115 +    }
  19.116 +
  19.117      // Don't do this for integer types. There is only potential profit if
  19.118      // the element type t is lower than _type; that is, for int types, if _type is
  19.119      // more restrictive than t.  This only happens here if one is short and the other
  19.120 @@ -1613,14 +1680,7 @@
  19.121          && Opcode() != Op_LoadKlass && Opcode() != Op_LoadNKlass) {
  19.122        // t might actually be lower than _type, if _type is a unique
  19.123        // concrete subclass of abstract class t.
  19.124 -      // Make sure the reference is not into the header, by comparing
  19.125 -      // the offset against the offset of the start of the array's data.
  19.126 -      // Different array types begin at slightly different offsets (12 vs. 16).
  19.127 -      // We choose T_BYTE as an example base type that is least restrictive
  19.128 -      // as to alignment, which will therefore produce the smallest
  19.129 -      // possible base offset.
  19.130 -      const int min_base_off = arrayOopDesc::base_offset_in_bytes(T_BYTE);
  19.131 -      if ((uint)off >= (uint)min_base_off) {  // is the offset beyond the header?
  19.132 +      if (off_beyond_header) {  // is the offset beyond the header?
  19.133          const Type* jt = t->join(_type);
  19.134          // In any case, do not allow the join, per se, to empty out the type.
  19.135          if (jt->empty() && !t->empty()) {
    20.1 --- a/src/share/vm/opto/parse.hpp	Mon Sep 09 19:53:28 2013 +0200
    20.2 +++ b/src/share/vm/opto/parse.hpp	Tue Sep 10 14:51:48 2013 -0700
    20.3 @@ -518,7 +518,7 @@
    20.4  
    20.5    // loading from a constant field or the constant pool
    20.6    // returns false if push failed (non-perm field constants only, not ldcs)
    20.7 -  bool push_constant(ciConstant con, bool require_constant = false, bool is_autobox_cache = false);
    20.8 +  bool push_constant(ciConstant con, bool require_constant = false, bool is_autobox_cache = false, const Type* basic_type = NULL);
    20.9  
   20.10    // implementation of object creation bytecodes
   20.11    void emit_guard_for_new(ciInstanceKlass* klass);
    21.1 --- a/src/share/vm/opto/parse3.cpp	Mon Sep 09 19:53:28 2013 +0200
    21.2 +++ b/src/share/vm/opto/parse3.cpp	Tue Sep 10 14:51:48 2013 -0700
    21.3 @@ -147,7 +147,15 @@
    21.4  void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
    21.5    // Does this field have a constant value?  If so, just push the value.
    21.6    if (field->is_constant()) {
    21.7 -    // final field
    21.8 +    // final or stable field
    21.9 +    const Type* stable_type = NULL;
   21.10 +    if (FoldStableValues && field->is_stable()) {
   21.11 +      stable_type = Type::get_const_type(field->type());
   21.12 +      if (field->type()->is_array_klass()) {
   21.13 +        int stable_dimension = field->type()->as_array_klass()->dimension();
   21.14 +        stable_type = stable_type->is_aryptr()->cast_to_stable(true, stable_dimension);
   21.15 +      }
   21.16 +    }
   21.17      if (field->is_static()) {
   21.18        // final static field
   21.19        if (C->eliminate_boxing()) {
   21.20 @@ -167,11 +175,10 @@
   21.21            }
   21.22          }
   21.23        }
   21.24 -      if (push_constant(field->constant_value()))
   21.25 +      if (push_constant(field->constant_value(), false, false, stable_type))
   21.26          return;
   21.27 -    }
   21.28 -    else {
   21.29 -      // final non-static field
   21.30 +    } else {
   21.31 +      // final or stable non-static field
   21.32        // Treat final non-static fields of trusted classes (classes in
   21.33        // java.lang.invoke and sun.invoke packages and subpackages) as
   21.34        // compile time constants.
   21.35 @@ -179,8 +186,12 @@
   21.36          const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr();
   21.37          ciObject* constant_oop = oop_ptr->const_oop();
   21.38          ciConstant constant = field->constant_value_of(constant_oop);
   21.39 -        if (push_constant(constant, true))
   21.40 -          return;
   21.41 +        if (FoldStableValues && field->is_stable() && constant.is_null_or_zero()) {
   21.42 +          // fall through to field load; the field is not yet initialized
   21.43 +        } else {
   21.44 +          if (push_constant(constant, true, false, stable_type))
   21.45 +            return;
   21.46 +        }
   21.47        }
   21.48      }
   21.49    }
   21.50 @@ -301,7 +312,8 @@
   21.51    // Note the presence of writes to final non-static fields, so that we
   21.52    // can insert a memory barrier later on to keep the writes from floating
   21.53    // out of the constructor.
   21.54 -  if (is_field && field->is_final()) {
   21.55 +  // Any method can write a @Stable field; insert memory barriers after those also.
   21.56 +  if (is_field && (field->is_final() || field->is_stable())) {
   21.57      set_wrote_final(true);
   21.58      // Preserve allocation ptr to create precedent edge to it in membar
   21.59      // generated on exit from constructor.
   21.60 @@ -314,35 +326,21 @@
   21.61  }
   21.62  
   21.63  
   21.64 -bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_autobox_cache) {
   21.65 +
   21.66 +bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_autobox_cache, const Type* stable_type) {
   21.67 +  const Type* con_type = Type::make_from_constant(constant, require_constant, is_autobox_cache);
   21.68    switch (constant.basic_type()) {
   21.69 -  case T_BOOLEAN:  push( intcon(constant.as_boolean()) ); break;
   21.70 -  case T_INT:      push( intcon(constant.as_int())     ); break;
   21.71 -  case T_CHAR:     push( intcon(constant.as_char())    ); break;
   21.72 -  case T_BYTE:     push( intcon(constant.as_byte())    ); break;
   21.73 -  case T_SHORT:    push( intcon(constant.as_short())   ); break;
   21.74 -  case T_FLOAT:    push( makecon(TypeF::make(constant.as_float())) );  break;
   21.75 -  case T_DOUBLE:   push_pair( makecon(TypeD::make(constant.as_double())) );  break;
   21.76 -  case T_LONG:     push_pair( longcon(constant.as_long()) ); break;
   21.77    case T_ARRAY:
   21.78 -  case T_OBJECT: {
   21.79 +  case T_OBJECT:
   21.80      // cases:
   21.81      //   can_be_constant    = (oop not scavengable || ScavengeRootsInCode != 0)
   21.82      //   should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
   21.83      // An oop is not scavengable if it is in the perm gen.
   21.84 -    ciObject* oop_constant = constant.as_object();
   21.85 -    if (oop_constant->is_null_object()) {
   21.86 -      push( zerocon(T_OBJECT) );
   21.87 -      break;
   21.88 -    } else if (require_constant || oop_constant->should_be_constant()) {
   21.89 -      push( makecon(TypeOopPtr::make_from_constant(oop_constant, require_constant, is_autobox_cache)) );
   21.90 -      break;
   21.91 -    } else {
   21.92 -      // we cannot inline the oop, but we can use it later to narrow a type
   21.93 -      return false;
   21.94 -    }
   21.95 -  }
   21.96 -  case T_ILLEGAL: {
   21.97 +    if (stable_type != NULL && con_type != NULL && con_type->isa_oopptr())
   21.98 +      con_type = con_type->join(stable_type);
   21.99 +    break;
  21.100 +
  21.101 +  case T_ILLEGAL:
  21.102      // Invalid ciConstant returned due to OutOfMemoryError in the CI
  21.103      assert(C->env()->failing(), "otherwise should not see this");
  21.104      // These always occur because of object types; we are going to
  21.105 @@ -350,17 +348,16 @@
  21.106      push( zerocon(T_OBJECT) );
  21.107      return false;
  21.108    }
  21.109 -  default:
  21.110 -    ShouldNotReachHere();
  21.111 +
  21.112 +  if (con_type == NULL)
  21.113 +    // we cannot inline the oop, but we can use it later to narrow a type
  21.114      return false;
  21.115 -  }
  21.116  
  21.117 -  // success
  21.118 +  push_node(constant.basic_type(), makecon(con_type));
  21.119    return true;
  21.120  }
  21.121  
  21.122  
  21.123 -
  21.124  //=============================================================================
  21.125  void Parse::do_anewarray() {
  21.126    bool will_link;
    22.1 --- a/src/share/vm/opto/type.cpp	Mon Sep 09 19:53:28 2013 +0200
    22.2 +++ b/src/share/vm/opto/type.cpp	Tue Sep 10 14:51:48 2013 -0700
    22.3 @@ -189,6 +189,38 @@
    22.4  }
    22.5  
    22.6  
    22.7 +//-----------------------make_from_constant------------------------------------
    22.8 +const Type* Type::make_from_constant(ciConstant constant,
    22.9 +                                     bool require_constant, bool is_autobox_cache) {
   22.10 +  switch (constant.basic_type()) {
   22.11 +  case T_BOOLEAN:  return TypeInt::make(constant.as_boolean());
   22.12 +  case T_CHAR:     return TypeInt::make(constant.as_char());
   22.13 +  case T_BYTE:     return TypeInt::make(constant.as_byte());
   22.14 +  case T_SHORT:    return TypeInt::make(constant.as_short());
   22.15 +  case T_INT:      return TypeInt::make(constant.as_int());
   22.16 +  case T_LONG:     return TypeLong::make(constant.as_long());
   22.17 +  case T_FLOAT:    return TypeF::make(constant.as_float());
   22.18 +  case T_DOUBLE:   return TypeD::make(constant.as_double());
   22.19 +  case T_ARRAY:
   22.20 +  case T_OBJECT:
   22.21 +    {
   22.22 +      // cases:
   22.23 +      //   can_be_constant    = (oop not scavengable || ScavengeRootsInCode != 0)
   22.24 +      //   should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
   22.25 +      // An oop is not scavengable if it is in the perm gen.
   22.26 +      ciObject* oop_constant = constant.as_object();
   22.27 +      if (oop_constant->is_null_object()) {
   22.28 +        return Type::get_zero_type(T_OBJECT);
   22.29 +      } else if (require_constant || oop_constant->should_be_constant()) {
   22.30 +        return TypeOopPtr::make_from_constant(oop_constant, require_constant, is_autobox_cache);
   22.31 +      }
   22.32 +    }
   22.33 +  }
   22.34 +  // Fall through to failure
   22.35 +  return NULL;
   22.36 +}
   22.37 +
   22.38 +
   22.39  //------------------------------make-------------------------------------------
   22.40  // Create a simple Type, with default empty symbol sets.  Then hashcons it
   22.41  // and look for an existing copy in the type dictionary.
   22.42 @@ -1824,12 +1856,12 @@
   22.43  }
   22.44  
   22.45  //------------------------------make-------------------------------------------
   22.46 -const TypeAry *TypeAry::make( const Type *elem, const TypeInt *size) {
   22.47 +const TypeAry* TypeAry::make(const Type* elem, const TypeInt* size, bool stable) {
   22.48    if (UseCompressedOops && elem->isa_oopptr()) {
   22.49      elem = elem->make_narrowoop();
   22.50    }
   22.51    size = normalize_array_size(size);
   22.52 -  return (TypeAry*)(new TypeAry(elem,size))->hashcons();
   22.53 +  return (TypeAry*)(new TypeAry(elem,size,stable))->hashcons();
   22.54  }
   22.55  
   22.56  //------------------------------meet-------------------------------------------
   22.57 @@ -1850,7 +1882,8 @@
   22.58    case Array: {                 // Meeting 2 arrays?
   22.59      const TypeAry *a = t->is_ary();
   22.60      return TypeAry::make(_elem->meet(a->_elem),
   22.61 -                         _size->xmeet(a->_size)->is_int());
   22.62 +                         _size->xmeet(a->_size)->is_int(),
   22.63 +                         _stable & a->_stable);
   22.64    }
   22.65    case Top:
   22.66      break;
   22.67 @@ -1863,7 +1896,7 @@
   22.68  const Type *TypeAry::xdual() const {
   22.69    const TypeInt* size_dual = _size->dual()->is_int();
   22.70    size_dual = normalize_array_size(size_dual);
   22.71 -  return new TypeAry( _elem->dual(), size_dual);
   22.72 +  return new TypeAry(_elem->dual(), size_dual, !_stable);
   22.73  }
   22.74  
   22.75  //------------------------------eq---------------------------------------------
   22.76 @@ -1871,13 +1904,14 @@
   22.77  bool TypeAry::eq( const Type *t ) const {
   22.78    const TypeAry *a = (const TypeAry*)t;
   22.79    return _elem == a->_elem &&
   22.80 +    _stable == a->_stable &&
   22.81      _size == a->_size;
   22.82  }
   22.83  
   22.84  //------------------------------hash-------------------------------------------
   22.85  // Type-specific hashing function.
   22.86  int TypeAry::hash(void) const {
   22.87 -  return (intptr_t)_elem + (intptr_t)_size;
   22.88 +  return (intptr_t)_elem + (intptr_t)_size + (_stable ? 43 : 0);
   22.89  }
   22.90  
   22.91  //----------------------interface_vs_oop---------------------------------------
   22.92 @@ -1894,6 +1928,7 @@
   22.93  //------------------------------dump2------------------------------------------
   22.94  #ifndef PRODUCT
   22.95  void TypeAry::dump2( Dict &d, uint depth, outputStream *st ) const {
   22.96 +  if (_stable)  st->print("stable:");
   22.97    _elem->dump2(d, depth, st);
   22.98    st->print("[");
   22.99    _size->dump2(d, depth, st);
  22.100 @@ -3457,11 +3492,39 @@
  22.101    assert(new_size != NULL, "");
  22.102    new_size = narrow_size_type(new_size);
  22.103    if (new_size == size())  return this;
  22.104 -  const TypeAry* new_ary = TypeAry::make(elem(), new_size);
  22.105 +  const TypeAry* new_ary = TypeAry::make(elem(), new_size, is_stable());
  22.106    return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id);
  22.107  }
  22.108  
  22.109  
  22.110 +//------------------------------cast_to_stable---------------------------------
  22.111 +const TypeAryPtr* TypeAryPtr::cast_to_stable(bool stable, int stable_dimension) const {
  22.112 +  if (stable_dimension <= 0 || (stable_dimension == 1 && stable == this->is_stable()))
  22.113 +    return this;
  22.114 +
  22.115 +  const Type* elem = this->elem();
  22.116 +  const TypePtr* elem_ptr = elem->make_ptr();
  22.117 +
  22.118 +  if (stable_dimension > 1 && elem_ptr != NULL && elem_ptr->isa_aryptr()) {
  22.119 +    // If this is widened from a narrow oop, TypeAry::make will re-narrow it.
  22.120 +    elem = elem_ptr = elem_ptr->is_aryptr()->cast_to_stable(stable, stable_dimension - 1);
  22.121 +  }
  22.122 +
  22.123 +  const TypeAry* new_ary = TypeAry::make(elem, size(), stable);
  22.124 +
  22.125 +  return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id);
  22.126 +}
  22.127 +
  22.128 +//-----------------------------stable_dimension--------------------------------
  22.129 +int TypeAryPtr::stable_dimension() const {
  22.130 +  if (!is_stable())  return 0;
  22.131 +  int dim = 1;
  22.132 +  const TypePtr* elem_ptr = elem()->make_ptr();
  22.133 +  if (elem_ptr != NULL && elem_ptr->isa_aryptr())
  22.134 +    dim += elem_ptr->is_aryptr()->stable_dimension();
  22.135 +  return dim;
  22.136 +}
  22.137 +
  22.138  //------------------------------eq---------------------------------------------
  22.139  // Structural equality check for Type representations
  22.140  bool TypeAryPtr::eq( const Type *t ) const {
  22.141 @@ -3570,7 +3633,7 @@
  22.142          // Something like byte[int+] meets char[int+].
  22.143          // This must fall to bottom, not (int[-128..65535])[int+].
  22.144          instance_id = InstanceBot;
  22.145 -        tary = TypeAry::make(Type::BOTTOM, tary->_size);
  22.146 +        tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
  22.147        }
  22.148      } else // Non integral arrays.
  22.149      // Must fall to bottom if exact klasses in upper lattice
  22.150 @@ -3584,7 +3647,7 @@
  22.151           (tap ->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) ||
  22.152           // 'this' is exact and super or unrelated:
  22.153           (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) {
  22.154 -      tary = TypeAry::make(Type::BOTTOM, tary->_size);
  22.155 +      tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
  22.156        return make( NotNull, NULL, tary, lazy_klass, false, off, InstanceBot );
  22.157      }
  22.158  
    23.1 --- a/src/share/vm/opto/type.hpp	Mon Sep 09 19:53:28 2013 +0200
    23.2 +++ b/src/share/vm/opto/type.hpp	Tue Sep 10 14:51:48 2013 -0700
    23.3 @@ -372,6 +372,10 @@
    23.4    // Mapping from CI type system to compiler type:
    23.5    static const Type* get_typeflow_type(ciType* type);
    23.6  
    23.7 +  static const Type* make_from_constant(ciConstant constant,
    23.8 +                                        bool require_constant = false,
    23.9 +                                        bool is_autobox_cache = false);
   23.10 +
   23.11  private:
   23.12    // support arrays
   23.13    static const BasicType _basic_type[];
   23.14 @@ -588,8 +592,8 @@
   23.15  //------------------------------TypeAry----------------------------------------
   23.16  // Class of Array Types
   23.17  class TypeAry : public Type {
   23.18 -  TypeAry( const Type *elem, const TypeInt *size) : Type(Array),
   23.19 -    _elem(elem), _size(size) {}
   23.20 +  TypeAry(const Type* elem, const TypeInt* size, bool stable) : Type(Array),
   23.21 +      _elem(elem), _size(size), _stable(stable) {}
   23.22  public:
   23.23    virtual bool eq( const Type *t ) const;
   23.24    virtual int  hash() const;             // Type specific hashing
   23.25 @@ -599,10 +603,11 @@
   23.26  private:
   23.27    const Type *_elem;            // Element type of array
   23.28    const TypeInt *_size;         // Elements in array
   23.29 +  const bool _stable;           // Are elements @Stable?
   23.30    friend class TypeAryPtr;
   23.31  
   23.32  public:
   23.33 -  static const TypeAry *make(  const Type *elem, const TypeInt *size);
   23.34 +  static const TypeAry* make(const Type* elem, const TypeInt* size, bool stable = false);
   23.35  
   23.36    virtual const Type *xmeet( const Type *t ) const;
   23.37    virtual const Type *xdual() const;    // Compute dual right now.
   23.38 @@ -988,6 +993,7 @@
   23.39    const TypeAry* ary() const  { return _ary; }
   23.40    const Type*    elem() const { return _ary->_elem; }
   23.41    const TypeInt* size() const { return _ary->_size; }
   23.42 +  bool      is_stable() const { return _ary->_stable; }
   23.43  
   23.44    bool is_autobox_cache() const { return _is_autobox_cache; }
   23.45  
   23.46 @@ -1011,6 +1017,9 @@
   23.47    virtual const Type *xmeet( const Type *t ) const;
   23.48    virtual const Type *xdual() const;    // Compute dual right now.
   23.49  
   23.50 +  const TypeAryPtr* cast_to_stable(bool stable, int stable_dimension = 1) const;
   23.51 +  int stable_dimension() const;
   23.52 +
   23.53    // Convenience common pre-built types.
   23.54    static const TypeAryPtr *RANGE;
   23.55    static const TypeAryPtr *OOPS;
    24.1 --- a/src/share/vm/runtime/globals.hpp	Mon Sep 09 19:53:28 2013 +0200
    24.2 +++ b/src/share/vm/runtime/globals.hpp	Tue Sep 10 14:51:48 2013 -0700
    24.3 @@ -3649,6 +3649,9 @@
    24.4    experimental(bool, TrustFinalNonStaticFields, false,                      \
    24.5            "trust final non-static declarations for constant folding")       \
    24.6                                                                              \
    24.7 +  experimental(bool, FoldStableValues, false,                               \
    24.8 +          "Private flag to control optimizations for stable variables")     \
    24.9 +                                                                            \
   24.10    develop(bool, TraceInvokeDynamic, false,                                  \
   24.11            "trace internal invoke dynamic operations")                       \
   24.12                                                                              \
    25.1 --- a/src/share/vm/utilities/accessFlags.hpp	Mon Sep 09 19:53:28 2013 +0200
    25.2 +++ b/src/share/vm/utilities/accessFlags.hpp	Tue Sep 10 14:51:48 2013 -0700
    25.3 @@ -78,11 +78,13 @@
    25.4    JVM_ACC_FIELD_ACCESS_WATCHED       = 0x00002000,  // field access is watched by JVMTI
    25.5    JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000,  // field modification is watched by JVMTI
    25.6    JVM_ACC_FIELD_INTERNAL             = 0x00000400,  // internal field, same as JVM_ACC_ABSTRACT
    25.7 +  JVM_ACC_FIELD_STABLE               = 0x00000020,  // @Stable field, same as JVM_ACC_SYNCHRONIZED
    25.8    JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE = 0x00000800, // field has generic signature
    25.9  
   25.10    JVM_ACC_FIELD_INTERNAL_FLAGS       = JVM_ACC_FIELD_ACCESS_WATCHED |
   25.11                                         JVM_ACC_FIELD_MODIFICATION_WATCHED |
   25.12                                         JVM_ACC_FIELD_INTERNAL |
   25.13 +                                       JVM_ACC_FIELD_STABLE |
   25.14                                         JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE,
   25.15  
   25.16                                                      // flags accepted by set_field_flags()
   25.17 @@ -148,6 +150,7 @@
   25.18                                          { return (_flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; }
   25.19    bool on_stack() const                 { return (_flags & JVM_ACC_ON_STACK) != 0; }
   25.20    bool is_internal() const              { return (_flags & JVM_ACC_FIELD_INTERNAL) != 0; }
   25.21 +  bool is_stable() const                { return (_flags & JVM_ACC_FIELD_STABLE) != 0; }
   25.22    bool field_has_generic_signature() const
   25.23                                          { return (_flags & JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) != 0; }
   25.24  

mercurial