Merge

Mon, 16 Sep 2013 09:41:03 +0200

author
tschatzl
date
Mon, 16 Sep 2013 09:41:03 +0200
changeset 5710
884ed7a10f09
parent 5709
9cb63cd234a0
parent 5665
e42e456fbe6e
child 5712
f9b58dbeab91

Merge

src/share/vm/opto/compile.cpp 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/type.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/globals.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/.hgtags	Fri Sep 13 07:57:13 2013 +0200
     1.2 +++ b/.hgtags	Mon Sep 16 09:41:03 2013 +0200
     1.3 @@ -375,3 +375,5 @@
     1.4  18b4798adbc42c6fa16f5ecb7d5cd3ca130754bf hs25-b48
     1.5  aed585cafc0d9655726af6d1e1081d1c94cb3b5c jdk8-b106
     1.6  50794d8ac11c9579b41dec4de23b808fef9f34a1 hs25-b49
     1.7 +5b7f90aab3ad25a25b75b7b2bb18d5ae23d8231c jdk8-b107
     1.8 +a09fe9d1e016c285307507a5793bc4fa6215e9c9 hs25-b50
     2.1 --- a/make/hotspot_version	Fri Sep 13 07:57:13 2013 +0200
     2.2 +++ b/make/hotspot_version	Mon Sep 16 09:41:03 2013 +0200
     2.3 @@ -35,7 +35,7 @@
     2.4  
     2.5  HS_MAJOR_VER=25
     2.6  HS_MINOR_VER=0
     2.7 -HS_BUILD_NUMBER=50
     2.8 +HS_BUILD_NUMBER=51
     2.9  
    2.10  JDK_MAJOR_VER=1
    2.11  JDK_MINOR_VER=8
     3.1 --- a/src/cpu/sparc/vm/c2_globals_sparc.hpp	Fri Sep 13 07:57:13 2013 +0200
     3.2 +++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp	Mon Sep 16 09:41:03 2013 +0200
     3.3 @@ -57,6 +57,7 @@
     3.4  define_pd_global(bool, UseTLAB,                      true);
     3.5  define_pd_global(bool, ResizeTLAB,                   true);
     3.6  define_pd_global(intx, LoopUnrollLimit,              60); // Design center runs on 1.3.1
     3.7 +define_pd_global(intx, MinJumpTableSize,             5);
     3.8  
     3.9  // Peephole and CISC spilling both break the graph, and so makes the
    3.10  // scheduler sick.
     4.1 --- a/src/cpu/x86/vm/c2_globals_x86.hpp	Fri Sep 13 07:57:13 2013 +0200
     4.2 +++ b/src/cpu/x86/vm/c2_globals_x86.hpp	Mon Sep 16 09:41:03 2013 +0200
     4.3 @@ -30,7 +30,6 @@
     4.4  
     4.5  // Sets the default values for platform dependent flags used by the server compiler.
     4.6  // (see c2_globals.hpp).  Alpha-sorted.
     4.7 -
     4.8  define_pd_global(bool, BackgroundCompilation,        true);
     4.9  define_pd_global(bool, UseTLAB,                      true);
    4.10  define_pd_global(bool, ResizeTLAB,                   true);
    4.11 @@ -52,6 +51,7 @@
    4.12  define_pd_global(intx, ConditionalMoveLimit,         3);
    4.13  define_pd_global(intx, FLOATPRESSURE,                6);
    4.14  define_pd_global(intx, FreqInlineSize,               325);
    4.15 +define_pd_global(intx, MinJumpTableSize,             10);
    4.16  #ifdef AMD64
    4.17  define_pd_global(intx, INTPRESSURE,                  13);
    4.18  define_pd_global(intx, InteriorEntryAlignment,       16);
     5.1 --- a/src/share/vm/ci/ciArray.cpp	Fri Sep 13 07:57:13 2013 +0200
     5.2 +++ b/src/share/vm/ci/ciArray.cpp	Mon Sep 16 09:41:03 2013 +0200
     5.3 @@ -24,13 +24,92 @@
     5.4  
     5.5  #include "precompiled.hpp"
     5.6  #include "ci/ciArray.hpp"
     5.7 +#include "ci/ciArrayKlass.hpp"
     5.8 +#include "ci/ciConstant.hpp"
     5.9  #include "ci/ciKlass.hpp"
    5.10  #include "ci/ciUtilities.hpp"
    5.11 +#include "oops/objArrayOop.hpp"
    5.12 +#include "oops/typeArrayOop.hpp"
    5.13  
    5.14  // ciArray
    5.15  //
    5.16  // This class represents an arrayOop in the HotSpot virtual
    5.17  // machine.
    5.18 +static BasicType fixup_element_type(BasicType bt) {
    5.19 +  if (bt == T_ARRAY)    return T_OBJECT;
    5.20 +  if (bt == T_BOOLEAN)  return T_BYTE;
    5.21 +  return bt;
    5.22 +}
    5.23 +
    5.24 +ciConstant ciArray::element_value_impl(BasicType elembt,
    5.25 +                                       arrayOop ary,
    5.26 +                                       int index) {
    5.27 +  if (ary == NULL)
    5.28 +    return ciConstant();
    5.29 +  assert(ary->is_array(), "");
    5.30 +  if (index < 0 || index >= ary->length())
    5.31 +    return ciConstant();
    5.32 +  ArrayKlass* ak = (ArrayKlass*) ary->klass();
    5.33 +  BasicType abt = ak->element_type();
    5.34 +  if (fixup_element_type(elembt) !=
    5.35 +      fixup_element_type(abt))
    5.36 +    return ciConstant();
    5.37 +  switch (elembt) {
    5.38 +  case T_ARRAY:
    5.39 +  case T_OBJECT:
    5.40 +    {
    5.41 +      assert(ary->is_objArray(), "");
    5.42 +      objArrayOop objary = (objArrayOop) ary;
    5.43 +      oop elem = objary->obj_at(index);
    5.44 +      ciEnv* env = CURRENT_ENV;
    5.45 +      ciObject* box = env->get_object(elem);
    5.46 +      return ciConstant(T_OBJECT, box);
    5.47 +    }
    5.48 +  }
    5.49 +  assert(ary->is_typeArray(), "");
    5.50 +  typeArrayOop tary = (typeArrayOop) ary;
    5.51 +  jint value = 0;
    5.52 +  switch (elembt) {
    5.53 +  case T_LONG:          return ciConstant(tary->long_at(index));
    5.54 +  case T_FLOAT:         return ciConstant(tary->float_at(index));
    5.55 +  case T_DOUBLE:        return ciConstant(tary->double_at(index));
    5.56 +  default:              return ciConstant();
    5.57 +  case T_BYTE:          value = tary->byte_at(index);           break;
    5.58 +  case T_BOOLEAN:       value = tary->byte_at(index) & 1;       break;
    5.59 +  case T_SHORT:         value = tary->short_at(index);          break;
    5.60 +  case T_CHAR:          value = tary->char_at(index);           break;
    5.61 +  case T_INT:           value = tary->int_at(index);            break;
    5.62 +  }
    5.63 +  return ciConstant(elembt, value);
    5.64 +}
    5.65 +
    5.66 +// ------------------------------------------------------------------
    5.67 +// ciArray::element_value
    5.68 +//
    5.69 +// Current value of an element.
    5.70 +// Returns T_ILLEGAL if there is no element at the given index.
    5.71 +ciConstant ciArray::element_value(int index) {
    5.72 +  BasicType elembt = element_basic_type();
    5.73 +  GUARDED_VM_ENTRY(
    5.74 +    return element_value_impl(elembt, get_arrayOop(), index);
    5.75 +  )
    5.76 +}
    5.77 +
    5.78 +// ------------------------------------------------------------------
    5.79 +// ciArray::element_value_by_offset
    5.80 +//
    5.81 +// Current value of an element at the specified offset.
    5.82 +// Returns T_ILLEGAL if there is no element at the given offset.
    5.83 +ciConstant ciArray::element_value_by_offset(intptr_t element_offset) {
    5.84 +  BasicType elembt = element_basic_type();
    5.85 +  intptr_t shift  = exact_log2(type2aelembytes(elembt));
    5.86 +  intptr_t header = arrayOopDesc::base_offset_in_bytes(elembt);
    5.87 +  intptr_t index = (element_offset - header) >> shift;
    5.88 +  intptr_t offset = header + ((intptr_t)index << shift);
    5.89 +  if (offset != element_offset || index != (jint)index)
    5.90 +    return ciConstant();
    5.91 +  return element_value((jint) index);
    5.92 +}
    5.93  
    5.94  // ------------------------------------------------------------------
    5.95  // ciArray::print_impl
     6.1 --- a/src/share/vm/ci/ciArray.hpp	Fri Sep 13 07:57:13 2013 +0200
     6.2 +++ b/src/share/vm/ci/ciArray.hpp	Mon Sep 16 09:41:03 2013 +0200
     6.3 @@ -25,6 +25,8 @@
     6.4  #ifndef SHARE_VM_CI_CIARRAY_HPP
     6.5  #define SHARE_VM_CI_CIARRAY_HPP
     6.6  
     6.7 +#include "ci/ciArrayKlass.hpp"
     6.8 +#include "ci/ciConstant.hpp"
     6.9  #include "ci/ciObject.hpp"
    6.10  #include "oops/arrayOop.hpp"
    6.11  #include "oops/objArrayOop.hpp"
    6.12 @@ -45,15 +47,30 @@
    6.13  
    6.14    ciArray(ciKlass* klass, int len) : ciObject(klass), _length(len) {}
    6.15  
    6.16 -  arrayOop get_arrayOop() { return (arrayOop)get_oop(); }
    6.17 +  arrayOop get_arrayOop() const { return (arrayOop)get_oop(); }
    6.18  
    6.19    const char* type_string() { return "ciArray"; }
    6.20  
    6.21    void print_impl(outputStream* st);
    6.22  
    6.23 +  ciConstant element_value_impl(BasicType elembt, arrayOop ary, int index);
    6.24 +
    6.25  public:
    6.26    int length() { return _length; }
    6.27  
    6.28 +  // Convenience routines.
    6.29 +  ciArrayKlass* array_type()         { return klass()->as_array_klass(); }
    6.30 +  ciType*       element_type()       { return array_type()->element_type(); }
    6.31 +  BasicType     element_basic_type() { return element_type()->basic_type(); }
    6.32 +
    6.33 +  // Current value of an element.
    6.34 +  // Returns T_ILLEGAL if there is no element at the given index.
    6.35 +  ciConstant element_value(int index);
    6.36 +
    6.37 +  // Current value of an element at the specified offset.
    6.38 +  // Returns T_ILLEGAL if there is no element at the given offset.
    6.39 +  ciConstant element_value_by_offset(intptr_t element_offset);
    6.40 +
    6.41    // What kind of ciObject is this?
    6.42    bool is_array()        { return true; }
    6.43    bool is_java_object()  { return true; }
     7.1 --- a/src/share/vm/ci/ciConstant.hpp	Fri Sep 13 07:57:13 2013 +0200
     7.2 +++ b/src/share/vm/ci/ciConstant.hpp	Mon Sep 16 09:41:03 2013 +0200
     7.3 @@ -41,7 +41,6 @@
     7.4    union {
     7.5      jint      _int;
     7.6      jlong     _long;
     7.7 -    jint      _long_half[2];
     7.8      jfloat    _float;
     7.9      jdouble   _double;
    7.10      ciObject* _object;
    7.11 @@ -111,6 +110,20 @@
    7.12      return _value._object;
    7.13    }
    7.14  
    7.15 +  bool      is_null_or_zero() const {
    7.16 +    if (!is_java_primitive(basic_type())) {
    7.17 +      return as_object()->is_null_object();
    7.18 +    } else if (type2size[basic_type()] == 1) {
    7.19 +      // treat float bits as int, to avoid comparison with -0 and NaN
    7.20 +      return (_value._int == 0);
    7.21 +    } else if (type2size[basic_type()] == 2) {
    7.22 +      // treat double bits as long, to avoid comparison with -0 and NaN
    7.23 +      return (_value._long == 0);
    7.24 +    } else {
    7.25 +      return false;
    7.26 +    }
    7.27 +  }
    7.28 +
    7.29    // Debugging output
    7.30    void print();
    7.31  };
     8.1 --- a/src/share/vm/ci/ciField.cpp	Fri Sep 13 07:57:13 2013 +0200
     8.2 +++ b/src/share/vm/ci/ciField.cpp	Mon Sep 16 09:41:03 2013 +0200
     8.3 @@ -189,12 +189,14 @@
     8.4    _holder = CURRENT_ENV->get_instance_klass(fd->field_holder());
     8.5  
     8.6    // Check to see if the field is constant.
     8.7 -  if (_holder->is_initialized() && this->is_final()) {
     8.8 +  bool is_final = this->is_final();
     8.9 +  bool is_stable = FoldStableValues && this->is_stable();
    8.10 +  if (_holder->is_initialized() && (is_final || is_stable)) {
    8.11      if (!this->is_static()) {
    8.12        // A field can be constant if it's a final static field or if
    8.13        // it's a final non-static field of a trusted class (classes in
    8.14        // java.lang.invoke and sun.invoke packages and subpackages).
    8.15 -      if (trust_final_non_static_fields(_holder)) {
    8.16 +      if (is_stable || trust_final_non_static_fields(_holder)) {
    8.17          _is_constant = true;
    8.18          return;
    8.19        }
    8.20 @@ -227,7 +229,6 @@
    8.21  
    8.22      Handle mirror = k->java_mirror();
    8.23  
    8.24 -    _is_constant = true;
    8.25      switch(type()->basic_type()) {
    8.26      case T_BYTE:
    8.27        _constant_value = ciConstant(type()->basic_type(), mirror->byte_field(_offset));
    8.28 @@ -273,6 +274,12 @@
    8.29          }
    8.30        }
    8.31      }
    8.32 +    if (is_stable && _constant_value.is_null_or_zero()) {
    8.33 +      // It is not a constant after all; treat it as uninitialized.
    8.34 +      _is_constant = false;
    8.35 +    } else {
    8.36 +      _is_constant = true;
    8.37 +    }
    8.38    } else {
    8.39      _is_constant = false;
    8.40    }
    8.41 @@ -373,8 +380,11 @@
    8.42    tty->print(" signature=");
    8.43    _signature->print_symbol();
    8.44    tty->print(" offset=%d type=", _offset);
    8.45 -  if (_type != NULL) _type->print_name();
    8.46 -  else               tty->print("(reference)");
    8.47 +  if (_type != NULL)
    8.48 +    _type->print_name();
    8.49 +  else
    8.50 +    tty->print("(reference)");
    8.51 +  tty->print(" flags=%04x", flags().as_int());
    8.52    tty->print(" is_constant=%s", bool_to_str(_is_constant));
    8.53    if (_is_constant && is_static()) {
    8.54      tty->print(" constant_value=");
     9.1 --- a/src/share/vm/ci/ciField.hpp	Fri Sep 13 07:57:13 2013 +0200
     9.2 +++ b/src/share/vm/ci/ciField.hpp	Mon Sep 16 09:41:03 2013 +0200
     9.3 @@ -139,7 +139,10 @@
     9.4    //      non-constant fields.  These are java.lang.System.in
     9.5    //      and java.lang.System.out.  Abomination.
     9.6    //
     9.7 -  // Note: the check for case 4 is not yet implemented.
     9.8 +  // A field is also considered constant if it is marked @Stable
     9.9 +  // and is non-null (or non-zero, if a primitive).
    9.10 +  // For non-static fields, the null/zero check must be
    9.11 +  // arranged by the user, as constant_value().is_null_or_zero().
    9.12    bool is_constant() { return _is_constant; }
    9.13  
    9.14    // Get the constant value of this field.
    9.15 @@ -173,6 +176,7 @@
    9.16    bool is_protected   () { return flags().is_protected(); }
    9.17    bool is_static      () { return flags().is_static(); }
    9.18    bool is_final       () { return flags().is_final(); }
    9.19 +  bool is_stable      () { return flags().is_stable(); }
    9.20    bool is_volatile    () { return flags().is_volatile(); }
    9.21    bool is_transient   () { return flags().is_transient(); }
    9.22  
    10.1 --- a/src/share/vm/ci/ciFlags.hpp	Fri Sep 13 07:57:13 2013 +0200
    10.2 +++ b/src/share/vm/ci/ciFlags.hpp	Mon Sep 16 09:41:03 2013 +0200
    10.3 @@ -59,6 +59,7 @@
    10.4    bool is_interface   () const         { return (_flags & JVM_ACC_INTERFACE   ) != 0; }
    10.5    bool is_abstract    () const         { return (_flags & JVM_ACC_ABSTRACT    ) != 0; }
    10.6    bool is_strict      () const         { return (_flags & JVM_ACC_STRICT      ) != 0; }
    10.7 +  bool is_stable      () const         { return (_flags & JVM_ACC_FIELD_STABLE) != 0; }
    10.8  
    10.9    // Conversion
   10.10    jint   as_int()                      { return _flags; }
    11.1 --- a/src/share/vm/ci/ciInstance.cpp	Fri Sep 13 07:57:13 2013 +0200
    11.2 +++ b/src/share/vm/ci/ciInstance.cpp	Mon Sep 16 09:41:03 2013 +0200
    11.3 @@ -127,6 +127,8 @@
    11.4  ciConstant ciInstance::field_value_by_offset(int field_offset) {
    11.5    ciInstanceKlass* ik = klass()->as_instance_klass();
    11.6    ciField* field = ik->get_field_by_offset(field_offset, false);
    11.7 +  if (field == NULL)
    11.8 +    return ciConstant();  // T_ILLEGAL
    11.9    return field_value(field);
   11.10  }
   11.11  
    12.1 --- a/src/share/vm/ci/ciTypeArray.cpp	Fri Sep 13 07:57:13 2013 +0200
    12.2 +++ b/src/share/vm/ci/ciTypeArray.cpp	Mon Sep 16 09:41:03 2013 +0200
    12.3 @@ -39,5 +39,10 @@
    12.4  jchar ciTypeArray::char_at(int index) {
    12.5    VM_ENTRY_MARK;
    12.6    assert(index >= 0 && index < length(), "out of range");
    12.7 -  return get_typeArrayOop()->char_at(index);
    12.8 +  jchar c = get_typeArrayOop()->char_at(index);
    12.9 +#ifdef ASSERT
   12.10 +  jchar d = element_value(index).as_char();
   12.11 +  assert(c == d, "");
   12.12 +#endif //ASSERT
   12.13 +  return c;
   12.14  }
    13.1 --- a/src/share/vm/classfile/classFileParser.cpp	Fri Sep 13 07:57:13 2013 +0200
    13.2 +++ b/src/share/vm/classfile/classFileParser.cpp	Mon Sep 16 09:41:03 2013 +0200
    13.3 @@ -1774,6 +1774,10 @@
    13.4      if (_location != _in_method)  break;  // only allow for methods
    13.5      if (!privileged)              break;  // only allow in privileged code
    13.6      return _method_LambdaForm_Hidden;
    13.7 +  case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_invoke_Stable_signature):
    13.8 +    if (_location != _in_field)   break;  // only allow for fields
    13.9 +    if (!privileged)              break;  // only allow in privileged code
   13.10 +    return _field_Stable;
   13.11    case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Contended_signature):
   13.12      if (_location != _in_field && _location != _in_class)          break;  // only allow for fields and classes
   13.13      if (!EnableContended || (RestrictContended && !privileged))    break;  // honor privileges
   13.14 @@ -1786,6 +1790,8 @@
   13.15  void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
   13.16    if (is_contended())
   13.17      f->set_contended_group(contended_group());
   13.18 +  if (is_stable())
   13.19 +    f->set_stable(true);
   13.20  }
   13.21  
   13.22  ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
    14.1 --- a/src/share/vm/classfile/classFileParser.hpp	Fri Sep 13 07:57:13 2013 +0200
    14.2 +++ b/src/share/vm/classfile/classFileParser.hpp	Mon Sep 16 09:41:03 2013 +0200
    14.3 @@ -125,6 +125,7 @@
    14.4        _method_LambdaForm_Compiled,
    14.5        _method_LambdaForm_Hidden,
    14.6        _sun_misc_Contended,
    14.7 +      _field_Stable,
    14.8        _annotation_LIMIT
    14.9      };
   14.10      const Location _location;
   14.11 @@ -143,14 +144,23 @@
   14.12        assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
   14.13        _annotations_present |= nth_bit((int)id);
   14.14      }
   14.15 +
   14.16 +    void remove_annotation(ID id) {
   14.17 +      assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
   14.18 +      _annotations_present &= ~nth_bit((int)id);
   14.19 +    }
   14.20 +
   14.21      // Report if the annotation is present.
   14.22 -    bool has_any_annotations() { return _annotations_present != 0; }
   14.23 -    bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; }
   14.24 +    bool has_any_annotations() const { return _annotations_present != 0; }
   14.25 +    bool has_annotation(ID id) const { return (nth_bit((int)id) & _annotations_present) != 0; }
   14.26  
   14.27      void set_contended_group(u2 group) { _contended_group = group; }
   14.28 -    u2 contended_group() { return _contended_group; }
   14.29 +    u2 contended_group() const { return _contended_group; }
   14.30  
   14.31 -    bool is_contended() { return has_annotation(_sun_misc_Contended); }
   14.32 +    bool is_contended() const { return has_annotation(_sun_misc_Contended); }
   14.33 +
   14.34 +    void set_stable(bool stable) { set_annotation(_field_Stable); }
   14.35 +    bool is_stable() const { return has_annotation(_field_Stable); }
   14.36    };
   14.37  
   14.38    // This class also doubles as a holder for metadata cleanup.
    15.1 --- a/src/share/vm/classfile/vmSymbols.hpp	Fri Sep 13 07:57:13 2013 +0200
    15.2 +++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Sep 16 09:41:03 2013 +0200
    15.3 @@ -270,6 +270,7 @@
    15.4    template(java_lang_invoke_LambdaForm,               "java/lang/invoke/LambdaForm")              \
    15.5    template(java_lang_invoke_ForceInline_signature,    "Ljava/lang/invoke/ForceInline;")           \
    15.6    template(java_lang_invoke_DontInline_signature,     "Ljava/lang/invoke/DontInline;")            \
    15.7 +  template(sun_invoke_Stable_signature,               "Lsun/invoke/Stable;")                      \
    15.8    template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
    15.9    template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;")  \
   15.10    template(java_lang_invoke_MagicLambdaImpl,          "java/lang/invoke/MagicLambdaImpl")         \
    16.1 --- a/src/share/vm/oops/fieldInfo.hpp	Fri Sep 13 07:57:13 2013 +0200
    16.2 +++ b/src/share/vm/oops/fieldInfo.hpp	Mon Sep 16 09:41:03 2013 +0200
    16.3 @@ -240,6 +240,14 @@
    16.4      return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0;
    16.5    }
    16.6  
    16.7 +  bool is_stable() const {
    16.8 +    return (access_flags() & JVM_ACC_FIELD_STABLE) != 0;
    16.9 +  }
   16.10 +  void set_stable(bool z) {
   16.11 +    if (z) _shorts[access_flags_offset] |=  JVM_ACC_FIELD_STABLE;
   16.12 +    else   _shorts[access_flags_offset] &= ~JVM_ACC_FIELD_STABLE;
   16.13 +  }
   16.14 +
   16.15    Symbol* lookup_symbol(int symbol_index) const {
   16.16      assert(is_internal(), "only internal fields");
   16.17      return vmSymbols::symbol_at((vmSymbols::SID)symbol_index);
    17.1 --- a/src/share/vm/opto/c2_globals.hpp	Fri Sep 13 07:57:13 2013 +0200
    17.2 +++ b/src/share/vm/opto/c2_globals.hpp	Mon Sep 16 09:41:03 2013 +0200
    17.3 @@ -421,7 +421,7 @@
    17.4    product(bool, UseDivMod, true,                                            \
    17.5            "Use combined DivMod instruction if available")                   \
    17.6                                                                              \
    17.7 -  product(intx, MinJumpTableSize, 18,                                       \
    17.8 +  product_pd(intx, MinJumpTableSize,                                        \
    17.9            "Minimum number of targets in a generated jump table")            \
   17.10                                                                              \
   17.11    product(intx, MaxJumpTableSize, 65000,                                    \
   17.12 @@ -448,6 +448,9 @@
   17.13    product(bool, EliminateAutoBox, true,                                     \
   17.14            "Control optimizations for autobox elimination")                  \
   17.15                                                                              \
   17.16 +  experimental(bool, UseImplicitStableValues, false,                        \
   17.17 +          "Mark well-known stable fields as such (e.g. String.value)")      \
   17.18 +                                                                            \
   17.19    product(intx, AutoBoxCacheMax, 128,                                       \
   17.20            "Sets max value cached by the java.lang.Integer autobox cache")   \
   17.21                                                                              \
    18.1 --- a/src/share/vm/opto/compile.cpp	Fri Sep 13 07:57:13 2013 +0200
    18.2 +++ b/src/share/vm/opto/compile.cpp	Mon Sep 16 09:41:03 2013 +0200
    18.3 @@ -1297,6 +1297,10 @@
    18.4  
    18.5    // Array pointers need some flattening
    18.6    const TypeAryPtr *ta = tj->isa_aryptr();
    18.7 +  if (ta && ta->is_stable()) {
    18.8 +    // Erase stability property for alias analysis.
    18.9 +    tj = ta = ta->cast_to_stable(false);
   18.10 +  }
   18.11    if( ta && is_known_inst ) {
   18.12      if ( offset != Type::OffsetBot &&
   18.13           offset > arrayOopDesc::length_offset_in_bytes() ) {
   18.14 @@ -1497,6 +1501,7 @@
   18.15    _index = i;
   18.16    _adr_type = at;
   18.17    _field = NULL;
   18.18 +  _element = NULL;
   18.19    _is_rewritable = true; // default
   18.20    const TypeOopPtr *atoop = (at != NULL) ? at->isa_oopptr() : NULL;
   18.21    if (atoop != NULL && atoop->is_known_instance()) {
   18.22 @@ -1615,6 +1620,16 @@
   18.23            && flat->is_instptr()->klass() == env()->Class_klass())
   18.24          alias_type(idx)->set_rewritable(false);
   18.25      }
   18.26 +    if (flat->isa_aryptr()) {
   18.27 +#ifdef ASSERT
   18.28 +      const int header_size_min  = arrayOopDesc::base_offset_in_bytes(T_BYTE);
   18.29 +      // (T_BYTE has the weakest alignment and size restrictions...)
   18.30 +      assert(flat->offset() < header_size_min, "array body reference must be OffsetBot");
   18.31 +#endif
   18.32 +      if (flat->offset() == TypePtr::OffsetBot) {
   18.33 +        alias_type(idx)->set_element(flat->is_aryptr()->elem());
   18.34 +      }
   18.35 +    }
   18.36      if (flat->isa_klassptr()) {
   18.37        if (flat->offset() == in_bytes(Klass::super_check_offset_offset()))
   18.38          alias_type(idx)->set_rewritable(false);
   18.39 @@ -1677,7 +1692,7 @@
   18.40    else
   18.41      t = TypeOopPtr::make_from_klass_raw(field->holder());
   18.42    AliasType* atp = alias_type(t->add_offset(field->offset_in_bytes()), field);
   18.43 -  assert(field->is_final() == !atp->is_rewritable(), "must get the rewritable bits correct");
   18.44 +  assert((field->is_final() || field->is_stable()) == !atp->is_rewritable(), "must get the rewritable bits correct");
   18.45    return atp;
   18.46  }
   18.47  
    19.1 --- a/src/share/vm/opto/compile.hpp	Fri Sep 13 07:57:13 2013 +0200
    19.2 +++ b/src/share/vm/opto/compile.hpp	Mon Sep 16 09:41:03 2013 +0200
    19.3 @@ -72,6 +72,7 @@
    19.4  class StartNode;
    19.5  class SafePointNode;
    19.6  class JVMState;
    19.7 +class Type;
    19.8  class TypeData;
    19.9  class TypePtr;
   19.10  class TypeOopPtr;
   19.11 @@ -119,6 +120,7 @@
   19.12      int             _index;         // unique index, used with MergeMemNode
   19.13      const TypePtr*  _adr_type;      // normalized address type
   19.14      ciField*        _field;         // relevant instance field, or null if none
   19.15 +    const Type*     _element;       // relevant array element type, or null if none
   19.16      bool            _is_rewritable; // false if the memory is write-once only
   19.17      int             _general_index; // if this is type is an instance, the general
   19.18                                      // type that this is an instance of
   19.19 @@ -129,6 +131,7 @@
   19.20      int             index()         const { return _index; }
   19.21      const TypePtr*  adr_type()      const { return _adr_type; }
   19.22      ciField*        field()         const { return _field; }
   19.23 +    const Type*     element()       const { return _element; }
   19.24      bool            is_rewritable() const { return _is_rewritable; }
   19.25      bool            is_volatile()   const { return (_field ? _field->is_volatile() : false); }
   19.26      int             general_index() const { return (_general_index != 0) ? _general_index : _index; }
   19.27 @@ -137,7 +140,14 @@
   19.28      void set_field(ciField* f) {
   19.29        assert(!_field,"");
   19.30        _field = f;
   19.31 -      if (f->is_final())  _is_rewritable = false;
   19.32 +      if (f->is_final() || f->is_stable()) {
   19.33 +        // In the case of @Stable, multiple writes are possible but may be assumed to be no-ops.
   19.34 +        _is_rewritable = false;
   19.35 +      }
   19.36 +    }
   19.37 +    void set_element(const Type* e) {
   19.38 +      assert(_element == NULL, "");
   19.39 +      _element = e;
   19.40      }
   19.41  
   19.42      void print_on(outputStream* st) PRODUCT_RETURN;
    20.1 --- a/src/share/vm/opto/graphKit.cpp	Fri Sep 13 07:57:13 2013 +0200
    20.2 +++ b/src/share/vm/opto/graphKit.cpp	Mon Sep 16 09:41:03 2013 +0200
    20.3 @@ -3825,8 +3825,13 @@
    20.4                                                     TypeAry::make(TypeInt::CHAR,TypeInt::POS),
    20.5                                                     ciTypeArrayKlass::make(T_CHAR), true, 0);
    20.6    int value_field_idx = C->get_alias_index(value_field_type);
    20.7 -  return make_load(ctrl, basic_plus_adr(str, str, value_offset),
    20.8 -                   value_type, T_OBJECT, value_field_idx);
    20.9 +  Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset),
   20.10 +                         value_type, T_OBJECT, value_field_idx);
   20.11 +  // String.value field is known to be @Stable.
   20.12 +  if (UseImplicitStableValues) {
   20.13 +    load = cast_array_to_stable(load, value_type);
   20.14 +  }
   20.15 +  return load;
   20.16  }
   20.17  
   20.18  void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) {
   20.19 @@ -3844,9 +3849,6 @@
   20.20    const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
   20.21                                                       false, NULL, 0);
   20.22    const TypePtr* value_field_type = string_type->add_offset(value_offset);
   20.23 -  const TypeAryPtr*  value_type = TypeAryPtr::make(TypePtr::NotNull,
   20.24 -                                                   TypeAry::make(TypeInt::CHAR,TypeInt::POS),
   20.25 -                                                   ciTypeArrayKlass::make(T_CHAR), true, 0);
   20.26    int value_field_idx = C->get_alias_index(value_field_type);
   20.27    store_to_memory(ctrl, basic_plus_adr(str, value_offset),
   20.28                    value, T_OBJECT, value_field_idx);
   20.29 @@ -3861,3 +3863,9 @@
   20.30    store_to_memory(ctrl, basic_plus_adr(str, count_offset),
   20.31                    value, T_INT, count_field_idx);
   20.32  }
   20.33 +
   20.34 +Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) {
   20.35 +  // Reify the property as a CastPP node in Ideal graph to comply with monotonicity
   20.36 +  // assumption of CCP analysis.
   20.37 +  return _gvn.transform(new(C) CastPPNode(ary, ary_type->cast_to_stable(true)));
   20.38 +}
    21.1 --- a/src/share/vm/opto/graphKit.hpp	Fri Sep 13 07:57:13 2013 +0200
    21.2 +++ b/src/share/vm/opto/graphKit.hpp	Mon Sep 16 09:41:03 2013 +0200
    21.3 @@ -836,6 +836,9 @@
    21.4    // Insert a loop predicate into the graph
    21.5    void add_predicate(int nargs = 0);
    21.6    void add_predicate_impl(Deoptimization::DeoptReason reason, int nargs);
    21.7 +
    21.8 +  // Produce new array node of stable type
    21.9 +  Node* cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type);
   21.10  };
   21.11  
   21.12  // Helper class to support building of control flow branches. Upon
    22.1 --- a/src/share/vm/opto/library_call.cpp	Fri Sep 13 07:57:13 2013 +0200
    22.2 +++ b/src/share/vm/opto/library_call.cpp	Mon Sep 16 09:41:03 2013 +0200
    22.3 @@ -1280,6 +1280,11 @@
    22.4    const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin));
    22.5    const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot);
    22.6  
    22.7 +  // String.value field is known to be @Stable.
    22.8 +  if (UseImplicitStableValues) {
    22.9 +    target = cast_array_to_stable(target, target_type);
   22.10 +  }
   22.11 +
   22.12    IdealKit kit(this, false, true);
   22.13  #define __ kit.
   22.14    Node* zero             = __ ConI(0);
    23.1 --- a/src/share/vm/opto/memnode.cpp	Fri Sep 13 07:57:13 2013 +0200
    23.2 +++ b/src/share/vm/opto/memnode.cpp	Mon Sep 16 09:41:03 2013 +0200
    23.3 @@ -962,6 +962,19 @@
    23.4    return (uintptr_t)in(Control) + (uintptr_t)in(Memory) + (uintptr_t)in(Address);
    23.5  }
    23.6  
    23.7 +static bool skip_through_membars(Compile::AliasType* atp, const TypeInstPtr* tp, bool eliminate_boxing) {
    23.8 +  if ((atp != NULL) && (atp->index() >= Compile::AliasIdxRaw)) {
    23.9 +    bool non_volatile = (atp->field() != NULL) && !atp->field()->is_volatile();
   23.10 +    bool is_stable_ary = FoldStableValues &&
   23.11 +                         (tp != NULL) && (tp->isa_aryptr() != NULL) &&
   23.12 +                         tp->isa_aryptr()->is_stable();
   23.13 +
   23.14 +    return (eliminate_boxing && non_volatile) || is_stable_ary;
   23.15 +  }
   23.16 +
   23.17 +  return false;
   23.18 +}
   23.19 +
   23.20  //---------------------------can_see_stored_value------------------------------
   23.21  // This routine exists to make sure this set of tests is done the same
   23.22  // everywhere.  We need to make a coordinated change: first LoadNode::Ideal
   23.23 @@ -976,11 +989,9 @@
   23.24    const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr();
   23.25    Compile::AliasType* atp = (tp != NULL) ? phase->C->alias_type(tp) : NULL;
   23.26    // This is more general than load from boxing objects.
   23.27 -  if (phase->C->eliminate_boxing() && (atp != NULL) &&
   23.28 -      (atp->index() >= Compile::AliasIdxRaw) &&
   23.29 -      (atp->field() != NULL) && !atp->field()->is_volatile()) {
   23.30 +  if (skip_through_membars(atp, tp, phase->C->eliminate_boxing())) {
   23.31      uint alias_idx = atp->index();
   23.32 -    bool final = atp->field()->is_final();
   23.33 +    bool final = !atp->is_rewritable();
   23.34      Node* result = NULL;
   23.35      Node* current = st;
   23.36      // Skip through chains of MemBarNodes checking the MergeMems for
   23.37 @@ -1015,7 +1026,6 @@
   23.38      }
   23.39    }
   23.40  
   23.41 -
   23.42    // Loop around twice in the case Load -> Initialize -> Store.
   23.43    // (See PhaseIterGVN::add_users_to_worklist, which knows about this case.)
   23.44    for (int trip = 0; trip <= 1; trip++) {
   23.45 @@ -1577,6 +1587,40 @@
   23.46    return NULL;
   23.47  }
   23.48  
   23.49 +// Try to constant-fold a stable array element.
   23.50 +static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) {
   23.51 +  assert(ary->is_stable(), "array should be stable");
   23.52 +
   23.53 +  if (ary->const_oop() != NULL) {
   23.54 +    // Decode the results of GraphKit::array_element_address.
   23.55 +    ciArray* aobj = ary->const_oop()->as_array();
   23.56 +    ciConstant con = aobj->element_value_by_offset(off);
   23.57 +
   23.58 +    if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) {
   23.59 +      const Type* con_type = Type::make_from_constant(con);
   23.60 +      if (con_type != NULL) {
   23.61 +        if (con_type->isa_aryptr()) {
   23.62 +          // Join with the array element type, in case it is also stable.
   23.63 +          int dim = ary->stable_dimension();
   23.64 +          con_type = con_type->is_aryptr()->cast_to_stable(true, dim-1);
   23.65 +        }
   23.66 +        if (loadbt == T_NARROWOOP && con_type->isa_oopptr()) {
   23.67 +          con_type = con_type->make_narrowoop();
   23.68 +        }
   23.69 +#ifndef PRODUCT
   23.70 +        if (TraceIterativeGVN) {
   23.71 +          tty->print("FoldStableValues: array element [off=%d]: con_type=", off);
   23.72 +          con_type->dump(); tty->cr();
   23.73 +        }
   23.74 +#endif //PRODUCT
   23.75 +        return con_type;
   23.76 +      }
   23.77 +    }
   23.78 +  }
   23.79 +
   23.80 +  return NULL;
   23.81 +}
   23.82 +
   23.83  //------------------------------Value-----------------------------------------
   23.84  const Type *LoadNode::Value( PhaseTransform *phase ) const {
   23.85    // Either input is TOP ==> the result is TOP
   23.86 @@ -1591,8 +1635,31 @@
   23.87    Compile* C = phase->C;
   23.88  
   23.89    // Try to guess loaded type from pointer type
   23.90 -  if (tp->base() == Type::AryPtr) {
   23.91 -    const Type *t = tp->is_aryptr()->elem();
   23.92 +  if (tp->isa_aryptr()) {
   23.93 +    const TypeAryPtr* ary = tp->is_aryptr();
   23.94 +    const Type *t = ary->elem();
   23.95 +
   23.96 +    // Determine whether the reference is beyond the header or not, by comparing
   23.97 +    // the offset against the offset of the start of the array's data.
   23.98 +    // Different array types begin at slightly different offsets (12 vs. 16).
   23.99 +    // We choose T_BYTE as an example base type that is least restrictive
  23.100 +    // as to alignment, which will therefore produce the smallest
  23.101 +    // possible base offset.
  23.102 +    const int min_base_off = arrayOopDesc::base_offset_in_bytes(T_BYTE);
  23.103 +    const bool off_beyond_header = ((uint)off >= (uint)min_base_off);
  23.104 +
  23.105 +    // Try to constant-fold a stable array element.
  23.106 +    if (FoldStableValues && ary->is_stable()) {
  23.107 +      // Make sure the reference is not into the header
  23.108 +      if (off_beyond_header && off != Type::OffsetBot) {
  23.109 +        assert(adr->is_AddP() && adr->in(AddPNode::Offset)->is_Con(), "offset is a constant");
  23.110 +        const Type* con_type = fold_stable_ary_elem(ary, off, memory_type());
  23.111 +        if (con_type != NULL) {
  23.112 +          return con_type;
  23.113 +        }
  23.114 +      }
  23.115 +    }
  23.116 +
  23.117      // Don't do this for integer types. There is only potential profit if
  23.118      // the element type t is lower than _type; that is, for int types, if _type is
  23.119      // more restrictive than t.  This only happens here if one is short and the other
  23.120 @@ -1613,14 +1680,7 @@
  23.121          && Opcode() != Op_LoadKlass && Opcode() != Op_LoadNKlass) {
  23.122        // t might actually be lower than _type, if _type is a unique
  23.123        // concrete subclass of abstract class t.
  23.124 -      // Make sure the reference is not into the header, by comparing
  23.125 -      // the offset against the offset of the start of the array's data.
  23.126 -      // Different array types begin at slightly different offsets (12 vs. 16).
  23.127 -      // We choose T_BYTE as an example base type that is least restrictive
  23.128 -      // as to alignment, which will therefore produce the smallest
  23.129 -      // possible base offset.
  23.130 -      const int min_base_off = arrayOopDesc::base_offset_in_bytes(T_BYTE);
  23.131 -      if ((uint)off >= (uint)min_base_off) {  // is the offset beyond the header?
  23.132 +      if (off_beyond_header) {  // is the offset beyond the header?
  23.133          const Type* jt = t->join(_type);
  23.134          // In any case, do not allow the join, per se, to empty out the type.
  23.135          if (jt->empty() && !t->empty()) {
    24.1 --- a/src/share/vm/opto/parse.hpp	Fri Sep 13 07:57:13 2013 +0200
    24.2 +++ b/src/share/vm/opto/parse.hpp	Mon Sep 16 09:41:03 2013 +0200
    24.3 @@ -518,7 +518,7 @@
    24.4  
    24.5    // loading from a constant field or the constant pool
    24.6    // returns false if push failed (non-perm field constants only, not ldcs)
    24.7 -  bool push_constant(ciConstant con, bool require_constant = false, bool is_autobox_cache = false);
    24.8 +  bool push_constant(ciConstant con, bool require_constant = false, bool is_autobox_cache = false, const Type* basic_type = NULL);
    24.9  
   24.10    // implementation of object creation bytecodes
   24.11    void emit_guard_for_new(ciInstanceKlass* klass);
    25.1 --- a/src/share/vm/opto/parse3.cpp	Fri Sep 13 07:57:13 2013 +0200
    25.2 +++ b/src/share/vm/opto/parse3.cpp	Mon Sep 16 09:41:03 2013 +0200
    25.3 @@ -147,7 +147,15 @@
    25.4  void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
    25.5    // Does this field have a constant value?  If so, just push the value.
    25.6    if (field->is_constant()) {
    25.7 -    // final field
    25.8 +    // final or stable field
    25.9 +    const Type* stable_type = NULL;
   25.10 +    if (FoldStableValues && field->is_stable()) {
   25.11 +      stable_type = Type::get_const_type(field->type());
   25.12 +      if (field->type()->is_array_klass()) {
   25.13 +        int stable_dimension = field->type()->as_array_klass()->dimension();
   25.14 +        stable_type = stable_type->is_aryptr()->cast_to_stable(true, stable_dimension);
   25.15 +      }
   25.16 +    }
   25.17      if (field->is_static()) {
   25.18        // final static field
   25.19        if (C->eliminate_boxing()) {
   25.20 @@ -167,11 +175,10 @@
   25.21            }
   25.22          }
   25.23        }
   25.24 -      if (push_constant(field->constant_value()))
   25.25 +      if (push_constant(field->constant_value(), false, false, stable_type))
   25.26          return;
   25.27 -    }
   25.28 -    else {
   25.29 -      // final non-static field
   25.30 +    } else {
   25.31 +      // final or stable non-static field
   25.32        // Treat final non-static fields of trusted classes (classes in
   25.33        // java.lang.invoke and sun.invoke packages and subpackages) as
   25.34        // compile time constants.
   25.35 @@ -179,8 +186,12 @@
   25.36          const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr();
   25.37          ciObject* constant_oop = oop_ptr->const_oop();
   25.38          ciConstant constant = field->constant_value_of(constant_oop);
   25.39 -        if (push_constant(constant, true))
   25.40 -          return;
   25.41 +        if (FoldStableValues && field->is_stable() && constant.is_null_or_zero()) {
   25.42 +          // fall through to field load; the field is not yet initialized
   25.43 +        } else {
   25.44 +          if (push_constant(constant, true, false, stable_type))
   25.45 +            return;
   25.46 +        }
   25.47        }
   25.48      }
   25.49    }
   25.50 @@ -301,7 +312,8 @@
   25.51    // Note the presence of writes to final non-static fields, so that we
   25.52    // can insert a memory barrier later on to keep the writes from floating
   25.53    // out of the constructor.
   25.54 -  if (is_field && field->is_final()) {
   25.55 +  // Any method can write a @Stable field; insert memory barriers after those also.
   25.56 +  if (is_field && (field->is_final() || field->is_stable())) {
   25.57      set_wrote_final(true);
   25.58      // Preserve allocation ptr to create precedent edge to it in membar
   25.59      // generated on exit from constructor.
   25.60 @@ -314,35 +326,21 @@
   25.61  }
   25.62  
   25.63  
   25.64 -bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_autobox_cache) {
   25.65 +
   25.66 +bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_autobox_cache, const Type* stable_type) {
   25.67 +  const Type* con_type = Type::make_from_constant(constant, require_constant, is_autobox_cache);
   25.68    switch (constant.basic_type()) {
   25.69 -  case T_BOOLEAN:  push( intcon(constant.as_boolean()) ); break;
   25.70 -  case T_INT:      push( intcon(constant.as_int())     ); break;
   25.71 -  case T_CHAR:     push( intcon(constant.as_char())    ); break;
   25.72 -  case T_BYTE:     push( intcon(constant.as_byte())    ); break;
   25.73 -  case T_SHORT:    push( intcon(constant.as_short())   ); break;
   25.74 -  case T_FLOAT:    push( makecon(TypeF::make(constant.as_float())) );  break;
   25.75 -  case T_DOUBLE:   push_pair( makecon(TypeD::make(constant.as_double())) );  break;
   25.76 -  case T_LONG:     push_pair( longcon(constant.as_long()) ); break;
   25.77    case T_ARRAY:
   25.78 -  case T_OBJECT: {
   25.79 +  case T_OBJECT:
   25.80      // cases:
   25.81      //   can_be_constant    = (oop not scavengable || ScavengeRootsInCode != 0)
   25.82      //   should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
   25.83      // An oop is not scavengable if it is in the perm gen.
   25.84 -    ciObject* oop_constant = constant.as_object();
   25.85 -    if (oop_constant->is_null_object()) {
   25.86 -      push( zerocon(T_OBJECT) );
   25.87 -      break;
   25.88 -    } else if (require_constant || oop_constant->should_be_constant()) {
   25.89 -      push( makecon(TypeOopPtr::make_from_constant(oop_constant, require_constant, is_autobox_cache)) );
   25.90 -      break;
   25.91 -    } else {
   25.92 -      // we cannot inline the oop, but we can use it later to narrow a type
   25.93 -      return false;
   25.94 -    }
   25.95 -  }
   25.96 -  case T_ILLEGAL: {
   25.97 +    if (stable_type != NULL && con_type != NULL && con_type->isa_oopptr())
   25.98 +      con_type = con_type->join(stable_type);
   25.99 +    break;
  25.100 +
  25.101 +  case T_ILLEGAL:
  25.102      // Invalid ciConstant returned due to OutOfMemoryError in the CI
  25.103      assert(C->env()->failing(), "otherwise should not see this");
  25.104      // These always occur because of object types; we are going to
  25.105 @@ -350,17 +348,16 @@
  25.106      push( zerocon(T_OBJECT) );
  25.107      return false;
  25.108    }
  25.109 -  default:
  25.110 -    ShouldNotReachHere();
  25.111 +
  25.112 +  if (con_type == NULL)
  25.113 +    // we cannot inline the oop, but we can use it later to narrow a type
  25.114      return false;
  25.115 -  }
  25.116  
  25.117 -  // success
  25.118 +  push_node(constant.basic_type(), makecon(con_type));
  25.119    return true;
  25.120  }
  25.121  
  25.122  
  25.123 -
  25.124  //=============================================================================
  25.125  void Parse::do_anewarray() {
  25.126    bool will_link;
    26.1 --- a/src/share/vm/opto/type.cpp	Fri Sep 13 07:57:13 2013 +0200
    26.2 +++ b/src/share/vm/opto/type.cpp	Mon Sep 16 09:41:03 2013 +0200
    26.3 @@ -189,6 +189,38 @@
    26.4  }
    26.5  
    26.6  
    26.7 +//-----------------------make_from_constant------------------------------------
    26.8 +const Type* Type::make_from_constant(ciConstant constant,
    26.9 +                                     bool require_constant, bool is_autobox_cache) {
   26.10 +  switch (constant.basic_type()) {
   26.11 +  case T_BOOLEAN:  return TypeInt::make(constant.as_boolean());
   26.12 +  case T_CHAR:     return TypeInt::make(constant.as_char());
   26.13 +  case T_BYTE:     return TypeInt::make(constant.as_byte());
   26.14 +  case T_SHORT:    return TypeInt::make(constant.as_short());
   26.15 +  case T_INT:      return TypeInt::make(constant.as_int());
   26.16 +  case T_LONG:     return TypeLong::make(constant.as_long());
   26.17 +  case T_FLOAT:    return TypeF::make(constant.as_float());
   26.18 +  case T_DOUBLE:   return TypeD::make(constant.as_double());
   26.19 +  case T_ARRAY:
   26.20 +  case T_OBJECT:
   26.21 +    {
   26.22 +      // cases:
   26.23 +      //   can_be_constant    = (oop not scavengable || ScavengeRootsInCode != 0)
   26.24 +      //   should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
   26.25 +      // An oop is not scavengable if it is in the perm gen.
   26.26 +      ciObject* oop_constant = constant.as_object();
   26.27 +      if (oop_constant->is_null_object()) {
   26.28 +        return Type::get_zero_type(T_OBJECT);
   26.29 +      } else if (require_constant || oop_constant->should_be_constant()) {
   26.30 +        return TypeOopPtr::make_from_constant(oop_constant, require_constant, is_autobox_cache);
   26.31 +      }
   26.32 +    }
   26.33 +  }
   26.34 +  // Fall through to failure
   26.35 +  return NULL;
   26.36 +}
   26.37 +
   26.38 +
   26.39  //------------------------------make-------------------------------------------
   26.40  // Create a simple Type, with default empty symbol sets.  Then hashcons it
   26.41  // and look for an existing copy in the type dictionary.
   26.42 @@ -1824,12 +1856,12 @@
   26.43  }
   26.44  
   26.45  //------------------------------make-------------------------------------------
   26.46 -const TypeAry *TypeAry::make( const Type *elem, const TypeInt *size) {
   26.47 +const TypeAry* TypeAry::make(const Type* elem, const TypeInt* size, bool stable) {
   26.48    if (UseCompressedOops && elem->isa_oopptr()) {
   26.49      elem = elem->make_narrowoop();
   26.50    }
   26.51    size = normalize_array_size(size);
   26.52 -  return (TypeAry*)(new TypeAry(elem,size))->hashcons();
   26.53 +  return (TypeAry*)(new TypeAry(elem,size,stable))->hashcons();
   26.54  }
   26.55  
   26.56  //------------------------------meet-------------------------------------------
   26.57 @@ -1850,7 +1882,8 @@
   26.58    case Array: {                 // Meeting 2 arrays?
   26.59      const TypeAry *a = t->is_ary();
   26.60      return TypeAry::make(_elem->meet(a->_elem),
   26.61 -                         _size->xmeet(a->_size)->is_int());
   26.62 +                         _size->xmeet(a->_size)->is_int(),
   26.63 +                         _stable & a->_stable);
   26.64    }
   26.65    case Top:
   26.66      break;
   26.67 @@ -1863,7 +1896,7 @@
   26.68  const Type *TypeAry::xdual() const {
   26.69    const TypeInt* size_dual = _size->dual()->is_int();
   26.70    size_dual = normalize_array_size(size_dual);
   26.71 -  return new TypeAry( _elem->dual(), size_dual);
   26.72 +  return new TypeAry(_elem->dual(), size_dual, !_stable);
   26.73  }
   26.74  
   26.75  //------------------------------eq---------------------------------------------
   26.76 @@ -1871,13 +1904,14 @@
   26.77  bool TypeAry::eq( const Type *t ) const {
   26.78    const TypeAry *a = (const TypeAry*)t;
   26.79    return _elem == a->_elem &&
   26.80 +    _stable == a->_stable &&
   26.81      _size == a->_size;
   26.82  }
   26.83  
   26.84  //------------------------------hash-------------------------------------------
   26.85  // Type-specific hashing function.
   26.86  int TypeAry::hash(void) const {
   26.87 -  return (intptr_t)_elem + (intptr_t)_size;
   26.88 +  return (intptr_t)_elem + (intptr_t)_size + (_stable ? 43 : 0);
   26.89  }
   26.90  
   26.91  //----------------------interface_vs_oop---------------------------------------
   26.92 @@ -1894,6 +1928,7 @@
   26.93  //------------------------------dump2------------------------------------------
   26.94  #ifndef PRODUCT
   26.95  void TypeAry::dump2( Dict &d, uint depth, outputStream *st ) const {
   26.96 +  if (_stable)  st->print("stable:");
   26.97    _elem->dump2(d, depth, st);
   26.98    st->print("[");
   26.99    _size->dump2(d, depth, st);
  26.100 @@ -3457,11 +3492,39 @@
  26.101    assert(new_size != NULL, "");
  26.102    new_size = narrow_size_type(new_size);
  26.103    if (new_size == size())  return this;
  26.104 -  const TypeAry* new_ary = TypeAry::make(elem(), new_size);
  26.105 +  const TypeAry* new_ary = TypeAry::make(elem(), new_size, is_stable());
  26.106    return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id);
  26.107  }
  26.108  
  26.109  
  26.110 +//------------------------------cast_to_stable---------------------------------
  26.111 +const TypeAryPtr* TypeAryPtr::cast_to_stable(bool stable, int stable_dimension) const {
  26.112 +  if (stable_dimension <= 0 || (stable_dimension == 1 && stable == this->is_stable()))
  26.113 +    return this;
  26.114 +
  26.115 +  const Type* elem = this->elem();
  26.116 +  const TypePtr* elem_ptr = elem->make_ptr();
  26.117 +
  26.118 +  if (stable_dimension > 1 && elem_ptr != NULL && elem_ptr->isa_aryptr()) {
  26.119 +    // If this is widened from a narrow oop, TypeAry::make will re-narrow it.
  26.120 +    elem = elem_ptr = elem_ptr->is_aryptr()->cast_to_stable(stable, stable_dimension - 1);
  26.121 +  }
  26.122 +
  26.123 +  const TypeAry* new_ary = TypeAry::make(elem, size(), stable);
  26.124 +
  26.125 +  return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id);
  26.126 +}
  26.127 +
  26.128 +//-----------------------------stable_dimension--------------------------------
  26.129 +int TypeAryPtr::stable_dimension() const {
  26.130 +  if (!is_stable())  return 0;
  26.131 +  int dim = 1;
  26.132 +  const TypePtr* elem_ptr = elem()->make_ptr();
  26.133 +  if (elem_ptr != NULL && elem_ptr->isa_aryptr())
  26.134 +    dim += elem_ptr->is_aryptr()->stable_dimension();
  26.135 +  return dim;
  26.136 +}
  26.137 +
  26.138  //------------------------------eq---------------------------------------------
  26.139  // Structural equality check for Type representations
  26.140  bool TypeAryPtr::eq( const Type *t ) const {
  26.141 @@ -3570,7 +3633,7 @@
  26.142          // Something like byte[int+] meets char[int+].
  26.143          // This must fall to bottom, not (int[-128..65535])[int+].
  26.144          instance_id = InstanceBot;
  26.145 -        tary = TypeAry::make(Type::BOTTOM, tary->_size);
  26.146 +        tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
  26.147        }
  26.148      } else // Non integral arrays.
  26.149      // Must fall to bottom if exact klasses in upper lattice
  26.150 @@ -3584,7 +3647,7 @@
  26.151           (tap ->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) ||
  26.152           // 'this' is exact and super or unrelated:
  26.153           (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) {
  26.154 -      tary = TypeAry::make(Type::BOTTOM, tary->_size);
  26.155 +      tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
  26.156        return make( NotNull, NULL, tary, lazy_klass, false, off, InstanceBot );
  26.157      }
  26.158  
    27.1 --- a/src/share/vm/opto/type.hpp	Fri Sep 13 07:57:13 2013 +0200
    27.2 +++ b/src/share/vm/opto/type.hpp	Mon Sep 16 09:41:03 2013 +0200
    27.3 @@ -372,6 +372,10 @@
    27.4    // Mapping from CI type system to compiler type:
    27.5    static const Type* get_typeflow_type(ciType* type);
    27.6  
    27.7 +  static const Type* make_from_constant(ciConstant constant,
    27.8 +                                        bool require_constant = false,
    27.9 +                                        bool is_autobox_cache = false);
   27.10 +
   27.11  private:
   27.12    // support arrays
   27.13    static const BasicType _basic_type[];
   27.14 @@ -588,8 +592,8 @@
   27.15  //------------------------------TypeAry----------------------------------------
   27.16  // Class of Array Types
   27.17  class TypeAry : public Type {
   27.18 -  TypeAry( const Type *elem, const TypeInt *size) : Type(Array),
   27.19 -    _elem(elem), _size(size) {}
   27.20 +  TypeAry(const Type* elem, const TypeInt* size, bool stable) : Type(Array),
   27.21 +      _elem(elem), _size(size), _stable(stable) {}
   27.22  public:
   27.23    virtual bool eq( const Type *t ) const;
   27.24    virtual int  hash() const;             // Type specific hashing
   27.25 @@ -599,10 +603,11 @@
   27.26  private:
   27.27    const Type *_elem;            // Element type of array
   27.28    const TypeInt *_size;         // Elements in array
   27.29 +  const bool _stable;           // Are elements @Stable?
   27.30    friend class TypeAryPtr;
   27.31  
   27.32  public:
   27.33 -  static const TypeAry *make(  const Type *elem, const TypeInt *size);
   27.34 +  static const TypeAry* make(const Type* elem, const TypeInt* size, bool stable = false);
   27.35  
   27.36    virtual const Type *xmeet( const Type *t ) const;
   27.37    virtual const Type *xdual() const;    // Compute dual right now.
   27.38 @@ -988,6 +993,7 @@
   27.39    const TypeAry* ary() const  { return _ary; }
   27.40    const Type*    elem() const { return _ary->_elem; }
   27.41    const TypeInt* size() const { return _ary->_size; }
   27.42 +  bool      is_stable() const { return _ary->_stable; }
   27.43  
   27.44    bool is_autobox_cache() const { return _is_autobox_cache; }
   27.45  
   27.46 @@ -1011,6 +1017,9 @@
   27.47    virtual const Type *xmeet( const Type *t ) const;
   27.48    virtual const Type *xdual() const;    // Compute dual right now.
   27.49  
   27.50 +  const TypeAryPtr* cast_to_stable(bool stable, int stable_dimension = 1) const;
   27.51 +  int stable_dimension() const;
   27.52 +
   27.53    // Convenience common pre-built types.
   27.54    static const TypeAryPtr *RANGE;
   27.55    static const TypeAryPtr *OOPS;
    28.1 --- a/src/share/vm/runtime/globals.hpp	Fri Sep 13 07:57:13 2013 +0200
    28.2 +++ b/src/share/vm/runtime/globals.hpp	Mon Sep 16 09:41:03 2013 +0200
    28.3 @@ -3649,6 +3649,9 @@
    28.4    experimental(bool, TrustFinalNonStaticFields, false,                      \
    28.5            "trust final non-static declarations for constant folding")       \
    28.6                                                                              \
    28.7 +  experimental(bool, FoldStableValues, false,                               \
    28.8 +          "Private flag to control optimizations for stable variables")     \
    28.9 +                                                                            \
   28.10    develop(bool, TraceInvokeDynamic, false,                                  \
   28.11            "trace internal invoke dynamic operations")                       \
   28.12                                                                              \
    29.1 --- a/src/share/vm/runtime/interfaceSupport.hpp	Fri Sep 13 07:57:13 2013 +0200
    29.2 +++ b/src/share/vm/runtime/interfaceSupport.hpp	Mon Sep 16 09:41:03 2013 +0200
    29.3 @@ -471,16 +471,6 @@
    29.4      VM_ENTRY_BASE(result_type, header, thread)                       \
    29.5      debug_only(VMEntryWrapper __vew;)
    29.6  
    29.7 -// Another special case for nmethod_entry_point so the nmethod that the
    29.8 -// interpreter is about to branch to doesn't get flushed before as we
    29.9 -// branch to it's interpreter_entry_point.  Skip stress testing here too.
   29.10 -// Also we don't allow async exceptions because it is just too painful.
   29.11 -#define IRT_ENTRY_FOR_NMETHOD(result_type, header)                   \
   29.12 -  result_type header {                                               \
   29.13 -    nmethodLocker _nmlock(nm);                                       \
   29.14 -    ThreadInVMfromJavaNoAsyncException __tiv(thread);                                \
   29.15 -    VM_ENTRY_BASE(result_type, header, thread)
   29.16 -
   29.17  #define IRT_END }
   29.18  
   29.19  
    30.1 --- a/src/share/vm/utilities/accessFlags.hpp	Fri Sep 13 07:57:13 2013 +0200
    30.2 +++ b/src/share/vm/utilities/accessFlags.hpp	Mon Sep 16 09:41:03 2013 +0200
    30.3 @@ -78,11 +78,13 @@
    30.4    JVM_ACC_FIELD_ACCESS_WATCHED       = 0x00002000,  // field access is watched by JVMTI
    30.5    JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000,  // field modification is watched by JVMTI
    30.6    JVM_ACC_FIELD_INTERNAL             = 0x00000400,  // internal field, same as JVM_ACC_ABSTRACT
    30.7 +  JVM_ACC_FIELD_STABLE               = 0x00000020,  // @Stable field, same as JVM_ACC_SYNCHRONIZED
    30.8    JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE = 0x00000800, // field has generic signature
    30.9  
   30.10    JVM_ACC_FIELD_INTERNAL_FLAGS       = JVM_ACC_FIELD_ACCESS_WATCHED |
   30.11                                         JVM_ACC_FIELD_MODIFICATION_WATCHED |
   30.12                                         JVM_ACC_FIELD_INTERNAL |
   30.13 +                                       JVM_ACC_FIELD_STABLE |
   30.14                                         JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE,
   30.15  
   30.16                                                      // flags accepted by set_field_flags()
   30.17 @@ -148,6 +150,7 @@
   30.18                                          { return (_flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; }
   30.19    bool on_stack() const                 { return (_flags & JVM_ACC_ON_STACK) != 0; }
   30.20    bool is_internal() const              { return (_flags & JVM_ACC_FIELD_INTERNAL) != 0; }
   30.21 +  bool is_stable() const                { return (_flags & JVM_ACC_FIELD_STABLE) != 0; }
   30.22    bool field_has_generic_signature() const
   30.23                                          { return (_flags & JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) != 0; }
   30.24  
    31.1 --- a/test/gc/TestVerifyDuringStartup.java	Fri Sep 13 07:57:13 2013 +0200
    31.2 +++ b/test/gc/TestVerifyDuringStartup.java	Mon Sep 16 09:41:03 2013 +0200
    31.3 @@ -48,7 +48,7 @@
    31.4                                               "-XX:+VerifyDuringStartup",
    31.5                                               "-version"});
    31.6  
    31.7 -    System.out.print("Testing:\n" + JDKToolFinder.getJDKTool("java"));
    31.8 +    System.out.print("Testing:\n" + JDKToolFinder.getCurrentJDKTool("java"));
    31.9      for (int i = 0; i < vmOpts.size(); i += 1) {
   31.10        System.out.print(" " + vmOpts.get(i));
   31.11      }
    32.1 --- a/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java	Fri Sep 13 07:57:13 2013 +0200
    32.2 +++ b/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java	Mon Sep 16 09:41:03 2013 +0200
    32.3 @@ -27,24 +27,43 @@
    32.4  
    32.5  public final class JDKToolFinder {
    32.6  
    32.7 -  private JDKToolFinder() {
    32.8 -  }
    32.9 -
   32.10 -  /**
   32.11 -   * Returns the full path to an executable in jdk/bin based on System property
   32.12 -   * test.jdk (set by jtreg test suite)
   32.13 -   *
   32.14 -   * @return Full path to an executable in jdk/bin
   32.15 -   */
   32.16 -  public static String getJDKTool(String tool) {
   32.17 -    String binPath = System.getProperty("test.jdk");
   32.18 -    if (binPath == null) {
   32.19 -      throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. "
   32.20 -          + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'.");
   32.21 +    private JDKToolFinder() {
   32.22      }
   32.23  
   32.24 -    binPath += File.separatorChar + "bin" + File.separatorChar + tool;
   32.25 +    /**
   32.26 +     * Returns the full path to an executable in jdk/bin based on System
   32.27 +     * property {@code compile.jdk} (set by jtreg test suite)
   32.28 +     *
   32.29 +     * @return Full path to an executable in jdk/bin
   32.30 +     */
   32.31 +    public static String getJDKTool(String tool) {
   32.32 +        String binPath = System.getProperty("compile.jdk");
   32.33 +        if (binPath == null) {
   32.34 +            throw new RuntimeException("System property 'compile.jdk' not set. "
   32.35 +                    + "This property is normally set by jtreg. "
   32.36 +                    + "When running test separately, set this property using "
   32.37 +                    + "'-Dcompile.jdk=/path/to/jdk'.");
   32.38 +        }
   32.39 +        binPath += File.separatorChar + "bin" + File.separatorChar + tool;
   32.40  
   32.41 -    return binPath;
   32.42 -  }
   32.43 +        return binPath;
   32.44 +    }
   32.45 +    /**
   32.46 +     * Returns the full path to an executable in &lt;current jdk&gt;/bin based
   32.47 +     * on System property {@code test.jdk} (set by jtreg test suite)
   32.48 +     *
   32.49 +     * @return Full path to an executable in jdk/bin
   32.50 +     */
   32.51 +    public static String getCurrentJDKTool(String tool) {
   32.52 +        String binPath = System.getProperty("test.jdk");
   32.53 +        if (binPath == null) {
   32.54 +            throw new RuntimeException("System property 'test.jdk' not set. "
   32.55 +                + "This property is normally set by jtreg. "
   32.56 +                + "When running test separately, set this property using "
   32.57 +                + "'-Dtest.jdk=/path/to/jdk'.");
   32.58 +        }
   32.59 +        binPath += File.separatorChar + "bin" + File.separatorChar + tool;
   32.60 +
   32.61 +        return binPath;
   32.62 +    }
   32.63  }
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/test/testlibrary/ctw/Makefile	Mon Sep 16 09:41:03 2013 +0200
    33.3 @@ -0,0 +1,73 @@
    33.4 +#
    33.5 +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    33.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    33.7 +#
    33.8 +# This code is free software; you can redistribute it and/or modify it
    33.9 +# under the terms of the GNU General Public License version 2 only, as
   33.10 +# published by the Free Software Foundation.
   33.11 +#
   33.12 +# This code is distributed in the hope that it will be useful, but WITHOUT
   33.13 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   33.14 +# FITNESS FOR A PARTICULAR PURPOSE.	See the GNU General Public License
   33.15 +# version 2 for more details (a copy is included in the LICENSE file that
   33.16 +# accompanied this code).
   33.17 +#
   33.18 +# You should have received a copy of the GNU General Public License version
   33.19 +# 2 along with this work; if not, write to the Free Software Foundation,
   33.20 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   33.21 +#
   33.22 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   33.23 +# or visit www.oracle.com if you need additional information or have any
   33.24 +# questions.
   33.25 +#
   33.26 +#
   33.27 +
   33.28 +ifneq "x$(ALT_BOOTDIR)" "x"
   33.29 +	BOOTDIR := $(ALT_BOOTDIR)
   33.30 +endif
   33.31 +
   33.32 +ifeq "x$(BOOTDIR)" "x"
   33.33 +	JDK_HOME := $(shell dirname $(shell which java))/..
   33.34 +else
   33.35 +	JDK_HOME := $(BOOTDIR)
   33.36 +endif
   33.37 +
   33.38 +SRC_DIR = src
   33.39 +BUILD_DIR = build
   33.40 +OUTPUT_DIR = $(BUILD_DIR)/classes
   33.41 +WHITEBOX_DIR = ../whitebox
   33.42 +
   33.43 +JAVAC = $(JDK_HOME)/bin/javac
   33.44 +JAR = $(JDK_HOME)/bin/jar
   33.45 +
   33.46 +SRC_FILES = $(shell find $(SRC_DIR) -name '*.java')
   33.47 +
   33.48 +MAIN_CLASS = sun.hotspot.tools.ctw.CompileTheWorld
   33.49 +
   33.50 +.PHONY: clean cleantmp
   33.51 +
   33.52 +all: ctw.jar cleantmp
   33.53 +
   33.54 +clean: cleantmp
   33.55 +	@rm -rf ctw.jar wb.jar
   33.56 +
   33.57 +cleantmp:
   33.58 +	@rm -rf filelist manifest.mf
   33.59 +	@rm -rf $(BUILD_DIR)
   33.60 +
   33.61 +ctw.jar: filelist wb.jar manifest.mf
   33.62 +	@mkdir -p $(OUTPUT_DIR)
   33.63 +	$(JAVAC) -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp wb.jar @filelist
   33.64 +	$(JAR) cfm ctw.jar manifest.mf -C $(OUTPUT_DIR) .
   33.65 +
   33.66 +wb.jar: 
   33.67 +	make -C ${WHITEBOX_DIR} wb.jar
   33.68 +	cp ${WHITEBOX_DIR}/wb.jar ./
   33.69 +	make -C ${WHITEBOX_DIR} clean
   33.70 +
   33.71 +filelist: $(SRC_FILES)
   33.72 +	@rm -f $@
   33.73 +	@echo $(SRC_FILES) > $@
   33.74 +
   33.75 +manifest.mf:
   33.76 +	@echo "Main-Class: ${MAIN_CLASS}" > manifest.mf
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/test/testlibrary/ctw/README	Mon Sep 16 09:41:03 2013 +0200
    34.3 @@ -0,0 +1,93 @@
    34.4 +#
    34.5 +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    34.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    34.7 +#
    34.8 +# This code is free software; you can redistribute it and/or modify it
    34.9 +# under the terms of the GNU General Public License version 2 only, as
   34.10 +# published by the Free Software Foundation.
   34.11 +#
   34.12 +# This code is distributed in the hope that it will be useful, but WITHOUT
   34.13 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   34.14 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   34.15 +# version 2 for more details (a copy is included in the LICENSE file that
   34.16 +# accompanied this code).
   34.17 +#
   34.18 +# You should have received a copy of the GNU General Public License version
   34.19 +# 2 along with this work; if not, write to the Free Software Foundation,
   34.20 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   34.21 +#
   34.22 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   34.23 +# or visit www.oracle.com if you need additional information or have any
   34.24 +# questions.
   34.25 +#
   34.26 +#
   34.27 +
   34.28 +DESCRIPTION
   34.29 +
   34.30 +This is replacement for CompileTheWorld (CTW) written on java. Its purpose is
   34.31 +to make possible the use of CTW in product builds.
   34.32 +
   34.33 +DEPENDENCES
   34.34 +
   34.35 +The tool depends on Whitebox API. Assumed, that the sources of whitebox are
   34.36 +located in '../whitebox' directory.
   34.37 +
   34.38 +BUILDING
   34.39 +
   34.40 +Simple way to build, just type 'make'.
   34.41 +
   34.42 +Makefile uses environment variables 'ALT_BOOTDIR', 'BOOTDIR' as root-dir of jdk
   34.43 +that will be used for compilation and creating jar.
   34.44 +
   34.45 +On successful building 'ctw.jar' will be created.
   34.46 +
   34.47 +RUNNING
   34.48 +
   34.49 +Since the tool uses WhiteBox API, options 'UnlockDiagnosticVMOptions' and
   34.50 +'WhiteBoxAPI' should be specified, and 'wb.jar' should be added to
   34.51 +boot-classpath:
   34.52 +  $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar 
   34.53 +
   34.54 +Arguments can be paths to '.jar, '.zip', '.lst' files or directories with
   34.55 +classes, that define which classes will be compiled:
   34.56 +  - '.jar', '.zip' files and directories are interpreted like in classpath
   34.57 +(including '<dir>/*' syntax)
   34.58 +  - '.lst' files -- files with class names (in java notation) to compile.
   34.59 +CTW will try to find these classes with default class loader, so they should
   34.60 +be located in classpath.
   34.61 +
   34.62 +Without arguments it would work as old version of CTW: all classes in
   34.63 +boot-classpath will be compiled, excluding classes in 'rt.jar' if 'rt.jar' isn't
   34.64 +first in boot-classpath.
   34.65 +
   34.66 +Due CTW's flags also are not available in product builds, the tool uses
   34.67 +properties with the same names:
   34.68 +  - 'CompileTheWorldPreloadClasses' -- type:boolean, default:true, description:
   34.69 +Preload all classes used by a class before start loading
   34.70 +  - 'CompileTheWorldStartAt' -- type:long, default:1, description: First class
   34.71 +to consider
   34.72 +  - 'CompileTheWorldStopAt' -- type:long, default:Long.MAX_VALUE, description:
   34.73 +Last class to consider
   34.74 +
   34.75 +Also it uses additional properties:
   34.76 +  - 'sun.hotspot.tools.ctw.verbose' -- type:boolean, default:false,
   34.77 +description: Verbose output, adds additional information about compilation
   34.78 +  - 'sun.hotspot.tools.ctw.logfile' -- type:string, default:null,
   34.79 +description: Path to logfile, if it's null, cout will be used.
   34.80 +
   34.81 +EXAMPLES
   34.82 +
   34.83 +compile classes from 'rt.jar':
   34.84 +  $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ${JAVA_HOME}/jre/lib/rt.jar
   34.85 +
   34.86 +compile classes from all '.jar' in './testjars' directory:
   34.87 +  $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ./testjars/*
   34.88 +
   34.89 +compile classes from './build/classes' directory:
   34.90 +  $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ./build/classes
   34.91 +
   34.92 +compile only java.lang.String, java.lang.Object classes:
   34.93 +  $ echo java.lang.String > classes.lst
   34.94 +  $ echo java.lang.Object >> classes.lst
   34.95 +  $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar classes.lst
   34.96 +
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java	Mon Sep 16 09:41:03 2013 +0200
    35.3 @@ -0,0 +1,117 @@
    35.4 +/*
    35.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    35.7 + *
    35.8 + * This code is free software; you can redistribute it and/or modify it
    35.9 + * under the terms of the GNU General Public License version 2 only, as
   35.10 + * published by the Free Software Foundation.
   35.11 + *
   35.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   35.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   35.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   35.15 + * version 2 for more details (a copy is included in the LICENSE file that
   35.16 + * accompanied this code).
   35.17 + *
   35.18 + * You should have received a copy of the GNU General Public License version
   35.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   35.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   35.21 + *
   35.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   35.23 + * or visit www.oracle.com if you need additional information or have any
   35.24 + * questions.
   35.25 + */
   35.26 +
   35.27 +package sun.hotspot.tools.ctw;
   35.28 +
   35.29 +import java.net.MalformedURLException;
   35.30 +import java.net.URL;
   35.31 +import java.net.URLClassLoader;
   35.32 +import java.util.Set;
   35.33 +import java.util.EnumSet;
   35.34 +import java.util.HashSet;
   35.35 +import java.util.concurrent.Executor;
   35.36 +
   35.37 +import java.io.*;
   35.38 +import java.nio.file.*;
   35.39 +import java.nio.file.attribute.*;
   35.40 +
   35.41 +/**
   35.42 + * * Handler for dirs containing classes to compile.
   35.43 + * @author igor.ignatyev@oracle.com
   35.44 + */
   35.45 +public class ClassPathDirEntry extends PathHandler {
   35.46 +
   35.47 +    private final int rootLength = root.toString().length();
   35.48 +
   35.49 +    public ClassPathDirEntry(Path root, Executor executor) {
   35.50 +        super(root, executor);
   35.51 +        try {
   35.52 +            URL url = root.toUri().toURL();
   35.53 +            setLoader(new URLClassLoader(new URL[]{url}));
   35.54 +        } catch (MalformedURLException e) {
   35.55 +            e.printStackTrace();
   35.56 +        }
   35.57 +    }
   35.58 +
   35.59 +    @Override
   35.60 +    public void process() {
   35.61 +        System.out.println("# dir: " + root);
   35.62 +        if (!Files.exists(root)) {
   35.63 +            return;
   35.64 +        }
   35.65 +        try {
   35.66 +            Files.walkFileTree(root, EnumSet.of(FileVisitOption.FOLLOW_LINKS),
   35.67 +                    Integer.MAX_VALUE, new CompileFileVisitor());
   35.68 +        } catch (IOException ioe) {
   35.69 +            ioe.printStackTrace();
   35.70 +        }
   35.71 +    }
   35.72 +
   35.73 +    private void processFile(Path file) {
   35.74 +        if (Utils.isClassFile(file.toString())) {
   35.75 +            processClass(pathToClassName(file));
   35.76 +        }
   35.77 +    }
   35.78 +
   35.79 +    private String pathToClassName(Path file) {
   35.80 +        String fileString;
   35.81 +        if (root == file) {
   35.82 +            fileString = file.normalize().toString();
   35.83 +        } else {
   35.84 +            fileString = file.normalize().toString().substring(rootLength + 1);
   35.85 +        }
   35.86 +        return Utils.fileNameToClassName(fileString);
   35.87 +    }
   35.88 +
   35.89 +    private class CompileFileVisitor extends SimpleFileVisitor<Path> {
   35.90 +
   35.91 +        private final Set<Path> ready = new HashSet<>();
   35.92 +
   35.93 +        @Override
   35.94 +        public FileVisitResult preVisitDirectory(Path dir,
   35.95 +                BasicFileAttributes attrs) throws IOException {
   35.96 +            if (ready.contains(dir)) {
   35.97 +                return FileVisitResult.SKIP_SUBTREE;
   35.98 +            }
   35.99 +            ready.add(dir);
  35.100 +            return super.preVisitDirectory(dir, attrs);
  35.101 +        }
  35.102 +
  35.103 +        @Override
  35.104 +        public FileVisitResult visitFile(Path file,
  35.105 +                BasicFileAttributes attrs) throws IOException {
  35.106 +            if (!ready.contains(file)) {
  35.107 +                processFile(file);
  35.108 +            }
  35.109 +            return isFinished() ? FileVisitResult.TERMINATE
  35.110 +                    : FileVisitResult.CONTINUE;
  35.111 +        }
  35.112 +
  35.113 +        @Override
  35.114 +        public FileVisitResult visitFileFailed(Path file,
  35.115 +                IOException exc) throws IOException {
  35.116 +            return FileVisitResult.CONTINUE;
  35.117 +        }
  35.118 +    }
  35.119 +}
  35.120 +
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java	Mon Sep 16 09:41:03 2013 +0200
    36.3 @@ -0,0 +1,81 @@
    36.4 +/*
    36.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    36.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    36.7 + *
    36.8 + * This code is free software; you can redistribute it and/or modify it
    36.9 + * under the terms of the GNU General Public License version 2 only, as
   36.10 + * published by the Free Software Foundation.
   36.11 + *
   36.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   36.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   36.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   36.15 + * version 2 for more details (a copy is included in the LICENSE file that
   36.16 + * accompanied this code).
   36.17 + *
   36.18 + * You should have received a copy of the GNU General Public License version
   36.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   36.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   36.21 + *
   36.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   36.23 + * or visit www.oracle.com if you need additional information or have any
   36.24 + * questions.
   36.25 + */
   36.26 +
   36.27 +package sun.hotspot.tools.ctw;
   36.28 +
   36.29 +import java.net.MalformedURLException;
   36.30 +import java.net.URL;
   36.31 +import java.net.URLClassLoader;
   36.32 +import java.util.*;
   36.33 +import java.util.jar.*;
   36.34 +import java.util.concurrent.Executor;
   36.35 +
   36.36 +import java.io.*;
   36.37 +import java.nio.file.*;
   36.38 +
   36.39 +/**
   36.40 + * Handler for jar-files containing classes to compile.
   36.41 + * @author igor.ignatyev@oracle.com
   36.42 + */
   36.43 +public class ClassPathJarEntry extends PathHandler {
   36.44 +
   36.45 +    public ClassPathJarEntry(Path root, Executor executor) {
   36.46 +        super(root, executor);
   36.47 +        try {
   36.48 +            URL url = root.toUri().toURL();
   36.49 +            setLoader(new URLClassLoader(new URL[]{url}));
   36.50 +        } catch (MalformedURLException e) {
   36.51 +            e.printStackTrace();
   36.52 +        }
   36.53 +    }
   36.54 +
   36.55 +    @Override
   36.56 +    public void process() {
   36.57 +        System.out.println("# jar: " + root);
   36.58 +        if (!Files.exists(root)) {
   36.59 +            return;
   36.60 +        }
   36.61 +        try {
   36.62 +            JarFile jarFile = new JarFile(root.toFile());
   36.63 +            JarEntry entry;
   36.64 +            for (Enumeration<JarEntry> e = jarFile.entries();
   36.65 +                    e.hasMoreElements(); ) {
   36.66 +                entry = e.nextElement();
   36.67 +                processJarEntry(entry);
   36.68 +                if (isFinished()) {
   36.69 +                    return;
   36.70 +                }
   36.71 +            }
   36.72 +        } catch (IOException ioe) {
   36.73 +            ioe.printStackTrace();
   36.74 +        }
   36.75 +    }
   36.76 +
   36.77 +     private void processJarEntry(JarEntry entry) {
   36.78 +        String filename = entry.getName();
   36.79 +        if (Utils.isClassFile(filename)) {
   36.80 +            processClass(Utils.fileNameToClassName(filename));
   36.81 +        }
   36.82 +    }
   36.83 +}
   36.84 +
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java	Mon Sep 16 09:41:03 2013 +0200
    37.3 @@ -0,0 +1,62 @@
    37.4 +/*
    37.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    37.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    37.7 + *
    37.8 + * This code is free software; you can redistribute it and/or modify it
    37.9 + * under the terms of the GNU General Public License version 2 only, as
   37.10 + * published by the Free Software Foundation.
   37.11 + *
   37.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   37.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   37.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   37.15 + * version 2 for more details (a copy is included in the LICENSE file that
   37.16 + * accompanied this code).
   37.17 + *
   37.18 + * You should have received a copy of the GNU General Public License version
   37.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   37.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   37.21 + *
   37.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   37.23 + * or visit www.oracle.com if you need additional information or have any
   37.24 + * questions.
   37.25 + */
   37.26 +
   37.27 +package sun.hotspot.tools.ctw;
   37.28 +
   37.29 +import java.io.IOException;
   37.30 +import java.nio.file.DirectoryStream;
   37.31 +import java.nio.file.Files;
   37.32 +import java.nio.file.Path;
   37.33 +import java.util.concurrent.Executor;
   37.34 +
   37.35 +/**
   37.36 + * Handler for dirs containing jar-files with classes to compile.
   37.37 + *
   37.38 + * @author igor.ignatyev@oracle.com
   37.39 + */
   37.40 +public class ClassPathJarInDirEntry extends PathHandler {
   37.41 +
   37.42 +    public ClassPathJarInDirEntry(Path root, Executor executor) {
   37.43 +        super(root, executor);
   37.44 +    }
   37.45 +
   37.46 +    @Override
   37.47 +    public void process() {
   37.48 +        System.out.println("# jar_in_dir: " + root);
   37.49 +        if (!Files.exists(root)) {
   37.50 +            return;
   37.51 +        }
   37.52 +        try (DirectoryStream<Path> ds
   37.53 +                = Files.newDirectoryStream(root, "*.jar")) {
   37.54 +            for (Path p : ds) {
   37.55 +                new ClassPathJarEntry(p, executor).process();
   37.56 +                if (isFinished()) {
   37.57 +                    return;
   37.58 +                }
   37.59 +            }
   37.60 +        } catch (IOException ioe) {
   37.61 +            ioe.printStackTrace();
   37.62 +        }
   37.63 +    }
   37.64 +}
   37.65 +
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java	Mon Sep 16 09:41:03 2013 +0200
    38.3 @@ -0,0 +1,61 @@
    38.4 +/*
    38.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    38.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    38.7 + *
    38.8 + * This code is free software; you can redistribute it and/or modify it
    38.9 + * under the terms of the GNU General Public License version 2 only, as
   38.10 + * published by the Free Software Foundation.
   38.11 + *
   38.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   38.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   38.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   38.15 + * version 2 for more details (a copy is included in the LICENSE file that
   38.16 + * accompanied this code).
   38.17 + *
   38.18 + * You should have received a copy of the GNU General Public License version
   38.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   38.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   38.21 + *
   38.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   38.23 + * or visit www.oracle.com if you need additional information or have any
   38.24 + * questions.
   38.25 + */
   38.26 +
   38.27 +package sun.hotspot.tools.ctw;
   38.28 +
   38.29 +import java.io.BufferedReader;
   38.30 +import java.io.IOException;
   38.31 +import java.nio.charset.StandardCharsets;
   38.32 +import java.nio.file.Files;
   38.33 +import java.nio.file.Path;
   38.34 +import java.util.concurrent.Executor;
   38.35 +
   38.36 +/**
   38.37 + * Handler for files containing a list of classes to compile.
   38.38 + *
   38.39 + * @author igor.ignatyev@oracle.com
   38.40 + */
   38.41 +public class ClassesListInFile extends PathHandler {
   38.42 +    public ClassesListInFile(Path root, Executor executor) {
   38.43 +        super(root, executor);
   38.44 +    }
   38.45 +
   38.46 +    @Override
   38.47 +    public void process() {
   38.48 +        System.out.println("# list: " + root);
   38.49 +        if (!Files.exists(root)) {
   38.50 +            return;
   38.51 +        }
   38.52 +        try {
   38.53 +            try (BufferedReader reader = Files.newBufferedReader(root,
   38.54 +                    StandardCharsets.UTF_8)) {
   38.55 +                String line;
   38.56 +                while (!isFinished() && ((line = reader.readLine()) != null)) {
   38.57 +                    processClass(line);
   38.58 +                }
   38.59 +            }
   38.60 +        } catch (IOException e) {
   38.61 +            e.printStackTrace();
   38.62 +        }
   38.63 +    }
   38.64 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java	Mon Sep 16 09:41:03 2013 +0200
    39.3 @@ -0,0 +1,175 @@
    39.4 +/*
    39.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    39.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    39.7 + *
    39.8 + * This code is free software; you can redistribute it and/or modify it
    39.9 + * under the terms of the GNU General Public License version 2 only, as
   39.10 + * published by the Free Software Foundation.
   39.11 + *
   39.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   39.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   39.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   39.15 + * version 2 for more details (a copy is included in the LICENSE file that
   39.16 + * accompanied this code).
   39.17 + *
   39.18 + * You should have received a copy of the GNU General Public License version
   39.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   39.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   39.21 + *
   39.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   39.23 + * or visit www.oracle.com if you need additional information or have any
   39.24 + * questions.
   39.25 + */
   39.26 +
   39.27 +package sun.hotspot.tools.ctw;
   39.28 +
   39.29 +import sun.management.ManagementFactoryHelper;
   39.30 +
   39.31 +import java.io.*;
   39.32 +import java.nio.file.Files;
   39.33 +import java.nio.file.Paths;
   39.34 +
   39.35 +import java.util.List;
   39.36 +import java.util.concurrent.*;
   39.37 +
   39.38 +/**
   39.39 + * @author igor.ignatyev@oracle.com
   39.40 + */
   39.41 +public class CompileTheWorld {
   39.42 +    /**
   39.43 +     * Entry point. Compiles classes in {@code args}, or all classes in
   39.44 +     * boot-classpath if args is empty
   39.45 +     *
   39.46 +     * @param args paths to jar/zip, dir contains classes, or to .lst file
   39.47 +     *             contains list of classes to compile
   39.48 +     */
   39.49 +    public static void main(String[] args) {
   39.50 +        String logfile = Utils.LOG_FILE;
   39.51 +        PrintStream os = null;
   39.52 +        if (logfile != null) {
   39.53 +            try {
   39.54 +                os = new PrintStream(Files.newOutputStream(Paths.get(logfile)));
   39.55 +            } catch (IOException io) {
   39.56 +            }
   39.57 +        }
   39.58 +        if (os != null) {
   39.59 +            System.setOut(os);
   39.60 +        }
   39.61 +
   39.62 +        try {
   39.63 +            try {
   39.64 +                if (ManagementFactoryHelper.getCompilationMXBean() == null) {
   39.65 +                    throw new RuntimeException(
   39.66 +                            "CTW can not work in interpreted mode");
   39.67 +                }
   39.68 +            } catch (java.lang.NoClassDefFoundError e) {
   39.69 +                // compact1, compact2 support
   39.70 +            }
   39.71 +            String[] paths = args;
   39.72 +            boolean skipRtJar = false;
   39.73 +            if (args.length == 0) {
   39.74 +                paths = getDefaultPaths();
   39.75 +                skipRtJar = true;
   39.76 +            }
   39.77 +            ExecutorService executor = createExecutor();
   39.78 +            long start = System.currentTimeMillis();
   39.79 +            try {
   39.80 +                String path;
   39.81 +                for (int i = 0, n = paths.length; i < n
   39.82 +                        && !PathHandler.isFinished(); ++i) {
   39.83 +                    path = paths[i];
   39.84 +                    if (skipRtJar && i > 0 && isRtJar(path)) {
   39.85 +                        // rt.jar is not first, so skip it
   39.86 +                        continue;
   39.87 +                    }
   39.88 +                    PathHandler.create(path, executor).process();
   39.89 +                }
   39.90 +            } finally {
   39.91 +                await(executor);
   39.92 +            }
   39.93 +            System.out.printf("Done (%d classes, %d methods, %d ms)%n",
   39.94 +                    Compiler.getClassCount(),
   39.95 +                    Compiler.getMethodCount(),
   39.96 +                    System.currentTimeMillis() - start);
   39.97 +        } finally {
   39.98 +            if (os != null) {
   39.99 +                os.close();
  39.100 +            }
  39.101 +        }
  39.102 +    }
  39.103 +
  39.104 +    private static ExecutorService createExecutor() {
  39.105 +        final int threadsCount = Math.min(
  39.106 +                Runtime.getRuntime().availableProcessors(),
  39.107 +                Utils.CI_COMPILER_COUNT);
  39.108 +        ExecutorService result;
  39.109 +        if (threadsCount > 1) {
  39.110 +            result = new ThreadPoolExecutor(threadsCount, threadsCount,
  39.111 +                    /* keepAliveTime */ 0L, TimeUnit.MILLISECONDS,
  39.112 +                    new ArrayBlockingQueue<>(threadsCount),
  39.113 +                    new ThreadPoolExecutor.CallerRunsPolicy());
  39.114 +        } else {
  39.115 +            result = new CurrentThreadExecutor();
  39.116 +        }
  39.117 +        return result;
  39.118 +    }
  39.119 +
  39.120 +    private static String[] getDefaultPaths() {
  39.121 +        String property = System.getProperty("sun.boot.class.path");
  39.122 +        System.out.println(
  39.123 +                "# use 'sun.boot.class.path' as args: " + property);
  39.124 +        return Utils.PATH_SEPARATOR.split(property);
  39.125 +    }
  39.126 +
  39.127 +    private static void await(ExecutorService executor) {
  39.128 +        executor.shutdown();
  39.129 +        while (!executor.isTerminated()) {
  39.130 +            try {
  39.131 +                executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
  39.132 +            } catch (InterruptedException ie) {
  39.133 +                Thread.currentThread().interrupt();
  39.134 +                break;
  39.135 +            }
  39.136 +        }
  39.137 +    }
  39.138 +
  39.139 +    private static boolean isRtJar(String path) {
  39.140 +        return Utils.endsWithIgnoreCase(path, File.separator + "rt.jar");
  39.141 +    }
  39.142 +
  39.143 +    private static class CurrentThreadExecutor extends AbstractExecutorService {
  39.144 +        private boolean isShutdown;
  39.145 +
  39.146 +        @Override
  39.147 +        public void shutdown() {
  39.148 +            this.isShutdown = true;
  39.149 +        }
  39.150 +
  39.151 +        @Override
  39.152 +        public List<Runnable> shutdownNow() {
  39.153 +            return null;
  39.154 +        }
  39.155 +
  39.156 +        @Override
  39.157 +        public boolean isShutdown() {
  39.158 +            return isShutdown;
  39.159 +        }
  39.160 +
  39.161 +        @Override
  39.162 +        public boolean isTerminated() {
  39.163 +            return isShutdown;
  39.164 +        }
  39.165 +
  39.166 +        @Override
  39.167 +        public boolean awaitTermination(long timeout, TimeUnit unit)
  39.168 +                throws InterruptedException {
  39.169 +            return isShutdown;
  39.170 +        }
  39.171 +
  39.172 +        @Override
  39.173 +        public void execute(Runnable command) {
  39.174 +            command.run();
  39.175 +        }
  39.176 +    }
  39.177 +}
  39.178 +
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java	Mon Sep 16 09:41:03 2013 +0200
    40.3 @@ -0,0 +1,235 @@
    40.4 +/*
    40.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    40.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    40.7 + *
    40.8 + * This code is free software; you can redistribute it and/or modify it
    40.9 + * under the terms of the GNU General Public License version 2 only, as
   40.10 + * published by the Free Software Foundation.
   40.11 + *
   40.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   40.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   40.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   40.15 + * version 2 for more details (a copy is included in the LICENSE file that
   40.16 + * accompanied this code).
   40.17 + *
   40.18 + * You should have received a copy of the GNU General Public License version
   40.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   40.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   40.21 + *
   40.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   40.23 + * or visit www.oracle.com if you need additional information or have any
   40.24 + * questions.
   40.25 + */
   40.26 +
   40.27 +package sun.hotspot.tools.ctw;
   40.28 +
   40.29 +import sun.hotspot.WhiteBox;
   40.30 +import sun.misc.SharedSecrets;
   40.31 +import sun.reflect.ConstantPool;
   40.32 +
   40.33 +import java.lang.reflect.Executable;
   40.34 +
   40.35 +import java.util.Objects;
   40.36 +import java.util.concurrent.Executor;
   40.37 +import java.util.concurrent.atomic.AtomicLong;
   40.38 +
   40.39 +/**
   40.40 + * Provide method to compile whole class.
   40.41 + * Also contains compiled methods and classes counters.
   40.42 + *
   40.43 + * @author igor.ignatyev@oracle.com
   40.44 + */
   40.45 +public class Compiler {
   40.46 +    private Compiler() { }
   40.47 +    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
   40.48 +    private static final AtomicLong CLASS_COUNT = new AtomicLong(0L);
   40.49 +    private static final AtomicLong METHOD_COUNT = new AtomicLong(0L);
   40.50 +    private static volatile boolean CLASSES_LIMIT_REACHED = false;
   40.51 +
   40.52 +    /**
   40.53 +     * @return count of processed classes
   40.54 +     */
   40.55 +    public static long getClassCount() {
   40.56 +        return CLASS_COUNT.get();
   40.57 +    }
   40.58 +
   40.59 +    /**
   40.60 +     * @return count of processed methods
   40.61 +     */
   40.62 +    public static long getMethodCount() {
   40.63 +        return METHOD_COUNT.get();
   40.64 +    }
   40.65 +
   40.66 +    /**
   40.67 +     * @return {@code true} if classes limit is reached
   40.68 +     */
   40.69 +    public static boolean isLimitReached() {
   40.70 +        return CLASSES_LIMIT_REACHED;
   40.71 +    }
   40.72 +
   40.73 +    /**
   40.74 +     * Compiles all methods and constructors.
   40.75 +     *
   40.76 +     * @param aClass class to compile
   40.77 +     * @param executor executor used for compile task invocation
   40.78 +     * @throws NullPointerException if {@code class} or {@code executor}
   40.79 +     *                              is {@code null}
   40.80 +     */
   40.81 +    public static void compileClass(Class aClass, Executor executor) {
   40.82 +        Objects.requireNonNull(aClass);
   40.83 +        Objects.requireNonNull(executor);
   40.84 +        long id = CLASS_COUNT.incrementAndGet();
   40.85 +        if (id > Utils.COMPILE_THE_WORLD_STOP_AT) {
   40.86 +            CLASS_COUNT.decrementAndGet();
   40.87 +            CLASSES_LIMIT_REACHED = true;
   40.88 +            return;
   40.89 +        }
   40.90 +
   40.91 +        if (id >= Utils.COMPILE_THE_WORLD_START_AT) {
   40.92 +            String name = aClass.getName();
   40.93 +            try {
   40.94 +                System.out.printf("[%d]\t%s%n", id, name);
   40.95 +                ConstantPool constantPool = SharedSecrets.getJavaLangAccess().
   40.96 +                        getConstantPool(aClass);
   40.97 +                if (Utils.COMPILE_THE_WORLD_PRELOAD_CLASSES) {
   40.98 +                    preloadClasses(name, id, constantPool);
   40.99 +                }
  40.100 +                long methodCount = 0;
  40.101 +                for (Executable e : aClass.getDeclaredConstructors()) {
  40.102 +                    ++methodCount;
  40.103 +                    executor.execute(new CompileMethodCommand(id, name, e));
  40.104 +                }
  40.105 +                for (Executable e : aClass.getDeclaredMethods()) {
  40.106 +                    ++methodCount;
  40.107 +                    executor.execute(new CompileMethodCommand(id, name, e));
  40.108 +                }
  40.109 +                METHOD_COUNT.addAndGet(methodCount);
  40.110 +
  40.111 +                if (Utils.DEOPTIMIZE_ALL_CLASSES_RATE > 0
  40.112 +                        && (id % Utils.DEOPTIMIZE_ALL_CLASSES_RATE == 0)) {
  40.113 +                    WHITE_BOX.deoptimizeAll();
  40.114 +                }
  40.115 +            } catch (Throwable t) {
  40.116 +                System.out.printf("[%d]\t%s\tskipping %s%n", id, name, t);
  40.117 +                t.printStackTrace();
  40.118 +            }
  40.119 +        }
  40.120 +    }
  40.121 +
  40.122 +    private static void preloadClasses(String className, long id,
  40.123 +            ConstantPool constantPool) {
  40.124 +        try {
  40.125 +            for (int i = 0, n = constantPool.getSize(); i < n; ++i) {
  40.126 +                try {
  40.127 +                    constantPool.getClassAt(i);
  40.128 +                } catch (IllegalArgumentException ignore) {
  40.129 +                }
  40.130 +            }
  40.131 +        } catch (Throwable t) {
  40.132 +            System.out.printf("[%d]\t%s\tpreloading failed : %s%n", id,
  40.133 +                    className, t);
  40.134 +        }
  40.135 +    }
  40.136 +
  40.137 +
  40.138 +
  40.139 +    /**
  40.140 +     * Compilation of method.
  40.141 +     * Will compile method on all available comp levels.
  40.142 +     */
  40.143 +    private static class CompileMethodCommand implements Runnable {
  40.144 +        private final long classId;
  40.145 +        private final String className;
  40.146 +        private final Executable method;
  40.147 +
  40.148 +        /**
  40.149 +         * @param classId   id of class
  40.150 +         * @param className name of class
  40.151 +         * @param method    compiled for compilation
  40.152 +         */
  40.153 +        public CompileMethodCommand(long classId, String className,
  40.154 +                Executable method) {
  40.155 +            this.classId = classId;
  40.156 +            this.className = className;
  40.157 +            this.method = method;
  40.158 +        }
  40.159 +
  40.160 +        @Override
  40.161 +        public final void run() {
  40.162 +            int compLevel = Utils.INITIAL_COMP_LEVEL;
  40.163 +            if (Utils.TIERED_COMPILATION) {
  40.164 +                for (int i = compLevel; i <= Utils.TIERED_STOP_AT_LEVEL; ++i) {
  40.165 +                    WHITE_BOX.deoptimizeMethod(method);
  40.166 +                    compileMethod(method, i);
  40.167 +                }
  40.168 +            } else {
  40.169 +                compileMethod(method, compLevel);
  40.170 +            }
  40.171 +        }
  40.172 +
  40.173 +        private void waitCompilation() {
  40.174 +            if (!Utils.BACKGROUND_COMPILATION) {
  40.175 +                return;
  40.176 +            }
  40.177 +            final Object obj = new Object();
  40.178 +            synchronized (obj) {
  40.179 +                for (int i = 0;
  40.180 +                     i < 10 && WHITE_BOX.isMethodQueuedForCompilation(method);
  40.181 +                     ++i) {
  40.182 +                    try {
  40.183 +                        obj.wait(1000);
  40.184 +                    } catch (InterruptedException e) {
  40.185 +                        Thread.currentThread().interrupt();
  40.186 +                    }
  40.187 +                }
  40.188 +            }
  40.189 +        }
  40.190 +
  40.191 +        private void compileMethod(Executable method, int compLevel) {
  40.192 +            if (WHITE_BOX.isMethodCompilable(method, compLevel)) {
  40.193 +                try {
  40.194 +                    WHITE_BOX.enqueueMethodForCompilation(method, compLevel);
  40.195 +                    waitCompilation();
  40.196 +                    int tmp = WHITE_BOX.getMethodCompilationLevel(method);
  40.197 +                    if (tmp != compLevel) {
  40.198 +                        logMethod(method, "compilation level = " + tmp
  40.199 +                                + ", but not " + compLevel);
  40.200 +                    } else if (Utils.IS_VERBOSE) {
  40.201 +                        logMethod(method, "compilation level = " + tmp + ". OK");
  40.202 +                    }
  40.203 +                } catch (Throwable t) {
  40.204 +                    logMethod(method, "error on compile at " + compLevel
  40.205 +                            + " level");
  40.206 +                    t.printStackTrace();
  40.207 +                }
  40.208 +            } else if (Utils.IS_VERBOSE) {
  40.209 +                logMethod(method, "not compilable at " + compLevel);
  40.210 +            }
  40.211 +        }
  40.212 +
  40.213 +        private void logMethod(Executable method, String message) {
  40.214 +            StringBuilder builder = new StringBuilder("[");
  40.215 +            builder.append(classId);
  40.216 +            builder.append("]\t");
  40.217 +            builder.append(className);
  40.218 +            builder.append("::");
  40.219 +            builder.append(method.getName());
  40.220 +            builder.append('(');
  40.221 +            Class[] params = method.getParameterTypes();
  40.222 +            for (int i = 0, n = params.length - 1; i < n; ++i) {
  40.223 +                builder.append(params[i].getName());
  40.224 +                builder.append(", ");
  40.225 +            }
  40.226 +            if (params.length != 0) {
  40.227 +                builder.append(params[params.length - 1].getName());
  40.228 +            }
  40.229 +            builder.append(')');
  40.230 +            if (message != null) {
  40.231 +                builder.append('\t');
  40.232 +                builder.append(message);
  40.233 +            }
  40.234 +            System.err.println(builder);
  40.235 +        }
  40.236 +    }
  40.237 +
  40.238 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java	Mon Sep 16 09:41:03 2013 +0200
    41.3 @@ -0,0 +1,149 @@
    41.4 +/*
    41.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    41.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    41.7 + *
    41.8 + * This code is free software; you can redistribute it and/or modify it
    41.9 + * under the terms of the GNU General Public License version 2 only, as
   41.10 + * published by the Free Software Foundation.
   41.11 + *
   41.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   41.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   41.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   41.15 + * version 2 for more details (a copy is included in the LICENSE file that
   41.16 + * accompanied this code).
   41.17 + *
   41.18 + * You should have received a copy of the GNU General Public License version
   41.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   41.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   41.21 + *
   41.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   41.23 + * or visit www.oracle.com if you need additional information or have any
   41.24 + * questions.
   41.25 + */
   41.26 +
   41.27 +package sun.hotspot.tools.ctw;
   41.28 +
   41.29 +import java.nio.file.Files;
   41.30 +import java.nio.file.Path;
   41.31 +import java.nio.file.Paths;
   41.32 +import java.io.File;
   41.33 +
   41.34 +import java.util.Objects;
   41.35 +import java.util.regex.Pattern;
   41.36 +import java.util.regex.Matcher;
   41.37 +import java.util.concurrent.Executor;
   41.38 +
   41.39 +/**
   41.40 + * Abstract handler for path.
   41.41 + * <p/>
   41.42 + * Concrete subclasses should implement method {@link #process()}.
   41.43 + *
   41.44 + * @author igor.ignatyev@oracle.com
   41.45 + */
   41.46 +public abstract class PathHandler {
   41.47 +    private static final Pattern JAR_IN_DIR_PATTERN
   41.48 +            = Pattern.compile("^(.*[/\\\\])?\\*$");
   41.49 +    protected final Path root;
   41.50 +    protected final Executor executor;
   41.51 +    private ClassLoader loader;
   41.52 +
   41.53 +    /**
   41.54 +     * @param root     root path to process
   41.55 +     * @param executor executor used for process task invocation
   41.56 +     * @throws NullPointerException if {@code root} or {@code executor} is
   41.57 +     *                              {@code null}
   41.58 +     */
   41.59 +    protected PathHandler(Path root, Executor executor) {
   41.60 +        Objects.requireNonNull(root);
   41.61 +        Objects.requireNonNull(executor);
   41.62 +        this.root = root.normalize();
   41.63 +        this.executor = executor;
   41.64 +        this.loader = ClassLoader.getSystemClassLoader();
   41.65 +    }
   41.66 +
   41.67 +   /**
   41.68 +     * Factory method. Construct concrete handler in depends from {@code path}.
   41.69 +     *
   41.70 +     * @param path     the path to process
   41.71 +     * @param executor executor used for compile task invocation
   41.72 +     * @throws NullPointerException if {@code path} or {@code executor} is
   41.73 +     *                              {@code null}
   41.74 +     */
   41.75 +    public static PathHandler create(String path, Executor executor) {
   41.76 +        Objects.requireNonNull(path);
   41.77 +        Objects.requireNonNull(executor);
   41.78 +        Matcher matcher = JAR_IN_DIR_PATTERN.matcher(path);
   41.79 +        if (matcher.matches()) {
   41.80 +            path = matcher.group(1);
   41.81 +            path = path.isEmpty() ? "." : path;
   41.82 +            return new ClassPathJarInDirEntry(Paths.get(path), executor);
   41.83 +        } else {
   41.84 +            path = path.isEmpty() ? "." : path;
   41.85 +            Path p = Paths.get(path);
   41.86 +            if (isJarFile(p)) {
   41.87 +                return new ClassPathJarEntry(p, executor);
   41.88 +            } else if (isListFile(p)) {
   41.89 +                return new ClassesListInFile(p, executor);
   41.90 +            } else {
   41.91 +                return new ClassPathDirEntry(p, executor);
   41.92 +            }
   41.93 +        }
   41.94 +    }
   41.95 +
   41.96 +    private static boolean isJarFile(Path path) {
   41.97 +        if (Files.isRegularFile(path)) {
   41.98 +            String name = path.toString();
   41.99 +            return Utils.endsWithIgnoreCase(name, ".zip")
  41.100 +                    || Utils.endsWithIgnoreCase(name, ".jar");
  41.101 +        }
  41.102 +        return false;
  41.103 +    }
  41.104 +
  41.105 +    private static boolean isListFile(Path path) {
  41.106 +        if (Files.isRegularFile(path)) {
  41.107 +            String name = path.toString();
  41.108 +            return Utils.endsWithIgnoreCase(name, ".lst");
  41.109 +        }
  41.110 +        return false;
  41.111 +    }
  41.112 +
  41.113 +    /**
  41.114 +     * Processes all classes in specified path.
  41.115 +     */
  41.116 +    public abstract void process();
  41.117 +
  41.118 +   /**
  41.119 +     * Sets class loader, that will be used to define class at
  41.120 +     * {@link #processClass(String)}.
  41.121 +     *
  41.122 +     * @param loader class loader
  41.123 +     * @throws NullPointerException if {@code loader} is {@code null}
  41.124 +     */
  41.125 +    protected final void setLoader(ClassLoader loader) {
  41.126 +        Objects.requireNonNull(loader);
  41.127 +        this.loader = loader;
  41.128 +    }
  41.129 +
  41.130 +    /**
  41.131 +     * Processes specificed class.
  41.132 +     * @param name fully qualified name of class to process
  41.133 +     */
  41.134 +    protected final void processClass(String name) {
  41.135 +        try {
  41.136 +            Class aClass = Class.forName(name, true, loader);
  41.137 +            Compiler.compileClass(aClass, executor);
  41.138 +        } catch (ClassNotFoundException | LinkageError e) {
  41.139 +            System.out.printf("Class %s loading failed : %s%n", name,
  41.140 +                e.getMessage());
  41.141 +        }
  41.142 +    }
  41.143 +
  41.144 +    /**
  41.145 +     * @return {@code true} if processing should be stopped
  41.146 +     */
  41.147 +    public static boolean isFinished() {
  41.148 +        return Compiler.isLimitReached();
  41.149 +    }
  41.150 +
  41.151 +}
  41.152 +
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java	Mon Sep 16 09:41:03 2013 +0200
    42.3 @@ -0,0 +1,215 @@
    42.4 +/*
    42.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    42.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    42.7 + *
    42.8 + * This code is free software; you can redistribute it and/or modify it
    42.9 + * under the terms of the GNU General Public License version 2 only, as
   42.10 + * published by the Free Software Foundation.
   42.11 + *
   42.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   42.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   42.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   42.15 + * version 2 for more details (a copy is included in the LICENSE file that
   42.16 + * accompanied this code).
   42.17 + *
   42.18 + * You should have received a copy of the GNU General Public License version
   42.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   42.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   42.21 + *
   42.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   42.23 + * or visit www.oracle.com if you need additional information or have any
   42.24 + * questions.
   42.25 + */
   42.26 +
   42.27 +package sun.hotspot.tools.ctw;
   42.28 +
   42.29 +import com.sun.management.HotSpotDiagnosticMXBean;
   42.30 +import sun.management.ManagementFactoryHelper;
   42.31 +
   42.32 +import java.io.File;
   42.33 +import java.util.regex.Pattern;
   42.34 +
   42.35 +/**
   42.36 + * Auxiliary methods.
   42.37 + *
   42.38 + * @author igor.ignatyev@oracle.com
   42.39 + */
   42.40 +public class Utils {
   42.41 +    /**
   42.42 +     * Value of {@code -XX:CompileThreshold}
   42.43 +     */
   42.44 +    public static final boolean TIERED_COMPILATION
   42.45 +            = Boolean.parseBoolean(getVMOption("TieredCompilation", "false"));
   42.46 +    /**
   42.47 +     * Value of {@code -XX:BackgroundCompilation}
   42.48 +     */
   42.49 +    public static final boolean BACKGROUND_COMPILATION
   42.50 +            = Boolean.parseBoolean(getVMOption("BackgroundCompilation",
   42.51 +            "false"));
   42.52 +    /**
   42.53 +     * Value of {@code -XX:TieredStopAtLevel}
   42.54 +     */
   42.55 +    public static final int TIERED_STOP_AT_LEVEL;
   42.56 +    /**
   42.57 +     * Value of {@code -XX:CICompilerCount}
   42.58 +     */
   42.59 +    public static final Integer CI_COMPILER_COUNT
   42.60 +            = Integer.valueOf(getVMOption("CICompilerCount", "1"));
   42.61 +    /**
   42.62 +     * Initial compilation level.
   42.63 +     */
   42.64 +    public static final int INITIAL_COMP_LEVEL;
   42.65 +    /**
   42.66 +     * Compiled path-separator regexp.
   42.67 +     */
   42.68 +    public static final Pattern PATH_SEPARATOR = Pattern.compile(
   42.69 +            File.pathSeparator, Pattern.LITERAL);
   42.70 +    /**
   42.71 +     * Value of {@code -DDeoptimizeAllClassesRate}. Frequency of
   42.72 +     * {@code WB.deoptimizeAll()} invocation If it less that {@code 0},
   42.73 +     * {@code WB.deoptimizeAll()} will not be invoked.
   42.74 +     */
   42.75 +    public static final int DEOPTIMIZE_ALL_CLASSES_RATE
   42.76 +            = Integer.getInteger("DeoptimizeAllClassesRate", -1);
   42.77 +    /**
   42.78 +     * Value of {@code -DCompileTheWorldStopAt}. Last class to consider.
   42.79 +     */
   42.80 +    public static final long COMPILE_THE_WORLD_STOP_AT
   42.81 +            = Long.getLong("CompileTheWorldStopAt", Long.MAX_VALUE);
   42.82 +    /**
   42.83 +     * Value of {@code -DCompileTheWorldStartAt}. First class to consider.
   42.84 +     */
   42.85 +    public static final long COMPILE_THE_WORLD_START_AT
   42.86 +            = Long.getLong("CompileTheWorldStartAt", 1);
   42.87 +    /**
   42.88 +     * Value of {@code -DCompileTheWorldPreloadClasses}. Preload all classes
   42.89 +     * used by a class before start loading.
   42.90 +     */
   42.91 +    public static final boolean COMPILE_THE_WORLD_PRELOAD_CLASSES;
   42.92 +    /**
   42.93 +     * Value of {@code -Dsun.hotspot.tools.ctw.verbose}. Verbose output,
   42.94 +     * adds additional information about compilation.
   42.95 +     */
   42.96 +    public static final boolean IS_VERBOSE
   42.97 +            = Boolean.getBoolean("sun.hotspot.tools.ctw.verbose");
   42.98 +    /**
   42.99 +     * Value of {@code -Dsun.hotspot.tools.ctw.logfile}.Path to logfile, if
  42.100 +     * it's null, cout will be used.
  42.101 +     */
  42.102 +    public static final String LOG_FILE
  42.103 +            = System.getProperty("sun.hotspot.tools.ctw.logfile");
  42.104 +    static {
  42.105 +        if (Utils.TIERED_COMPILATION) {
  42.106 +            INITIAL_COMP_LEVEL = 1;
  42.107 +        } else {
  42.108 +            String vmName = System.getProperty("java.vm.name");
  42.109 +            if (Utils.endsWithIgnoreCase(vmName, " Server VM")) {
  42.110 +                INITIAL_COMP_LEVEL = 4;
  42.111 +            } else if (Utils.endsWithIgnoreCase(vmName, " Client VM")
  42.112 +                    || Utils.endsWithIgnoreCase(vmName, " Minimal VM")) {
  42.113 +                INITIAL_COMP_LEVEL = 1;
  42.114 +            } else {
  42.115 +                throw new RuntimeException("Unknown VM: " + vmName);
  42.116 +            }
  42.117 +        }
  42.118 +
  42.119 +        TIERED_STOP_AT_LEVEL = Integer.parseInt(getVMOption("TieredStopAtLevel",
  42.120 +                String.valueOf(INITIAL_COMP_LEVEL)));
  42.121 +    }
  42.122 +
  42.123 +    static {
  42.124 +        String tmp = System.getProperty("CompileTheWorldPreloadClasses");
  42.125 +        if (tmp == null) {
  42.126 +            COMPILE_THE_WORLD_PRELOAD_CLASSES = true;
  42.127 +        } else {
  42.128 +            COMPILE_THE_WORLD_PRELOAD_CLASSES = Boolean.parseBoolean(tmp);
  42.129 +        }
  42.130 +    }
  42.131 +
  42.132 +    public static final String CLASSFILE_EXT = ".class";
  42.133 +
  42.134 +    private Utils() {
  42.135 +    }
  42.136 +
  42.137 +    /**
  42.138 +     * Tests if the string ends with the suffix, ignoring case
  42.139 +     * considerations
  42.140 +     *
  42.141 +     * @param string the tested string
  42.142 +     * @param suffix the suffix
  42.143 +     * @return {@code true} if {@code string} ends with the {@code suffix}
  42.144 +     * @see String#endsWith(String)
  42.145 +     */
  42.146 +    public static boolean endsWithIgnoreCase(String string, String suffix) {
  42.147 +        if (string == null || suffix == null) {
  42.148 +            return false;
  42.149 +        }
  42.150 +        int length = suffix.length();
  42.151 +        int toffset = string.length() - length;
  42.152 +        if (toffset < 0) {
  42.153 +            return false;
  42.154 +        }
  42.155 +        return string.regionMatches(true, toffset, suffix, 0, length);
  42.156 +    }
  42.157 +
  42.158 +    /**
  42.159 +     * Returns value of VM option.
  42.160 +     *
  42.161 +     * @param name option's name
  42.162 +     * @return value of option or {@code null}, if option doesn't exist
  42.163 +     * @throws NullPointerException if name is null
  42.164 +     */
  42.165 +    public static String getVMOption(String name) {
  42.166 +        String result;
  42.167 +        HotSpotDiagnosticMXBean diagnostic
  42.168 +                = ManagementFactoryHelper.getDiagnosticMXBean();
  42.169 +        result = diagnostic.getVMOption(name).getValue();
  42.170 +        return result;
  42.171 +    }
  42.172 +
  42.173 +    /**
  42.174 +     * Returns value of VM option or default value.
  42.175 +     *
  42.176 +     * @param name         option's name
  42.177 +     * @param defaultValue default value
  42.178 +     * @return value of option or {@code defaultValue}, if option doesn't exist
  42.179 +     * @throws NullPointerException if name is null
  42.180 +     * @see #getVMOption(String)
  42.181 +     */
  42.182 +    public static String getVMOption(String name, String defaultValue) {
  42.183 +        String result;
  42.184 +        try {
  42.185 +            result = getVMOption(name);
  42.186 +        } catch (NoClassDefFoundError e) {
  42.187 +            // compact1, compact2 support
  42.188 +            result = defaultValue;
  42.189 +        }
  42.190 +        return result == null ? defaultValue : result;
  42.191 +    }
  42.192 +
  42.193 +    /**
  42.194 +     * Tests if the filename is valid filename for class file.
  42.195 +     *
  42.196 +     * @param filename tested filename
  42.197 +     */
  42.198 +    public static boolean isClassFile(String filename) {
  42.199 +        // If the filename has a period after removing '.class', it's not valid class file
  42.200 +        return endsWithIgnoreCase(filename, CLASSFILE_EXT)
  42.201 +                && (filename.indexOf('.')
  42.202 +                == (filename.length() - CLASSFILE_EXT.length()));
  42.203 +    }
  42.204 +
  42.205 +    /**
  42.206 +     * Converts the filename to classname.
  42.207 +     *
  42.208 +     * @param filename filename to convert
  42.209 +     * @return corresponding classname.
  42.210 +     * @throws AssertionError if filename isn't valid filename for class file -
  42.211 +     *                        {@link #isClassFile(String)}
  42.212 +     */
  42.213 +    public static String fileNameToClassName(String filename) {
  42.214 +        assert isClassFile(filename);
  42.215 +        return filename.substring(0, filename.length() - CLASSFILE_EXT.length())
  42.216 +                       .replace(File.separatorChar, '.');
  42.217 +    }
  42.218 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/test/testlibrary/ctw/test/Bar.java	Mon Sep 16 09:41:03 2013 +0200
    43.3 @@ -0,0 +1,5 @@
    43.4 +public class Bar {
    43.5 +  private static void staticMethod() { }
    43.6 +  public void method() { }
    43.7 +  protected Bar() { }
    43.8 +}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/test/testlibrary/ctw/test/ClassesDirTest.java	Mon Sep 16 09:41:03 2013 +0200
    44.3 @@ -0,0 +1,61 @@
    44.4 +/*
    44.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    44.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    44.7 + *
    44.8 + * This code is free software; you can redistribute it and/or modify it
    44.9 + * under the terms of the GNU General Public License version 2 only, as
   44.10 + * published by the Free Software Foundation.
   44.11 + *
   44.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   44.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   44.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   44.15 + * version 2 for more details (a copy is included in the LICENSE file that
   44.16 + * accompanied this code).
   44.17 + *
   44.18 + * You should have received a copy of the GNU General Public License version
   44.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   44.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   44.21 + *
   44.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   44.23 + * or visit www.oracle.com if you need additional information or have any
   44.24 + * questions.
   44.25 + */
   44.26 +
   44.27 +/*
   44.28 + * @test ClassesDirTest
   44.29 + * @bug 8012447
   44.30 + * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
   44.31 + * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox ClassesDirTest Foo Bar
   44.32 + * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
   44.33 + * @run main ClassesDirTest prepare
   44.34 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes
   44.35 + * @run main ClassesDirTest check ctw.log
   44.36 + * @summary testing of CompileTheWorld :: classes in directory
   44.37 + * @author igor.ignatyev@oracle.com
   44.38 + */
   44.39 +
   44.40 +import java.nio.file.Files;
   44.41 +import java.nio.file.Paths;
   44.42 +import java.nio.file.StandardCopyOption;
   44.43 +
   44.44 +public class ClassesDirTest extends CtwTest {
   44.45 +    private static final String[] SHOULD_CONTAIN
   44.46 +            = {"# dir: classes", "Done (2 classes, 6 methods, "};
   44.47 +
   44.48 +    private ClassesDirTest() {
   44.49 +        super(SHOULD_CONTAIN);
   44.50 +    }
   44.51 +
   44.52 +    public static void main(String[] args) throws Exception {
   44.53 +        new ClassesDirTest().run(args);
   44.54 +    }
   44.55 +
   44.56 +    protected void prepare() throws Exception {
   44.57 +        String path = "classes";
   44.58 +        Files.createDirectory(Paths.get(path));
   44.59 +        Files.move(Paths.get("Foo.class"), Paths.get(path, "Foo.class"),
   44.60 +                StandardCopyOption.REPLACE_EXISTING);
   44.61 +        Files.move(Paths.get("Bar.class"), Paths.get(path, "Bar.class"),
   44.62 +                StandardCopyOption.REPLACE_EXISTING);
   44.63 +    }
   44.64 +}
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/test/testlibrary/ctw/test/ClassesListTest.java	Mon Sep 16 09:41:03 2013 +0200
    45.3 @@ -0,0 +1,58 @@
    45.4 +/*
    45.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    45.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    45.7 + *
    45.8 + * This code is free software; you can redistribute it and/or modify it
    45.9 + * under the terms of the GNU General Public License version 2 only, as
   45.10 + * published by the Free Software Foundation.
   45.11 + *
   45.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   45.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   45.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   45.15 + * version 2 for more details (a copy is included in the LICENSE file that
   45.16 + * accompanied this code).
   45.17 + *
   45.18 + * You should have received a copy of the GNU General Public License version
   45.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   45.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   45.21 + *
   45.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   45.23 + * or visit www.oracle.com if you need additional information or have any
   45.24 + * questions.
   45.25 + */
   45.26 +
   45.27 +/*
   45.28 + * @test ClassesListTest
   45.29 + * @bug 8012447
   45.30 + * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
   45.31 + * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox ClassesListTest Foo Bar
   45.32 + * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
   45.33 + * @run main ClassesListTest prepare
   45.34 + * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes.lst
   45.35 + * @run main ClassesListTest check ctw.log
   45.36 + * @summary testing of CompileTheWorld :: list of classes in file
   45.37 + * @author igor.ignatyev@oracle.com
   45.38 + */
   45.39 +
   45.40 +import java.nio.file.Files;
   45.41 +import java.nio.file.Paths;
   45.42 +import java.nio.file.StandardCopyOption;
   45.43 +
   45.44 +public class ClassesListTest extends CtwTest {
   45.45 +    private static final String[] SHOULD_CONTAIN
   45.46 +            = {"# list: classes.lst", "Done (4 classes, "};
   45.47 +
   45.48 +    private ClassesListTest() {
   45.49 +        super(SHOULD_CONTAIN);
   45.50 +    }
   45.51 +
   45.52 +    public static void main(String[] args) throws Exception {
   45.53 +        new ClassesListTest().run(args);
   45.54 +    }
   45.55 +
   45.56 +    protected void prepare() throws Exception {
   45.57 +        String path = "classes.lst";
   45.58 +        Files.copy(Paths.get(System.getProperty("test.src"), path),
   45.59 +                Paths.get(path), StandardCopyOption.REPLACE_EXISTING);
   45.60 +    }
   45.61 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/test/testlibrary/ctw/test/CtwTest.java	Mon Sep 16 09:41:03 2013 +0200
    46.3 @@ -0,0 +1,118 @@
    46.4 +/*
    46.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    46.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    46.7 + *
    46.8 + * This code is free software; you can redistribute it and/or modify it
    46.9 + * under the terms of the GNU General Public License version 2 only, as
   46.10 + * published by the Free Software Foundation.
   46.11 + *
   46.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   46.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   46.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   46.15 + * version 2 for more details (a copy is included in the LICENSE file that
   46.16 + * accompanied this code).
   46.17 + *
   46.18 + * You should have received a copy of the GNU General Public License version
   46.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   46.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   46.21 + *
   46.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   46.23 + * or visit www.oracle.com if you need additional information or have any
   46.24 + * questions.
   46.25 + */
   46.26 +
   46.27 +import java.util.List;
   46.28 +import java.util.Collections;
   46.29 +import java.util.ArrayList;
   46.30 +
   46.31 +import java.io.File;
   46.32 +import java.io.Writer;
   46.33 +import java.io.FileWriter;
   46.34 +import java.io.IOException;
   46.35 +import java.io.BufferedReader;
   46.36 +
   46.37 +import java.nio.file.Files;
   46.38 +import java.nio.file.Paths;
   46.39 +import java.nio.file.StandardCopyOption;
   46.40 +import java.nio.charset.Charset;
   46.41 +
   46.42 +import com.oracle.java.testlibrary.JDKToolFinder;
   46.43 +import com.oracle.java.testlibrary.OutputAnalyzer;
   46.44 +
   46.45 +public abstract class CtwTest {
   46.46 +    protected final String[] shouldContain;
   46.47 +    protected CtwTest(String[] shouldContain) {
   46.48 +        this.shouldContain = shouldContain;
   46.49 +    }
   46.50 +
   46.51 +    public void run(String[] args) throws Exception {
   46.52 +        if (args.length == 0) {
   46.53 +            throw new Error("args is empty");
   46.54 +        }
   46.55 +        switch (args[0]) {
   46.56 +            case "prepare":
   46.57 +                prepare();
   46.58 +                break;
   46.59 +            case "check":
   46.60 +                check(args);
   46.61 +                break;
   46.62 +            default:
   46.63 +                throw new Error("unregonized action -- " + args[0]);
   46.64 +        }
   46.65 +    }
   46.66 +
   46.67 +    protected void prepare() throws Exception { }
   46.68 +
   46.69 +    protected void check(String[] args) throws Exception  {
   46.70 +        if (args.length < 2) {
   46.71 +            throw new Error("logfile isn't specified");
   46.72 +        }
   46.73 +        String logfile = args[1];
   46.74 +        try (BufferedReader r = Files.newBufferedReader(Paths.get(logfile),
   46.75 +                Charset.defaultCharset())) {
   46.76 +            OutputAnalyzer output = readOutput(r);
   46.77 +           for (String test : shouldContain) {
   46.78 +                output.shouldContain(test);
   46.79 +            }
   46.80 +        }
   46.81 +    }
   46.82 +
   46.83 +    private static OutputAnalyzer readOutput(BufferedReader reader)
   46.84 +            throws IOException {
   46.85 +        StringBuilder builder = new StringBuilder();
   46.86 +        String eol = String.format("%n");
   46.87 +        String line;
   46.88 +
   46.89 +        while ((line = reader.readLine()) != null) {
   46.90 +            builder.append(line);
   46.91 +            builder.append(eol);
   46.92 +        }
   46.93 +        return new OutputAnalyzer(builder.toString(), "");
   46.94 +    }
   46.95 +
   46.96 +    protected void dump(OutputAnalyzer output, String name) {
   46.97 +        try (Writer w = new FileWriter(name + ".out")) {
   46.98 +            String s = output.getStdout();
   46.99 +            w.write(s, s.length(), 0);
  46.100 +        } catch (IOException io) {
  46.101 +            io.printStackTrace();
  46.102 +        }
  46.103 +        try (Writer w = new FileWriter(name + ".err")) {
  46.104 +            String s = output.getStderr();
  46.105 +            w.write(s, s.length(), 0);
  46.106 +        } catch (IOException io) {
  46.107 +            io.printStackTrace();
  46.108 +        }
  46.109 +    }
  46.110 +
  46.111 +    protected ProcessBuilder createJarProcessBuilder(String... command)
  46.112 +            throws Exception {
  46.113 +        String javapath = JDKToolFinder.getJDKTool("jar");
  46.114 +
  46.115 +        ArrayList<String> args = new ArrayList<>();
  46.116 +        args.add(javapath);
  46.117 +        Collections.addAll(args, command);
  46.118 +
  46.119 +        return new ProcessBuilder(args.toArray(new String[args.size()]));
  46.120 +    }
  46.121 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/test/testlibrary/ctw/test/Foo.java	Mon Sep 16 09:41:03 2013 +0200
    47.3 @@ -0,0 +1,5 @@
    47.4 +public class Foo {
    47.5 +  private static void staticMethod() { }
    47.6 +  public void method() { }
    47.7 +  protected Foo() { }
    47.8 +}
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/test/testlibrary/ctw/test/JarDirTest.java	Mon Sep 16 09:41:03 2013 +0200
    48.3 @@ -0,0 +1,75 @@
    48.4 +/*
    48.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    48.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    48.7 + *
    48.8 + * This code is free software; you can redistribute it and/or modify it
    48.9 + * under the terms of the GNU General Public License version 2 only, as
   48.10 + * published by the Free Software Foundation.
   48.11 + *
   48.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   48.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   48.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   48.15 + * version 2 for more details (a copy is included in the LICENSE file that
   48.16 + * accompanied this code).
   48.17 + *
   48.18 + * You should have received a copy of the GNU General Public License version
   48.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   48.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   48.21 + *
   48.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   48.23 + * or visit www.oracle.com if you need additional information or have any
   48.24 + * questions.
   48.25 + */
   48.26 +
   48.27 +/*
   48.28 + * @test JarDirTest
   48.29 + * @bug 8012447
   48.30 + * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
   48.31 + * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox JarDirTest Foo Bar
   48.32 + * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
   48.33 + * @run main JarDirTest prepare
   48.34 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld jars/*
   48.35 + * @run main JarDirTest check ctw.log
   48.36 + * @summary testing of CompileTheWorld :: jars in directory
   48.37 + * @author igor.ignatyev@oracle.com
   48.38 + */
   48.39 +
   48.40 +import java.io.File;
   48.41 +import java.nio.file.Files;
   48.42 +import java.nio.file.Paths;
   48.43 +
   48.44 +import com.oracle.java.testlibrary.OutputAnalyzer;
   48.45 +
   48.46 +public class JarDirTest extends CtwTest {
   48.47 +    private static final String[] SHOULD_CONTAIN
   48.48 +            = {"# jar_in_dir: jars",
   48.49 +                    "# jar: jars" + File.separator +"foo.jar",
   48.50 +                    "# jar: jars" + File.separator +"bar.jar",
   48.51 +                    "Done (4 classes, 12 methods, "};
   48.52 +
   48.53 +    private JarDirTest() {
   48.54 +        super(SHOULD_CONTAIN);
   48.55 +    }
   48.56 +
   48.57 +    public static void main(String[] args) throws Exception {
   48.58 +        new JarDirTest().run(args);
   48.59 +    }
   48.60 +
   48.61 +    protected void prepare() throws Exception {
   48.62 +        String path = "jars";
   48.63 +        Files.createDirectory(Paths.get(path));
   48.64 +
   48.65 +        ProcessBuilder pb = createJarProcessBuilder("cf", "jars/foo.jar",
   48.66 +                "Foo.class", "Bar.class");
   48.67 +        OutputAnalyzer output = new OutputAnalyzer(pb.start());
   48.68 +        dump(output, "ctw-foo.jar");
   48.69 +        output.shouldHaveExitValue(0);
   48.70 +
   48.71 +        pb = createJarProcessBuilder("cf", "jars/bar.jar", "Foo.class",
   48.72 +                "Bar.class");
   48.73 +        output = new OutputAnalyzer(pb.start());
   48.74 +        dump(output, "ctw-bar.jar");
   48.75 +        output.shouldHaveExitValue(0);
   48.76 +    }
   48.77 +
   48.78 +}
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/test/testlibrary/ctw/test/JarsTest.java	Mon Sep 16 09:41:03 2013 +0200
    49.3 @@ -0,0 +1,65 @@
    49.4 +/*
    49.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    49.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    49.7 + *
    49.8 + * This code is free software; you can redistribute it and/or modify it
    49.9 + * under the terms of the GNU General Public License version 2 only, as
   49.10 + * published by the Free Software Foundation.
   49.11 + *
   49.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   49.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   49.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   49.15 + * version 2 for more details (a copy is included in the LICENSE file that
   49.16 + * accompanied this code).
   49.17 + *
   49.18 + * You should have received a copy of the GNU General Public License version
   49.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   49.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   49.21 + *
   49.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   49.23 + * or visit www.oracle.com if you need additional information or have any
   49.24 + * questions.
   49.25 + */
   49.26 +
   49.27 +/*
   49.28 + * @test JarsTest
   49.29 + * @bug 8012447
   49.30 + * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
   49.31 + * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox JarsTest Foo Bar
   49.32 + * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
   49.33 + * @run main JarsTest prepare
   49.34 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld foo.jar bar.jar
   49.35 + * @run main JarsTest check ctw.log
   49.36 + * @summary testing of CompileTheWorld :: jars
   49.37 + * @author igor.ignatyev@oracle.com
   49.38 + */
   49.39 +
   49.40 +import com.oracle.java.testlibrary.OutputAnalyzer;
   49.41 +
   49.42 +public class JarsTest extends CtwTest {
   49.43 +    private static final String[] SHOULD_CONTAIN
   49.44 +            = {"# jar: foo.jar", "# jar: bar.jar",
   49.45 +                    "Done (4 classes, 12 methods, "};
   49.46 +
   49.47 +    private JarsTest() {
   49.48 +        super(SHOULD_CONTAIN);
   49.49 +    }
   49.50 +
   49.51 +    public static void main(String[] args) throws Exception {
   49.52 +        new JarsTest().run(args);
   49.53 +    }
   49.54 +
   49.55 +    protected void prepare() throws Exception {
   49.56 +        ProcessBuilder pb = createJarProcessBuilder("cf", "foo.jar",
   49.57 +                "Foo.class", "Bar.class");
   49.58 +        OutputAnalyzer output = new OutputAnalyzer(pb.start());
   49.59 +        dump(output, "ctw-foo.jar");
   49.60 +        output.shouldHaveExitValue(0);
   49.61 +
   49.62 +        pb = createJarProcessBuilder("cf", "bar.jar", "Foo.class", "Bar.class");
   49.63 +        output = new OutputAnalyzer(pb.start());
   49.64 +        dump(output, "ctw-bar.jar");
   49.65 +        output.shouldHaveExitValue(0);
   49.66 +    }
   49.67 +
   49.68 +}
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/test/testlibrary/ctw/test/classes.lst	Mon Sep 16 09:41:03 2013 +0200
    50.3 @@ -0,0 +1,4 @@
    50.4 +java.lang.String
    50.5 +java.lang.Object
    50.6 +Foo
    50.7 +Bar
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/test/testlibrary/whitebox/Makefile	Mon Sep 16 09:41:03 2013 +0200
    51.3 @@ -0,0 +1,63 @@
    51.4 +#
    51.5 +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    51.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    51.7 +#
    51.8 +# This code is free software; you can redistribute it and/or modify it
    51.9 +# under the terms of the GNU General Public License version 2 only, as
   51.10 +# published by the Free Software Foundation.
   51.11 +#
   51.12 +# This code is distributed in the hope that it will be useful, but WITHOUT
   51.13 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   51.14 +# FITNESS FOR A PARTICULAR PURPOSE.	See the GNU General Public License
   51.15 +# version 2 for more details (a copy is included in the LICENSE file that
   51.16 +# accompanied this code).
   51.17 +#
   51.18 +# You should have received a copy of the GNU General Public License version
   51.19 +# 2 along with this work; if not, write to the Free Software Foundation,
   51.20 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   51.21 +#
   51.22 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   51.23 +# or visit www.oracle.com if you need additional information or have any
   51.24 +# questions.
   51.25 +#
   51.26 +#
   51.27 +
   51.28 +ifneq "x$(ALT_BOOTDIR)" "x"
   51.29 +	BOOTDIR := $(ALT_BOOTDIR)
   51.30 +endif
   51.31 +
   51.32 +ifeq "x$(BOOTDIR)" "x"
   51.33 +	JDK_HOME := $(shell dirname $(shell which java))/..
   51.34 +else
   51.35 +	JDK_HOME := $(BOOTDIR)
   51.36 +endif
   51.37 +
   51.38 +SRC_DIR = ./
   51.39 +BUILD_DIR = build
   51.40 +OUTPUT_DIR = $(BUILD_DIR)/classes
   51.41 +
   51.42 +JAVAC = $(JDK_HOME)/bin/javac
   51.43 +JAR = $(JDK_HOME)/bin/jar
   51.44 +
   51.45 +SRC_FILES = $(shell find $(SRC_DIR) -name '*.java')
   51.46 +
   51.47 +.PHONY: filelist clean cleantmp
   51.48 +
   51.49 +all: wb.jar cleantmp
   51.50 +
   51.51 +wb.jar: filelist
   51.52 +	@mkdir -p $(OUTPUT_DIR)
   51.53 +	$(JAVAC) -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp $(OUTPUT_DIR) @filelist
   51.54 +	$(JAR) cf wb.jar -C $(OUTPUT_DIR) .
   51.55 +	@rm -rf $(OUTPUT_DIR)
   51.56 +
   51.57 +filelist: $(SRC_FILES)
   51.58 +	@rm -f $@
   51.59 +	@echo $(SRC_FILES) > $@
   51.60 +
   51.61 +clean: cleantmp
   51.62 +	@rm -rf wb.jar
   51.63 +
   51.64 +cleantmp:
   51.65 +	@rm -rf filelist
   51.66 +	@rm -rf $(BUILD_DIR)

mercurial