# HG changeset patch # User lana # Date 1366218762 25200 # Node ID 6c560f9ebb3e5894adedd1a082e37eaebb84684f # Parent 124ca22437b147526b7d42a264184cebb6284d01# Parent 5201379fe48713a26b46b89c9fd3e4c9210a5e85 Merge diff -r 124ca22437b1 -r 6c560f9ebb3e .hgtags --- a/.hgtags Fri Apr 12 10:14:42 2013 +0100 +++ b/.hgtags Wed Apr 17 10:12:42 2013 -0700 @@ -332,3 +332,4 @@ a947f40fb536e5b9e0aa210cf26abb430f80887a hs25-b26 42fe530cd478744a4d12a0cbf803f0fc804bab1a jdk8-b85 09b0d3e9ba6cdf7da07d4010d2d1df14596f6864 hs25-b27 +6d88a566d369f6a1f86912cad7d0912686b2fda1 hs25-b28 diff -r 124ca22437b1 -r 6c560f9ebb3e make/hotspot_version --- a/make/hotspot_version Fri Apr 12 10:14:42 2013 +0100 +++ b/make/hotspot_version Wed Apr 17 10:12:42 2013 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=27 +HS_BUILD_NUMBER=28 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/adlc/output_c.cpp --- a/src/share/vm/adlc/output_c.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/adlc/output_c.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -63,11 +63,10 @@ RegDef *reg_def = NULL; RegDef *next = NULL; registers->reset_RegDefs(); - for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { + for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) { next = registers->iter_RegDefs(); const char *comma = (next != NULL) ? "," : " // no trailing comma"; - fprintf(fp," \"%s\"%s\n", - reg_def->_regname, comma ); + fprintf(fp," \"%s\"%s\n", reg_def->_regname, comma); } // Finish defining enumeration @@ -79,10 +78,10 @@ reg_def = NULL; next = NULL; registers->reset_RegDefs(); - for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { + for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) { next = registers->iter_RegDefs(); const char *comma = (next != NULL) ? "," : " // no trailing comma"; - fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma ); + fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma); } // Finish defining array fprintf(fp,"\t};\n"); @@ -104,19 +103,17 @@ RegDef *reg_def = NULL; RegDef *next = NULL; registers->reset_RegDefs(); - for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { + for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) { next = registers->iter_RegDefs(); const char* register_encode = reg_def->register_encode(); const char *comma = (next != NULL) ? "," : " // no trailing comma"; int encval; if (!ADLParser::is_int_token(register_encode, encval)) { - fprintf(fp," %s%s // %s\n", - register_encode, comma, reg_def->_regname ); + fprintf(fp," %s%s // %s\n", register_encode, comma, reg_def->_regname); } else { // Output known constants in hex char format (backward compatibility). assert(encval < 256, "Exceeded supported width for register encoding"); - fprintf(fp," (unsigned char)'\\x%X'%s // %s\n", - encval, comma, reg_def->_regname ); + fprintf(fp," (unsigned char)'\\x%X'%s // %s\n", encval, comma, reg_def->_regname); } } // Finish defining enumeration @@ -133,9 +130,10 @@ fprintf(fp,"// Enumeration of register class names\n"); fprintf(fp, "enum machRegisterClass {\n"); registers->_rclasses.reset(); - for( const char *class_name = NULL; - (class_name = registers->_rclasses.iter()) != NULL; ) { - fprintf(fp," %s,\n", toUpper( class_name )); + for (const char *class_name = NULL; (class_name = registers->_rclasses.iter()) != NULL;) { + const char * class_name_to_upper = toUpper(class_name); + fprintf(fp," %s,\n", class_name_to_upper); + delete[] class_name_to_upper; } // Finish defining enumeration fprintf(fp, " _last_Mach_Reg_Class\n"); @@ -148,7 +146,7 @@ void ArchDesc::declare_register_masks(FILE *fp_hpp) { const char *rc_name; - if( _register ) { + if (_register) { // Build enumeration of user-defined register classes. defineRegClassEnum(fp_hpp, _register); @@ -156,24 +154,27 @@ fprintf(fp_hpp,"\n"); fprintf(fp_hpp,"// Register masks, one for each register class.\n"); _register->_rclasses.reset(); - for( rc_name = NULL; - (rc_name = _register->_rclasses.iter()) != NULL; ) { - const char *prefix = ""; - RegClass *reg_class = _register->getRegClass(rc_name); - assert( reg_class, "Using an undefined register class"); + for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) { + const char *prefix = ""; + RegClass *reg_class = _register->getRegClass(rc_name); + assert(reg_class, "Using an undefined register class"); + + const char* rc_name_to_upper = toUpper(rc_name); if (reg_class->_user_defined == NULL) { - fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix, toUpper( rc_name ) ); - fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name )); + fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix, rc_name_to_upper); + fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper); } else { - fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, toUpper( rc_name ), reg_class->_user_defined); + fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, rc_name_to_upper, reg_class->_user_defined); } - if( reg_class->_stack_or_reg ) { + if (reg_class->_stack_or_reg) { assert(reg_class->_user_defined == NULL, "no user defined reg class here"); - fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, toUpper( rc_name ) ); - fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name ) ); + fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, rc_name_to_upper); + fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper); } + delete[] rc_name_to_upper; + } } } @@ -183,34 +184,41 @@ void ArchDesc::build_register_masks(FILE *fp_cpp) { const char *rc_name; - if( _register ) { + if (_register) { // Generate a list of register masks, one for each class. fprintf(fp_cpp,"\n"); fprintf(fp_cpp,"// Register masks, one for each register class.\n"); _register->_rclasses.reset(); - for( rc_name = NULL; - (rc_name = _register->_rclasses.iter()) != NULL; ) { - const char *prefix = ""; - RegClass *reg_class = _register->getRegClass(rc_name); - assert( reg_class, "Using an undefined register class"); - - if (reg_class->_user_defined != NULL) continue; + for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) { + const char *prefix = ""; + RegClass *reg_class = _register->getRegClass(rc_name); + assert(reg_class, "Using an undefined register class"); + + if (reg_class->_user_defined != NULL) { + continue; + } int len = RegisterForm::RegMask_Size(); - fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, toUpper( rc_name ) ); - { int i; - for( i = 0; i < len-1; i++ ) - fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,false)); - fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,false)); + const char* rc_name_to_upper = toUpper(rc_name); + fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, rc_name_to_upper); + + { + int i; + for(i = 0; i < len - 1; i++) { + fprintf(fp_cpp," 0x%x,", reg_class->regs_in_word(i, false)); + } + fprintf(fp_cpp," 0x%x );\n", reg_class->regs_in_word(i, false)); } - if( reg_class->_stack_or_reg ) { + if (reg_class->_stack_or_reg) { int i; - fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, toUpper( rc_name ) ); - for( i = 0; i < len-1; i++ ) - fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,true)); - fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,true)); + fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, rc_name_to_upper); + for(i = 0; i < len - 1; i++) { + fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i, true)); + } + fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i, true)); } + delete[] rc_name_to_upper; } } } @@ -2676,7 +2684,9 @@ if (strcmp(first_reg_class, "stack_slots") == 0) { fprintf(fp," return &(Compile::current()->FIRST_STACK_mask());\n"); } else { - fprintf(fp," return &%s_mask();\n", toUpper(first_reg_class)); + const char* first_reg_class_to_upper = toUpper(first_reg_class); + fprintf(fp," return &%s_mask();\n", first_reg_class_to_upper); + delete[] first_reg_class_to_upper; } } else { // Build a switch statement to return the desired mask. @@ -2688,7 +2698,9 @@ if( !strcmp(reg_class, "stack_slots") ) { fprintf(fp, " case %d: return &(Compile::current()->FIRST_STACK_mask());\n", index); } else { - fprintf(fp, " case %d: return &%s_mask();\n", index, toUpper(reg_class)); + const char* reg_class_to_upper = toUpper(reg_class); + fprintf(fp, " case %d: return &%s_mask();\n", index, reg_class_to_upper); + delete[] reg_class_to_upper; } } fprintf(fp," }\n"); diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/adlc/output_h.cpp --- a/src/share/vm/adlc/output_h.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/adlc/output_h.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -2069,9 +2069,21 @@ void closing() { fprintf(_cpp, " _LAST_MACH_OPER\n"); OutputMap::closing(); } - void map(OpClassForm &opc) { fprintf(_cpp, " %s", _AD.machOperEnum(opc._ident) ); } - void map(OperandForm &oper) { fprintf(_cpp, " %s", _AD.machOperEnum(oper._ident) ); } - void map(char *name) { fprintf(_cpp, " %s", _AD.machOperEnum(name)); } + void map(OpClassForm &opc) { + const char* opc_ident_to_upper = _AD.machOperEnum(opc._ident); + fprintf(_cpp, " %s", opc_ident_to_upper); + delete[] opc_ident_to_upper; + } + void map(OperandForm &oper) { + const char* oper_ident_to_upper = _AD.machOperEnum(oper._ident); + fprintf(_cpp, " %s", oper_ident_to_upper); + delete[] oper_ident_to_upper; + } + void map(char *name) { + const char* name_to_upper = _AD.machOperEnum(name); + fprintf(_cpp, " %s", name_to_upper); + delete[] name_to_upper; + } bool do_instructions() { return false; } void map(InstructForm &inst){ assert( false, "ShouldNotCallThis()"); } diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/c1/c1_ValueMap.cpp --- a/src/share/vm/c1/c1_ValueMap.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/c1/c1_ValueMap.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -316,6 +316,7 @@ ShortLoopOptimizer* _short_loop_optimizer; Instruction* _insertion_point; ValueStack * _state; + bool _insert_is_pred; void set_invariant(Value v) const { _gvn->set_processed(v); } bool is_invariant(Value v) const { return _gvn->is_processed(v); } @@ -339,6 +340,7 @@ assert(insertion_block->end()->as_Base() == NULL, "cannot insert into entry block"); _insertion_point = insertion_block->end()->prev(); + _insert_is_pred = loop_header->is_predecessor(insertion_block); BlockEnd *block_end = insertion_block->end(); _state = block_end->state_before(); @@ -379,13 +381,13 @@ } else if (cur->as_LoadField() != NULL) { LoadField* lf = (LoadField*)cur; // deoptimizes on NullPointerException - cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj()); + cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj()) && _insert_is_pred; } else if (cur->as_ArrayLength() != NULL) { ArrayLength *length = cur->as_ArrayLength(); cur_invariant = is_invariant(length->array()); } else if (cur->as_LoadIndexed() != NULL) { LoadIndexed *li = (LoadIndexed *)cur->as_LoadIndexed(); - cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index()); + cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index()) && _insert_is_pred; } if (cur_invariant) { diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/classfile/classFileParser.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -1723,9 +1723,6 @@ } else { coll->set_contended_group(0); // default contended group } - coll->set_contended(true); - } else { - coll->set_contended(false); } } } diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/classfile/classFileParser.hpp --- a/src/share/vm/classfile/classFileParser.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/classfile/classFileParser.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -150,7 +150,6 @@ void set_contended_group(u2 group) { _contended_group = group; } u2 contended_group() { return _contended_group; } - void set_contended(bool contended) { set_annotation(_sun_misc_Contended); } bool is_contended() { return has_annotation(_sun_misc_Contended); } }; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/classfile/classLoaderData.cpp --- a/src/share/vm/classfile/classLoaderData.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/classfile/classLoaderData.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -70,15 +70,19 @@ _is_anonymous(is_anonymous), _keep_alive(is_anonymous), // initially _metaspace(NULL), _unloading(false), _klasses(NULL), _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL), - _next(NULL), _dependencies(NULL), + _next(NULL), _dependencies(), _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) { // empty } void ClassLoaderData::init_dependencies(TRAPS) { + _dependencies.init(CHECK); +} + +void ClassLoaderData::Dependencies::init(TRAPS) { // Create empty dependencies array to add to. CMS requires this to be // an oop so that it can track additions via card marks. We think. - _dependencies = (oop)oopFactory::new_objectArray(2, CHECK); + _list_head = oopFactory::new_objectArray(2, CHECK); } bool ClassLoaderData::claim() { @@ -95,13 +99,17 @@ } f->do_oop(&_class_loader); - f->do_oop(&_dependencies); + _dependencies.oops_do(f); _handles->oops_do(f); if (klass_closure != NULL) { classes_do(klass_closure); } } +void ClassLoaderData::Dependencies::oops_do(OopClosure* f) { + f->do_oop((oop*)&_list_head); +} + void ClassLoaderData::classes_do(KlassClosure* klass_closure) { for (Klass* k = _klasses; k != NULL; k = k->next_link()) { klass_closure->do_klass(k); @@ -154,14 +162,14 @@ // It's a dependency we won't find through GC, add it. This is relatively rare // Must handle over GC point. Handle dependency(THREAD, to); - from_cld->add_dependency(dependency, CHECK); + from_cld->_dependencies.add(dependency, CHECK); } -void ClassLoaderData::add_dependency(Handle dependency, TRAPS) { +void ClassLoaderData::Dependencies::add(Handle dependency, TRAPS) { // Check first if this dependency is already in the list. // Save a pointer to the last to add to under the lock. - objArrayOop ok = (objArrayOop)_dependencies; + objArrayOop ok = _list_head; objArrayOop last = NULL; while (ok != NULL) { last = ok; @@ -184,16 +192,17 @@ objArrayHandle new_dependency(THREAD, deps); // Add the dependency under lock - locked_add_dependency(last_handle, new_dependency); + locked_add(last_handle, new_dependency, THREAD); } -void ClassLoaderData::locked_add_dependency(objArrayHandle last_handle, - objArrayHandle new_dependency) { +void ClassLoaderData::Dependencies::locked_add(objArrayHandle last_handle, + objArrayHandle new_dependency, + Thread* THREAD) { // Have to lock and put the new dependency on the end of the dependency // array so the card mark for CMS sees that this dependency is new. // Can probably do this lock free with some effort. - MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); + ObjectLocker ol(Handle(THREAD, _list_head), THREAD); oop loader_or_mirror = new_dependency->obj_at(0); diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/classfile/classLoaderData.hpp --- a/src/share/vm/classfile/classLoaderData.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/classfile/classLoaderData.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -93,6 +93,18 @@ class ClassLoaderData : public CHeapObj { friend class VMStructs; private: + class Dependencies VALUE_OBJ_CLASS_SPEC { + objArrayOop _list_head; + void locked_add(objArrayHandle last, + objArrayHandle new_dependency, + Thread* THREAD); + public: + Dependencies() : _list_head(NULL) {} + void add(Handle dependency, TRAPS); + void init(TRAPS); + void oops_do(OopClosure* f); + }; + friend class ClassLoaderDataGraph; friend class ClassLoaderDataGraphMetaspaceIterator; friend class MetaDataFactory; @@ -100,10 +112,11 @@ static ClassLoaderData * _the_null_class_loader_data; - oop _class_loader; // oop used to uniquely identify a class loader - // class loader or a canonical class path - oop _dependencies; // oop to hold dependencies from this class loader - // data to others. + oop _class_loader; // oop used to uniquely identify a class loader + // class loader or a canonical class path + Dependencies _dependencies; // holds dependencies from this class loader + // data to others. + Metaspace * _metaspace; // Meta-space where meta-data defined by the // classes in the class loader are allocated. Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup. @@ -134,9 +147,6 @@ static Metaspace* _ro_metaspace; static Metaspace* _rw_metaspace; - void add_dependency(Handle dependency, TRAPS); - void locked_add_dependency(objArrayHandle last, objArrayHandle new_dependency); - void set_next(ClassLoaderData* next) { _next = next; } ClassLoaderData* next() const { return _next; } diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/classfile/systemDictionary.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -1592,9 +1592,10 @@ // Used for assertions and verification only Klass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_data) { #ifndef ASSERT - guarantee(VerifyBeforeGC || - VerifyDuringGC || - VerifyBeforeExit || + guarantee(VerifyBeforeGC || + VerifyDuringGC || + VerifyBeforeExit || + VerifyDuringStartup || VerifyAfterGC, "too expensive"); #endif assert_locked_or_safepoint(SystemDictionary_lock); diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/compiler/compileBroker.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -1206,11 +1206,8 @@ assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range"); assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods"); assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized"); - - if (!TieredCompilation) { - comp_level = CompLevel_highest_tier; - } - + // allow any levels for WhiteBox + assert(WhiteBoxAPI || TieredCompilation || comp_level == CompLevel_highest_tier, "only CompLevel_highest_tier must be used in non-tiered"); // return quickly if possible // lock, make sure that the compilation diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -48,6 +48,7 @@ #include "memory/iterator.hpp" #include "memory/referencePolicy.hpp" #include "memory/resourceArea.hpp" +#include "memory/tenuredGeneration.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/globals_extension.hpp" @@ -916,7 +917,31 @@ return; } - size_t expand_bytes = 0; + // Compute some numbers about the state of the heap. + const size_t used_after_gc = used(); + const size_t capacity_after_gc = capacity(); + + CardGeneration::compute_new_size(); + + // Reset again after a possible resizing + cmsSpace()->reset_after_compaction(); + + assert(used() == used_after_gc && used_after_gc <= capacity(), + err_msg("used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT + " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity())); +} + +void ConcurrentMarkSweepGeneration::compute_new_size_free_list() { + assert_locked_or_safepoint(Heap_lock); + + // If incremental collection failed, we just want to expand + // to the limit. + if (incremental_collection_failed()) { + clear_incremental_collection_failed(); + grow_to_reserved(); + return; + } + double free_percentage = ((double) free()) / capacity(); double desired_free_percentage = (double) MinHeapFreeRatio / 100; double maximum_free_percentage = (double) MaxHeapFreeRatio / 100; @@ -925,9 +950,7 @@ if (free_percentage < desired_free_percentage) { size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage)); assert(desired_capacity >= capacity(), "invalid expansion size"); - expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes); - } - if (expand_bytes > 0) { + size_t expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes); if (PrintGCDetails && Verbose) { size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage)); gclog_or_tty->print_cr("\nFrom compute_new_size: "); @@ -961,6 +984,14 @@ gclog_or_tty->print_cr(" Expanded free fraction %f", ((double) free()) / capacity()); } + } else { + size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage)); + assert(desired_capacity <= capacity(), "invalid expansion size"); + size_t shrink_bytes = capacity() - desired_capacity; + // Don't shrink unless the delta is greater than the minimum shrink we want + if (shrink_bytes >= MinHeapDeltaBytes) { + shrink_free_list_by(shrink_bytes); + } } } @@ -1872,7 +1903,7 @@ assert_locked_or_safepoint(Heap_lock); FreelistLocker z(this); MetaspaceGC::compute_new_size(); - _cmsGen->compute_new_size(); + _cmsGen->compute_new_size_free_list(); } // A work method used by foreground collection to determine @@ -2601,6 +2632,10 @@ } void ConcurrentMarkSweepGeneration::gc_prologue(bool full) { + + _capacity_at_prologue = capacity(); + _used_at_prologue = used(); + // Delegate to CMScollector which knows how to coordinate between // this and any other CMS generations that it is responsible for // collecting. @@ -2774,6 +2809,23 @@ } } + +void +CMSCollector::print_on_error(outputStream* st) { + CMSCollector* collector = ConcurrentMarkSweepGeneration::_collector; + if (collector != NULL) { + CMSBitMap* bitmap = &collector->_markBitMap; + st->print_cr("Marking Bits: (CMSBitMap*) " PTR_FORMAT, bitmap); + bitmap->print_on_error(st, " Bits: "); + + st->cr(); + + CMSBitMap* mut_bitmap = &collector->_modUnionTable; + st->print_cr("Mod Union Table: (CMSBitMap*) " PTR_FORMAT, mut_bitmap); + mut_bitmap->print_on_error(st, " Bits: "); + } +} + //////////////////////////////////////////////////////// // CMS Verification Support //////////////////////////////////////////////////////// @@ -3300,6 +3352,26 @@ } +void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) { + assert_locked_or_safepoint(ExpandHeap_lock); + // Shrink committed space + _virtual_space.shrink_by(bytes); + // Shrink space; this also shrinks the space's BOT + _cmsSpace->set_end((HeapWord*) _virtual_space.high()); + size_t new_word_size = heap_word_size(_cmsSpace->capacity()); + // Shrink the shared block offset array + _bts->resize(new_word_size); + MemRegion mr(_cmsSpace->bottom(), new_word_size); + // Shrink the card table + Universe::heap()->barrier_set()->resize_covered_region(mr); + + if (Verbose && PrintGC) { + size_t new_mem_size = _virtual_space.committed_size(); + size_t old_mem_size = new_mem_size + bytes; + gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K", + name(), old_mem_size/K, new_mem_size/K); + } +} void ConcurrentMarkSweepGeneration::shrink(size_t bytes) { assert_locked_or_safepoint(Heap_lock); @@ -3351,7 +3423,7 @@ return success; } -void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) { +void ConcurrentMarkSweepGeneration::shrink_free_list_by(size_t bytes) { assert_locked_or_safepoint(Heap_lock); assert_lock_strong(freelistLock()); // XXX Fix when compaction is implemented. @@ -6476,6 +6548,10 @@ } } +void CMSBitMap::print_on_error(outputStream* st, const char* prefix) const { + _bm.print_on_error(st, prefix); +} + #ifndef PRODUCT void CMSBitMap::assert_locked() const { CMSLockVerifier::assert_locked(lock()); @@ -9074,51 +9150,6 @@ } } -// The desired expansion delta is computed so that: -// . desired free percentage or greater is used -void ASConcurrentMarkSweepGeneration::compute_new_size() { - assert_locked_or_safepoint(Heap_lock); - - GenCollectedHeap* gch = (GenCollectedHeap*) GenCollectedHeap::heap(); - - // If incremental collection failed, we just want to expand - // to the limit. - if (incremental_collection_failed()) { - clear_incremental_collection_failed(); - grow_to_reserved(); - return; - } - - assert(UseAdaptiveSizePolicy, "Should be using adaptive sizing"); - - assert(gch->kind() == CollectedHeap::GenCollectedHeap, - "Wrong type of heap"); - int prev_level = level() - 1; - assert(prev_level >= 0, "The cms generation is the lowest generation"); - Generation* prev_gen = gch->get_gen(prev_level); - assert(prev_gen->kind() == Generation::ASParNew, - "Wrong type of young generation"); - ParNewGeneration* younger_gen = (ParNewGeneration*) prev_gen; - size_t cur_eden = younger_gen->eden()->capacity(); - CMSAdaptiveSizePolicy* size_policy = cms_size_policy(); - size_t cur_promo = free(); - size_policy->compute_tenured_generation_free_space(cur_promo, - max_available(), - cur_eden); - resize(cur_promo, size_policy->promo_size()); - - // Record the new size of the space in the cms generation - // that is available for promotions. This is temporary. - // It should be the desired promo size. - size_policy->avg_cms_promo()->sample(free()); - size_policy->avg_old_live()->sample(used()); - - if (UsePerfData) { - CMSGCAdaptivePolicyCounters* counters = gc_adaptive_policy_counters(); - counters->update_cms_capacity_counter(capacity()); - } -} - void ASConcurrentMarkSweepGeneration::shrink_by(size_t desired_bytes) { assert_locked_or_safepoint(Heap_lock); assert_lock_strong(freelistLock()); diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -60,6 +60,7 @@ class FreeChunk; class PromotionInfo; class ScanMarkedObjectsAgainCarefullyClosure; +class TenuredGeneration; // A generic CMS bit map. It's the basis for both the CMS marking bit map // as well as for the mod union table (in each case only a subset of the @@ -150,6 +151,8 @@ size_t heapWordToOffset(HeapWord* addr) const; size_t heapWordDiffToOffsetDiff(size_t diff) const; + void print_on_error(outputStream* st, const char* prefix) const; + // debugging // is this address range covered by the bit-map? NOT_PRODUCT( @@ -810,9 +813,6 @@ // used regions of each generation to limit the extent of sweep void save_sweep_limits(); - // Resize the generations included in the collector. - void compute_new_size(); - // A work method used by foreground collection to determine // what type of collection (compacting or not, continuing or fresh) // it should do. @@ -909,6 +909,9 @@ void releaseFreelistLocks() const; bool haveFreelistLocks() const; + // Adjust size of underlying generation + void compute_new_size(); + // GC prologue and epilogue void gc_prologue(bool full); void gc_epilogue(bool full); @@ -983,6 +986,8 @@ CMSAdaptiveSizePolicy* size_policy(); CMSGCAdaptivePolicyCounters* gc_adaptive_policy_counters(); + static void print_on_error(outputStream* st); + // debugging void verify(); bool verify_after_remark(); @@ -1082,7 +1087,7 @@ protected: // Shrink generation by specified size (returns false if unable to shrink) - virtual void shrink_by(size_t bytes); + void shrink_free_list_by(size_t bytes); // Update statistics for GC virtual void update_gc_stats(int level, bool full); @@ -1233,6 +1238,7 @@ CMSExpansionCause::Cause cause); virtual bool expand(size_t bytes, size_t expand_bytes); void shrink(size_t bytes); + void shrink_by(size_t bytes); HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz); bool expand_and_ensure_spooling_space(PromotionInfo* promo); @@ -1293,7 +1299,13 @@ bool must_be_youngest() const { return false; } bool must_be_oldest() const { return true; } - void compute_new_size(); + // Resize the generation after a compacting GC. The + // generation can be treated as a contiguous space + // after the compaction. + virtual void compute_new_size(); + // Resize the generation after a non-compacting + // collection. + void compute_new_size_free_list(); CollectionTypes debug_collection_type() { return _debug_collection_type; } void rotate_debug_collection_type(); @@ -1315,7 +1327,6 @@ virtual void shrink_by(size_t bytes); public: - virtual void compute_new_size(); ASConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size, int level, CardTableRS* ct, bool use_adaptive_freelists, diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -101,6 +101,10 @@ } #endif +void CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const { + _bm.print_on_error(st, prefix); +} + bool CMBitMap::allocate(ReservedSpace heap_rs) { _bmStartWord = (HeapWord*)(heap_rs.base()); _bmWordSize = heap_rs.size()/HeapWordSize; // heap_rs.size() is in bytes @@ -3277,6 +3281,13 @@ } } +void ConcurrentMark::print_on_error(outputStream* st) const { + st->print_cr("Marking Bits (Prev, Next): (CMBitMap*) " PTR_FORMAT ", (CMBitMap*) " PTR_FORMAT, + _prevMarkBitMap, _nextMarkBitMap); + _prevMarkBitMap->print_on_error(st, " Prev Bits: "); + _nextMarkBitMap->print_on_error(st, " Next Bits: "); +} + // We take a break if someone is trying to stop the world. bool ConcurrentMark::do_yield_check(uint worker_id) { if (should_yield()) { diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -113,6 +113,8 @@ return res; } + void print_on_error(outputStream* st, const char* prefix) const; + // debugging NOT_PRODUCT(bool covers(ReservedSpace rs) const;) }; @@ -829,6 +831,8 @@ void print_worker_threads_on(outputStream* st) const; + void print_on_error(outputStream* st) const; + // The following indicate whether a given verbose level has been // set. Notice that anything above stats is conditional to // _MARKING_VERBOSE_ having been set to 1 diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -3427,6 +3427,15 @@ heap_region_iterate(&blk); } +void G1CollectedHeap::print_on_error(outputStream* st) const { + this->CollectedHeap::print_on_error(st); + + if (_cm != NULL) { + st->cr(); + _cm->print_on_error(st); + } +} + void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { if (G1CollectedHeap::use_parallel_gc_threads()) { workers()->print_worker_threads_on(st); diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -1575,6 +1575,7 @@ virtual void verify(bool silent); virtual void print_on(outputStream* st) const; virtual void print_extended_on(outputStream* st) const; + virtual void print_on_error(outputStream* st) const; virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -173,6 +173,12 @@ void reset_counters(); #endif // #ifndef PRODUCT + void print_on_error(outputStream* st) const { + st->print_cr("Marking Bits: (ParMarkBitMap*) " PTR_FORMAT, this); + _beg_bits.print_on_error(st, " Begin Bits: "); + _end_bits.print_on_error(st, " End Bits: "); + } + #ifdef ASSERT void verify_clear() const; inline void verify_bit(idx_t bit) const; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -648,6 +648,15 @@ MetaspaceAux::print_on(st); } +void ParallelScavengeHeap::print_on_error(outputStream* st) const { + this->CollectedHeap::print_on_error(st); + + if (UseParallelOldGC) { + st->cr(); + PSParallelCompact::print_on_error(st); + } +} + void ParallelScavengeHeap::gc_threads_do(ThreadClosure* tc) const { PSScavenge::gc_task_manager()->threads_do(tc); } diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -220,6 +220,7 @@ void prepare_for_verify(); virtual void print_on(outputStream* st) const; + virtual void print_on_error(outputStream* st) const; virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; virtual void print_tracing_info() const; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -165,6 +165,10 @@ #endif // #ifdef ASSERT +void PSParallelCompact::print_on_error(outputStream* st) { + _mark_bitmap.print_on_error(st); +} + #ifndef PRODUCT const char* PSParallelCompact::space_names[] = { "old ", "eden", "from", "to " diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -1163,6 +1163,8 @@ // Time since last full gc (in milliseconds). static jlong millis_since_last_gc(); + static void print_on_error(outputStream* st); + #ifndef PRODUCT // Debugging support. static const char* space_names[last_space_id]; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/gc_interface/collectedHeap.hpp --- a/src/share/vm/gc_interface/collectedHeap.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -567,6 +567,14 @@ print_on(st); } + virtual void print_on_error(outputStream* st) const { + st->print_cr("Heap:"); + print_extended_on(st); + st->cr(); + + _barrier_set->print_on(st); + } + // Print all GC threads (other than the VM thread) // used by this heap. virtual void print_gc_threads_on(outputStream* st) const = 0; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/interpreter/linkResolver.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -217,6 +217,7 @@ TRAPS) { vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name); if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s", vmIntrinsics::name_at(iid), klass->external_name(), name->as_C_string(), full_signature->as_C_string()); @@ -231,6 +232,7 @@ TempNewSymbol basic_signature = MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK); if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("lookup_polymorphic_method %s %s => basic %s", name->as_C_string(), full_signature->as_C_string(), @@ -283,6 +285,8 @@ } if (result.not_null()) { #ifdef ASSERT + ResourceMark rm(THREAD); + TempNewSymbol basic_signature = MethodHandles::lookup_basic_type_signature(full_signature, CHECK); int actual_size_of_params = result->size_of_parameters(); @@ -1222,8 +1226,10 @@ Symbol* method_signature = NULL; KlassHandle current_klass; resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); - if (TraceMethodHandles) + if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string()); + } resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK); } diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/memory/allocation.hpp --- a/src/share/vm/memory/allocation.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/memory/allocation.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -611,4 +611,23 @@ void check() PRODUCT_RETURN; }; +// Helper class to allocate arrays that may become large. +// Uses the OS malloc for allocations smaller than ArrayAllocatorMallocLimit +// and uses mapped memory for larger allocations. +// Most OS mallocs do something similar but Solaris malloc does not revert +// to mapped memory for large allocations. By default ArrayAllocatorMallocLimit +// is set so that we always use malloc except for Solaris where we set the +// limit to get mapped memory. +template +class ArrayAllocator : StackObj { + char* _addr; + bool _use_malloc; + size_t _size; + public: + ArrayAllocator() : _addr(NULL), _use_malloc(false), _size(0) { } + ~ArrayAllocator() { free(); } + E* allocate(size_t length); + void free(); +}; + #endif // SHARE_VM_MEMORY_ALLOCATION_HPP diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/memory/allocation.inline.hpp --- a/src/share/vm/memory/allocation.inline.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/memory/allocation.inline.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -108,5 +108,49 @@ FreeHeap(p, F); } +template +E* ArrayAllocator::allocate(size_t length) { + assert(_addr == NULL, "Already in use"); + + _size = sizeof(E) * length; + _use_malloc = _size < ArrayAllocatorMallocLimit; + + if (_use_malloc) { + _addr = AllocateHeap(_size, F); + if (_addr == NULL && _size >= (size_t)os::vm_allocation_granularity()) { + // malloc failed let's try with mmap instead + _use_malloc = false; + } else { + return (E*)_addr; + } + } + + int alignment = os::vm_allocation_granularity(); + _size = align_size_up(_size, alignment); + + _addr = os::reserve_memory(_size, NULL, alignment); + if (_addr == NULL) { + vm_exit_out_of_memory(_size, "Allocator (reserve)"); + } + + bool success = os::commit_memory(_addr, _size, false /* executable */); + if (!success) { + vm_exit_out_of_memory(_size, "Allocator (commit)"); + } + + return (E*)_addr; +} + +template +void ArrayAllocator::free() { + if (_addr != NULL) { + if (_use_malloc) { + FreeHeap(_addr, F); + } else { + os::release_memory(_addr, _size); + } + _addr = NULL; + } +} #endif // SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/memory/genCollectedHeap.cpp --- a/src/share/vm/memory/genCollectedHeap.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/memory/genCollectedHeap.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -819,12 +819,13 @@ // Returns "TRUE" iff "p" points into the committed areas of the heap. bool GenCollectedHeap::is_in(const void* p) const { #ifndef ASSERT - guarantee(VerifyBeforeGC || - VerifyDuringGC || - VerifyBeforeExit || - PrintAssembly || - tty->count() != 0 || // already printing - VerifyAfterGC || + guarantee(VerifyBeforeGC || + VerifyDuringGC || + VerifyBeforeExit || + VerifyDuringStartup || + PrintAssembly || + tty->count() != 0 || // already printing + VerifyAfterGC || VMError::fatal_error_in_progress(), "too expensive"); #endif @@ -1132,6 +1133,17 @@ #endif // INCLUDE_ALL_GCS } +void GenCollectedHeap::print_on_error(outputStream* st) const { + this->CollectedHeap::print_on_error(st); + +#if INCLUDE_ALL_GCS + if (UseConcMarkSweepGC) { + st->cr(); + CMSCollector::print_on_error(st); + } +#endif // INCLUDE_ALL_GCS +} + void GenCollectedHeap::print_tracing_info() const { if (TraceGen0Time) { get_gen(0)->print_summary_info(); diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/memory/genCollectedHeap.hpp --- a/src/share/vm/memory/genCollectedHeap.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/memory/genCollectedHeap.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -344,6 +344,7 @@ virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; virtual void print_tracing_info() const; + virtual void print_on_error(outputStream* st) const; // PrintGC, PrintGCDetails support void print_heap_change(size_t prev_used) const; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/memory/generation.cpp --- a/src/share/vm/memory/generation.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/memory/generation.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -382,7 +382,9 @@ CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level, GenRemSet* remset) : - Generation(rs, initial_byte_size, level), _rs(remset) + Generation(rs, initial_byte_size, level), _rs(remset), + _shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(), + _used_at_prologue() { HeapWord* start = (HeapWord*)rs.base(); size_t reserved_byte_size = rs.size(); @@ -406,6 +408,9 @@ // the end if we try. guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned"); } + _min_heap_delta_bytes = MinHeapDeltaBytes; + _capacity_at_prologue = initial_byte_size; + _used_at_prologue = 0; } bool CardGeneration::expand(size_t bytes, size_t expand_bytes) { @@ -457,6 +462,160 @@ } +void CardGeneration::compute_new_size() { + assert(_shrink_factor <= 100, "invalid shrink factor"); + size_t current_shrink_factor = _shrink_factor; + _shrink_factor = 0; + + // We don't have floating point command-line arguments + // Note: argument processing ensures that MinHeapFreeRatio < 100. + const double minimum_free_percentage = MinHeapFreeRatio / 100.0; + const double maximum_used_percentage = 1.0 - minimum_free_percentage; + + // Compute some numbers about the state of the heap. + const size_t used_after_gc = used(); + const size_t capacity_after_gc = capacity(); + + const double min_tmp = used_after_gc / maximum_used_percentage; + size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx)); + // Don't shrink less than the initial generation size + minimum_desired_capacity = MAX2(minimum_desired_capacity, + spec()->init_size()); + assert(used_after_gc <= minimum_desired_capacity, "sanity check"); + + if (PrintGC && Verbose) { + const size_t free_after_gc = free(); + const double free_percentage = ((double)free_after_gc) / capacity_after_gc; + gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: "); + gclog_or_tty->print_cr(" " + " minimum_free_percentage: %6.2f" + " maximum_used_percentage: %6.2f", + minimum_free_percentage, + maximum_used_percentage); + gclog_or_tty->print_cr(" " + " free_after_gc : %6.1fK" + " used_after_gc : %6.1fK" + " capacity_after_gc : %6.1fK", + free_after_gc / (double) K, + used_after_gc / (double) K, + capacity_after_gc / (double) K); + gclog_or_tty->print_cr(" " + " free_percentage: %6.2f", + free_percentage); + } + + if (capacity_after_gc < minimum_desired_capacity) { + // If we have less free space than we want then expand + size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; + // Don't expand unless it's significant + if (expand_bytes >= _min_heap_delta_bytes) { + expand(expand_bytes, 0); // safe if expansion fails + } + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" expanding:" + " minimum_desired_capacity: %6.1fK" + " expand_bytes: %6.1fK" + " _min_heap_delta_bytes: %6.1fK", + minimum_desired_capacity / (double) K, + expand_bytes / (double) K, + _min_heap_delta_bytes / (double) K); + } + return; + } + + // No expansion, now see if we want to shrink + size_t shrink_bytes = 0; + // We would never want to shrink more than this + size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity; + + if (MaxHeapFreeRatio < 100) { + const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; + const double minimum_used_percentage = 1.0 - maximum_free_percentage; + const double max_tmp = used_after_gc / minimum_used_percentage; + size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); + maximum_desired_capacity = MAX2(maximum_desired_capacity, + spec()->init_size()); + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" " + " maximum_free_percentage: %6.2f" + " minimum_used_percentage: %6.2f", + maximum_free_percentage, + minimum_used_percentage); + gclog_or_tty->print_cr(" " + " _capacity_at_prologue: %6.1fK" + " minimum_desired_capacity: %6.1fK" + " maximum_desired_capacity: %6.1fK", + _capacity_at_prologue / (double) K, + minimum_desired_capacity / (double) K, + maximum_desired_capacity / (double) K); + } + assert(minimum_desired_capacity <= maximum_desired_capacity, + "sanity check"); + + if (capacity_after_gc > maximum_desired_capacity) { + // Capacity too large, compute shrinking size + shrink_bytes = capacity_after_gc - maximum_desired_capacity; + // We don't want shrink all the way back to initSize if people call + // System.gc(), because some programs do that between "phases" and then + // we'd just have to grow the heap up again for the next phase. So we + // damp the shrinking: 0% on the first call, 10% on the second call, 40% + // on the third call, and 100% by the fourth call. But if we recompute + // size without shrinking, it goes back to 0%. + shrink_bytes = shrink_bytes / 100 * current_shrink_factor; + assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); + if (current_shrink_factor == 0) { + _shrink_factor = 10; + } else { + _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100); + } + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" " + " shrinking:" + " initSize: %.1fK" + " maximum_desired_capacity: %.1fK", + spec()->init_size() / (double) K, + maximum_desired_capacity / (double) K); + gclog_or_tty->print_cr(" " + " shrink_bytes: %.1fK" + " current_shrink_factor: %d" + " new shrink factor: %d" + " _min_heap_delta_bytes: %.1fK", + shrink_bytes / (double) K, + current_shrink_factor, + _shrink_factor, + _min_heap_delta_bytes / (double) K); + } + } + } + + if (capacity_after_gc > _capacity_at_prologue) { + // We might have expanded for promotions, in which case we might want to + // take back that expansion if there's room after GC. That keeps us from + // stretching the heap with promotions when there's plenty of room. + size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue; + expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes); + // We have two shrinking computations, take the largest + shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion); + assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" " + " aggressive shrinking:" + " _capacity_at_prologue: %.1fK" + " capacity_after_gc: %.1fK" + " expansion_for_promotion: %.1fK" + " shrink_bytes: %.1fK", + capacity_after_gc / (double) K, + _capacity_at_prologue / (double) K, + expansion_for_promotion / (double) K, + shrink_bytes / (double) K); + } + } + // Don't shrink unless it's significant + if (shrink_bytes >= _min_heap_delta_bytes) { + shrink(shrink_bytes); + } +} + // Currently nothing to do. void CardGeneration::prepare_for_verify() {} diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/memory/generation.hpp --- a/src/share/vm/memory/generation.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/memory/generation.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -634,6 +634,17 @@ // This is local to this generation. BlockOffsetSharedArray* _bts; + // current shrinking effect: this damps shrinking when the heap gets empty. + size_t _shrink_factor; + + size_t _min_heap_delta_bytes; // Minimum amount to expand. + + // Some statistics from before gc started. + // These are gathered in the gc_prologue (and should_collect) + // to control growing/shrinking policy in spite of promotions. + size_t _capacity_at_prologue; + size_t _used_at_prologue; + CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level, GenRemSet* remset); @@ -644,6 +655,11 @@ // necessarily the full "bytes") was done. virtual bool expand(size_t bytes, size_t expand_bytes); + // Shrink generation with specified size (returns false if unable to shrink) + virtual void shrink(size_t bytes) = 0; + + virtual void compute_new_size(); + virtual void clear_remembered_set(); virtual void invalidate_remembered_set(); @@ -667,7 +683,6 @@ friend class VM_PopulateDumpSharedSpace; protected: - size_t _min_heap_delta_bytes; // Minimum amount to expand. ContiguousSpace* _the_space; // actual space holding objects WaterMark _last_gc; // watermark between objects allocated before // and after last GC. @@ -688,11 +703,10 @@ public: OneContigSpaceCardGeneration(ReservedSpace rs, size_t initial_byte_size, - size_t min_heap_delta_bytes, int level, GenRemSet* remset, ContiguousSpace* space) : CardGeneration(rs, initial_byte_size, level, remset), - _the_space(space), _min_heap_delta_bytes(min_heap_delta_bytes) + _the_space(space) {} inline bool is_in(const void* p) const; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/memory/tenuredGeneration.cpp --- a/src/share/vm/memory/tenuredGeneration.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/memory/tenuredGeneration.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -39,7 +39,7 @@ size_t initial_byte_size, int level, GenRemSet* remset) : OneContigSpaceCardGeneration(rs, initial_byte_size, - MinHeapDeltaBytes, level, remset, NULL) + level, remset, NULL) { HeapWord* bottom = (HeapWord*) _virtual_space.low(); HeapWord* end = (HeapWord*) _virtual_space.high(); @@ -86,162 +86,6 @@ return "tenured generation"; } -void TenuredGeneration::compute_new_size() { - assert(_shrink_factor <= 100, "invalid shrink factor"); - size_t current_shrink_factor = _shrink_factor; - _shrink_factor = 0; - - // We don't have floating point command-line arguments - // Note: argument processing ensures that MinHeapFreeRatio < 100. - const double minimum_free_percentage = MinHeapFreeRatio / 100.0; - const double maximum_used_percentage = 1.0 - minimum_free_percentage; - - // Compute some numbers about the state of the heap. - const size_t used_after_gc = used(); - const size_t capacity_after_gc = capacity(); - - const double min_tmp = used_after_gc / maximum_used_percentage; - size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx)); - // Don't shrink less than the initial generation size - minimum_desired_capacity = MAX2(minimum_desired_capacity, - spec()->init_size()); - assert(used_after_gc <= minimum_desired_capacity, "sanity check"); - - if (PrintGC && Verbose) { - const size_t free_after_gc = free(); - const double free_percentage = ((double)free_after_gc) / capacity_after_gc; - gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: "); - gclog_or_tty->print_cr(" " - " minimum_free_percentage: %6.2f" - " maximum_used_percentage: %6.2f", - minimum_free_percentage, - maximum_used_percentage); - gclog_or_tty->print_cr(" " - " free_after_gc : %6.1fK" - " used_after_gc : %6.1fK" - " capacity_after_gc : %6.1fK", - free_after_gc / (double) K, - used_after_gc / (double) K, - capacity_after_gc / (double) K); - gclog_or_tty->print_cr(" " - " free_percentage: %6.2f", - free_percentage); - } - - if (capacity_after_gc < minimum_desired_capacity) { - // If we have less free space than we want then expand - size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; - // Don't expand unless it's significant - if (expand_bytes >= _min_heap_delta_bytes) { - expand(expand_bytes, 0); // safe if expansion fails - } - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" expanding:" - " minimum_desired_capacity: %6.1fK" - " expand_bytes: %6.1fK" - " _min_heap_delta_bytes: %6.1fK", - minimum_desired_capacity / (double) K, - expand_bytes / (double) K, - _min_heap_delta_bytes / (double) K); - } - return; - } - - // No expansion, now see if we want to shrink - size_t shrink_bytes = 0; - // We would never want to shrink more than this - size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity; - - if (MaxHeapFreeRatio < 100) { - const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; - const double minimum_used_percentage = 1.0 - maximum_free_percentage; - const double max_tmp = used_after_gc / minimum_used_percentage; - size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); - maximum_desired_capacity = MAX2(maximum_desired_capacity, - spec()->init_size()); - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " maximum_free_percentage: %6.2f" - " minimum_used_percentage: %6.2f", - maximum_free_percentage, - minimum_used_percentage); - gclog_or_tty->print_cr(" " - " _capacity_at_prologue: %6.1fK" - " minimum_desired_capacity: %6.1fK" - " maximum_desired_capacity: %6.1fK", - _capacity_at_prologue / (double) K, - minimum_desired_capacity / (double) K, - maximum_desired_capacity / (double) K); - } - assert(minimum_desired_capacity <= maximum_desired_capacity, - "sanity check"); - - if (capacity_after_gc > maximum_desired_capacity) { - // Capacity too large, compute shrinking size - shrink_bytes = capacity_after_gc - maximum_desired_capacity; - // We don't want shrink all the way back to initSize if people call - // System.gc(), because some programs do that between "phases" and then - // we'd just have to grow the heap up again for the next phase. So we - // damp the shrinking: 0% on the first call, 10% on the second call, 40% - // on the third call, and 100% by the fourth call. But if we recompute - // size without shrinking, it goes back to 0%. - shrink_bytes = shrink_bytes / 100 * current_shrink_factor; - assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); - if (current_shrink_factor == 0) { - _shrink_factor = 10; - } else { - _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100); - } - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " shrinking:" - " initSize: %.1fK" - " maximum_desired_capacity: %.1fK", - spec()->init_size() / (double) K, - maximum_desired_capacity / (double) K); - gclog_or_tty->print_cr(" " - " shrink_bytes: %.1fK" - " current_shrink_factor: %d" - " new shrink factor: %d" - " _min_heap_delta_bytes: %.1fK", - shrink_bytes / (double) K, - current_shrink_factor, - _shrink_factor, - _min_heap_delta_bytes / (double) K); - } - } - } - - if (capacity_after_gc > _capacity_at_prologue) { - // We might have expanded for promotions, in which case we might want to - // take back that expansion if there's room after GC. That keeps us from - // stretching the heap with promotions when there's plenty of room. - size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue; - expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes); - // We have two shrinking computations, take the largest - shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion); - assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " aggressive shrinking:" - " _capacity_at_prologue: %.1fK" - " capacity_after_gc: %.1fK" - " expansion_for_promotion: %.1fK" - " shrink_bytes: %.1fK", - capacity_after_gc / (double) K, - _capacity_at_prologue / (double) K, - expansion_for_promotion / (double) K, - shrink_bytes / (double) K); - } - } - // Don't shrink unless it's significant - if (shrink_bytes >= _min_heap_delta_bytes) { - shrink(shrink_bytes); - } - assert(used() == used_after_gc && used_after_gc <= capacity(), - "sanity check"); -} - void TenuredGeneration::gc_prologue(bool full) { _capacity_at_prologue = capacity(); _used_at_prologue = used(); @@ -312,6 +156,19 @@ size, is_tlab); } +void TenuredGeneration::compute_new_size() { + assert_locked_or_safepoint(Heap_lock); + + // Compute some numbers about the state of the heap. + const size_t used_after_gc = used(); + const size_t capacity_after_gc = capacity(); + + CardGeneration::compute_new_size(); + + assert(used() == used_after_gc && used_after_gc <= capacity(), + err_msg("used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT + " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity())); +} void TenuredGeneration::update_gc_stats(int current_level, bool full) { // If the next lower level(s) has been collected, gather any statistics diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/memory/tenuredGeneration.hpp --- a/src/share/vm/memory/tenuredGeneration.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/memory/tenuredGeneration.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -38,13 +38,6 @@ class TenuredGeneration: public OneContigSpaceCardGeneration { friend class VMStructs; protected: - // current shrinking effect: this damps shrinking when the heap gets empty. - size_t _shrink_factor; - // Some statistics from before gc started. - // These are gathered in the gc_prologue (and should_collect) - // to control growing/shrinking policy in spite of promotions. - size_t _capacity_at_prologue; - size_t _used_at_prologue; #if INCLUDE_ALL_GCS // To support parallel promotion: an array of parallel allocation @@ -80,9 +73,6 @@ return !CollectGen0First; } - // Mark sweep support - void compute_new_size(); - virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); bool should_collect(bool full, @@ -93,6 +83,7 @@ bool clear_all_soft_refs, size_t size, bool is_tlab); + virtual void compute_new_size(); #if INCLUDE_ALL_GCS // Overrides. diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/oops/method.hpp --- a/src/share/vm/oops/method.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/oops/method.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -758,15 +758,19 @@ void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason); public: - bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); } - void set_not_c1_compilable() { _access_flags.set_not_c1_compilable(); } - bool is_not_c2_compilable() const { return access_flags().is_not_c2_compilable(); } - void set_not_c2_compilable() { _access_flags.set_not_c2_compilable(); } + bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); } + void set_not_c1_compilable() { _access_flags.set_not_c1_compilable(); } + void clear_not_c1_compilable() { _access_flags.clear_not_c1_compilable(); } + bool is_not_c2_compilable() const { return access_flags().is_not_c2_compilable(); } + void set_not_c2_compilable() { _access_flags.set_not_c2_compilable(); } + void clear_not_c2_compilable() { _access_flags.clear_not_c2_compilable(); } - bool is_not_c1_osr_compilable() const { return is_not_c1_compilable(); } // don't waste an accessFlags bit - void set_not_c1_osr_compilable() { set_not_c1_compilable(); } // don't waste an accessFlags bit - bool is_not_c2_osr_compilable() const { return access_flags().is_not_c2_osr_compilable(); } - void set_not_c2_osr_compilable() { _access_flags.set_not_c2_osr_compilable(); } + bool is_not_c1_osr_compilable() const { return is_not_c1_compilable(); } // don't waste an accessFlags bit + void set_not_c1_osr_compilable() { set_not_c1_compilable(); } // don't waste an accessFlags bit + void clear_not_c1_osr_compilable() { clear_not_c1_compilable(); } // don't waste an accessFlags bit + bool is_not_c2_osr_compilable() const { return access_flags().is_not_c2_osr_compilable(); } + void set_not_c2_osr_compilable() { _access_flags.set_not_c2_osr_compilable(); } + void clear_not_c2_osr_compilable() { _access_flags.clear_not_c2_osr_compilable(); } // Background compilation support bool queued_for_compilation() const { return access_flags().queued_for_compilation(); } diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/oops/methodData.cpp --- a/src/share/vm/oops/methodData.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/oops/methodData.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -660,29 +660,9 @@ // Set the method back-pointer. _method = method(); - _invocation_counter.init(); - _backedge_counter.init(); - _invocation_counter_start = 0; - _backedge_counter_start = 0; - _num_loops = 0; - _num_blocks = 0; - _highest_comp_level = 0; - _highest_osr_comp_level = 0; - _would_profile = true; + init(); set_creation_mileage(mileage_of(method())); - // Initialize flags and trap history. - _nof_decompiles = 0; - _nof_overflow_recompiles = 0; - _nof_overflow_traps = 0; - _eflags = 0; - _arg_local = 0; - _arg_stack = 0; - _arg_returned = 0; - assert(sizeof(_trap_hist) % sizeof(HeapWord) == 0, "align"); - Copy::zero_to_words((HeapWord*) &_trap_hist, - sizeof(_trap_hist) / sizeof(HeapWord)); - // Go through the bytecodes and allocate and initialize the // corresponding data cells. int data_size = 0; @@ -721,7 +701,27 @@ post_initialize(&stream); set_size(object_size); +} +void MethodData::init() { + _invocation_counter.init(); + _backedge_counter.init(); + _invocation_counter_start = 0; + _backedge_counter_start = 0; + _num_loops = 0; + _num_blocks = 0; + _highest_comp_level = 0; + _highest_osr_comp_level = 0; + _would_profile = true; + + // Initialize flags and trap history. + _nof_decompiles = 0; + _nof_overflow_recompiles = 0; + _nof_overflow_traps = 0; + clear_escape_info(); + assert(sizeof(_trap_hist) % sizeof(HeapWord) == 0, "align"); + Copy::zero_to_words((HeapWord*) &_trap_hist, + sizeof(_trap_hist) / sizeof(HeapWord)); } // Get a measure of how much mileage the method has on it. diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/oops/methodData.hpp --- a/src/share/vm/oops/methodData.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/oops/methodData.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -1284,8 +1284,8 @@ return bytecode_cell_count(code) != no_profile_data; } - // Perform initialization of a new MethodData* - void initialize(methodHandle method); + // reset into original state + void init(); // My size int size_in_bytes() const { return _size; } @@ -1365,6 +1365,7 @@ intx arg_stack() { return _arg_stack; } intx arg_returned() { return _arg_returned; } uint arg_modified(int a) { ArgInfoData *aid = arg_info(); + assert(aid != NULL, "arg_info must be not null"); assert(a >= 0 && a < aid->number_of_args(), "valid argument number"); return aid->arg_modified(a); } @@ -1373,8 +1374,8 @@ void set_arg_stack(intx v) { _arg_stack = v; } void set_arg_returned(intx v) { _arg_returned = v; } void set_arg_modified(int a, uint v) { ArgInfoData *aid = arg_info(); + assert(aid != NULL, "arg_info must be not null"); assert(a >= 0 && a < aid->number_of_args(), "valid argument number"); - aid->set_arg_modified(a, v); } void clear_escape_info() { _eflags = _arg_local = _arg_stack = _arg_returned = 0; } diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/prims/whitebox.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -49,6 +49,7 @@ #endif // INCLUDE_NMT #include "compiler/compileBroker.hpp" +#include "runtime/compilationPolicy.hpp" bool WhiteBox::_used = false; @@ -214,11 +215,11 @@ return (code->is_alive() && !code->is_marked_for_deoptimization()); WB_END -WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method)) +WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); MutexLockerEx mu(Compile_lock); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); - return !mh->is_not_compilable(); + return CompilationPolicy::can_be_compiled(mh, comp_level); WB_END WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method)) @@ -242,7 +243,7 @@ mh->set_not_compilable(); WB_END -WB_ENTRY(jboolean, WB_SetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) +WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); bool result = mh->dont_inline(); @@ -255,6 +256,54 @@ CompileBroker::queue_size(CompLevel_full_profile) /* C1 */; WB_END + +WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + bool result = mh->force_inline(); + mh->set_force_inline(value == JNI_TRUE); + return result; +WB_END + +WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + nmethod* nm = CompileBroker::compile_method(mh, InvocationEntryBci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD); + MutexLockerEx mu(Compile_lock); + return (mh->queued_for_compilation() || nm != NULL); +WB_END + +WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + MutexLockerEx mu(Compile_lock); + MethodData* mdo = mh->method_data(); + + if (mdo != NULL) { + mdo->init(); + ResourceMark rm; + int arg_count = mdo->method()->size_of_parameters(); + for (int i = 0; i < arg_count; i++) { + mdo->set_arg_modified(i, 0); + } + } + + mh->backedge_counter()->init(); + mh->invocation_counter()->init(); + mh->set_interpreter_invocation_count(0); + mh->set_interpreter_throwout_count(0); + mh->clear_not_c1_compilable(); + mh->clear_not_c2_compilable(); + mh->clear_not_c2_osr_compilable(); + NOT_PRODUCT(mh->set_compiled_invocation_count(0)); + +#ifdef TIERED + mh->set_rate(0.0F); + mh->set_prev_event_count(0); + mh->set_prev_time(0); +#endif +WB_END + WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString)) ResourceMark rm(THREAD); int len; @@ -272,7 +321,6 @@ Universe::heap()->collect(GCCause::_last_ditch_collection); WB_END - //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -354,18 +402,24 @@ (void*)&WB_DeoptimizeMethod }, {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Method;)Z", (void*)&WB_IsMethodCompiled }, - {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;)Z", + {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;I)Z", (void*)&WB_IsMethodCompilable}, {CC"isMethodQueuedForCompilation", CC"(Ljava/lang/reflect/Method;)Z", (void*)&WB_IsMethodQueuedForCompilation}, {CC"makeMethodNotCompilable", CC"(Ljava/lang/reflect/Method;)V", (void*)&WB_MakeMethodNotCompilable}, - {CC"setDontInlineMethod", - CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_SetDontInlineMethod}, + {CC"testSetDontInlineMethod", + CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_TestSetDontInlineMethod}, {CC"getMethodCompilationLevel", CC"(Ljava/lang/reflect/Method;)I", (void*)&WB_GetMethodCompilationLevel}, {CC"getCompileQueuesSize", CC"()I", (void*)&WB_GetCompileQueuesSize}, + {CC"testSetForceInlineMethod", + CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_TestSetForceInlineMethod}, + {CC"enqueueMethodForCompilation", + CC"(Ljava/lang/reflect/Method;I)Z", (void*)&WB_EnqueueMethodForCompilation}, + {CC"clearMethodState", + CC"(Ljava/lang/reflect/Method;)V", (void*)&WB_ClearMethodState}, {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable }, {CC"fullGC", CC"()V", (void*)&WB_FullGC }, }; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/runtime/arguments.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -2010,11 +2010,12 @@ // than just disable the lock verification. This will be fixed under // bug 4788986. if (UseConcMarkSweepGC && FLSVerifyAllHeapReferences) { - if (VerifyGCStartAt == 0) { + if (VerifyDuringStartup) { warning("Heap verification at start-up disabled " "(due to current incompatibility with FLSVerifyAllHeapReferences)"); - VerifyGCStartAt = 1; // Disable verification at start-up + VerifyDuringStartup = false; // Disable verification at start-up } + if (VerifyBeforeExit) { warning("Heap verification at shutdown disabled " "(due to current incompatibility with FLSVerifyAllHeapReferences)"); diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/runtime/compilationPolicy.cpp --- a/src/share/vm/runtime/compilationPolicy.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/runtime/compilationPolicy.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -123,9 +123,10 @@ } if (comp_level == CompLevel_all) { return !m->is_not_compilable(CompLevel_simple) && !m->is_not_compilable(CompLevel_full_optimization); - } else { + } else if (is_compile(comp_level)) { return !m->is_not_compilable(comp_level); } + return false; } bool CompilationPolicy::is_compilation_enabled() { diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/runtime/compilationPolicy.hpp --- a/src/share/vm/runtime/compilationPolicy.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/runtime/compilationPolicy.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -96,7 +96,7 @@ void reset_counter_for_back_branch_event(methodHandle method); public: NonTieredCompPolicy() : _compiler_count(0) { } - virtual CompLevel initial_compile_level() { return CompLevel_initial_compile; } + virtual CompLevel initial_compile_level() { return CompLevel_highest_tier; } virtual int compiler_count(CompLevel comp_level); virtual void do_safepoint_work(); virtual void reprofile(ScopeDesc* trap_scope, bool is_osr); diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/runtime/globals.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -2123,6 +2123,10 @@ product(intx, PrefetchFieldsAhead, -1, \ "How many fields ahead to prefetch in oop scan (<= 0 means off)") \ \ + diagnostic(bool, VerifyDuringStartup, false, \ + "Verify memory system before executing any Java code " \ + "during VM initialization") \ + \ diagnostic(bool, VerifyBeforeExit, trueInDebug, \ "Verify system before exiting") \ \ @@ -3664,8 +3668,13 @@ product(bool, PrintGCCause, true, \ "Include GC cause in GC logging") \ \ - product(bool, AllowNonVirtualCalls, false, \ - "Obey the ACC_SUPER flag and allow invokenonvirtual calls") + product(bool , AllowNonVirtualCalls, false, \ + "Obey the ACC_SUPER flag and allow invokenonvirtual calls") \ + \ + experimental(uintx, ArrayAllocatorMallocLimit, \ + SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx), \ + "Allocation less than this value will be allocated " \ + "using malloc. Larger allocations will use mmap.") /* * Macros for factoring of globals diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/runtime/thread.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -3446,9 +3446,9 @@ } assert (Universe::is_fully_initialized(), "not initialized"); - if (VerifyBeforeGC && VerifyGCStartAt == 0) { - Universe::heap()->prepare_for_verify(); - Universe::verify(); // make sure we're starting with a clean slate + if (VerifyDuringStartup) { + VM_Verify verify_op(false /* silent */); // make sure we're starting with a clean slate + VMThread::execute(&verify_op); } EXCEPTION_MARK; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/runtime/vmStructs.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -478,6 +478,9 @@ \ nonstatic_field(CardGeneration, _rs, GenRemSet*) \ nonstatic_field(CardGeneration, _bts, BlockOffsetSharedArray*) \ + nonstatic_field(CardGeneration, _shrink_factor, size_t) \ + nonstatic_field(CardGeneration, _capacity_at_prologue, size_t) \ + nonstatic_field(CardGeneration, _used_at_prologue, size_t) \ \ nonstatic_field(CardTableModRefBS, _whole_heap, const MemRegion) \ nonstatic_field(CardTableModRefBS, _guard_index, const size_t) \ @@ -548,8 +551,6 @@ nonstatic_field(Space, _bottom, HeapWord*) \ nonstatic_field(Space, _end, HeapWord*) \ \ - nonstatic_field(TenuredGeneration, _shrink_factor, size_t) \ - nonstatic_field(TenuredGeneration, _capacity_at_prologue, size_t) \ nonstatic_field(ThreadLocalAllocBuffer, _start, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _top, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _end, HeapWord*) \ diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/runtime/vm_operations.cpp --- a/src/share/vm/runtime/vm_operations.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/runtime/vm_operations.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -175,7 +175,8 @@ } void VM_Verify::doit() { - Universe::verify(); + Universe::heap()->prepare_for_verify(); + Universe::verify(_silent); } bool VM_PrintThreads::doit_prologue() { diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/runtime/vm_operations.hpp --- a/src/share/vm/runtime/vm_operations.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/runtime/vm_operations.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -300,9 +300,9 @@ class VM_Verify: public VM_Operation { private: - KlassHandle _dependee; + bool _silent; public: - VM_Verify() {} + VM_Verify(bool silent) : _silent(silent) {} VMOp_Type type() const { return VMOp_Verify; } void doit(); }; diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/utilities/accessFlags.hpp --- a/src/share/vm/utilities/accessFlags.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/utilities/accessFlags.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -194,6 +194,9 @@ void set_is_obsolete() { atomic_set_bits(JVM_ACC_IS_OBSOLETE); } void set_is_prefixed_native() { atomic_set_bits(JVM_ACC_IS_PREFIXED_NATIVE); } + void clear_not_c1_compilable() { atomic_clear_bits(JVM_ACC_NOT_C1_COMPILABLE); } + void clear_not_c2_compilable() { atomic_clear_bits(JVM_ACC_NOT_C2_COMPILABLE); } + void clear_not_c2_osr_compilable() { atomic_clear_bits(JVM_ACC_NOT_C2_OSR_COMPILABLE); } // Klass* flags void set_has_vanilla_constructor() { atomic_set_bits(JVM_ACC_HAS_VANILLA_CONSTRUCTOR); } void set_has_finalizer() { atomic_set_bits(JVM_ACC_HAS_FINALIZER); } diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/utilities/bitMap.cpp --- a/src/share/vm/utilities/bitMap.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/utilities/bitMap.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -516,6 +516,10 @@ return sum; } +void BitMap::print_on_error(outputStream* st, const char* prefix) const { + st->print_cr("%s[" PTR_FORMAT ", " PTR_FORMAT ")", + prefix, map(), (char*)map() + (size() >> LogBitsPerByte)); +} #ifndef PRODUCT diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/utilities/bitMap.hpp --- a/src/share/vm/utilities/bitMap.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/utilities/bitMap.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -262,6 +262,7 @@ bool is_full() const; bool is_empty() const; + void print_on_error(outputStream* st, const char* prefix) const; #ifndef PRODUCT public: diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/utilities/globalDefinitions.hpp --- a/src/share/vm/utilities/globalDefinitions.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/utilities/globalDefinitions.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -845,6 +845,10 @@ return comp_level == CompLevel_highest_tier; } +inline bool is_compile(int comp_level) { + return is_c1_compile(comp_level) || is_c2_compile(comp_level); +} + //---------------------------------------------------------------------------------------------------- // 'Forward' declarations of frequently used classes // (in order to reduce interface dependencies & reduce diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/utilities/taskqueue.hpp --- a/src/share/vm/utilities/taskqueue.hpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/utilities/taskqueue.hpp Wed Apr 17 10:12:42 2013 -0700 @@ -253,6 +253,7 @@ template class GenericTaskQueue: public TaskQueueSuper { + ArrayAllocator _array_allocator; protected: typedef typename TaskQueueSuper::Age Age; typedef typename TaskQueueSuper::idx_t idx_t; @@ -314,7 +315,7 @@ template void GenericTaskQueue::initialize() { - _elems = NEW_C_HEAP_ARRAY(E, N, F); + _elems = _array_allocator.allocate(N); } template diff -r 124ca22437b1 -r 6c560f9ebb3e src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Fri Apr 12 10:14:42 2013 +0100 +++ b/src/share/vm/utilities/vmError.cpp Wed Apr 17 10:12:42 2013 -0700 @@ -685,13 +685,7 @@ STEP(190, "(printing heap information)" ) if (_verbose && Universe::is_fully_initialized()) { - // Print heap information before vm abort. As we'd like as much - // information as possible in the report we ask for the - // extended (i.e., more detailed) version. - Universe::print_on(st, true /* extended */); - st->cr(); - - Universe::heap()->barrier_set()->print_on(st); + Universe::heap()->print_on_error(st); st->cr(); st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page()); diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/6863420/Test.java --- a/test/compiler/6863420/Test.java Fri Apr 12 10:14:42 2013 +0100 +++ b/test/compiler/6863420/Test.java Wed Apr 17 10:12:42 2013 -0700 @@ -27,17 +27,35 @@ * @bug 6863420 * @summary os::javaTimeNanos() go backward on Solaris x86 * - * @run main/othervm Test + * Notice the internal timeout in timeout thread Test.TOT. + * @run main/othervm/timeout=300 Test */ public class Test { + + static final int INTERNAL_TIMEOUT=240; + static class TOT extends Thread { + public void run() { + try { + Thread.sleep(INTERNAL_TIMEOUT*1000); + } catch (InterruptedException ex) { + } + done = true; + } + } + static long value = 0; static boolean got_backward_time = false; + static volatile boolean done = false; public static void main(String args[]) { final int count = 100000; - for (int numThreads = 1; numThreads <= 32; numThreads++) { + TOT tot = new TOT(); + tot.setDaemon(true); + tot.start(); + + for (int numThreads = 1; !done && numThreads <= 32; numThreads++) { final int numRuns = 1; for (int t=1; t <= numRuns; t++) { final int curRun = t; @@ -48,7 +66,7 @@ Runnable thread = new Runnable() { public void run() { - for (long l = 0; l < 100000; l++) { + for (long l = 0; !done && l < 100000; l++) { final long start = System.nanoTime(); if (value == 12345678) { System.out.println("Wow!"); diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/8011706/Test8011706.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8011706/Test8011706.java Wed Apr 17 10:12:42 2013 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8011706 + * @summary loop invariant code motion may move load before store to the same field + * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation Test8011706 + * + */ + +public class Test8011706 { + int[] array; + + void m(boolean test, int[] array1, int[] array2) { + int i = 0; + if (test) { + array = array1; + } else { + array = array2; + } + + while(true) { + int v = array[i]; + i++; + if (i >= 10) return; + } + } + + static public void main(String[] args) { + int[] new_array = new int[10]; + Test8011706 ti = new Test8011706(); + boolean failed = false; + try { + for (int i = 0; i < 10000; i++) { + ti.array = null; + ti.m(true, new_array, new_array); + } + } catch(NullPointerException ex) { + throw new RuntimeException("TEST FAILED", ex); + } + System.out.println("TEST PASSED"); + } + +} diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/whitebox/ClearMethodStateTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/ClearMethodStateTest.java Wed Apr 17 10:12:42 2013 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test ClearMethodStateTest + * @library /testlibrary /testlibrary/whitebox + * @build ClearMethodStateTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ClearMethodStateTest + * @author igor.ignatyev@oracle.com + */ +public class ClearMethodStateTest extends CompilerWhiteBoxTest { + public static void main(String[] args) throws Exception { + // to prevent inlining #method into #compile() and #test() + WHITE_BOX.testSetDontInlineMethod(METHOD, true); + new ClearMethodStateTest().runTest(); + } + + protected void test() throws Exception { + checkNotCompiled(METHOD); + compile(); + checkCompiled(METHOD); + WHITE_BOX.clearMethodState(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + + + if (!TIERED_COMPILATION) { + WHITE_BOX.clearMethodState(METHOD); + compile(COMPILE_THRESHOLD); + checkCompiled(METHOD); + + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + WHITE_BOX.clearMethodState(METHOD); + + if (COMPILE_THRESHOLD > 1) { + compile(COMPILE_THRESHOLD - 1); + checkNotCompiled(METHOD); + } else { + System.err.println("Warning: 'CompileThreshold' <= 1"); + } + + method(); + checkCompiled(METHOD); + } else { + System.err.println( + "Warning: part of test is not applicable in Tiered"); + } + } +} diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/whitebox/CompilerWhiteBoxTest.java --- a/test/compiler/whitebox/CompilerWhiteBoxTest.java Fri Apr 12 10:14:42 2013 +0100 +++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java Wed Apr 17 10:12:42 2013 -0700 @@ -37,6 +37,8 @@ = Integer.parseInt(getVMOption("CompileThreshold", "10000")); protected static final boolean BACKGROUND_COMPILATION = Boolean.valueOf(getVMOption("BackgroundCompilation", "true")); + protected static final boolean TIERED_COMPILATION + = Boolean.valueOf(getVMOption("TieredCompilation", "false")); protected static Method getMethod(String name) { try { @@ -81,6 +83,9 @@ } protected static void checkNotCompiled(Method method) { + if (WHITE_BOX.isMethodQueuedForCompilation(method)) { + throw new RuntimeException(method + " must not be in queue"); + } if (WHITE_BOX.isMethodCompiled(method)) { throw new RuntimeException(method + " must be not compiled"); } @@ -139,8 +144,11 @@ protected abstract void test() throws Exception; protected final int compile() { + return compile(Math.max(COMPILE_THRESHOLD, 150000)); + } + + protected final int compile(int count) { int result = 0; - int count = Math.max(COMPILE_THRESHOLD, 150000); for (int i = 0; i < count; ++i) { result += method(); } diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/whitebox/DeoptimizeAllTest.java --- a/test/compiler/whitebox/DeoptimizeAllTest.java Fri Apr 12 10:14:42 2013 +0100 +++ b/test/compiler/whitebox/DeoptimizeAllTest.java Wed Apr 17 10:12:42 2013 -0700 @@ -33,7 +33,7 @@ public static void main(String[] args) throws Exception { // to prevent inlining #method into #compile() - WHITE_BOX.setDontInlineMethod(METHOD, true); + WHITE_BOX.testSetDontInlineMethod(METHOD, true); new DeoptimizeAllTest().runTest(); } diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/whitebox/DeoptimizeMethodTest.java --- a/test/compiler/whitebox/DeoptimizeMethodTest.java Fri Apr 12 10:14:42 2013 +0100 +++ b/test/compiler/whitebox/DeoptimizeMethodTest.java Wed Apr 17 10:12:42 2013 -0700 @@ -33,7 +33,7 @@ public static void main(String[] args) throws Exception { // to prevent inlining #method into #compile() - WHITE_BOX.setDontInlineMethod(METHOD, true); + WHITE_BOX.testSetDontInlineMethod(METHOD, true); new DeoptimizeMethodTest().runTest(); } diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/whitebox/EnqueueMethodForCompilationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/EnqueueMethodForCompilationTest.java Wed Apr 17 10:12:42 2013 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test EnqueueMethodForCompilationTest + * @library /testlibrary /testlibrary/whitebox + * @build EnqueueMethodForCompilationTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI EnqueueMethodForCompilationTest + * @author igor.ignatyev@oracle.com + */ +public class EnqueueMethodForCompilationTest extends CompilerWhiteBoxTest { + public static void main(String[] args) throws Exception { + // to prevent inlining #method into #compile() + WHITE_BOX.testSetDontInlineMethod(METHOD, true); + new EnqueueMethodForCompilationTest().runTest(); + } + + protected void test() throws Exception { + checkNotCompiled(METHOD); + + WHITE_BOX.enqueueMethodForCompilation(METHOD, 0); + if (WHITE_BOX.isMethodCompilable(METHOD, 0)) { + throw new RuntimeException(METHOD + " is compilable at level 0"); + } + checkNotCompiled(METHOD); + + WHITE_BOX.enqueueMethodForCompilation(METHOD, -1); + checkNotCompiled(METHOD); + + WHITE_BOX.enqueueMethodForCompilation(METHOD, 5); + if (!WHITE_BOX.isMethodCompilable(METHOD, 5)) { + checkNotCompiled(METHOD); + compile(); + checkCompiled(METHOD); + } else { + checkCompiled(METHOD); + } + + int compLevel = WHITE_BOX.getMethodCompilationLevel(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + + WHITE_BOX.enqueueMethodForCompilation(METHOD, compLevel); + checkCompiled(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + + compile(); + checkCompiled(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + } +} diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/whitebox/IsMethodCompilableTest.java --- a/test/compiler/whitebox/IsMethodCompilableTest.java Fri Apr 12 10:14:42 2013 +0100 +++ b/test/compiler/whitebox/IsMethodCompilableTest.java Wed Apr 17 10:12:42 2013 -0700 @@ -45,7 +45,7 @@ public static void main(String[] args) throws Exception { // to prevent inlining #method into #compile() - WHITE_BOX.setDontInlineMethod(METHOD, true); + WHITE_BOX.testSetDontInlineMethod(METHOD, true); new IsMethodCompilableTest().runTest(); } @@ -60,26 +60,47 @@ "Warning: test is not applicable if PerMethodRecompilationCutoff == Inf"); return; } - boolean madeNotCompilable = false; + + // deoptimze 'PerMethodRecompilationCutoff' times and clear state + for (long i = 0L, n = PER_METHOD_RECOMPILATION_CUTOFF - 1; i < n; ++i) { + compileAndDeoptimaze(); + } + if (!WHITE_BOX.isMethodCompilable(METHOD)) { + throw new RuntimeException(METHOD + " is not compilable after " + + (PER_METHOD_RECOMPILATION_CUTOFF - 1) + " iterations"); + } + WHITE_BOX.clearMethodState(METHOD); - for (long i = 0; i < PER_METHOD_RECOMPILATION_CUTOFF; ++i) { - compile(); - waitBackgroundCompilation(METHOD); - WHITE_BOX.deoptimizeMethod(METHOD); - if (!WHITE_BOX.isMethodCompilable(METHOD)) { - madeNotCompilable = true; - break; - } + // deoptimze 'PerMethodRecompilationCutoff' + 1 times + long i; + for (i = 0L; i < PER_METHOD_RECOMPILATION_CUTOFF + && WHITE_BOX.isMethodCompilable(METHOD); ++i) { + compileAndDeoptimaze(); } - if (!madeNotCompilable) { + if (i != PER_METHOD_RECOMPILATION_CUTOFF) { + throw new RuntimeException(METHOD + " is not compilable after " + + i + " iterations, but must only after " + + PER_METHOD_RECOMPILATION_CUTOFF); + } + if (WHITE_BOX.isMethodCompilable(METHOD)) { throw new RuntimeException(METHOD + " is still compilable after " + PER_METHOD_RECOMPILATION_CUTOFF + " iterations"); } compile(); - if (WHITE_BOX.isMethodCompiled(METHOD)) { - printInfo(METHOD); - throw new RuntimeException( - METHOD + " is not compilable but compiled"); + checkNotCompiled(METHOD); + + WHITE_BOX.clearMethodState(METHOD); + if (!WHITE_BOX.isMethodCompilable(METHOD)) { + throw new RuntimeException(METHOD + + " is compilable after clearMethodState()"); } + compile(); + checkCompiled(METHOD); + } + + private void compileAndDeoptimaze() throws Exception { + compile(); + waitBackgroundCompilation(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); } } diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/whitebox/MakeMethodNotCompilableTest.java --- a/test/compiler/whitebox/MakeMethodNotCompilableTest.java Fri Apr 12 10:14:42 2013 +0100 +++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java Wed Apr 17 10:12:42 2013 -0700 @@ -33,7 +33,7 @@ public static void main(String[] args) throws Exception { // to prevent inlining #method into #compile() - WHITE_BOX.setDontInlineMethod(METHOD, true); + WHITE_BOX.testSetDontInlineMethod(METHOD, true); new MakeMethodNotCompilableTest().runTest(); } @@ -46,9 +46,6 @@ throw new RuntimeException(METHOD + " must be not compilable"); } compile(); - if (WHITE_BOX.isMethodQueuedForCompilation(METHOD)) { - throw new RuntimeException(METHOD + " must not be in queue"); - } checkNotCompiled(METHOD); if (WHITE_BOX.isMethodCompilable(METHOD)) { throw new RuntimeException(METHOD + " must be not compilable"); diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/whitebox/SetDontInlineMethodTest.java --- a/test/compiler/whitebox/SetDontInlineMethodTest.java Fri Apr 12 10:14:42 2013 +0100 +++ b/test/compiler/whitebox/SetDontInlineMethodTest.java Wed Apr 17 10:12:42 2013 -0700 @@ -36,23 +36,23 @@ } protected void test() throws Exception { - if (WHITE_BOX.setDontInlineMethod(METHOD, true)) { + if (WHITE_BOX.testSetDontInlineMethod(METHOD, true)) { throw new RuntimeException("on start " + METHOD + " must be inlineable"); } - if (!WHITE_BOX.setDontInlineMethod(METHOD, true)) { + if (!WHITE_BOX.testSetDontInlineMethod(METHOD, true)) { throw new RuntimeException("after first change to true " + METHOD + " must be not inlineable"); } - if (!WHITE_BOX.setDontInlineMethod(METHOD, false)) { + if (!WHITE_BOX.testSetDontInlineMethod(METHOD, false)) { throw new RuntimeException("after second change to true " + METHOD + " must be still not inlineable"); } - if (WHITE_BOX.setDontInlineMethod(METHOD, false)) { + if (WHITE_BOX.testSetDontInlineMethod(METHOD, false)) { throw new RuntimeException("after first change to false" + METHOD + " must be inlineable"); } - if (WHITE_BOX.setDontInlineMethod(METHOD, false)) { + if (WHITE_BOX.testSetDontInlineMethod(METHOD, false)) { throw new RuntimeException("after second change to false " + METHOD + " must be inlineable"); } diff -r 124ca22437b1 -r 6c560f9ebb3e test/compiler/whitebox/SetForceInlineMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/SetForceInlineMethodTest.java Wed Apr 17 10:12:42 2013 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test SetForceInlineMethodTest + * @library /testlibrary /testlibrary/whitebox + * @build SetForceInlineMethodTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetForceInlineMethodTest + * @author igor.ignatyev@oracle.com + */ +public class SetForceInlineMethodTest extends CompilerWhiteBoxTest { + + public static void main(String[] args) throws Exception { + new SetForceInlineMethodTest().runTest(); + } + + protected void test() throws Exception { + if (WHITE_BOX.testSetForceInlineMethod(METHOD, true)) { + throw new RuntimeException("on start " + METHOD + + " must be not force inlineable"); + } + if (!WHITE_BOX.testSetForceInlineMethod(METHOD, true)) { + throw new RuntimeException("after first change to true " + METHOD + + " must be force inlineable"); + } + if (!WHITE_BOX.testSetForceInlineMethod(METHOD, false)) { + throw new RuntimeException("after second change to true " + METHOD + + " must be still force inlineable"); + } + if (WHITE_BOX.testSetForceInlineMethod(METHOD, false)) { + throw new RuntimeException("after first change to false" + METHOD + + " must be not force inlineable"); + } + if (WHITE_BOX.testSetForceInlineMethod(METHOD, false)) { + throw new RuntimeException("after second change to false " + METHOD + + " must be not force inlineable"); + } + } +} diff -r 124ca22437b1 -r 6c560f9ebb3e test/gc/6941923/Test6941923.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/6941923/Test6941923.java Wed Apr 17 10:12:42 2013 -0700 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test Test6941923.java + * @bug 6941923 + * @summary test flags for gc log rotation + * @library /testlibrary + * @run main/othervm/timeout=600 Test6941923 + * + */ +import com.oracle.java.testlibrary.*; +import java.io.File; +import java.io.FilenameFilter; +import java.util.ArrayList; +import java.util.Arrays; + +class GCLoggingGenerator { + + public static void main(String[] args) throws Exception { + + long sizeOfLog = Long.parseLong(args[0]); + long lines = sizeOfLog / 80; + // full.GC generates ad least 1-line which is not shorter then 80 chars + // for some GC 2 shorter lines are generated + for (long i = 0; i < lines; i++) { + System.gc(); + } + } +} + +public class Test6941923 { + + static final File currentDirectory = new File("."); + static final String logFileName = "test.log"; + static final int logFileSizeK = 16; + static FilenameFilter logFilter = new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.startsWith(logFileName); + } + }; + + public static void cleanLogs() { + for (File log : currentDirectory.listFiles(logFilter)) { + if (!log.delete()) { + throw new Error("Unable to delete " + log.getAbsolutePath()); + } + } + } + + public static void runTest(int numberOfFiles) throws Exception { + + ArrayList args = new ArrayList(); + String[] logOpts = new String[]{ + "-cp", System.getProperty("java.class.path"), + "-Xloggc:" + logFileName, + "-XX:-DisableExplicitGC", // to sure that System.gc() works + "-XX:+PrintGC", "-XX:+PrintGCDetails", "-XX:+UseGCLogFileRotation", + "-XX:NumberOfGCLogFiles=" + numberOfFiles, + "-XX:GCLogFileSize=" + logFileSizeK + "K", "-Xmx128M"}; + // System.getProperty("test.java.opts") is '' if no options is set + // need to skip such empty + String[] externalVMopts = System.getProperty("test.java.opts").length() == 0 + ? new String[0] + : System.getProperty("test.java.opts").split(" "); + args.addAll(Arrays.asList(externalVMopts)); + args.addAll(Arrays.asList(logOpts)); + args.add(GCLoggingGenerator.class.getName()); + args.add(String.valueOf(numberOfFiles * logFileSizeK * 1024)); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[0])); + pb.redirectErrorStream(true); + pb.redirectOutput(new File(GCLoggingGenerator.class.getName() + ".log")); + Process process = pb.start(); + int result = process.waitFor(); + if (result != 0) { + throw new Error("Unexpected exit code = " + result); + } + File[] logs = currentDirectory.listFiles(logFilter); + int smallFilesNumber = 0; + for (File log : logs) { + if (log.length() < logFileSizeK * 1024) { + smallFilesNumber++; + } + } + if (logs.length != numberOfFiles) { + throw new Error("There are only " + logs.length + " logs instead " + numberOfFiles); + } + if (smallFilesNumber > 1) { + throw new Error("There should maximum one log with size < " + logFileSizeK + "K"); + } + } + + public static void main(String[] args) throws Exception { + cleanLogs(); + runTest(1); + cleanLogs(); + runTest(3); + cleanLogs(); + } +} diff -r 124ca22437b1 -r 6c560f9ebb3e test/gc/6941923/test6941923.sh --- a/test/gc/6941923/test6941923.sh Fri Apr 12 10:14:42 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -## -## @test @(#)test6941923.sh -## @bug 6941923 -## @summary test new added flags for gc log rotation -## @author yqi -## @run shell test6941923.sh -## -## some tests require path to find test source dir -if [ "${TESTSRC}" = "" ] -then - TESTSRC=${PWD} - echo "TESTSRC not set. Using "${TESTSRC}" as default" -fi -echo "TESTSRC=${TESTSRC}" -## Adding common setup Variables for running shell tests. -. ${TESTSRC}/../../test_env.sh - -## skip on windows -OS=`uname -s` -case "$OS" in - Windows_* | CYGWIN_* ) - echo "Test skipped for Windows" - exit 0 - ;; -esac - -# create a small test case -testname="Test" -if [ -e ${testname}.java ]; then - rm -rf ${testname}.* -fi - -cat >> ${testname}.java << __EOF__ -import java.util.Vector; - -public class Test implements Runnable -{ - private boolean _should_stop = false; - - public static void main(String[] args) throws Exception { - - long limit = Long.parseLong(args[0]) * 60L * 1000L; // minutes - Test t = new Test(); - t.set_stop(false); - Thread thr = new Thread(t); - thr.start(); - - long time1 = System.currentTimeMillis(); - long time2 = System.currentTimeMillis(); - while (time2 - time1 < limit) { - try { - Thread.sleep(2000); // 2 seconds - } - catch(Exception e) {} - time2 = System.currentTimeMillis(); - System.out.print("\r... " + (time2 - time1)/1000 + " seconds"); - } - System.out.println(); - t.set_stop(true); - } - public void set_stop(boolean value) { _should_stop = value; } - public void run() { - int cap = 20000; - int fix_size = 2048; - int loop = 0; - Vector< byte[] > v = new Vector< byte[] >(cap); - while(!_should_stop) { - byte[] g = new byte[fix_size]; - v.add(g); - loop++; - if (loop > cap) { - v = null; - cap *= 2; - if (cap > 80000) cap = 80000; - v = new Vector< byte[] >(cap); - } - } - } -} -__EOF__ - -msgsuccess="succeeded" -msgfail="failed" -gclogsize="16K" -filesize=$((16*1024)) -${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${testname}.java > $NULL 2>&1 - -if [ $? != 0 ]; then - echo "${COMPILEJAVA}/bin/javac ${testname}.java $fail" - exit -1 -fi - -# test for 2 minutes, it will complete circulation of gc log rotation -tts=2 -logfile="test.log" -hotspotlog="hotspot.log" - -if [ -e $logfile ]; then - rm -rf $logfile -fi - -#also delete $hotspotlog if it exists -if [ -f $hotspotlog ]; then - rm -rf $hotspotlog -fi - -options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=1 -XX:GCLogFileSize=$gclogsize" -echo "Test gc log rotation in same file, wait for $tts minutes ...." -${TESTJAVA}/bin/java $options $testname $tts -if [ $? != 0 ]; then - echo "$msgfail" - exit -1 -fi - -# rotation file will be $logfile.0 -if [ -f $logfile.0 ]; then - outfilesize=`ls -l $logfile.0 | awk '{print $5 }'` - if [ $((outfilesize)) -ge $((filesize)) ]; then - echo $msgsuccess - else - echo $msgfail - fi -else - echo $msgfail - exit -1 -fi - -# delete log file -rm -rf $logfile.0 -if [ -f $hotspotlog ]; then - rm -rf $hotspotlog -fi - -#multiple log files -numoffiles=3 -options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=$numoffiles -XX:GCLogFileSize=$gclogsize" -echo "Test gc log rotation in $numoffiles files, wait for $tts minutes ...." -${TESTJAVA}/bin/java $options $testname $tts -if [ $? != 0 ]; then - echo "$msgfail" - exit -1 -fi - -atleast=0 # at least size of numoffile-1 files >= $gclogsize -tk=0 -while [ $(($tk)) -lt $(($numoffiles)) ] -do - if [ -f $logfile.$tk ]; then - outfilesize=`ls -l $logfile.$tk | awk '{ print $5 }'` - if [ $(($outfilesize)) -ge $(($filesize)) ]; then - atleast=$((atleast+1)) - fi - fi - tk=$((tk+1)) -done - -rm -rf $logfile.* -rm -rf $testname.* -rm -rf $hotspotlog - -if [ $(($atleast)) -ge $(($numoffiles-1)) ]; then - echo $msgsuccess -else - echo $msgfail - exit -1 -fi diff -r 124ca22437b1 -r 6c560f9ebb3e test/gc/TestVerifyBeforeGCDuringStartup.java --- a/test/gc/TestVerifyBeforeGCDuringStartup.java Fri Apr 12 10:14:42 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test TestVerifyBeforeGCDuringStartup.java - * @key gc - * @bug 8010463 - * @summary Simple test run with -XX:+VerifyBeforeGC -XX:-UseTLAB to verify 8010463 - * @library /testlibrary - */ - -import com.oracle.java.testlibrary.OutputAnalyzer; -import com.oracle.java.testlibrary.ProcessTools; - -public class TestVerifyBeforeGCDuringStartup { - public static void main(String args[]) throws Exception { - ProcessBuilder pb = - ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"), - "-XX:-UseTLAB", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+VerifyBeforeGC", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("[Verifying"); - output.shouldHaveExitValue(0); - } -} diff -r 124ca22437b1 -r 6c560f9ebb3e test/gc/TestVerifyDuringStartup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/TestVerifyDuringStartup.java Wed Apr 17 10:12:42 2013 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test TestVerifyDuringStartup.java + * @key gc + * @bug 8010463 + * @summary Simple test run with -XX:+VerifyDuringStartup -XX:-UseTLAB to verify 8010463 + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +public class TestVerifyDuringStartup { + public static void main(String args[]) throws Exception { + ProcessBuilder pb = + ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"), + "-XX:-UseTLAB", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+VerifyDuringStartup", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("[Verifying"); + output.shouldHaveExitValue(0); + } +} diff -r 124ca22437b1 -r 6c560f9ebb3e test/gc/metaspace/G1AddMetaspaceDependency.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/metaspace/G1AddMetaspaceDependency.java Wed Apr 17 10:12:42 2013 -0700 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test G1AddMetaspaceDependency + * @bug 8010196 + * @summary Checks that we don't get locking problems when adding metaspace dependencies with the G1 update buffer monitor + * @run main/othervm -XX:+UseG1GC -XX:G1UpdateBufferSize=1 G1AddMetaspaceDependency + */ + +import java.io.InputStream; + +public class G1AddMetaspaceDependency { + + static byte[] getClassBytes(String name) { + byte[] b = null; + try (InputStream is = ClassLoader.getSystemResourceAsStream(name)) { + byte[] tmp = new byte[is.available()]; + is.read(tmp); + b = tmp; + } finally { + if (b == null) { + throw new RuntimeException("Unable to load class file"); + } + return b; + } + } + + static final String a_name = G1AddMetaspaceDependency.class.getName() + "$A"; + static final String b_name = G1AddMetaspaceDependency.class.getName() + "$B"; + + public static void main(String... args) throws Exception { + final byte[] a_bytes = getClassBytes(a_name + ".class"); + final byte[] b_bytes = getClassBytes(b_name + ".class"); + + for (int i = 0; i < 1000; i += 1) { + runTest(a_bytes, b_bytes); + } + } + + static class Loader extends ClassLoader { + private final String myClass; + private final byte[] myBytes; + private final String friendClass; + private final ClassLoader friendLoader; + + Loader(String myClass, byte[] myBytes, + String friendClass, ClassLoader friendLoader) { + this.myClass = myClass; + this.myBytes = myBytes; + this.friendClass = friendClass; + this.friendLoader = friendLoader; + } + + Loader(String myClass, byte[] myBytes) { + this(myClass, myBytes, null, null); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + Class c = findLoadedClass(name); + if (c != null) { + return c; + } + + if (name.equals(friendClass)) { + return friendLoader.loadClass(name); + } + + if (name.equals(myClass)) { + c = defineClass(name, myBytes, 0, myBytes.length); + resolveClass(c); + return c; + } + + return findSystemClass(name); + } + + } + + private static void runTest(final byte[] a_bytes, final byte[] b_bytes) throws Exception { + Loader a_loader = new Loader(a_name, a_bytes); + Loader b_loader = new Loader(b_name, b_bytes, a_name, a_loader); + Loader c_loader = new Loader(b_name, b_bytes, a_name, a_loader); + Loader d_loader = new Loader(b_name, b_bytes, a_name, a_loader); + Loader e_loader = new Loader(b_name, b_bytes, a_name, a_loader); + Loader f_loader = new Loader(b_name, b_bytes, a_name, a_loader); + Loader g_loader = new Loader(b_name, b_bytes, a_name, a_loader); + + byte[] b = new byte[20 * 2 << 20]; + Class c; + c = b_loader.loadClass(b_name); + c = c_loader.loadClass(b_name); + c = d_loader.loadClass(b_name); + c = e_loader.loadClass(b_name); + c = f_loader.loadClass(b_name); + c = g_loader.loadClass(b_name); + } + public class A { + } + class B extends A { + } +} diff -r 124ca22437b1 -r 6c560f9ebb3e test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Apr 12 10:14:42 2013 +0100 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Wed Apr 17 10:12:42 2013 -0700 @@ -91,13 +91,19 @@ // Compiler public native void deoptimizeAll(); public native boolean isMethodCompiled(Method method); - public native boolean isMethodCompilable(Method method); + public boolean isMethodCompilable(Method method) { + return isMethodCompilable(method, -1 /*any*/); + } + public native boolean isMethodCompilable(Method method, int compLevel); public native boolean isMethodQueuedForCompilation(Method method); public native int deoptimizeMethod(Method method); public native void makeMethodNotCompilable(Method method); public native int getMethodCompilationLevel(Method method); - public native boolean setDontInlineMethod(Method method, boolean value); + public native boolean testSetDontInlineMethod(Method method, boolean value); public native int getCompileQueuesSize(); + public native boolean testSetForceInlineMethod(Method method, boolean value); + public native boolean enqueueMethodForCompilation(Method method, int compLevel); + public native void clearMethodState(Method method); //Intered strings public native boolean isInStringTable(String str);