This commit is contained in:
Lana Steuck 2013-04-17 10:12:42 -07:00
commit 1b5f599819
66 changed files with 1294 additions and 577 deletions

View File

@ -332,3 +332,4 @@ af788b85010ebabbc1e8f52c6766e08c7a95cf99 jdk8-b84
a947f40fb536e5b9e0aa210cf26abb430f80887a hs25-b26 a947f40fb536e5b9e0aa210cf26abb430f80887a hs25-b26
42fe530cd478744a4d12a0cbf803f0fc804bab1a jdk8-b85 42fe530cd478744a4d12a0cbf803f0fc804bab1a jdk8-b85
09b0d3e9ba6cdf7da07d4010d2d1df14596f6864 hs25-b27 09b0d3e9ba6cdf7da07d4010d2d1df14596f6864 hs25-b27
6d88a566d369f6a1f86912cad7d0912686b2fda1 hs25-b28

View File

@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013
HS_MAJOR_VER=25 HS_MAJOR_VER=25
HS_MINOR_VER=0 HS_MINOR_VER=0
HS_BUILD_NUMBER=27 HS_BUILD_NUMBER=28
JDK_MAJOR_VER=1 JDK_MAJOR_VER=1
JDK_MINOR_VER=8 JDK_MINOR_VER=8

View File

@ -63,11 +63,10 @@ static void defineRegNames(FILE *fp, RegisterForm *registers) {
RegDef *reg_def = NULL; RegDef *reg_def = NULL;
RegDef *next = NULL; RegDef *next = NULL;
registers->reset_RegDefs(); 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(); next = registers->iter_RegDefs();
const char *comma = (next != NULL) ? "," : " // no trailing comma"; const char *comma = (next != NULL) ? "," : " // no trailing comma";
fprintf(fp," \"%s\"%s\n", fprintf(fp," \"%s\"%s\n", reg_def->_regname, comma);
reg_def->_regname, comma );
} }
// Finish defining enumeration // Finish defining enumeration
@ -79,10 +78,10 @@ static void defineRegNames(FILE *fp, RegisterForm *registers) {
reg_def = NULL; reg_def = NULL;
next = NULL; next = NULL;
registers->reset_RegDefs(); 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(); next = registers->iter_RegDefs();
const char *comma = (next != NULL) ? "," : " // no trailing comma"; 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 // Finish defining array
fprintf(fp,"\t};\n"); fprintf(fp,"\t};\n");
@ -104,19 +103,17 @@ static void defineRegEncodes(FILE *fp, RegisterForm *registers) {
RegDef *reg_def = NULL; RegDef *reg_def = NULL;
RegDef *next = NULL; RegDef *next = NULL;
registers->reset_RegDefs(); 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(); next = registers->iter_RegDefs();
const char* register_encode = reg_def->register_encode(); const char* register_encode = reg_def->register_encode();
const char *comma = (next != NULL) ? "," : " // no trailing comma"; const char *comma = (next != NULL) ? "," : " // no trailing comma";
int encval; int encval;
if (!ADLParser::is_int_token(register_encode, encval)) { if (!ADLParser::is_int_token(register_encode, encval)) {
fprintf(fp," %s%s // %s\n", fprintf(fp," %s%s // %s\n", register_encode, comma, reg_def->_regname);
register_encode, comma, reg_def->_regname );
} else { } else {
// Output known constants in hex char format (backward compatibility). // Output known constants in hex char format (backward compatibility).
assert(encval < 256, "Exceeded supported width for register encoding"); assert(encval < 256, "Exceeded supported width for register encoding");
fprintf(fp," (unsigned char)'\\x%X'%s // %s\n", fprintf(fp," (unsigned char)'\\x%X'%s // %s\n", encval, comma, reg_def->_regname);
encval, comma, reg_def->_regname );
} }
} }
// Finish defining enumeration // Finish defining enumeration
@ -133,9 +130,10 @@ static void defineRegClassEnum(FILE *fp, RegisterForm *registers) {
fprintf(fp,"// Enumeration of register class names\n"); fprintf(fp,"// Enumeration of register class names\n");
fprintf(fp, "enum machRegisterClass {\n"); fprintf(fp, "enum machRegisterClass {\n");
registers->_rclasses.reset(); registers->_rclasses.reset();
for( const char *class_name = NULL; for (const char *class_name = NULL; (class_name = registers->_rclasses.iter()) != NULL;) {
(class_name = registers->_rclasses.iter()) != NULL; ) { const char * class_name_to_upper = toUpper(class_name);
fprintf(fp," %s,\n", toUpper( class_name )); fprintf(fp," %s,\n", class_name_to_upper);
delete[] class_name_to_upper;
} }
// Finish defining enumeration // Finish defining enumeration
fprintf(fp, " _last_Mach_Reg_Class\n"); fprintf(fp, " _last_Mach_Reg_Class\n");
@ -148,7 +146,7 @@ static void defineRegClassEnum(FILE *fp, RegisterForm *registers) {
void ArchDesc::declare_register_masks(FILE *fp_hpp) { void ArchDesc::declare_register_masks(FILE *fp_hpp) {
const char *rc_name; const char *rc_name;
if( _register ) { if (_register) {
// Build enumeration of user-defined register classes. // Build enumeration of user-defined register classes.
defineRegClassEnum(fp_hpp, _register); defineRegClassEnum(fp_hpp, _register);
@ -156,24 +154,27 @@ void ArchDesc::declare_register_masks(FILE *fp_hpp) {
fprintf(fp_hpp,"\n"); fprintf(fp_hpp,"\n");
fprintf(fp_hpp,"// Register masks, one for each register class.\n"); fprintf(fp_hpp,"// Register masks, one for each register class.\n");
_register->_rclasses.reset(); _register->_rclasses.reset();
for( rc_name = NULL; for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) {
(rc_name = _register->_rclasses.iter()) != NULL; ) {
const char *prefix = ""; const char *prefix = "";
RegClass *reg_class = _register->getRegClass(rc_name); RegClass *reg_class = _register->getRegClass(rc_name);
assert( reg_class, "Using an undefined register class"); assert(reg_class, "Using an undefined register class");
const char* rc_name_to_upper = toUpper(rc_name);
if (reg_class->_user_defined == NULL) { if (reg_class->_user_defined == NULL) {
fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", 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, toUpper( rc_name ), prefix, toUpper( rc_name )); 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 { } 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"); 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, "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, toUpper( rc_name ), prefix, toUpper( rc_name ) ); 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::declare_register_masks(FILE *fp_hpp) {
void ArchDesc::build_register_masks(FILE *fp_cpp) { void ArchDesc::build_register_masks(FILE *fp_cpp) {
const char *rc_name; const char *rc_name;
if( _register ) { if (_register) {
// Generate a list of register masks, one for each class. // Generate a list of register masks, one for each class.
fprintf(fp_cpp,"\n"); fprintf(fp_cpp,"\n");
fprintf(fp_cpp,"// Register masks, one for each register class.\n"); fprintf(fp_cpp,"// Register masks, one for each register class.\n");
_register->_rclasses.reset(); _register->_rclasses.reset();
for( rc_name = NULL; for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) {
(rc_name = _register->_rclasses.iter()) != NULL; ) {
const char *prefix = ""; const char *prefix = "";
RegClass *reg_class = _register->getRegClass(rc_name); RegClass *reg_class = _register->getRegClass(rc_name);
assert( reg_class, "Using an undefined register class"); assert(reg_class, "Using an undefined register class");
if (reg_class->_user_defined != NULL) continue; if (reg_class->_user_defined != NULL) {
continue;
}
int len = RegisterForm::RegMask_Size(); int len = RegisterForm::RegMask_Size();
fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, toUpper( rc_name ) ); const char* rc_name_to_upper = toUpper(rc_name);
{ int i; fprintf(fp_cpp, "const RegMask _%s%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,false)); {
fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,false)); 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; int i;
fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, toUpper( rc_name ) ); fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, rc_name_to_upper);
for( i = 0; i < len-1; i++ ) for(i = 0; i < len - 1; i++) {
fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,true)); 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," 0x%x );\n",reg_class->regs_in_word(i, true));
}
delete[] rc_name_to_upper;
} }
} }
} }
@ -2676,7 +2684,9 @@ static void defineIn_RegMask(FILE *fp, FormDict &globals, OperandForm &oper) {
if (strcmp(first_reg_class, "stack_slots") == 0) { if (strcmp(first_reg_class, "stack_slots") == 0) {
fprintf(fp," return &(Compile::current()->FIRST_STACK_mask());\n"); fprintf(fp," return &(Compile::current()->FIRST_STACK_mask());\n");
} else { } 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 { } else {
// Build a switch statement to return the desired mask. // Build a switch statement to return the desired mask.
@ -2688,7 +2698,9 @@ static void defineIn_RegMask(FILE *fp, FormDict &globals, OperandForm &oper) {
if( !strcmp(reg_class, "stack_slots") ) { if( !strcmp(reg_class, "stack_slots") ) {
fprintf(fp, " case %d: return &(Compile::current()->FIRST_STACK_mask());\n", index); fprintf(fp, " case %d: return &(Compile::current()->FIRST_STACK_mask());\n", index);
} else { } 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"); fprintf(fp," }\n");

View File

@ -2069,9 +2069,21 @@ public:
void closing() { fprintf(_cpp, " _LAST_MACH_OPER\n"); void closing() { fprintf(_cpp, " _LAST_MACH_OPER\n");
OutputMap::closing(); OutputMap::closing();
} }
void map(OpClassForm &opc) { fprintf(_cpp, " %s", _AD.machOperEnum(opc._ident) ); } void map(OpClassForm &opc) {
void map(OperandForm &oper) { fprintf(_cpp, " %s", _AD.machOperEnum(oper._ident) ); } const char* opc_ident_to_upper = _AD.machOperEnum(opc._ident);
void map(char *name) { fprintf(_cpp, " %s", _AD.machOperEnum(name)); } 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; } bool do_instructions() { return false; }
void map(InstructForm &inst){ assert( false, "ShouldNotCallThis()"); } void map(InstructForm &inst){ assert( false, "ShouldNotCallThis()"); }

View File

@ -316,6 +316,7 @@ class LoopInvariantCodeMotion : public StackObj {
ShortLoopOptimizer* _short_loop_optimizer; ShortLoopOptimizer* _short_loop_optimizer;
Instruction* _insertion_point; Instruction* _insertion_point;
ValueStack * _state; ValueStack * _state;
bool _insert_is_pred;
void set_invariant(Value v) const { _gvn->set_processed(v); } void set_invariant(Value v) const { _gvn->set_processed(v); }
bool is_invariant(Value v) const { return _gvn->is_processed(v); } bool is_invariant(Value v) const { return _gvn->is_processed(v); }
@ -339,6 +340,7 @@ LoopInvariantCodeMotion::LoopInvariantCodeMotion(ShortLoopOptimizer *slo, Global
assert(insertion_block->end()->as_Base() == NULL, "cannot insert into entry block"); assert(insertion_block->end()->as_Base() == NULL, "cannot insert into entry block");
_insertion_point = insertion_block->end()->prev(); _insertion_point = insertion_block->end()->prev();
_insert_is_pred = loop_header->is_predecessor(insertion_block);
BlockEnd *block_end = insertion_block->end(); BlockEnd *block_end = insertion_block->end();
_state = block_end->state_before(); _state = block_end->state_before();
@ -379,13 +381,13 @@ void LoopInvariantCodeMotion::process_block(BlockBegin* block) {
} else if (cur->as_LoadField() != NULL) { } else if (cur->as_LoadField() != NULL) {
LoadField* lf = (LoadField*)cur; LoadField* lf = (LoadField*)cur;
// deoptimizes on NullPointerException // 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) { } else if (cur->as_ArrayLength() != NULL) {
ArrayLength *length = cur->as_ArrayLength(); ArrayLength *length = cur->as_ArrayLength();
cur_invariant = is_invariant(length->array()); cur_invariant = is_invariant(length->array());
} else if (cur->as_LoadIndexed() != NULL) { } else if (cur->as_LoadIndexed() != NULL) {
LoadIndexed *li = (LoadIndexed *)cur->as_LoadIndexed(); 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) { if (cur_invariant) {

View File

@ -1723,9 +1723,6 @@ void ClassFileParser::parse_annotations(u1* buffer, int limit,
} else { } else {
coll->set_contended_group(0); // default contended group coll->set_contended_group(0); // default contended group
} }
coll->set_contended(true);
} else {
coll->set_contended(false);
} }
} }
} }

View File

@ -150,7 +150,6 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
void set_contended_group(u2 group) { _contended_group = group; } void set_contended_group(u2 group) { _contended_group = group; }
u2 contended_group() { return _contended_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); } bool is_contended() { return has_annotation(_sun_misc_Contended); }
}; };

