Mon, 16 Sep 2013 09:41:03 +0200
Merge
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 <current jdk>/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)