View File

@ -70,15 +70,19 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) :
_is_anonymous(is_anonymous), _keep_alive(is_anonymous), // initially _is_anonymous(is_anonymous), _keep_alive(is_anonymous), // initially
_metaspace(NULL), _unloading(false), _klasses(NULL), _metaspace(NULL), _unloading(false), _klasses(NULL),
_claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(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)) { _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) {
// empty // empty
} }
void ClassLoaderData::init_dependencies(TRAPS) { 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 // 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. // 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() { bool ClassLoaderData::claim() {
@ -95,13 +99,17 @@ void ClassLoaderData::oops_do(OopClosure* f, KlassClosure* klass_closure, bool m
} }
f->do_oop(&_class_loader); f->do_oop(&_class_loader);
f->do_oop(&_dependencies); _dependencies.oops_do(f);
_handles->oops_do(f); _handles->oops_do(f);
if (klass_closure != NULL) { if (klass_closure != NULL) {
classes_do(klass_closure); classes_do(klass_closure);
} }
} }
void ClassLoaderData::Dependencies::oops_do(OopClosure* f) {
f->do_oop((oop*)&_list_head);
}
void ClassLoaderData::classes_do(KlassClosure* klass_closure) { void ClassLoaderData::classes_do(KlassClosure* klass_closure) {
for (Klass* k = _klasses; k != NULL; k = k->next_link()) { for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
klass_closure->do_klass(k); klass_closure->do_klass(k);
@ -154,14 +162,14 @@ void ClassLoaderData::record_dependency(Klass* k, TRAPS) {
// It's a dependency we won't find through GC, add it. This is relatively rare // It's a dependency we won't find through GC, add it. This is relatively rare
// Must handle over GC point. // Must handle over GC point.
Handle dependency(THREAD, to); 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. // Check first if this dependency is already in the list.
// Save a pointer to the last to add to under the lock. // Save a pointer to the last to add to under the lock.
objArrayOop ok = (objArrayOop)_dependencies; objArrayOop ok = _list_head;
objArrayOop last = NULL; objArrayOop last = NULL;
while (ok != NULL) { while (ok != NULL) {
last = ok; last = ok;
@ -184,16 +192,17 @@ void ClassLoaderData::add_dependency(Handle dependency, TRAPS) {
objArrayHandle new_dependency(THREAD, deps); objArrayHandle new_dependency(THREAD, deps);
// Add the dependency under lock // 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, void ClassLoaderData::Dependencies::locked_add(objArrayHandle last_handle,
objArrayHandle new_dependency) { objArrayHandle new_dependency,
Thread* THREAD) {
// Have to lock and put the new dependency on the end of the dependency // 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. // array so the card mark for CMS sees that this dependency is new.
// Can probably do this lock free with some effort. // 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); oop loader_or_mirror = new_dependency->obj_at(0);

View File

@ -93,6 +93,18 @@ class ClassLoaderDataGraph : public AllStatic {
class ClassLoaderData : public CHeapObj<mtClass> { class ClassLoaderData : public CHeapObj<mtClass> {
friend class VMStructs; friend class VMStructs;
private: 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 ClassLoaderDataGraph;
friend class ClassLoaderDataGraphMetaspaceIterator; friend class ClassLoaderDataGraphMetaspaceIterator;
friend class MetaDataFactory; friend class MetaDataFactory;
@ -102,8 +114,9 @@ class ClassLoaderData : public CHeapObj<mtClass> {
oop _class_loader; // oop used to uniquely identify a class loader oop _class_loader; // oop used to uniquely identify a class loader
// class loader or a canonical class path // class loader or a canonical class path
oop _dependencies; // oop to hold dependencies from this class loader Dependencies _dependencies; // holds dependencies from this class loader
// data to others. // data to others.
Metaspace * _metaspace; // Meta-space where meta-data defined by the Metaspace * _metaspace; // Meta-space where meta-data defined by the
// classes in the class loader are allocated. // classes in the class loader are allocated.
Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup. Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup.
@ -134,9 +147,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
static Metaspace* _ro_metaspace; static Metaspace* _ro_metaspace;
static Metaspace* _rw_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; } void set_next(ClassLoaderData* next) { _next = next; }
ClassLoaderData* next() const { return _next; } ClassLoaderData* next() const { return _next; }

View File

@ -1595,6 +1595,7 @@ Klass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_
guarantee(VerifyBeforeGC || guarantee(VerifyBeforeGC ||
VerifyDuringGC || VerifyDuringGC ||
VerifyBeforeExit || VerifyBeforeExit ||
VerifyDuringStartup ||
VerifyAfterGC, "too expensive"); VerifyAfterGC, "too expensive");
#endif #endif
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);

View File

@ -1206,11 +1206,8 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci,
assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range"); 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->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"); assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized");
// allow any levels for WhiteBox
if (!TieredCompilation) { assert(WhiteBoxAPI || TieredCompilation || comp_level == CompLevel_highest_tier, "only CompLevel_highest_tier must be used in non-tiered");
comp_level = CompLevel_highest_tier;
}
// return quickly if possible // return quickly if possible
// lock, make sure that the compilation // lock, make sure that the compilation

View File

@ -48,6 +48,7 @@
#include "memory/iterator.hpp" #include "memory/iterator.hpp"
#include "memory/referencePolicy.hpp" #include "memory/referencePolicy.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "memory/tenuredGeneration.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp" #include "prims/jvmtiExport.hpp"
#include "runtime/globals_extension.hpp" #include "runtime/globals_extension.hpp"
@ -916,7 +917,31 @@ void ConcurrentMarkSweepGeneration::compute_new_size() {
return; 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 free_percentage = ((double) free()) / capacity();
double desired_free_percentage = (double) MinHeapFreeRatio / 100; double desired_free_percentage = (double) MinHeapFreeRatio / 100;
double maximum_free_percentage = (double) MaxHeapFreeRatio / 100; double maximum_free_percentage = (double) MaxHeapFreeRatio / 100;
@ -925,9 +950,7 @@ void ConcurrentMarkSweepGeneration::compute_new_size() {
if (free_percentage < desired_free_percentage) { if (free_percentage < desired_free_percentage) {
size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage)); size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
assert(desired_capacity >= capacity(), "invalid expansion size"); assert(desired_capacity >= capacity(), "invalid expansion size");
expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes); size_t expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes);
}
if (expand_bytes > 0) {
if (PrintGCDetails && Verbose) { if (PrintGCDetails && Verbose) {
size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage)); size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
gclog_or_tty->print_cr("\nFrom compute_new_size: "); gclog_or_tty->print_cr("\nFrom compute_new_size: ");
@ -961,6 +984,14 @@ void ConcurrentMarkSweepGeneration::compute_new_size() {
gclog_or_tty->print_cr(" Expanded free fraction %f", gclog_or_tty->print_cr(" Expanded free fraction %f",
((double) free()) / capacity()); ((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 @@ void CMSCollector::compute_new_size() {
assert_locked_or_safepoint(Heap_lock); assert_locked_or_safepoint(Heap_lock);
FreelistLocker z(this); FreelistLocker z(this);
MetaspaceGC::compute_new_size(); MetaspaceGC::compute_new_size();
_cmsGen->compute_new_size(); _cmsGen->compute_new_size_free_list();
} }
// A work method used by foreground collection to determine // A work method used by foreground collection to determine
@ -2601,6 +2632,10 @@ void CMSCollector::gc_prologue(bool full) {
} }
void ConcurrentMarkSweepGeneration::gc_prologue(bool full) { void ConcurrentMarkSweepGeneration::gc_prologue(bool full) {
_capacity_at_prologue = capacity();
_used_at_prologue = used();
// Delegate to CMScollector which knows how to coordinate between // Delegate to CMScollector which knows how to coordinate between
// this and any other CMS generations that it is responsible for // this and any other CMS generations that it is responsible for
// collecting. // collecting.
@ -2774,6 +2809,23 @@ bool CMSCollector::is_cms_reachable(HeapWord* addr) {
} }
} }
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 // CMS Verification Support
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
@ -3300,6 +3352,26 @@ bool ConcurrentMarkSweepGeneration::expand_and_ensure_spooling_space(
} }
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) { void ConcurrentMarkSweepGeneration::shrink(size_t bytes) {
assert_locked_or_safepoint(Heap_lock); assert_locked_or_safepoint(Heap_lock);
@ -3351,7 +3423,7 @@ bool ConcurrentMarkSweepGeneration::grow_to_reserved() {
return success; 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_locked_or_safepoint(Heap_lock);
assert_lock_strong(freelistLock()); assert_lock_strong(freelistLock());
// XXX Fix when compaction is implemented. // XXX Fix when compaction is implemented.
@ -6476,6 +6548,10 @@ void CMSBitMap::dirty_range_iterate_clear(MemRegion mr, MemRegionClosure* cl) {
} }
} }
void CMSBitMap::print_on_error(outputStream* st, const char* prefix) const {
_bm.print_on_error(st, prefix);
}
#ifndef PRODUCT #ifndef PRODUCT
void CMSBitMap::assert_locked() const { void CMSBitMap::assert_locked() const {
CMSLockVerifier::assert_locked(lock()); CMSLockVerifier::assert_locked(lock());
@ -9074,51 +9150,6 @@ void ASConcurrentMarkSweepGeneration::update_counters(size_t used) {
} }
} }
// 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) { void ASConcurrentMarkSweepGeneration::shrink_by(size_t desired_bytes) {
assert_locked_or_safepoint(Heap_lock); assert_locked_or_safepoint(Heap_lock);
assert_lock_strong(freelistLock()); assert_lock_strong(freelistLock());

View File

@ -60,6 +60,7 @@ class CompactibleFreeListSpace;
class FreeChunk; class FreeChunk;
class PromotionInfo; class PromotionInfo;
class ScanMarkedObjectsAgainCarefullyClosure; class ScanMarkedObjectsAgainCarefullyClosure;
class TenuredGeneration;
// A generic CMS bit map. It's the basis for both the CMS marking bit map // 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 // as well as for the mod union table (in each case only a subset of the
@ -150,6 +151,8 @@ class CMSBitMap VALUE_OBJ_CLASS_SPEC {
size_t heapWordToOffset(HeapWord* addr) const; size_t heapWordToOffset(HeapWord* addr) const;
size_t heapWordDiffToOffsetDiff(size_t diff) const; size_t heapWordDiffToOffsetDiff(size_t diff) const;
void print_on_error(outputStream* st, const char* prefix) const;
// debugging // debugging
// is this address range covered by the bit-map? // is this address range covered by the bit-map?
NOT_PRODUCT( NOT_PRODUCT(
@ -810,9 +813,6 @@ class CMSCollector: public CHeapObj<mtGC> {
// used regions of each generation to limit the extent of sweep // used regions of each generation to limit the extent of sweep
void save_sweep_limits(); void save_sweep_limits();
// Resize the generations included in the collector.
void compute_new_size();
// A work method used by foreground collection to determine // A work method used by foreground collection to determine
// what type of collection (compacting or not, continuing or fresh) // what type of collection (compacting or not, continuing or fresh)
// it should do. // it should do.
@ -909,6 +909,9 @@ class CMSCollector: public CHeapObj<mtGC> {
void releaseFreelistLocks() const; void releaseFreelistLocks() const;
bool haveFreelistLocks() const; bool haveFreelistLocks() const;
// Adjust size of underlying generation
void compute_new_size();
// GC prologue and epilogue // GC prologue and epilogue
void gc_prologue(bool full); void gc_prologue(bool full);
void gc_epilogue(bool full); void gc_epilogue(bool full);
@ -983,6 +986,8 @@ class CMSCollector: public CHeapObj<mtGC> {
CMSAdaptiveSizePolicy* size_policy(); CMSAdaptiveSizePolicy* size_policy();
CMSGCAdaptivePolicyCounters* gc_adaptive_policy_counters(); CMSGCAdaptivePolicyCounters* gc_adaptive_policy_counters();
static void print_on_error(outputStream* st);
// debugging // debugging
void verify(); void verify();
bool verify_after_remark(); bool verify_after_remark();
@ -1082,7 +1087,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
protected: protected:
// Shrink generation by specified size (returns false if unable to shrink) // 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 // Update statistics for GC
virtual void update_gc_stats(int level, bool full); virtual void update_gc_stats(int level, bool full);
@ -1233,6 +1238,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
CMSExpansionCause::Cause cause); CMSExpansionCause::Cause cause);
virtual bool expand(size_t bytes, size_t expand_bytes); virtual bool expand(size_t bytes, size_t expand_bytes);
void shrink(size_t bytes); void shrink(size_t bytes);
void shrink_by(size_t bytes);
HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz); HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz);
bool expand_and_ensure_spooling_space(PromotionInfo* promo); bool expand_and_ensure_spooling_space(PromotionInfo* promo);
@ -1293,7 +1299,13 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
bool must_be_youngest() const { return false; } bool must_be_youngest() const { return false; }
bool must_be_oldest() const { return true; } 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; } CollectionTypes debug_collection_type() { return _debug_collection_type; }
void rotate_debug_collection_type(); void rotate_debug_collection_type();
@ -1315,7 +1327,6 @@ class ASConcurrentMarkSweepGeneration : public ConcurrentMarkSweepGeneration {
virtual void shrink_by(size_t bytes); virtual void shrink_by(size_t bytes);
public: public:
virtual void compute_new_size();
ASConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size, ASConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
int level, CardTableRS* ct, int level, CardTableRS* ct,
bool use_adaptive_freelists, bool use_adaptive_freelists,

View File

@ -101,6 +101,10 @@ bool CMBitMapRO::covers(ReservedSpace heap_rs) const {
} }
#endif #endif
void CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const {
_bm.print_on_error(st, prefix);
}
bool CMBitMap::allocate(ReservedSpace heap_rs) { bool CMBitMap::allocate(ReservedSpace heap_rs) {
_bmStartWord = (HeapWord*)(heap_rs.base()); _bmStartWord = (HeapWord*)(heap_rs.base());
_bmWordSize = heap_rs.size()/HeapWordSize; // heap_rs.size() is in bytes _bmWordSize = heap_rs.size()/HeapWordSize; // heap_rs.size() is in bytes
@ -3277,6 +3281,13 @@ void ConcurrentMark::print_worker_threads_on(outputStream* st) const {
} }
} }
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. // We take a break if someone is trying to stop the world.
bool ConcurrentMark::do_yield_check(uint worker_id) { bool ConcurrentMark::do_yield_check(uint worker_id) {
if (should_yield()) { if (should_yield()) {

View File

@ -113,6 +113,8 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC {
return res; return res;
} }
void print_on_error(outputStream* st, const char* prefix) const;
// debugging // debugging
NOT_PRODUCT(bool covers(ReservedSpace rs) const;) NOT_PRODUCT(bool covers(ReservedSpace rs) const;)
}; };
@ -829,6 +831,8 @@ public:
void print_worker_threads_on(outputStream* st) const; 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 // The following indicate whether a given verbose level has been
// set. Notice that anything above stats is conditional to // set. Notice that anything above stats is conditional to
// _MARKING_VERBOSE_ having been set to 1 // _MARKING_VERBOSE_ having been set to 1

View File

@ -3427,6 +3427,15 @@ void G1CollectedHeap::print_extended_on(outputStream* st) const {
heap_region_iterate(&blk); 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 { void G1CollectedHeap::print_gc_threads_on(outputStream* st) const {
if (G1CollectedHeap::use_parallel_gc_threads()) { if (G1CollectedHeap::use_parallel_gc_threads()) {
workers()->print_worker_threads_on(st); workers()->print_worker_threads_on(st);

View File

@ -1575,6 +1575,7 @@ public:
virtual void verify(bool silent); virtual void verify(bool silent);
virtual void print_on(outputStream* st) const; virtual void print_on(outputStream* st) const;
virtual void print_extended_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 print_gc_threads_on(outputStream* st) const;
virtual void gc_threads_do(ThreadClosure* tc) const; virtual void gc_threads_do(ThreadClosure* tc) const;

View File

@ -173,6 +173,12 @@ public:
void reset_counters(); void reset_counters();
#endif // #ifndef PRODUCT #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 #ifdef ASSERT
void verify_clear() const; void verify_clear() const;
inline void verify_bit(idx_t bit) const; inline void verify_bit(idx_t bit) const;

View File

@ -648,6 +648,15 @@ void ParallelScavengeHeap::print_on(outputStream* st) const {
MetaspaceAux::print_on(st); 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 { void ParallelScavengeHeap::gc_threads_do(ThreadClosure* tc) const {
PSScavenge::gc_task_manager()->threads_do(tc); PSScavenge::gc_task_manager()->threads_do(tc);
} }

View File

@ -220,6 +220,7 @@ class ParallelScavengeHeap : public CollectedHeap {
void prepare_for_verify(); void prepare_for_verify();
virtual void print_on(outputStream* st) const; 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 print_gc_threads_on(outputStream* st) const;
virtual void gc_threads_do(ThreadClosure* tc) const; virtual void gc_threads_do(ThreadClosure* tc) const;
virtual void print_tracing_info() const; virtual void print_tracing_info() const;

View File

@ -165,6 +165,10 @@ void SplitInfo::verify_clear()
#endif // #ifdef ASSERT #endif // #ifdef ASSERT
void PSParallelCompact::print_on_error(outputStream* st) {
_mark_bitmap.print_on_error(st);
}
#ifndef PRODUCT #ifndef PRODUCT
const char* PSParallelCompact::space_names[] = { const char* PSParallelCompact::space_names[] = {
"old ", "eden", "from", "to " "old ", "eden", "from", "to "

View File

@ -1163,6 +1163,8 @@ class PSParallelCompact : AllStatic {
// Time since last full gc (in milliseconds). // Time since last full gc (in milliseconds).
static jlong millis_since_last_gc(); static jlong millis_since_last_gc();
static void print_on_error(outputStream* st);
#ifndef PRODUCT #ifndef PRODUCT
// Debugging support. // Debugging support.
static const char* space_names[last_space_id]; static const char* space_names[last_space_id];

View File

@ -567,6 +567,14 @@ class CollectedHeap : public CHeapObj<mtInternal> {
print_on(st); 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) // Print all GC threads (other than the VM thread)
// used by this heap. // used by this heap.
virtual void print_gc_threads_on(outputStream* st) const = 0; virtual void print_gc_threads_on(outputStream* st) const = 0;

View File

@ -217,6 +217,7 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
TRAPS) { TRAPS) {
vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name); vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name);
if (TraceMethodHandles) { if (TraceMethodHandles) {
ResourceMark rm(THREAD);
tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s", tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s",
vmIntrinsics::name_at(iid), klass->external_name(), vmIntrinsics::name_at(iid), klass->external_name(),
name->as_C_string(), full_signature->as_C_string()); name->as_C_string(), full_signature->as_C_string());
@ -231,6 +232,7 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
TempNewSymbol basic_signature = TempNewSymbol basic_signature =
MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK); MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK);
if (TraceMethodHandles) { if (TraceMethodHandles) {
ResourceMark rm(THREAD);
tty->print_cr("lookup_polymorphic_method %s %s => basic %s", tty->print_cr("lookup_polymorphic_method %s %s => basic %s",
name->as_C_string(), name->as_C_string(),
full_signature->as_C_string(), full_signature->as_C_string(),
@ -283,6 +285,8 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
} }
if (result.not_null()) { if (result.not_null()) {
#ifdef ASSERT #ifdef ASSERT
ResourceMark rm(THREAD);
TempNewSymbol basic_signature = TempNewSymbol basic_signature =
MethodHandles::lookup_basic_type_signature(full_signature, CHECK); MethodHandles::lookup_basic_type_signature(full_signature, CHECK);
int actual_size_of_params = result->size_of_parameters(); int actual_size_of_params = result->size_of_parameters();
@ -1222,8 +1226,10 @@ void LinkResolver::resolve_invokehandle(CallInfo& result, constantPoolHandle poo
Symbol* method_signature = NULL; Symbol* method_signature = NULL;
KlassHandle current_klass; KlassHandle current_klass;
resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); 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()); 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); resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK);
} }

View File

@ -611,4 +611,23 @@ public:
void check() PRODUCT_RETURN; 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 E, MEMFLAGS F>
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 #endif // SHARE_VM_MEMORY_ALLOCATION_HPP

View File

@ -108,5 +108,49 @@ template <MEMFLAGS F> void CHeapObj<F>::operator delete(void* p){
FreeHeap(p, F); FreeHeap(p, F);
} }
template <class E, MEMFLAGS F>
E* ArrayAllocator<E, F>::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<class E, MEMFLAGS F>
void ArrayAllocator<E, F>::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 #endif // SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP

View File

@ -822,6 +822,7 @@ bool GenCollectedHeap::is_in(const void* p) const {
guarantee(VerifyBeforeGC || guarantee(VerifyBeforeGC ||
VerifyDuringGC || VerifyDuringGC ||
VerifyBeforeExit || VerifyBeforeExit ||
VerifyDuringStartup ||
PrintAssembly || PrintAssembly ||
tty->count() != 0 || // already printing tty->count() != 0 || // already printing
VerifyAfterGC || VerifyAfterGC ||
@ -1132,6 +1133,17 @@ void GenCollectedHeap::print_gc_threads_on(outputStream* st) const {
#endif // INCLUDE_ALL_GCS #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 { void GenCollectedHeap::print_tracing_info() const {
if (TraceGen0Time) { if (TraceGen0Time) {
get_gen(0)->print_summary_info(); get_gen(0)->print_summary_info();

View File

@ -344,6 +344,7 @@ public:
virtual void print_gc_threads_on(outputStream* st) const; virtual void print_gc_threads_on(outputStream* st) const;
virtual void gc_threads_do(ThreadClosure* tc) const; virtual void gc_threads_do(ThreadClosure* tc) const;
virtual void print_tracing_info() const; virtual void print_tracing_info() const;
virtual void print_on_error(outputStream* st) const;
// PrintGC, PrintGCDetails support // PrintGC, PrintGCDetails support
void print_heap_change(size_t prev_used) const; void print_heap_change(size_t prev_used) const;

View File

@ -382,7 +382,9 @@ void Generation::compact() {
CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size, CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size,
int level, int level,
GenRemSet* remset) : 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(); HeapWord* start = (HeapWord*)rs.base();
size_t reserved_byte_size = rs.size(); size_t reserved_byte_size = rs.size();
@ -406,6 +408,9 @@ CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size,
// the end if we try. // the end if we try.
guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned"); 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) { bool CardGeneration::expand(size_t bytes, size_t expand_bytes) {
@ -457,6 +462,160 @@ void CardGeneration::invalidate_remembered_set() {
} }
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. // Currently nothing to do.
void CardGeneration::prepare_for_verify() {} void CardGeneration::prepare_for_verify() {}

View File

@ -634,6 +634,17 @@ class CardGeneration: public Generation {
// This is local to this generation. // This is local to this generation.
BlockOffsetSharedArray* _bts; 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, CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level,
GenRemSet* remset); GenRemSet* remset);
@ -644,6 +655,11 @@ class CardGeneration: public Generation {
// necessarily the full "bytes") was done. // necessarily the full "bytes") was done.
virtual bool expand(size_t bytes, size_t expand_bytes); 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 clear_remembered_set();
virtual void invalidate_remembered_set(); virtual void invalidate_remembered_set();
@ -667,7 +683,6 @@ class OneContigSpaceCardGeneration: public CardGeneration {
friend class VM_PopulateDumpSharedSpace; friend class VM_PopulateDumpSharedSpace;
protected: protected:
size_t _min_heap_delta_bytes; // Minimum amount to expand.
ContiguousSpace* _the_space; // actual space holding objects ContiguousSpace* _the_space; // actual space holding objects
WaterMark _last_gc; // watermark between objects allocated before WaterMark _last_gc; // watermark between objects allocated before
// and after last GC. // and after last GC.
@ -688,11 +703,10 @@ class OneContigSpaceCardGeneration: public CardGeneration {
public: public:
OneContigSpaceCardGeneration(ReservedSpace rs, size_t initial_byte_size, OneContigSpaceCardGeneration(ReservedSpace rs, size_t initial_byte_size,
size_t min_heap_delta_bytes,
int level, GenRemSet* remset, int level, GenRemSet* remset,
ContiguousSpace* space) : ContiguousSpace* space) :
CardGeneration(rs, initial_byte_size, level, remset), 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; inline bool is_in(const void* p) const;

View File

@ -39,7 +39,7 @@ TenuredGeneration::TenuredGeneration(ReservedSpace rs,
size_t initial_byte_size, int level, size_t initial_byte_size, int level,
GenRemSet* remset) : GenRemSet* remset) :
OneContigSpaceCardGeneration(rs, initial_byte_size, OneContigSpaceCardGeneration(rs, initial_byte_size,
MinHeapDeltaBytes, level, remset, NULL) level, remset, NULL)
{ {
HeapWord* bottom = (HeapWord*) _virtual_space.low(); HeapWord* bottom = (HeapWord*) _virtual_space.low();
HeapWord* end = (HeapWord*) _virtual_space.high(); HeapWord* end = (HeapWord*) _virtual_space.high();
@ -86,162 +86,6 @@ const char* TenuredGeneration::name() const {
return "tenured generation"; 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) { void TenuredGeneration::gc_prologue(bool full) {
_capacity_at_prologue = capacity(); _capacity_at_prologue = capacity();
_used_at_prologue = used(); _used_at_prologue = used();
@ -312,6 +156,19 @@ void TenuredGeneration::collect(bool full,
size, is_tlab); 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, void TenuredGeneration::update_gc_stats(int current_level,
bool full) { bool full) {
// If the next lower level(s) has been collected, gather any statistics // If the next lower level(s) has been collected, gather any statistics

View File

@ -38,13 +38,6 @@ class ParGCAllocBufferWithBOT;
class TenuredGeneration: public OneContigSpaceCardGeneration { class TenuredGeneration: public OneContigSpaceCardGeneration {
friend class VMStructs; friend class VMStructs;
protected: 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 #if INCLUDE_ALL_GCS
// To support parallel promotion: an array of parallel allocation // To support parallel promotion: an array of parallel allocation
@ -80,9 +73,6 @@ class TenuredGeneration: public OneContigSpaceCardGeneration {
return !CollectGen0First; return !CollectGen0First;
} }
// Mark sweep support
void compute_new_size();
virtual void gc_prologue(bool full); virtual void gc_prologue(bool full);
virtual void gc_epilogue(bool full); virtual void gc_epilogue(bool full);
bool should_collect(bool full, bool should_collect(bool full,
@ -93,6 +83,7 @@ class TenuredGeneration: public OneContigSpaceCardGeneration {
bool clear_all_soft_refs, bool clear_all_soft_refs,
size_t size, size_t size,
bool is_tlab); bool is_tlab);
virtual void compute_new_size();
#if INCLUDE_ALL_GCS #if INCLUDE_ALL_GCS
// Overrides. // Overrides.

View File

@ -760,13 +760,17 @@ class Method : public Metadata {
public: public:
bool is_not_c1_compilable() const { return access_flags().is_not_c1_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 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(); } 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 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 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 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(); } 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 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 // Background compilation support
bool queued_for_compilation() const { return access_flags().queued_for_compilation(); } bool queued_for_compilation() const { return access_flags().queued_for_compilation(); }

View File

@ -660,29 +660,9 @@ MethodData::MethodData(methodHandle method, int size, TRAPS) {
// Set the method back-pointer. // Set the method back-pointer.
_method = method(); _method = method();
_invocation_counter.init(); 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;
set_creation_mileage(mileage_of(method())); 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 // Go through the bytecodes and allocate and initialize the
// corresponding data cells. // corresponding data cells.
int data_size = 0; int data_size = 0;
@ -721,7 +701,27 @@ MethodData::MethodData(methodHandle method, int size, TRAPS) {
post_initialize(&stream); post_initialize(&stream);
set_size(object_size); 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. // Get a measure of how much mileage the method has on it.

View File

@ -1284,8 +1284,8 @@ public:
return bytecode_cell_count(code) != no_profile_data; return bytecode_cell_count(code) != no_profile_data;
} }
// Perform initialization of a new MethodData* // reset into original state
void initialize(methodHandle method); void init();
// My size // My size
int size_in_bytes() const { return _size; } int size_in_bytes() const { return _size; }
@ -1365,6 +1365,7 @@ public:
intx arg_stack() { return _arg_stack; } intx arg_stack() { return _arg_stack; }
intx arg_returned() { return _arg_returned; } intx arg_returned() { return _arg_returned; }
uint arg_modified(int a) { ArgInfoData *aid = arg_info(); 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"); assert(a >= 0 && a < aid->number_of_args(), "valid argument number");
return aid->arg_modified(a); } return aid->arg_modified(a); }
@ -1373,8 +1374,8 @@ public:
void set_arg_stack(intx v) { _arg_stack = v; } void set_arg_stack(intx v) { _arg_stack = v; }
void set_arg_returned(intx v) { _arg_returned = v; } void set_arg_returned(intx v) { _arg_returned = v; }
void set_arg_modified(int a, uint v) { ArgInfoData *aid = arg_info(); 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"); assert(a >= 0 && a < aid->number_of_args(), "valid argument number");
aid->set_arg_modified(a, v); } aid->set_arg_modified(a, v); }
void clear_escape_info() { _eflags = _arg_local = _arg_stack = _arg_returned = 0; } void clear_escape_info() { _eflags = _arg_local = _arg_stack = _arg_returned = 0; }

View File

@ -49,6 +49,7 @@
#endif // INCLUDE_NMT #endif // INCLUDE_NMT
#include "compiler/compileBroker.hpp" #include "compiler/compileBroker.hpp"
#include "runtime/compilationPolicy.hpp"
bool WhiteBox::_used = false; bool WhiteBox::_used = false;
@ -214,11 +215,11 @@ WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method))
return (code->is_alive() && !code->is_marked_for_deoptimization()); return (code->is_alive() && !code->is_marked_for_deoptimization());
WB_END 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); jmethodID jmid = reflected_method_to_jmid(thread, env, method);
MutexLockerEx mu(Compile_lock); MutexLockerEx mu(Compile_lock);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); 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_END
WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method)) WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
@ -242,7 +243,7 @@ WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method
mh->set_not_compilable(); mh->set_not_compilable();
WB_END 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); jmethodID jmid = reflected_method_to_jmid(thread, env, method);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
bool result = mh->dont_inline(); bool result = mh->dont_inline();
@ -255,6 +256,54 @@ WB_ENTRY(jint, WB_GetCompileQueuesSize(JNIEnv* env, jobject o))
CompileBroker::queue_size(CompLevel_full_profile) /* C1 */; CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
WB_END 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)) WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
int len; int len;
@ -272,7 +321,6 @@ WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
Universe::heap()->collect(GCCause::_last_ditch_collection); Universe::heap()->collect(GCCause::_last_ditch_collection);
WB_END WB_END
//Some convenience methods to deal with objects from java //Some convenience methods to deal with objects from java
int WhiteBox::offset_for_field(const char* field_name, oop object, int WhiteBox::offset_for_field(const char* field_name, oop object,
Symbol* signature_symbol) { Symbol* signature_symbol) {
@ -354,18 +402,24 @@ static JNINativeMethod methods[] = {
(void*)&WB_DeoptimizeMethod }, (void*)&WB_DeoptimizeMethod },
{CC"isMethodCompiled", CC"(Ljava/lang/reflect/Method;)Z", {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Method;)Z",
(void*)&WB_IsMethodCompiled }, (void*)&WB_IsMethodCompiled },
{CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;)Z", {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;I)Z",
(void*)&WB_IsMethodCompilable}, (void*)&WB_IsMethodCompilable},
{CC"isMethodQueuedForCompilation", {CC"isMethodQueuedForCompilation",
CC"(Ljava/lang/reflect/Method;)Z", (void*)&WB_IsMethodQueuedForCompilation}, CC"(Ljava/lang/reflect/Method;)Z", (void*)&WB_IsMethodQueuedForCompilation},
{CC"makeMethodNotCompilable", {CC"makeMethodNotCompilable",
CC"(Ljava/lang/reflect/Method;)V", (void*)&WB_MakeMethodNotCompilable}, CC"(Ljava/lang/reflect/Method;)V", (void*)&WB_MakeMethodNotCompilable},
{CC"setDontInlineMethod", {CC"testSetDontInlineMethod",
CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_SetDontInlineMethod}, CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_TestSetDontInlineMethod},
{CC"getMethodCompilationLevel", {CC"getMethodCompilationLevel",
CC"(Ljava/lang/reflect/Method;)I", (void*)&WB_GetMethodCompilationLevel}, CC"(Ljava/lang/reflect/Method;)I", (void*)&WB_GetMethodCompilationLevel},
{CC"getCompileQueuesSize", {CC"getCompileQueuesSize",
CC"()I", (void*)&WB_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"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable },
{CC"fullGC", CC"()V", (void*)&WB_FullGC }, {CC"fullGC", CC"()V", (void*)&WB_FullGC },
}; };

View File

@ -2010,11 +2010,12 @@ bool Arguments::check_vm_args_consistency() {
// than just disable the lock verification. This will be fixed under // than just disable the lock verification. This will be fixed under
// bug 4788986. // bug 4788986.
if (UseConcMarkSweepGC && FLSVerifyAllHeapReferences) { if (UseConcMarkSweepGC && FLSVerifyAllHeapReferences) {
if (VerifyGCStartAt == 0) { if (VerifyDuringStartup) {
warning("Heap verification at start-up disabled " warning("Heap verification at start-up disabled "
"(due to current incompatibility with FLSVerifyAllHeapReferences)"); "(due to current incompatibility with FLSVerifyAllHeapReferences)");
VerifyGCStartAt = 1; // Disable verification at start-up VerifyDuringStartup = false; // Disable verification at start-up
} }
if (VerifyBeforeExit) { if (VerifyBeforeExit) {
warning("Heap verification at shutdown disabled " warning("Heap verification at shutdown disabled "
"(due to current incompatibility with FLSVerifyAllHeapReferences)"); "(due to current incompatibility with FLSVerifyAllHeapReferences)");

View File

@ -123,9 +123,10 @@ bool CompilationPolicy::can_be_compiled(methodHandle m, int comp_level) {
} }
if (comp_level == CompLevel_all) { if (comp_level == CompLevel_all) {
return !m->is_not_compilable(CompLevel_simple) && !m->is_not_compilable(CompLevel_full_optimization); 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 !m->is_not_compilable(comp_level);
} }
return false;
} }
bool CompilationPolicy::is_compilation_enabled() { bool CompilationPolicy::is_compilation_enabled() {

View File

@ -96,7 +96,7 @@ protected:
void reset_counter_for_back_branch_event(methodHandle method); void reset_counter_for_back_branch_event(methodHandle method);
public: public:
NonTieredCompPolicy() : _compiler_count(0) { } 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 int compiler_count(CompLevel comp_level);
virtual void do_safepoint_work(); virtual void do_safepoint_work();
virtual void reprofile(ScopeDesc* trap_scope, bool is_osr); virtual void reprofile(ScopeDesc* trap_scope, bool is_osr);

View File

@ -2123,6 +2123,10 @@ class CommandLineFlags {
product(intx, PrefetchFieldsAhead, -1, \ product(intx, PrefetchFieldsAhead, -1, \
"How many fields ahead to prefetch in oop scan (<= 0 means off)") \ "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, \ diagnostic(bool, VerifyBeforeExit, trueInDebug, \
"Verify system before exiting") \ "Verify system before exiting") \
\ \
@ -3664,8 +3668,13 @@ class CommandLineFlags {
product(bool, PrintGCCause, true, \ product(bool, PrintGCCause, true, \
"Include GC cause in GC logging") \ "Include GC cause in GC logging") \
\ \
product(bool, AllowNonVirtualCalls, false, \ product(bool , AllowNonVirtualCalls, false, \
"Obey the ACC_SUPER flag and allow invokenonvirtual calls") "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 * Macros for factoring of globals

View File

@ -3446,9 +3446,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
} }
assert (Universe::is_fully_initialized(), "not initialized"); assert (Universe::is_fully_initialized(), "not initialized");
if (VerifyBeforeGC && VerifyGCStartAt == 0) { if (VerifyDuringStartup) {
Universe::heap()->prepare_for_verify(); VM_Verify verify_op(false /* silent */); // make sure we're starting with a clean slate
Universe::verify(); // make sure we're starting with a clean slate VMThread::execute(&verify_op);
} }
EXCEPTION_MARK; EXCEPTION_MARK;

View File

@ -478,6 +478,9 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
\ \
nonstatic_field(CardGeneration, _rs, GenRemSet*) \ nonstatic_field(CardGeneration, _rs, GenRemSet*) \
nonstatic_field(CardGeneration, _bts, BlockOffsetSharedArray*) \ 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, _whole_heap, const MemRegion) \
nonstatic_field(CardTableModRefBS, _guard_index, const size_t) \ nonstatic_field(CardTableModRefBS, _guard_index, const size_t) \
@ -548,8 +551,6 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
nonstatic_field(Space, _bottom, HeapWord*) \ nonstatic_field(Space, _bottom, HeapWord*) \
nonstatic_field(Space, _end, 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, _start, HeapWord*) \
nonstatic_field(ThreadLocalAllocBuffer, _top, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _top, HeapWord*) \
nonstatic_field(ThreadLocalAllocBuffer, _end, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _end, HeapWord*) \

View File

@ -175,7 +175,8 @@ void VM_HandleFullCodeCache::doit() {
} }
void VM_Verify::doit() { void VM_Verify::doit() {
Universe::verify(); Universe::heap()->prepare_for_verify();
Universe::verify(_silent);
} }
bool VM_PrintThreads::doit_prologue() { bool VM_PrintThreads::doit_prologue() {

View File

@ -300,9 +300,9 @@ class VM_UnlinkSymbols: public VM_Operation {
class VM_Verify: public VM_Operation { class VM_Verify: public VM_Operation {
private: private:
KlassHandle _dependee; bool _silent;
public: public:
VM_Verify() {} VM_Verify(bool silent) : _silent(silent) {}
VMOp_Type type() const { return VMOp_Verify; } VMOp_Type type() const { return VMOp_Verify; }
void doit(); void doit();
}; };

View File

@ -194,6 +194,9 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
void set_is_obsolete() { atomic_set_bits(JVM_ACC_IS_OBSOLETE); } 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 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 // Klass* flags
void set_has_vanilla_constructor() { atomic_set_bits(JVM_ACC_HAS_VANILLA_CONSTRUCTOR); } void set_has_vanilla_constructor() { atomic_set_bits(JVM_ACC_HAS_VANILLA_CONSTRUCTOR); }
void set_has_finalizer() { atomic_set_bits(JVM_ACC_HAS_FINALIZER); } void set_has_finalizer() { atomic_set_bits(JVM_ACC_HAS_FINALIZER); }

View File

@ -516,6 +516,10 @@ BitMap::idx_t BitMap::count_one_bits() const {
return sum; 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 #ifndef PRODUCT

View File

@ -262,6 +262,7 @@ class BitMap VALUE_OBJ_CLASS_SPEC {
bool is_full() const; bool is_full() const;
bool is_empty() const; bool is_empty() const;
void print_on_error(outputStream* st, const char* prefix) const;
#ifndef PRODUCT #ifndef PRODUCT
public: public:

View File

@ -845,6 +845,10 @@ inline bool is_highest_tier_compile(int comp_level) {
return comp_level == CompLevel_highest_tier; 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 // 'Forward' declarations of frequently used classes
// (in order to reduce interface dependencies & reduce // (in order to reduce interface dependencies & reduce

View File

@ -253,6 +253,7 @@ public:
template <class E, MEMFLAGS F, unsigned int N = TASKQUEUE_SIZE> template <class E, MEMFLAGS F, unsigned int N = TASKQUEUE_SIZE>
class GenericTaskQueue: public TaskQueueSuper<N, F> { class GenericTaskQueue: public TaskQueueSuper<N, F> {
ArrayAllocator<E, F> _array_allocator;
protected: protected:
typedef typename TaskQueueSuper<N, F>::Age Age; typedef typename TaskQueueSuper<N, F>::Age Age;
typedef typename TaskQueueSuper<N, F>::idx_t idx_t; typedef typename TaskQueueSuper<N, F>::idx_t idx_t;
@ -314,7 +315,7 @@ GenericTaskQueue<E, F, N>::GenericTaskQueue() {
template<class E, MEMFLAGS F, unsigned int N> template<class E, MEMFLAGS F, unsigned int N>
void GenericTaskQueue<E, F, N>::initialize() { void GenericTaskQueue<E, F, N>::initialize() {
_elems = NEW_C_HEAP_ARRAY(E, N, F); _elems = _array_allocator.allocate(N);
} }
template<class E, MEMFLAGS F, unsigned int N> template<class E, MEMFLAGS F, unsigned int N>

View File

@ -685,13 +685,7 @@ void VMError::report(outputStream* st) {
STEP(190, "(printing heap information)" ) STEP(190, "(printing heap information)" )
if (_verbose && Universe::is_fully_initialized()) { if (_verbose && Universe::is_fully_initialized()) {
// Print heap information before vm abort. As we'd like as much Universe::heap()->print_on_error(st);
// 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);
st->cr(); st->cr();
st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page()); st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page());

View File

@ -27,17 +27,35 @@
* @bug 6863420 * @bug 6863420
* @summary os::javaTimeNanos() go backward on Solaris x86 * @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 { 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 long value = 0;
static boolean got_backward_time = false; static boolean got_backward_time = false;
static volatile boolean done = false;
public static void main(String args[]) { public static void main(String args[]) {
final int count = 100000; 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; final int numRuns = 1;
for (int t=1; t <= numRuns; t++) { for (int t=1; t <= numRuns; t++) {
final int curRun = t; final int curRun = t;
@ -48,7 +66,7 @@ public class Test {
Runnable thread = Runnable thread =
new Runnable() { new Runnable() {
public void run() { public void run() {
for (long l = 0; l < 100000; l++) { for (long l = 0; !done && l < 100000; l++) {
final long start = System.nanoTime(); final long start = System.nanoTime();
if (value == 12345678) { if (value == 12345678) {
System.out.println("Wow!"); System.out.println("Wow!");

View File

@ -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");
}
}

View File

@ -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");
}
}
}

View File

@ -37,6 +37,8 @@ public abstract class CompilerWhiteBoxTest {
= Integer.parseInt(getVMOption("CompileThreshold", "10000")); = Integer.parseInt(getVMOption("CompileThreshold", "10000"));
protected static final boolean BACKGROUND_COMPILATION protected static final boolean BACKGROUND_COMPILATION
= Boolean.valueOf(getVMOption("BackgroundCompilation", "true")); = Boolean.valueOf(getVMOption("BackgroundCompilation", "true"));
protected static final boolean TIERED_COMPILATION
= Boolean.valueOf(getVMOption("TieredCompilation", "false"));
protected static Method getMethod(String name) { protected static Method getMethod(String name) {
try { try {
@ -81,6 +83,9 @@ public abstract class CompilerWhiteBoxTest {
} }
protected static void checkNotCompiled(Method method) { 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)) { if (WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException(method + " must be not compiled"); throw new RuntimeException(method + " must be not compiled");
} }
@ -139,8 +144,11 @@ public abstract class CompilerWhiteBoxTest {
protected abstract void test() throws Exception; protected abstract void test() throws Exception;
protected final int compile() { protected final int compile() {
return compile(Math.max(COMPILE_THRESHOLD, 150000));
}
protected final int compile(int count) {
int result = 0; int result = 0;
int count = Math.max(COMPILE_THRESHOLD, 150000);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
result += method(); result += method();
} }

View File

@ -33,7 +33,7 @@ public class DeoptimizeAllTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// to prevent inlining #method into #compile() // to prevent inlining #method into #compile()
WHITE_BOX.setDontInlineMethod(METHOD, true); WHITE_BOX.testSetDontInlineMethod(METHOD, true);
new DeoptimizeAllTest().runTest(); new DeoptimizeAllTest().runTest();
} }

View File

@ -33,7 +33,7 @@ public class DeoptimizeMethodTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// to prevent inlining #method into #compile() // to prevent inlining #method into #compile()
WHITE_BOX.setDontInlineMethod(METHOD, true); WHITE_BOX.testSetDontInlineMethod(METHOD, true);
new DeoptimizeMethodTest().runTest(); new DeoptimizeMethodTest().runTest();
} }

View File

@ -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);
}
}

View File

@ -45,7 +45,7 @@ public class IsMethodCompilableTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// to prevent inlining #method into #compile() // to prevent inlining #method into #compile()
WHITE_BOX.setDontInlineMethod(METHOD, true); WHITE_BOX.testSetDontInlineMethod(METHOD, true);
new IsMethodCompilableTest().runTest(); new IsMethodCompilableTest().runTest();
} }
@ -60,26 +60,47 @@ public class IsMethodCompilableTest extends CompilerWhiteBoxTest {
"Warning: test is not applicable if PerMethodRecompilationCutoff == Inf"); "Warning: test is not applicable if PerMethodRecompilationCutoff == Inf");
return; return;
} }
boolean madeNotCompilable = false;
for (long i = 0; i < PER_METHOD_RECOMPILATION_CUTOFF; ++i) { // deoptimze 'PerMethodRecompilationCutoff' times and clear state
compile(); for (long i = 0L, n = PER_METHOD_RECOMPILATION_CUTOFF - 1; i < n; ++i) {
waitBackgroundCompilation(METHOD); compileAndDeoptimaze();
WHITE_BOX.deoptimizeMethod(METHOD); }
if (!WHITE_BOX.isMethodCompilable(METHOD)) { if (!WHITE_BOX.isMethodCompilable(METHOD)) {
madeNotCompilable = true; throw new RuntimeException(METHOD + " is not compilable after "
break; + (PER_METHOD_RECOMPILATION_CUTOFF - 1) + " iterations");
} }
WHITE_BOX.clearMethodState(METHOD);
// 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 " throw new RuntimeException(METHOD + " is still compilable after "
+ PER_METHOD_RECOMPILATION_CUTOFF + " iterations"); + PER_METHOD_RECOMPILATION_CUTOFF + " iterations");
} }
compile(); compile();
if (WHITE_BOX.isMethodCompiled(METHOD)) { checkNotCompiled(METHOD);
printInfo(METHOD);
throw new RuntimeException( WHITE_BOX.clearMethodState(METHOD);
METHOD + " is not compilable but compiled"); 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);
} }
} }

View File

@ -33,7 +33,7 @@ public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// to prevent inlining #method into #compile() // to prevent inlining #method into #compile()
WHITE_BOX.setDontInlineMethod(METHOD, true); WHITE_BOX.testSetDontInlineMethod(METHOD, true);
new MakeMethodNotCompilableTest().runTest(); new MakeMethodNotCompilableTest().runTest();
} }
@ -46,9 +46,6 @@ public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest {
throw new RuntimeException(METHOD + " must be not compilable"); throw new RuntimeException(METHOD + " must be not compilable");
} }
compile(); compile();
if (WHITE_BOX.isMethodQueuedForCompilation(METHOD)) {
throw new RuntimeException(METHOD + " must not be in queue");
}
checkNotCompiled(METHOD); checkNotCompiled(METHOD);
if (WHITE_BOX.isMethodCompilable(METHOD)) { if (WHITE_BOX.isMethodCompilable(METHOD)) {
throw new RuntimeException(METHOD + " must be not compilable"); throw new RuntimeException(METHOD + " must be not compilable");

View File

@ -36,23 +36,23 @@ public class SetDontInlineMethodTest extends CompilerWhiteBoxTest {
} }
protected void test() throws Exception { protected void test() throws Exception {
if (WHITE_BOX.setDontInlineMethod(METHOD, true)) { if (WHITE_BOX.testSetDontInlineMethod(METHOD, true)) {
throw new RuntimeException("on start " + METHOD throw new RuntimeException("on start " + METHOD
+ " must be inlineable"); + " must be inlineable");
} }
if (!WHITE_BOX.setDontInlineMethod(METHOD, true)) { if (!WHITE_BOX.testSetDontInlineMethod(METHOD, true)) {
throw new RuntimeException("after first change to true " + METHOD throw new RuntimeException("after first change to true " + METHOD
+ " must be not inlineable"); + " 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 throw new RuntimeException("after second change to true " + METHOD
+ " must be still not inlineable"); + " 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 throw new RuntimeException("after first change to false" + METHOD
+ " must be inlineable"); + " must be inlineable");
} }
if (WHITE_BOX.setDontInlineMethod(METHOD, false)) { if (WHITE_BOX.testSetDontInlineMethod(METHOD, false)) {
throw new RuntimeException("after second change to false " + METHOD throw new RuntimeException("after second change to false " + METHOD
+ " must be inlineable"); + " must be inlineable");
} }

View File

@ -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");
}
}
}

View File

@ -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<String> 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();
}
}

View File

@ -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

View File

@ -21,23 +21,23 @@
* questions. * questions.
*/ */
/* @test TestVerifyBeforeGCDuringStartup.java /* @test TestVerifyDuringStartup.java
* @key gc * @key gc
* @bug 8010463 * @bug 8010463
* @summary Simple test run with -XX:+VerifyBeforeGC -XX:-UseTLAB to verify 8010463 * @summary Simple test run with -XX:+VerifyDuringStartup -XX:-UseTLAB to verify 8010463
* @library /testlibrary * @library /testlibrary
*/ */
import com.oracle.java.testlibrary.OutputAnalyzer; import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools; import com.oracle.java.testlibrary.ProcessTools;
public class TestVerifyBeforeGCDuringStartup { public class TestVerifyDuringStartup {
public static void main(String args[]) throws Exception { public static void main(String args[]) throws Exception {
ProcessBuilder pb = ProcessBuilder pb =
ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"), ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"),
"-XX:-UseTLAB", "-XX:-UseTLAB",
"-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockDiagnosticVMOptions",
"-XX:+VerifyBeforeGC", "-version"); "-XX:+VerifyDuringStartup", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start()); OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("[Verifying"); output.shouldContain("[Verifying");
output.shouldHaveExitValue(0); output.shouldHaveExitValue(0);

View File

@ -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 {
}
}

View File

@ -91,13 +91,19 @@ public class WhiteBox {
// Compiler // Compiler
public native void deoptimizeAll(); public native void deoptimizeAll();
public native boolean isMethodCompiled(Method method); 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 boolean isMethodQueuedForCompilation(Method method);
public native int deoptimizeMethod(Method method); public native int deoptimizeMethod(Method method);
public native void makeMethodNotCompilable(Method method); public native void makeMethodNotCompilable(Method method);
public native int getMethodCompilationLevel(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 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 //Intered strings
public native boolean isInStringTable(String str); public native boolean isInStringTable(String str);